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)( 39 void **options, const lzma_allocator *allocator, 40 const uint8_t *props, size_t props_size); 41 42 } lzma_filter_decoder; 43 44 45 static const lzma_filter_decoder decoders[] = { 46 #ifdef HAVE_DECODER_LZMA1 47 { 48 .id = LZMA_FILTER_LZMA1, 49 .init = &lzma_lzma_decoder_init, 50 .memusage = &lzma_lzma_decoder_memusage, 51 .props_decode = &lzma_lzma_props_decode, 52 }, 53 { 54 .id = LZMA_FILTER_LZMA1EXT, 55 .init = &lzma_lzma_decoder_init, 56 .memusage = &lzma_lzma_decoder_memusage, 57 .props_decode = &lzma_lzma_props_decode, 58 }, 59 #endif 60 #ifdef HAVE_DECODER_LZMA2 61 { 62 .id = LZMA_FILTER_LZMA2, 63 .init = &lzma_lzma2_decoder_init, 64 .memusage = &lzma_lzma2_decoder_memusage, 65 .props_decode = &lzma_lzma2_props_decode, 66 }, 67 #endif 68 #ifdef HAVE_DECODER_X86 69 { 70 .id = LZMA_FILTER_X86, 71 .init = &lzma_simple_x86_decoder_init, 72 .memusage = NULL, 73 .props_decode = &lzma_simple_props_decode, 74 }, 75 #endif 76 #ifdef HAVE_DECODER_POWERPC 77 { 78 .id = LZMA_FILTER_POWERPC, 79 .init = &lzma_simple_powerpc_decoder_init, 80 .memusage = NULL, 81 .props_decode = &lzma_simple_props_decode, 82 }, 83 #endif 84 #ifdef HAVE_DECODER_IA64 85 { 86 .id = LZMA_FILTER_IA64, 87 .init = &lzma_simple_ia64_decoder_init, 88 .memusage = NULL, 89 .props_decode = &lzma_simple_props_decode, 90 }, 91 #endif 92 #ifdef HAVE_DECODER_ARM 93 { 94 .id = LZMA_FILTER_ARM, 95 .init = &lzma_simple_arm_decoder_init, 96 .memusage = NULL, 97 .props_decode = &lzma_simple_props_decode, 98 }, 99 #endif 100 #ifdef HAVE_DECODER_ARMTHUMB 101 { 102 .id = LZMA_FILTER_ARMTHUMB, 103 .init = &lzma_simple_armthumb_decoder_init, 104 .memusage = NULL, 105 .props_decode = &lzma_simple_props_decode, 106 }, 107 #endif 108 #ifdef HAVE_DECODER_ARM64 109 { 110 .id = LZMA_FILTER_ARM64, 111 .init = &lzma_simple_arm64_decoder_init, 112 .memusage = NULL, 113 .props_decode = &lzma_simple_props_decode, 114 }, 115 #endif 116 #ifdef HAVE_DECODER_SPARC 117 { 118 .id = LZMA_FILTER_SPARC, 119 .init = &lzma_simple_sparc_decoder_init, 120 .memusage = NULL, 121 .props_decode = &lzma_simple_props_decode, 122 }, 123 #endif 124 #ifdef HAVE_DECODER_DELTA 125 { 126 .id = LZMA_FILTER_DELTA, 127 .init = &lzma_delta_decoder_init, 128 .memusage = &lzma_delta_coder_memusage, 129 .props_decode = &lzma_delta_props_decode, 130 }, 131 #endif 132 }; 133 134 135 static const lzma_filter_decoder * 136 decoder_find(lzma_vli id) 137 { 138 for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) 139 if (decoders[i].id == id) 140 return decoders + i; 141 142 return NULL; 143 } 144 145 146 extern LZMA_API(lzma_bool) 147 lzma_filter_decoder_is_supported(lzma_vli id) 148 { 149 return decoder_find(id) != NULL; 150 } 151 152 153 extern lzma_ret 154 lzma_raw_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, 155 const lzma_filter *options) 156 { 157 return lzma_raw_coder_init(next, allocator, 158 options, (lzma_filter_find)(&decoder_find), false); 159 } 160 161 162 extern LZMA_API(lzma_ret) 163 lzma_raw_decoder(lzma_stream *strm, const lzma_filter *options) 164 { 165 lzma_next_strm_init(lzma_raw_decoder_init, strm, options); 166 167 strm->internal->supported_actions[LZMA_RUN] = true; 168 strm->internal->supported_actions[LZMA_FINISH] = true; 169 170 return LZMA_OK; 171 } 172 173 174 extern LZMA_API(uint64_t) 175 lzma_raw_decoder_memusage(const lzma_filter *filters) 176 { 177 return lzma_raw_coder_memusage( 178 (lzma_filter_find)(&decoder_find), filters); 179 } 180 181 182 extern LZMA_API(lzma_ret) 183 lzma_properties_decode(lzma_filter *filter, const lzma_allocator *allocator, 184 const uint8_t *props, size_t props_size) 185 { 186 // Make it always NULL so that the caller can always safely free() it. 187 filter->options = NULL; 188 189 const lzma_filter_decoder *const fd = decoder_find(filter->id); 190 if (fd == NULL) 191 return LZMA_OPTIONS_ERROR; 192 193 if (fd->props_decode == NULL) 194 return props_size == 0 ? LZMA_OK : LZMA_OPTIONS_ERROR; 195 196 return fd->props_decode( 197 &filter->options, allocator, props, props_size); 198 } 199