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