1 /////////////////////////////////////////////////////////////////////////////// 2 // 3 /// \file filter_decoder.c 4 /// \brief Filter ID mapping to filter-specific functions 5 // 6 // Author: Lasse Collin 7 // 8 // This file has been put into the public domain. 9 // You can do whatever you want with this file. 10 // 11 /////////////////////////////////////////////////////////////////////////////// 12 13 #include "filter_decoder.h" 14 #include "filter_common.h" 15 #include "lzma_decoder.h" 16 #include "lzma2_decoder.h" 17 #include "simple_decoder.h" 18 #include "delta_decoder.h" 19 20 21 typedef struct { 22 /// Filter ID 23 lzma_vli id; 24 25 /// Initializes the filter encoder and calls lzma_next_filter_init() 26 /// for filters + 1. 27 lzma_init_function init; 28 29 /// Calculates memory usage of the encoder. If the options are 30 /// invalid, UINT64_MAX is returned. 31 uint64_t (*memusage)(const void *options); 32 33 /// Decodes Filter Properties. 34 /// 35 /// \return - LZMA_OK: Properties decoded successfully. 36 /// - LZMA_OPTIONS_ERROR: Unsupported properties 37 /// - LZMA_MEM_ERROR: Memory allocation failed. 38 lzma_ret (*props_decode)(void **options, lzma_allocator *allocator, 39 const uint8_t *props, size_t props_size); 40 41 } lzma_filter_decoder; 42 43 44 static const lzma_filter_decoder decoders[] = { 45 #ifdef HAVE_DECODER_LZMA1 46 { 47 .id = LZMA_FILTER_LZMA1, 48 .init = &lzma_lzma_decoder_init, 49 .memusage = &lzma_lzma_decoder_memusage, 50 .props_decode = &lzma_lzma_props_decode, 51 }, 52 #endif 53 #ifdef HAVE_DECODER_LZMA2 54 { 55 .id = LZMA_FILTER_LZMA2, 56 .init = &lzma_lzma2_decoder_init, 57 .memusage = &lzma_lzma2_decoder_memusage, 58 .props_decode = &lzma_lzma2_props_decode, 59 }, 60 #endif 61 #ifdef HAVE_DECODER_X86 62 { 63 .id = LZMA_FILTER_X86, 64 .init = &lzma_simple_x86_decoder_init, 65 .memusage = NULL, 66 .props_decode = &lzma_simple_props_decode, 67 }, 68 #endif 69 #ifdef HAVE_DECODER_POWERPC 70 { 71 .id = LZMA_FILTER_POWERPC, 72 .init = &lzma_simple_powerpc_decoder_init, 73 .memusage = NULL, 74 .props_decode = &lzma_simple_props_decode, 75 }, 76 #endif 77 #ifdef HAVE_DECODER_IA64 78 { 79 .id = LZMA_FILTER_IA64, 80 .init = &lzma_simple_ia64_decoder_init, 81 .memusage = NULL, 82 .props_decode = &lzma_simple_props_decode, 83 }, 84 #endif 85 #ifdef HAVE_DECODER_ARM 86 { 87 .id = LZMA_FILTER_ARM, 88 .init = &lzma_simple_arm_decoder_init, 89 .memusage = NULL, 90 .props_decode = &lzma_simple_props_decode, 91 }, 92 #endif 93 #ifdef HAVE_DECODER_ARMTHUMB 94 { 95 .id = LZMA_FILTER_ARMTHUMB, 96 .init = &lzma_simple_armthumb_decoder_init, 97 .memusage = NULL, 98 .props_decode = &lzma_simple_props_decode, 99 }, 100 #endif 101 #ifdef HAVE_DECODER_SPARC 102 { 103 .id = LZMA_FILTER_SPARC, 104 .init = &lzma_simple_sparc_decoder_init, 105 .memusage = NULL, 106 .props_decode = &lzma_simple_props_decode, 107 }, 108 #endif 109 #ifdef HAVE_DECODER_DELTA 110 { 111 .id = LZMA_FILTER_DELTA, 112 .init = &lzma_delta_decoder_init, 113 .memusage = &lzma_delta_coder_memusage, 114 .props_decode = &lzma_delta_props_decode, 115 }, 116 #endif 117 }; 118 119 120 static const lzma_filter_decoder * 121 decoder_find(lzma_vli id) 122 { 123 for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) 124 if (decoders[i].id == id) 125 return decoders + i; 126 127 return NULL; 128 } 129 130 131 extern LZMA_API(lzma_bool) 132 lzma_filter_decoder_is_supported(lzma_vli id) 133 { 134 return decoder_find(id) != NULL; 135 } 136 137 138 extern lzma_ret 139 lzma_raw_decoder_init(lzma_next_coder *next, lzma_allocator *allocator, 140 const lzma_filter *options) 141 { 142 return lzma_raw_coder_init(next, allocator, 143 options, (lzma_filter_find)(&decoder_find), false); 144 } 145 146 147 extern LZMA_API(lzma_ret) 148 lzma_raw_decoder(lzma_stream *strm, const lzma_filter *options) 149 { 150 lzma_next_strm_init(lzma_raw_decoder_init, strm, options); 151 152 strm->internal->supported_actions[LZMA_RUN] = true; 153 strm->internal->supported_actions[LZMA_FINISH] = true; 154 155 return LZMA_OK; 156 } 157 158 159 extern LZMA_API(uint64_t) 160 lzma_raw_decoder_memusage(const lzma_filter *filters) 161 { 162 return lzma_raw_coder_memusage( 163 (lzma_filter_find)(&decoder_find), filters); 164 } 165 166 167 extern LZMA_API(lzma_ret) 168 lzma_properties_decode(lzma_filter *filter, lzma_allocator *allocator, 169 const uint8_t *props, size_t props_size) 170 { 171 // Make it always NULL so that the caller can always safely free() it. 172 filter->options = NULL; 173 174 const lzma_filter_decoder *const fd = decoder_find(filter->id); 175 if (fd == NULL) 176 return LZMA_OPTIONS_ERROR; 177 178 if (fd->props_decode == NULL) 179 return props_size == 0 ? LZMA_OK : LZMA_OPTIONS_ERROR; 180 181 return fd->props_decode( 182 &filter->options, allocator, props, props_size); 183 } 184