Home | History | Annotate | Line # | Download | only in common
      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