Deleted Added
full compact
bzlib.c (90067) bzlib.c (146293)
1
2/*-------------------------------------------------------------*/
3/*--- Library top-level functions. ---*/
4/*--- bzlib.c ---*/
5/*-------------------------------------------------------------*/
6
7/*--
8 This file is a part of bzip2 and/or libbzip2, a program and
9 library for lossless, block-sorting data compression.
10
1
2/*-------------------------------------------------------------*/
3/*--- Library top-level functions. ---*/
4/*--- bzlib.c ---*/
5/*-------------------------------------------------------------*/
6
7/*--
8 This file is a part of bzip2 and/or libbzip2, a program and
9 library for lossless, block-sorting data compression.
10
11 Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
11 Copyright (C) 1996-2005 Julian R Seward. All rights reserved.
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
15 are met:
16
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
19
20 2. The origin of this software must not be misrepresented; you must
21 not claim that you wrote the original software. If you use this
22 software in a product, an acknowledgment in the product
23 documentation would be appreciated but is not required.
24
25 3. Altered source versions must be plainly marked as such, and must
26 not be misrepresented as being the original software.
27
28 4. The name of the author may not be used to endorse or promote
29 products derived from this software without specific prior written
30 permission.
31
32 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
33 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
36 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
40 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
44 Julian Seward, Cambridge, UK.
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
15 are met:
16
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
19
20 2. The origin of this software must not be misrepresented; you must
21 not claim that you wrote the original software. If you use this
22 software in a product, an acknowledgment in the product
23 documentation would be appreciated but is not required.
24
25 3. Altered source versions must be plainly marked as such, and must
26 not be misrepresented as being the original software.
27
28 4. The name of the author may not be used to endorse or promote
29 products derived from this software without specific prior written
30 permission.
31
32 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
33 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
36 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
40 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
44 Julian Seward, Cambridge, UK.
45 jseward@acm.org
45 jseward@bzip.org
46 bzip2/libbzip2 version 1.0 of 21 March 2000
47
48 This program is based on (at least) the work of:
49 Mike Burrows
50 David Wheeler
51 Peter Fenwick
52 Alistair Moffat
53 Radford Neal
54 Ian H. Witten
55 Robert Sedgewick
56 Jon L. Bentley
57
58 For more information on these sources, see the manual.
59--*/
60
61/*--
62 CHANGES
63 ~~~~~~~
64 0.9.0 -- original version.
65
66 0.9.0a/b -- no changes in this file.
67
68 0.9.0c
69 * made zero-length BZ_FLUSH work correctly in bzCompress().
70 * fixed bzWrite/bzRead to ignore zero-length requests.
71 * fixed bzread to correctly handle read requests after EOF.
72 * wrong parameter order in call to bzDecompressInit in
73 bzBuffToBuffDecompress. Fixed.
74--*/
75
76#include "bzlib_private.h"
77
78
79/*---------------------------------------------------*/
80/*--- Compression stuff ---*/
81/*---------------------------------------------------*/
82
83
84/*---------------------------------------------------*/
85#ifndef BZ_NO_STDIO
86void BZ2_bz__AssertH__fail ( int errcode )
87{
88 fprintf(stderr,
89 "\n\nbzip2/libbzip2: internal error number %d.\n"
90 "This is a bug in bzip2/libbzip2, %s.\n"
46 bzip2/libbzip2 version 1.0 of 21 March 2000
47
48 This program is based on (at least) the work of:
49 Mike Burrows
50 David Wheeler
51 Peter Fenwick
52 Alistair Moffat
53 Radford Neal
54 Ian H. Witten
55 Robert Sedgewick
56 Jon L. Bentley
57
58 For more information on these sources, see the manual.
59--*/
60
61/*--
62 CHANGES
63 ~~~~~~~
64 0.9.0 -- original version.
65
66 0.9.0a/b -- no changes in this file.
67
68 0.9.0c
69 * made zero-length BZ_FLUSH work correctly in bzCompress().
70 * fixed bzWrite/bzRead to ignore zero-length requests.
71 * fixed bzread to correctly handle read requests after EOF.
72 * wrong parameter order in call to bzDecompressInit in
73 bzBuffToBuffDecompress. Fixed.
74--*/
75
76#include "bzlib_private.h"
77
78
79/*---------------------------------------------------*/
80/*--- Compression stuff ---*/
81/*---------------------------------------------------*/
82
83
84/*---------------------------------------------------*/
85#ifndef BZ_NO_STDIO
86void BZ2_bz__AssertH__fail ( int errcode )
87{
88 fprintf(stderr,
89 "\n\nbzip2/libbzip2: internal error number %d.\n"
90 "This is a bug in bzip2/libbzip2, %s.\n"
91 "Please report it to me at: jseward@acm.org. If this happened\n"
91 "Please report it to me at: jseward@bzip.org. If this happened\n"
92 "when you were using some program which uses libbzip2 as a\n"
93 "component, you should also report this bug to the author(s)\n"
94 "of that program. Please make an effort to report this bug;\n"
95 "timely and accurate bug reports eventually lead to higher\n"
92 "when you were using some program which uses libbzip2 as a\n"
93 "component, you should also report this bug to the author(s)\n"
94 "of that program. Please make an effort to report this bug;\n"
95 "timely and accurate bug reports eventually lead to higher\n"
96 "quality software. Thanks. Julian Seward, 30 December 2001.\n\n",
96 "quality software. Thanks. Julian Seward, 15 February 2005.\n\n",
97 errcode,
98 BZ2_bzlibVersion()
99 );
100
101 if (errcode == 1007) {
102 fprintf(stderr,
103 "\n*** A special note about internal error number 1007 ***\n"
104 "\n"
105 "Experience suggests that a common cause of i.e. 1007\n"
106 "is unreliable memory or other hardware. The 1007 assertion\n"
107 "just happens to cross-check the results of huge numbers of\n"
108 "memory reads/writes, and so acts (unintendedly) as a stress\n"
109 "test of your memory system.\n"
110 "\n"
111 "I suggest the following: try compressing the file again,\n"
112 "possibly monitoring progress in detail with the -vv flag.\n"
113 "\n"
114 "* If the error cannot be reproduced, and/or happens at different\n"
115 " points in compression, you may have a flaky memory system.\n"
116 " Try a memory-test program. I have used Memtest86\n"
117 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
118 " Memtest86 tests memory much more thorougly than your BIOSs\n"
119 " power-on test, and may find failures that the BIOS doesn't.\n"
120 "\n"
121 "* If the error can be repeatably reproduced, this is a bug in\n"
122 " bzip2, and I would very much like to hear about it. Please\n"
123 " let me know, and, ideally, save a copy of the file causing the\n"
124 " problem -- without which I will be unable to investigate it.\n"
125 "\n"
126 );
127 }
128
129 exit(3);
130}
131#endif
132
133
134/*---------------------------------------------------*/
135static
136int bz_config_ok ( void )
137{
138 if (sizeof(int) != 4) return 0;
139 if (sizeof(short) != 2) return 0;
140 if (sizeof(char) != 1) return 0;
141 return 1;
142}
143
144
145/*---------------------------------------------------*/
146static
147void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
148{
149 void* v = malloc ( items * size );
150 return v;
151}
152
153static
154void default_bzfree ( void* opaque, void* addr )
155{
156 if (addr != NULL) free ( addr );
157}
158
159
160/*---------------------------------------------------*/
161static
162void prepare_new_block ( EState* s )
163{
164 Int32 i;
165 s->nblock = 0;
166 s->numZ = 0;
167 s->state_out_pos = 0;
168 BZ_INITIALISE_CRC ( s->blockCRC );
169 for (i = 0; i < 256; i++) s->inUse[i] = False;
170 s->blockNo++;
171}
172
173
174/*---------------------------------------------------*/
175static
176void init_RL ( EState* s )
177{
178 s->state_in_ch = 256;
179 s->state_in_len = 0;
180}
181
182
183static
184Bool isempty_RL ( EState* s )
185{
186 if (s->state_in_ch < 256 && s->state_in_len > 0)
187 return False; else
188 return True;
189}
190
191
192/*---------------------------------------------------*/
193int BZ_API(BZ2_bzCompressInit)
194 ( bz_stream* strm,
195 int blockSize100k,
196 int verbosity,
197 int workFactor )
198{
199 Int32 n;
200 EState* s;
201
202 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
203
204 if (strm == NULL ||
205 blockSize100k < 1 || blockSize100k > 9 ||
206 workFactor < 0 || workFactor > 250)
207 return BZ_PARAM_ERROR;
208
209 if (workFactor == 0) workFactor = 30;
210 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
211 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
212
213 s = BZALLOC( sizeof(EState) );
214 if (s == NULL) return BZ_MEM_ERROR;
215 s->strm = strm;
216
217 s->arr1 = NULL;
218 s->arr2 = NULL;
219 s->ftab = NULL;
220
221 n = 100000 * blockSize100k;
222 s->arr1 = BZALLOC( n * sizeof(UInt32) );
223 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
224 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
225
226 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
227 if (s->arr1 != NULL) BZFREE(s->arr1);
228 if (s->arr2 != NULL) BZFREE(s->arr2);
229 if (s->ftab != NULL) BZFREE(s->ftab);
230 if (s != NULL) BZFREE(s);
231 return BZ_MEM_ERROR;
232 }
233
234 s->blockNo = 0;
235 s->state = BZ_S_INPUT;
236 s->mode = BZ_M_RUNNING;
237 s->combinedCRC = 0;
238 s->blockSize100k = blockSize100k;
239 s->nblockMAX = 100000 * blockSize100k - 19;
240 s->verbosity = verbosity;
241 s->workFactor = workFactor;
242
243 s->block = (UChar*)s->arr2;
244 s->mtfv = (UInt16*)s->arr1;
245 s->zbits = NULL;
246 s->ptr = (UInt32*)s->arr1;
247
248 strm->state = s;
249 strm->total_in_lo32 = 0;
250 strm->total_in_hi32 = 0;
251 strm->total_out_lo32 = 0;
252 strm->total_out_hi32 = 0;
253 init_RL ( s );
254 prepare_new_block ( s );
255 return BZ_OK;
256}
257
258
259/*---------------------------------------------------*/
260static
261void add_pair_to_block ( EState* s )
262{
263 Int32 i;
264 UChar ch = (UChar)(s->state_in_ch);
265 for (i = 0; i < s->state_in_len; i++) {
266 BZ_UPDATE_CRC( s->blockCRC, ch );
267 }
268 s->inUse[s->state_in_ch] = True;
269 switch (s->state_in_len) {
270 case 1:
271 s->block[s->nblock] = (UChar)ch; s->nblock++;
272 break;
273 case 2:
274 s->block[s->nblock] = (UChar)ch; s->nblock++;
275 s->block[s->nblock] = (UChar)ch; s->nblock++;
276 break;
277 case 3:
278 s->block[s->nblock] = (UChar)ch; s->nblock++;
279 s->block[s->nblock] = (UChar)ch; s->nblock++;
280 s->block[s->nblock] = (UChar)ch; s->nblock++;
281 break;
282 default:
283 s->inUse[s->state_in_len-4] = True;
284 s->block[s->nblock] = (UChar)ch; s->nblock++;
285 s->block[s->nblock] = (UChar)ch; s->nblock++;
286 s->block[s->nblock] = (UChar)ch; s->nblock++;
287 s->block[s->nblock] = (UChar)ch; s->nblock++;
288 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
289 s->nblock++;
290 break;
291 }
292}
293
294
295/*---------------------------------------------------*/
296static
297void flush_RL ( EState* s )
298{
299 if (s->state_in_ch < 256) add_pair_to_block ( s );
300 init_RL ( s );
301}
302
303
304/*---------------------------------------------------*/
305#define ADD_CHAR_TO_BLOCK(zs,zchh0) \
306{ \
307 UInt32 zchh = (UInt32)(zchh0); \
308 /*-- fast track the common case --*/ \
309 if (zchh != zs->state_in_ch && \
310 zs->state_in_len == 1) { \
311 UChar ch = (UChar)(zs->state_in_ch); \
312 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
313 zs->inUse[zs->state_in_ch] = True; \
314 zs->block[zs->nblock] = (UChar)ch; \
315 zs->nblock++; \
316 zs->state_in_ch = zchh; \
317 } \
318 else \
319 /*-- general, uncommon cases --*/ \
320 if (zchh != zs->state_in_ch || \
321 zs->state_in_len == 255) { \
322 if (zs->state_in_ch < 256) \
323 add_pair_to_block ( zs ); \
324 zs->state_in_ch = zchh; \
325 zs->state_in_len = 1; \
326 } else { \
327 zs->state_in_len++; \
328 } \
329}
330
331
332/*---------------------------------------------------*/
333static
334Bool copy_input_until_stop ( EState* s )
335{
336 Bool progress_in = False;
337
338 if (s->mode == BZ_M_RUNNING) {
339
340 /*-- fast track the common case --*/
341 while (True) {
342 /*-- block full? --*/
343 if (s->nblock >= s->nblockMAX) break;
344 /*-- no input? --*/
345 if (s->strm->avail_in == 0) break;
346 progress_in = True;
347 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
348 s->strm->next_in++;
349 s->strm->avail_in--;
350 s->strm->total_in_lo32++;
351 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
352 }
353
354 } else {
355
356 /*-- general, uncommon case --*/
357 while (True) {
358 /*-- block full? --*/
359 if (s->nblock >= s->nblockMAX) break;
360 /*-- no input? --*/
361 if (s->strm->avail_in == 0) break;
362 /*-- flush/finish end? --*/
363 if (s->avail_in_expect == 0) break;
364 progress_in = True;
365 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
366 s->strm->next_in++;
367 s->strm->avail_in--;
368 s->strm->total_in_lo32++;
369 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
370 s->avail_in_expect--;
371 }
372 }
373 return progress_in;
374}
375
376
377/*---------------------------------------------------*/
378static
379Bool copy_output_until_stop ( EState* s )
380{
381 Bool progress_out = False;
382
383 while (True) {
384
385 /*-- no output space? --*/
386 if (s->strm->avail_out == 0) break;
387
388 /*-- block done? --*/
389 if (s->state_out_pos >= s->numZ) break;
390
391 progress_out = True;
392 *(s->strm->next_out) = s->zbits[s->state_out_pos];
393 s->state_out_pos++;
394 s->strm->avail_out--;
395 s->strm->next_out++;
396 s->strm->total_out_lo32++;
397 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
398 }
399
400 return progress_out;
401}
402
403
404/*---------------------------------------------------*/
405static
406Bool handle_compress ( bz_stream* strm )
407{
408 Bool progress_in = False;
409 Bool progress_out = False;
410 EState* s = strm->state;
411
412 while (True) {
413
414 if (s->state == BZ_S_OUTPUT) {
415 progress_out |= copy_output_until_stop ( s );
416 if (s->state_out_pos < s->numZ) break;
417 if (s->mode == BZ_M_FINISHING &&
418 s->avail_in_expect == 0 &&
419 isempty_RL(s)) break;
420 prepare_new_block ( s );
421 s->state = BZ_S_INPUT;
422 if (s->mode == BZ_M_FLUSHING &&
423 s->avail_in_expect == 0 &&
424 isempty_RL(s)) break;
425 }
426
427 if (s->state == BZ_S_INPUT) {
428 progress_in |= copy_input_until_stop ( s );
429 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
430 flush_RL ( s );
431 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
432 s->state = BZ_S_OUTPUT;
433 }
434 else
435 if (s->nblock >= s->nblockMAX) {
436 BZ2_compressBlock ( s, False );
437 s->state = BZ_S_OUTPUT;
438 }
439 else
440 if (s->strm->avail_in == 0) {
441 break;
442 }
443 }
444
445 }
446
447 return progress_in || progress_out;
448}
449
450
451/*---------------------------------------------------*/
452int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
453{
454 Bool progress;
455 EState* s;
456 if (strm == NULL) return BZ_PARAM_ERROR;
457 s = strm->state;
458 if (s == NULL) return BZ_PARAM_ERROR;
459 if (s->strm != strm) return BZ_PARAM_ERROR;
460
461 preswitch:
462 switch (s->mode) {
463
464 case BZ_M_IDLE:
465 return BZ_SEQUENCE_ERROR;
466
467 case BZ_M_RUNNING:
468 if (action == BZ_RUN) {
469 progress = handle_compress ( strm );
470 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
471 }
472 else
473 if (action == BZ_FLUSH) {
474 s->avail_in_expect = strm->avail_in;
475 s->mode = BZ_M_FLUSHING;
476 goto preswitch;
477 }
478 else
479 if (action == BZ_FINISH) {
480 s->avail_in_expect = strm->avail_in;
481 s->mode = BZ_M_FINISHING;
482 goto preswitch;
483 }
484 else
485 return BZ_PARAM_ERROR;
486
487 case BZ_M_FLUSHING:
488 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
489 if (s->avail_in_expect != s->strm->avail_in)
490 return BZ_SEQUENCE_ERROR;
491 progress = handle_compress ( strm );
492 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
493 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
494 s->mode = BZ_M_RUNNING;
495 return BZ_RUN_OK;
496
497 case BZ_M_FINISHING:
498 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
499 if (s->avail_in_expect != s->strm->avail_in)
500 return BZ_SEQUENCE_ERROR;
501 progress = handle_compress ( strm );
502 if (!progress) return BZ_SEQUENCE_ERROR;
503 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
504 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
505 s->mode = BZ_M_IDLE;
506 return BZ_STREAM_END;
507 }
508 return BZ_OK; /*--not reached--*/
509}
510
511
512/*---------------------------------------------------*/
513int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
514{
515 EState* s;
516 if (strm == NULL) return BZ_PARAM_ERROR;
517 s = strm->state;
518 if (s == NULL) return BZ_PARAM_ERROR;
519 if (s->strm != strm) return BZ_PARAM_ERROR;
520
521 if (s->arr1 != NULL) BZFREE(s->arr1);
522 if (s->arr2 != NULL) BZFREE(s->arr2);
523 if (s->ftab != NULL) BZFREE(s->ftab);
524 BZFREE(strm->state);
525
526 strm->state = NULL;
527
528 return BZ_OK;
529}
530
531
532/*---------------------------------------------------*/
533/*--- Decompression stuff ---*/
534/*---------------------------------------------------*/
535
536/*---------------------------------------------------*/
537int BZ_API(BZ2_bzDecompressInit)
538 ( bz_stream* strm,
539 int verbosity,
540 int small )
541{
542 DState* s;
543
544 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
545
546 if (strm == NULL) return BZ_PARAM_ERROR;
547 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
548 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
549
550 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
551 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
552
553 s = BZALLOC( sizeof(DState) );
554 if (s == NULL) return BZ_MEM_ERROR;
555 s->strm = strm;
556 strm->state = s;
557 s->state = BZ_X_MAGIC_1;
558 s->bsLive = 0;
559 s->bsBuff = 0;
560 s->calculatedCombinedCRC = 0;
561 strm->total_in_lo32 = 0;
562 strm->total_in_hi32 = 0;
563 strm->total_out_lo32 = 0;
564 strm->total_out_hi32 = 0;
565 s->smallDecompress = (Bool)small;
566 s->ll4 = NULL;
567 s->ll16 = NULL;
568 s->tt = NULL;
569 s->currBlockNo = 0;
570 s->verbosity = verbosity;
571
572 return BZ_OK;
573}
574
575
576/*---------------------------------------------------*/
97 errcode,
98 BZ2_bzlibVersion()
99 );
100
101 if (errcode == 1007) {
102 fprintf(stderr,
103 "\n*** A special note about internal error number 1007 ***\n"
104 "\n"
105 "Experience suggests that a common cause of i.e. 1007\n"
106 "is unreliable memory or other hardware. The 1007 assertion\n"
107 "just happens to cross-check the results of huge numbers of\n"
108 "memory reads/writes, and so acts (unintendedly) as a stress\n"
109 "test of your memory system.\n"
110 "\n"
111 "I suggest the following: try compressing the file again,\n"
112 "possibly monitoring progress in detail with the -vv flag.\n"
113 "\n"
114 "* If the error cannot be reproduced, and/or happens at different\n"
115 " points in compression, you may have a flaky memory system.\n"
116 " Try a memory-test program. I have used Memtest86\n"
117 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
118 " Memtest86 tests memory much more thorougly than your BIOSs\n"
119 " power-on test, and may find failures that the BIOS doesn't.\n"
120 "\n"
121 "* If the error can be repeatably reproduced, this is a bug in\n"
122 " bzip2, and I would very much like to hear about it. Please\n"
123 " let me know, and, ideally, save a copy of the file causing the\n"
124 " problem -- without which I will be unable to investigate it.\n"
125 "\n"
126 );
127 }
128
129 exit(3);
130}
131#endif
132
133
134/*---------------------------------------------------*/
135static
136int bz_config_ok ( void )
137{
138 if (sizeof(int) != 4) return 0;
139 if (sizeof(short) != 2) return 0;
140 if (sizeof(char) != 1) return 0;
141 return 1;
142}
143
144
145/*---------------------------------------------------*/
146static
147void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
148{
149 void* v = malloc ( items * size );
150 return v;
151}
152
153static
154void default_bzfree ( void* opaque, void* addr )
155{
156 if (addr != NULL) free ( addr );
157}
158
159
160/*---------------------------------------------------*/
161static
162void prepare_new_block ( EState* s )
163{
164 Int32 i;
165 s->nblock = 0;
166 s->numZ = 0;
167 s->state_out_pos = 0;
168 BZ_INITIALISE_CRC ( s->blockCRC );
169 for (i = 0; i < 256; i++) s->inUse[i] = False;
170 s->blockNo++;
171}
172
173
174/*---------------------------------------------------*/
175static
176void init_RL ( EState* s )
177{
178 s->state_in_ch = 256;
179 s->state_in_len = 0;
180}
181
182
183static
184Bool isempty_RL ( EState* s )
185{
186 if (s->state_in_ch < 256 && s->state_in_len > 0)
187 return False; else
188 return True;
189}
190
191
192/*---------------------------------------------------*/
193int BZ_API(BZ2_bzCompressInit)
194 ( bz_stream* strm,
195 int blockSize100k,
196 int verbosity,
197 int workFactor )
198{
199 Int32 n;
200 EState* s;
201
202 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
203
204 if (strm == NULL ||
205 blockSize100k < 1 || blockSize100k > 9 ||
206 workFactor < 0 || workFactor > 250)
207 return BZ_PARAM_ERROR;
208
209 if (workFactor == 0) workFactor = 30;
210 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
211 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
212
213 s = BZALLOC( sizeof(EState) );
214 if (s == NULL) return BZ_MEM_ERROR;
215 s->strm = strm;
216
217 s->arr1 = NULL;
218 s->arr2 = NULL;
219 s->ftab = NULL;
220
221 n = 100000 * blockSize100k;
222 s->arr1 = BZALLOC( n * sizeof(UInt32) );
223 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
224 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
225
226 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
227 if (s->arr1 != NULL) BZFREE(s->arr1);
228 if (s->arr2 != NULL) BZFREE(s->arr2);
229 if (s->ftab != NULL) BZFREE(s->ftab);
230 if (s != NULL) BZFREE(s);
231 return BZ_MEM_ERROR;
232 }
233
234 s->blockNo = 0;
235 s->state = BZ_S_INPUT;
236 s->mode = BZ_M_RUNNING;
237 s->combinedCRC = 0;
238 s->blockSize100k = blockSize100k;
239 s->nblockMAX = 100000 * blockSize100k - 19;
240 s->verbosity = verbosity;
241 s->workFactor = workFactor;
242
243 s->block = (UChar*)s->arr2;
244 s->mtfv = (UInt16*)s->arr1;
245 s->zbits = NULL;
246 s->ptr = (UInt32*)s->arr1;
247
248 strm->state = s;
249 strm->total_in_lo32 = 0;
250 strm->total_in_hi32 = 0;
251 strm->total_out_lo32 = 0;
252 strm->total_out_hi32 = 0;
253 init_RL ( s );
254 prepare_new_block ( s );
255 return BZ_OK;
256}
257
258
259/*---------------------------------------------------*/
260static
261void add_pair_to_block ( EState* s )
262{
263 Int32 i;
264 UChar ch = (UChar)(s->state_in_ch);
265 for (i = 0; i < s->state_in_len; i++) {
266 BZ_UPDATE_CRC( s->blockCRC, ch );
267 }
268 s->inUse[s->state_in_ch] = True;
269 switch (s->state_in_len) {
270 case 1:
271 s->block[s->nblock] = (UChar)ch; s->nblock++;
272 break;
273 case 2:
274 s->block[s->nblock] = (UChar)ch; s->nblock++;
275 s->block[s->nblock] = (UChar)ch; s->nblock++;
276 break;
277 case 3:
278 s->block[s->nblock] = (UChar)ch; s->nblock++;
279 s->block[s->nblock] = (UChar)ch; s->nblock++;
280 s->block[s->nblock] = (UChar)ch; s->nblock++;
281 break;
282 default:
283 s->inUse[s->state_in_len-4] = True;
284 s->block[s->nblock] = (UChar)ch; s->nblock++;
285 s->block[s->nblock] = (UChar)ch; s->nblock++;
286 s->block[s->nblock] = (UChar)ch; s->nblock++;
287 s->block[s->nblock] = (UChar)ch; s->nblock++;
288 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
289 s->nblock++;
290 break;
291 }
292}
293
294
295/*---------------------------------------------------*/
296static
297void flush_RL ( EState* s )
298{
299 if (s->state_in_ch < 256) add_pair_to_block ( s );
300 init_RL ( s );
301}
302
303
304/*---------------------------------------------------*/
305#define ADD_CHAR_TO_BLOCK(zs,zchh0) \
306{ \
307 UInt32 zchh = (UInt32)(zchh0); \
308 /*-- fast track the common case --*/ \
309 if (zchh != zs->state_in_ch && \
310 zs->state_in_len == 1) { \
311 UChar ch = (UChar)(zs->state_in_ch); \
312 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
313 zs->inUse[zs->state_in_ch] = True; \
314 zs->block[zs->nblock] = (UChar)ch; \
315 zs->nblock++; \
316 zs->state_in_ch = zchh; \
317 } \
318 else \
319 /*-- general, uncommon cases --*/ \
320 if (zchh != zs->state_in_ch || \
321 zs->state_in_len == 255) { \
322 if (zs->state_in_ch < 256) \
323 add_pair_to_block ( zs ); \
324 zs->state_in_ch = zchh; \
325 zs->state_in_len = 1; \
326 } else { \
327 zs->state_in_len++; \
328 } \
329}
330
331
332/*---------------------------------------------------*/
333static
334Bool copy_input_until_stop ( EState* s )
335{
336 Bool progress_in = False;
337
338 if (s->mode == BZ_M_RUNNING) {
339
340 /*-- fast track the common case --*/
341 while (True) {
342 /*-- block full? --*/
343 if (s->nblock >= s->nblockMAX) break;
344 /*-- no input? --*/
345 if (s->strm->avail_in == 0) break;
346 progress_in = True;
347 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
348 s->strm->next_in++;
349 s->strm->avail_in--;
350 s->strm->total_in_lo32++;
351 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
352 }
353
354 } else {
355
356 /*-- general, uncommon case --*/
357 while (True) {
358 /*-- block full? --*/
359 if (s->nblock >= s->nblockMAX) break;
360 /*-- no input? --*/
361 if (s->strm->avail_in == 0) break;
362 /*-- flush/finish end? --*/
363 if (s->avail_in_expect == 0) break;
364 progress_in = True;
365 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
366 s->strm->next_in++;
367 s->strm->avail_in--;
368 s->strm->total_in_lo32++;
369 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
370 s->avail_in_expect--;
371 }
372 }
373 return progress_in;
374}
375
376
377/*---------------------------------------------------*/
378static
379Bool copy_output_until_stop ( EState* s )
380{
381 Bool progress_out = False;
382
383 while (True) {
384
385 /*-- no output space? --*/
386 if (s->strm->avail_out == 0) break;
387
388 /*-- block done? --*/
389 if (s->state_out_pos >= s->numZ) break;
390
391 progress_out = True;
392 *(s->strm->next_out) = s->zbits[s->state_out_pos];
393 s->state_out_pos++;
394 s->strm->avail_out--;
395 s->strm->next_out++;
396 s->strm->total_out_lo32++;
397 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
398 }
399
400 return progress_out;
401}
402
403
404/*---------------------------------------------------*/
405static
406Bool handle_compress ( bz_stream* strm )
407{
408 Bool progress_in = False;
409 Bool progress_out = False;
410 EState* s = strm->state;
411
412 while (True) {
413
414 if (s->state == BZ_S_OUTPUT) {
415 progress_out |= copy_output_until_stop ( s );
416 if (s->state_out_pos < s->numZ) break;
417 if (s->mode == BZ_M_FINISHING &&
418 s->avail_in_expect == 0 &&
419 isempty_RL(s)) break;
420 prepare_new_block ( s );
421 s->state = BZ_S_INPUT;
422 if (s->mode == BZ_M_FLUSHING &&
423 s->avail_in_expect == 0 &&
424 isempty_RL(s)) break;
425 }
426
427 if (s->state == BZ_S_INPUT) {
428 progress_in |= copy_input_until_stop ( s );
429 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
430 flush_RL ( s );
431 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
432 s->state = BZ_S_OUTPUT;
433 }
434 else
435 if (s->nblock >= s->nblockMAX) {
436 BZ2_compressBlock ( s, False );
437 s->state = BZ_S_OUTPUT;
438 }
439 else
440 if (s->strm->avail_in == 0) {
441 break;
442 }
443 }
444
445 }
446
447 return progress_in || progress_out;
448}
449
450
451/*---------------------------------------------------*/
452int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
453{
454 Bool progress;
455 EState* s;
456 if (strm == NULL) return BZ_PARAM_ERROR;
457 s = strm->state;
458 if (s == NULL) return BZ_PARAM_ERROR;
459 if (s->strm != strm) return BZ_PARAM_ERROR;
460
461 preswitch:
462 switch (s->mode) {
463
464 case BZ_M_IDLE:
465 return BZ_SEQUENCE_ERROR;
466
467 case BZ_M_RUNNING:
468 if (action == BZ_RUN) {
469 progress = handle_compress ( strm );
470 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
471 }
472 else
473 if (action == BZ_FLUSH) {
474 s->avail_in_expect = strm->avail_in;
475 s->mode = BZ_M_FLUSHING;
476 goto preswitch;
477 }
478 else
479 if (action == BZ_FINISH) {
480 s->avail_in_expect = strm->avail_in;
481 s->mode = BZ_M_FINISHING;
482 goto preswitch;
483 }
484 else
485 return BZ_PARAM_ERROR;
486
487 case BZ_M_FLUSHING:
488 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
489 if (s->avail_in_expect != s->strm->avail_in)
490 return BZ_SEQUENCE_ERROR;
491 progress = handle_compress ( strm );
492 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
493 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
494 s->mode = BZ_M_RUNNING;
495 return BZ_RUN_OK;
496
497 case BZ_M_FINISHING:
498 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
499 if (s->avail_in_expect != s->strm->avail_in)
500 return BZ_SEQUENCE_ERROR;
501 progress = handle_compress ( strm );
502 if (!progress) return BZ_SEQUENCE_ERROR;
503 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
504 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
505 s->mode = BZ_M_IDLE;
506 return BZ_STREAM_END;
507 }
508 return BZ_OK; /*--not reached--*/
509}
510
511
512/*---------------------------------------------------*/
513int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
514{
515 EState* s;
516 if (strm == NULL) return BZ_PARAM_ERROR;
517 s = strm->state;
518 if (s == NULL) return BZ_PARAM_ERROR;
519 if (s->strm != strm) return BZ_PARAM_ERROR;
520
521 if (s->arr1 != NULL) BZFREE(s->arr1);
522 if (s->arr2 != NULL) BZFREE(s->arr2);
523 if (s->ftab != NULL) BZFREE(s->ftab);
524 BZFREE(strm->state);
525
526 strm->state = NULL;
527
528 return BZ_OK;
529}
530
531
532/*---------------------------------------------------*/
533/*--- Decompression stuff ---*/
534/*---------------------------------------------------*/
535
536/*---------------------------------------------------*/
537int BZ_API(BZ2_bzDecompressInit)
538 ( bz_stream* strm,
539 int verbosity,
540 int small )
541{
542 DState* s;
543
544 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
545
546 if (strm == NULL) return BZ_PARAM_ERROR;
547 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
548 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
549
550 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
551 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
552
553 s = BZALLOC( sizeof(DState) );
554 if (s == NULL) return BZ_MEM_ERROR;
555 s->strm = strm;
556 strm->state = s;
557 s->state = BZ_X_MAGIC_1;
558 s->bsLive = 0;
559 s->bsBuff = 0;
560 s->calculatedCombinedCRC = 0;
561 strm->total_in_lo32 = 0;
562 strm->total_in_hi32 = 0;
563 strm->total_out_lo32 = 0;
564 strm->total_out_hi32 = 0;
565 s->smallDecompress = (Bool)small;
566 s->ll4 = NULL;
567 s->ll16 = NULL;
568 s->tt = NULL;
569 s->currBlockNo = 0;
570 s->verbosity = verbosity;
571
572 return BZ_OK;
573}
574
575
576/*---------------------------------------------------*/
577/* Return True iff data corruption is discovered.
578 Returns False if there is no problem.
579*/
577static
580static
578void unRLE_obuf_to_output_FAST ( DState* s )
581Bool unRLE_obuf_to_output_FAST ( DState* s )
579{
580 UChar k1;
581
582 if (s->blockRandomised) {
583
584 while (True) {
585 /* try to finish existing run */
586 while (True) {
582{
583 UChar k1;
584
585 if (s->blockRandomised) {
586
587 while (True) {
588 /* try to finish existing run */
589 while (True) {
587 if (s->strm->avail_out == 0) return;
590 if (s->strm->avail_out == 0) return False;
588 if (s->state_out_len == 0) break;
589 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
590 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
591 s->state_out_len--;
592 s->strm->next_out++;
593 s->strm->avail_out--;
594 s->strm->total_out_lo32++;
595 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
596 }
591 if (s->state_out_len == 0) break;
592 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
593 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
594 s->state_out_len--;
595 s->strm->next_out++;
596 s->strm->avail_out--;
597 s->strm->total_out_lo32++;
598 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
599 }
597
600
598 /* can a new run be started? */
601 /* can a new run be started? */
599 if (s->nblock_used == s->save_nblock+1) return;
602 if (s->nblock_used == s->save_nblock+1) return False;
600
603
604 /* Only caused by corrupt data stream? */
605 if (s->nblock_used > s->save_nblock+1)
606 return True;
601
602 s->state_out_len = 1;
603 s->state_out_ch = s->k0;
604 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
605 k1 ^= BZ_RAND_MASK; s->nblock_used++;
606 if (s->nblock_used == s->save_nblock+1) continue;
607 if (k1 != s->k0) { s->k0 = k1; continue; };
608
609 s->state_out_len = 2;
610 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
611 k1 ^= BZ_RAND_MASK; s->nblock_used++;
612 if (s->nblock_used == s->save_nblock+1) continue;
613 if (k1 != s->k0) { s->k0 = k1; continue; };
614
615 s->state_out_len = 3;
616 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
617 k1 ^= BZ_RAND_MASK; s->nblock_used++;
618 if (s->nblock_used == s->save_nblock+1) continue;
619 if (k1 != s->k0) { s->k0 = k1; continue; };
620
621 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
622 k1 ^= BZ_RAND_MASK; s->nblock_used++;
623 s->state_out_len = ((Int32)k1) + 4;
624 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
625 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
626 }
627
628 } else {
629
630 /* restore */
631 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
632 UChar c_state_out_ch = s->state_out_ch;
633 Int32 c_state_out_len = s->state_out_len;
634 Int32 c_nblock_used = s->nblock_used;
635 Int32 c_k0 = s->k0;
636 UInt32* c_tt = s->tt;
637 UInt32 c_tPos = s->tPos;
638 char* cs_next_out = s->strm->next_out;
639 unsigned int cs_avail_out = s->strm->avail_out;
640 /* end restore */
641
642 UInt32 avail_out_INIT = cs_avail_out;
643 Int32 s_save_nblockPP = s->save_nblock+1;
644 unsigned int total_out_lo32_old;
645
646 while (True) {
647
648 /* try to finish existing run */
649 if (c_state_out_len > 0) {
650 while (True) {
651 if (cs_avail_out == 0) goto return_notr;
652 if (c_state_out_len == 1) break;
653 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
654 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
655 c_state_out_len--;
656 cs_next_out++;
657 cs_avail_out--;
658 }
659 s_state_out_len_eq_one:
660 {
661 if (cs_avail_out == 0) {
662 c_state_out_len = 1; goto return_notr;
663 };
664 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
665 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
666 cs_next_out++;
667 cs_avail_out--;
668 }
669 }
607
608 s->state_out_len = 1;
609 s->state_out_ch = s->k0;
610 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
611 k1 ^= BZ_RAND_MASK; s->nblock_used++;
612 if (s->nblock_used == s->save_nblock+1) continue;
613 if (k1 != s->k0) { s->k0 = k1; continue; };
614
615 s->state_out_len = 2;
616 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
617 k1 ^= BZ_RAND_MASK; s->nblock_used++;
618 if (s->nblock_used == s->save_nblock+1) continue;
619 if (k1 != s->k0) { s->k0 = k1; continue; };
620
621 s->state_out_len = 3;
622 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
623 k1 ^= BZ_RAND_MASK; s->nblock_used++;
624 if (s->nblock_used == s->save_nblock+1) continue;
625 if (k1 != s->k0) { s->k0 = k1; continue; };
626
627 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
628 k1 ^= BZ_RAND_MASK; s->nblock_used++;
629 s->state_out_len = ((Int32)k1) + 4;
630 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
631 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
632 }
633
634 } else {
635
636 /* restore */
637 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
638 UChar c_state_out_ch = s->state_out_ch;
639 Int32 c_state_out_len = s->state_out_len;
640 Int32 c_nblock_used = s->nblock_used;
641 Int32 c_k0 = s->k0;
642 UInt32* c_tt = s->tt;
643 UInt32 c_tPos = s->tPos;
644 char* cs_next_out = s->strm->next_out;
645 unsigned int cs_avail_out = s->strm->avail_out;
646 /* end restore */
647
648 UInt32 avail_out_INIT = cs_avail_out;
649 Int32 s_save_nblockPP = s->save_nblock+1;
650 unsigned int total_out_lo32_old;
651
652 while (True) {
653
654 /* try to finish existing run */
655 if (c_state_out_len > 0) {
656 while (True) {
657 if (cs_avail_out == 0) goto return_notr;
658 if (c_state_out_len == 1) break;
659 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
660 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
661 c_state_out_len--;
662 cs_next_out++;
663 cs_avail_out--;
664 }
665 s_state_out_len_eq_one:
666 {
667 if (cs_avail_out == 0) {
668 c_state_out_len = 1; goto return_notr;
669 };
670 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
671 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
672 cs_next_out++;
673 cs_avail_out--;
674 }
675 }
676 /* Only caused by corrupt data stream? */
677 if (c_nblock_used > s_save_nblockPP)
678 return True;
679
670 /* can a new run be started? */
671 if (c_nblock_used == s_save_nblockPP) {
672 c_state_out_len = 0; goto return_notr;
673 };
674 c_state_out_ch = c_k0;
675 BZ_GET_FAST_C(k1); c_nblock_used++;
676 if (k1 != c_k0) {
677 c_k0 = k1; goto s_state_out_len_eq_one;
678 };
679 if (c_nblock_used == s_save_nblockPP)
680 goto s_state_out_len_eq_one;
681
682 c_state_out_len = 2;
683 BZ_GET_FAST_C(k1); c_nblock_used++;
684 if (c_nblock_used == s_save_nblockPP) continue;
685 if (k1 != c_k0) { c_k0 = k1; continue; };
686
687 c_state_out_len = 3;
688 BZ_GET_FAST_C(k1); c_nblock_used++;
689 if (c_nblock_used == s_save_nblockPP) continue;
690 if (k1 != c_k0) { c_k0 = k1; continue; };
691
692 BZ_GET_FAST_C(k1); c_nblock_used++;
693 c_state_out_len = ((Int32)k1) + 4;
694 BZ_GET_FAST_C(c_k0); c_nblock_used++;
695 }
696
697 return_notr:
698 total_out_lo32_old = s->strm->total_out_lo32;
699 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
700 if (s->strm->total_out_lo32 < total_out_lo32_old)
701 s->strm->total_out_hi32++;
702
703 /* save */
704 s->calculatedBlockCRC = c_calculatedBlockCRC;
705 s->state_out_ch = c_state_out_ch;
706 s->state_out_len = c_state_out_len;
707 s->nblock_used = c_nblock_used;
708 s->k0 = c_k0;
709 s->tt = c_tt;
710 s->tPos = c_tPos;
711 s->strm->next_out = cs_next_out;
712 s->strm->avail_out = cs_avail_out;
713 /* end save */
714 }
680 /* can a new run be started? */
681 if (c_nblock_used == s_save_nblockPP) {
682 c_state_out_len = 0; goto return_notr;
683 };
684 c_state_out_ch = c_k0;
685 BZ_GET_FAST_C(k1); c_nblock_used++;
686 if (k1 != c_k0) {
687 c_k0 = k1; goto s_state_out_len_eq_one;
688 };
689 if (c_nblock_used == s_save_nblockPP)
690 goto s_state_out_len_eq_one;
691
692 c_state_out_len = 2;
693 BZ_GET_FAST_C(k1); c_nblock_used++;
694 if (c_nblock_used == s_save_nblockPP) continue;
695 if (k1 != c_k0) { c_k0 = k1; continue; };
696
697 c_state_out_len = 3;
698 BZ_GET_FAST_C(k1); c_nblock_used++;
699 if (c_nblock_used == s_save_nblockPP) continue;
700 if (k1 != c_k0) { c_k0 = k1; continue; };
701
702 BZ_GET_FAST_C(k1); c_nblock_used++;
703 c_state_out_len = ((Int32)k1) + 4;
704 BZ_GET_FAST_C(c_k0); c_nblock_used++;
705 }
706
707 return_notr:
708 total_out_lo32_old = s->strm->total_out_lo32;
709 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
710 if (s->strm->total_out_lo32 < total_out_lo32_old)
711 s->strm->total_out_hi32++;
712
713 /* save */
714 s->calculatedBlockCRC = c_calculatedBlockCRC;
715 s->state_out_ch = c_state_out_ch;
716 s->state_out_len = c_state_out_len;
717 s->nblock_used = c_nblock_used;
718 s->k0 = c_k0;
719 s->tt = c_tt;
720 s->tPos = c_tPos;
721 s->strm->next_out = cs_next_out;
722 s->strm->avail_out = cs_avail_out;
723 /* end save */
724 }
725 return False;
715}
716
717
718
719/*---------------------------------------------------*/
720__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
721{
722 Int32 nb, na, mid;
723 nb = 0;
724 na = 256;
725 do {
726 mid = (nb + na) >> 1;
727 if (indx >= cftab[mid]) nb = mid; else na = mid;
728 }
729 while (na - nb != 1);
730 return nb;
731}
732
733
734/*---------------------------------------------------*/
726}
727
728
729
730/*---------------------------------------------------*/
731__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
732{
733 Int32 nb, na, mid;
734 nb = 0;
735 na = 256;
736 do {
737 mid = (nb + na) >> 1;
738 if (indx >= cftab[mid]) nb = mid; else na = mid;
739 }
740 while (na - nb != 1);
741 return nb;
742}
743
744
745/*---------------------------------------------------*/
746/* Return True iff data corruption is discovered.
747 Returns False if there is no problem.
748*/
735static
749static
736void unRLE_obuf_to_output_SMALL ( DState* s )
750Bool unRLE_obuf_to_output_SMALL ( DState* s )
737{
738 UChar k1;
739
740 if (s->blockRandomised) {
741
742 while (True) {
743 /* try to finish existing run */
744 while (True) {
751{
752 UChar k1;
753
754 if (s->blockRandomised) {
755
756 while (True) {
757 /* try to finish existing run */
758 while (True) {
745 if (s->strm->avail_out == 0) return;
759 if (s->strm->avail_out == 0) return False;
746 if (s->state_out_len == 0) break;
747 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
748 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
749 s->state_out_len--;
750 s->strm->next_out++;
751 s->strm->avail_out--;
752 s->strm->total_out_lo32++;
753 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
754 }
755
756 /* can a new run be started? */
760 if (s->state_out_len == 0) break;
761 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
762 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
763 s->state_out_len--;
764 s->strm->next_out++;
765 s->strm->avail_out--;
766 s->strm->total_out_lo32++;
767 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
768 }
769
770 /* can a new run be started? */
757 if (s->nblock_used == s->save_nblock+1) return;
758
771 if (s->nblock_used == s->save_nblock+1) return False;
772
773 /* Only caused by corrupt data stream? */
774 if (s->nblock_used > s->save_nblock+1)
775 return True;
759
760 s->state_out_len = 1;
761 s->state_out_ch = s->k0;
762 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
763 k1 ^= BZ_RAND_MASK; s->nblock_used++;
764 if (s->nblock_used == s->save_nblock+1) continue;
765 if (k1 != s->k0) { s->k0 = k1; continue; };
766
767 s->state_out_len = 2;
768 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
769 k1 ^= BZ_RAND_MASK; s->nblock_used++;
770 if (s->nblock_used == s->save_nblock+1) continue;
771 if (k1 != s->k0) { s->k0 = k1; continue; };
772
773 s->state_out_len = 3;
774 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
775 k1 ^= BZ_RAND_MASK; s->nblock_used++;
776 if (s->nblock_used == s->save_nblock+1) continue;
777 if (k1 != s->k0) { s->k0 = k1; continue; };
778
779 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
780 k1 ^= BZ_RAND_MASK; s->nblock_used++;
781 s->state_out_len = ((Int32)k1) + 4;
782 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
783 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
784 }
785
786 } else {
787
788 while (True) {
789 /* try to finish existing run */
790 while (True) {
776
777 s->state_out_len = 1;
778 s->state_out_ch = s->k0;
779 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
780 k1 ^= BZ_RAND_MASK; s->nblock_used++;
781 if (s->nblock_used == s->save_nblock+1) continue;
782 if (k1 != s->k0) { s->k0 = k1; continue; };
783
784 s->state_out_len = 2;
785 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
786 k1 ^= BZ_RAND_MASK; s->nblock_used++;
787 if (s->nblock_used == s->save_nblock+1) continue;
788 if (k1 != s->k0) { s->k0 = k1; continue; };
789
790 s->state_out_len = 3;
791 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
792 k1 ^= BZ_RAND_MASK; s->nblock_used++;
793 if (s->nblock_used == s->save_nblock+1) continue;
794 if (k1 != s->k0) { s->k0 = k1; continue; };
795
796 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
797 k1 ^= BZ_RAND_MASK; s->nblock_used++;
798 s->state_out_len = ((Int32)k1) + 4;
799 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
800 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
801 }
802
803 } else {
804
805 while (True) {
806 /* try to finish existing run */
807 while (True) {
791 if (s->strm->avail_out == 0) return;
808 if (s->strm->avail_out == 0) return False;
792 if (s->state_out_len == 0) break;
793 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
794 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
795 s->state_out_len--;
796 s->strm->next_out++;
797 s->strm->avail_out--;
798 s->strm->total_out_lo32++;
799 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
800 }
801
802 /* can a new run be started? */
809 if (s->state_out_len == 0) break;
810 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
811 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
812 s->state_out_len--;
813 s->strm->next_out++;
814 s->strm->avail_out--;
815 s->strm->total_out_lo32++;
816 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
817 }
818
819 /* can a new run be started? */
803 if (s->nblock_used == s->save_nblock+1) return;
820 if (s->nblock_used == s->save_nblock+1) return False;
821
822 /* Only caused by corrupt data stream? */
823 if (s->nblock_used > s->save_nblock+1)
824 return True;
804
805 s->state_out_len = 1;
806 s->state_out_ch = s->k0;
807 BZ_GET_SMALL(k1); s->nblock_used++;
808 if (s->nblock_used == s->save_nblock+1) continue;
809 if (k1 != s->k0) { s->k0 = k1; continue; };
810
811 s->state_out_len = 2;
812 BZ_GET_SMALL(k1); s->nblock_used++;
813 if (s->nblock_used == s->save_nblock+1) continue;
814 if (k1 != s->k0) { s->k0 = k1; continue; };
815
816 s->state_out_len = 3;
817 BZ_GET_SMALL(k1); s->nblock_used++;
818 if (s->nblock_used == s->save_nblock+1) continue;
819 if (k1 != s->k0) { s->k0 = k1; continue; };
820
821 BZ_GET_SMALL(k1); s->nblock_used++;
822 s->state_out_len = ((Int32)k1) + 4;
823 BZ_GET_SMALL(s->k0); s->nblock_used++;
824 }
825
826 }
827}
828
829
830/*---------------------------------------------------*/
831int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
832{
825
826 s->state_out_len = 1;
827 s->state_out_ch = s->k0;
828 BZ_GET_SMALL(k1); s->nblock_used++;
829 if (s->nblock_used == s->save_nblock+1) continue;
830 if (k1 != s->k0) { s->k0 = k1; continue; };
831
832 s->state_out_len = 2;
833 BZ_GET_SMALL(k1); s->nblock_used++;
834 if (s->nblock_used == s->save_nblock+1) continue;
835 if (k1 != s->k0) { s->k0 = k1; continue; };
836
837 s->state_out_len = 3;
838 BZ_GET_SMALL(k1); s->nblock_used++;
839 if (s->nblock_used == s->save_nblock+1) continue;
840 if (k1 != s->k0) { s->k0 = k1; continue; };
841
842 BZ_GET_SMALL(k1); s->nblock_used++;
843 s->state_out_len = ((Int32)k1) + 4;
844 BZ_GET_SMALL(s->k0); s->nblock_used++;
845 }
846
847 }
848}
849
850
851/*---------------------------------------------------*/
852int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
853{
854 Bool corrupt;
833 DState* s;
834 if (strm == NULL) return BZ_PARAM_ERROR;
835 s = strm->state;
836 if (s == NULL) return BZ_PARAM_ERROR;
837 if (s->strm != strm) return BZ_PARAM_ERROR;
838
839 while (True) {
840 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
841 if (s->state == BZ_X_OUTPUT) {
842 if (s->smallDecompress)
855 DState* s;
856 if (strm == NULL) return BZ_PARAM_ERROR;
857 s = strm->state;
858 if (s == NULL) return BZ_PARAM_ERROR;
859 if (s->strm != strm) return BZ_PARAM_ERROR;
860
861 while (True) {
862 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
863 if (s->state == BZ_X_OUTPUT) {
864 if (s->smallDecompress)
843 unRLE_obuf_to_output_SMALL ( s ); else
844 unRLE_obuf_to_output_FAST ( s );
865 corrupt = unRLE_obuf_to_output_SMALL ( s ); else
866 corrupt = unRLE_obuf_to_output_FAST ( s );
867 if (corrupt) return BZ_DATA_ERROR;
845 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
846 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
847 if (s->verbosity >= 3)
868 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
869 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
870 if (s->verbosity >= 3)
848 VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC,
871 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
849 s->calculatedBlockCRC );
850 if (s->verbosity >= 2) VPrintf0 ( "]" );
851 if (s->calculatedBlockCRC != s->storedBlockCRC)
852 return BZ_DATA_ERROR;
853 s->calculatedCombinedCRC
854 = (s->calculatedCombinedCRC << 1) |
855 (s->calculatedCombinedCRC >> 31);
856 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
857 s->state = BZ_X_BLKHDR_1;
858 } else {
859 return BZ_OK;
860 }
861 }
862 if (s->state >= BZ_X_MAGIC_1) {
863 Int32 r = BZ2_decompress ( s );
864 if (r == BZ_STREAM_END) {
865 if (s->verbosity >= 3)
872 s->calculatedBlockCRC );
873 if (s->verbosity >= 2) VPrintf0 ( "]" );
874 if (s->calculatedBlockCRC != s->storedBlockCRC)
875 return BZ_DATA_ERROR;
876 s->calculatedCombinedCRC
877 = (s->calculatedCombinedCRC << 1) |
878 (s->calculatedCombinedCRC >> 31);
879 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
880 s->state = BZ_X_BLKHDR_1;
881 } else {
882 return BZ_OK;
883 }
884 }
885 if (s->state >= BZ_X_MAGIC_1) {
886 Int32 r = BZ2_decompress ( s );
887 if (r == BZ_STREAM_END) {
888 if (s->verbosity >= 3)
866 VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x",
889 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
867 s->storedCombinedCRC, s->calculatedCombinedCRC );
868 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
869 return BZ_DATA_ERROR;
870 return r;
871 }
872 if (s->state != BZ_X_OUTPUT) return r;
873 }
874 }
875
876 AssertH ( 0, 6001 );
877
878 return 0; /*NOTREACHED*/
879}
880
881
882/*---------------------------------------------------*/
883int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
884{
885 DState* s;
886 if (strm == NULL) return BZ_PARAM_ERROR;
887 s = strm->state;
888 if (s == NULL) return BZ_PARAM_ERROR;
889 if (s->strm != strm) return BZ_PARAM_ERROR;
890
891 if (s->tt != NULL) BZFREE(s->tt);
892 if (s->ll16 != NULL) BZFREE(s->ll16);
893 if (s->ll4 != NULL) BZFREE(s->ll4);
894
895 BZFREE(strm->state);
896 strm->state = NULL;
897
898 return BZ_OK;
899}
900
901
902#ifndef BZ_NO_STDIO
903/*---------------------------------------------------*/
904/*--- File I/O stuff ---*/
905/*---------------------------------------------------*/
906
907#define BZ_SETERR(eee) \
908{ \
909 if (bzerror != NULL) *bzerror = eee; \
910 if (bzf != NULL) bzf->lastErr = eee; \
911}
912
913typedef
914 struct {
915 FILE* handle;
916 Char buf[BZ_MAX_UNUSED];
917 Int32 bufN;
918 Bool writing;
919 bz_stream strm;
920 Int32 lastErr;
921 Bool initialisedOk;
922 }
923 bzFile;
924
925
926/*---------------------------------------------*/
927static Bool myfeof ( FILE* f )
928{
929 Int32 c = fgetc ( f );
930 if (c == EOF) return True;
931 ungetc ( c, f );
932 return False;
933}
934
935
936/*---------------------------------------------------*/
937BZFILE* BZ_API(BZ2_bzWriteOpen)
938 ( int* bzerror,
939 FILE* f,
940 int blockSize100k,
941 int verbosity,
942 int workFactor )
943{
944 Int32 ret;
945 bzFile* bzf = NULL;
946
947 BZ_SETERR(BZ_OK);
948
949 if (f == NULL ||
950 (blockSize100k < 1 || blockSize100k > 9) ||
951 (workFactor < 0 || workFactor > 250) ||
952 (verbosity < 0 || verbosity > 4))
953 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
954
955 if (ferror(f))
956 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
957
958 bzf = malloc ( sizeof(bzFile) );
959 if (bzf == NULL)
960 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
961
962 BZ_SETERR(BZ_OK);
963 bzf->initialisedOk = False;
964 bzf->bufN = 0;
965 bzf->handle = f;
966 bzf->writing = True;
967 bzf->strm.bzalloc = NULL;
968 bzf->strm.bzfree = NULL;
969 bzf->strm.opaque = NULL;
970
971 if (workFactor == 0) workFactor = 30;
972 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
973 verbosity, workFactor );
974 if (ret != BZ_OK)
975 { BZ_SETERR(ret); free(bzf); return NULL; };
976
977 bzf->strm.avail_in = 0;
978 bzf->initialisedOk = True;
979 return bzf;
980}
981
982
983
984/*---------------------------------------------------*/
985void BZ_API(BZ2_bzWrite)
986 ( int* bzerror,
987 BZFILE* b,
988 void* buf,
989 int len )
990{
991 Int32 n, n2, ret;
992 bzFile* bzf = (bzFile*)b;
993
994 BZ_SETERR(BZ_OK);
995 if (bzf == NULL || buf == NULL || len < 0)
996 { BZ_SETERR(BZ_PARAM_ERROR); return; };
997 if (!(bzf->writing))
998 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
999 if (ferror(bzf->handle))
1000 { BZ_SETERR(BZ_IO_ERROR); return; };
1001
1002 if (len == 0)
1003 { BZ_SETERR(BZ_OK); return; };
1004
1005 bzf->strm.avail_in = len;
1006 bzf->strm.next_in = buf;
1007
1008 while (True) {
1009 bzf->strm.avail_out = BZ_MAX_UNUSED;
1010 bzf->strm.next_out = bzf->buf;
1011 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
1012 if (ret != BZ_RUN_OK)
1013 { BZ_SETERR(ret); return; };
1014
1015 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1016 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1017 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1018 n, bzf->handle );
1019 if (n != n2 || ferror(bzf->handle))
1020 { BZ_SETERR(BZ_IO_ERROR); return; };
1021 }
1022
1023 if (bzf->strm.avail_in == 0)
1024 { BZ_SETERR(BZ_OK); return; };
1025 }
1026}
1027
1028
1029/*---------------------------------------------------*/
1030void BZ_API(BZ2_bzWriteClose)
1031 ( int* bzerror,
1032 BZFILE* b,
1033 int abandon,
1034 unsigned int* nbytes_in,
1035 unsigned int* nbytes_out )
1036{
1037 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1038 nbytes_in, NULL, nbytes_out, NULL );
1039}
1040
1041
1042void BZ_API(BZ2_bzWriteClose64)
1043 ( int* bzerror,
1044 BZFILE* b,
1045 int abandon,
1046 unsigned int* nbytes_in_lo32,
1047 unsigned int* nbytes_in_hi32,
1048 unsigned int* nbytes_out_lo32,
1049 unsigned int* nbytes_out_hi32 )
1050{
1051 Int32 n, n2, ret;
1052 bzFile* bzf = (bzFile*)b;
1053
1054 if (bzf == NULL)
1055 { BZ_SETERR(BZ_OK); return; };
1056 if (!(bzf->writing))
1057 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1058 if (ferror(bzf->handle))
1059 { BZ_SETERR(BZ_IO_ERROR); return; };
1060
1061 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1062 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1063 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1064 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1065
1066 if ((!abandon) && bzf->lastErr == BZ_OK) {
1067 while (True) {
1068 bzf->strm.avail_out = BZ_MAX_UNUSED;
1069 bzf->strm.next_out = bzf->buf;
1070 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1071 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1072 { BZ_SETERR(ret); return; };
1073
1074 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1075 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1076 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1077 n, bzf->handle );
1078 if (n != n2 || ferror(bzf->handle))
1079 { BZ_SETERR(BZ_IO_ERROR); return; };
1080 }
1081
1082 if (ret == BZ_STREAM_END) break;
1083 }
1084 }
1085
1086 if ( !abandon && !ferror ( bzf->handle ) ) {
1087 fflush ( bzf->handle );
1088 if (ferror(bzf->handle))
1089 { BZ_SETERR(BZ_IO_ERROR); return; };
1090 }
1091
1092 if (nbytes_in_lo32 != NULL)
1093 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1094 if (nbytes_in_hi32 != NULL)
1095 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1096 if (nbytes_out_lo32 != NULL)
1097 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1098 if (nbytes_out_hi32 != NULL)
1099 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1100
1101 BZ_SETERR(BZ_OK);
1102 BZ2_bzCompressEnd ( &(bzf->strm) );
1103 free ( bzf );
1104}
1105
1106
1107/*---------------------------------------------------*/
1108BZFILE* BZ_API(BZ2_bzReadOpen)
1109 ( int* bzerror,
1110 FILE* f,
1111 int verbosity,
1112 int small,
1113 void* unused,
1114 int nUnused )
1115{
1116 bzFile* bzf = NULL;
1117 int ret;
1118
1119 BZ_SETERR(BZ_OK);
1120
1121 if (f == NULL ||
1122 (small != 0 && small != 1) ||
1123 (verbosity < 0 || verbosity > 4) ||
1124 (unused == NULL && nUnused != 0) ||
1125 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1126 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1127
1128 if (ferror(f))
1129 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1130
1131 bzf = malloc ( sizeof(bzFile) );
1132 if (bzf == NULL)
1133 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1134
1135 BZ_SETERR(BZ_OK);
1136
1137 bzf->initialisedOk = False;
1138 bzf->handle = f;
1139 bzf->bufN = 0;
1140 bzf->writing = False;
1141 bzf->strm.bzalloc = NULL;
1142 bzf->strm.bzfree = NULL;
1143 bzf->strm.opaque = NULL;
1144
1145 while (nUnused > 0) {
1146 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1147 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1148 nUnused--;
1149 }
1150
1151 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1152 if (ret != BZ_OK)
1153 { BZ_SETERR(ret); free(bzf); return NULL; };
1154
1155 bzf->strm.avail_in = bzf->bufN;
1156 bzf->strm.next_in = bzf->buf;
1157
1158 bzf->initialisedOk = True;
1159 return bzf;
1160}
1161
1162
1163/*---------------------------------------------------*/
1164void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1165{
1166 bzFile* bzf = (bzFile*)b;
1167
1168 BZ_SETERR(BZ_OK);
1169 if (bzf == NULL)
1170 { BZ_SETERR(BZ_OK); return; };
1171
1172 if (bzf->writing)
1173 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1174
1175 if (bzf->initialisedOk)
1176 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1177 free ( bzf );
1178}
1179
1180
1181/*---------------------------------------------------*/
1182int BZ_API(BZ2_bzRead)
1183 ( int* bzerror,
1184 BZFILE* b,
1185 void* buf,
1186 int len )
1187{
1188 Int32 n, ret;
1189 bzFile* bzf = (bzFile*)b;
1190
1191 BZ_SETERR(BZ_OK);
1192
1193 if (bzf == NULL || buf == NULL || len < 0)
1194 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1195
1196 if (bzf->writing)
1197 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1198
1199 if (len == 0)
1200 { BZ_SETERR(BZ_OK); return 0; };
1201
1202 bzf->strm.avail_out = len;
1203 bzf->strm.next_out = buf;
1204
1205 while (True) {
1206
1207 if (ferror(bzf->handle))
1208 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1209
1210 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1211 n = fread ( bzf->buf, sizeof(UChar),
1212 BZ_MAX_UNUSED, bzf->handle );
1213 if (ferror(bzf->handle))
1214 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1215 bzf->bufN = n;
1216 bzf->strm.avail_in = bzf->bufN;
1217 bzf->strm.next_in = bzf->buf;
1218 }
1219
1220 ret = BZ2_bzDecompress ( &(bzf->strm) );
1221
1222 if (ret != BZ_OK && ret != BZ_STREAM_END)
1223 { BZ_SETERR(ret); return 0; };
1224
1225 if (ret == BZ_OK && myfeof(bzf->handle) &&
1226 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1227 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1228
1229 if (ret == BZ_STREAM_END)
1230 { BZ_SETERR(BZ_STREAM_END);
1231 return len - bzf->strm.avail_out; };
1232 if (bzf->strm.avail_out == 0)
1233 { BZ_SETERR(BZ_OK); return len; };
1234
1235 }
1236
1237 return 0; /*not reached*/
1238}
1239
1240
1241/*---------------------------------------------------*/
1242void BZ_API(BZ2_bzReadGetUnused)
1243 ( int* bzerror,
1244 BZFILE* b,
1245 void** unused,
1246 int* nUnused )
1247{
1248 bzFile* bzf = (bzFile*)b;
1249 if (bzf == NULL)
1250 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1251 if (bzf->lastErr != BZ_STREAM_END)
1252 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1253 if (unused == NULL || nUnused == NULL)
1254 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1255
1256 BZ_SETERR(BZ_OK);
1257 *nUnused = bzf->strm.avail_in;
1258 *unused = bzf->strm.next_in;
1259}
1260#endif
1261
1262
1263/*---------------------------------------------------*/
1264/*--- Misc convenience stuff ---*/
1265/*---------------------------------------------------*/
1266
1267/*---------------------------------------------------*/
1268int BZ_API(BZ2_bzBuffToBuffCompress)
1269 ( char* dest,
1270 unsigned int* destLen,
1271 char* source,
1272 unsigned int sourceLen,
1273 int blockSize100k,
1274 int verbosity,
1275 int workFactor )
1276{
1277 bz_stream strm;
1278 int ret;
1279
1280 if (dest == NULL || destLen == NULL ||
1281 source == NULL ||
1282 blockSize100k < 1 || blockSize100k > 9 ||
1283 verbosity < 0 || verbosity > 4 ||
1284 workFactor < 0 || workFactor > 250)
1285 return BZ_PARAM_ERROR;
1286
1287 if (workFactor == 0) workFactor = 30;
1288 strm.bzalloc = NULL;
1289 strm.bzfree = NULL;
1290 strm.opaque = NULL;
1291 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1292 verbosity, workFactor );
1293 if (ret != BZ_OK) return ret;
1294
1295 strm.next_in = source;
1296 strm.next_out = dest;
1297 strm.avail_in = sourceLen;
1298 strm.avail_out = *destLen;
1299
1300 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1301 if (ret == BZ_FINISH_OK) goto output_overflow;
1302 if (ret != BZ_STREAM_END) goto errhandler;
1303
1304 /* normal termination */
1305 *destLen -= strm.avail_out;
1306 BZ2_bzCompressEnd ( &strm );
1307 return BZ_OK;
1308
1309 output_overflow:
1310 BZ2_bzCompressEnd ( &strm );
1311 return BZ_OUTBUFF_FULL;
1312
1313 errhandler:
1314 BZ2_bzCompressEnd ( &strm );
1315 return ret;
1316}
1317
1318
1319/*---------------------------------------------------*/
1320int BZ_API(BZ2_bzBuffToBuffDecompress)
1321 ( char* dest,
1322 unsigned int* destLen,
1323 char* source,
1324 unsigned int sourceLen,
1325 int small,
1326 int verbosity )
1327{
1328 bz_stream strm;
1329 int ret;
1330
1331 if (dest == NULL || destLen == NULL ||
1332 source == NULL ||
1333 (small != 0 && small != 1) ||
1334 verbosity < 0 || verbosity > 4)
1335 return BZ_PARAM_ERROR;
1336
1337 strm.bzalloc = NULL;
1338 strm.bzfree = NULL;
1339 strm.opaque = NULL;
1340 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1341 if (ret != BZ_OK) return ret;
1342
1343 strm.next_in = source;
1344 strm.next_out = dest;
1345 strm.avail_in = sourceLen;
1346 strm.avail_out = *destLen;
1347
1348 ret = BZ2_bzDecompress ( &strm );
1349 if (ret == BZ_OK) goto output_overflow_or_eof;
1350 if (ret != BZ_STREAM_END) goto errhandler;
1351
1352 /* normal termination */
1353 *destLen -= strm.avail_out;
1354 BZ2_bzDecompressEnd ( &strm );
1355 return BZ_OK;
1356
1357 output_overflow_or_eof:
1358 if (strm.avail_out > 0) {
1359 BZ2_bzDecompressEnd ( &strm );
1360 return BZ_UNEXPECTED_EOF;
1361 } else {
1362 BZ2_bzDecompressEnd ( &strm );
1363 return BZ_OUTBUFF_FULL;
1364 };
1365
1366 errhandler:
1367 BZ2_bzDecompressEnd ( &strm );
1368 return ret;
1369}
1370
1371
1372/*---------------------------------------------------*/
1373/*--
1374 Code contributed by Yoshioka Tsuneo
1375 (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
1376 to support better zlib compatibility.
1377 This code is not _officially_ part of libbzip2 (yet);
1378 I haven't tested it, documented it, or considered the
1379 threading-safeness of it.
1380 If this code breaks, please contact both Yoshioka and me.
1381--*/
1382/*---------------------------------------------------*/
1383
1384/*---------------------------------------------------*/
1385/*--
1386 return version like "0.9.0c".
1387--*/
1388const char * BZ_API(BZ2_bzlibVersion)(void)
1389{
1390 return BZ_VERSION;
1391}
1392
1393
1394#ifndef BZ_NO_STDIO
1395/*---------------------------------------------------*/
1396
1397#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1398# include <fcntl.h>
1399# include <io.h>
1400# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1401#else
1402# define SET_BINARY_MODE(file)
1403#endif
1404static
1405BZFILE * bzopen_or_bzdopen
1406 ( const char *path, /* no use when bzdopen */
1407 int fd, /* no use when bzdopen */
1408 const char *mode,
1409 int open_mode) /* bzopen: 0, bzdopen:1 */
1410{
1411 int bzerr;
1412 char unused[BZ_MAX_UNUSED];
1413 int blockSize100k = 9;
1414 int writing = 0;
1415 char mode2[10] = "";
1416 FILE *fp = NULL;
1417 BZFILE *bzfp = NULL;
1418 int verbosity = 0;
1419 int workFactor = 30;
1420 int smallMode = 0;
1421 int nUnused = 0;
1422
1423 if (mode == NULL) return NULL;
1424 while (*mode) {
1425 switch (*mode) {
1426 case 'r':
1427 writing = 0; break;
1428 case 'w':
1429 writing = 1; break;
1430 case 's':
1431 smallMode = 1; break;
1432 default:
1433 if (isdigit((int)(*mode))) {
1434 blockSize100k = *mode-BZ_HDR_0;
1435 }
1436 }
1437 mode++;
1438 }
1439 strcat(mode2, writing ? "w" : "r" );
1440 strcat(mode2,"b"); /* binary mode */
1441
1442 if (open_mode==0) {
1443 if (path==NULL || strcmp(path,"")==0) {
1444 fp = (writing ? stdout : stdin);
1445 SET_BINARY_MODE(fp);
1446 } else {
1447 fp = fopen(path,mode2);
1448 }
1449 } else {
1450#ifdef BZ_STRICT_ANSI
1451 fp = NULL;
1452#else
1453 fp = fdopen(fd,mode2);
1454#endif
1455 }
1456 if (fp == NULL) return NULL;
1457
1458 if (writing) {
1459 /* Guard against total chaos and anarchy -- JRS */
1460 if (blockSize100k < 1) blockSize100k = 1;
1461 if (blockSize100k > 9) blockSize100k = 9;
1462 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1463 verbosity,workFactor);
1464 } else {
1465 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1466 unused,nUnused);
1467 }
1468 if (bzfp == NULL) {
1469 if (fp != stdin && fp != stdout) fclose(fp);
1470 return NULL;
1471 }
1472 return bzfp;
1473}
1474
1475
1476/*---------------------------------------------------*/
1477/*--
1478 open file for read or write.
1479 ex) bzopen("file","w9")
1480 case path="" or NULL => use stdin or stdout.
1481--*/
1482BZFILE * BZ_API(BZ2_bzopen)
1483 ( const char *path,
1484 const char *mode )
1485{
1486 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1487}
1488
1489
1490/*---------------------------------------------------*/
1491BZFILE * BZ_API(BZ2_bzdopen)
1492 ( int fd,
1493 const char *mode )
1494{
1495 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1496}
1497
1498
1499/*---------------------------------------------------*/
1500int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1501{
1502 int bzerr, nread;
1503 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1504 nread = BZ2_bzRead(&bzerr,b,buf,len);
1505 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1506 return nread;
1507 } else {
1508 return -1;
1509 }
1510}
1511
1512
1513/*---------------------------------------------------*/
1514int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1515{
1516 int bzerr;
1517
1518 BZ2_bzWrite(&bzerr,b,buf,len);
1519 if(bzerr == BZ_OK){
1520 return len;
1521 }else{
1522 return -1;
1523 }
1524}
1525
1526
1527/*---------------------------------------------------*/
1528int BZ_API(BZ2_bzflush) (BZFILE *b)
1529{
1530 /* do nothing now... */
1531 return 0;
1532}
1533
1534
1535/*---------------------------------------------------*/
1536void BZ_API(BZ2_bzclose) (BZFILE* b)
1537{
1538 int bzerr;
1539 FILE *fp = ((bzFile *)b)->handle;
1540
1541 if (b==NULL) {return;}
1542 if(((bzFile*)b)->writing){
1543 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1544 if(bzerr != BZ_OK){
1545 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1546 }
1547 }else{
1548 BZ2_bzReadClose(&bzerr,b);
1549 }
1550 if(fp!=stdin && fp!=stdout){
1551 fclose(fp);
1552 }
1553}
1554
1555
1556/*---------------------------------------------------*/
1557/*--
1558 return last error code
1559--*/
1560static char *bzerrorstrings[] = {
1561 "OK"
1562 ,"SEQUENCE_ERROR"
1563 ,"PARAM_ERROR"
1564 ,"MEM_ERROR"
1565 ,"DATA_ERROR"
1566 ,"DATA_ERROR_MAGIC"
1567 ,"IO_ERROR"
1568 ,"UNEXPECTED_EOF"
1569 ,"OUTBUFF_FULL"
1570 ,"CONFIG_ERROR"
1571 ,"???" /* for future */
1572 ,"???" /* for future */
1573 ,"???" /* for future */
1574 ,"???" /* for future */
1575 ,"???" /* for future */
1576 ,"???" /* for future */
1577};
1578
1579
1580const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1581{
1582 int err = ((bzFile *)b)->lastErr;
1583
1584 if(err>0) err = 0;
1585 *errnum = err;
1586 return bzerrorstrings[err*-1];
1587}
1588#endif
1589
1590
1591/*-------------------------------------------------------------*/
1592/*--- end bzlib.c ---*/
1593/*-------------------------------------------------------------*/
890 s->storedCombinedCRC, s->calculatedCombinedCRC );
891 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
892 return BZ_DATA_ERROR;
893 return r;
894 }
895 if (s->state != BZ_X_OUTPUT) return r;
896 }
897 }
898
899 AssertH ( 0, 6001 );
900
901 return 0; /*NOTREACHED*/
902}
903
904
905/*---------------------------------------------------*/
906int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
907{
908 DState* s;
909 if (strm == NULL) return BZ_PARAM_ERROR;
910 s = strm->state;
911 if (s == NULL) return BZ_PARAM_ERROR;
912 if (s->strm != strm) return BZ_PARAM_ERROR;
913
914 if (s->tt != NULL) BZFREE(s->tt);
915 if (s->ll16 != NULL) BZFREE(s->ll16);
916 if (s->ll4 != NULL) BZFREE(s->ll4);
917
918 BZFREE(strm->state);
919 strm->state = NULL;
920
921 return BZ_OK;
922}
923
924
925#ifndef BZ_NO_STDIO
926/*---------------------------------------------------*/
927/*--- File I/O stuff ---*/
928/*---------------------------------------------------*/
929
930#define BZ_SETERR(eee) \
931{ \
932 if (bzerror != NULL) *bzerror = eee; \
933 if (bzf != NULL) bzf->lastErr = eee; \
934}
935
936typedef
937 struct {
938 FILE* handle;
939 Char buf[BZ_MAX_UNUSED];
940 Int32 bufN;
941 Bool writing;
942 bz_stream strm;
943 Int32 lastErr;
944 Bool initialisedOk;
945 }
946 bzFile;
947
948
949/*---------------------------------------------*/
950static Bool myfeof ( FILE* f )
951{
952 Int32 c = fgetc ( f );
953 if (c == EOF) return True;
954 ungetc ( c, f );
955 return False;
956}
957
958
959/*---------------------------------------------------*/
960BZFILE* BZ_API(BZ2_bzWriteOpen)
961 ( int* bzerror,
962 FILE* f,
963 int blockSize100k,
964 int verbosity,
965 int workFactor )
966{
967 Int32 ret;
968 bzFile* bzf = NULL;
969
970 BZ_SETERR(BZ_OK);
971
972 if (f == NULL ||
973 (blockSize100k < 1 || blockSize100k > 9) ||
974 (workFactor < 0 || workFactor > 250) ||
975 (verbosity < 0 || verbosity > 4))
976 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
977
978 if (ferror(f))
979 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
980
981 bzf = malloc ( sizeof(bzFile) );
982 if (bzf == NULL)
983 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
984
985 BZ_SETERR(BZ_OK);
986 bzf->initialisedOk = False;
987 bzf->bufN = 0;
988 bzf->handle = f;
989 bzf->writing = True;
990 bzf->strm.bzalloc = NULL;
991 bzf->strm.bzfree = NULL;
992 bzf->strm.opaque = NULL;
993
994 if (workFactor == 0) workFactor = 30;
995 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
996 verbosity, workFactor );
997 if (ret != BZ_OK)
998 { BZ_SETERR(ret); free(bzf); return NULL; };
999
1000 bzf->strm.avail_in = 0;
1001 bzf->initialisedOk = True;
1002 return bzf;
1003}
1004
1005
1006
1007/*---------------------------------------------------*/
1008void BZ_API(BZ2_bzWrite)
1009 ( int* bzerror,
1010 BZFILE* b,
1011 void* buf,
1012 int len )
1013{
1014 Int32 n, n2, ret;
1015 bzFile* bzf = (bzFile*)b;
1016
1017 BZ_SETERR(BZ_OK);
1018 if (bzf == NULL || buf == NULL || len < 0)
1019 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1020 if (!(bzf->writing))
1021 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1022 if (ferror(bzf->handle))
1023 { BZ_SETERR(BZ_IO_ERROR); return; };
1024
1025 if (len == 0)
1026 { BZ_SETERR(BZ_OK); return; };
1027
1028 bzf->strm.avail_in = len;
1029 bzf->strm.next_in = buf;
1030
1031 while (True) {
1032 bzf->strm.avail_out = BZ_MAX_UNUSED;
1033 bzf->strm.next_out = bzf->buf;
1034 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
1035 if (ret != BZ_RUN_OK)
1036 { BZ_SETERR(ret); return; };
1037
1038 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1039 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1040 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1041 n, bzf->handle );
1042 if (n != n2 || ferror(bzf->handle))
1043 { BZ_SETERR(BZ_IO_ERROR); return; };
1044 }
1045
1046 if (bzf->strm.avail_in == 0)
1047 { BZ_SETERR(BZ_OK); return; };
1048 }
1049}
1050
1051
1052/*---------------------------------------------------*/
1053void BZ_API(BZ2_bzWriteClose)
1054 ( int* bzerror,
1055 BZFILE* b,
1056 int abandon,
1057 unsigned int* nbytes_in,
1058 unsigned int* nbytes_out )
1059{
1060 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1061 nbytes_in, NULL, nbytes_out, NULL );
1062}
1063
1064
1065void BZ_API(BZ2_bzWriteClose64)
1066 ( int* bzerror,
1067 BZFILE* b,
1068 int abandon,
1069 unsigned int* nbytes_in_lo32,
1070 unsigned int* nbytes_in_hi32,
1071 unsigned int* nbytes_out_lo32,
1072 unsigned int* nbytes_out_hi32 )
1073{
1074 Int32 n, n2, ret;
1075 bzFile* bzf = (bzFile*)b;
1076
1077 if (bzf == NULL)
1078 { BZ_SETERR(BZ_OK); return; };
1079 if (!(bzf->writing))
1080 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1081 if (ferror(bzf->handle))
1082 { BZ_SETERR(BZ_IO_ERROR); return; };
1083
1084 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1085 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1086 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1087 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1088
1089 if ((!abandon) && bzf->lastErr == BZ_OK) {
1090 while (True) {
1091 bzf->strm.avail_out = BZ_MAX_UNUSED;
1092 bzf->strm.next_out = bzf->buf;
1093 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1094 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1095 { BZ_SETERR(ret); return; };
1096
1097 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1098 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1099 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1100 n, bzf->handle );
1101 if (n != n2 || ferror(bzf->handle))
1102 { BZ_SETERR(BZ_IO_ERROR); return; };
1103 }
1104
1105 if (ret == BZ_STREAM_END) break;
1106 }
1107 }
1108
1109 if ( !abandon && !ferror ( bzf->handle ) ) {
1110 fflush ( bzf->handle );
1111 if (ferror(bzf->handle))
1112 { BZ_SETERR(BZ_IO_ERROR); return; };
1113 }
1114
1115 if (nbytes_in_lo32 != NULL)
1116 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1117 if (nbytes_in_hi32 != NULL)
1118 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1119 if (nbytes_out_lo32 != NULL)
1120 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1121 if (nbytes_out_hi32 != NULL)
1122 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1123
1124 BZ_SETERR(BZ_OK);
1125 BZ2_bzCompressEnd ( &(bzf->strm) );
1126 free ( bzf );
1127}
1128
1129
1130/*---------------------------------------------------*/
1131BZFILE* BZ_API(BZ2_bzReadOpen)
1132 ( int* bzerror,
1133 FILE* f,
1134 int verbosity,
1135 int small,
1136 void* unused,
1137 int nUnused )
1138{
1139 bzFile* bzf = NULL;
1140 int ret;
1141
1142 BZ_SETERR(BZ_OK);
1143
1144 if (f == NULL ||
1145 (small != 0 && small != 1) ||
1146 (verbosity < 0 || verbosity > 4) ||
1147 (unused == NULL && nUnused != 0) ||
1148 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1149 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1150
1151 if (ferror(f))
1152 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1153
1154 bzf = malloc ( sizeof(bzFile) );
1155 if (bzf == NULL)
1156 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1157
1158 BZ_SETERR(BZ_OK);
1159
1160 bzf->initialisedOk = False;
1161 bzf->handle = f;
1162 bzf->bufN = 0;
1163 bzf->writing = False;
1164 bzf->strm.bzalloc = NULL;
1165 bzf->strm.bzfree = NULL;
1166 bzf->strm.opaque = NULL;
1167
1168 while (nUnused > 0) {
1169 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1170 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1171 nUnused--;
1172 }
1173
1174 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1175 if (ret != BZ_OK)
1176 { BZ_SETERR(ret); free(bzf); return NULL; };
1177
1178 bzf->strm.avail_in = bzf->bufN;
1179 bzf->strm.next_in = bzf->buf;
1180
1181 bzf->initialisedOk = True;
1182 return bzf;
1183}
1184
1185
1186/*---------------------------------------------------*/
1187void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1188{
1189 bzFile* bzf = (bzFile*)b;
1190
1191 BZ_SETERR(BZ_OK);
1192 if (bzf == NULL)
1193 { BZ_SETERR(BZ_OK); return; };
1194
1195 if (bzf->writing)
1196 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1197
1198 if (bzf->initialisedOk)
1199 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1200 free ( bzf );
1201}
1202
1203
1204/*---------------------------------------------------*/
1205int BZ_API(BZ2_bzRead)
1206 ( int* bzerror,
1207 BZFILE* b,
1208 void* buf,
1209 int len )
1210{
1211 Int32 n, ret;
1212 bzFile* bzf = (bzFile*)b;
1213
1214 BZ_SETERR(BZ_OK);
1215
1216 if (bzf == NULL || buf == NULL || len < 0)
1217 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1218
1219 if (bzf->writing)
1220 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1221
1222 if (len == 0)
1223 { BZ_SETERR(BZ_OK); return 0; };
1224
1225 bzf->strm.avail_out = len;
1226 bzf->strm.next_out = buf;
1227
1228 while (True) {
1229
1230 if (ferror(bzf->handle))
1231 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1232
1233 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1234 n = fread ( bzf->buf, sizeof(UChar),
1235 BZ_MAX_UNUSED, bzf->handle );
1236 if (ferror(bzf->handle))
1237 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1238 bzf->bufN = n;
1239 bzf->strm.avail_in = bzf->bufN;
1240 bzf->strm.next_in = bzf->buf;
1241 }
1242
1243 ret = BZ2_bzDecompress ( &(bzf->strm) );
1244
1245 if (ret != BZ_OK && ret != BZ_STREAM_END)
1246 { BZ_SETERR(ret); return 0; };
1247
1248 if (ret == BZ_OK && myfeof(bzf->handle) &&
1249 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1250 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1251
1252 if (ret == BZ_STREAM_END)
1253 { BZ_SETERR(BZ_STREAM_END);
1254 return len - bzf->strm.avail_out; };
1255 if (bzf->strm.avail_out == 0)
1256 { BZ_SETERR(BZ_OK); return len; };
1257
1258 }
1259
1260 return 0; /*not reached*/
1261}
1262
1263
1264/*---------------------------------------------------*/
1265void BZ_API(BZ2_bzReadGetUnused)
1266 ( int* bzerror,
1267 BZFILE* b,
1268 void** unused,
1269 int* nUnused )
1270{
1271 bzFile* bzf = (bzFile*)b;
1272 if (bzf == NULL)
1273 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1274 if (bzf->lastErr != BZ_STREAM_END)
1275 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1276 if (unused == NULL || nUnused == NULL)
1277 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1278
1279 BZ_SETERR(BZ_OK);
1280 *nUnused = bzf->strm.avail_in;
1281 *unused = bzf->strm.next_in;
1282}
1283#endif
1284
1285
1286/*---------------------------------------------------*/
1287/*--- Misc convenience stuff ---*/
1288/*---------------------------------------------------*/
1289
1290/*---------------------------------------------------*/
1291int BZ_API(BZ2_bzBuffToBuffCompress)
1292 ( char* dest,
1293 unsigned int* destLen,
1294 char* source,
1295 unsigned int sourceLen,
1296 int blockSize100k,
1297 int verbosity,
1298 int workFactor )
1299{
1300 bz_stream strm;
1301 int ret;
1302
1303 if (dest == NULL || destLen == NULL ||
1304 source == NULL ||
1305 blockSize100k < 1 || blockSize100k > 9 ||
1306 verbosity < 0 || verbosity > 4 ||
1307 workFactor < 0 || workFactor > 250)
1308 return BZ_PARAM_ERROR;
1309
1310 if (workFactor == 0) workFactor = 30;
1311 strm.bzalloc = NULL;
1312 strm.bzfree = NULL;
1313 strm.opaque = NULL;
1314 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1315 verbosity, workFactor );
1316 if (ret != BZ_OK) return ret;
1317
1318 strm.next_in = source;
1319 strm.next_out = dest;
1320 strm.avail_in = sourceLen;
1321 strm.avail_out = *destLen;
1322
1323 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1324 if (ret == BZ_FINISH_OK) goto output_overflow;
1325 if (ret != BZ_STREAM_END) goto errhandler;
1326
1327 /* normal termination */
1328 *destLen -= strm.avail_out;
1329 BZ2_bzCompressEnd ( &strm );
1330 return BZ_OK;
1331
1332 output_overflow:
1333 BZ2_bzCompressEnd ( &strm );
1334 return BZ_OUTBUFF_FULL;
1335
1336 errhandler:
1337 BZ2_bzCompressEnd ( &strm );
1338 return ret;
1339}
1340
1341
1342/*---------------------------------------------------*/
1343int BZ_API(BZ2_bzBuffToBuffDecompress)
1344 ( char* dest,
1345 unsigned int* destLen,
1346 char* source,
1347 unsigned int sourceLen,
1348 int small,
1349 int verbosity )
1350{
1351 bz_stream strm;
1352 int ret;
1353
1354 if (dest == NULL || destLen == NULL ||
1355 source == NULL ||
1356 (small != 0 && small != 1) ||
1357 verbosity < 0 || verbosity > 4)
1358 return BZ_PARAM_ERROR;
1359
1360 strm.bzalloc = NULL;
1361 strm.bzfree = NULL;
1362 strm.opaque = NULL;
1363 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1364 if (ret != BZ_OK) return ret;
1365
1366 strm.next_in = source;
1367 strm.next_out = dest;
1368 strm.avail_in = sourceLen;
1369 strm.avail_out = *destLen;
1370
1371 ret = BZ2_bzDecompress ( &strm );
1372 if (ret == BZ_OK) goto output_overflow_or_eof;
1373 if (ret != BZ_STREAM_END) goto errhandler;
1374
1375 /* normal termination */
1376 *destLen -= strm.avail_out;
1377 BZ2_bzDecompressEnd ( &strm );
1378 return BZ_OK;
1379
1380 output_overflow_or_eof:
1381 if (strm.avail_out > 0) {
1382 BZ2_bzDecompressEnd ( &strm );
1383 return BZ_UNEXPECTED_EOF;
1384 } else {
1385 BZ2_bzDecompressEnd ( &strm );
1386 return BZ_OUTBUFF_FULL;
1387 };
1388
1389 errhandler:
1390 BZ2_bzDecompressEnd ( &strm );
1391 return ret;
1392}
1393
1394
1395/*---------------------------------------------------*/
1396/*--
1397 Code contributed by Yoshioka Tsuneo
1398 (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
1399 to support better zlib compatibility.
1400 This code is not _officially_ part of libbzip2 (yet);
1401 I haven't tested it, documented it, or considered the
1402 threading-safeness of it.
1403 If this code breaks, please contact both Yoshioka and me.
1404--*/
1405/*---------------------------------------------------*/
1406
1407/*---------------------------------------------------*/
1408/*--
1409 return version like "0.9.0c".
1410--*/
1411const char * BZ_API(BZ2_bzlibVersion)(void)
1412{
1413 return BZ_VERSION;
1414}
1415
1416
1417#ifndef BZ_NO_STDIO
1418/*---------------------------------------------------*/
1419
1420#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1421# include <fcntl.h>
1422# include <io.h>
1423# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1424#else
1425# define SET_BINARY_MODE(file)
1426#endif
1427static
1428BZFILE * bzopen_or_bzdopen
1429 ( const char *path, /* no use when bzdopen */
1430 int fd, /* no use when bzdopen */
1431 const char *mode,
1432 int open_mode) /* bzopen: 0, bzdopen:1 */
1433{
1434 int bzerr;
1435 char unused[BZ_MAX_UNUSED];
1436 int blockSize100k = 9;
1437 int writing = 0;
1438 char mode2[10] = "";
1439 FILE *fp = NULL;
1440 BZFILE *bzfp = NULL;
1441 int verbosity = 0;
1442 int workFactor = 30;
1443 int smallMode = 0;
1444 int nUnused = 0;
1445
1446 if (mode == NULL) return NULL;
1447 while (*mode) {
1448 switch (*mode) {
1449 case 'r':
1450 writing = 0; break;
1451 case 'w':
1452 writing = 1; break;
1453 case 's':
1454 smallMode = 1; break;
1455 default:
1456 if (isdigit((int)(*mode))) {
1457 blockSize100k = *mode-BZ_HDR_0;
1458 }
1459 }
1460 mode++;
1461 }
1462 strcat(mode2, writing ? "w" : "r" );
1463 strcat(mode2,"b"); /* binary mode */
1464
1465 if (open_mode==0) {
1466 if (path==NULL || strcmp(path,"")==0) {
1467 fp = (writing ? stdout : stdin);
1468 SET_BINARY_MODE(fp);
1469 } else {
1470 fp = fopen(path,mode2);
1471 }
1472 } else {
1473#ifdef BZ_STRICT_ANSI
1474 fp = NULL;
1475#else
1476 fp = fdopen(fd,mode2);
1477#endif
1478 }
1479 if (fp == NULL) return NULL;
1480
1481 if (writing) {
1482 /* Guard against total chaos and anarchy -- JRS */
1483 if (blockSize100k < 1) blockSize100k = 1;
1484 if (blockSize100k > 9) blockSize100k = 9;
1485 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1486 verbosity,workFactor);
1487 } else {
1488 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1489 unused,nUnused);
1490 }
1491 if (bzfp == NULL) {
1492 if (fp != stdin && fp != stdout) fclose(fp);
1493 return NULL;
1494 }
1495 return bzfp;
1496}
1497
1498
1499/*---------------------------------------------------*/
1500/*--
1501 open file for read or write.
1502 ex) bzopen("file","w9")
1503 case path="" or NULL => use stdin or stdout.
1504--*/
1505BZFILE * BZ_API(BZ2_bzopen)
1506 ( const char *path,
1507 const char *mode )
1508{
1509 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1510}
1511
1512
1513/*---------------------------------------------------*/
1514BZFILE * BZ_API(BZ2_bzdopen)
1515 ( int fd,
1516 const char *mode )
1517{
1518 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1519}
1520
1521
1522/*---------------------------------------------------*/
1523int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1524{
1525 int bzerr, nread;
1526 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1527 nread = BZ2_bzRead(&bzerr,b,buf,len);
1528 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1529 return nread;
1530 } else {
1531 return -1;
1532 }
1533}
1534
1535
1536/*---------------------------------------------------*/
1537int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1538{
1539 int bzerr;
1540
1541 BZ2_bzWrite(&bzerr,b,buf,len);
1542 if(bzerr == BZ_OK){
1543 return len;
1544 }else{
1545 return -1;
1546 }
1547}
1548
1549
1550/*---------------------------------------------------*/
1551int BZ_API(BZ2_bzflush) (BZFILE *b)
1552{
1553 /* do nothing now... */
1554 return 0;
1555}
1556
1557
1558/*---------------------------------------------------*/
1559void BZ_API(BZ2_bzclose) (BZFILE* b)
1560{
1561 int bzerr;
1562 FILE *fp = ((bzFile *)b)->handle;
1563
1564 if (b==NULL) {return;}
1565 if(((bzFile*)b)->writing){
1566 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1567 if(bzerr != BZ_OK){
1568 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1569 }
1570 }else{
1571 BZ2_bzReadClose(&bzerr,b);
1572 }
1573 if(fp!=stdin && fp!=stdout){
1574 fclose(fp);
1575 }
1576}
1577
1578
1579/*---------------------------------------------------*/
1580/*--
1581 return last error code
1582--*/
1583static char *bzerrorstrings[] = {
1584 "OK"
1585 ,"SEQUENCE_ERROR"
1586 ,"PARAM_ERROR"
1587 ,"MEM_ERROR"
1588 ,"DATA_ERROR"
1589 ,"DATA_ERROR_MAGIC"
1590 ,"IO_ERROR"
1591 ,"UNEXPECTED_EOF"
1592 ,"OUTBUFF_FULL"
1593 ,"CONFIG_ERROR"
1594 ,"???" /* for future */
1595 ,"???" /* for future */
1596 ,"???" /* for future */
1597 ,"???" /* for future */
1598 ,"???" /* for future */
1599 ,"???" /* for future */
1600};
1601
1602
1603const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1604{
1605 int err = ((bzFile *)b)->lastErr;
1606
1607 if(err>0) err = 0;
1608 *errnum = err;
1609 return bzerrorstrings[err*-1];
1610}
1611#endif
1612
1613
1614/*-------------------------------------------------------------*/
1615/*--- end bzlib.c ---*/
1616/*-------------------------------------------------------------*/