Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(155)

Side by Side Diff: xz/src/liblzma/common/filter_common.c

Issue 2869016: Add an unpatched version of xz, XZ Utils, to /trunk/deps/third_party (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/
Patch Set: Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « xz/src/liblzma/common/filter_common.h ('k') | xz/src/liblzma/common/filter_decoder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file filter_common.c
4 /// \brief Filter-specific stuff common for both encoder and decoder
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_common.h"
14
15
16 static const struct {
17 /// Filter ID
18 lzma_vli id;
19
20 /// Size of the filter-specific options structure
21 size_t options_size;
22
23 /// True if it is OK to use this filter as non-last filter in
24 /// the chain.
25 bool non_last_ok;
26
27 /// True if it is OK to use this filter as the last filter in
28 /// the chain.
29 bool last_ok;
30
31 /// True if the filter may change the size of the data (that is, the
32 /// amount of encoded output can be different than the amount of
33 /// uncompressed input).
34 bool changes_size;
35
36 } features[] = {
37 #if defined (HAVE_ENCODER_LZMA1) || defined(HAVE_DECODER_LZMA1)
38 {
39 .id = LZMA_FILTER_LZMA1,
40 .options_size = sizeof(lzma_options_lzma),
41 .non_last_ok = false,
42 .last_ok = true,
43 .changes_size = true,
44 },
45 #endif
46 #ifdef HAVE_DECODER_LZMA2
47 {
48 .id = LZMA_FILTER_LZMA2,
49 .options_size = sizeof(lzma_options_lzma),
50 .non_last_ok = false,
51 .last_ok = true,
52 .changes_size = true,
53 },
54 #endif
55 #ifdef HAVE_DECODER_X86
56 {
57 .id = LZMA_FILTER_X86,
58 .options_size = sizeof(lzma_options_bcj),
59 .non_last_ok = true,
60 .last_ok = false,
61 .changes_size = false,
62 },
63 #endif
64 #if defined(HAVE_ENCODER_POWERPC) || defined(HAVE_DECODER_POWERPC)
65 {
66 .id = LZMA_FILTER_POWERPC,
67 .options_size = sizeof(lzma_options_bcj),
68 .non_last_ok = true,
69 .last_ok = false,
70 .changes_size = false,
71 },
72 #endif
73 #ifdef HAVE_DECODER_IA64
74 {
75 .id = LZMA_FILTER_IA64,
76 .options_size = sizeof(lzma_options_bcj),
77 .non_last_ok = true,
78 .last_ok = false,
79 .changes_size = false,
80 },
81 #endif
82 #if defined(HAVE_ENCODER_ARM) || defined(HAVE_DECODER_ARM)
83 {
84 .id = LZMA_FILTER_ARM,
85 .options_size = sizeof(lzma_options_bcj),
86 .non_last_ok = true,
87 .last_ok = false,
88 .changes_size = false,
89 },
90 #endif
91 #if defined(HAVE_ENCODER_ARMTHUMB) || defined(HAVE_DECODER_ARMTHUMB)
92 {
93 .id = LZMA_FILTER_ARMTHUMB,
94 .options_size = sizeof(lzma_options_bcj),
95 .non_last_ok = true,
96 .last_ok = false,
97 .changes_size = false,
98 },
99 #endif
100 #if defined(HAVE_ENCODER_SPARC) || defined(HAVE_DECODER_SPARC)
101 {
102 .id = LZMA_FILTER_SPARC,
103 .options_size = sizeof(lzma_options_bcj),
104 .non_last_ok = true,
105 .last_ok = false,
106 .changes_size = false,
107 },
108 #endif
109 #if defined(HAVE_ENCODER_DELTA) || defined(HAVE_DECODER_DELTA)
110 {
111 .id = LZMA_FILTER_DELTA,
112 .options_size = sizeof(lzma_options_delta),
113 .non_last_ok = true,
114 .last_ok = false,
115 .changes_size = false,
116 },
117 #endif
118 {
119 .id = LZMA_VLI_UNKNOWN
120 }
121 };
122
123
124 extern LZMA_API(lzma_ret)
125 lzma_filters_copy(const lzma_filter *src, lzma_filter *dest,
126 lzma_allocator *allocator)
127 {
128 if (src == NULL || dest == NULL)
129 return LZMA_PROG_ERROR;
130
131 lzma_ret ret;
132 size_t i;
133 for (i = 0; src[i].id != LZMA_VLI_UNKNOWN; ++i) {
134 // There must be a maximum of four filters plus
135 // the array terminator.
136 if (i == LZMA_FILTERS_MAX) {
137 ret = LZMA_OPTIONS_ERROR;
138 goto error;
139 }
140
141 dest[i].id = src[i].id;
142
143 if (src[i].options == NULL) {
144 dest[i].options = NULL;
145 } else {
146 // See if the filter is supported only when the
147 // options is not NULL. This might be convenient
148 // sometimes if the app is actually copying only
149 // a partial filter chain with a place holder ID.
150 //
151 // When options is not NULL, the Filter ID must be
152 // supported by us, because otherwise we don't know
153 // how big the options are.
154 size_t j;
155 for (j = 0; src[i].id != features[j].id; ++j) {
156 if (features[j].id == LZMA_VLI_UNKNOWN) {
157 ret = LZMA_OPTIONS_ERROR;
158 goto error;
159 }
160 }
161
162 // Allocate and copy the options.
163 dest[i].options = lzma_alloc(features[j].options_size,
164 allocator);
165 if (dest[i].options == NULL) {
166 ret = LZMA_MEM_ERROR;
167 goto error;
168 }
169
170 memcpy(dest[i].options, src[i].options,
171 features[j].options_size);
172 }
173 }
174
175 // Terminate the filter array.
176 assert(i <= LZMA_FILTERS_MAX + 1);
177 dest[i].id = LZMA_VLI_UNKNOWN;
178 dest[i].options = NULL;
179
180 return LZMA_OK;
181
182 error:
183 // Free the options which we have already allocated.
184 while (i-- > 0) {
185 lzma_free(dest[i].options, allocator);
186 dest[i].options = NULL;
187 }
188
189 return ret;
190 }
191
192
193 static lzma_ret
194 validate_chain(const lzma_filter *filters, size_t *count)
195 {
196 // There must be at least one filter.
197 if (filters == NULL || filters[0].id == LZMA_VLI_UNKNOWN)
198 return LZMA_PROG_ERROR;
199
200 // Number of non-last filters that may change the size of the data
201 // significantly (that is, more than 1-2 % or so).
202 size_t changes_size_count = 0;
203
204 // True if it is OK to add a new filter after the current filter.
205 bool non_last_ok = true;
206
207 // True if the last filter in the given chain is actually usable as
208 // the last filter. Only filters that support embedding End of Payload
209 // Marker can be used as the last filter in the chain.
210 bool last_ok = false;
211
212 size_t i = 0;
213 do {
214 size_t j;
215 for (j = 0; filters[i].id != features[j].id; ++j)
216 if (features[j].id == LZMA_VLI_UNKNOWN)
217 return LZMA_OPTIONS_ERROR;
218
219 // If the previous filter in the chain cannot be a non-last
220 // filter, the chain is invalid.
221 if (!non_last_ok)
222 return LZMA_OPTIONS_ERROR;
223
224 non_last_ok = features[j].non_last_ok;
225 last_ok = features[j].last_ok;
226 changes_size_count += features[j].changes_size;
227
228 } while (filters[++i].id != LZMA_VLI_UNKNOWN);
229
230 // There must be 1-4 filters. The last filter must be usable as
231 // the last filter in the chain. A maximum of three filters are
232 // allowed to change the size of the data.
233 if (i > LZMA_FILTERS_MAX || !last_ok || changes_size_count > 3)
234 return LZMA_OPTIONS_ERROR;
235
236 *count = i;
237 return LZMA_OK;
238 }
239
240
241 extern lzma_ret
242 lzma_raw_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
243 const lzma_filter *options,
244 lzma_filter_find coder_find, bool is_encoder)
245 {
246 // Do some basic validation and get the number of filters.
247 size_t count;
248 return_if_error(validate_chain(options, &count));
249
250 // Set the filter functions and copy the options pointer.
251 lzma_filter_info filters[LZMA_FILTERS_MAX + 1];
252 if (is_encoder) {
253 for (size_t i = 0; i < count; ++i) {
254 // The order of the filters is reversed in the
255 // encoder. It allows more efficient handling
256 // of the uncompressed data.
257 const size_t j = count - i - 1;
258
259 const lzma_filter_coder *const fc
260 = coder_find(options[i].id);
261 if (fc == NULL || fc->init == NULL)
262 return LZMA_OPTIONS_ERROR;
263
264 filters[j].id = options[i].id;
265 filters[j].init = fc->init;
266 filters[j].options = options[i].options;
267 }
268 } else {
269 for (size_t i = 0; i < count; ++i) {
270 const lzma_filter_coder *const fc
271 = coder_find(options[i].id);
272 if (fc == NULL || fc->init == NULL)
273 return LZMA_OPTIONS_ERROR;
274
275 filters[i].id = options[i].id;
276 filters[i].init = fc->init;
277 filters[i].options = options[i].options;
278 }
279 }
280
281 // Terminate the array.
282 filters[count].id = LZMA_VLI_UNKNOWN;
283 filters[count].init = NULL;
284
285 // Initialize the filters.
286 const lzma_ret ret = lzma_next_filter_init(next, allocator, filters);
287 if (ret != LZMA_OK)
288 lzma_next_end(next, allocator);
289
290 return ret;
291 }
292
293
294 extern uint64_t
295 lzma_raw_coder_memusage(lzma_filter_find coder_find,
296 const lzma_filter *filters)
297 {
298 // The chain has to have at least one filter.
299 {
300 size_t tmp;
301 if (validate_chain(filters, &tmp) != LZMA_OK)
302 return UINT64_MAX;
303 }
304
305 uint64_t total = 0;
306 size_t i = 0;
307
308 do {
309 const lzma_filter_coder *const fc
310 = coder_find(filters[i].id);
311 if (fc == NULL)
312 return UINT64_MAX; // Unsupported Filter ID
313
314 if (fc->memusage == NULL) {
315 // This filter doesn't have a function to calculate
316 // the memory usage and validate the options. Such
317 // filters need only little memory, so we use 1 KiB
318 // as a good estimate. They also accept all possible
319 // options, so there's no need to worry about lack
320 // of validation.
321 total += 1024;
322 } else {
323 // Call the filter-specific memory usage calculation
324 // function.
325 const uint64_t usage
326 = fc->memusage(filters[i].options);
327 if (usage == UINT64_MAX)
328 return UINT64_MAX; // Invalid options
329
330 total += usage;
331 }
332 } while (filters[++i].id != LZMA_VLI_UNKNOWN);
333
334 // Add some fixed amount of extra. It's to compensate memory usage
335 // of Stream, Block etc. coders, malloc() overhead, stack etc.
336 return total + LZMA_MEMUSAGE_BASE;
337 }
OLDNEW
« no previous file with comments | « xz/src/liblzma/common/filter_common.h ('k') | xz/src/liblzma/common/filter_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698