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 21typedef 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 44static 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 120static const lzma_filter_decoder * 121decoder_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 131extern LZMA_API(lzma_bool) 132lzma_filter_decoder_is_supported(lzma_vli id) 133{ 134 return decoder_find(id) != NULL; 135} 136 137 138extern lzma_ret 139lzma_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 147extern LZMA_API(lzma_ret) 148lzma_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 159extern LZMA_API(uint64_t) 160lzma_raw_decoder_memusage(const lzma_filter *filters) 161{ 162 return lzma_raw_coder_memusage( 163 (lzma_filter_find)(&decoder_find), filters); 164} 165 166 167extern LZMA_API(lzma_ret) 168lzma_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