2 /*-------------------------------------------------------------*/
3 /*--- Library top-level functions. ---*/
5 /*-------------------------------------------------------------*/
7 /* ------------------------------------------------------------------
8 This file is part of bzip2/libbzip2, a program and library for
9 lossless, block-sorting data compression.
11 bzip2/libbzip2 version 1.0.6 of 6 September 2010
12 Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
14 Please read the WARNING, DISCLAIMER and PATENTS sections in the
17 This program is released under the terms of the license contained
19 ------------------------------------------------------------------ */
22 0.9.0 -- original version.
23 0.9.0a/b -- no changes in this file.
24 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress().
25 fixed bzWrite/bzRead to ignore zero-length requests.
26 fixed bzread to correctly handle read requests after EOF.
27 wrong parameter order in call to bzDecompressInit in
28 bzBuffToBuffDecompress. Fixed.
31 #ifdef BZ_DECOMPRESS_ONLY
38 #include "bzlib_private.h"
41 /*---------------------------------------------------*/
42 /*--- Compression stuff ---*/
43 /*---------------------------------------------------*/
46 /*---------------------------------------------------*/
48 void BZ2_bz__AssertH__fail ( int errcode
)
51 "\n\nbzip2/libbzip2: internal error number %d.\n"
52 "This is a bug in bzip2/libbzip2, %s.\n"
53 "Please report it to me at: jseward@bzip.org. If this happened\n"
54 "when you were using some program which uses libbzip2 as a\n"
55 "component, you should also report this bug to the author(s)\n"
56 "of that program. Please make an effort to report this bug;\n"
57 "timely and accurate bug reports eventually lead to higher\n"
58 "quality software. Thanks. Julian Seward, 10 December 2007.\n\n",
63 if (errcode
== 1007) {
65 "\n*** A special note about internal error number 1007 ***\n"
67 "Experience suggests that a common cause of i.e. 1007\n"
68 "is unreliable memory or other hardware. The 1007 assertion\n"
69 "just happens to cross-check the results of huge numbers of\n"
70 "memory reads/writes, and so acts (unintendedly) as a stress\n"
71 "test of your memory system.\n"
73 "I suggest the following: try compressing the file again,\n"
74 "possibly monitoring progress in detail with the -vv flag.\n"
76 "* If the error cannot be reproduced, and/or happens at different\n"
77 " points in compression, you may have a flaky memory system.\n"
78 " Try a memory-test program. I have used Memtest86\n"
79 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
80 " Memtest86 tests memory much more thorougly than your BIOSs\n"
81 " power-on test, and may find failures that the BIOS doesn't.\n"
83 "* If the error can be repeatably reproduced, this is a bug in\n"
84 " bzip2, and I would very much like to hear about it. Please\n"
85 " let me know, and, ideally, save a copy of the file causing the\n"
86 " problem -- without which I will be unable to investigate it.\n"
96 /*---------------------------------------------------*/
98 int bz_config_ok ( void )
100 if (sizeof(int) != 4) return 0;
101 if (sizeof(short) != 2) return 0;
102 if (sizeof(char) != 1) return 0;
107 /*---------------------------------------------------*/
109 void* default_bzalloc ( void* opaque
, Int32 items
, Int32 size
)
111 return ExAllocatePool( PagedPool
, items
* size
);
115 void default_bzfree ( void* opaque
, void* addr
)
120 #ifndef BZ_DECOMPRESS_ONLY
122 /*---------------------------------------------------*/
124 void prepare_new_block ( EState
* s
)
129 s
->state_out_pos
= 0;
130 BZ_INITIALISE_CRC ( s
->blockCRC
);
131 for (i
= 0; i
< 256; i
++) s
->inUse
[i
] = False
;
136 /*---------------------------------------------------*/
138 void init_RL ( EState
* s
)
140 s
->state_in_ch
= 256;
146 Bool
isempty_RL ( EState
* s
)
148 if (s
->state_in_ch
< 256 && s
->state_in_len
> 0)
154 /*---------------------------------------------------*/
155 int BZ_API(BZ2_bzCompressInit
)
164 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
167 blockSize100k
< 1 || blockSize100k
> 9 ||
168 workFactor
< 0 || workFactor
> 250)
169 return BZ_PARAM_ERROR
;
171 if (workFactor
== 0) workFactor
= 30;
172 if (strm
->bzalloc
== NULL
) strm
->bzalloc
= default_bzalloc
;
173 if (strm
->bzfree
== NULL
) strm
->bzfree
= default_bzfree
;
175 s
= BZALLOC( sizeof(EState
) );
176 if (s
== NULL
) return BZ_MEM_ERROR
;
183 n
= 100000 * blockSize100k
;
184 s
->arr1
= BZALLOC( n
* sizeof(UInt32
) );
185 s
->arr2
= BZALLOC( (n
+BZ_N_OVERSHOOT
) * sizeof(UInt32
) );
186 s
->ftab
= BZALLOC( 65537 * sizeof(UInt32
) );
188 if (s
->arr1
== NULL
|| s
->arr2
== NULL
|| s
->ftab
== NULL
) {
189 if (s
->arr1
!= NULL
) BZFREE(s
->arr1
);
190 if (s
->arr2
!= NULL
) BZFREE(s
->arr2
);
191 if (s
->ftab
!= NULL
) BZFREE(s
->ftab
);
192 if (s
!= NULL
) BZFREE(s
);
197 s
->state
= BZ_S_INPUT
;
198 s
->mode
= BZ_M_RUNNING
;
200 s
->blockSize100k
= blockSize100k
;
201 s
->nblockMAX
= 100000 * blockSize100k
- 19;
202 s
->verbosity
= verbosity
;
203 s
->workFactor
= workFactor
;
205 s
->block
= (UChar
*)s
->arr2
;
206 s
->mtfv
= (UInt16
*)s
->arr1
;
208 s
->ptr
= (UInt32
*)s
->arr1
;
211 strm
->total_in_lo32
= 0;
212 strm
->total_in_hi32
= 0;
213 strm
->total_out_lo32
= 0;
214 strm
->total_out_hi32
= 0;
216 prepare_new_block ( s
);
221 /*---------------------------------------------------*/
223 void add_pair_to_block ( EState
* s
)
226 UChar ch
= (UChar
)(s
->state_in_ch
);
227 for (i
= 0; i
< s
->state_in_len
; i
++) {
228 BZ_UPDATE_CRC( s
->blockCRC
, ch
);
230 s
->inUse
[s
->state_in_ch
] = True
;
231 switch (s
->state_in_len
) {
233 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
236 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
237 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
240 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
241 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
242 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
245 s
->inUse
[s
->state_in_len
-4] = True
;
246 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
247 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
248 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
249 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
250 s
->block
[s
->nblock
] = ((UChar
)(s
->state_in_len
-4));
257 /*---------------------------------------------------*/
259 void flush_RL ( EState
* s
)
261 if (s
->state_in_ch
< 256) add_pair_to_block ( s
);
266 /*---------------------------------------------------*/
267 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
269 UInt32 zchh = (UInt32)(zchh0); \
270 /*-- fast track the common case --*/ \
271 if (zchh != zs->state_in_ch && \
272 zs->state_in_len == 1) { \
273 UChar ch = (UChar)(zs->state_in_ch); \
274 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
275 zs->inUse[zs->state_in_ch] = True; \
276 zs->block[zs->nblock] = (UChar)ch; \
278 zs->state_in_ch = zchh; \
281 /*-- general, uncommon cases --*/ \
282 if (zchh != zs->state_in_ch || \
283 zs->state_in_len == 255) { \
284 if (zs->state_in_ch < 256) \
285 add_pair_to_block ( zs ); \
286 zs->state_in_ch = zchh; \
287 zs->state_in_len = 1; \
289 zs->state_in_len++; \
294 /*---------------------------------------------------*/
296 Bool
copy_input_until_stop ( EState
* s
)
298 Bool progress_in
= False
;
300 if (s
->mode
== BZ_M_RUNNING
) {
302 /*-- fast track the common case --*/
304 /*-- block full? --*/
305 if (s
->nblock
>= s
->nblockMAX
) break;
307 if (s
->strm
->avail_in
== 0) break;
309 ADD_CHAR_TO_BLOCK ( s
, (UInt32
)(*((UChar
*)(s
->strm
->next_in
))) );
312 s
->strm
->total_in_lo32
++;
313 if (s
->strm
->total_in_lo32
== 0) s
->strm
->total_in_hi32
++;
318 /*-- general, uncommon case --*/
320 /*-- block full? --*/
321 if (s
->nblock
>= s
->nblockMAX
) break;
323 if (s
->strm
->avail_in
== 0) break;
324 /*-- flush/finish end? --*/
325 if (s
->avail_in_expect
== 0) break;
327 ADD_CHAR_TO_BLOCK ( s
, (UInt32
)(*((UChar
*)(s
->strm
->next_in
))) );
330 s
->strm
->total_in_lo32
++;
331 if (s
->strm
->total_in_lo32
== 0) s
->strm
->total_in_hi32
++;
332 s
->avail_in_expect
--;
339 /*---------------------------------------------------*/
341 Bool
copy_output_until_stop ( EState
* s
)
343 Bool progress_out
= False
;
347 /*-- no output space? --*/
348 if (s
->strm
->avail_out
== 0) break;
350 /*-- block done? --*/
351 if (s
->state_out_pos
>= s
->numZ
) break;
354 *(s
->strm
->next_out
) = s
->zbits
[s
->state_out_pos
];
356 s
->strm
->avail_out
--;
358 s
->strm
->total_out_lo32
++;
359 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
366 /*---------------------------------------------------*/
368 Bool
handle_compress ( bz_stream
* strm
)
370 Bool progress_in
= False
;
371 Bool progress_out
= False
;
372 EState
* s
= strm
->state
;
376 if (s
->state
== BZ_S_OUTPUT
) {
377 progress_out
|= copy_output_until_stop ( s
);
378 if (s
->state_out_pos
< s
->numZ
) break;
379 if (s
->mode
== BZ_M_FINISHING
&&
380 s
->avail_in_expect
== 0 &&
381 isempty_RL(s
)) break;
382 prepare_new_block ( s
);
383 s
->state
= BZ_S_INPUT
;
384 if (s
->mode
== BZ_M_FLUSHING
&&
385 s
->avail_in_expect
== 0 &&
386 isempty_RL(s
)) break;
389 if (s
->state
== BZ_S_INPUT
) {
390 progress_in
|= copy_input_until_stop ( s
);
391 if (s
->mode
!= BZ_M_RUNNING
&& s
->avail_in_expect
== 0) {
393 BZ2_compressBlock ( s
, (Bool
)(s
->mode
== BZ_M_FINISHING
) );
394 s
->state
= BZ_S_OUTPUT
;
397 if (s
->nblock
>= s
->nblockMAX
) {
398 BZ2_compressBlock ( s
, False
);
399 s
->state
= BZ_S_OUTPUT
;
402 if (s
->strm
->avail_in
== 0) {
409 return progress_in
|| progress_out
;
413 /*---------------------------------------------------*/
414 int BZ_API(BZ2_bzCompress
) ( bz_stream
*strm
, int action
)
418 if (strm
== NULL
) return BZ_PARAM_ERROR
;
420 if (s
== NULL
) return BZ_PARAM_ERROR
;
421 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
427 return BZ_SEQUENCE_ERROR
;
430 if (action
== BZ_RUN
) {
431 progress
= handle_compress ( strm
);
432 return progress
? BZ_RUN_OK
: BZ_PARAM_ERROR
;
435 if (action
== BZ_FLUSH
) {
436 s
->avail_in_expect
= strm
->avail_in
;
437 s
->mode
= BZ_M_FLUSHING
;
441 if (action
== BZ_FINISH
) {
442 s
->avail_in_expect
= strm
->avail_in
;
443 s
->mode
= BZ_M_FINISHING
;
447 return BZ_PARAM_ERROR
;
450 if (action
!= BZ_FLUSH
) return BZ_SEQUENCE_ERROR
;
451 if (s
->avail_in_expect
!= s
->strm
->avail_in
)
452 return BZ_SEQUENCE_ERROR
;
453 progress
= handle_compress ( strm
);
454 if (s
->avail_in_expect
> 0 || !isempty_RL(s
) ||
455 s
->state_out_pos
< s
->numZ
) return BZ_FLUSH_OK
;
456 s
->mode
= BZ_M_RUNNING
;
460 if (action
!= BZ_FINISH
) return BZ_SEQUENCE_ERROR
;
461 if (s
->avail_in_expect
!= s
->strm
->avail_in
)
462 return BZ_SEQUENCE_ERROR
;
463 progress
= handle_compress ( strm
);
464 if (!progress
) return BZ_SEQUENCE_ERROR
;
465 if (s
->avail_in_expect
> 0 || !isempty_RL(s
) ||
466 s
->state_out_pos
< s
->numZ
) return BZ_FINISH_OK
;
468 return BZ_STREAM_END
;
470 return BZ_OK
; /*--not reached--*/
474 /*---------------------------------------------------*/
475 int BZ_API(BZ2_bzCompressEnd
) ( bz_stream
*strm
)
478 if (strm
== NULL
) return BZ_PARAM_ERROR
;
480 if (s
== NULL
) return BZ_PARAM_ERROR
;
481 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
483 if (s
->arr1
!= NULL
) BZFREE(s
->arr1
);
484 if (s
->arr2
!= NULL
) BZFREE(s
->arr2
);
485 if (s
->ftab
!= NULL
) BZFREE(s
->ftab
);
493 #endif // BZ_DECOMPRESS_ONLY
495 /*---------------------------------------------------*/
496 /*--- Decompression stuff ---*/
497 /*---------------------------------------------------*/
499 /*---------------------------------------------------*/
500 int BZ_API(BZ2_bzDecompressInit
)
507 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
509 if (strm
== NULL
) return BZ_PARAM_ERROR
;
510 if (small
!= 0 && small
!= 1) return BZ_PARAM_ERROR
;
511 if (verbosity
< 0 || verbosity
> 4) return BZ_PARAM_ERROR
;
513 if (strm
->bzalloc
== NULL
) strm
->bzalloc
= default_bzalloc
;
514 if (strm
->bzfree
== NULL
) strm
->bzfree
= default_bzfree
;
516 s
= BZALLOC( sizeof(DState
) );
517 if (s
== NULL
) return BZ_MEM_ERROR
;
520 s
->state
= BZ_X_MAGIC_1
;
523 s
->calculatedCombinedCRC
= 0;
524 strm
->total_in_lo32
= 0;
525 strm
->total_in_hi32
= 0;
526 strm
->total_out_lo32
= 0;
527 strm
->total_out_hi32
= 0;
528 s
->smallDecompress
= (Bool
)small
;
533 s
->verbosity
= verbosity
;
538 #ifndef BZ_DECOMPRESS_ONLY
540 /*---------------------------------------------------*/
541 /* Return True iff data corruption is discovered.
542 Returns False if there is no problem.
545 Bool
unRLE_obuf_to_output_FAST ( DState
* s
)
549 if (s
->blockRandomised
) {
552 /* try to finish existing run */
554 if (s
->strm
->avail_out
== 0) return False
;
555 if (s
->state_out_len
== 0) break;
556 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
557 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
560 s
->strm
->avail_out
--;
561 s
->strm
->total_out_lo32
++;
562 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
565 /* can a new run be started? */
566 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
568 /* Only caused by corrupt data stream? */
569 if (s
->nblock_used
> s
->save_nblock
+1)
572 s
->state_out_len
= 1;
573 s
->state_out_ch
= s
->k0
;
574 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
575 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
576 if (s
->nblock_used
== s
->save_nblock
+1) continue;
577 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
579 s
->state_out_len
= 2;
580 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
581 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
582 if (s
->nblock_used
== s
->save_nblock
+1) continue;
583 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
585 s
->state_out_len
= 3;
586 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
587 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
588 if (s
->nblock_used
== s
->save_nblock
+1) continue;
589 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
591 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
592 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
593 s
->state_out_len
= ((Int32
)k1
) + 4;
594 BZ_GET_FAST(s
->k0
); BZ_RAND_UPD_MASK
;
595 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
601 UInt32 c_calculatedBlockCRC
= s
->calculatedBlockCRC
;
602 UChar c_state_out_ch
= s
->state_out_ch
;
603 Int32 c_state_out_len
= s
->state_out_len
;
604 Int32 c_nblock_used
= s
->nblock_used
;
606 UInt32
* c_tt
= s
->tt
;
607 UInt32 c_tPos
= s
->tPos
;
608 char* cs_next_out
= s
->strm
->next_out
;
609 unsigned int cs_avail_out
= s
->strm
->avail_out
;
610 Int32 ro_blockSize100k
= s
->blockSize100k
;
613 UInt32 avail_out_INIT
= cs_avail_out
;
614 Int32 s_save_nblockPP
= s
->save_nblock
+1;
615 unsigned int total_out_lo32_old
;
619 /* try to finish existing run */
620 if (c_state_out_len
> 0) {
622 if (cs_avail_out
== 0) goto return_notr
;
623 if (c_state_out_len
== 1) break;
624 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
625 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
630 s_state_out_len_eq_one
:
632 if (cs_avail_out
== 0) {
633 c_state_out_len
= 1; goto return_notr
;
635 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
636 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
641 /* Only caused by corrupt data stream? */
642 if (c_nblock_used
> s_save_nblockPP
)
645 /* can a new run be started? */
646 if (c_nblock_used
== s_save_nblockPP
) {
647 c_state_out_len
= 0; goto return_notr
;
649 c_state_out_ch
= c_k0
;
650 BZ_GET_FAST_C(k1
); c_nblock_used
++;
652 c_k0
= k1
; goto s_state_out_len_eq_one
;
654 if (c_nblock_used
== s_save_nblockPP
)
655 goto s_state_out_len_eq_one
;
658 BZ_GET_FAST_C(k1
); c_nblock_used
++;
659 if (c_nblock_used
== s_save_nblockPP
) continue;
660 if (k1
!= c_k0
) { c_k0
= k1
; continue; };
663 BZ_GET_FAST_C(k1
); c_nblock_used
++;
664 if (c_nblock_used
== s_save_nblockPP
) continue;
665 if (k1
!= c_k0
) { c_k0
= k1
; continue; };
667 BZ_GET_FAST_C(k1
); c_nblock_used
++;
668 c_state_out_len
= ((Int32
)k1
) + 4;
669 BZ_GET_FAST_C(c_k0
); c_nblock_used
++;
673 total_out_lo32_old
= s
->strm
->total_out_lo32
;
674 s
->strm
->total_out_lo32
+= (avail_out_INIT
- cs_avail_out
);
675 if (s
->strm
->total_out_lo32
< total_out_lo32_old
)
676 s
->strm
->total_out_hi32
++;
679 s
->calculatedBlockCRC
= c_calculatedBlockCRC
;
680 s
->state_out_ch
= c_state_out_ch
;
681 s
->state_out_len
= c_state_out_len
;
682 s
->nblock_used
= c_nblock_used
;
686 s
->strm
->next_out
= cs_next_out
;
687 s
->strm
->avail_out
= cs_avail_out
;
693 #endif // BZ_DECOMPRESS_ONLY
696 /*---------------------------------------------------*/
697 __inline__ Int32
BZ2_indexIntoF ( Int32 indx
, Int32
*cftab
)
703 mid
= (nb
+ na
) >> 1;
704 if (indx
>= cftab
[mid
]) nb
= mid
; else na
= mid
;
706 while (na
- nb
!= 1);
711 /*---------------------------------------------------*/
712 /* Return True iff data corruption is discovered.
713 Returns False if there is no problem.
716 Bool
unRLE_obuf_to_output_SMALL ( DState
* s
)
720 if (s
->blockRandomised
) {
723 /* try to finish existing run */
725 if (s
->strm
->avail_out
== 0) return False
;
726 if (s
->state_out_len
== 0) break;
727 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
728 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
731 s
->strm
->avail_out
--;
732 s
->strm
->total_out_lo32
++;
733 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
736 /* can a new run be started? */
737 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
739 /* Only caused by corrupt data stream? */
740 if (s
->nblock_used
> s
->save_nblock
+1)
743 s
->state_out_len
= 1;
744 s
->state_out_ch
= s
->k0
;
745 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
746 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
747 if (s
->nblock_used
== s
->save_nblock
+1) continue;
748 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
750 s
->state_out_len
= 2;
751 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
752 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
753 if (s
->nblock_used
== s
->save_nblock
+1) continue;
754 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
756 s
->state_out_len
= 3;
757 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
758 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
759 if (s
->nblock_used
== s
->save_nblock
+1) continue;
760 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
762 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
763 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
764 s
->state_out_len
= ((Int32
)k1
) + 4;
765 BZ_GET_SMALL(s
->k0
); BZ_RAND_UPD_MASK
;
766 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
772 /* try to finish existing run */
774 if (s
->strm
->avail_out
== 0) return False
;
775 if (s
->state_out_len
== 0) break;
776 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
777 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
780 s
->strm
->avail_out
--;
781 s
->strm
->total_out_lo32
++;
782 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
785 /* can a new run be started? */
786 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
788 /* Only caused by corrupt data stream? */
789 if (s
->nblock_used
> s
->save_nblock
+1)
792 s
->state_out_len
= 1;
793 s
->state_out_ch
= s
->k0
;
794 BZ_GET_SMALL(k1
); s
->nblock_used
++;
795 if (s
->nblock_used
== s
->save_nblock
+1) continue;
796 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
798 s
->state_out_len
= 2;
799 BZ_GET_SMALL(k1
); s
->nblock_used
++;
800 if (s
->nblock_used
== s
->save_nblock
+1) continue;
801 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
803 s
->state_out_len
= 3;
804 BZ_GET_SMALL(k1
); s
->nblock_used
++;
805 if (s
->nblock_used
== s
->save_nblock
+1) continue;
806 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
808 BZ_GET_SMALL(k1
); s
->nblock_used
++;
809 s
->state_out_len
= ((Int32
)k1
) + 4;
810 BZ_GET_SMALL(s
->k0
); s
->nblock_used
++;
817 /*---------------------------------------------------*/
818 int BZ_API(BZ2_bzDecompress
) ( bz_stream
*strm
)
822 if (strm
== NULL
) return BZ_PARAM_ERROR
;
824 if (s
== NULL
) return BZ_PARAM_ERROR
;
825 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
828 if (s
->state
== BZ_X_IDLE
) return BZ_SEQUENCE_ERROR
;
829 if (s
->state
== BZ_X_OUTPUT
) {
830 #ifndef BZ_DECOMPRESS_ONLY
831 if (s
->smallDecompress
)
832 corrupt
= unRLE_obuf_to_output_SMALL ( s
); else
833 corrupt
= unRLE_obuf_to_output_FAST ( s
);
834 if (corrupt
) return BZ_DATA_ERROR
;
836 corrupt
= unRLE_obuf_to_output_SMALL ( s
);
837 if (corrupt
) return BZ_DATA_ERROR
;
839 if (s
->nblock_used
== s
->save_nblock
+1 && s
->state_out_len
== 0) {
840 BZ_FINALISE_CRC ( s
->calculatedBlockCRC
);
841 if (s
->verbosity
>= 3)
842 VPrintf2 ( " {0x%08x, 0x%08x}", s
->storedBlockCRC
,
843 s
->calculatedBlockCRC
);
844 if (s
->verbosity
>= 2) VPrintf0 ( "]" );
845 if (s
->calculatedBlockCRC
!= s
->storedBlockCRC
)
846 return BZ_DATA_ERROR
;
847 s
->calculatedCombinedCRC
848 = (s
->calculatedCombinedCRC
<< 1) |
849 (s
->calculatedCombinedCRC
>> 31);
850 s
->calculatedCombinedCRC
^= s
->calculatedBlockCRC
;
851 s
->state
= BZ_X_BLKHDR_1
;
856 if (s
->state
>= BZ_X_MAGIC_1
) {
857 Int32 r
= BZ2_decompress ( s
);
858 if (r
== BZ_STREAM_END
) {
859 if (s
->verbosity
>= 3)
860 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
861 s
->storedCombinedCRC
, s
->calculatedCombinedCRC
);
862 if (s
->calculatedCombinedCRC
!= s
->storedCombinedCRC
)
863 return BZ_DATA_ERROR
;
866 if (s
->state
!= BZ_X_OUTPUT
) return r
;
872 return 0; /*NOTREACHED*/
876 /*---------------------------------------------------*/
877 int BZ_API(BZ2_bzDecompressEnd
) ( bz_stream
*strm
)
880 if (strm
== NULL
) return BZ_PARAM_ERROR
;
882 if (s
== NULL
) return BZ_PARAM_ERROR
;
883 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
885 if (s
->tt
!= NULL
) BZFREE(s
->tt
);
886 if (s
->ll16
!= NULL
) BZFREE(s
->ll16
);
887 if (s
->ll4
!= NULL
) BZFREE(s
->ll4
);
897 /*---------------------------------------------------*/
898 /*--- File I/O stuff ---*/
899 /*---------------------------------------------------*/
901 #define BZ_SETERR(eee) \
903 if (bzerror != NULL) *bzerror = eee; \
904 if (bzf != NULL) bzf->lastErr = eee; \
910 Char buf
[BZ_MAX_UNUSED
];
920 /*---------------------------------------------*/
921 static Bool
myfeof ( FILE* f
)
923 Int32 c
= fgetc ( f
);
924 if (c
== EOF
) return True
;
930 /*---------------------------------------------------*/
931 BZFILE
* BZ_API(BZ2_bzWriteOpen
)
944 (blockSize100k
< 1 || blockSize100k
> 9) ||
945 (workFactor
< 0 || workFactor
> 250) ||
946 (verbosity
< 0 || verbosity
> 4))
947 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
950 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
952 bzf
= malloc ( sizeof(bzFile
) );
954 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
957 bzf
->initialisedOk
= False
;
961 bzf
->strm
.bzalloc
= NULL
;
962 bzf
->strm
.bzfree
= NULL
;
963 bzf
->strm
.opaque
= NULL
;
965 if (workFactor
== 0) workFactor
= 30;
966 ret
= BZ2_bzCompressInit ( &(bzf
->strm
), blockSize100k
,
967 verbosity
, workFactor
);
969 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
971 bzf
->strm
.avail_in
= 0;
972 bzf
->initialisedOk
= True
;
978 /*---------------------------------------------------*/
979 void BZ_API(BZ2_bzWrite
)
986 bzFile
* bzf
= (bzFile
*)b
;
989 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
990 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
992 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
993 if (ferror(bzf
->handle
))
994 { BZ_SETERR(BZ_IO_ERROR
); return; };
997 { BZ_SETERR(BZ_OK
); return; };
999 bzf
->strm
.avail_in
= len
;
1000 bzf
->strm
.next_in
= buf
;
1003 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
1004 bzf
->strm
.next_out
= bzf
->buf
;
1005 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_RUN
);
1006 if (ret
!= BZ_RUN_OK
)
1007 { BZ_SETERR(ret
); return; };
1009 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
1010 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
1011 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
1013 if (n
!= n2
|| ferror(bzf
->handle
))
1014 { BZ_SETERR(BZ_IO_ERROR
); return; };
1017 if (bzf
->strm
.avail_in
== 0)
1018 { BZ_SETERR(BZ_OK
); return; };
1023 /*---------------------------------------------------*/
1024 void BZ_API(BZ2_bzWriteClose
)
1028 unsigned int* nbytes_in
,
1029 unsigned int* nbytes_out
)
1031 BZ2_bzWriteClose64 ( bzerror
, b
, abandon
,
1032 nbytes_in
, NULL
, nbytes_out
, NULL
);
1036 void BZ_API(BZ2_bzWriteClose64
)
1040 unsigned int* nbytes_in_lo32
,
1041 unsigned int* nbytes_in_hi32
,
1042 unsigned int* nbytes_out_lo32
,
1043 unsigned int* nbytes_out_hi32
)
1046 bzFile
* bzf
= (bzFile
*)b
;
1049 { BZ_SETERR(BZ_OK
); return; };
1050 if (!(bzf
->writing
))
1051 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1052 if (ferror(bzf
->handle
))
1053 { BZ_SETERR(BZ_IO_ERROR
); return; };
1055 if (nbytes_in_lo32
!= NULL
) *nbytes_in_lo32
= 0;
1056 if (nbytes_in_hi32
!= NULL
) *nbytes_in_hi32
= 0;
1057 if (nbytes_out_lo32
!= NULL
) *nbytes_out_lo32
= 0;
1058 if (nbytes_out_hi32
!= NULL
) *nbytes_out_hi32
= 0;
1060 if ((!abandon
) && bzf
->lastErr
== BZ_OK
) {
1062 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
1063 bzf
->strm
.next_out
= bzf
->buf
;
1064 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_FINISH
);
1065 if (ret
!= BZ_FINISH_OK
&& ret
!= BZ_STREAM_END
)
1066 { BZ_SETERR(ret
); return; };
1068 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
1069 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
1070 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
1072 if (n
!= n2
|| ferror(bzf
->handle
))
1073 { BZ_SETERR(BZ_IO_ERROR
); return; };
1076 if (ret
== BZ_STREAM_END
) break;
1080 if ( !abandon
&& !ferror ( bzf
->handle
) ) {
1081 fflush ( bzf
->handle
);
1082 if (ferror(bzf
->handle
))
1083 { BZ_SETERR(BZ_IO_ERROR
); return; };
1086 if (nbytes_in_lo32
!= NULL
)
1087 *nbytes_in_lo32
= bzf
->strm
.total_in_lo32
;
1088 if (nbytes_in_hi32
!= NULL
)
1089 *nbytes_in_hi32
= bzf
->strm
.total_in_hi32
;
1090 if (nbytes_out_lo32
!= NULL
)
1091 *nbytes_out_lo32
= bzf
->strm
.total_out_lo32
;
1092 if (nbytes_out_hi32
!= NULL
)
1093 *nbytes_out_hi32
= bzf
->strm
.total_out_hi32
;
1096 BZ2_bzCompressEnd ( &(bzf
->strm
) );
1101 /*---------------------------------------------------*/
1102 BZFILE
* BZ_API(BZ2_bzReadOpen
)
1116 (small
!= 0 && small
!= 1) ||
1117 (verbosity
< 0 || verbosity
> 4) ||
1118 (unused
== NULL
&& nUnused
!= 0) ||
1119 (unused
!= NULL
&& (nUnused
< 0 || nUnused
> BZ_MAX_UNUSED
)))
1120 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
1123 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
1125 bzf
= malloc ( sizeof(bzFile
) );
1127 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
1131 bzf
->initialisedOk
= False
;
1134 bzf
->writing
= False
;
1135 bzf
->strm
.bzalloc
= NULL
;
1136 bzf
->strm
.bzfree
= NULL
;
1137 bzf
->strm
.opaque
= NULL
;
1139 while (nUnused
> 0) {
1140 bzf
->buf
[bzf
->bufN
] = *((UChar
*)(unused
)); bzf
->bufN
++;
1141 unused
= ((void*)( 1 + ((UChar
*)(unused
)) ));
1145 ret
= BZ2_bzDecompressInit ( &(bzf
->strm
), verbosity
, small
);
1147 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
1149 bzf
->strm
.avail_in
= bzf
->bufN
;
1150 bzf
->strm
.next_in
= bzf
->buf
;
1152 bzf
->initialisedOk
= True
;
1157 /*---------------------------------------------------*/
1158 void BZ_API(BZ2_bzReadClose
) ( int *bzerror
, BZFILE
*b
)
1160 bzFile
* bzf
= (bzFile
*)b
;
1164 { BZ_SETERR(BZ_OK
); return; };
1167 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1169 if (bzf
->initialisedOk
)
1170 (void)BZ2_bzDecompressEnd ( &(bzf
->strm
) );
1175 /*---------------------------------------------------*/
1176 int BZ_API(BZ2_bzRead
)
1183 bzFile
* bzf
= (bzFile
*)b
;
1187 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
1188 { BZ_SETERR(BZ_PARAM_ERROR
); return 0; };
1191 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return 0; };
1194 { BZ_SETERR(BZ_OK
); return 0; };
1196 bzf
->strm
.avail_out
= len
;
1197 bzf
->strm
.next_out
= buf
;
1201 if (ferror(bzf
->handle
))
1202 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1204 if (bzf
->strm
.avail_in
== 0 && !myfeof(bzf
->handle
)) {
1205 n
= fread ( bzf
->buf
, sizeof(UChar
),
1206 BZ_MAX_UNUSED
, bzf
->handle
);
1207 if (ferror(bzf
->handle
))
1208 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1210 bzf
->strm
.avail_in
= bzf
->bufN
;
1211 bzf
->strm
.next_in
= bzf
->buf
;
1214 ret
= BZ2_bzDecompress ( &(bzf
->strm
) );
1216 if (ret
!= BZ_OK
&& ret
!= BZ_STREAM_END
)
1217 { BZ_SETERR(ret
); return 0; };
1219 if (ret
== BZ_OK
&& myfeof(bzf
->handle
) &&
1220 bzf
->strm
.avail_in
== 0 && bzf
->strm
.avail_out
> 0)
1221 { BZ_SETERR(BZ_UNEXPECTED_EOF
); return 0; };
1223 if (ret
== BZ_STREAM_END
)
1224 { BZ_SETERR(BZ_STREAM_END
);
1225 return len
- bzf
->strm
.avail_out
; };
1226 if (bzf
->strm
.avail_out
== 0)
1227 { BZ_SETERR(BZ_OK
); return len
; };
1231 return 0; /*not reached*/
1235 /*---------------------------------------------------*/
1236 void BZ_API(BZ2_bzReadGetUnused
)
1242 bzFile
* bzf
= (bzFile
*)b
;
1244 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1245 if (bzf
->lastErr
!= BZ_STREAM_END
)
1246 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1247 if (unused
== NULL
|| nUnused
== NULL
)
1248 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1251 *nUnused
= bzf
->strm
.avail_in
;
1252 *unused
= bzf
->strm
.next_in
;
1256 #ifndef BZ_DECOMPRESS_ONLY
1258 /*---------------------------------------------------*/
1259 /*--- Misc convenience stuff ---*/
1260 /*---------------------------------------------------*/
1262 /*---------------------------------------------------*/
1263 int BZ_API(BZ2_bzBuffToBuffCompress
)
1265 unsigned int* destLen
,
1267 unsigned int sourceLen
,
1275 if (dest
== NULL
|| destLen
== NULL
||
1277 blockSize100k
< 1 || blockSize100k
> 9 ||
1278 verbosity
< 0 || verbosity
> 4 ||
1279 workFactor
< 0 || workFactor
> 250)
1280 return BZ_PARAM_ERROR
;
1282 if (workFactor
== 0) workFactor
= 30;
1283 strm
.bzalloc
= NULL
;
1286 ret
= BZ2_bzCompressInit ( &strm
, blockSize100k
,
1287 verbosity
, workFactor
);
1288 if (ret
!= BZ_OK
) return ret
;
1290 strm
.next_in
= source
;
1291 strm
.next_out
= dest
;
1292 strm
.avail_in
= sourceLen
;
1293 strm
.avail_out
= *destLen
;
1295 ret
= BZ2_bzCompress ( &strm
, BZ_FINISH
);
1296 if (ret
== BZ_FINISH_OK
) goto output_overflow
;
1297 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1299 /* normal termination */
1300 *destLen
-= strm
.avail_out
;
1301 BZ2_bzCompressEnd ( &strm
);
1305 BZ2_bzCompressEnd ( &strm
);
1306 return BZ_OUTBUFF_FULL
;
1309 BZ2_bzCompressEnd ( &strm
);
1313 #endif // BZ_DECOMPRESS_0NLY
1315 /*---------------------------------------------------*/
1316 int BZ_API(BZ2_bzBuffToBuffDecompress
)
1318 unsigned int* destLen
,
1320 unsigned int sourceLen
,
1327 if (dest
== NULL
|| destLen
== NULL
||
1329 (small
!= 0 && small
!= 1) ||
1330 verbosity
< 0 || verbosity
> 4)
1331 return BZ_PARAM_ERROR
;
1333 strm
.bzalloc
= NULL
;
1336 ret
= BZ2_bzDecompressInit ( &strm
, verbosity
, small
);
1337 if (ret
!= BZ_OK
) return ret
;
1339 strm
.next_in
= source
;
1340 strm
.next_out
= dest
;
1341 strm
.avail_in
= sourceLen
;
1342 strm
.avail_out
= *destLen
;
1344 ret
= BZ2_bzDecompress ( &strm
);
1345 if (ret
== BZ_OK
) goto output_overflow_or_eof
;
1346 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1348 /* normal termination */
1349 *destLen
-= strm
.avail_out
;
1350 BZ2_bzDecompressEnd ( &strm
);
1353 output_overflow_or_eof
:
1354 if (strm
.avail_out
> 0) {
1355 BZ2_bzDecompressEnd ( &strm
);
1356 return BZ_UNEXPECTED_EOF
;
1358 BZ2_bzDecompressEnd ( &strm
);
1359 return BZ_OUTBUFF_FULL
;
1363 BZ2_bzDecompressEnd ( &strm
);
1368 /*---------------------------------------------------*/
1370 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1371 to support better zlib compatibility.
1372 This code is not _officially_ part of libbzip2 (yet);
1373 I haven't tested it, documented it, or considered the
1374 threading-safeness of it.
1375 If this code breaks, please contact both Yoshioka and me.
1377 /*---------------------------------------------------*/
1379 /*---------------------------------------------------*/
1381 return version like "0.9.5d, 4-Sept-1999".
1383 const char * BZ_API(BZ2_bzlibVersion
)(void)
1390 /*---------------------------------------------------*/
1392 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1395 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1397 # define SET_BINARY_MODE(file)
1400 BZFILE
* bzopen_or_bzdopen
1401 ( const char *path
, /* no use when bzdopen */
1402 int fd
, /* no use when bzdopen */
1404 int open_mode
) /* bzopen: 0, bzdopen:1 */
1407 char unused
[BZ_MAX_UNUSED
];
1408 int blockSize100k
= 9;
1410 char mode2
[10] = "";
1412 BZFILE
*bzfp
= NULL
;
1414 int workFactor
= 30;
1418 if (mode
== NULL
) return NULL
;
1426 smallMode
= 1; break;
1428 if (isdigit((int)(*mode
))) {
1429 blockSize100k
= *mode
-BZ_HDR_0
;
1434 strcat(mode2
, writing
? "w" : "r" );
1435 strcat(mode2
,"b"); /* binary mode */
1438 if (path
==NULL
|| strcmp(path
,"")==0) {
1439 fp
= (writing
? stdout
: stdin
);
1440 SET_BINARY_MODE(fp
);
1442 fp
= fopen(path
,mode2
);
1445 #ifdef BZ_STRICT_ANSI
1448 fp
= fdopen(fd
,mode2
);
1451 if (fp
== NULL
) return NULL
;
1454 /* Guard against total chaos and anarchy -- JRS */
1455 if (blockSize100k
< 1) blockSize100k
= 1;
1456 if (blockSize100k
> 9) blockSize100k
= 9;
1457 bzfp
= BZ2_bzWriteOpen(&bzerr
,fp
,blockSize100k
,
1458 verbosity
,workFactor
);
1460 bzfp
= BZ2_bzReadOpen(&bzerr
,fp
,verbosity
,smallMode
,
1464 if (fp
!= stdin
&& fp
!= stdout
) fclose(fp
);
1471 /*---------------------------------------------------*/
1473 open file for read or write.
1474 ex) bzopen("file","w9")
1475 case path="" or NULL => use stdin or stdout.
1477 BZFILE
* BZ_API(BZ2_bzopen
)
1481 return bzopen_or_bzdopen(path
,-1,mode
,/*bzopen*/0);
1485 /*---------------------------------------------------*/
1486 BZFILE
* BZ_API(BZ2_bzdopen
)
1490 return bzopen_or_bzdopen(NULL
,fd
,mode
,/*bzdopen*/1);
1494 /*---------------------------------------------------*/
1495 int BZ_API(BZ2_bzread
) (BZFILE
* b
, void* buf
, int len
)
1498 if (((bzFile
*)b
)->lastErr
== BZ_STREAM_END
) return 0;
1499 nread
= BZ2_bzRead(&bzerr
,b
,buf
,len
);
1500 if (bzerr
== BZ_OK
|| bzerr
== BZ_STREAM_END
) {
1508 /*---------------------------------------------------*/
1509 int BZ_API(BZ2_bzwrite
) (BZFILE
* b
, void* buf
, int len
)
1513 BZ2_bzWrite(&bzerr
,b
,buf
,len
);
1522 /*---------------------------------------------------*/
1523 int BZ_API(BZ2_bzflush
) (BZFILE
*b
)
1525 /* do nothing now... */
1530 /*---------------------------------------------------*/
1531 void BZ_API(BZ2_bzclose
) (BZFILE
* b
)
1536 if (b
==NULL
) {return;}
1537 fp
= ((bzFile
*)b
)->handle
;
1538 if(((bzFile
*)b
)->writing
){
1539 BZ2_bzWriteClose(&bzerr
,b
,0,NULL
,NULL
);
1541 BZ2_bzWriteClose(NULL
,b
,1,NULL
,NULL
);
1544 BZ2_bzReadClose(&bzerr
,b
);
1546 if(fp
!=stdin
&& fp
!=stdout
){
1552 /*---------------------------------------------------*/
1554 return last error code
1556 static const char *bzerrorstrings
[] = {
1567 ,"???" /* for future */
1568 ,"???" /* for future */
1569 ,"???" /* for future */
1570 ,"???" /* for future */
1571 ,"???" /* for future */
1572 ,"???" /* for future */
1576 const char * BZ_API(BZ2_bzerror
) (BZFILE
*b
, int *errnum
)
1578 int err
= ((bzFile
*)b
)->lastErr
;
1582 return bzerrorstrings
[err
*-1];
1587 /*-------------------------------------------------------------*/
1588 /*--- end bzlib.c ---*/
1589 /*-------------------------------------------------------------*/