2 /*-------------------------------------------------------------*/
3 /*--- Library top-level functions. ---*/
5 /*-------------------------------------------------------------*/
8 This file is a part of bzip2 and/or libbzip2, a program and
9 library for lossless, block-sorting data compression.
11 Copyright (C) 1996-2000 Julian R Seward. All rights reserved.
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
20 2. The origin of this software must not be misrepresented; you must
21 not claim that you wrote the original software. If you use this
22 software in a product, an acknowledgment in the product
23 documentation would be appreciated but is not required.
25 3. Altered source versions must be plainly marked as such, and must
26 not be misrepresented as being the original software.
28 4. The name of the author may not be used to endorse or promote
29 products derived from this software without specific prior written
32 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
33 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
36 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
40 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 Julian Seward, Cambridge, UK.
46 bzip2/libbzip2 version 1.0 of 21 March 2000
48 This program is based on (at least) the work of:
58 For more information on these sources, see the manual.
64 0.9.0 -- original version.
66 0.9.0a/b -- no changes in this file.
69 * made zero-length BZ_FLUSH work correctly in bzCompress().
70 * fixed bzWrite/bzRead to ignore zero-length requests.
71 * fixed bzread to correctly handle read requests after EOF.
72 * wrong parameter order in call to bzDecompressInit in
73 bzBuffToBuffDecompress. Fixed.
76 #ifdef BZ_DECOMPRESS_ONLY
84 #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, 21 March 2000.\n\n",
113 /*---------------------------------------------------*/
115 int bz_config_ok ( void )
117 if (sizeof(int) != 4) return 0;
118 if (sizeof(short) != 2) return 0;
119 if (sizeof(char) != 1) return 0;
123 /*---------------------------------------------------*/
125 void* default_bzalloc ( void* opaque
, Int32 items
, Int32 size
)
127 return ExAllocatePool( PagedPool
, items
* size
);
131 void default_bzfree ( void* opaque
, void* addr
)
136 #ifndef BZ_DECOMPRESS_ONLY
138 /*---------------------------------------------------*/
140 void prepare_new_block ( EState
* s
)
145 s
->state_out_pos
= 0;
146 BZ_INITIALISE_CRC ( s
->blockCRC
);
147 for (i
= 0; i
< 256; i
++) s
->inUse
[i
] = False
;
152 /*---------------------------------------------------*/
154 void init_RL ( EState
* s
)
156 s
->state_in_ch
= 256;
162 Bool
isempty_RL ( EState
* s
)
164 if (s
->state_in_ch
< 256 && s
->state_in_len
> 0)
170 /*---------------------------------------------------*/
171 int BZ_API(BZ2_bzCompressInit
)
180 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
183 blockSize100k
< 1 || blockSize100k
> 9 ||
184 workFactor
< 0 || workFactor
> 250)
185 return BZ_PARAM_ERROR
;
187 if (workFactor
== 0) workFactor
= 30;
188 if (strm
->bzalloc
== NULL
) strm
->bzalloc
= default_bzalloc
;
189 if (strm
->bzfree
== NULL
) strm
->bzfree
= default_bzfree
;
191 s
= BZALLOC( sizeof(EState
) );
192 if (s
== NULL
) return BZ_MEM_ERROR
;
199 n
= 100000 * blockSize100k
;
200 s
->arr1
= BZALLOC( n
* sizeof(UInt32
) );
201 s
->arr2
= BZALLOC( (n
+BZ_N_OVERSHOOT
) * sizeof(UInt32
) );
202 s
->ftab
= BZALLOC( 65537 * sizeof(UInt32
) );
204 if (s
->arr1
== NULL
|| s
->arr2
== NULL
|| s
->ftab
== NULL
) {
205 if (s
->arr1
!= NULL
) BZFREE(s
->arr1
);
206 if (s
->arr2
!= NULL
) BZFREE(s
->arr2
);
207 if (s
->ftab
!= NULL
) BZFREE(s
->ftab
);
208 if (s
!= NULL
) BZFREE(s
);
213 s
->state
= BZ_S_INPUT
;
214 s
->mode
= BZ_M_RUNNING
;
216 s
->blockSize100k
= blockSize100k
;
217 s
->nblockMAX
= 100000 * blockSize100k
- 19;
218 s
->verbosity
= verbosity
;
219 s
->workFactor
= workFactor
;
221 s
->block
= (UChar
*)s
->arr2
;
222 s
->mtfv
= (UInt16
*)s
->arr1
;
224 s
->ptr
= (UInt32
*)s
->arr1
;
227 strm
->total_in_lo32
= 0;
228 strm
->total_in_hi32
= 0;
229 strm
->total_out_lo32
= 0;
230 strm
->total_out_hi32
= 0;
232 prepare_new_block ( s
);
237 /*---------------------------------------------------*/
239 void add_pair_to_block ( EState
* s
)
242 UChar ch
= (UChar
)(s
->state_in_ch
);
243 for (i
= 0; i
< s
->state_in_len
; i
++) {
244 BZ_UPDATE_CRC( s
->blockCRC
, ch
);
246 s
->inUse
[s
->state_in_ch
] = True
;
247 switch (s
->state_in_len
) {
249 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
252 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
253 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
256 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
257 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
258 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
261 s
->inUse
[s
->state_in_len
-4] = True
;
262 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
263 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
264 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
265 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
266 s
->block
[s
->nblock
] = ((UChar
)(s
->state_in_len
-4));
273 /*---------------------------------------------------*/
275 void flush_RL ( EState
* s
)
277 if (s
->state_in_ch
< 256) add_pair_to_block ( s
);
282 /*---------------------------------------------------*/
283 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
285 UInt32 zchh = (UInt32)(zchh0); \
286 /*-- fast track the common case --*/ \
287 if (zchh != zs->state_in_ch && \
288 zs->state_in_len == 1) { \
289 UChar ch = (UChar)(zs->state_in_ch); \
290 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
291 zs->inUse[zs->state_in_ch] = True; \
292 zs->block[zs->nblock] = (UChar)ch; \
294 zs->state_in_ch = zchh; \
297 /*-- general, uncommon cases --*/ \
298 if (zchh != zs->state_in_ch || \
299 zs->state_in_len == 255) { \
300 if (zs->state_in_ch < 256) \
301 add_pair_to_block ( zs ); \
302 zs->state_in_ch = zchh; \
303 zs->state_in_len = 1; \
305 zs->state_in_len++; \
310 /*---------------------------------------------------*/
312 Bool
copy_input_until_stop ( EState
* s
)
314 Bool progress_in
= False
;
316 if (s
->mode
== BZ_M_RUNNING
) {
318 /*-- fast track the common case --*/
320 /*-- block full? --*/
321 if (s
->nblock
>= s
->nblockMAX
) break;
323 if (s
->strm
->avail_in
== 0) break;
325 ADD_CHAR_TO_BLOCK ( s
, (UInt32
)(*((UChar
*)(s
->strm
->next_in
))) );
328 s
->strm
->total_in_lo32
++;
329 if (s
->strm
->total_in_lo32
== 0) s
->strm
->total_in_hi32
++;
334 /*-- general, uncommon case --*/
336 /*-- block full? --*/
337 if (s
->nblock
>= s
->nblockMAX
) break;
339 if (s
->strm
->avail_in
== 0) break;
340 /*-- flush/finish end? --*/
341 if (s
->avail_in_expect
== 0) break;
343 ADD_CHAR_TO_BLOCK ( s
, (UInt32
)(*((UChar
*)(s
->strm
->next_in
))) );
346 s
->strm
->total_in_lo32
++;
347 if (s
->strm
->total_in_lo32
== 0) s
->strm
->total_in_hi32
++;
348 s
->avail_in_expect
--;
355 /*---------------------------------------------------*/
357 Bool
copy_output_until_stop ( EState
* s
)
359 Bool progress_out
= False
;
363 /*-- no output space? --*/
364 if (s
->strm
->avail_out
== 0) break;
366 /*-- block done? --*/
367 if (s
->state_out_pos
>= s
->numZ
) break;
370 *(s
->strm
->next_out
) = s
->zbits
[s
->state_out_pos
];
372 s
->strm
->avail_out
--;
374 s
->strm
->total_out_lo32
++;
375 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
382 /*---------------------------------------------------*/
384 Bool
handle_compress ( bz_stream
* strm
)
386 Bool progress_in
= False
;
387 Bool progress_out
= False
;
388 EState
* s
= strm
->state
;
392 if (s
->state
== BZ_S_OUTPUT
) {
393 progress_out
|= copy_output_until_stop ( s
);
394 if (s
->state_out_pos
< s
->numZ
) break;
395 if (s
->mode
== BZ_M_FINISHING
&&
396 s
->avail_in_expect
== 0 &&
397 isempty_RL(s
)) break;
398 prepare_new_block ( s
);
399 s
->state
= BZ_S_INPUT
;
400 if (s
->mode
== BZ_M_FLUSHING
&&
401 s
->avail_in_expect
== 0 &&
402 isempty_RL(s
)) break;
405 if (s
->state
== BZ_S_INPUT
) {
406 progress_in
|= copy_input_until_stop ( s
);
407 if (s
->mode
!= BZ_M_RUNNING
&& s
->avail_in_expect
== 0) {
409 BZ2_compressBlock ( s
, (Bool
)(s
->mode
== BZ_M_FINISHING
) );
410 s
->state
= BZ_S_OUTPUT
;
413 if (s
->nblock
>= s
->nblockMAX
) {
414 BZ2_compressBlock ( s
, False
);
415 s
->state
= BZ_S_OUTPUT
;
418 if (s
->strm
->avail_in
== 0) {
425 return progress_in
|| progress_out
;
429 /*---------------------------------------------------*/
430 int BZ_API(BZ2_bzCompress
) ( bz_stream
*strm
, int action
)
434 if (strm
== NULL
) return BZ_PARAM_ERROR
;
436 if (s
== NULL
) return BZ_PARAM_ERROR
;
437 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
443 return BZ_SEQUENCE_ERROR
;
446 if (action
== BZ_RUN
) {
447 progress
= handle_compress ( strm
);
448 return progress
? BZ_RUN_OK
: BZ_PARAM_ERROR
;
451 if (action
== BZ_FLUSH
) {
452 s
->avail_in_expect
= strm
->avail_in
;
453 s
->mode
= BZ_M_FLUSHING
;
457 if (action
== BZ_FINISH
) {
458 s
->avail_in_expect
= strm
->avail_in
;
459 s
->mode
= BZ_M_FINISHING
;
463 return BZ_PARAM_ERROR
;
466 if (action
!= BZ_FLUSH
) return BZ_SEQUENCE_ERROR
;
467 if (s
->avail_in_expect
!= s
->strm
->avail_in
)
468 return BZ_SEQUENCE_ERROR
;
469 progress
= handle_compress ( strm
);
470 if (s
->avail_in_expect
> 0 || !isempty_RL(s
) ||
471 s
->state_out_pos
< s
->numZ
) return BZ_FLUSH_OK
;
472 s
->mode
= BZ_M_RUNNING
;
476 if (action
!= BZ_FINISH
) return BZ_SEQUENCE_ERROR
;
477 if (s
->avail_in_expect
!= s
->strm
->avail_in
)
478 return BZ_SEQUENCE_ERROR
;
479 progress
= handle_compress ( strm
);
480 if (!progress
) return BZ_SEQUENCE_ERROR
;
481 if (s
->avail_in_expect
> 0 || !isempty_RL(s
) ||
482 s
->state_out_pos
< s
->numZ
) return BZ_FINISH_OK
;
484 return BZ_STREAM_END
;
486 return BZ_OK
; /*--not reached--*/
490 /*---------------------------------------------------*/
491 int BZ_API(BZ2_bzCompressEnd
) ( bz_stream
*strm
)
494 if (strm
== NULL
) return BZ_PARAM_ERROR
;
496 if (s
== NULL
) return BZ_PARAM_ERROR
;
497 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
499 if (s
->arr1
!= NULL
) BZFREE(s
->arr1
);
500 if (s
->arr2
!= NULL
) BZFREE(s
->arr2
);
501 if (s
->ftab
!= NULL
) BZFREE(s
->ftab
);
509 #endif // BZ_DECOMPRESS_ONLY
511 /*---------------------------------------------------*/
512 /*--- Decompression stuff ---*/
513 /*---------------------------------------------------*/
515 /*---------------------------------------------------*/
516 int BZ_API(BZ2_bzDecompressInit
)
523 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
525 if (strm
== NULL
) return BZ_PARAM_ERROR
;
526 if (small
!= 0 && small
!= 1) return BZ_PARAM_ERROR
;
527 if (verbosity
< 0 || verbosity
> 4) return BZ_PARAM_ERROR
;
529 if (strm
->bzalloc
== NULL
) strm
->bzalloc
= default_bzalloc
;
530 if (strm
->bzfree
== NULL
) strm
->bzfree
= default_bzfree
;
532 s
= BZALLOC( sizeof(DState
) );
533 if (s
== NULL
) return BZ_MEM_ERROR
;
536 s
->state
= BZ_X_MAGIC_1
;
539 s
->calculatedCombinedCRC
= 0;
540 strm
->total_in_lo32
= 0;
541 strm
->total_in_hi32
= 0;
542 strm
->total_out_lo32
= 0;
543 strm
->total_out_hi32
= 0;
544 s
->smallDecompress
= (Bool
)small
;
549 s
->verbosity
= verbosity
;
554 #ifndef BZ_DECOMPRESS_ONLY
556 /*---------------------------------------------------*/
558 void unRLE_obuf_to_output_FAST ( DState
* s
)
562 if (s
->blockRandomised
) {
565 /* try to finish existing run */
567 if (s
->strm
->avail_out
== 0) return;
568 if (s
->state_out_len
== 0) break;
569 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
570 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
573 s
->strm
->avail_out
--;
574 s
->strm
->total_out_lo32
++;
575 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
578 /* can a new run be started? */
579 if (s
->nblock_used
== s
->save_nblock
+1) return;
582 s
->state_out_len
= 1;
583 s
->state_out_ch
= s
->k0
;
584 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
585 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
586 if (s
->nblock_used
== s
->save_nblock
+1) continue;
587 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
589 s
->state_out_len
= 2;
590 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
591 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
592 if (s
->nblock_used
== s
->save_nblock
+1) continue;
593 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
595 s
->state_out_len
= 3;
596 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
597 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
598 if (s
->nblock_used
== s
->save_nblock
+1) continue;
599 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
601 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
602 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
603 s
->state_out_len
= ((Int32
)k1
) + 4;
604 BZ_GET_FAST(s
->k0
); BZ_RAND_UPD_MASK
;
605 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
611 UInt32 c_calculatedBlockCRC
= s
->calculatedBlockCRC
;
612 UChar c_state_out_ch
= s
->state_out_ch
;
613 Int32 c_state_out_len
= s
->state_out_len
;
614 Int32 c_nblock_used
= s
->nblock_used
;
616 UInt32
* c_tt
= s
->tt
;
617 UInt32 c_tPos
= s
->tPos
;
618 char* cs_next_out
= s
->strm
->next_out
;
619 unsigned int cs_avail_out
= s
->strm
->avail_out
;
622 UInt32 avail_out_INIT
= cs_avail_out
;
623 Int32 s_save_nblockPP
= s
->save_nblock
+1;
624 unsigned int total_out_lo32_old
;
628 /* try to finish existing run */
629 if (c_state_out_len
> 0) {
631 if (cs_avail_out
== 0) goto return_notr
;
632 if (c_state_out_len
== 1) break;
633 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
634 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
639 s_state_out_len_eq_one
:
641 if (cs_avail_out
== 0) {
642 c_state_out_len
= 1; goto return_notr
;
644 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
645 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
650 /* can a new run be started? */
651 if (c_nblock_used
== s_save_nblockPP
) {
652 c_state_out_len
= 0; goto return_notr
;
654 c_state_out_ch
= c_k0
;
655 BZ_GET_FAST_C(k1
); c_nblock_used
++;
657 c_k0
= k1
; goto s_state_out_len_eq_one
;
659 if (c_nblock_used
== s_save_nblockPP
)
660 goto s_state_out_len_eq_one
;
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; };
668 BZ_GET_FAST_C(k1
); c_nblock_used
++;
669 if (c_nblock_used
== s_save_nblockPP
) continue;
670 if (k1
!= c_k0
) { c_k0
= k1
; continue; };
672 BZ_GET_FAST_C(k1
); c_nblock_used
++;
673 c_state_out_len
= ((Int32
)k1
) + 4;
674 BZ_GET_FAST_C(c_k0
); c_nblock_used
++;
678 total_out_lo32_old
= s
->strm
->total_out_lo32
;
679 s
->strm
->total_out_lo32
+= (avail_out_INIT
- cs_avail_out
);
680 if (s
->strm
->total_out_lo32
< total_out_lo32_old
)
681 s
->strm
->total_out_hi32
++;
684 s
->calculatedBlockCRC
= c_calculatedBlockCRC
;
685 s
->state_out_ch
= c_state_out_ch
;
686 s
->state_out_len
= c_state_out_len
;
687 s
->nblock_used
= c_nblock_used
;
691 s
->strm
->next_out
= cs_next_out
;
692 s
->strm
->avail_out
= cs_avail_out
;
697 #endif // BZ_DECOMPRESS_ONLY
699 /*---------------------------------------------------*/
700 __inline__ Int32
BZ2_indexIntoF ( Int32 indx
, Int32
*cftab
)
706 mid
= (nb
+ na
) >> 1;
707 if (indx
>= cftab
[mid
]) nb
= mid
; else na
= mid
;
709 while (na
- nb
!= 1);
713 /*---------------------------------------------------*/
715 void unRLE_obuf_to_output_SMALL ( DState
* s
)
719 if (s
->blockRandomised
) {
722 /* try to finish existing run */
724 if (s
->strm
->avail_out
== 0) return;
725 if (s
->state_out_len
== 0) break;
726 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
727 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
730 s
->strm
->avail_out
--;
731 s
->strm
->total_out_lo32
++;
732 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
735 /* can a new run be started? */
736 if (s
->nblock_used
== s
->save_nblock
+1) return;
739 s
->state_out_len
= 1;
740 s
->state_out_ch
= s
->k0
;
741 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
742 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
743 if (s
->nblock_used
== s
->save_nblock
+1) continue;
744 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
746 s
->state_out_len
= 2;
747 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
748 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
749 if (s
->nblock_used
== s
->save_nblock
+1) continue;
750 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
752 s
->state_out_len
= 3;
753 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
754 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
755 if (s
->nblock_used
== s
->save_nblock
+1) continue;
756 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
758 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
759 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
760 s
->state_out_len
= ((Int32
)k1
) + 4;
761 BZ_GET_SMALL(s
->k0
); BZ_RAND_UPD_MASK
;
762 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
768 /* try to finish existing run */
770 if (s
->strm
->avail_out
== 0) return;
771 if (s
->state_out_len
== 0) break;
772 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
773 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
776 s
->strm
->avail_out
--;
777 s
->strm
->total_out_lo32
++;
778 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
781 /* can a new run be started? */
782 if (s
->nblock_used
== s
->save_nblock
+1) return;
784 s
->state_out_len
= 1;
785 s
->state_out_ch
= s
->k0
;
786 BZ_GET_SMALL(k1
); s
->nblock_used
++;
787 if (s
->nblock_used
== s
->save_nblock
+1) continue;
788 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
790 s
->state_out_len
= 2;
791 BZ_GET_SMALL(k1
); s
->nblock_used
++;
792 if (s
->nblock_used
== s
->save_nblock
+1) continue;
793 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
795 s
->state_out_len
= 3;
796 BZ_GET_SMALL(k1
); s
->nblock_used
++;
797 if (s
->nblock_used
== s
->save_nblock
+1) continue;
798 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
800 BZ_GET_SMALL(k1
); s
->nblock_used
++;
801 s
->state_out_len
= ((Int32
)k1
) + 4;
802 BZ_GET_SMALL(s
->k0
); s
->nblock_used
++;
808 /*---------------------------------------------------*/
809 int BZ_API(BZ2_bzDecompress
) ( bz_stream
*strm
)
812 if (strm
== NULL
) return BZ_PARAM_ERROR
;
814 if (s
== NULL
) return BZ_PARAM_ERROR
;
815 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
818 if (s
->state
== BZ_X_IDLE
) return BZ_SEQUENCE_ERROR
;
819 if (s
->state
== BZ_X_OUTPUT
) {
820 #ifndef BZ_DECOMPRESS_ONLY
821 if (s
->smallDecompress
)
822 unRLE_obuf_to_output_SMALL ( s
); else
823 unRLE_obuf_to_output_FAST ( s
);
825 unRLE_obuf_to_output_SMALL ( s
);
827 if (s
->nblock_used
== s
->save_nblock
+1 && s
->state_out_len
== 0) {
828 BZ_FINALISE_CRC ( s
->calculatedBlockCRC
);
829 if (s
->verbosity
>= 3)
830 VPrintf2 ( " {0x%x, 0x%x}", s
->storedBlockCRC
,
831 s
->calculatedBlockCRC
);
832 if (s
->verbosity
>= 2) VPrintf0 ( "]" );
833 if (s
->calculatedBlockCRC
!= s
->storedBlockCRC
)
834 return BZ_DATA_ERROR
;
835 s
->calculatedCombinedCRC
836 = (s
->calculatedCombinedCRC
<< 1) |
837 (s
->calculatedCombinedCRC
>> 31);
838 s
->calculatedCombinedCRC
^= s
->calculatedBlockCRC
;
839 s
->state
= BZ_X_BLKHDR_1
;
844 if (s
->state
>= BZ_X_MAGIC_1
) {
845 Int32 r
= BZ2_decompress ( s
);
846 if (r
== BZ_STREAM_END
) {
847 if (s
->verbosity
>= 3)
848 VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x",
849 s
->storedCombinedCRC
, s
->calculatedCombinedCRC
);
850 if (s
->calculatedCombinedCRC
!= s
->storedCombinedCRC
)
851 return BZ_DATA_ERROR
;
854 if (s
->state
!= BZ_X_OUTPUT
) return r
;
860 return 0; /*NOTREACHED*/
864 /*---------------------------------------------------*/
865 int BZ_API(BZ2_bzDecompressEnd
) ( bz_stream
*strm
)
868 if (strm
== NULL
) return BZ_PARAM_ERROR
;
870 if (s
== NULL
) return BZ_PARAM_ERROR
;
871 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
873 if (s
->tt
!= NULL
) BZFREE(s
->tt
);
874 if (s
->ll16
!= NULL
) BZFREE(s
->ll16
);
875 if (s
->ll4
!= NULL
) BZFREE(s
->ll4
);
885 /*---------------------------------------------------*/
886 /*--- File I/O stuff ---*/
887 /*---------------------------------------------------*/
889 #define BZ_SETERR(eee) \
891 if (bzerror != NULL) *bzerror = eee; \
892 if (bzf != NULL) bzf->lastErr = eee; \
898 Char buf
[BZ_MAX_UNUSED
];
908 /*---------------------------------------------*/
909 static Bool
myfeof ( FILE* f
)
911 Int32 c
= fgetc ( f
);
912 if (c
== EOF
) return True
;
918 /*---------------------------------------------------*/
919 BZFILE
* BZ_API(BZ2_bzWriteOpen
)
932 (blockSize100k
< 1 || blockSize100k
> 9) ||
933 (workFactor
< 0 || workFactor
> 250) ||
934 (verbosity
< 0 || verbosity
> 4))
935 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
938 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
940 bzf
= malloc ( sizeof(bzFile
) );
942 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
945 bzf
->initialisedOk
= False
;
949 bzf
->strm
.bzalloc
= NULL
;
950 bzf
->strm
.bzfree
= NULL
;
951 bzf
->strm
.opaque
= NULL
;
953 if (workFactor
== 0) workFactor
= 30;
954 ret
= BZ2_bzCompressInit ( &(bzf
->strm
), blockSize100k
,
955 verbosity
, workFactor
);
957 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
959 bzf
->strm
.avail_in
= 0;
960 bzf
->initialisedOk
= True
;
966 /*---------------------------------------------------*/
967 void BZ_API(BZ2_bzWrite
)
974 bzFile
* bzf
= (bzFile
*)b
;
977 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
978 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
980 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
981 if (ferror(bzf
->handle
))
982 { BZ_SETERR(BZ_IO_ERROR
); return; };
985 { BZ_SETERR(BZ_OK
); return; };
987 bzf
->strm
.avail_in
= len
;
988 bzf
->strm
.next_in
= buf
;
991 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
992 bzf
->strm
.next_out
= bzf
->buf
;
993 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_RUN
);
994 if (ret
!= BZ_RUN_OK
)
995 { BZ_SETERR(ret
); return; };
997 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
998 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
999 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
1001 if (n
!= n2
|| ferror(bzf
->handle
))
1002 { BZ_SETERR(BZ_IO_ERROR
); return; };
1005 if (bzf
->strm
.avail_in
== 0)
1006 { BZ_SETERR(BZ_OK
); return; };
1011 /*---------------------------------------------------*/
1012 void BZ_API(BZ2_bzWriteClose
)
1016 unsigned int* nbytes_in
,
1017 unsigned int* nbytes_out
)
1019 BZ2_bzWriteClose64 ( bzerror
, b
, abandon
,
1020 nbytes_in
, NULL
, nbytes_out
, NULL
);
1024 void BZ_API(BZ2_bzWriteClose64
)
1028 unsigned int* nbytes_in_lo32
,
1029 unsigned int* nbytes_in_hi32
,
1030 unsigned int* nbytes_out_lo32
,
1031 unsigned int* nbytes_out_hi32
)
1034 bzFile
* bzf
= (bzFile
*)b
;
1037 { BZ_SETERR(BZ_OK
); return; };
1038 if (!(bzf
->writing
))
1039 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1040 if (ferror(bzf
->handle
))
1041 { BZ_SETERR(BZ_IO_ERROR
); return; };
1043 if (nbytes_in_lo32
!= NULL
) *nbytes_in_lo32
= 0;
1044 if (nbytes_in_hi32
!= NULL
) *nbytes_in_hi32
= 0;
1045 if (nbytes_out_lo32
!= NULL
) *nbytes_out_lo32
= 0;
1046 if (nbytes_out_hi32
!= NULL
) *nbytes_out_hi32
= 0;
1048 if ((!abandon
) && bzf
->lastErr
== BZ_OK
) {
1050 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
1051 bzf
->strm
.next_out
= bzf
->buf
;
1052 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_FINISH
);
1053 if (ret
!= BZ_FINISH_OK
&& ret
!= BZ_STREAM_END
)
1054 { BZ_SETERR(ret
); return; };
1056 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
1057 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
1058 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
1060 if (n
!= n2
|| ferror(bzf
->handle
))
1061 { BZ_SETERR(BZ_IO_ERROR
); return; };
1064 if (ret
== BZ_STREAM_END
) break;
1068 if ( !abandon
&& !ferror ( bzf
->handle
) ) {
1069 fflush ( bzf
->handle
);
1070 if (ferror(bzf
->handle
))
1071 { BZ_SETERR(BZ_IO_ERROR
); return; };
1074 if (nbytes_in_lo32
!= NULL
)
1075 *nbytes_in_lo32
= bzf
->strm
.total_in_lo32
;
1076 if (nbytes_in_hi32
!= NULL
)
1077 *nbytes_in_hi32
= bzf
->strm
.total_in_hi32
;
1078 if (nbytes_out_lo32
!= NULL
)
1079 *nbytes_out_lo32
= bzf
->strm
.total_out_lo32
;
1080 if (nbytes_out_hi32
!= NULL
)
1081 *nbytes_out_hi32
= bzf
->strm
.total_out_hi32
;
1084 BZ2_bzCompressEnd ( &(bzf
->strm
) );
1089 /*---------------------------------------------------*/
1090 BZFILE
* BZ_API(BZ2_bzReadOpen
)
1104 (small
!= 0 && small
!= 1) ||
1105 (verbosity
< 0 || verbosity
> 4) ||
1106 (unused
== NULL
&& nUnused
!= 0) ||
1107 (unused
!= NULL
&& (nUnused
< 0 || nUnused
> BZ_MAX_UNUSED
)))
1108 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
1111 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
1113 bzf
= malloc ( sizeof(bzFile
) );
1115 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
1119 bzf
->initialisedOk
= False
;
1122 bzf
->writing
= False
;
1123 bzf
->strm
.bzalloc
= NULL
;
1124 bzf
->strm
.bzfree
= NULL
;
1125 bzf
->strm
.opaque
= NULL
;
1127 while (nUnused
> 0) {
1128 bzf
->buf
[bzf
->bufN
] = *((UChar
*)(unused
)); bzf
->bufN
++;
1129 unused
= ((void*)( 1 + ((UChar
*)(unused
)) ));
1133 ret
= BZ2_bzDecompressInit ( &(bzf
->strm
), verbosity
, small
);
1135 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
1137 bzf
->strm
.avail_in
= bzf
->bufN
;
1138 bzf
->strm
.next_in
= bzf
->buf
;
1140 bzf
->initialisedOk
= True
;
1145 /*---------------------------------------------------*/
1146 void BZ_API(BZ2_bzReadClose
) ( int *bzerror
, BZFILE
*b
)
1148 bzFile
* bzf
= (bzFile
*)b
;
1152 { BZ_SETERR(BZ_OK
); return; };
1155 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1157 if (bzf
->initialisedOk
)
1158 (void)BZ2_bzDecompressEnd ( &(bzf
->strm
) );
1163 /*---------------------------------------------------*/
1164 int BZ_API(BZ2_bzRead
)
1171 bzFile
* bzf
= (bzFile
*)b
;
1175 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
1176 { BZ_SETERR(BZ_PARAM_ERROR
); return 0; };
1179 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return 0; };
1182 { BZ_SETERR(BZ_OK
); return 0; };
1184 bzf
->strm
.avail_out
= len
;
1185 bzf
->strm
.next_out
= buf
;
1189 if (ferror(bzf
->handle
))
1190 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1192 if (bzf
->strm
.avail_in
== 0 && !myfeof(bzf
->handle
)) {
1193 n
= fread ( bzf
->buf
, sizeof(UChar
),
1194 BZ_MAX_UNUSED
, bzf
->handle
);
1195 if (ferror(bzf
->handle
))
1196 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1198 bzf
->strm
.avail_in
= bzf
->bufN
;
1199 bzf
->strm
.next_in
= bzf
->buf
;
1202 ret
= BZ2_bzDecompress ( &(bzf
->strm
) );
1204 if (ret
!= BZ_OK
&& ret
!= BZ_STREAM_END
)
1205 { BZ_SETERR(ret
); return 0; };
1207 if (ret
== BZ_OK
&& myfeof(bzf
->handle
) &&
1208 bzf
->strm
.avail_in
== 0 && bzf
->strm
.avail_out
> 0)
1209 { BZ_SETERR(BZ_UNEXPECTED_EOF
); return 0; };
1211 if (ret
== BZ_STREAM_END
)
1212 { BZ_SETERR(BZ_STREAM_END
);
1213 return len
- bzf
->strm
.avail_out
; };
1214 if (bzf
->strm
.avail_out
== 0)
1215 { BZ_SETERR(BZ_OK
); return len
; };
1219 return 0; /*not reached*/
1223 /*---------------------------------------------------*/
1224 void BZ_API(BZ2_bzReadGetUnused
)
1230 bzFile
* bzf
= (bzFile
*)b
;
1232 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1233 if (bzf
->lastErr
!= BZ_STREAM_END
)
1234 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1235 if (unused
== NULL
|| nUnused
== NULL
)
1236 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1239 *nUnused
= bzf
->strm
.avail_in
;
1240 *unused
= bzf
->strm
.next_in
;
1244 #ifndef BZ_DECOMPRESS_ONLY
1246 /*---------------------------------------------------*/
1247 /*--- Misc convenience stuff ---*/
1248 /*---------------------------------------------------*/
1250 /*---------------------------------------------------*/
1251 int BZ_API(BZ2_bzBuffToBuffCompress
)
1253 unsigned int* destLen
,
1255 unsigned int sourceLen
,
1263 if (dest
== NULL
|| destLen
== NULL
||
1265 blockSize100k
< 1 || blockSize100k
> 9 ||
1266 verbosity
< 0 || verbosity
> 4 ||
1267 workFactor
< 0 || workFactor
> 250)
1268 return BZ_PARAM_ERROR
;
1270 if (workFactor
== 0) workFactor
= 30;
1271 strm
.bzalloc
= NULL
;
1275 ret
= BZ2_bzCompressInit ( &strm
, blockSize100k
,
1276 verbosity
, workFactor
);
1277 if (ret
!= BZ_OK
) return ret
;
1279 strm
.next_in
= source
;
1280 strm
.next_out
= dest
;
1281 strm
.avail_in
= sourceLen
;
1282 strm
.avail_out
= *destLen
;
1284 ret
= BZ2_bzCompress ( &strm
, BZ_FINISH
);
1285 if (ret
== BZ_FINISH_OK
) goto output_overflow
;
1286 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1288 /* normal termination */
1289 *destLen
-= strm
.avail_out
;
1291 BZ2_bzCompressEnd ( &strm
);
1296 BZ2_bzCompressEnd ( &strm
);
1297 return BZ_OUTBUFF_FULL
;
1301 BZ2_bzCompressEnd ( &strm
);
1305 #endif // BZ_DECOMPRESS_0NLY
1307 /*---------------------------------------------------*/
1308 int BZ_API(BZ2_bzBuffToBuffDecompress
)
1310 unsigned int* destLen
,
1312 unsigned int sourceLen
,
1319 if (dest
== NULL
|| destLen
== NULL
||
1321 (small
!= 0 && small
!= 1) ||
1322 verbosity
< 0 || verbosity
> 4)
1323 return BZ_PARAM_ERROR
;
1325 strm
.bzalloc
= NULL
;
1328 ret
= BZ2_bzDecompressInit ( &strm
, verbosity
, small
);
1329 if (ret
!= BZ_OK
) return ret
;
1331 strm
.next_in
= source
;
1332 strm
.next_out
= dest
;
1333 strm
.avail_in
= sourceLen
;
1334 strm
.avail_out
= *destLen
;
1336 ret
= BZ2_bzDecompress ( &strm
);
1337 if (ret
== BZ_OK
) goto output_overflow_or_eof
;
1338 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1340 /* normal termination */
1341 *destLen
-= strm
.avail_out
;
1342 BZ2_bzDecompressEnd ( &strm
);
1345 output_overflow_or_eof
:
1346 if (strm
.avail_out
> 0) {
1347 BZ2_bzDecompressEnd ( &strm
);
1348 return BZ_UNEXPECTED_EOF
;
1350 BZ2_bzDecompressEnd ( &strm
);
1351 return BZ_OUTBUFF_FULL
;
1355 BZ2_bzDecompressEnd ( &strm
);
1360 /*---------------------------------------------------*/
1362 Code contributed by Yoshioka Tsuneo
1363 (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
1364 to support better zlib compatibility.
1365 This code is not _officially_ part of libbzip2 (yet);
1366 I haven't tested it, documented it, or considered the
1367 threading-safeness of it.
1368 If this code breaks, please contact both Yoshioka and me.
1370 /*---------------------------------------------------*/
1372 /*---------------------------------------------------*/
1374 return version like "0.9.0c".
1376 const char * BZ_API(BZ2_bzlibVersion
)(void)
1383 /*---------------------------------------------------*/
1385 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1388 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1390 # define SET_BINARY_MODE(file)
1393 BZFILE
* bzopen_or_bzdopen
1394 ( const char *path
, /* no use when bzdopen */
1395 int fd
, /* no use when bzdopen */
1397 int open_mode
) /* bzopen: 0, bzdopen:1 */
1400 char unused
[BZ_MAX_UNUSED
];
1401 int blockSize100k
= 9;
1403 char mode2
[10] = "";
1405 BZFILE
*bzfp
= NULL
;
1407 int workFactor
= 30;
1411 if (mode
== NULL
) return NULL
;
1419 smallMode
= 1; break;
1421 if (isdigit((int)(*mode
))) {
1422 blockSize100k
= *mode
-'0';
1427 strcat(mode2
, writing
? "w" : "r" );
1428 strcat(mode2
,"b"); /* binary mode */
1431 if (path
==NULL
|| strcmp(path
,"")==0) {
1432 fp
= (writing
? stdout
: stdin
);
1433 SET_BINARY_MODE(fp
);
1435 fp
= fopen(path
,mode2
);
1438 #ifdef BZ_STRICT_ANSI
1441 fp
= fdopen(fd
,mode2
);
1444 if (fp
== NULL
) return NULL
;
1447 /* Guard against total chaos and anarchy -- JRS */
1448 if (blockSize100k
< 1) blockSize100k
= 1;
1449 if (blockSize100k
> 9) blockSize100k
= 9;
1450 bzfp
= BZ2_bzWriteOpen(&bzerr
,fp
,blockSize100k
,
1451 verbosity
,workFactor
);
1453 bzfp
= BZ2_bzReadOpen(&bzerr
,fp
,verbosity
,smallMode
,
1457 if (fp
!= stdin
&& fp
!= stdout
) fclose(fp
);
1464 /*---------------------------------------------------*/
1466 open file for read or write.
1467 ex) bzopen("file","w9")
1468 case path="" or NULL => use stdin or stdout.
1470 BZFILE
* BZ_API(BZ2_bzopen
)
1474 return bzopen_or_bzdopen(path
,-1,mode
,/*bzopen*/0);
1478 /*---------------------------------------------------*/
1479 BZFILE
* BZ_API(BZ2_bzdopen
)
1483 return bzopen_or_bzdopen(NULL
,fd
,mode
,/*bzdopen*/1);
1487 /*---------------------------------------------------*/
1488 int BZ_API(BZ2_bzread
) (BZFILE
* b
, void* buf
, int len
)
1491 if (((bzFile
*)b
)->lastErr
== BZ_STREAM_END
) return 0;
1492 nread
= BZ2_bzRead(&bzerr
,b
,buf
,len
);
1493 if (bzerr
== BZ_OK
|| bzerr
== BZ_STREAM_END
) {
1501 /*---------------------------------------------------*/
1502 int BZ_API(BZ2_bzwrite
) (BZFILE
* b
, void* buf
, int len
)
1506 BZ2_bzWrite(&bzerr
,b
,buf
,len
);
1515 /*---------------------------------------------------*/
1516 int BZ_API(BZ2_bzflush
) (BZFILE
*b
)
1518 /* do nothing now... */
1523 /*---------------------------------------------------*/
1524 void BZ_API(BZ2_bzclose
) (BZFILE
* b
)
1527 FILE *fp
= ((bzFile
*)b
)->handle
;
1529 if (b
==NULL
) {return;}
1530 if(((bzFile
*)b
)->writing
){
1531 BZ2_bzWriteClose(&bzerr
,b
,0,NULL
,NULL
);
1533 BZ2_bzWriteClose(NULL
,b
,1,NULL
,NULL
);
1536 BZ2_bzReadClose(&bzerr
,b
);
1538 if(fp
!=stdin
&& fp
!=stdout
){
1544 /*---------------------------------------------------*/
1546 return last error code
1548 static char *bzerrorstrings
[] = {
1559 ,"???" /* for future */
1560 ,"???" /* for future */
1561 ,"???" /* for future */
1562 ,"???" /* for future */
1563 ,"???" /* for future */
1564 ,"???" /* for future */
1568 const char * BZ_API(BZ2_bzerror
) (BZFILE
*b
, int *errnum
)
1570 int err
= ((bzFile
*)b
)->lastErr
;
1574 return bzerrorstrings
[err
*-1];
1579 /*-------------------------------------------------------------*/
1580 /*--- end bzlib.c ---*/
1581 /*-------------------------------------------------------------*/