1 ///////////////////////////////////////////////////////////////////////////////
3 /// \file filter_flags_encoder.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_encoder.h"
25 /// Calculate the size of the Filter Properties field
27 get_properties_size(uint32_t *size, const lzma_options_filter *options)
29 lzma_ret ret = LZMA_OK;
31 switch (options->id) {
32 #ifdef HAVE_FILTER_SUBBLOCK
33 case LZMA_FILTER_SUBBLOCK:
38 #ifdef HAVE_FILTER_SIMPLE
39 # ifdef HAVE_FILTER_X86
42 # ifdef HAVE_FILTER_POWERPC
43 case LZMA_FILTER_POWERPC:
45 # ifdef HAVE_FILTER_IA64
46 case LZMA_FILTER_IA64:
48 # ifdef HAVE_FILTER_ARM
51 # ifdef HAVE_FILTER_ARMTHUMB
52 case LZMA_FILTER_ARMTHUMB:
54 # ifdef HAVE_FILTER_SPARC
55 case LZMA_FILTER_SPARC:
57 if (options->options == NULL || ((const lzma_options_simple *)(
58 options->options))->start_offset == 0)
65 #ifdef HAVE_FILTER_DELTA
66 case LZMA_FILTER_DELTA:
71 #ifdef HAVE_FILTER_LZMA
72 case LZMA_FILTER_LZMA:
78 // Unknown filter - if the Filter ID is a proper VLI,
79 // return LZMA_HEADER_ERROR instead of LZMA_PROG_ERROR,
80 // because it's possible that we just don't have support
81 // compiled in for the requested filter.
82 ret = options->id <= LZMA_VLI_VALUE_MAX
83 ? LZMA_HEADER_ERROR : LZMA_PROG_ERROR;
91 extern LZMA_API lzma_ret
92 lzma_filter_flags_size(uint32_t *size, const lzma_options_filter *options)
94 // Get size of Filter Properties. This also validates the Filter ID.
96 return_if_error(get_properties_size(&prop_size, options));
98 // Calculate the size of the Filter ID and Size of Properties fields.
99 // These cannot fail since get_properties_size() already succeeded.
100 *size = lzma_vli_size(options->id) + lzma_vli_size(prop_size)
107 #ifdef HAVE_FILTER_SIMPLE
108 /// Encodes Filter Properties of the so called simple filters
110 properties_simple(uint8_t *out, size_t *out_pos, size_t out_size,
111 const lzma_options_simple *options)
113 if (options == NULL || options->start_offset == 0)
116 if (out_size - *out_pos < 4)
117 return LZMA_PROG_ERROR;
119 integer_write_32(out + *out_pos, options->start_offset);
127 #ifdef HAVE_FILTER_DELTA
128 /// Encodes Filter Properties of the Delta filter
130 properties_delta(uint8_t *out, size_t *out_pos, size_t out_size,
131 const lzma_options_delta *options)
134 return LZMA_PROG_ERROR;
136 // It's possible that newer liblzma versions will support larger
138 if (options->distance < LZMA_DELTA_DISTANCE_MIN
139 || options->distance > LZMA_DELTA_DISTANCE_MAX)
140 return LZMA_HEADER_ERROR;
142 if (out_size - *out_pos < 1)
143 return LZMA_PROG_ERROR;
145 out[*out_pos] = options->distance - LZMA_DELTA_DISTANCE_MIN;
153 #ifdef HAVE_FILTER_LZMA
154 /// Encodes LZMA Properties and Dictionary Flags (two bytes)
156 properties_lzma(uint8_t *out, size_t *out_pos, size_t out_size,
157 const lzma_options_lzma *options)
160 return LZMA_PROG_ERROR;
162 if (out_size - *out_pos < 2)
163 return LZMA_PROG_ERROR;
166 if (lzma_lzma_encode_properties(options, out + *out_pos))
167 return LZMA_HEADER_ERROR;
173 // Dictionary size is encoded using similar encoding that is used
174 // internally by LZMA.
176 // This won't work if dictionary size can be zero:
177 # if LZMA_DICTIONARY_SIZE_MIN < 1
178 # error LZMA_DICTIONARY_SIZE_MIN cannot be zero.
181 uint32_t d = options->dictionary_size;
184 if (d < LZMA_DICTIONARY_SIZE_MIN || d > LZMA_DICTIONARY_SIZE_MAX)
185 return LZMA_HEADER_ERROR;
187 // Round up to to the next 2^n or 2^n + 2^(n - 1) depending on which
197 // Get the highest two bits using the proper encoding:
198 out[*out_pos] = get_pos_slot(d) - 24;
206 extern LZMA_API lzma_ret
207 lzma_filter_flags_encode(uint8_t *out, size_t *out_pos, size_t out_size,
208 const lzma_options_filter *options)
210 // Minimum output is one byte (everything fits into Misc).
211 // The caller should have checked that there is enough output space,
212 // so we return LZMA_PROG_ERROR instead of LZMA_BUF_ERROR.
213 if (*out_pos >= out_size)
214 return LZMA_PROG_ERROR;
216 // Get size of Filter Properties.
218 return_if_error(get_properties_size(&prop_size, options));
221 return_if_error(lzma_vli_encode(options->id, NULL,
222 out, out_pos, out_size));
224 // Size of Properties
225 return_if_error(lzma_vli_encode(prop_size, NULL,
226 out, out_pos, out_size));
230 switch (options->id) {
231 #ifdef HAVE_FILTER_SUBBLOCK
232 case LZMA_FILTER_SUBBLOCK:
233 assert(prop_size == 0);
238 #ifdef HAVE_FILTER_SIMPLE
239 # ifdef HAVE_FILTER_X86
240 case LZMA_FILTER_X86:
242 # ifdef HAVE_FILTER_POWERPC
243 case LZMA_FILTER_POWERPC:
245 # ifdef HAVE_FILTER_IA64
246 case LZMA_FILTER_IA64:
248 # ifdef HAVE_FILTER_ARM
249 case LZMA_FILTER_ARM:
251 # ifdef HAVE_FILTER_ARMTHUMB
252 case LZMA_FILTER_ARMTHUMB:
254 # ifdef HAVE_FILTER_SPARC
255 case LZMA_FILTER_SPARC:
257 ret = properties_simple(out, out_pos, out_size,
262 #ifdef HAVE_FILTER_DELTA
263 case LZMA_FILTER_DELTA:
264 ret = properties_delta(out, out_pos, out_size,
269 #ifdef HAVE_FILTER_LZMA
270 case LZMA_FILTER_LZMA:
271 ret = properties_lzma(out, out_pos, out_size,
278 ret = LZMA_PROG_ERROR;