5 * This file is a modified version of bzlib.c from the bzip2-1.0.2
6 * distribution which can be found at http://sources.redhat.com/bzip2/
9 /*-------------------------------------------------------------*/
10 /*--- Library top-level functions. ---*/
12 /*-------------------------------------------------------------*/
15 This file is a part of bzip2 and/or libbzip2, a program and
16 library for lossless, block-sorting data compression.
18 Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
20 Redistribution and use in source and binary forms, with or without
21 modification, are permitted provided that the following conditions
24 1. Redistributions of source code must retain the above copyright
25 notice, this list of conditions and the following disclaimer.
27 2. The origin of this software must not be misrepresented; you must
28 not claim that you wrote the original software. If you use this
29 software in a product, an acknowledgment in the product
30 documentation would be appreciated but is not required.
32 3. Altered source versions must be plainly marked as such, and must
33 not be misrepresented as being the original software.
35 4. The name of the author may not be used to endorse or promote
36 products derived from this software without specific prior written
39 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
40 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
41 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
43 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
44 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
45 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
46 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
47 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
48 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
49 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 Julian Seward, Cambridge, UK.
53 bzip2/libbzip2 version 1.0 of 21 March 2000
55 This program is based on (at least) the work of:
65 For more information on these sources, see the manual.
71 0.9.0 -- original version.
73 0.9.0a/b -- no changes in this file.
76 * made zero-length BZ_FLUSH work correctly in bzCompress().
77 * fixed bzWrite/bzRead to ignore zero-length requests.
78 * fixed bzread to correctly handle read requests after EOF.
79 * wrong parameter order in call to bzDecompressInit in
80 bzBuffToBuffDecompress. Fixed.
83 #include "bzlib_private.h"
85 /*---------------------------------------------------*/
86 /*--- Compression stuff ---*/
87 /*---------------------------------------------------*/
90 /*---------------------------------------------------*/
92 void BZ2_bz__AssertH__fail ( int errcode )
95 "\n\nbzip2/libbzip2: internal error number %d.\n"
96 "This is a bug in bzip2/libbzip2, %s.\n"
97 "Please report it to me at: jseward@acm.org. If this happened\n"
98 "when you were using some program which uses libbzip2 as a\n"
99 "component, you should also report this bug to the author(s)\n"
100 "of that program. Please make an effort to report this bug;\n"
101 "timely and accurate bug reports eventually lead to higher\n"
102 "quality software. Thanks. Julian Seward, 30 December 2001.\n\n",
107 if (errcode == 1007) {
109 "\n*** A special note about internal error number 1007 ***\n"
111 "Experience suggests that a common cause of i.e. 1007\n"
112 "is unreliable memory or other hardware. The 1007 assertion\n"
113 "just happens to cross-check the results of huge numbers of\n"
114 "memory reads/writes, and so acts (unintendedly) as a stress\n"
115 "test of your memory system.\n"
117 "I suggest the following: try compressing the file again,\n"
118 "possibly monitoring progress in detail with the -vv flag.\n"
120 "* If the error cannot be reproduced, and/or happens at different\n"
121 " points in compression, you may have a flaky memory system.\n"
122 " Try a memory-test program. I have used Memtest86\n"
123 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
124 " Memtest86 tests memory much more thorougly than your BIOSs\n"
125 " power-on test, and may find failures that the BIOS doesn't.\n"
127 "* If the error can be repeatably reproduced, this is a bug in\n"
128 " bzip2, and I would very much like to hear about it. Please\n"
129 " let me know, and, ideally, save a copy of the file causing the\n"
130 " problem -- without which I will be unable to investigate it.\n"
140 /*---------------------------------------------------*/
142 int bz_config_ok ( void )
144 if (sizeof(int) != 4) return 0;
145 if (sizeof(short) != 2) return 0;
146 if (sizeof(char) != 1) return 0;
151 /*---------------------------------------------------*/
153 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
155 void* v = malloc ( items * size );
160 void default_bzfree ( void* opaque, void* addr )
162 if (addr != NULL) free ( addr );
165 #ifndef BZ_NO_COMPRESS
166 /*---------------------------------------------------*/
168 void prepare_new_block ( EState* s )
173 s->state_out_pos = 0;
174 BZ_INITIALISE_CRC ( s->blockCRC );
175 for (i = 0; i < 256; i++) s->inUse[i] = False;
180 /*---------------------------------------------------*/
182 void init_RL ( EState* s )
184 s->state_in_ch = 256;
190 Bool isempty_RL ( EState* s )
192 if (s->state_in_ch < 256 && s->state_in_len > 0)
197 /*---------------------------------------------------*/
198 int BZ_API(BZ2_bzCompressInit)
207 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
210 blockSize100k < 1 || blockSize100k > 9 ||
211 workFactor < 0 || workFactor > 250)
212 return BZ_PARAM_ERROR;
214 if (workFactor == 0) workFactor = 30;
215 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
216 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
218 s = BZALLOC( sizeof(EState) );
219 if (s == NULL) return BZ_MEM_ERROR;
226 n = 100000 * blockSize100k;
227 s->arr1 = BZALLOC( n * sizeof(UInt32) );
228 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
229 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
231 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
232 if (s->arr1 != NULL) BZFREE(s->arr1);
233 if (s->arr2 != NULL) BZFREE(s->arr2);
234 if (s->ftab != NULL) BZFREE(s->ftab);
235 if (s != NULL) BZFREE(s);
240 s->state = BZ_S_INPUT;
241 s->mode = BZ_M_RUNNING;
243 s->blockSize100k = blockSize100k;
244 s->nblockMAX = 100000 * blockSize100k - 19;
245 s->verbosity = verbosity;
246 s->workFactor = workFactor;
248 s->block = (UChar*)s->arr2;
249 s->mtfv = (UInt16*)s->arr1;
251 s->ptr = (UInt32*)s->arr1;
254 strm->total_in_lo32 = 0;
255 strm->total_in_hi32 = 0;
256 strm->total_out_lo32 = 0;
257 strm->total_out_hi32 = 0;
259 prepare_new_block ( s );
264 /*---------------------------------------------------*/
266 void add_pair_to_block ( EState* s )
269 UChar ch = (UChar)(s->state_in_ch);
270 for (i = 0; i < s->state_in_len; i++) {
271 BZ_UPDATE_CRC( s->blockCRC, ch );
273 s->inUse[s->state_in_ch] = True;
274 switch (s->state_in_len) {
276 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++;
283 s->block[s->nblock] = (UChar)ch; s->nblock++;
284 s->block[s->nblock] = (UChar)ch; s->nblock++;
285 s->block[s->nblock] = (UChar)ch; s->nblock++;
288 s->inUse[s->state_in_len-4] = True;
289 s->block[s->nblock] = (UChar)ch; s->nblock++;
290 s->block[s->nblock] = (UChar)ch; s->nblock++;
291 s->block[s->nblock] = (UChar)ch; s->nblock++;
292 s->block[s->nblock] = (UChar)ch; s->nblock++;
293 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
300 /*---------------------------------------------------*/
302 void flush_RL ( EState* s )
304 if (s->state_in_ch < 256) add_pair_to_block ( s );
309 /*---------------------------------------------------*/
310 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
312 UInt32 zchh = (UInt32)(zchh0); \
313 /*-- fast track the common case --*/ \
314 if (zchh != zs->state_in_ch && \
315 zs->state_in_len == 1) { \
316 UChar ch = (UChar)(zs->state_in_ch); \
317 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
318 zs->inUse[zs->state_in_ch] = True; \
319 zs->block[zs->nblock] = (UChar)ch; \
321 zs->state_in_ch = zchh; \
324 /*-- general, uncommon cases --*/ \
325 if (zchh != zs->state_in_ch || \
326 zs->state_in_len == 255) { \
327 if (zs->state_in_ch < 256) \
328 add_pair_to_block ( zs ); \
329 zs->state_in_ch = zchh; \
330 zs->state_in_len = 1; \
332 zs->state_in_len++; \
337 /*---------------------------------------------------*/
339 Bool copy_input_until_stop ( EState* s )
341 Bool progress_in = False;
343 if (s->mode == BZ_M_RUNNING) {
345 /*-- fast track the common case --*/
347 /*-- block full? --*/
348 if (s->nblock >= s->nblockMAX) break;
350 if (s->strm->avail_in == 0) break;
352 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
355 s->strm->total_in_lo32++;
356 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
361 /*-- general, uncommon case --*/
363 /*-- block full? --*/
364 if (s->nblock >= s->nblockMAX) break;
366 if (s->strm->avail_in == 0) break;
367 /*-- flush/finish end? --*/
368 if (s->avail_in_expect == 0) break;
370 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
373 s->strm->total_in_lo32++;
374 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
375 s->avail_in_expect--;
382 /*---------------------------------------------------*/
384 Bool copy_output_until_stop ( EState* s )
386 Bool progress_out = False;
390 /*-- no output space? --*/
391 if (s->strm->avail_out == 0) break;
393 /*-- block done? --*/
394 if (s->state_out_pos >= s->numZ) break;
397 *(s->strm->next_out) = s->zbits[s->state_out_pos];
399 s->strm->avail_out--;
401 s->strm->total_out_lo32++;
402 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
409 /*---------------------------------------------------*/
411 Bool handle_compress ( bz_stream* strm )
413 Bool progress_in = False;
414 Bool progress_out = False;
415 EState* s = strm->state;
419 if (s->state == BZ_S_OUTPUT) {
420 progress_out |= copy_output_until_stop ( s );
421 if (s->state_out_pos < s->numZ) break;
422 if (s->mode == BZ_M_FINISHING &&
423 s->avail_in_expect == 0 &&
424 isempty_RL(s)) break;
425 prepare_new_block ( s );
426 s->state = BZ_S_INPUT;
427 if (s->mode == BZ_M_FLUSHING &&
428 s->avail_in_expect == 0 &&
429 isempty_RL(s)) break;
432 if (s->state == BZ_S_INPUT) {
433 progress_in |= copy_input_until_stop ( s );
434 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
436 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
437 s->state = BZ_S_OUTPUT;
440 if (s->nblock >= s->nblockMAX) {
441 BZ2_compressBlock ( s, False );
442 s->state = BZ_S_OUTPUT;
445 if (s->strm->avail_in == 0) {
452 return progress_in || progress_out;
456 /*---------------------------------------------------*/
457 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
461 if (strm == NULL) return BZ_PARAM_ERROR;
463 if (s == NULL) return BZ_PARAM_ERROR;
464 if (s->strm != strm) return BZ_PARAM_ERROR;
470 return BZ_SEQUENCE_ERROR;
473 if (action == BZ_RUN) {
474 progress = handle_compress ( strm );
475 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
478 if (action == BZ_FLUSH) {
479 s->avail_in_expect = strm->avail_in;
480 s->mode = BZ_M_FLUSHING;
484 if (action == BZ_FINISH) {
485 s->avail_in_expect = strm->avail_in;
486 s->mode = BZ_M_FINISHING;
490 return BZ_PARAM_ERROR;
493 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
494 if (s->avail_in_expect != s->strm->avail_in)
495 return BZ_SEQUENCE_ERROR;
496 progress = handle_compress ( strm );
497 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
498 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
499 s->mode = BZ_M_RUNNING;
503 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
504 if (s->avail_in_expect != s->strm->avail_in)
505 return BZ_SEQUENCE_ERROR;
506 progress = handle_compress ( strm );
507 if (!progress) return BZ_SEQUENCE_ERROR;
508 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
509 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
511 return BZ_STREAM_END;
513 return BZ_OK; /*--not reached--*/
517 /*---------------------------------------------------*/
518 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
521 if (strm == NULL) return BZ_PARAM_ERROR;
523 if (s == NULL) return BZ_PARAM_ERROR;
524 if (s->strm != strm) return BZ_PARAM_ERROR;
526 if (s->arr1 != NULL) BZFREE(s->arr1);
527 if (s->arr2 != NULL) BZFREE(s->arr2);
528 if (s->ftab != NULL) BZFREE(s->ftab);
535 #endif /* BZ_NO_COMPRESS */
537 /*---------------------------------------------------*/
538 /*--- Decompression stuff ---*/
539 /*---------------------------------------------------*/
541 /*---------------------------------------------------*/
542 int BZ_API(BZ2_bzDecompressInit)
549 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
551 if (strm == NULL) return BZ_PARAM_ERROR;
552 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
553 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
555 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
556 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
558 s = BZALLOC( sizeof(DState) );
559 if (s == NULL) return BZ_MEM_ERROR;
562 s->state = BZ_X_MAGIC_1;
565 s->calculatedCombinedCRC = 0;
566 strm->total_in_lo32 = 0;
567 strm->total_in_hi32 = 0;
568 strm->total_out_lo32 = 0;
569 strm->total_out_hi32 = 0;
570 s->smallDecompress = (Bool)small;
575 s->verbosity = verbosity;
581 /*---------------------------------------------------*/
583 void unRLE_obuf_to_output_FAST ( DState* s )
587 if (s->blockRandomised) {
590 /* try to finish existing run */
592 if (s->strm->avail_out == 0) return;
593 if (s->state_out_len == 0) break;
594 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
595 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
598 s->strm->avail_out--;
599 s->strm->total_out_lo32++;
600 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
603 /* can a new run be started? */
604 if (s->nblock_used == s->save_nblock+1) return;
607 s->state_out_len = 1;
608 s->state_out_ch = s->k0;
609 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
610 k1 ^= BZ_RAND_MASK; s->nblock_used++;
611 if (s->nblock_used == s->save_nblock+1) continue;
612 if (k1 != s->k0) { s->k0 = k1; continue; };
614 s->state_out_len = 2;
615 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
616 k1 ^= BZ_RAND_MASK; s->nblock_used++;
617 if (s->nblock_used == s->save_nblock+1) continue;
618 if (k1 != s->k0) { s->k0 = k1; continue; };
620 s->state_out_len = 3;
621 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
622 k1 ^= BZ_RAND_MASK; s->nblock_used++;
623 if (s->nblock_used == s->save_nblock+1) continue;
624 if (k1 != s->k0) { s->k0 = k1; continue; };
626 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
627 k1 ^= BZ_RAND_MASK; s->nblock_used++;
628 s->state_out_len = ((Int32)k1) + 4;
629 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
630 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
636 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
637 UChar c_state_out_ch = s->state_out_ch;
638 Int32 c_state_out_len = s->state_out_len;
639 Int32 c_nblock_used = s->nblock_used;
641 UInt32* c_tt = s->tt;
642 UInt32 c_tPos = s->tPos;
643 char* cs_next_out = s->strm->next_out;
644 unsigned int cs_avail_out = s->strm->avail_out;
647 UInt32 avail_out_INIT = cs_avail_out;
648 Int32 s_save_nblockPP = s->save_nblock+1;
649 unsigned int total_out_lo32_old;
653 /* try to finish existing run */
654 if (c_state_out_len > 0) {
656 if (cs_avail_out == 0) goto return_notr;
657 if (c_state_out_len == 1) break;
658 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
659 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
664 s_state_out_len_eq_one:
666 if (cs_avail_out == 0) {
667 c_state_out_len = 1; goto return_notr;
669 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
670 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
675 /* can a new run be started? */
676 if (c_nblock_used == s_save_nblockPP) {
677 c_state_out_len = 0; goto return_notr;
679 c_state_out_ch = c_k0;
680 BZ_GET_FAST_C(k1); c_nblock_used++;
682 c_k0 = k1; goto s_state_out_len_eq_one;
684 if (c_nblock_used == s_save_nblockPP)
685 goto s_state_out_len_eq_one;
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; };
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; };
697 BZ_GET_FAST_C(k1); c_nblock_used++;
698 c_state_out_len = ((Int32)k1) + 4;
699 BZ_GET_FAST_C(c_k0); c_nblock_used++;
703 total_out_lo32_old = s->strm->total_out_lo32;
704 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
705 if (s->strm->total_out_lo32 < total_out_lo32_old)
706 s->strm->total_out_hi32++;
709 s->calculatedBlockCRC = c_calculatedBlockCRC;
710 s->state_out_ch = c_state_out_ch;
711 s->state_out_len = c_state_out_len;
712 s->nblock_used = c_nblock_used;
716 s->strm->next_out = cs_next_out;
717 s->strm->avail_out = cs_avail_out;
723 /*---------------------------------------------------*/
724 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
730 mid = (nb + na) >> 1;
731 if (indx >= cftab[mid]) nb = mid; else na = mid;
733 while (na - nb != 1);
738 /*---------------------------------------------------*/
740 void unRLE_obuf_to_output_SMALL ( DState* s )
744 if (s->blockRandomised) {
747 /* try to finish existing run */
749 if (s->strm->avail_out == 0) return;
750 if (s->state_out_len == 0) break;
751 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
752 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
755 s->strm->avail_out--;
756 s->strm->total_out_lo32++;
757 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
760 /* can a new run be started? */
761 if (s->nblock_used == s->save_nblock+1) return;
764 s->state_out_len = 1;
765 s->state_out_ch = s->k0;
766 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
767 k1 ^= BZ_RAND_MASK; s->nblock_used++;
768 if (s->nblock_used == s->save_nblock+1) continue;
769 if (k1 != s->k0) { s->k0 = k1; continue; };
771 s->state_out_len = 2;
772 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
773 k1 ^= BZ_RAND_MASK; s->nblock_used++;
774 if (s->nblock_used == s->save_nblock+1) continue;
775 if (k1 != s->k0) { s->k0 = k1; continue; };
777 s->state_out_len = 3;
778 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
779 k1 ^= BZ_RAND_MASK; s->nblock_used++;
780 if (s->nblock_used == s->save_nblock+1) continue;
781 if (k1 != s->k0) { s->k0 = k1; continue; };
783 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
784 k1 ^= BZ_RAND_MASK; s->nblock_used++;
785 s->state_out_len = ((Int32)k1) + 4;
786 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
787 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
793 /* try to finish existing run */
795 if (s->strm->avail_out == 0) return;
796 if (s->state_out_len == 0) break;
797 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
798 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
801 s->strm->avail_out--;
802 s->strm->total_out_lo32++;
803 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
806 /* can a new run be started? */
807 if (s->nblock_used == s->save_nblock+1) return;
809 s->state_out_len = 1;
810 s->state_out_ch = s->k0;
811 BZ_GET_SMALL(k1); s->nblock_used++;
812 if (s->nblock_used == s->save_nblock+1) continue;
813 if (k1 != s->k0) { s->k0 = k1; continue; };
815 s->state_out_len = 2;
816 BZ_GET_SMALL(k1); s->nblock_used++;
817 if (s->nblock_used == s->save_nblock+1) continue;
818 if (k1 != s->k0) { s->k0 = k1; continue; };
820 s->state_out_len = 3;
821 BZ_GET_SMALL(k1); s->nblock_used++;
822 if (s->nblock_used == s->save_nblock+1) continue;
823 if (k1 != s->k0) { s->k0 = k1; continue; };
825 BZ_GET_SMALL(k1); s->nblock_used++;
826 s->state_out_len = ((Int32)k1) + 4;
827 BZ_GET_SMALL(s->k0); s->nblock_used++;
834 /*---------------------------------------------------*/
835 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
838 if (strm == NULL) return BZ_PARAM_ERROR;
840 if (s == NULL) return BZ_PARAM_ERROR;
841 if (s->strm != strm) return BZ_PARAM_ERROR;
844 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
845 if (s->state == BZ_X_OUTPUT) {
846 if (s->smallDecompress)
847 unRLE_obuf_to_output_SMALL ( s ); else
848 unRLE_obuf_to_output_FAST ( s );
849 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
850 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
851 if (s->verbosity >= 3)
852 VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC,
853 s->calculatedBlockCRC );
854 if (s->verbosity >= 2) VPrintf0 ( "]" );
855 if (s->calculatedBlockCRC != s->storedBlockCRC)
856 return BZ_DATA_ERROR;
857 s->calculatedCombinedCRC
858 = (s->calculatedCombinedCRC << 1) |
859 (s->calculatedCombinedCRC >> 31);
860 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
861 s->state = BZ_X_BLKHDR_1;
866 if (s->state >= BZ_X_MAGIC_1) {
867 Int32 r = BZ2_decompress ( s );
868 if (r == BZ_STREAM_END) {
869 if (s->verbosity >= 3)
870 VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x",
871 s->storedCombinedCRC, s->calculatedCombinedCRC );
872 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
873 return BZ_DATA_ERROR;
876 if (s->state != BZ_X_OUTPUT) return r;
882 return 0; /*NOTREACHED*/
886 /*---------------------------------------------------*/
887 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
890 if (strm == NULL) return BZ_PARAM_ERROR;
892 if (s == NULL) return BZ_PARAM_ERROR;
893 if (s->strm != strm) return BZ_PARAM_ERROR;
895 if (s->tt != NULL) BZFREE(s->tt);
896 if (s->ll16 != NULL) BZFREE(s->ll16);
897 if (s->ll4 != NULL) BZFREE(s->ll4);
907 /*---------------------------------------------------*/
908 /*--- File I/O stuff ---*/
909 /*---------------------------------------------------*/
911 #define BZ_SETERR(eee) \
913 if (bzerror != NULL) *bzerror = eee; \
914 if (bzf != NULL) bzf->lastErr = eee; \
920 Char buf[BZ_MAX_UNUSED];
930 /*---------------------------------------------*/
931 static Bool myfeof ( FILE* f )
933 Int32 c = fgetc ( f );
934 if (c == EOF) return True;
940 /*---------------------------------------------------*/
941 BZFILE* BZ_API(BZ2_bzWriteOpen)
954 (blockSize100k < 1 || blockSize100k > 9) ||
955 (workFactor < 0 || workFactor > 250) ||
956 (verbosity < 0 || verbosity > 4))
957 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
960 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
962 bzf = malloc ( sizeof(bzFile) );
964 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
967 bzf->initialisedOk = False;
971 bzf->strm.bzalloc = NULL;
972 bzf->strm.bzfree = NULL;
973 bzf->strm.opaque = NULL;
975 if (workFactor == 0) workFactor = 30;
976 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
977 verbosity, workFactor );
979 { BZ_SETERR(ret); free(bzf); return NULL; };
981 bzf->strm.avail_in = 0;
982 bzf->initialisedOk = True;
987 /*---------------------------------------------------*/
988 void BZ_API(BZ2_bzWrite)
995 bzFile* bzf = (bzFile*)b;
998 if (bzf == NULL || buf == NULL || len < 0)
999 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1000 if (!(bzf->writing))
1001 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1002 if (ferror(bzf->handle))
1003 { BZ_SETERR(BZ_IO_ERROR); return; };
1006 { BZ_SETERR(BZ_OK); return; };
1008 bzf->strm.avail_in = len;
1009 bzf->strm.next_in = buf;
1012 bzf->strm.avail_out = BZ_MAX_UNUSED;
1013 bzf->strm.next_out = bzf->buf;
1014 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
1015 if (ret != BZ_RUN_OK)
1016 { BZ_SETERR(ret); return; };
1018 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1019 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1020 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1022 if (n != n2 || ferror(bzf->handle))
1023 { BZ_SETERR(BZ_IO_ERROR); return; };
1026 if (bzf->strm.avail_in == 0)
1027 { BZ_SETERR(BZ_OK); return; };
1032 /*---------------------------------------------------*/
1033 void BZ_API(BZ2_bzWriteClose)
1037 unsigned int* nbytes_in,
1038 unsigned int* nbytes_out )
1040 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1041 nbytes_in, NULL, nbytes_out, NULL );
1045 void BZ_API(BZ2_bzWriteClose64)
1049 unsigned int* nbytes_in_lo32,
1050 unsigned int* nbytes_in_hi32,
1051 unsigned int* nbytes_out_lo32,
1052 unsigned int* nbytes_out_hi32 )
1055 bzFile* bzf = (bzFile*)b;
1058 { BZ_SETERR(BZ_OK); return; };
1059 if (!(bzf->writing))
1060 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1061 if (ferror(bzf->handle))
1062 { BZ_SETERR(BZ_IO_ERROR); return; };
1064 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1065 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1066 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1067 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1069 if ((!abandon) && bzf->lastErr == BZ_OK) {
1071 bzf->strm.avail_out = BZ_MAX_UNUSED;
1072 bzf->strm.next_out = bzf->buf;
1073 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1074 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1075 { BZ_SETERR(ret); return; };
1077 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1078 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1079 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1081 if (n != n2 || ferror(bzf->handle))
1082 { BZ_SETERR(BZ_IO_ERROR); return; };
1085 if (ret == BZ_STREAM_END) break;
1089 if ( !abandon && !ferror ( bzf->handle ) ) {
1090 fflush ( bzf->handle );
1091 if (ferror(bzf->handle))
1092 { BZ_SETERR(BZ_IO_ERROR); return; };
1095 if (nbytes_in_lo32 != NULL)
1096 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1097 if (nbytes_in_hi32 != NULL)
1098 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1099 if (nbytes_out_lo32 != NULL)
1100 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1101 if (nbytes_out_hi32 != NULL)
1102 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1105 BZ2_bzCompressEnd ( &(bzf->strm) );
1110 /*---------------------------------------------------*/
1111 BZFILE* BZ_API(BZ2_bzReadOpen)
1125 (small != 0 && small != 1) ||
1126 (verbosity < 0 || verbosity > 4) ||
1127 (unused == NULL && nUnused != 0) ||
1128 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1129 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1132 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1134 bzf = malloc ( sizeof(bzFile) );
1136 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1140 bzf->initialisedOk = False;
1143 bzf->writing = False;
1144 bzf->strm.bzalloc = NULL;
1145 bzf->strm.bzfree = NULL;
1146 bzf->strm.opaque = NULL;
1148 while (nUnused > 0) {
1149 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1150 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1154 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1156 { BZ_SETERR(ret); free(bzf); return NULL; };
1158 bzf->strm.avail_in = bzf->bufN;
1159 bzf->strm.next_in = bzf->buf;
1161 bzf->initialisedOk = True;
1166 /*---------------------------------------------------*/
1167 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1169 bzFile* bzf = (bzFile*)b;
1173 { BZ_SETERR(BZ_OK); return; };
1176 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1178 if (bzf->initialisedOk)
1179 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1184 /*---------------------------------------------------*/
1185 int BZ_API(BZ2_bzRead)
1192 bzFile* bzf = (bzFile*)b;
1196 if (bzf == NULL || buf == NULL || len < 0)
1197 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1200 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1203 { BZ_SETERR(BZ_OK); return 0; };
1205 bzf->strm.avail_out = len;
1206 bzf->strm.next_out = buf;
1210 if (ferror(bzf->handle))
1211 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1213 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1214 n = fread ( bzf->buf, sizeof(UChar),
1215 BZ_MAX_UNUSED, bzf->handle );
1216 if (ferror(bzf->handle))
1217 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1219 bzf->strm.avail_in = bzf->bufN;
1220 bzf->strm.next_in = bzf->buf;
1223 ret = BZ2_bzDecompress ( &(bzf->strm) );
1225 if (ret != BZ_OK && ret != BZ_STREAM_END)
1226 { BZ_SETERR(ret); return 0; };
1228 if (ret == BZ_OK && myfeof(bzf->handle) &&
1229 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1230 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1232 if (ret == BZ_STREAM_END)
1233 { BZ_SETERR(BZ_STREAM_END);
1234 return len - bzf->strm.avail_out; };
1235 if (bzf->strm.avail_out == 0)
1236 { BZ_SETERR(BZ_OK); return len; };
1240 return 0; /*not reached*/
1244 /*---------------------------------------------------*/
1245 void BZ_API(BZ2_bzReadGetUnused)
1251 bzFile* bzf = (bzFile*)b;
1253 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1254 if (bzf->lastErr != BZ_STREAM_END)
1255 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1256 if (unused == NULL || nUnused == NULL)
1257 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1260 *nUnused = bzf->strm.avail_in;
1261 *unused = bzf->strm.next_in;
1266 /*---------------------------------------------------*/
1267 /*--- Misc convenience stuff ---*/
1268 /*---------------------------------------------------*/
1269 #ifndef BZ_NO_COMPRESS
1270 /*---------------------------------------------------*/
1271 int BZ_API(BZ2_bzBuffToBuffCompress)
1273 unsigned int* destLen,
1275 unsigned int sourceLen,
1283 if (dest == NULL || destLen == NULL ||
1285 blockSize100k < 1 || blockSize100k > 9 ||
1286 verbosity < 0 || verbosity > 4 ||
1287 workFactor < 0 || workFactor > 250)
1288 return BZ_PARAM_ERROR;
1290 if (workFactor == 0) workFactor = 30;
1291 strm.bzalloc = NULL;
1294 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1295 verbosity, workFactor );
1296 if (ret != BZ_OK) return ret;
1298 strm.next_in = source;
1299 strm.next_out = dest;
1300 strm.avail_in = sourceLen;
1301 strm.avail_out = *destLen;
1303 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1304 if (ret == BZ_FINISH_OK) goto output_overflow;
1305 if (ret != BZ_STREAM_END) goto errhandler;
1307 /* normal termination */
1308 *destLen -= strm.avail_out;
1309 BZ2_bzCompressEnd ( &strm );
1313 BZ2_bzCompressEnd ( &strm );
1314 return BZ_OUTBUFF_FULL;
1317 BZ2_bzCompressEnd ( &strm );
1320 #endif /* BZ_NO_COMPRESS */
1322 /*---------------------------------------------------*/
1323 int BZ_API(BZ2_bzBuffToBuffDecompress)
1325 unsigned int* destLen,
1327 unsigned int sourceLen,
1334 if (destLen == NULL || source == NULL)
1335 return BZ_PARAM_ERROR;
1337 strm.bzalloc = NULL;
1340 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1341 if (ret != BZ_OK) return ret;
1343 strm.next_in = source;
1344 strm.next_out = dest;
1345 strm.avail_in = sourceLen;
1346 strm.avail_out = *destLen;
1348 ret = BZ2_bzDecompress ( &strm );
1349 if (ret == BZ_OK) goto output_overflow_or_eof;
1350 if (ret != BZ_STREAM_END) goto errhandler;
1352 /* normal termination */
1353 *destLen -= strm.avail_out;
1354 BZ2_bzDecompressEnd ( &strm );
1357 output_overflow_or_eof:
1358 if (strm.avail_out > 0) {
1359 BZ2_bzDecompressEnd ( &strm );
1360 return BZ_UNEXPECTED_EOF;
1362 BZ2_bzDecompressEnd ( &strm );
1363 return BZ_OUTBUFF_FULL;
1367 BZ2_bzDecompressEnd ( &strm );
1372 /*---------------------------------------------------*/
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.
1382 /*---------------------------------------------------*/
1384 /*---------------------------------------------------*/
1386 return version like "0.9.0c".
1388 const char * BZ_API(BZ2_bzlibVersion)(void)
1395 /*---------------------------------------------------*/
1397 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1400 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1402 # define SET_BINARY_MODE(file)
1405 BZFILE * bzopen_or_bzdopen
1406 ( const char *path, /* no use when bzdopen */
1407 int fd, /* no use when bzdopen */
1409 int open_mode) /* bzopen: 0, bzdopen:1 */
1412 char unused[BZ_MAX_UNUSED];
1413 int blockSize100k = 9;
1415 char mode2[10] = "";
1417 BZFILE *bzfp = NULL;
1419 int workFactor = 30;
1423 if (mode == NULL) return NULL;
1431 smallMode = 1; break;
1433 if (isdigit((int)(*mode))) {
1434 blockSize100k = *mode-BZ_HDR_0;
1439 strcat(mode2, writing ? "w" : "r" );
1440 strcat(mode2,"b"); /* binary mode */
1443 if (path==NULL || strcmp(path,"")==0) {
1444 fp = (writing ? stdout : stdin);
1445 SET_BINARY_MODE(fp);
1447 fp = fopen(path,mode2);
1450 #ifdef BZ_STRICT_ANSI
1453 fp = fdopen(fd,mode2);
1456 if (fp == NULL) return NULL;
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);
1465 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1469 if (fp != stdin && fp != stdout) fclose(fp);
1476 /*---------------------------------------------------*/
1478 open file for read or write.
1479 ex) bzopen("file","w9")
1480 case path="" or NULL => use stdin or stdout.
1482 BZFILE * BZ_API(BZ2_bzopen)
1486 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1490 /*---------------------------------------------------*/
1491 BZFILE * BZ_API(BZ2_bzdopen)
1495 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1499 /*---------------------------------------------------*/
1500 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
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) {
1513 /*---------------------------------------------------*/
1514 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1518 BZ2_bzWrite(&bzerr,b,buf,len);
1527 /*---------------------------------------------------*/
1528 int BZ_API(BZ2_bzflush) (BZFILE *b)
1530 /* do nothing now... */
1535 /*---------------------------------------------------*/
1536 void BZ_API(BZ2_bzclose) (BZFILE* b)
1539 FILE *fp = ((bzFile *)b)->handle;
1541 if (b==NULL) {return;}
1542 if(((bzFile*)b)->writing){
1543 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1545 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1548 BZ2_bzReadClose(&bzerr,b);
1550 if(fp!=stdin && fp!=stdout){
1556 /*---------------------------------------------------*/
1558 return last error code
1560 static char *bzerrorstrings[] = {
1571 ,"???" /* for future */
1572 ,"???" /* for future */
1573 ,"???" /* for future */
1574 ,"???" /* for future */
1575 ,"???" /* for future */
1576 ,"???" /* for future */
1580 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1582 int err = ((bzFile *)b)->lastErr;
1586 return bzerrorstrings[err*-1];
1591 /*-------------------------------------------------------------*/
1592 /*--- end bzlib.c ---*/
1593 /*-------------------------------------------------------------*/
1595 #endif /* CONFIG_BZIP2 */