diff options
Diffstat (limited to 'archival/bz/bzlib.c')
-rw-r--r-- | archival/bz/bzlib.c | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/archival/bz/bzlib.c b/archival/bz/bzlib.c new file mode 100644 index 000000000..3125bb0bf --- /dev/null +++ b/archival/bz/bzlib.c | |||
@@ -0,0 +1,433 @@ | |||
1 | /* | ||
2 | * bzip2 is written by Julian Seward <jseward@bzip.org>. | ||
3 | * Adapted for busybox by Denys Vlasenko <vda.linux@googlemail.com>. | ||
4 | * See README and LICENSE files in this directory for more information. | ||
5 | */ | ||
6 | |||
7 | /*-------------------------------------------------------------*/ | ||
8 | /*--- Library top-level functions. ---*/ | ||
9 | /*--- bzlib.c ---*/ | ||
10 | /*-------------------------------------------------------------*/ | ||
11 | |||
12 | /* ------------------------------------------------------------------ | ||
13 | This file is part of bzip2/libbzip2, a program and library for | ||
14 | lossless, block-sorting data compression. | ||
15 | |||
16 | bzip2/libbzip2 version 1.0.4 of 20 December 2006 | ||
17 | Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org> | ||
18 | |||
19 | Please read the WARNING, DISCLAIMER and PATENTS sections in the | ||
20 | README file. | ||
21 | |||
22 | This program is released under the terms of the license contained | ||
23 | in the file LICENSE. | ||
24 | ------------------------------------------------------------------ */ | ||
25 | |||
26 | /* CHANGES | ||
27 | * 0.9.0 -- original version. | ||
28 | * 0.9.0a/b -- no changes in this file. | ||
29 | * 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress(). | ||
30 | * fixed bzWrite/bzRead to ignore zero-length requests. | ||
31 | * fixed bzread to correctly handle read requests after EOF. | ||
32 | * wrong parameter order in call to bzDecompressInit in | ||
33 | * bzBuffToBuffDecompress. Fixed. | ||
34 | */ | ||
35 | |||
36 | /* #include "bzlib_private.h" */ | ||
37 | |||
38 | /*---------------------------------------------------*/ | ||
39 | /*--- Compression stuff ---*/ | ||
40 | /*---------------------------------------------------*/ | ||
41 | |||
42 | /*---------------------------------------------------*/ | ||
43 | #ifndef BZ_NO_STDIO | ||
44 | static void bz_assert_fail(int errcode) | ||
45 | { | ||
46 | /* if (errcode == 1007) bb_error_msg_and_die("probably bad RAM"); */ | ||
47 | bb_error_msg_and_die("bzip2 internal error %d", errcode); | ||
48 | } | ||
49 | #endif | ||
50 | |||
51 | |||
52 | /*---------------------------------------------------*/ | ||
53 | static | ||
54 | void prepare_new_block(EState* s) | ||
55 | { | ||
56 | int32_t i; | ||
57 | s->nblock = 0; | ||
58 | s->numZ = 0; | ||
59 | s->state_out_pos = 0; | ||
60 | BZ_INITIALISE_CRC(s->blockCRC); | ||
61 | for (i = 0; i < 256; i++) s->inUse[i] = False; | ||
62 | s->blockNo++; | ||
63 | } | ||
64 | |||
65 | |||
66 | /*---------------------------------------------------*/ | ||
67 | static | ||
68 | ALWAYS_INLINE | ||
69 | void init_RL(EState* s) | ||
70 | { | ||
71 | s->state_in_ch = 256; | ||
72 | s->state_in_len = 0; | ||
73 | } | ||
74 | |||
75 | |||
76 | static | ||
77 | Bool isempty_RL(EState* s) | ||
78 | { | ||
79 | if (s->state_in_ch < 256 && s->state_in_len > 0) | ||
80 | return False; | ||
81 | return True; | ||
82 | } | ||
83 | |||
84 | |||
85 | /*---------------------------------------------------*/ | ||
86 | static | ||
87 | void BZ2_bzCompressInit(bz_stream *strm, int blockSize100k) | ||
88 | { | ||
89 | int32_t n; | ||
90 | EState* s; | ||
91 | |||
92 | s = xzalloc(sizeof(EState)); | ||
93 | s->strm = strm; | ||
94 | |||
95 | n = 100000 * blockSize100k; | ||
96 | s->arr1 = xmalloc(n * sizeof(uint32_t)); | ||
97 | s->mtfv = (uint16_t*)s->arr1; | ||
98 | s->ptr = (uint32_t*)s->arr1; | ||
99 | s->arr2 = xmalloc((n + BZ_N_OVERSHOOT) * sizeof(uint32_t)); | ||
100 | s->block = (UChar*)s->arr2; | ||
101 | s->ftab = xmalloc(65537 * sizeof(uint32_t)); | ||
102 | |||
103 | s->state = BZ_S_INPUT; | ||
104 | s->mode = BZ_M_RUNNING; | ||
105 | s->blockSize100k = blockSize100k; | ||
106 | s->nblockMAX = n - 19; | ||
107 | |||
108 | strm->state = s; | ||
109 | /*strm->total_in = 0;*/ | ||
110 | strm->total_out = 0; | ||
111 | init_RL(s); | ||
112 | prepare_new_block(s); | ||
113 | } | ||
114 | |||
115 | |||
116 | /*---------------------------------------------------*/ | ||
117 | static | ||
118 | void add_pair_to_block(EState* s) | ||
119 | { | ||
120 | int32_t i; | ||
121 | UChar ch = (UChar)(s->state_in_ch); | ||
122 | for (i = 0; i < s->state_in_len; i++) { | ||
123 | BZ_UPDATE_CRC(s->blockCRC, ch); | ||
124 | } | ||
125 | s->inUse[s->state_in_ch] = True; | ||
126 | switch (s->state_in_len) { | ||
127 | case 1: | ||
128 | s->block[s->nblock] = (UChar)ch; s->nblock++; | ||
129 | break; | ||
130 | case 2: | ||
131 | s->block[s->nblock] = (UChar)ch; s->nblock++; | ||
132 | s->block[s->nblock] = (UChar)ch; s->nblock++; | ||
133 | break; | ||
134 | case 3: | ||
135 | s->block[s->nblock] = (UChar)ch; s->nblock++; | ||
136 | s->block[s->nblock] = (UChar)ch; s->nblock++; | ||
137 | s->block[s->nblock] = (UChar)ch; s->nblock++; | ||
138 | break; | ||
139 | default: | ||
140 | s->inUse[s->state_in_len-4] = True; | ||
141 | s->block[s->nblock] = (UChar)ch; s->nblock++; | ||
142 | s->block[s->nblock] = (UChar)ch; s->nblock++; | ||
143 | s->block[s->nblock] = (UChar)ch; s->nblock++; | ||
144 | s->block[s->nblock] = (UChar)ch; s->nblock++; | ||
145 | s->block[s->nblock] = ((UChar)(s->state_in_len-4)); | ||
146 | s->nblock++; | ||
147 | break; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | |||
152 | /*---------------------------------------------------*/ | ||
153 | static | ||
154 | void flush_RL(EState* s) | ||
155 | { | ||
156 | if (s->state_in_ch < 256) add_pair_to_block(s); | ||
157 | init_RL(s); | ||
158 | } | ||
159 | |||
160 | |||
161 | /*---------------------------------------------------*/ | ||
162 | #define ADD_CHAR_TO_BLOCK(zs, zchh0) \ | ||
163 | { \ | ||
164 | uint32_t zchh = (uint32_t)(zchh0); \ | ||
165 | /*-- fast track the common case --*/ \ | ||
166 | if (zchh != zs->state_in_ch && zs->state_in_len == 1) { \ | ||
167 | UChar ch = (UChar)(zs->state_in_ch); \ | ||
168 | BZ_UPDATE_CRC(zs->blockCRC, ch); \ | ||
169 | zs->inUse[zs->state_in_ch] = True; \ | ||
170 | zs->block[zs->nblock] = (UChar)ch; \ | ||
171 | zs->nblock++; \ | ||
172 | zs->state_in_ch = zchh; \ | ||
173 | } \ | ||
174 | else \ | ||
175 | /*-- general, uncommon cases --*/ \ | ||
176 | if (zchh != zs->state_in_ch || \ | ||
177 | zs->state_in_len == 255) { \ | ||
178 | if (zs->state_in_ch < 256) \ | ||
179 | add_pair_to_block(zs); \ | ||
180 | zs->state_in_ch = zchh; \ | ||
181 | zs->state_in_len = 1; \ | ||
182 | } else { \ | ||
183 | zs->state_in_len++; \ | ||
184 | } \ | ||
185 | } | ||
186 | |||
187 | |||
188 | /*---------------------------------------------------*/ | ||
189 | static | ||
190 | Bool copy_input_until_stop(EState* s) | ||
191 | { | ||
192 | Bool progress_in = False; | ||
193 | |||
194 | //vda: cannot simplify this until avail_in_expect is removed | ||
195 | if (s->mode == BZ_M_RUNNING) { | ||
196 | /*-- fast track the common case --*/ | ||
197 | while (1) { | ||
198 | /*-- block full? --*/ | ||
199 | if (s->nblock >= s->nblockMAX) break; | ||
200 | /*-- no input? --*/ | ||
201 | if (s->strm->avail_in == 0) break; | ||
202 | progress_in = True; | ||
203 | ADD_CHAR_TO_BLOCK(s, (uint32_t)(*((UChar*)(s->strm->next_in)))); | ||
204 | s->strm->next_in++; | ||
205 | s->strm->avail_in--; | ||
206 | /*s->strm->total_in++;*/ | ||
207 | } | ||
208 | } else { | ||
209 | /*-- general, uncommon case --*/ | ||
210 | while (1) { | ||
211 | /*-- block full? --*/ | ||
212 | if (s->nblock >= s->nblockMAX) break; | ||
213 | /*-- no input? --*/ | ||
214 | if (s->strm->avail_in == 0) break; | ||
215 | /*-- flush/finish end? --*/ | ||
216 | if (s->avail_in_expect == 0) break; | ||
217 | progress_in = True; | ||
218 | ADD_CHAR_TO_BLOCK(s, (uint32_t)(*((UChar*)(s->strm->next_in)))); | ||
219 | s->strm->next_in++; | ||
220 | s->strm->avail_in--; | ||
221 | /*s->strm->total_in++;*/ | ||
222 | s->avail_in_expect--; | ||
223 | } | ||
224 | } | ||
225 | return progress_in; | ||
226 | } | ||
227 | |||
228 | |||
229 | /*---------------------------------------------------*/ | ||
230 | static | ||
231 | Bool copy_output_until_stop(EState* s) | ||
232 | { | ||
233 | Bool progress_out = False; | ||
234 | |||
235 | while (1) { | ||
236 | |||
237 | /*-- no output space? --*/ | ||
238 | if (s->strm->avail_out == 0) break; | ||
239 | |||
240 | /*-- block done? --*/ | ||
241 | if (s->state_out_pos >= s->numZ) break; | ||
242 | |||
243 | progress_out = True; | ||
244 | *(s->strm->next_out) = s->zbits[s->state_out_pos]; | ||
245 | s->state_out_pos++; | ||
246 | s->strm->avail_out--; | ||
247 | s->strm->next_out++; | ||
248 | s->strm->total_out++; | ||
249 | } | ||
250 | |||
251 | return progress_out; | ||
252 | } | ||
253 | |||
254 | |||
255 | /*---------------------------------------------------*/ | ||
256 | static | ||
257 | Bool handle_compress(bz_stream *strm) | ||
258 | { | ||
259 | Bool progress_in = False; | ||
260 | Bool progress_out = False; | ||
261 | EState* s = strm->state; | ||
262 | |||
263 | while (1) { | ||
264 | if (s->state == BZ_S_OUTPUT) { | ||
265 | progress_out |= copy_output_until_stop(s); | ||
266 | if (s->state_out_pos < s->numZ) break; | ||
267 | if (s->mode == BZ_M_FINISHING | ||
268 | && s->avail_in_expect == 0 | ||
269 | && isempty_RL(s)) | ||
270 | break; | ||
271 | prepare_new_block(s); | ||
272 | s->state = BZ_S_INPUT; | ||
273 | if (s->mode == BZ_M_FLUSHING | ||
274 | && s->avail_in_expect == 0 | ||
275 | && isempty_RL(s)) | ||
276 | break; | ||
277 | } | ||
278 | |||
279 | if (s->state == BZ_S_INPUT) { | ||
280 | progress_in |= copy_input_until_stop(s); | ||
281 | if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) { | ||
282 | flush_RL(s); | ||
283 | BZ2_compressBlock(s, (Bool)(s->mode == BZ_M_FINISHING)); | ||
284 | s->state = BZ_S_OUTPUT; | ||
285 | } else | ||
286 | if (s->nblock >= s->nblockMAX) { | ||
287 | BZ2_compressBlock(s, False); | ||
288 | s->state = BZ_S_OUTPUT; | ||
289 | } else | ||
290 | if (s->strm->avail_in == 0) { | ||
291 | break; | ||
292 | } | ||
293 | } | ||
294 | |||
295 | } | ||
296 | |||
297 | return progress_in || progress_out; | ||
298 | } | ||
299 | |||
300 | |||
301 | /*---------------------------------------------------*/ | ||
302 | static | ||
303 | int BZ2_bzCompress(bz_stream *strm, int action) | ||
304 | { | ||
305 | Bool progress; | ||
306 | EState* s; | ||
307 | if (strm == NULL) return BZ_PARAM_ERROR; | ||
308 | s = strm->state; | ||
309 | if (s == NULL) return BZ_PARAM_ERROR; | ||
310 | if (s->strm != strm) return BZ_PARAM_ERROR; | ||
311 | |||
312 | preswitch: | ||
313 | switch (s->mode) { | ||
314 | |||
315 | case BZ_M_IDLE: | ||
316 | return BZ_SEQUENCE_ERROR; | ||
317 | |||
318 | case BZ_M_RUNNING: | ||
319 | if (action == BZ_RUN) { | ||
320 | progress = handle_compress(strm); | ||
321 | return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; | ||
322 | } | ||
323 | else | ||
324 | if (action == BZ_FLUSH) { | ||
325 | s->avail_in_expect = strm->avail_in; | ||
326 | s->mode = BZ_M_FLUSHING; | ||
327 | goto preswitch; | ||
328 | } | ||
329 | else | ||
330 | if (action == BZ_FINISH) { | ||
331 | s->avail_in_expect = strm->avail_in; | ||
332 | s->mode = BZ_M_FINISHING; | ||
333 | goto preswitch; | ||
334 | } | ||
335 | else | ||
336 | return BZ_PARAM_ERROR; | ||
337 | |||
338 | case BZ_M_FLUSHING: | ||
339 | if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR; | ||
340 | if (s->avail_in_expect != s->strm->avail_in) | ||
341 | return BZ_SEQUENCE_ERROR; | ||
342 | progress = handle_compress(strm); | ||
343 | if (s->avail_in_expect > 0 || !isempty_RL(s) || s->state_out_pos < s->numZ) | ||
344 | return BZ_FLUSH_OK; | ||
345 | s->mode = BZ_M_RUNNING; | ||
346 | return BZ_RUN_OK; | ||
347 | |||
348 | case BZ_M_FINISHING: | ||
349 | if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR; | ||
350 | if (s->avail_in_expect != s->strm->avail_in) | ||
351 | return BZ_SEQUENCE_ERROR; | ||
352 | progress = handle_compress(strm); | ||
353 | if (!progress) return BZ_SEQUENCE_ERROR; | ||
354 | if (s->avail_in_expect > 0 || !isempty_RL(s) || s->state_out_pos < s->numZ) | ||
355 | return BZ_FINISH_OK; | ||
356 | s->mode = BZ_M_IDLE; | ||
357 | return BZ_STREAM_END; | ||
358 | } | ||
359 | return BZ_OK; /*--not reached--*/ | ||
360 | } | ||
361 | |||
362 | |||
363 | /*---------------------------------------------------*/ | ||
364 | static | ||
365 | int BZ2_bzCompressEnd(bz_stream *strm) | ||
366 | { | ||
367 | EState* s; | ||
368 | if (strm == NULL) return BZ_PARAM_ERROR; | ||
369 | s = strm->state; | ||
370 | if (s == NULL) return BZ_PARAM_ERROR; | ||
371 | if (s->strm != strm) return BZ_PARAM_ERROR; | ||
372 | |||
373 | if (s->arr1 != NULL) free(s->arr1); | ||
374 | if (s->arr2 != NULL) free(s->arr2); | ||
375 | if (s->ftab != NULL) free(s->ftab); | ||
376 | free(strm->state); | ||
377 | |||
378 | strm->state = NULL; | ||
379 | |||
380 | return BZ_OK; | ||
381 | } | ||
382 | |||
383 | |||
384 | /*---------------------------------------------------*/ | ||
385 | /*--- Misc convenience stuff ---*/ | ||
386 | /*---------------------------------------------------*/ | ||
387 | |||
388 | /*---------------------------------------------------*/ | ||
389 | #ifdef EXAMPLE_CODE_FOR_MEM_TO_MEM_COMPRESSION | ||
390 | static | ||
391 | int BZ2_bzBuffToBuffCompress(char* dest, | ||
392 | unsigned int* destLen, | ||
393 | char* source, | ||
394 | unsigned int sourceLen, | ||
395 | int blockSize100k) | ||
396 | { | ||
397 | bz_stream strm; | ||
398 | int ret; | ||
399 | |||
400 | if (dest == NULL || destLen == NULL || | ||
401 | source == NULL || | ||
402 | blockSize100k < 1 || blockSize100k > 9) | ||
403 | return BZ_PARAM_ERROR; | ||
404 | |||
405 | BZ2_bzCompressInit(&strm, blockSize100k); | ||
406 | |||
407 | strm.next_in = source; | ||
408 | strm.next_out = dest; | ||
409 | strm.avail_in = sourceLen; | ||
410 | strm.avail_out = *destLen; | ||
411 | |||
412 | ret = BZ2_bzCompress(&strm, BZ_FINISH); | ||
413 | if (ret == BZ_FINISH_OK) goto output_overflow; | ||
414 | if (ret != BZ_STREAM_END) goto errhandler; | ||
415 | |||
416 | /* normal termination */ | ||
417 | *destLen -= strm.avail_out; | ||
418 | BZ2_bzCompressEnd(&strm); | ||
419 | return BZ_OK; | ||
420 | |||
421 | output_overflow: | ||
422 | BZ2_bzCompressEnd(&strm); | ||
423 | return BZ_OUTBUFF_FULL; | ||
424 | |||
425 | errhandler: | ||
426 | BZ2_bzCompressEnd(&strm); | ||
427 | return ret; | ||
428 | } | ||
429 | #endif | ||
430 | |||
431 | /*-------------------------------------------------------------*/ | ||
432 | /*--- end bzlib.c ---*/ | ||
433 | /*-------------------------------------------------------------*/ | ||