aboutsummaryrefslogtreecommitdiff
path: root/archival/bz/bzlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'archival/bz/bzlib.c')
-rw-r--r--archival/bz/bzlib.c433
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/* ------------------------------------------------------------------
13This file is part of bzip2/libbzip2, a program and library for
14lossless, block-sorting data compression.
15
16bzip2/libbzip2 version 1.0.4 of 20 December 2006
17Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
18
19Please read the WARNING, DISCLAIMER and PATENTS sections in the
20README file.
21
22This program is released under the terms of the license contained
23in 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
44static 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/*---------------------------------------------------*/
53static
54void 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/*---------------------------------------------------*/
67static
68ALWAYS_INLINE
69void init_RL(EState* s)
70{
71 s->state_in_ch = 256;
72 s->state_in_len = 0;
73}
74
75
76static
77Bool 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/*---------------------------------------------------*/
86static
87void 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/*---------------------------------------------------*/
117static
118void 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/*---------------------------------------------------*/
153static
154void 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/*---------------------------------------------------*/
189static
190Bool 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/*---------------------------------------------------*/
230static
231Bool 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/*---------------------------------------------------*/
256static
257Bool 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/*---------------------------------------------------*/
302static
303int 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/*---------------------------------------------------*/
364static
365int 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
390static
391int 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/*-------------------------------------------------------------*/