1 // SPDX-License-Identifier: 0BSD 2 3 /////////////////////////////////////////////////////////////////////////////// 4 // 5 /// \file filter_decoder.c 6 /// \brief Filter ID mapping to filter-specific functions 7 // 8 // Author: Lasse Collin 9 // 10 /////////////////////////////////////////////////////////////////////////////// 11 12 #include "filter_decoder.h" 13 #include "filter_common.h" 14 #include "lzma_decoder.h" 15 #include "lzma2_decoder.h" 16 #include "simple_decoder.h" 17 #include "delta_decoder.h" 18 19 20 typedef struct { 21 /// Filter ID 22 lzma_vli id; 23 24 /// Initializes the filter encoder and calls lzma_next_filter_init() 25 /// for filters + 1. 26 lzma_init_function init; 27 28 /// Calculates memory usage of the encoder. If the options are 29 /// invalid, UINT64_MAX is returned. 30 uint64_t (*memusage)(const void *options); 31 32 /// Decodes Filter Properties. 33 /// 34 /// \return - LZMA_OK: Properties decoded successfully. 35 /// - LZMA_OPTIONS_ERROR: Unsupported properties 36 /// - LZMA_MEM_ERROR: Memory allocation failed. 37 lzma_ret (*props_decode)( 38 void **options, const 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 { 53 .id = LZMA_FILTER_LZMA1EXT, 54 .init = &lzma_lzma_decoder_init, 55 .memusage = &lzma_lzma_decoder_memusage, 56 .props_decode = &lzma_lzma_props_decode, 57 }, 58 #endif 59 #ifdef HAVE_DECODER_LZMA2 60 { 61 .id = LZMA_FILTER_LZMA2, 62 .init = &lzma_lzma2_decoder_init, 63 .memusage = &lzma_lzma2_decoder_memusage, 64 .props_decode = &lzma_lzma2_props_decode, 65 }, 66 #endif 67 #ifdef HAVE_DECODER_X86 68 { 69 .id = LZMA_FILTER_X86, 70 .init = &lzma_simple_x86_decoder_init, 71 .memusage = NULL, 72 .props_decode = &lzma_simple_props_decode, 73 }, 74 #endif 75 #ifdef HAVE_DECODER_POWERPC 76 { 77 .id = LZMA_FILTER_POWERPC, 78 .init = &lzma_simple_powerpc_decoder_init, 79 .memusage = NULL, 80 .props_decode = &lzma_simple_props_decode, 81 }, 82 #endif 83 #ifdef HAVE_DECODER_IA64 84 { 85 .id = LZMA_FILTER_IA64, 86 .init = &lzma_simple_ia64_decoder_init, 87 .memusage = NULL, 88 .props_decode = &lzma_simple_props_decode, 89 }, 90 #endif 91 #ifdef HAVE_DECODER_ARM 92 { 93 .id = LZMA_FILTER_ARM, 94 .init = &lzma_simple_arm_decoder_init, 95 .memusage = NULL, 96 .props_decode = &lzma_simple_props_decode, 97 }, 98 #endif 99 #ifdef HAVE_DECODER_ARMTHUMB 100 { 101 .id = LZMA_FILTER_ARMTHUMB, 102 .init = &lzma_simple_armthumb_decoder_init, 103 .memusage = NULL, 104 .props_decode = &lzma_simple_props_decode, 105 }, 106 #endif 107 #ifdef HAVE_DECODER_ARM64 108 { 109 .id = LZMA_FILTER_ARM64, 110 .init = &lzma_simple_arm64_decoder_init, 111 .memusage = NULL, 112 .props_decode = &lzma_simple_props_decode, 113 }, 114 #endif 115 #ifdef HAVE_DECODER_SPARC 116 { 117 .id = LZMA_FILTER_SPARC, 118 .init = &lzma_simple_sparc_decoder_init, 119 .memusage = NULL, 120 .props_decode = &lzma_simple_props_decode, 121 }, 122 #endif 123 #ifdef HAVE_DECODER_RISCV 124 { 125 .id = LZMA_FILTER_RISCV, 126 .init = &lzma_simple_riscv_decoder_init, 127 .memusage = NULL, 128 .props_decode = &lzma_simple_props_decode, 129 }, 130 #endif 131 #ifdef HAVE_DECODER_DELTA 132 { 133 .id = LZMA_FILTER_DELTA, 134 .init = &lzma_delta_decoder_init, 135 .memusage = &lzma_delta_coder_memusage, 136 .props_decode = &lzma_delta_props_decode, 137 }, 138 #endif 139 }; 140 141 142 static const lzma_filter_decoder * 143 decoder_find(lzma_vli id) 144 { 145 for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) 146 if (decoders[i].id == id) 147 return decoders + i; 148 149 return NULL; 150 } 151 152 153 // lzma_filter_coder begins with the same members as lzma_filter_decoder. 154 // This function is a wrapper with a type that is compatible with the 155 // typedef of lzma_filter_find in filter_common.h. 156 static const lzma_filter_coder * 157 coder_find(lzma_vli id) 158 { 159 return (const lzma_filter_coder *)decoder_find(id); 160 } 161 162 163 extern LZMA_API(lzma_bool) 164 lzma_filter_decoder_is_supported(lzma_vli id) 165 { 166 return decoder_find(id) != NULL; 167 } 168 169 170 extern lzma_ret 171 lzma_raw_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, 172 const lzma_filter *options) 173 { 174 return lzma_raw_coder_init(next, allocator, 175 options, &coder_find, false); 176 } 177 178 179 extern LZMA_API(lzma_ret) 180 lzma_raw_decoder(lzma_stream *strm, const lzma_filter *options) 181 { 182 lzma_next_strm_init(lzma_raw_decoder_init, strm, options); 183 184 strm->internal->supported_actions[LZMA_RUN] = true; 185 strm->internal->supported_actions[LZMA_FINISH] = true; 186 187 return LZMA_OK; 188 } 189 190 191 extern LZMA_API(uint64_t) 192 lzma_raw_decoder_memusage(const lzma_filter *filters) 193 { 194 return lzma_raw_coder_memusage(&coder_find, filters); 195 } 196 197 198 extern LZMA_API(lzma_ret) 199 lzma_properties_decode(lzma_filter *filter, const lzma_allocator *allocator, 200 const uint8_t *props, size_t props_size) 201 { 202 // Make it always NULL so that the caller can always safely free() it. 203 filter->options = NULL; 204 205 const lzma_filter_decoder *const fd = decoder_find(filter->id); 206 if (fd == NULL) 207 return LZMA_OPTIONS_ERROR; 208 209 if (fd->props_decode == NULL) 210 return props_size == 0 ? LZMA_OK : LZMA_OPTIONS_ERROR; 211 212 return fd->props_decode( 213 &filter->options, allocator, props, props_size); 214 } 215