7 * This file is a modified version of bzlib.c from the bzip2-1.0.2
8 * distribution which can be found at http://sources.redhat.com/bzip2/
11 /*-------------------------------------------------------------*/
12 /*--- Library top-level functions. ---*/
14 /*-------------------------------------------------------------*/
17 This file is a part of bzip2 and/or libbzip2, a program and
18 library for lossless, block-sorting data compression.
20 Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
22 Redistribution and use in source and binary forms, with or without
23 modification, are permitted provided that the following conditions
26 1. Redistributions of source code must retain the above copyright
27 notice, this list of conditions and the following disclaimer.
29 2. The origin of this software must not be misrepresented; you must
30 not claim that you wrote the original software. If you use this
31 software in a product, an acknowledgment in the product
32 documentation would be appreciated but is not required.
34 3. Altered source versions must be plainly marked as such, and must
35 not be misrepresented as being the original software.
37 4. The name of the author may not be used to endorse or promote
38 products derived from this software without specific prior written
41 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
42 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
45 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
47 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
48 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
50 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
51 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 Julian Seward, Cambridge, UK.
55 bzip2/libbzip2 version 1.0 of 21 March 2000
57 This program is based on (at least) the work of:
67 For more information on these sources, see the manual.
73 0.9.0 -- original version.
75 0.9.0a/b -- no changes in this file.
78 * made zero-length BZ_FLUSH work correctly in bzCompress().
79 * fixed bzWrite/bzRead to ignore zero-length requests.
80 * fixed bzread to correctly handle read requests after EOF.
81 * wrong parameter order in call to bzDecompressInit in
82 bzBuffToBuffDecompress. Fixed.
85 #include "bzlib_private.h"
87 /*---------------------------------------------------*/
88 /*--- Compression stuff ---*/
89 /*---------------------------------------------------*/
92 /*---------------------------------------------------*/
94 void BZ2_bz__AssertH__fail ( int errcode )
97 "\n\nbzip2/libbzip2: internal error number %d.\n"
98 "This is a bug in bzip2/libbzip2, %s.\n"
99 "Please report it to me at: jseward@acm.org. If this happened\n"
100 "when you were using some program which uses libbzip2 as a\n"
101 "component, you should also report this bug to the author(s)\n"
102 "of that program. Please make an effort to report this bug;\n"
103 "timely and accurate bug reports eventually lead to higher\n"
104 "quality software. Thanks. Julian Seward, 30 December 2001.\n\n",
109 if (errcode == 1007) {
111 "\n*** A special note about internal error number 1007 ***\n"
113 "Experience suggests that a common cause of i.e. 1007\n"
114 "is unreliable memory or other hardware. The 1007 assertion\n"
115 "just happens to cross-check the results of huge numbers of\n"
116 "memory reads/writes, and so acts (unintendedly) as a stress\n"
117 "test of your memory system.\n"
119 "I suggest the following: try compressing the file again,\n"
120 "possibly monitoring progress in detail with the -vv flag.\n"
122 "* If the error cannot be reproduced, and/or happens at different\n"
123 " points in compression, you may have a flaky memory system.\n"
124 " Try a memory-test program. I have used Memtest86\n"
125 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
126 " Memtest86 tests memory much more thorougly than your BIOSs\n"
127 " power-on test, and may find failures that the BIOS doesn't.\n"
129 "* If the error can be repeatably reproduced, this is a bug in\n"
130 " bzip2, and I would very much like to hear about it. Please\n"
131 " let me know, and, ideally, save a copy of the file causing the\n"
132 " problem -- without which I will be unable to investigate it.\n"
142 /*---------------------------------------------------*/
144 int bz_config_ok ( void )
146 if (sizeof(int) != 4) return 0;
147 if (sizeof(short) != 2) return 0;
148 if (sizeof(char) != 1) return 0;
153 /*---------------------------------------------------*/
155 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
157 void* v = malloc ( items * size );
162 void default_bzfree ( void* opaque, void* addr )
164 if (addr != NULL) free ( addr );
167 #ifndef BZ_NO_COMPRESS
168 /*---------------------------------------------------*/
170 void prepare_new_block ( EState* s )
175 s->state_out_pos = 0;
176 BZ_INITIALISE_CRC ( s->blockCRC );
177 for (i = 0; i < 256; i++) s->inUse[i] = False;
182 /*---------------------------------------------------*/
184 void init_RL ( EState* s )
186 s->state_in_ch = 256;
192 Bool isempty_RL ( EState* s )
194 if (s->state_in_ch < 256 && s->state_in_len > 0)
199 /*---------------------------------------------------*/
200 int BZ_API(BZ2_bzCompressInit)
209 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
212 blockSize100k < 1 || blockSize100k > 9 ||
213 workFactor < 0 || workFactor > 250)
214 return BZ_PARAM_ERROR;
216 if (workFactor == 0) workFactor = 30;
217 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
218 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
220 s = BZALLOC( sizeof(EState) );
221 if (s == NULL) return BZ_MEM_ERROR;
228 n = 100000 * blockSize100k;
229 s->arr1 = BZALLOC( n * sizeof(UInt32) );
230 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
231 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
233 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
234 if (s->arr1 != NULL) BZFREE(s->arr1);
235 if (s->arr2 != NULL) BZFREE(s->arr2);
236 if (s->ftab != NULL) BZFREE(s->ftab);
237 if (s != NULL) BZFREE(s);
242 s->state = BZ_S_INPUT;
243 s->mode = BZ_M_RUNNING;
245 s->blockSize100k = blockSize100k;
246 s->nblockMAX = 100000 * blockSize100k - 19;
247 s->verbosity = verbosity;
248 s->workFactor = workFactor;
250 s->block = (UChar*)s->arr2;
251 s->mtfv = (UInt16*)s->arr1;
253 s->ptr = (UInt32*)s->arr1;
256 strm->total_in_lo32 = 0;
257 strm->total_in_hi32 = 0;
258 strm->total_out_lo32 = 0;
259 strm->total_out_hi32 = 0;
261 prepare_new_block ( s );
266 /*---------------------------------------------------*/
268 void add_pair_to_block ( EState* s )
271 UChar ch = (UChar)(s->state_in_ch);
272 for (i = 0; i < s->state_in_len; i++) {
273 BZ_UPDATE_CRC( s->blockCRC, ch );
275 s->inUse[s->state_in_ch] = True;
276 switch (s->state_in_len) {
278 s->block[s->nblock] = (UChar)ch; s->nblock++;
281 s->block[s->nblock] = (UChar)ch; s->nblock++;
282 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++;
290 s->inUse[s->state_in_len-4] = True;
291 s->block[s->nblock] = (UChar)ch; s->nblock++;
292 s->block[s->nblock] = (UChar)ch; s->nblock++;
293 s->block[s->nblock] = (UChar)ch; s->nblock++;
294 s->block[s->nblock] = (UChar)ch; s->nblock++;
295 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
302 /*---------------------------------------------------*/
304 void flush_RL ( EState* s )
306 if (s->state_in_ch < 256) add_pair_to_block ( s );
311 /*---------------------------------------------------*/
312 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
314 UInt32 zchh = (UInt32)(zchh0); \
315 /*-- fast track the common case --*/ \
316 if (zchh != zs->state_in_ch && \
317 zs->state_in_len == 1) { \
318 UChar ch = (UChar)(zs->state_in_ch); \
319 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
320 zs->inUse[zs->state_in_ch] = True; \
321 zs->block[zs->nblock] = (UChar)ch; \
323 zs->state_in_ch = zchh; \
326 /*-- general, uncommon cases --*/ \
327 if (zchh != zs->state_in_ch || \
328 zs->state_in_len == 255) { \
329 if (zs->state_in_ch < 256) \
330 add_pair_to_block ( zs ); \
331 zs->state_in_ch = zchh; \
332 zs->state_in_len = 1; \
334 zs->state_in_len++; \
339 /*---------------------------------------------------*/
341 Bool copy_input_until_stop ( EState* s )
343 Bool progress_in = False;
345 if (s->mode == BZ_M_RUNNING) {
347 /*-- fast track the common case --*/
349 /*-- block full? --*/
350 if (s->nblock >= s->nblockMAX) break;
352 if (s->strm->avail_in == 0) break;
354 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
357 s->strm->total_in_lo32++;
358 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
363 /*-- general, uncommon case --*/
365 /*-- block full? --*/
366 if (s->nblock >= s->nblockMAX) break;
368 if (s->strm->avail_in == 0) break;
369 /*-- flush/finish end? --*/
370 if (s->avail_in_expect == 0) break;
372 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
375 s->strm->total_in_lo32++;
376 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
377 s->avail_in_expect--;
384 /*---------------------------------------------------*/
386 Bool copy_output_until_stop ( EState* s )
388 Bool progress_out = False;
392 /*-- no output space? --*/
393 if (s->strm->avail_out == 0) break;
395 /*-- block done? --*/
396 if (s->state_out_pos >= s->numZ) break;
399 *(s->strm->next_out) = s->zbits[s->state_out_pos];
401 s->strm->avail_out--;
403 s->strm->total_out_lo32++;
404 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
411 /*---------------------------------------------------*/
413 Bool handle_compress ( bz_stream* strm )
415 Bool progress_in = False;
416 Bool progress_out = False;
417 EState* s = strm->state;
421 if (s->state == BZ_S_OUTPUT) {
422 progress_out |= copy_output_until_stop ( s );
423 if (s->state_out_pos < s->numZ) break;
424 if (s->mode == BZ_M_FINISHING &&
425 s->avail_in_expect == 0 &&
426 isempty_RL(s)) break;
427 prepare_new_block ( s );
428 s->state = BZ_S_INPUT;
429 if (s->mode == BZ_M_FLUSHING &&
430 s->avail_in_expect == 0 &&
431 isempty_RL(s)) break;
434 if (s->state == BZ_S_INPUT) {
435 progress_in |= copy_input_until_stop ( s );
436 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
438 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
439 s->state = BZ_S_OUTPUT;
442 if (s->nblock >= s->nblockMAX) {
443 BZ2_compressBlock ( s, False );
444 s->state = BZ_S_OUTPUT;
447 if (s->strm->avail_in == 0) {
454 return progress_in || progress_out;
458 /*---------------------------------------------------*/
459 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
463 if (strm == NULL) return BZ_PARAM_ERROR;
465 if (s == NULL) return BZ_PARAM_ERROR;
466 if (s->strm != strm) return BZ_PARAM_ERROR;
472 return BZ_SEQUENCE_ERROR;
475 if (action == BZ_RUN) {
476 progress = handle_compress ( strm );
477 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
480 if (action == BZ_FLUSH) {
481 s->avail_in_expect = strm->avail_in;
482 s->mode = BZ_M_FLUSHING;
486 if (action == BZ_FINISH) {
487 s->avail_in_expect = strm->avail_in;
488 s->mode = BZ_M_FINISHING;
492 return BZ_PARAM_ERROR;
495 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
496 if (s->avail_in_expect != s->strm->avail_in)
497 return BZ_SEQUENCE_ERROR;
498 progress = handle_compress ( strm );
499 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
500 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
501 s->mode = BZ_M_RUNNING;
505 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
506 if (s->avail_in_expect != s->strm->avail_in)
507 return BZ_SEQUENCE_ERROR;
508 progress = handle_compress ( strm );
509 if (!progress) return BZ_SEQUENCE_ERROR;
510 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
511 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
513 return BZ_STREAM_END;
515 return BZ_OK; /*--not reached--*/
519 /*---------------------------------------------------*/
520 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
523 if (strm == NULL) return BZ_PARAM_ERROR;
525 if (s == NULL) return BZ_PARAM_ERROR;
526 if (s->strm != strm) return BZ_PARAM_ERROR;
528 if (s->arr1 != NULL) BZFREE(s->arr1);
529 if (s->arr2 != NULL) BZFREE(s->arr2);
530 if (s->ftab != NULL) BZFREE(s->ftab);
537 #endif /* BZ_NO_COMPRESS */
539 /*---------------------------------------------------*/
540 /*--- Decompression stuff ---*/
541 /*---------------------------------------------------*/
543 /*---------------------------------------------------*/
544 int BZ_API(BZ2_bzDecompressInit)
551 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
553 if (strm == NULL) return BZ_PARAM_ERROR;
554 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
555 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
557 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
558 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
560 s = BZALLOC( sizeof(DState) );
561 if (s == NULL) return BZ_MEM_ERROR;
564 s->state = BZ_X_MAGIC_1;
567 s->calculatedCombinedCRC = 0;
568 strm->total_in_lo32 = 0;
569 strm->total_in_hi32 = 0;
570 strm->total_out_lo32 = 0;
571 strm->total_out_hi32 = 0;
572 s->smallDecompress = (Bool)small;
577 s->verbosity = verbosity;
583 /*---------------------------------------------------*/
585 void unRLE_obuf_to_output_FAST ( DState* s )
589 if (s->blockRandomised) {
592 /* try to finish existing run */
594 if (s->strm->avail_out == 0) return;
595 if (s->state_out_len == 0) break;
596 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
597 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
600 s->strm->avail_out--;
601 s->strm->total_out_lo32++;
602 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
605 /* can a new run be started? */
606 if (s->nblock_used == s->save_nblock+1) return;
609 s->state_out_len = 1;
610 s->state_out_ch = s->k0;
611 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
612 k1 ^= BZ_RAND_MASK; s->nblock_used++;
613 if (s->nblock_used == s->save_nblock+1) continue;
614 if (k1 != s->k0) { s->k0 = k1; continue; };
616 s->state_out_len = 2;
617 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
618 k1 ^= BZ_RAND_MASK; s->nblock_used++;
619 if (s->nblock_used == s->save_nblock+1) continue;
620 if (k1 != s->k0) { s->k0 = k1; continue; };
622 s->state_out_len = 3;
623 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
624 k1 ^= BZ_RAND_MASK; s->nblock_used++;
625 if (s->nblock_used == s->save_nblock+1) continue;
626 if (k1 != s->k0) { s->k0 = k1; continue; };
628 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
629 k1 ^= BZ_RAND_MASK; s->nblock_used++;
630 s->state_out_len = ((Int32)k1) + 4;
631 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
632 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
638 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
639 UChar c_state_out_ch = s->state_out_ch;
640 Int32 c_state_out_len = s->state_out_len;
641 Int32 c_nblock_used = s->nblock_used;
643 UInt32* c_tt = s->tt;
644 UInt32 c_tPos = s->tPos;
645 char* cs_next_out = s->strm->next_out;
646 unsigned int cs_avail_out = s->strm->avail_out;
649 UInt32 avail_out_INIT = cs_avail_out;
650 Int32 s_save_nblockPP = s->save_nblock+1;
651 unsigned int total_out_lo32_old;
655 /* try to finish existing run */
656 if (c_state_out_len > 0) {
658 if (cs_avail_out == 0) goto return_notr;
659 if (c_state_out_len == 1) break;
660 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
661 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
666 s_state_out_len_eq_one:
668 if (cs_avail_out == 0) {
669 c_state_out_len = 1; goto return_notr;
671 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
672 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
677 /* can a new run be started? */
678 if (c_nblock_used == s_save_nblockPP) {
679 c_state_out_len = 0; goto return_notr;
681 c_state_out_ch = c_k0;
682 BZ_GET_FAST_C(k1); c_nblock_used++;
684 c_k0 = k1; goto s_state_out_len_eq_one;
686 if (c_nblock_used == s_save_nblockPP)
687 goto s_state_out_len_eq_one;
690 BZ_GET_FAST_C(k1); c_nblock_used++;
691 if (c_nblock_used == s_save_nblockPP) continue;
692 if (k1 != c_k0) { c_k0 = k1; continue; };
695 BZ_GET_FAST_C(k1); c_nblock_used++;
696 if (c_nblock_used == s_save_nblockPP) continue;
697 if (k1 != c_k0) { c_k0 = k1; continue; };
699 BZ_GET_FAST_C(k1); c_nblock_used++;
700 c_state_out_len = ((Int32)k1) + 4;
701 BZ_GET_FAST_C(c_k0); c_nblock_used++;
705 total_out_lo32_old = s->strm->total_out_lo32;
706 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
707 if (s->strm->total_out_lo32 < total_out_lo32_old)
708 s->strm->total_out_hi32++;
711 s->calculatedBlockCRC = c_calculatedBlockCRC;
712 s->state_out_ch = c_state_out_ch;
713 s->state_out_len = c_state_out_len;
714 s->nblock_used = c_nblock_used;
718 s->strm->next_out = cs_next_out;
719 s->strm->avail_out = cs_avail_out;
725 /*---------------------------------------------------*/
726 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
732 mid = (nb + na) >> 1;
733 if (indx >= cftab[mid]) nb = mid; else na = mid;
735 while (na - nb != 1);
740 /*---------------------------------------------------*/
742 void unRLE_obuf_to_output_SMALL ( DState* s )
746 if (s->blockRandomised) {
749 /* try to finish existing run */
751 if (s->strm->avail_out == 0) return;
752 if (s->state_out_len == 0) break;
753 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
754 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
757 s->strm->avail_out--;
758 s->strm->total_out_lo32++;
759 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
762 /* can a new run be started? */
763 if (s->nblock_used == s->save_nblock+1) return;
766 s->state_out_len = 1;
767 s->state_out_ch = s->k0;
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; };
773 s->state_out_len = 2;
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; };
779 s->state_out_len = 3;
780 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
781 k1 ^= BZ_RAND_MASK; s->nblock_used++;
782 if (s->nblock_used == s->save_nblock+1) continue;
783 if (k1 != s->k0) { s->k0 = k1; continue; };
785 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
786 k1 ^= BZ_RAND_MASK; s->nblock_used++;
787 s->state_out_len = ((Int32)k1) + 4;
788 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
789 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
795 /* try to finish existing run */
797 if (s->strm->avail_out == 0) return;
798 if (s->state_out_len == 0) break;
799 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
800 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
803 s->strm->avail_out--;
804 s->strm->total_out_lo32++;
805 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
808 /* can a new run be started? */
809 if (s->nblock_used == s->save_nblock+1) return;
811 s->state_out_len = 1;
812 s->state_out_ch = s->k0;
813 BZ_GET_SMALL(k1); s->nblock_used++;
814 if (s->nblock_used == s->save_nblock+1) continue;
815 if (k1 != s->k0) { s->k0 = k1; continue; };
817 s->state_out_len = 2;
818 BZ_GET_SMALL(k1); s->nblock_used++;
819 if (s->nblock_used == s->save_nblock+1) continue;
820 if (k1 != s->k0) { s->k0 = k1; continue; };
822 s->state_out_len = 3;
823 BZ_GET_SMALL(k1); s->nblock_used++;
824 if (s->nblock_used == s->save_nblock+1) continue;
825 if (k1 != s->k0) { s->k0 = k1; continue; };
827 BZ_GET_SMALL(k1); s->nblock_used++;
828 s->state_out_len = ((Int32)k1) + 4;
829 BZ_GET_SMALL(s->k0); s->nblock_used++;
836 /*---------------------------------------------------*/
837 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
840 if (strm == NULL) return BZ_PARAM_ERROR;
842 if (s == NULL) return BZ_PARAM_ERROR;
843 if (s->strm != strm) return BZ_PARAM_ERROR;
846 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
849 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
850 if (s->state == BZ_X_OUTPUT) {
851 if (s->smallDecompress)
852 unRLE_obuf_to_output_SMALL ( s ); else
853 unRLE_obuf_to_output_FAST ( s );
854 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
855 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
856 if (s->verbosity >= 3)
857 VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC,
858 s->calculatedBlockCRC );
859 if (s->verbosity >= 2) VPrintf0 ( "]" );
860 if (s->calculatedBlockCRC != s->storedBlockCRC)
861 return BZ_DATA_ERROR;
862 s->calculatedCombinedCRC
863 = (s->calculatedCombinedCRC << 1) |
864 (s->calculatedCombinedCRC >> 31);
865 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
866 s->state = BZ_X_BLKHDR_1;
871 if (s->state >= BZ_X_MAGIC_1) {
872 Int32 r = BZ2_decompress ( s );
873 if (r == BZ_STREAM_END) {
874 if (s->verbosity >= 3)
875 VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x",
876 s->storedCombinedCRC, s->calculatedCombinedCRC );
877 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
878 return BZ_DATA_ERROR;
881 if (s->state != BZ_X_OUTPUT) return r;
887 return 0; /*NOTREACHED*/
891 /*---------------------------------------------------*/
892 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
895 if (strm == NULL) return BZ_PARAM_ERROR;
897 if (s == NULL) return BZ_PARAM_ERROR;
898 if (s->strm != strm) return BZ_PARAM_ERROR;
900 if (s->tt != NULL) BZFREE(s->tt);
901 if (s->ll16 != NULL) BZFREE(s->ll16);
902 if (s->ll4 != NULL) BZFREE(s->ll4);
912 /*---------------------------------------------------*/
913 /*--- File I/O stuff ---*/
914 /*---------------------------------------------------*/
916 #define BZ_SETERR(eee) \
918 if (bzerror != NULL) *bzerror = eee; \
919 if (bzf != NULL) bzf->lastErr = eee; \
925 Char buf[BZ_MAX_UNUSED];
935 /*---------------------------------------------*/
936 static Bool myfeof ( FILE* f )
938 Int32 c = fgetc ( f );
939 if (c == EOF) return True;
945 /*---------------------------------------------------*/
946 BZFILE* BZ_API(BZ2_bzWriteOpen)
959 (blockSize100k < 1 || blockSize100k > 9) ||
960 (workFactor < 0 || workFactor > 250) ||
961 (verbosity < 0 || verbosity > 4))
962 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
965 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
967 bzf = malloc ( sizeof(bzFile) );
969 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
972 bzf->initialisedOk = False;
976 bzf->strm.bzalloc = NULL;
977 bzf->strm.bzfree = NULL;
978 bzf->strm.opaque = NULL;
980 if (workFactor == 0) workFactor = 30;
981 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
982 verbosity, workFactor );
984 { BZ_SETERR(ret); free(bzf); return NULL; };
986 bzf->strm.avail_in = 0;
987 bzf->initialisedOk = True;
992 /*---------------------------------------------------*/
993 void BZ_API(BZ2_bzWrite)
1000 bzFile* bzf = (bzFile*)b;
1003 if (bzf == NULL || buf == NULL || len < 0)
1004 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1005 if (!(bzf->writing))
1006 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1007 if (ferror(bzf->handle))
1008 { BZ_SETERR(BZ_IO_ERROR); return; };
1011 { BZ_SETERR(BZ_OK); return; };
1013 bzf->strm.avail_in = len;
1014 bzf->strm.next_in = buf;
1017 bzf->strm.avail_out = BZ_MAX_UNUSED;
1018 bzf->strm.next_out = bzf->buf;
1019 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
1020 if (ret != BZ_RUN_OK)
1021 { BZ_SETERR(ret); return; };
1023 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1024 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1025 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1027 if (n != n2 || ferror(bzf->handle))
1028 { BZ_SETERR(BZ_IO_ERROR); return; };
1031 if (bzf->strm.avail_in == 0)
1032 { BZ_SETERR(BZ_OK); return; };
1037 /*---------------------------------------------------*/
1038 void BZ_API(BZ2_bzWriteClose)
1042 unsigned int* nbytes_in,
1043 unsigned int* nbytes_out )
1045 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1046 nbytes_in, NULL, nbytes_out, NULL );
1050 void BZ_API(BZ2_bzWriteClose64)
1054 unsigned int* nbytes_in_lo32,
1055 unsigned int* nbytes_in_hi32,
1056 unsigned int* nbytes_out_lo32,
1057 unsigned int* nbytes_out_hi32 )
1060 bzFile* bzf = (bzFile*)b;
1063 { BZ_SETERR(BZ_OK); return; };
1064 if (!(bzf->writing))
1065 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1066 if (ferror(bzf->handle))
1067 { BZ_SETERR(BZ_IO_ERROR); return; };
1069 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1070 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1071 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1072 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1074 if ((!abandon) && bzf->lastErr == BZ_OK) {
1076 bzf->strm.avail_out = BZ_MAX_UNUSED;
1077 bzf->strm.next_out = bzf->buf;
1078 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1079 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1080 { BZ_SETERR(ret); return; };
1082 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1083 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1084 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1086 if (n != n2 || ferror(bzf->handle))
1087 { BZ_SETERR(BZ_IO_ERROR); return; };
1090 if (ret == BZ_STREAM_END) break;
1094 if ( !abandon && !ferror ( bzf->handle ) ) {
1095 fflush ( bzf->handle );
1096 if (ferror(bzf->handle))
1097 { BZ_SETERR(BZ_IO_ERROR); return; };
1100 if (nbytes_in_lo32 != NULL)
1101 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1102 if (nbytes_in_hi32 != NULL)
1103 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1104 if (nbytes_out_lo32 != NULL)
1105 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1106 if (nbytes_out_hi32 != NULL)
1107 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1110 BZ2_bzCompressEnd ( &(bzf->strm) );
1115 /*---------------------------------------------------*/
1116 BZFILE* BZ_API(BZ2_bzReadOpen)
1130 (small != 0 && small != 1) ||
1131 (verbosity < 0 || verbosity > 4) ||
1132 (unused == NULL && nUnused != 0) ||
1133 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1134 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1137 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1139 bzf = malloc ( sizeof(bzFile) );
1141 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1145 bzf->initialisedOk = False;
1148 bzf->writing = False;
1149 bzf->strm.bzalloc = NULL;
1150 bzf->strm.bzfree = NULL;
1151 bzf->strm.opaque = NULL;
1153 while (nUnused > 0) {
1154 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1155 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1159 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1161 { BZ_SETERR(ret); free(bzf); return NULL; };
1163 bzf->strm.avail_in = bzf->bufN;
1164 bzf->strm.next_in = bzf->buf;
1166 bzf->initialisedOk = True;
1171 /*---------------------------------------------------*/
1172 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1174 bzFile* bzf = (bzFile*)b;
1178 { BZ_SETERR(BZ_OK); return; };
1181 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1183 if (bzf->initialisedOk)
1184 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1189 /*---------------------------------------------------*/
1190 int BZ_API(BZ2_bzRead)
1197 bzFile* bzf = (bzFile*)b;
1201 if (bzf == NULL || buf == NULL || len < 0)
1202 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1205 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1208 { BZ_SETERR(BZ_OK); return 0; };
1210 bzf->strm.avail_out = len;
1211 bzf->strm.next_out = buf;
1215 if (ferror(bzf->handle))
1216 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1218 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1219 n = fread ( bzf->buf, sizeof(UChar),
1220 BZ_MAX_UNUSED, bzf->handle );
1221 if (ferror(bzf->handle))
1222 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1224 bzf->strm.avail_in = bzf->bufN;
1225 bzf->strm.next_in = bzf->buf;
1228 ret = BZ2_bzDecompress ( &(bzf->strm) );
1230 if (ret != BZ_OK && ret != BZ_STREAM_END)
1231 { BZ_SETERR(ret); return 0; };
1233 if (ret == BZ_OK && myfeof(bzf->handle) &&
1234 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1235 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1237 if (ret == BZ_STREAM_END)
1238 { BZ_SETERR(BZ_STREAM_END);
1239 return len - bzf->strm.avail_out; };
1240 if (bzf->strm.avail_out == 0)
1241 { BZ_SETERR(BZ_OK); return len; };
1245 return 0; /*not reached*/
1249 /*---------------------------------------------------*/
1250 void BZ_API(BZ2_bzReadGetUnused)
1256 bzFile* bzf = (bzFile*)b;
1258 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1259 if (bzf->lastErr != BZ_STREAM_END)
1260 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1261 if (unused == NULL || nUnused == NULL)
1262 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1265 *nUnused = bzf->strm.avail_in;
1266 *unused = bzf->strm.next_in;
1271 /*---------------------------------------------------*/
1272 /*--- Misc convenience stuff ---*/
1273 /*---------------------------------------------------*/
1274 #ifndef BZ_NO_COMPRESS
1275 /*---------------------------------------------------*/
1276 int BZ_API(BZ2_bzBuffToBuffCompress)
1278 unsigned int* destLen,
1280 unsigned int sourceLen,
1288 if (dest == NULL || destLen == NULL ||
1290 blockSize100k < 1 || blockSize100k > 9 ||
1291 verbosity < 0 || verbosity > 4 ||
1292 workFactor < 0 || workFactor > 250)
1293 return BZ_PARAM_ERROR;
1295 if (workFactor == 0) workFactor = 30;
1296 strm.bzalloc = NULL;
1299 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1300 verbosity, workFactor );
1301 if (ret != BZ_OK) return ret;
1303 strm.next_in = source;
1304 strm.next_out = dest;
1305 strm.avail_in = sourceLen;
1306 strm.avail_out = *destLen;
1308 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1309 if (ret == BZ_FINISH_OK) goto output_overflow;
1310 if (ret != BZ_STREAM_END) goto errhandler;
1312 /* normal termination */
1313 *destLen -= strm.avail_out;
1314 BZ2_bzCompressEnd ( &strm );
1318 BZ2_bzCompressEnd ( &strm );
1319 return BZ_OUTBUFF_FULL;
1322 BZ2_bzCompressEnd ( &strm );
1325 #endif /* BZ_NO_COMPRESS */
1327 /*---------------------------------------------------*/
1328 int BZ_API(BZ2_bzBuffToBuffDecompress)
1330 unsigned int* destLen,
1332 unsigned int sourceLen,
1339 if (destLen == NULL || source == NULL)
1340 return BZ_PARAM_ERROR;
1342 strm.bzalloc = NULL;
1345 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1346 if (ret != BZ_OK) return ret;
1348 strm.next_in = source;
1349 strm.next_out = dest;
1350 strm.avail_in = sourceLen;
1351 strm.avail_out = *destLen;
1353 ret = BZ2_bzDecompress ( &strm );
1354 if (ret == BZ_OK) goto output_overflow_or_eof;
1355 if (ret != BZ_STREAM_END) goto errhandler;
1357 /* normal termination */
1358 *destLen -= strm.avail_out;
1359 BZ2_bzDecompressEnd ( &strm );
1362 output_overflow_or_eof:
1363 if (strm.avail_out > 0) {
1364 BZ2_bzDecompressEnd ( &strm );
1365 return BZ_UNEXPECTED_EOF;
1367 BZ2_bzDecompressEnd ( &strm );
1368 return BZ_OUTBUFF_FULL;
1372 BZ2_bzDecompressEnd ( &strm );
1377 /*---------------------------------------------------*/
1379 Code contributed by Yoshioka Tsuneo
1380 (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
1381 to support better zlib compatibility.
1382 This code is not _officially_ part of libbzip2 (yet);
1383 I haven't tested it, documented it, or considered the
1384 threading-safeness of it.
1385 If this code breaks, please contact both Yoshioka and me.
1387 /*---------------------------------------------------*/
1389 /*---------------------------------------------------*/
1391 return version like "0.9.0c".
1393 const char * BZ_API(BZ2_bzlibVersion)(void)
1400 /*---------------------------------------------------*/
1402 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1405 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1407 # define SET_BINARY_MODE(file)
1410 BZFILE * bzopen_or_bzdopen
1411 ( const char *path, /* no use when bzdopen */
1412 int fd, /* no use when bzdopen */
1414 int open_mode) /* bzopen: 0, bzdopen:1 */
1417 char unused[BZ_MAX_UNUSED];
1418 int blockSize100k = 9;
1420 char mode2[10] = "";
1422 BZFILE *bzfp = NULL;
1424 int workFactor = 30;
1428 if (mode == NULL) return NULL;
1436 smallMode = 1; break;
1438 if (isdigit((int)(*mode))) {
1439 blockSize100k = *mode-BZ_HDR_0;
1444 strcat(mode2, writing ? "w" : "r" );
1445 strcat(mode2,"b"); /* binary mode */
1448 if (path==NULL || strcmp(path,"")==0) {
1449 fp = (writing ? stdout : stdin);
1450 SET_BINARY_MODE(fp);
1452 fp = fopen(path,mode2);
1455 #ifdef BZ_STRICT_ANSI
1458 fp = fdopen(fd,mode2);
1461 if (fp == NULL) return NULL;
1464 /* Guard against total chaos and anarchy -- JRS */
1465 if (blockSize100k < 1) blockSize100k = 1;
1466 if (blockSize100k > 9) blockSize100k = 9;
1467 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1468 verbosity,workFactor);
1470 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1474 if (fp != stdin && fp != stdout) fclose(fp);
1481 /*---------------------------------------------------*/
1483 open file for read or write.
1484 ex) bzopen("file","w9")
1485 case path="" or NULL => use stdin or stdout.
1487 BZFILE * BZ_API(BZ2_bzopen)
1491 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1495 /*---------------------------------------------------*/
1496 BZFILE * BZ_API(BZ2_bzdopen)
1500 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1504 /*---------------------------------------------------*/
1505 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1508 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1509 nread = BZ2_bzRead(&bzerr,b,buf,len);
1510 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1518 /*---------------------------------------------------*/
1519 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1523 BZ2_bzWrite(&bzerr,b,buf,len);
1532 /*---------------------------------------------------*/
1533 int BZ_API(BZ2_bzflush) (BZFILE *b)
1535 /* do nothing now... */
1540 /*---------------------------------------------------*/
1541 void BZ_API(BZ2_bzclose) (BZFILE* b)
1544 FILE *fp = ((bzFile *)b)->handle;
1546 if (b==NULL) {return;}
1547 if(((bzFile*)b)->writing){
1548 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1550 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1553 BZ2_bzReadClose(&bzerr,b);
1555 if(fp!=stdin && fp!=stdout){
1561 /*---------------------------------------------------*/
1563 return last error code
1565 static char *bzerrorstrings[] = {
1576 ,"???" /* for future */
1577 ,"???" /* for future */
1578 ,"???" /* for future */
1579 ,"???" /* for future */
1580 ,"???" /* for future */
1581 ,"???" /* for future */
1585 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1587 int err = ((bzFile *)b)->lastErr;
1591 return bzerrorstrings[err*-1];
1596 /*-------------------------------------------------------------*/
1597 /*--- end bzlib.c ---*/
1598 /*-------------------------------------------------------------*/
1600 #endif /* CONFIG_BZIP2 */