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 #include "bzlib_private.h"
79 /*---------------------------------------------------*/
80 /*--- Compression stuff ---*/
81 /*---------------------------------------------------*/
84 /*---------------------------------------------------*/
86 void BZ2_bz__AssertH__fail ( int errcode
)
89 "\n\nbzip2/libbzip2: internal error number %d.\n"
90 "This is a bug in bzip2/libbzip2, %s.\n"
91 "Please report it to me at: jseward@acm.org. If this happened\n"
92 "when you were using some program which uses libbzip2 as a\n"
93 "component, you should also report this bug to the author(s)\n"
94 "of that program. Please make an effort to report this bug;\n"
95 "timely and accurate bug reports eventually lead to higher\n"
96 "quality software. Thanks. Julian Seward, 21 March 2000.\n\n",
105 /*---------------------------------------------------*/
107 int bz_config_ok ( void )
109 if (sizeof(int) != 4) return 0;
110 if (sizeof(short) != 2) return 0;
111 if (sizeof(char) != 1) return 0;
116 _stdcall
void *(*BZ2_malloc
)( unsigned long size
);
117 _stdcall
void (*BZ2_free
)( void *ptr
);
120 /*---------------------------------------------------*/
122 void* default_bzalloc ( void* opaque
, Int32 items
, Int32 size
)
124 void* v
= BZ2_malloc ( items
* size
);
129 void default_bzfree ( void* opaque
, void* addr
)
131 if (addr
!= NULL
) BZ2_free ( addr
);
135 #ifndef BZ_DECOMPRESS_ONLY
137 /*---------------------------------------------------*/
139 void prepare_new_block ( EState
* s
)
144 s
->state_out_pos
= 0;
145 BZ_INITIALISE_CRC ( s
->blockCRC
);
146 for (i
= 0; i
< 256; i
++) s
->inUse
[i
] = False
;
151 /*---------------------------------------------------*/
153 void init_RL ( EState
* s
)
155 s
->state_in_ch
= 256;
161 Bool
isempty_RL ( EState
* s
)
163 if (s
->state_in_ch
< 256 && s
->state_in_len
> 0)
169 /*---------------------------------------------------*/
170 int BZ_API(BZ2_bzCompressInit
)
179 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
182 blockSize100k
< 1 || blockSize100k
> 9 ||
183 workFactor
< 0 || workFactor
> 250)
184 return BZ_PARAM_ERROR
;
186 if (workFactor
== 0) workFactor
= 30;
187 if (strm
->bzalloc
== NULL
) strm
->bzalloc
= default_bzalloc
;
188 if (strm
->bzfree
== NULL
) strm
->bzfree
= default_bzfree
;
190 s
= BZALLOC( sizeof(EState
) );
191 if (s
== NULL
) return BZ_MEM_ERROR
;
198 n
= 100000 * blockSize100k
;
199 s
->arr1
= BZALLOC( n
* sizeof(UInt32
) );
200 s
->arr2
= BZALLOC( (n
+BZ_N_OVERSHOOT
) * sizeof(UInt32
) );
201 s
->ftab
= BZALLOC( 65537 * sizeof(UInt32
) );
203 if (s
->arr1
== NULL
|| s
->arr2
== NULL
|| s
->ftab
== NULL
) {
204 if (s
->arr1
!= NULL
) BZFREE(s
->arr1
);
205 if (s
->arr2
!= NULL
) BZFREE(s
->arr2
);
206 if (s
->ftab
!= NULL
) BZFREE(s
->ftab
);
207 if (s
!= NULL
) BZFREE(s
);
212 s
->state
= BZ_S_INPUT
;
213 s
->mode
= BZ_M_RUNNING
;
215 s
->blockSize100k
= blockSize100k
;
216 s
->nblockMAX
= 100000 * blockSize100k
- 19;
217 s
->verbosity
= verbosity
;
218 s
->workFactor
= workFactor
;
220 s
->block
= (UChar
*)s
->arr2
;
221 s
->mtfv
= (UInt16
*)s
->arr1
;
223 s
->ptr
= (UInt32
*)s
->arr1
;
226 strm
->total_in_lo32
= 0;
227 strm
->total_in_hi32
= 0;
228 strm
->total_out_lo32
= 0;
229 strm
->total_out_hi32
= 0;
231 prepare_new_block ( s
);
236 /*---------------------------------------------------*/
238 void add_pair_to_block ( EState
* s
)
241 UChar ch
= (UChar
)(s
->state_in_ch
);
242 for (i
= 0; i
< s
->state_in_len
; i
++) {
243 BZ_UPDATE_CRC( s
->blockCRC
, ch
);
245 s
->inUse
[s
->state_in_ch
] = True
;
246 switch (s
->state_in_len
) {
248 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
251 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
252 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
255 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
++;
260 s
->inUse
[s
->state_in_len
-4] = True
;
261 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
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
)(s
->state_in_len
-4));
272 /*---------------------------------------------------*/
274 void flush_RL ( EState
* s
)
276 if (s
->state_in_ch
< 256) add_pair_to_block ( s
);
281 /*---------------------------------------------------*/
282 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
284 UInt32 zchh = (UInt32)(zchh0); \
285 /*-- fast track the common case --*/ \
286 if (zchh != zs->state_in_ch && \
287 zs->state_in_len == 1) { \
288 UChar ch = (UChar)(zs->state_in_ch); \
289 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
290 zs->inUse[zs->state_in_ch] = True; \
291 zs->block[zs->nblock] = (UChar)ch; \
293 zs->state_in_ch = zchh; \
296 /*-- general, uncommon cases --*/ \
297 if (zchh != zs->state_in_ch || \
298 zs->state_in_len == 255) { \
299 if (zs->state_in_ch < 256) \
300 add_pair_to_block ( zs ); \
301 zs->state_in_ch = zchh; \
302 zs->state_in_len = 1; \
304 zs->state_in_len++; \
309 /*---------------------------------------------------*/
311 Bool
copy_input_until_stop ( EState
* s
)
313 Bool progress_in
= False
;
315 if (s
->mode
== BZ_M_RUNNING
) {
317 /*-- fast track the common case --*/
319 /*-- block full? --*/
320 if (s
->nblock
>= s
->nblockMAX
) break;
322 if (s
->strm
->avail_in
== 0) break;
324 ADD_CHAR_TO_BLOCK ( s
, (UInt32
)(*((UChar
*)(s
->strm
->next_in
))) );
327 s
->strm
->total_in_lo32
++;
328 if (s
->strm
->total_in_lo32
== 0) s
->strm
->total_in_hi32
++;
333 /*-- general, uncommon case --*/
335 /*-- block full? --*/
336 if (s
->nblock
>= s
->nblockMAX
) break;
338 if (s
->strm
->avail_in
== 0) break;
339 /*-- flush/finish end? --*/
340 if (s
->avail_in_expect
== 0) break;
342 ADD_CHAR_TO_BLOCK ( s
, (UInt32
)(*((UChar
*)(s
->strm
->next_in
))) );
345 s
->strm
->total_in_lo32
++;
346 if (s
->strm
->total_in_lo32
== 0) s
->strm
->total_in_hi32
++;
347 s
->avail_in_expect
--;
354 /*---------------------------------------------------*/
356 Bool
copy_output_until_stop ( EState
* s
)
358 Bool progress_out
= False
;
362 /*-- no output space? --*/
363 if (s
->strm
->avail_out
== 0) break;
365 /*-- block done? --*/
366 if (s
->state_out_pos
>= s
->numZ
) break;
369 *(s
->strm
->next_out
) = s
->zbits
[s
->state_out_pos
];
371 s
->strm
->avail_out
--;
373 s
->strm
->total_out_lo32
++;
374 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
381 /*---------------------------------------------------*/
383 Bool
handle_compress ( bz_stream
* strm
)
385 Bool progress_in
= False
;
386 Bool progress_out
= False
;
387 EState
* s
= strm
->state
;
391 if (s
->state
== BZ_S_OUTPUT
) {
392 progress_out
|= copy_output_until_stop ( s
);
393 if (s
->state_out_pos
< s
->numZ
) break;
394 if (s
->mode
== BZ_M_FINISHING
&&
395 s
->avail_in_expect
== 0 &&
396 isempty_RL(s
)) break;
397 prepare_new_block ( s
);
398 s
->state
= BZ_S_INPUT
;
399 if (s
->mode
== BZ_M_FLUSHING
&&
400 s
->avail_in_expect
== 0 &&
401 isempty_RL(s
)) break;
404 if (s
->state
== BZ_S_INPUT
) {
405 progress_in
|= copy_input_until_stop ( s
);
406 if (s
->mode
!= BZ_M_RUNNING
&& s
->avail_in_expect
== 0) {
408 BZ2_compressBlock ( s
, (Bool
)(s
->mode
== BZ_M_FINISHING
) );
409 s
->state
= BZ_S_OUTPUT
;
412 if (s
->nblock
>= s
->nblockMAX
) {
413 BZ2_compressBlock ( s
, False
);
414 s
->state
= BZ_S_OUTPUT
;
417 if (s
->strm
->avail_in
== 0) {
424 return progress_in
|| progress_out
;
428 /*---------------------------------------------------*/
429 int BZ_API(BZ2_bzCompress
) ( bz_stream
*strm
, int action
)
433 if (strm
== NULL
) return BZ_PARAM_ERROR
;
435 if (s
== NULL
) return BZ_PARAM_ERROR
;
436 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
442 return BZ_SEQUENCE_ERROR
;
445 if (action
== BZ_RUN
) {
446 progress
= handle_compress ( strm
);
447 return progress
? BZ_RUN_OK
: BZ_PARAM_ERROR
;
450 if (action
== BZ_FLUSH
) {
451 s
->avail_in_expect
= strm
->avail_in
;
452 s
->mode
= BZ_M_FLUSHING
;
456 if (action
== BZ_FINISH
) {
457 s
->avail_in_expect
= strm
->avail_in
;
458 s
->mode
= BZ_M_FINISHING
;
462 return BZ_PARAM_ERROR
;
465 if (action
!= BZ_FLUSH
) return BZ_SEQUENCE_ERROR
;
466 if (s
->avail_in_expect
!= s
->strm
->avail_in
)
467 return BZ_SEQUENCE_ERROR
;
468 progress
= handle_compress ( strm
);
469 if (s
->avail_in_expect
> 0 || !isempty_RL(s
) ||
470 s
->state_out_pos
< s
->numZ
) return BZ_FLUSH_OK
;
471 s
->mode
= BZ_M_RUNNING
;
475 if (action
!= BZ_FINISH
) return BZ_SEQUENCE_ERROR
;
476 if (s
->avail_in_expect
!= s
->strm
->avail_in
)
477 return BZ_SEQUENCE_ERROR
;
478 progress
= handle_compress ( strm
);
479 if (!progress
) return BZ_SEQUENCE_ERROR
;
480 if (s
->avail_in_expect
> 0 || !isempty_RL(s
) ||
481 s
->state_out_pos
< s
->numZ
) return BZ_FINISH_OK
;
483 return BZ_STREAM_END
;
485 return BZ_OK
; /*--not reached--*/
489 /*---------------------------------------------------*/
490 int BZ_API(BZ2_bzCompressEnd
) ( bz_stream
*strm
)
493 if (strm
== NULL
) return BZ_PARAM_ERROR
;
495 if (s
== NULL
) return BZ_PARAM_ERROR
;
496 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
498 if (s
->arr1
!= NULL
) BZFREE(s
->arr1
);
499 if (s
->arr2
!= NULL
) BZFREE(s
->arr2
);
500 if (s
->ftab
!= NULL
) BZFREE(s
->ftab
);
508 #endif // BZ_DECOMPRESS_ONLY
510 /*---------------------------------------------------*/
511 /*--- Decompression stuff ---*/
512 /*---------------------------------------------------*/
514 /*---------------------------------------------------*/
515 int BZ_API(BZ2_bzDecompressInit
)
522 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
524 if (strm
== NULL
) return BZ_PARAM_ERROR
;
525 if (small
!= 0 && small
!= 1) return BZ_PARAM_ERROR
;
526 if (verbosity
< 0 || verbosity
> 4) return BZ_PARAM_ERROR
;
528 if (strm
->bzalloc
== NULL
) strm
->bzalloc
= default_bzalloc
;
529 if (strm
->bzfree
== NULL
) strm
->bzfree
= default_bzfree
;
531 s
= BZALLOC( sizeof(DState
) );
532 if (s
== NULL
) return BZ_MEM_ERROR
;
535 s
->state
= BZ_X_MAGIC_1
;
538 s
->calculatedCombinedCRC
= 0;
539 strm
->total_in_lo32
= 0;
540 strm
->total_in_hi32
= 0;
541 strm
->total_out_lo32
= 0;
542 strm
->total_out_hi32
= 0;
543 s
->smallDecompress
= (Bool
)small
;
548 s
->verbosity
= verbosity
;
553 /*---------------------------------------------------*/
555 void unRLE_obuf_to_output_FAST ( DState
* s
)
559 if (s
->blockRandomised
) {
562 /* try to finish existing run */
564 if (s
->strm
->avail_out
== 0) return;
565 if (s
->state_out_len
== 0) break;
566 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
567 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
570 s
->strm
->avail_out
--;
571 s
->strm
->total_out_lo32
++;
572 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
575 /* can a new run be started? */
576 if (s
->nblock_used
== s
->save_nblock
+1) return;
579 s
->state_out_len
= 1;
580 s
->state_out_ch
= s
->k0
;
581 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
582 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
583 if (s
->nblock_used
== s
->save_nblock
+1) continue;
584 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
586 s
->state_out_len
= 2;
587 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
588 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
589 if (s
->nblock_used
== s
->save_nblock
+1) continue;
590 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
592 s
->state_out_len
= 3;
593 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
594 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
595 if (s
->nblock_used
== s
->save_nblock
+1) continue;
596 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
598 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
599 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
600 s
->state_out_len
= ((Int32
)k1
) + 4;
601 BZ_GET_FAST(s
->k0
); BZ_RAND_UPD_MASK
;
602 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
608 UInt32 c_calculatedBlockCRC
= s
->calculatedBlockCRC
;
609 UChar c_state_out_ch
= s
->state_out_ch
;
610 Int32 c_state_out_len
= s
->state_out_len
;
611 Int32 c_nblock_used
= s
->nblock_used
;
613 UInt32
* c_tt
= s
->tt
;
614 UInt32 c_tPos
= s
->tPos
;
615 char* cs_next_out
= s
->strm
->next_out
;
616 unsigned int cs_avail_out
= s
->strm
->avail_out
;
619 UInt32 avail_out_INIT
= cs_avail_out
;
620 Int32 s_save_nblockPP
= s
->save_nblock
+1;
621 unsigned int total_out_lo32_old
;
625 /* try to finish existing run */
626 if (c_state_out_len
> 0) {
628 if (cs_avail_out
== 0) goto return_notr
;
629 if (c_state_out_len
== 1) break;
630 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
631 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
636 s_state_out_len_eq_one
:
638 if (cs_avail_out
== 0) {
639 c_state_out_len
= 1; goto return_notr
;
641 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
642 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
647 /* can a new run be started? */
648 if (c_nblock_used
== s_save_nblockPP
) {
649 c_state_out_len
= 0; goto return_notr
;
651 c_state_out_ch
= c_k0
;
652 BZ_GET_FAST_C(k1
); c_nblock_used
++;
654 c_k0
= k1
; goto s_state_out_len_eq_one
;
656 if (c_nblock_used
== s_save_nblockPP
)
657 goto s_state_out_len_eq_one
;
660 BZ_GET_FAST_C(k1
); c_nblock_used
++;
661 if (c_nblock_used
== s_save_nblockPP
) continue;
662 if (k1
!= c_k0
) { c_k0
= k1
; continue; };
665 BZ_GET_FAST_C(k1
); c_nblock_used
++;
666 if (c_nblock_used
== s_save_nblockPP
) continue;
667 if (k1
!= c_k0
) { c_k0
= k1
; continue; };
669 BZ_GET_FAST_C(k1
); c_nblock_used
++;
670 c_state_out_len
= ((Int32
)k1
) + 4;
671 BZ_GET_FAST_C(c_k0
); c_nblock_used
++;
675 total_out_lo32_old
= s
->strm
->total_out_lo32
;
676 s
->strm
->total_out_lo32
+= (avail_out_INIT
- cs_avail_out
);
677 if (s
->strm
->total_out_lo32
< total_out_lo32_old
)
678 s
->strm
->total_out_hi32
++;
681 s
->calculatedBlockCRC
= c_calculatedBlockCRC
;
682 s
->state_out_ch
= c_state_out_ch
;
683 s
->state_out_len
= c_state_out_len
;
684 s
->nblock_used
= c_nblock_used
;
688 s
->strm
->next_out
= cs_next_out
;
689 s
->strm
->avail_out
= cs_avail_out
;
694 /*---------------------------------------------------*/
695 __inline__ Int32
BZ2_indexIntoF ( Int32 indx
, Int32
*cftab
)
701 mid
= (nb
+ na
) >> 1;
702 if (indx
>= cftab
[mid
]) nb
= mid
; else na
= mid
;
704 while (na
- nb
!= 1);
708 /*---------------------------------------------------*/
710 void unRLE_obuf_to_output_SMALL ( DState
* s
)
714 if (s
->blockRandomised
) {
717 /* try to finish existing run */
719 if (s
->strm
->avail_out
== 0) return;
720 if (s
->state_out_len
== 0) break;
721 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
722 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
725 s
->strm
->avail_out
--;
726 s
->strm
->total_out_lo32
++;
727 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
730 /* can a new run be started? */
731 if (s
->nblock_used
== s
->save_nblock
+1) return;
734 s
->state_out_len
= 1;
735 s
->state_out_ch
= s
->k0
;
736 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
737 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
738 if (s
->nblock_used
== s
->save_nblock
+1) continue;
739 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
741 s
->state_out_len
= 2;
742 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
743 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
744 if (s
->nblock_used
== s
->save_nblock
+1) continue;
745 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
747 s
->state_out_len
= 3;
748 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
749 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
750 if (s
->nblock_used
== s
->save_nblock
+1) continue;
751 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
753 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
754 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
755 s
->state_out_len
= ((Int32
)k1
) + 4;
756 BZ_GET_SMALL(s
->k0
); BZ_RAND_UPD_MASK
;
757 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
763 /* try to finish existing run */
765 if (s
->strm
->avail_out
== 0) return;
766 if (s
->state_out_len
== 0) break;
767 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
768 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
771 s
->strm
->avail_out
--;
772 s
->strm
->total_out_lo32
++;
773 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
776 /* can a new run be started? */
777 if (s
->nblock_used
== s
->save_nblock
+1) return;
779 s
->state_out_len
= 1;
780 s
->state_out_ch
= s
->k0
;
781 BZ_GET_SMALL(k1
); s
->nblock_used
++;
782 if (s
->nblock_used
== s
->save_nblock
+1) continue;
783 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
785 s
->state_out_len
= 2;
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
= 3;
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 BZ_GET_SMALL(k1
); s
->nblock_used
++;
796 s
->state_out_len
= ((Int32
)k1
) + 4;
797 BZ_GET_SMALL(s
->k0
); s
->nblock_used
++;
803 /*---------------------------------------------------*/
804 int BZ_API(BZ2_bzDecompress
) ( bz_stream
*strm
)
807 if (strm
== NULL
) return BZ_PARAM_ERROR
;
809 if (s
== NULL
) return BZ_PARAM_ERROR
;
810 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
813 if (s
->state
== BZ_X_IDLE
) return BZ_SEQUENCE_ERROR
;
814 if (s
->state
== BZ_X_OUTPUT
) {
815 if (s
->smallDecompress
)
816 unRLE_obuf_to_output_SMALL ( s
); else
817 unRLE_obuf_to_output_FAST ( s
);
818 if (s
->nblock_used
== s
->save_nblock
+1 && s
->state_out_len
== 0) {
819 BZ_FINALISE_CRC ( s
->calculatedBlockCRC
);
820 if (s
->verbosity
>= 3)
821 VPrintf2 ( " {0x%x, 0x%x}", s
->storedBlockCRC
,
822 s
->calculatedBlockCRC
);
823 if (s
->verbosity
>= 2) VPrintf0 ( "]" );
824 if (s
->calculatedBlockCRC
!= s
->storedBlockCRC
)
825 return BZ_DATA_ERROR
;
826 s
->calculatedCombinedCRC
827 = (s
->calculatedCombinedCRC
<< 1) |
828 (s
->calculatedCombinedCRC
>> 31);
829 s
->calculatedCombinedCRC
^= s
->calculatedBlockCRC
;
830 s
->state
= BZ_X_BLKHDR_1
;
835 if (s
->state
>= BZ_X_MAGIC_1
) {
836 Int32 r
= BZ2_decompress ( s
);
837 if (r
== BZ_STREAM_END
) {
838 if (s
->verbosity
>= 3)
839 VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x",
840 s
->storedCombinedCRC
, s
->calculatedCombinedCRC
);
841 if (s
->calculatedCombinedCRC
!= s
->storedCombinedCRC
)
842 return BZ_DATA_ERROR
;
845 if (s
->state
!= BZ_X_OUTPUT
) return r
;
851 return 0; /*NOTREACHED*/
855 /*---------------------------------------------------*/
856 int BZ_API(BZ2_bzDecompressEnd
) ( bz_stream
*strm
)
859 if (strm
== NULL
) return BZ_PARAM_ERROR
;
861 if (s
== NULL
) return BZ_PARAM_ERROR
;
862 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
864 if (s
->tt
!= NULL
) BZFREE(s
->tt
);
865 if (s
->ll16
!= NULL
) BZFREE(s
->ll16
);
866 if (s
->ll4
!= NULL
) BZFREE(s
->ll4
);
876 /*---------------------------------------------------*/
877 /*--- File I/O stuff ---*/
878 /*---------------------------------------------------*/
880 #define BZ_SETERR(eee) \
882 if (bzerror != NULL) *bzerror = eee; \
883 if (bzf != NULL) bzf->lastErr = eee; \
889 Char buf
[BZ_MAX_UNUSED
];
899 /*---------------------------------------------*/
900 static Bool
myfeof ( FILE* f
)
902 Int32 c
= fgetc ( f
);
903 if (c
== EOF
) return True
;
909 /*---------------------------------------------------*/
910 BZFILE
* BZ_API(BZ2_bzWriteOpen
)
923 (blockSize100k
< 1 || blockSize100k
> 9) ||
924 (workFactor
< 0 || workFactor
> 250) ||
925 (verbosity
< 0 || verbosity
> 4))
926 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
929 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
931 bzf
= malloc ( sizeof(bzFile
) );
933 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
936 bzf
->initialisedOk
= False
;
940 bzf
->strm
.bzalloc
= NULL
;
941 bzf
->strm
.bzfree
= NULL
;
942 bzf
->strm
.opaque
= NULL
;
944 if (workFactor
== 0) workFactor
= 30;
945 ret
= BZ2_bzCompressInit ( &(bzf
->strm
), blockSize100k
,
946 verbosity
, workFactor
);
948 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
950 bzf
->strm
.avail_in
= 0;
951 bzf
->initialisedOk
= True
;
957 /*---------------------------------------------------*/
958 void BZ_API(BZ2_bzWrite
)
965 bzFile
* bzf
= (bzFile
*)b
;
968 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
969 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
971 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
972 if (ferror(bzf
->handle
))
973 { BZ_SETERR(BZ_IO_ERROR
); return; };
976 { BZ_SETERR(BZ_OK
); return; };
978 bzf
->strm
.avail_in
= len
;
979 bzf
->strm
.next_in
= buf
;
982 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
983 bzf
->strm
.next_out
= bzf
->buf
;
984 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_RUN
);
985 if (ret
!= BZ_RUN_OK
)
986 { BZ_SETERR(ret
); return; };
988 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
989 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
990 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
992 if (n
!= n2
|| ferror(bzf
->handle
))
993 { BZ_SETERR(BZ_IO_ERROR
); return; };
996 if (bzf
->strm
.avail_in
== 0)
997 { BZ_SETERR(BZ_OK
); return; };
1002 /*---------------------------------------------------*/
1003 void BZ_API(BZ2_bzWriteClose
)
1007 unsigned int* nbytes_in
,
1008 unsigned int* nbytes_out
)
1010 BZ2_bzWriteClose64 ( bzerror
, b
, abandon
,
1011 nbytes_in
, NULL
, nbytes_out
, NULL
);
1015 void BZ_API(BZ2_bzWriteClose64
)
1019 unsigned int* nbytes_in_lo32
,
1020 unsigned int* nbytes_in_hi32
,
1021 unsigned int* nbytes_out_lo32
,
1022 unsigned int* nbytes_out_hi32
)
1025 bzFile
* bzf
= (bzFile
*)b
;
1028 { BZ_SETERR(BZ_OK
); return; };
1029 if (!(bzf
->writing
))
1030 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1031 if (ferror(bzf
->handle
))
1032 { BZ_SETERR(BZ_IO_ERROR
); return; };
1034 if (nbytes_in_lo32
!= NULL
) *nbytes_in_lo32
= 0;
1035 if (nbytes_in_hi32
!= NULL
) *nbytes_in_hi32
= 0;
1036 if (nbytes_out_lo32
!= NULL
) *nbytes_out_lo32
= 0;
1037 if (nbytes_out_hi32
!= NULL
) *nbytes_out_hi32
= 0;
1039 if ((!abandon
) && bzf
->lastErr
== BZ_OK
) {
1041 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
1042 bzf
->strm
.next_out
= bzf
->buf
;
1043 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_FINISH
);
1044 if (ret
!= BZ_FINISH_OK
&& ret
!= BZ_STREAM_END
)
1045 { BZ_SETERR(ret
); return; };
1047 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
1048 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
1049 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
1051 if (n
!= n2
|| ferror(bzf
->handle
))
1052 { BZ_SETERR(BZ_IO_ERROR
); return; };
1055 if (ret
== BZ_STREAM_END
) break;
1059 if ( !abandon
&& !ferror ( bzf
->handle
) ) {
1060 fflush ( bzf
->handle
);
1061 if (ferror(bzf
->handle
))
1062 { BZ_SETERR(BZ_IO_ERROR
); return; };
1065 if (nbytes_in_lo32
!= NULL
)
1066 *nbytes_in_lo32
= bzf
->strm
.total_in_lo32
;
1067 if (nbytes_in_hi32
!= NULL
)
1068 *nbytes_in_hi32
= bzf
->strm
.total_in_hi32
;
1069 if (nbytes_out_lo32
!= NULL
)
1070 *nbytes_out_lo32
= bzf
->strm
.total_out_lo32
;
1071 if (nbytes_out_hi32
!= NULL
)
1072 *nbytes_out_hi32
= bzf
->strm
.total_out_hi32
;
1075 BZ2_bzCompressEnd ( &(bzf
->strm
) );
1080 /*---------------------------------------------------*/
1081 BZFILE
* BZ_API(BZ2_bzReadOpen
)
1095 (small
!= 0 && small
!= 1) ||
1096 (verbosity
< 0 || verbosity
> 4) ||
1097 (unused
== NULL
&& nUnused
!= 0) ||
1098 (unused
!= NULL
&& (nUnused
< 0 || nUnused
> BZ_MAX_UNUSED
)))
1099 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
1102 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
1104 bzf
= malloc ( sizeof(bzFile
) );
1106 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
1110 bzf
->initialisedOk
= False
;
1113 bzf
->writing
= False
;
1114 bzf
->strm
.bzalloc
= NULL
;
1115 bzf
->strm
.bzfree
= NULL
;
1116 bzf
->strm
.opaque
= NULL
;
1118 while (nUnused
> 0) {
1119 bzf
->buf
[bzf
->bufN
] = *((UChar
*)(unused
)); bzf
->bufN
++;
1120 unused
= ((void*)( 1 + ((UChar
*)(unused
)) ));
1124 ret
= BZ2_bzDecompressInit ( &(bzf
->strm
), verbosity
, small
);
1126 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
1128 bzf
->strm
.avail_in
= bzf
->bufN
;
1129 bzf
->strm
.next_in
= bzf
->buf
;
1131 bzf
->initialisedOk
= True
;
1136 /*---------------------------------------------------*/
1137 void BZ_API(BZ2_bzReadClose
) ( int *bzerror
, BZFILE
*b
)
1139 bzFile
* bzf
= (bzFile
*)b
;
1143 { BZ_SETERR(BZ_OK
); return; };
1146 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1148 if (bzf
->initialisedOk
)
1149 (void)BZ2_bzDecompressEnd ( &(bzf
->strm
) );
1154 /*---------------------------------------------------*/
1155 int BZ_API(BZ2_bzRead
)
1162 bzFile
* bzf
= (bzFile
*)b
;
1166 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
1167 { BZ_SETERR(BZ_PARAM_ERROR
); return 0; };
1170 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return 0; };
1173 { BZ_SETERR(BZ_OK
); return 0; };
1175 bzf
->strm
.avail_out
= len
;
1176 bzf
->strm
.next_out
= buf
;
1180 if (ferror(bzf
->handle
))
1181 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1183 if (bzf
->strm
.avail_in
== 0 && !myfeof(bzf
->handle
)) {
1184 n
= fread ( bzf
->buf
, sizeof(UChar
),
1185 BZ_MAX_UNUSED
, bzf
->handle
);
1186 if (ferror(bzf
->handle
))
1187 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1189 bzf
->strm
.avail_in
= bzf
->bufN
;
1190 bzf
->strm
.next_in
= bzf
->buf
;
1193 ret
= BZ2_bzDecompress ( &(bzf
->strm
) );
1195 if (ret
!= BZ_OK
&& ret
!= BZ_STREAM_END
)
1196 { BZ_SETERR(ret
); return 0; };
1198 if (ret
== BZ_OK
&& myfeof(bzf
->handle
) &&
1199 bzf
->strm
.avail_in
== 0 && bzf
->strm
.avail_out
> 0)
1200 { BZ_SETERR(BZ_UNEXPECTED_EOF
); return 0; };
1202 if (ret
== BZ_STREAM_END
)
1203 { BZ_SETERR(BZ_STREAM_END
);
1204 return len
- bzf
->strm
.avail_out
; };
1205 if (bzf
->strm
.avail_out
== 0)
1206 { BZ_SETERR(BZ_OK
); return len
; };
1210 return 0; /*not reached*/
1214 /*---------------------------------------------------*/
1215 void BZ_API(BZ2_bzReadGetUnused
)
1221 bzFile
* bzf
= (bzFile
*)b
;
1223 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1224 if (bzf
->lastErr
!= BZ_STREAM_END
)
1225 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1226 if (unused
== NULL
|| nUnused
== NULL
)
1227 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1230 *nUnused
= bzf
->strm
.avail_in
;
1231 *unused
= bzf
->strm
.next_in
;
1235 #ifndef BZ_DECOMPRESS_ONLY
1237 /*---------------------------------------------------*/
1238 /*--- Misc convenience stuff ---*/
1239 /*---------------------------------------------------*/
1241 /*---------------------------------------------------*/
1242 int BZ_API(BZ2_bzBuffToBuffCompress
)
1244 unsigned int* destLen
,
1246 unsigned int sourceLen
,
1254 if (dest
== NULL
|| destLen
== NULL
||
1256 blockSize100k
< 1 || blockSize100k
> 9 ||
1257 verbosity
< 0 || verbosity
> 4 ||
1258 workFactor
< 0 || workFactor
> 250)
1259 return BZ_PARAM_ERROR
;
1261 if (workFactor
== 0) workFactor
= 30;
1262 strm
.bzalloc
= NULL
;
1265 ret
= BZ2_bzCompressInit ( &strm
, blockSize100k
,
1266 verbosity
, workFactor
);
1267 if (ret
!= BZ_OK
) return ret
;
1269 strm
.next_in
= source
;
1270 strm
.next_out
= dest
;
1271 strm
.avail_in
= sourceLen
;
1272 strm
.avail_out
= *destLen
;
1274 ret
= BZ2_bzCompress ( &strm
, BZ_FINISH
);
1275 if (ret
== BZ_FINISH_OK
) goto output_overflow
;
1276 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1278 /* normal termination */
1279 *destLen
-= strm
.avail_out
;
1280 BZ2_bzCompressEnd ( &strm
);
1284 BZ2_bzCompressEnd ( &strm
);
1285 return BZ_OUTBUFF_FULL
;
1288 BZ2_bzCompressEnd ( &strm
);
1292 #endif // BZ_DECOMPRESS_0NLY
1294 /*---------------------------------------------------*/
1295 int BZ_API(BZ2_bzBuffToBuffDecompress
)
1297 unsigned int* destLen
,
1299 unsigned int sourceLen
,
1306 if (dest
== NULL
|| destLen
== NULL
||
1308 (small
!= 0 && small
!= 1) ||
1309 verbosity
< 0 || verbosity
> 4)
1310 return BZ_PARAM_ERROR
;
1312 strm
.bzalloc
= NULL
;
1315 ret
= BZ2_bzDecompressInit ( &strm
, verbosity
, small
);
1316 if (ret
!= BZ_OK
) return ret
;
1318 strm
.next_in
= source
;
1319 strm
.next_out
= dest
;
1320 strm
.avail_in
= sourceLen
;
1321 strm
.avail_out
= *destLen
;
1323 ret
= BZ2_bzDecompress ( &strm
);
1324 if (ret
== BZ_OK
) goto output_overflow_or_eof
;
1325 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1327 /* normal termination */
1328 *destLen
-= strm
.avail_out
;
1329 BZ2_bzDecompressEnd ( &strm
);
1332 output_overflow_or_eof
:
1333 if (strm
.avail_out
> 0) {
1334 BZ2_bzDecompressEnd ( &strm
);
1335 return BZ_UNEXPECTED_EOF
;
1337 BZ2_bzDecompressEnd ( &strm
);
1338 return BZ_OUTBUFF_FULL
;
1342 BZ2_bzDecompressEnd ( &strm
);
1347 /*---------------------------------------------------*/
1349 Code contributed by Yoshioka Tsuneo
1350 (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
1351 to support better zlib compatibility.
1352 This code is not _officially_ part of libbzip2 (yet);
1353 I haven't tested it, documented it, or considered the
1354 threading-safeness of it.
1355 If this code breaks, please contact both Yoshioka and me.
1357 /*---------------------------------------------------*/
1359 /*---------------------------------------------------*/
1361 return version like "0.9.0c".
1363 const char * BZ_API(BZ2_bzlibVersion
)(void)
1370 /*---------------------------------------------------*/
1372 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1375 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1377 # define SET_BINARY_MODE(file)
1380 BZFILE
* bzopen_or_bzdopen
1381 ( const char *path
, /* no use when bzdopen */
1382 int fd
, /* no use when bzdopen */
1384 int open_mode
) /* bzopen: 0, bzdopen:1 */
1387 char unused
[BZ_MAX_UNUSED
];
1388 int blockSize100k
= 9;
1390 char mode2
[10] = "";
1392 BZFILE
*bzfp
= NULL
;
1394 int workFactor
= 30;
1398 if (mode
== NULL
) return NULL
;
1406 smallMode
= 1; break;
1408 if (isdigit((int)(*mode
))) {
1409 blockSize100k
= *mode
-'0';
1414 strcat(mode2
, writing
? "w" : "r" );
1415 strcat(mode2
,"b"); /* binary mode */
1418 if (path
==NULL
|| strcmp(path
,"")==0) {
1419 fp
= (writing
? stdout
: stdin
);
1420 SET_BINARY_MODE(fp
);
1422 fp
= fopen(path
,mode2
);
1425 #ifdef BZ_STRICT_ANSI
1428 fp
= fdopen(fd
,mode2
);
1431 if (fp
== NULL
) return NULL
;
1434 /* Guard against total chaos and anarchy -- JRS */
1435 if (blockSize100k
< 1) blockSize100k
= 1;
1436 if (blockSize100k
> 9) blockSize100k
= 9;
1437 bzfp
= BZ2_bzWriteOpen(&bzerr
,fp
,blockSize100k
,
1438 verbosity
,workFactor
);
1440 bzfp
= BZ2_bzReadOpen(&bzerr
,fp
,verbosity
,smallMode
,
1444 if (fp
!= stdin
&& fp
!= stdout
) fclose(fp
);
1451 /*---------------------------------------------------*/
1453 open file for read or write.
1454 ex) bzopen("file","w9")
1455 case path="" or NULL => use stdin or stdout.
1457 BZFILE
* BZ_API(BZ2_bzopen
)
1461 return bzopen_or_bzdopen(path
,-1,mode
,/*bzopen*/0);
1465 /*---------------------------------------------------*/
1466 BZFILE
* BZ_API(BZ2_bzdopen
)
1470 return bzopen_or_bzdopen(NULL
,fd
,mode
,/*bzdopen*/1);
1474 /*---------------------------------------------------*/
1475 int BZ_API(BZ2_bzread
) (BZFILE
* b
, void* buf
, int len
)
1478 if (((bzFile
*)b
)->lastErr
== BZ_STREAM_END
) return 0;
1479 nread
= BZ2_bzRead(&bzerr
,b
,buf
,len
);
1480 if (bzerr
== BZ_OK
|| bzerr
== BZ_STREAM_END
) {
1488 /*---------------------------------------------------*/
1489 int BZ_API(BZ2_bzwrite
) (BZFILE
* b
, void* buf
, int len
)
1493 BZ2_bzWrite(&bzerr
,b
,buf
,len
);
1502 /*---------------------------------------------------*/
1503 int BZ_API(BZ2_bzflush
) (BZFILE
*b
)
1505 /* do nothing now... */
1510 /*---------------------------------------------------*/
1511 void BZ_API(BZ2_bzclose
) (BZFILE
* b
)
1514 FILE *fp
= ((bzFile
*)b
)->handle
;
1516 if (b
==NULL
) {return;}
1517 if(((bzFile
*)b
)->writing
){
1518 BZ2_bzWriteClose(&bzerr
,b
,0,NULL
,NULL
);
1520 BZ2_bzWriteClose(NULL
,b
,1,NULL
,NULL
);
1523 BZ2_bzReadClose(&bzerr
,b
);
1525 if(fp
!=stdin
&& fp
!=stdout
){
1531 /*---------------------------------------------------*/
1533 return last error code
1535 static char *bzerrorstrings
[] = {
1546 ,"???" /* for future */
1547 ,"???" /* for future */
1548 ,"???" /* for future */
1549 ,"???" /* for future */
1550 ,"???" /* for future */
1551 ,"???" /* for future */
1555 const char * BZ_API(BZ2_bzerror
) (BZFILE
*b
, int *errnum
)
1557 int err
= ((bzFile
*)b
)->lastErr
;
1561 return bzerrorstrings
[err
*-1];
1566 /*-------------------------------------------------------------*/
1567 /*--- end bzlib.c ---*/
1568 /*-------------------------------------------------------------*/