1 ///////////////////////////////////////////////////////////////////////////////
3 /// \file filter_flags_decoder.c
4 /// \brief Decodes a Filter Flags field
6 // Copyright (C) 2007 Lasse Collin
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
18 ///////////////////////////////////////////////////////////////////////////////
21 #include "lzma_decoder.h"
24 #ifdef HAVE_FILTER_SUBBLOCK
26 properties_subblock(lzma_options_filter *options, lzma_allocator *allocator,
27 const uint8_t *props lzma_attribute((unused)),
28 size_t prop_size lzma_attribute((unused)))
31 return LZMA_HEADER_ERROR;
33 options->options = lzma_alloc(
34 sizeof(lzma_options_subblock), allocator);
35 if (options->options == NULL)
36 return LZMA_MEM_ERROR;
38 ((lzma_options_subblock *)(options->options))->allow_subfilters = true;
44 #ifdef HAVE_FILTER_SIMPLE
46 properties_simple(lzma_options_filter *options, lzma_allocator *allocator,
47 const uint8_t *props, size_t prop_size)
53 return LZMA_HEADER_ERROR;
55 lzma_options_simple *simple = lzma_alloc(
56 sizeof(lzma_options_simple), allocator);
58 return LZMA_MEM_ERROR;
60 simple->start_offset = integer_read_32(props);
62 // Don't leave an options structure allocated if start_offset is zero.
63 if (simple->start_offset == 0)
64 lzma_free(simple, allocator);
66 options->options = simple;
73 #ifdef HAVE_FILTER_DELTA
75 properties_delta(lzma_options_filter *options, lzma_allocator *allocator,
76 const uint8_t *props, size_t prop_size)
79 return LZMA_HEADER_ERROR;
81 options->options = lzma_alloc(sizeof(lzma_options_delta), allocator);
82 if (options->options == NULL)
83 return LZMA_MEM_ERROR;
85 ((lzma_options_delta *)(options->options))->distance
86 = (uint32_t)(props[0]) + 1;
93 #ifdef HAVE_FILTER_LZMA
95 properties_lzma(lzma_options_filter *options, lzma_allocator *allocator,
96 const uint8_t *props, size_t prop_size)
98 // LZMA properties are always two bytes (at least for now).
100 return LZMA_HEADER_ERROR;
102 lzma_options_lzma *lzma = lzma_alloc(
103 sizeof(lzma_options_lzma), allocator);
105 return LZMA_MEM_ERROR;
107 // Decode lc, lp, and pb.
108 if (lzma_lzma_decode_properties(lzma, props[0]))
111 // Check that reserved bits are unset.
115 // Decode the dictionary size.
116 // FIXME The specification says that maximum is 4 GiB.
119 #if LZMA_DICTIONARY_SIZE_MAX != UINT32_C(1) << 30
120 # error Update the if()-condition a few lines
121 # error above to match LZMA_DICTIONARY_SIZE_MAX.
124 lzma->dictionary_size = 2 | (props[1] & 1);
125 lzma->dictionary_size <<= props[1] / 2 + 11;
127 options->options = lzma;
131 lzma_free(lzma, allocator);
132 return LZMA_HEADER_ERROR;
137 extern LZMA_API lzma_ret
138 lzma_filter_flags_decode(
139 lzma_options_filter *options, lzma_allocator *allocator,
140 const uint8_t *in, size_t *in_pos, size_t in_size)
142 // Set the pointer to NULL so the caller can always safely free it.
143 options->options = NULL;
146 return_if_error(lzma_vli_decode(&options->id, NULL,
147 in, in_pos, in_size));
149 // Size of Properties
151 return_if_error(lzma_vli_decode(&prop_size, NULL,
152 in, in_pos, in_size));
154 // Check that we have enough input.
155 if (prop_size > in_size - *in_pos)
156 return LZMA_DATA_ERROR;
158 // Determine the function to decode the properties.
159 lzma_ret (*get_properties)(lzma_options_filter *options,
160 lzma_allocator *allocator, const uint8_t *props,
163 switch (options->id) {
164 #ifdef HAVE_FILTER_SUBBLOCK
165 case LZMA_FILTER_SUBBLOCK:
166 get_properties = &properties_subblock;
169 #ifdef HAVE_FILTER_SIMPLE
170 # ifdef HAVE_FILTER_X86
171 case LZMA_FILTER_X86:
173 # ifdef HAVE_FILTER_POWERPC
174 case LZMA_FILTER_POWERPC:
176 # ifdef HAVE_FILTER_IA64
177 case LZMA_FILTER_IA64:
179 # ifdef HAVE_FILTER_ARM
180 case LZMA_FILTER_ARM:
182 # ifdef HAVE_FILTER_ARMTHUMB
183 case LZMA_FILTER_ARMTHUMB:
185 # ifdef HAVE_FILTER_SPARC
186 case LZMA_FILTER_SPARC:
188 get_properties = &properties_simple;
191 #ifdef HAVE_FILTER_DELTA
192 case LZMA_FILTER_DELTA:
193 get_properties = &properties_delta;
196 #ifdef HAVE_FILTER_LZMA
197 case LZMA_FILTER_LZMA:
198 get_properties = &properties_lzma;
202 return LZMA_HEADER_ERROR;
205 const uint8_t *props = in + *in_pos;
206 *in_pos += prop_size;
207 return get_properties(options, allocator, props, prop_size);