9813 isainfo should learn about SHA Instrs
[unleashed.git] / usr / src / common / bzip2 / bzlib.c
blob22e2d8826eec04a200622b6280240ca02fff6a13
2 /*-------------------------------------------------------------*/
3 /*--- Library top-level functions. ---*/
4 /*--- bzlib.c ---*/
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
15 README file.
17 This program is released under the terms of the license contained
18 in the file LICENSE.
19 ------------------------------------------------------------------ */
21 /* CHANGES
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 #include "bzlib_private.h"
33 #ifndef BZ_NO_COMPRESS
35 /*---------------------------------------------------*/
36 /*--- Compression stuff ---*/
37 /*---------------------------------------------------*/
40 /*---------------------------------------------------*/
41 #ifndef BZ_NO_STDIO
42 void BZ2_bz__AssertH__fail ( int errcode )
44 fprintf(stderr,
45 "\n\nbzip2/libbzip2: internal error number %d.\n"
46 "This is a bug in bzip2/libbzip2, %s.\n"
47 "Please report it to me at: jseward@bzip.org. If this happened\n"
48 "when you were using some program which uses libbzip2 as a\n"
49 "component, you should also report this bug to the author(s)\n"
50 "of that program. Please make an effort to report this bug;\n"
51 "timely and accurate bug reports eventually lead to higher\n"
52 "quality software. Thanks. Julian Seward, 10 December 2007.\n\n",
53 errcode,
54 BZ2_bzlibVersion()
57 if (errcode == 1007) {
58 fprintf(stderr,
59 "\n*** A special note about internal error number 1007 ***\n"
60 "\n"
61 "Experience suggests that a common cause of i.e. 1007\n"
62 "is unreliable memory or other hardware. The 1007 assertion\n"
63 "just happens to cross-check the results of huge numbers of\n"
64 "memory reads/writes, and so acts (unintendedly) as a stress\n"
65 "test of your memory system.\n"
66 "\n"
67 "I suggest the following: try compressing the file again,\n"
68 "possibly monitoring progress in detail with the -vv flag.\n"
69 "\n"
70 "* If the error cannot be reproduced, and/or happens at different\n"
71 " points in compression, you may have a flaky memory system.\n"
72 " Try a memory-test program. I have used Memtest86\n"
73 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
74 " Memtest86 tests memory much more thorougly than your BIOSs\n"
75 " power-on test, and may find failures that the BIOS doesn't.\n"
76 "\n"
77 "* If the error can be repeatably reproduced, this is a bug in\n"
78 " bzip2, and I would very much like to hear about it. Please\n"
79 " let me know, and, ideally, save a copy of the file causing the\n"
80 " problem -- without which I will be unable to investigate it.\n"
81 "\n"
85 exit(3);
87 #endif
89 #endif /* BZ_NO_COMPRESS */
91 /*---------------------------------------------------*/
92 static
93 int bz_config_ok ( void )
95 if (sizeof(int) != 4) return 0;
96 if (sizeof(short) != 2) return 0;
97 if (sizeof(char) != 1) return 0;
98 return 1;
102 * Added for Solaris kernel
104 #define BZES \
105 BZE(BZ_OK) \
106 BZE(BZ_RUN_OK) \
107 BZE(BZ_FLUSH_OK) \
108 BZE(BZ_FINISH_OK) \
109 BZE(BZ_STREAM_END) \
110 BZE(BZ_SEQUENCE_ERROR) \
111 BZE(BZ_PARAM_ERROR) \
112 BZE(BZ_MEM_ERROR) \
113 BZE(BZ_DATA_ERROR) \
114 BZE(BZ_DATA_ERROR_MAGIC) \
115 BZE(BZ_IO_ERROR) \
116 BZE(BZ_UNEXPECTED_EOF) \
117 BZE(BZ_OUTBUFF_FULL) \
118 BZE(BZ_CONFIG_ERROR)
120 BZ_EXTERN const char * BZ_API(BZ2_bzErrorString) (
121 int error_code
124 switch (error_code)
126 #define BZE(x) case x: return (#x);
127 BZES
128 #undef BZE
130 return ("BZ_UNKNOWN_ERROR");
133 #ifndef BZ_LOADER
134 #include <sys/sysmacros.h>
135 #endif
137 #ifdef _KERNEL
139 #include <sys/types.h>
140 #include <sys/cmn_err.h>
141 #include <sys/kmem.h>
143 void
144 bz_internal_error(int errcode)
146 panic("bzip2 internal error: %s\n", BZ2_bzErrorString(errcode));
149 /*---------------------------------------------------*/
150 typedef struct {
151 char *buf;
152 size_t sz;
153 } bzap;
155 static
156 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
158 size_t sz = sizeof (bzap) + BZ2_BZALLOC_ALIGN + (items * size);
159 uintptr_t p = (uintptr_t)kmem_alloc(sz, KM_SLEEP);
161 if (p != NULL) {
162 bzap *pp = (bzap *)((p + sizeof (bzap) + BZ2_BZALLOC_ALIGN - 1) &
163 -BZ2_BZALLOC_ALIGN);
164 pp[-1].buf = (void *)p;
165 pp[-1].sz = sz;
166 return (pp);
168 return (NULL);
171 static
172 void default_bzfree ( void* opaque, void* addr )
174 if (addr != NULL) {
175 bzap *pp = (bzap *)addr - 1;
176 kmem_free(pp->buf, pp->sz);
180 #else
182 /*---------------------------------------------------*/
183 static
184 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
186 void* v = malloc ( items * size );
187 return v;
190 static
191 void default_bzfree ( void* opaque, void* addr )
193 if (addr != NULL) free ( addr );
195 #endif /* _KERNEL */
197 /*---------------------------------------------------*/
198 #ifndef BZ_NO_COMPRESS
199 static
200 void prepare_new_block ( EState* s )
202 Int32 i;
203 s->nblock = 0;
204 s->numZ = 0;
205 s->state_out_pos = 0;
206 BZ_INITIALISE_CRC ( s->blockCRC );
207 for (i = 0; i < 256; i++) s->inUse[i] = False;
208 s->blockNo++;
212 /*---------------------------------------------------*/
213 static
214 void init_RL ( EState* s )
216 s->state_in_ch = 256;
217 s->state_in_len = 0;
221 static
222 Bool isempty_RL ( EState* s )
224 if (s->state_in_ch < 256 && s->state_in_len > 0)
225 return False; else
226 return True;
230 /*---------------------------------------------------*/
231 int BZ_API(BZ2_bzCompressInit)
232 ( bz_stream* strm,
233 int blockSize100k,
234 int verbosity,
235 int workFactor )
237 Int32 n;
238 EState* s;
240 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
242 if (strm == NULL ||
243 blockSize100k < 1 || blockSize100k > 9 ||
244 workFactor < 0 || workFactor > 250)
245 return BZ_PARAM_ERROR;
247 if (workFactor == 0) workFactor = 30;
248 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
249 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
251 s = BZALLOC( sizeof(EState) );
252 if (s == NULL) return BZ_MEM_ERROR;
253 s->strm = strm;
255 s->arr1 = NULL;
256 s->arr2 = NULL;
257 s->ftab = NULL;
259 n = 100000 * blockSize100k;
260 s->arr1 = BZALLOC( n * sizeof(UInt32) );
261 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
262 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
264 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
265 if (s->arr1 != NULL) BZFREE(s->arr1);
266 if (s->arr2 != NULL) BZFREE(s->arr2);
267 if (s->ftab != NULL) BZFREE(s->ftab);
268 if (s != NULL) BZFREE(s);
269 return BZ_MEM_ERROR;
272 s->blockNo = 0;
273 s->state = BZ_S_INPUT;
274 s->mode = BZ_M_RUNNING;
275 s->combinedCRC = 0;
276 s->blockSize100k = blockSize100k;
277 s->nblockMAX = 100000 * blockSize100k - 19;
278 s->verbosity = verbosity;
279 s->workFactor = workFactor;
281 s->block = (UChar*)s->arr2;
282 s->mtfv = (UInt16*)s->arr1;
283 s->zbits = NULL;
284 s->ptr = (UInt32*)s->arr1;
286 strm->state = s;
287 strm->total_in_lo32 = 0;
288 strm->total_in_hi32 = 0;
289 strm->total_out_lo32 = 0;
290 strm->total_out_hi32 = 0;
291 init_RL ( s );
292 prepare_new_block ( s );
293 return BZ_OK;
296 /*---------------------------------------------------*/
298 * returns the BZALLOC size needed for bzCompressInit
300 int BZ_API(BZ2_bzCompressInitSize) (
301 int blockSize100k)
303 Int32 n, t;
305 n = 100000 * blockSize100k;
306 t = 0;
307 t += ( sizeof(EState) );
308 t = P2ROUNDUP(t, BZ2_BZALLOC_ALIGN);
309 t += ( n * sizeof(UInt32) );
310 t = P2ROUNDUP(t, BZ2_BZALLOC_ALIGN);
311 t += ( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
312 t = P2ROUNDUP(t, BZ2_BZALLOC_ALIGN);
313 t += ( 65537 * sizeof(UInt32) );
314 t = P2ROUNDUP(t, BZ2_BZALLOC_ALIGN);
315 return (t);
318 /*---------------------------------------------------*/
320 * added to allow reuse of bz_stream without malloc/free
322 int BZ_API(BZ2_bzCompressReset) ( bz_stream *strm )
324 EState* s = strm->state;
326 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
328 if (s == NULL) return BZ_MEM_ERROR;
329 s->strm = strm;
331 s->blockNo = 0;
332 s->state = BZ_S_INPUT;
333 s->mode = BZ_M_RUNNING;
334 s->combinedCRC = 0;
335 s->nblockMAX = 100000 * s->blockSize100k - 19;
337 s->block = (UChar*)s->arr2;
338 s->mtfv = (UInt16*)s->arr1;
339 s->zbits = NULL;
340 s->ptr = (UInt32*)s->arr1;
342 strm->state = s;
343 strm->total_in_lo32 = 0;
344 strm->total_in_hi32 = 0;
345 strm->total_out_lo32 = 0;
346 strm->total_out_hi32 = 0;
347 init_RL ( s );
348 prepare_new_block ( s );
349 return BZ_OK;
353 /*---------------------------------------------------*/
354 static
355 void add_pair_to_block ( EState* s )
357 Int32 i;
358 UChar ch = (UChar)(s->state_in_ch);
359 for (i = 0; i < s->state_in_len; i++) {
360 BZ_UPDATE_CRC( s->blockCRC, ch );
362 s->inUse[s->state_in_ch] = True;
363 switch (s->state_in_len) {
364 case 1:
365 s->block[s->nblock] = (UChar)ch; s->nblock++;
366 break;
367 case 2:
368 s->block[s->nblock] = (UChar)ch; s->nblock++;
369 s->block[s->nblock] = (UChar)ch; s->nblock++;
370 break;
371 case 3:
372 s->block[s->nblock] = (UChar)ch; s->nblock++;
373 s->block[s->nblock] = (UChar)ch; s->nblock++;
374 s->block[s->nblock] = (UChar)ch; s->nblock++;
375 break;
376 default:
377 s->inUse[s->state_in_len-4] = True;
378 s->block[s->nblock] = (UChar)ch; s->nblock++;
379 s->block[s->nblock] = (UChar)ch; s->nblock++;
380 s->block[s->nblock] = (UChar)ch; s->nblock++;
381 s->block[s->nblock] = (UChar)ch; s->nblock++;
382 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
383 s->nblock++;
384 break;
389 /*---------------------------------------------------*/
390 static
391 void flush_RL ( EState* s )
393 if (s->state_in_ch < 256) add_pair_to_block ( s );
394 init_RL ( s );
398 /*---------------------------------------------------*/
399 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
401 UInt32 zchh = (UInt32)(zchh0); \
402 /*-- fast track the common case --*/ \
403 if (zchh != zs->state_in_ch && \
404 zs->state_in_len == 1) { \
405 UChar ch = (UChar)(zs->state_in_ch); \
406 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
407 zs->inUse[zs->state_in_ch] = True; \
408 zs->block[zs->nblock] = (UChar)ch; \
409 zs->nblock++; \
410 zs->state_in_ch = zchh; \
412 else \
413 /*-- general, uncommon cases --*/ \
414 if (zchh != zs->state_in_ch || \
415 zs->state_in_len == 255) { \
416 if (zs->state_in_ch < 256) \
417 add_pair_to_block ( zs ); \
418 zs->state_in_ch = zchh; \
419 zs->state_in_len = 1; \
420 } else { \
421 zs->state_in_len++; \
426 /*---------------------------------------------------*/
427 static
428 Bool copy_input_until_stop ( EState* s )
430 Bool progress_in = False;
432 if (s->mode == BZ_M_RUNNING) {
434 /*-- fast track the common case --*/
435 while (True) {
436 /*-- block full? --*/
437 if (s->nblock >= s->nblockMAX) break;
438 /*-- no input? --*/
439 if (s->strm->avail_in == 0) break;
440 progress_in = True;
441 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
442 s->strm->next_in++;
443 s->strm->avail_in--;
444 s->strm->total_in_lo32++;
445 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
448 } else {
450 /*-- general, uncommon case --*/
451 while (True) {
452 /*-- block full? --*/
453 if (s->nblock >= s->nblockMAX) break;
454 /*-- no input? --*/
455 if (s->strm->avail_in == 0) break;
456 /*-- flush/finish end? --*/
457 if (s->avail_in_expect == 0) break;
458 progress_in = True;
459 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
460 s->strm->next_in++;
461 s->strm->avail_in--;
462 s->strm->total_in_lo32++;
463 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
464 s->avail_in_expect--;
467 return progress_in;
471 /*---------------------------------------------------*/
472 static
473 Bool copy_output_until_stop ( EState* s )
475 Bool progress_out = False;
477 while (True) {
479 /*-- no output space? --*/
480 if (s->strm->avail_out == 0) break;
482 /*-- block done? --*/
483 if (s->state_out_pos >= s->numZ) break;
485 progress_out = True;
486 *(s->strm->next_out) = s->zbits[s->state_out_pos];
487 s->state_out_pos++;
488 s->strm->avail_out--;
489 s->strm->next_out++;
490 s->strm->total_out_lo32++;
491 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
494 return progress_out;
498 /*---------------------------------------------------*/
499 static
500 Bool handle_compress ( bz_stream* strm )
502 Bool progress_in = False;
503 Bool progress_out = False;
504 EState* s = strm->state;
506 while (True) {
508 if (s->state == BZ_S_OUTPUT) {
509 progress_out |= copy_output_until_stop ( s );
510 if (s->state_out_pos < s->numZ) break;
511 if (s->mode == BZ_M_FINISHING &&
512 s->avail_in_expect == 0 &&
513 isempty_RL(s)) break;
514 prepare_new_block ( s );
515 s->state = BZ_S_INPUT;
516 if (s->mode == BZ_M_FLUSHING &&
517 s->avail_in_expect == 0 &&
518 isempty_RL(s)) break;
521 if (s->state == BZ_S_INPUT) {
522 progress_in |= copy_input_until_stop ( s );
523 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
524 flush_RL ( s );
525 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
526 s->state = BZ_S_OUTPUT;
528 else
529 if (s->nblock >= s->nblockMAX) {
530 BZ2_compressBlock ( s, False );
531 s->state = BZ_S_OUTPUT;
533 else
534 if (s->strm->avail_in == 0) {
535 break;
541 return progress_in || progress_out;
545 /*---------------------------------------------------*/
546 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
548 Bool progress;
549 EState* s;
550 if (strm == NULL) return BZ_PARAM_ERROR;
551 s = strm->state;
552 if (s == NULL) return BZ_PARAM_ERROR;
553 if (s->strm != strm) return BZ_PARAM_ERROR;
555 preswitch:
556 switch (s->mode) {
558 case BZ_M_IDLE:
559 return BZ_SEQUENCE_ERROR;
561 case BZ_M_RUNNING:
562 if (action == BZ_RUN) {
563 progress = handle_compress ( strm );
564 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
566 else
567 if (action == BZ_FLUSH) {
568 s->avail_in_expect = strm->avail_in;
569 s->mode = BZ_M_FLUSHING;
570 goto preswitch;
572 else
573 if (action == BZ_FINISH) {
574 s->avail_in_expect = strm->avail_in;
575 s->mode = BZ_M_FINISHING;
576 goto preswitch;
578 else
579 return BZ_PARAM_ERROR;
581 case BZ_M_FLUSHING:
582 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
583 if (s->avail_in_expect != s->strm->avail_in)
584 return BZ_SEQUENCE_ERROR;
585 progress = handle_compress ( strm );
586 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
587 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
588 s->mode = BZ_M_RUNNING;
589 return BZ_RUN_OK;
591 case BZ_M_FINISHING:
592 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
593 if (s->avail_in_expect != s->strm->avail_in)
594 return BZ_SEQUENCE_ERROR;
595 progress = handle_compress ( strm );
596 if (!progress) return BZ_SEQUENCE_ERROR;
597 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
598 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
599 s->mode = BZ_M_IDLE;
600 return BZ_STREAM_END;
602 return BZ_OK; /*--not reached--*/
606 /*---------------------------------------------------*/
607 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
609 EState* s;
610 if (strm == NULL) return BZ_PARAM_ERROR;
611 s = strm->state;
612 if (s == NULL) return BZ_PARAM_ERROR;
613 if (s->strm != strm) return BZ_PARAM_ERROR;
615 if (s->arr1 != NULL) BZFREE(s->arr1);
616 if (s->arr2 != NULL) BZFREE(s->arr2);
617 if (s->ftab != NULL) BZFREE(s->ftab);
618 BZFREE(strm->state);
620 strm->state = NULL;
622 return BZ_OK;
625 #endif /* BZ_NO_COMPRESS */
627 /*---------------------------------------------------*/
628 /*--- Decompression stuff ---*/
629 /*---------------------------------------------------*/
631 /*---------------------------------------------------*/
632 int BZ_API(BZ2_bzDecompressInit)
633 ( bz_stream* strm,
634 int verbosity,
635 int small )
637 DState* s;
639 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
641 if (strm == NULL) return BZ_PARAM_ERROR;
642 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
643 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
645 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
646 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
648 s = BZALLOC( sizeof(DState) );
649 if (s == NULL) return BZ_MEM_ERROR;
650 s->strm = strm;
651 strm->state = s;
652 s->state = BZ_X_MAGIC_1;
653 s->bsLive = 0;
654 s->bsBuff = 0;
655 s->calculatedCombinedCRC = 0;
656 strm->total_in_lo32 = 0;
657 strm->total_in_hi32 = 0;
658 strm->total_out_lo32 = 0;
659 strm->total_out_hi32 = 0;
660 s->smallDecompress = (Bool)small;
661 s->ll4 = NULL;
662 s->ll16 = NULL;
663 s->tt = NULL;
664 s->currBlockNo = 0;
665 s->verbosity = verbosity;
667 return BZ_OK;
670 /*---------------------------------------------------*/
672 * added to allow reuse of bz_stream without malloc/free
674 int BZ_API(BZ2_bzDecompressReset) ( bz_stream* strm )
676 DState* s = strm->state;
678 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
680 if (strm == NULL) return BZ_PARAM_ERROR;
682 s->strm = strm;
684 s->state = BZ_X_MAGIC_1;
685 s->bsLive = 0;
686 s->bsBuff = 0;
687 s->calculatedCombinedCRC = 0;
688 strm->total_in_lo32 = 0;
689 strm->total_in_hi32 = 0;
690 strm->total_out_lo32 = 0;
691 strm->total_out_hi32 = 0;
693 s->ll4 = NULL;
694 s->ll16 = NULL;
695 s->tt = NULL;
696 s->currBlockNo = 0;
699 return BZ_OK;
703 /*---------------------------------------------------*/
704 /* Return True iff data corruption is discovered.
705 Returns False if there is no problem.
707 static
708 Bool unRLE_obuf_to_output_FAST ( DState* s )
710 UChar k1;
712 if (s->blockRandomised) {
714 while (True) {
715 /* try to finish existing run */
716 while (True) {
717 if (s->strm->avail_out == 0) return False;
718 if (s->state_out_len == 0) break;
719 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
720 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
721 s->state_out_len--;
722 s->strm->next_out++;
723 s->strm->avail_out--;
724 s->strm->total_out_lo32++;
725 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
728 /* can a new run be started? */
729 if (s->nblock_used == s->save_nblock+1) return False;
731 /* Only caused by corrupt data stream? */
732 if (s->nblock_used > s->save_nblock+1)
733 return True;
735 s->state_out_len = 1;
736 s->state_out_ch = s->k0;
737 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
738 k1 ^= BZ_RAND_MASK; s->nblock_used++;
739 if (s->nblock_used == s->save_nblock+1) continue;
740 if (k1 != s->k0) { s->k0 = k1; continue; };
742 s->state_out_len = 2;
743 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
744 k1 ^= BZ_RAND_MASK; s->nblock_used++;
745 if (s->nblock_used == s->save_nblock+1) continue;
746 if (k1 != s->k0) { s->k0 = k1; continue; };
748 s->state_out_len = 3;
749 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
750 k1 ^= BZ_RAND_MASK; s->nblock_used++;
751 if (s->nblock_used == s->save_nblock+1) continue;
752 if (k1 != s->k0) { s->k0 = k1; continue; };
754 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
755 k1 ^= BZ_RAND_MASK; s->nblock_used++;
756 s->state_out_len = ((Int32)k1) + 4;
757 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
758 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
761 } else {
763 /* restore */
764 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
765 UChar c_state_out_ch = s->state_out_ch;
766 Int32 c_state_out_len = s->state_out_len;
767 Int32 c_nblock_used = s->nblock_used;
768 Int32 c_k0 = s->k0;
769 UInt32* c_tt = s->tt;
770 UInt32 c_tPos = s->tPos;
771 char* cs_next_out = s->strm->next_out;
772 unsigned int cs_avail_out = s->strm->avail_out;
773 Int32 ro_blockSize100k = s->blockSize100k;
774 /* end restore */
776 UInt32 avail_out_INIT = cs_avail_out;
777 Int32 s_save_nblockPP = s->save_nblock+1;
778 unsigned int total_out_lo32_old;
780 while (True) {
782 /* try to finish existing run */
783 if (c_state_out_len > 0) {
784 while (True) {
785 if (cs_avail_out == 0) goto return_notr;
786 if (c_state_out_len == 1) break;
787 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
788 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
789 c_state_out_len--;
790 cs_next_out++;
791 cs_avail_out--;
793 s_state_out_len_eq_one:
795 if (cs_avail_out == 0) {
796 c_state_out_len = 1; goto return_notr;
798 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
799 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
800 cs_next_out++;
801 cs_avail_out--;
804 /* Only caused by corrupt data stream? */
805 if (c_nblock_used > s_save_nblockPP)
806 return True;
808 /* can a new run be started? */
809 if (c_nblock_used == s_save_nblockPP) {
810 c_state_out_len = 0; goto return_notr;
812 c_state_out_ch = c_k0;
813 BZ_GET_FAST_C(k1); c_nblock_used++;
814 if (k1 != c_k0) {
815 c_k0 = k1; goto s_state_out_len_eq_one;
817 if (c_nblock_used == s_save_nblockPP)
818 goto s_state_out_len_eq_one;
820 c_state_out_len = 2;
821 BZ_GET_FAST_C(k1); c_nblock_used++;
822 if (c_nblock_used == s_save_nblockPP) continue;
823 if (k1 != c_k0) { c_k0 = k1; continue; };
825 c_state_out_len = 3;
826 BZ_GET_FAST_C(k1); c_nblock_used++;
827 if (c_nblock_used == s_save_nblockPP) continue;
828 if (k1 != c_k0) { c_k0 = k1; continue; };
830 BZ_GET_FAST_C(k1); c_nblock_used++;
831 c_state_out_len = ((Int32)k1) + 4;
832 BZ_GET_FAST_C(c_k0); c_nblock_used++;
835 return_notr:
836 total_out_lo32_old = s->strm->total_out_lo32;
837 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
838 if (s->strm->total_out_lo32 < total_out_lo32_old)
839 s->strm->total_out_hi32++;
841 /* save */
842 s->calculatedBlockCRC = c_calculatedBlockCRC;
843 s->state_out_ch = c_state_out_ch;
844 s->state_out_len = c_state_out_len;
845 s->nblock_used = c_nblock_used;
846 s->k0 = c_k0;
847 s->tt = c_tt;
848 s->tPos = c_tPos;
849 s->strm->next_out = cs_next_out;
850 s->strm->avail_out = cs_avail_out;
851 /* end save */
853 return False;
858 /*---------------------------------------------------*/
859 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
861 Int32 nb, na, mid;
862 nb = 0;
863 na = 256;
864 do {
865 mid = (nb + na) >> 1;
866 if (indx >= cftab[mid]) nb = mid; else na = mid;
868 while (na - nb != 1);
869 return nb;
873 /*---------------------------------------------------*/
874 /* Return True iff data corruption is discovered.
875 Returns False if there is no problem.
877 static
878 Bool unRLE_obuf_to_output_SMALL ( DState* s )
880 UChar k1;
882 if (s->blockRandomised) {
884 while (True) {
885 /* try to finish existing run */
886 while (True) {
887 if (s->strm->avail_out == 0) return False;
888 if (s->state_out_len == 0) break;
889 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
890 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
891 s->state_out_len--;
892 s->strm->next_out++;
893 s->strm->avail_out--;
894 s->strm->total_out_lo32++;
895 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
898 /* can a new run be started? */
899 if (s->nblock_used == s->save_nblock+1) return False;
901 /* Only caused by corrupt data stream? */
902 if (s->nblock_used > s->save_nblock+1)
903 return True;
905 s->state_out_len = 1;
906 s->state_out_ch = s->k0;
907 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
908 k1 ^= BZ_RAND_MASK; s->nblock_used++;
909 if (s->nblock_used == s->save_nblock+1) continue;
910 if (k1 != s->k0) { s->k0 = k1; continue; };
912 s->state_out_len = 2;
913 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
914 k1 ^= BZ_RAND_MASK; s->nblock_used++;
915 if (s->nblock_used == s->save_nblock+1) continue;
916 if (k1 != s->k0) { s->k0 = k1; continue; };
918 s->state_out_len = 3;
919 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
920 k1 ^= BZ_RAND_MASK; s->nblock_used++;
921 if (s->nblock_used == s->save_nblock+1) continue;
922 if (k1 != s->k0) { s->k0 = k1; continue; };
924 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
925 k1 ^= BZ_RAND_MASK; s->nblock_used++;
926 s->state_out_len = ((Int32)k1) + 4;
927 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
928 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
931 } else {
933 while (True) {
934 /* try to finish existing run */
935 while (True) {
936 if (s->strm->avail_out == 0) return False;
937 if (s->state_out_len == 0) break;
938 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
939 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
940 s->state_out_len--;
941 s->strm->next_out++;
942 s->strm->avail_out--;
943 s->strm->total_out_lo32++;
944 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
947 /* can a new run be started? */
948 if (s->nblock_used == s->save_nblock+1) return False;
950 /* Only caused by corrupt data stream? */
951 if (s->nblock_used > s->save_nblock+1)
952 return True;
954 s->state_out_len = 1;
955 s->state_out_ch = s->k0;
956 BZ_GET_SMALL(k1); s->nblock_used++;
957 if (s->nblock_used == s->save_nblock+1) continue;
958 if (k1 != s->k0) { s->k0 = k1; continue; };
960 s->state_out_len = 2;
961 BZ_GET_SMALL(k1); s->nblock_used++;
962 if (s->nblock_used == s->save_nblock+1) continue;
963 if (k1 != s->k0) { s->k0 = k1; continue; };
965 s->state_out_len = 3;
966 BZ_GET_SMALL(k1); s->nblock_used++;
967 if (s->nblock_used == s->save_nblock+1) continue;
968 if (k1 != s->k0) { s->k0 = k1; continue; };
970 BZ_GET_SMALL(k1); s->nblock_used++;
971 s->state_out_len = ((Int32)k1) + 4;
972 BZ_GET_SMALL(s->k0); s->nblock_used++;
979 /*---------------------------------------------------*/
980 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
982 Bool corrupt;
983 DState* s;
984 if (strm == NULL) return BZ_PARAM_ERROR;
985 s = strm->state;
986 if (s == NULL) return BZ_PARAM_ERROR;
987 if (s->strm != strm) return BZ_PARAM_ERROR;
989 while (True) {
990 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
991 if (s->state == BZ_X_OUTPUT) {
992 if (s->smallDecompress)
993 corrupt = unRLE_obuf_to_output_SMALL ( s ); else
994 corrupt = unRLE_obuf_to_output_FAST ( s );
995 if (corrupt) return BZ_DATA_ERROR;
996 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
997 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
998 if (s->verbosity >= 3)
999 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
1000 s->calculatedBlockCRC );
1001 if (s->verbosity >= 2) VPrintf0 ( "]" );
1002 if (s->calculatedBlockCRC != s->storedBlockCRC)
1003 return BZ_DATA_ERROR;
1004 s->calculatedCombinedCRC
1005 = (s->calculatedCombinedCRC << 1) |
1006 (s->calculatedCombinedCRC >> 31);
1007 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
1008 s->state = BZ_X_BLKHDR_1;
1009 } else {
1010 return BZ_OK;
1013 if (s->state >= BZ_X_MAGIC_1) {
1014 Int32 r = BZ2_decompress ( s );
1015 if (r == BZ_STREAM_END) {
1016 if (s->verbosity >= 3)
1017 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
1018 s->storedCombinedCRC, s->calculatedCombinedCRC );
1019 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
1020 return BZ_DATA_ERROR;
1021 return r;
1023 if (s->state != BZ_X_OUTPUT) return r;
1027 #if 0
1028 AssertH ( 0, 6001 );
1030 return 0; /*NOTREACHED*/
1031 #endif
1035 /*---------------------------------------------------*/
1036 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
1038 DState* s;
1039 if (strm == NULL) return BZ_PARAM_ERROR;
1040 s = strm->state;
1041 if (s == NULL) return BZ_PARAM_ERROR;
1042 if (s->strm != strm) return BZ_PARAM_ERROR;
1044 if (s->tt != NULL) BZFREE(s->tt);
1045 if (s->ll16 != NULL) BZFREE(s->ll16);
1046 if (s->ll4 != NULL) BZFREE(s->ll4);
1048 BZFREE(strm->state);
1049 strm->state = NULL;
1051 return BZ_OK;
1054 #ifndef BZ_NO_COMPRESS
1056 #ifndef BZ_NO_STDIO
1057 /*---------------------------------------------------*/
1058 /*--- File I/O stuff ---*/
1059 /*---------------------------------------------------*/
1061 #define BZ_SETERR(eee) \
1063 if (bzerror != NULL) *bzerror = eee; \
1064 if (bzf != NULL) bzf->lastErr = eee; \
1067 typedef
1068 struct {
1069 FILE* handle;
1070 Char buf[BZ_MAX_UNUSED];
1071 Int32 bufN;
1072 Bool writing;
1073 bz_stream strm;
1074 Int32 lastErr;
1075 Bool initialisedOk;
1077 bzFile;
1080 /*---------------------------------------------*/
1081 static Bool myfeof ( FILE* f )
1083 Int32 c = fgetc ( f );
1084 if (c == EOF) return True;
1085 ungetc ( c, f );
1086 return False;
1090 /*---------------------------------------------------*/
1091 BZFILE* BZ_API(BZ2_bzWriteOpen)
1092 ( int* bzerror,
1093 FILE* f,
1094 int blockSize100k,
1095 int verbosity,
1096 int workFactor )
1098 Int32 ret;
1099 bzFile* bzf = NULL;
1101 BZ_SETERR(BZ_OK);
1103 if (f == NULL ||
1104 (blockSize100k < 1 || blockSize100k > 9) ||
1105 (workFactor < 0 || workFactor > 250) ||
1106 (verbosity < 0 || verbosity > 4))
1107 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1109 if (ferror(f))
1110 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1112 bzf = malloc ( sizeof(bzFile) );
1113 if (bzf == NULL)
1114 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1116 BZ_SETERR(BZ_OK);
1117 bzf->initialisedOk = False;
1118 bzf->bufN = 0;
1119 bzf->handle = f;
1120 bzf->writing = True;
1121 bzf->strm.bzalloc = NULL;
1122 bzf->strm.bzfree = NULL;
1123 bzf->strm.opaque = NULL;
1125 if (workFactor == 0) workFactor = 30;
1126 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
1127 verbosity, workFactor );
1128 if (ret != BZ_OK)
1129 { BZ_SETERR(ret); free(bzf); return NULL; };
1131 bzf->strm.avail_in = 0;
1132 bzf->initialisedOk = True;
1133 return bzf;
1138 /*---------------------------------------------------*/
1139 void BZ_API(BZ2_bzWrite)
1140 ( int* bzerror,
1141 BZFILE* b,
1142 void* buf,
1143 int len )
1145 Int32 n, n2, ret;
1146 bzFile* bzf = (bzFile*)b;
1148 BZ_SETERR(BZ_OK);
1149 if (bzf == NULL || buf == NULL || len < 0)
1150 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1151 if (!(bzf->writing))
1152 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1153 if (ferror(bzf->handle))
1154 { BZ_SETERR(BZ_IO_ERROR); return; };
1156 if (len == 0)
1157 { BZ_SETERR(BZ_OK); return; };
1159 bzf->strm.avail_in = len;
1160 bzf->strm.next_in = buf;
1162 while (True) {
1163 bzf->strm.avail_out = BZ_MAX_UNUSED;
1164 bzf->strm.next_out = bzf->buf;
1165 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
1166 if (ret != BZ_RUN_OK)
1167 { BZ_SETERR(ret); return; };
1169 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1170 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1171 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1172 n, bzf->handle );
1173 if (n != n2 || ferror(bzf->handle))
1174 { BZ_SETERR(BZ_IO_ERROR); return; };
1177 if (bzf->strm.avail_in == 0)
1178 { BZ_SETERR(BZ_OK); return; };
1183 /*---------------------------------------------------*/
1184 void BZ_API(BZ2_bzWriteClose)
1185 ( int* bzerror,
1186 BZFILE* b,
1187 int abandon,
1188 unsigned int* nbytes_in,
1189 unsigned int* nbytes_out )
1191 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1192 nbytes_in, NULL, nbytes_out, NULL );
1196 void BZ_API(BZ2_bzWriteClose64)
1197 ( int* bzerror,
1198 BZFILE* b,
1199 int abandon,
1200 unsigned int* nbytes_in_lo32,
1201 unsigned int* nbytes_in_hi32,
1202 unsigned int* nbytes_out_lo32,
1203 unsigned int* nbytes_out_hi32 )
1205 Int32 n, n2, ret;
1206 bzFile* bzf = (bzFile*)b;
1208 if (bzf == NULL)
1209 { BZ_SETERR(BZ_OK); return; };
1210 if (!(bzf->writing))
1211 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1212 if (ferror(bzf->handle))
1213 { BZ_SETERR(BZ_IO_ERROR); return; };
1215 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1216 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1217 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1218 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1220 if ((!abandon) && bzf->lastErr == BZ_OK) {
1221 while (True) {
1222 bzf->strm.avail_out = BZ_MAX_UNUSED;
1223 bzf->strm.next_out = bzf->buf;
1224 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1225 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1226 { BZ_SETERR(ret); return; };
1228 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1229 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1230 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1231 n, bzf->handle );
1232 if (n != n2 || ferror(bzf->handle))
1233 { BZ_SETERR(BZ_IO_ERROR); return; };
1236 if (ret == BZ_STREAM_END) break;
1240 if ( !abandon && !ferror ( bzf->handle ) ) {
1241 fflush ( bzf->handle );
1242 if (ferror(bzf->handle))
1243 { BZ_SETERR(BZ_IO_ERROR); return; };
1246 if (nbytes_in_lo32 != NULL)
1247 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1248 if (nbytes_in_hi32 != NULL)
1249 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1250 if (nbytes_out_lo32 != NULL)
1251 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1252 if (nbytes_out_hi32 != NULL)
1253 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1255 BZ_SETERR(BZ_OK);
1256 (void) BZ2_bzCompressEnd ( &(bzf->strm) );
1257 free ( bzf );
1261 /*---------------------------------------------------*/
1262 BZFILE* BZ_API(BZ2_bzReadOpen)
1263 ( int* bzerror,
1264 FILE* f,
1265 int verbosity,
1266 int small,
1267 void* unused,
1268 int nUnused )
1270 bzFile* bzf = NULL;
1271 int ret;
1273 BZ_SETERR(BZ_OK);
1275 if (f == NULL ||
1276 (small != 0 && small != 1) ||
1277 (verbosity < 0 || verbosity > 4) ||
1278 (unused == NULL && nUnused != 0) ||
1279 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1280 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1282 if (ferror(f))
1283 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1285 bzf = malloc ( sizeof(bzFile) );
1286 if (bzf == NULL)
1287 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1289 BZ_SETERR(BZ_OK);
1291 bzf->initialisedOk = False;
1292 bzf->handle = f;
1293 bzf->bufN = 0;
1294 bzf->writing = False;
1295 bzf->strm.bzalloc = NULL;
1296 bzf->strm.bzfree = NULL;
1297 bzf->strm.opaque = NULL;
1299 while (nUnused > 0) {
1300 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1301 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1302 nUnused--;
1305 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1306 if (ret != BZ_OK)
1307 { BZ_SETERR(ret); free(bzf); return NULL; };
1309 bzf->strm.avail_in = bzf->bufN;
1310 bzf->strm.next_in = bzf->buf;
1312 bzf->initialisedOk = True;
1313 return bzf;
1317 /*---------------------------------------------------*/
1318 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1320 bzFile* bzf = (bzFile*)b;
1322 BZ_SETERR(BZ_OK);
1323 if (bzf == NULL)
1324 { BZ_SETERR(BZ_OK); return; };
1326 if (bzf->writing)
1327 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1329 if (bzf->initialisedOk)
1330 (void) BZ2_bzDecompressEnd ( &(bzf->strm) );
1331 free ( bzf );
1335 /*---------------------------------------------------*/
1336 int BZ_API(BZ2_bzRead)
1337 ( int* bzerror,
1338 BZFILE* b,
1339 void* buf,
1340 int len )
1342 Int32 n, ret;
1343 bzFile* bzf = (bzFile*)b;
1345 BZ_SETERR(BZ_OK);
1347 if (bzf == NULL || buf == NULL || len < 0)
1348 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1350 if (bzf->writing)
1351 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1353 if (len == 0)
1354 { BZ_SETERR(BZ_OK); return 0; };
1356 bzf->strm.avail_out = len;
1357 bzf->strm.next_out = buf;
1359 while (True) {
1361 if (ferror(bzf->handle))
1362 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1364 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1365 n = fread ( bzf->buf, sizeof(UChar),
1366 BZ_MAX_UNUSED, bzf->handle );
1367 if (ferror(bzf->handle))
1368 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1369 bzf->bufN = n;
1370 bzf->strm.avail_in = bzf->bufN;
1371 bzf->strm.next_in = bzf->buf;
1374 ret = BZ2_bzDecompress ( &(bzf->strm) );
1376 if (ret != BZ_OK && ret != BZ_STREAM_END)
1377 { BZ_SETERR(ret); return 0; };
1379 if (ret == BZ_OK && myfeof(bzf->handle) &&
1380 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1381 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1383 if (ret == BZ_STREAM_END)
1384 { BZ_SETERR(BZ_STREAM_END);
1385 return len - bzf->strm.avail_out; };
1386 if (bzf->strm.avail_out == 0)
1387 { BZ_SETERR(BZ_OK); return len; };
1391 return 0; /*not reached*/
1395 /*---------------------------------------------------*/
1396 void BZ_API(BZ2_bzReadGetUnused)
1397 ( int* bzerror,
1398 BZFILE* b,
1399 void** unused,
1400 int* nUnused )
1402 bzFile* bzf = (bzFile*)b;
1403 if (bzf == NULL)
1404 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1405 if (bzf->lastErr != BZ_STREAM_END)
1406 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1407 if (unused == NULL || nUnused == NULL)
1408 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1410 BZ_SETERR(BZ_OK);
1411 *nUnused = bzf->strm.avail_in;
1412 *unused = bzf->strm.next_in;
1414 #endif
1417 /*---------------------------------------------------*/
1418 /*--- Misc convenience stuff ---*/
1419 /*---------------------------------------------------*/
1421 /*---------------------------------------------------*/
1422 int BZ_API(BZ2_bzBuffToBuffCompress)
1423 ( char* dest,
1424 unsigned int* destLen,
1425 char* source,
1426 unsigned int sourceLen,
1427 int blockSize100k,
1428 int verbosity,
1429 int workFactor )
1431 bz_stream strm;
1432 int ret;
1434 if (dest == NULL || destLen == NULL ||
1435 source == NULL ||
1436 blockSize100k < 1 || blockSize100k > 9 ||
1437 verbosity < 0 || verbosity > 4 ||
1438 workFactor < 0 || workFactor > 250)
1439 return BZ_PARAM_ERROR;
1441 if (workFactor == 0) workFactor = 30;
1442 strm.bzalloc = NULL;
1443 strm.bzfree = NULL;
1444 strm.opaque = NULL;
1445 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1446 verbosity, workFactor );
1447 if (ret != BZ_OK) return ret;
1449 strm.next_in = source;
1450 strm.next_out = dest;
1451 strm.avail_in = sourceLen;
1452 strm.avail_out = *destLen;
1454 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1455 if (ret == BZ_FINISH_OK) goto output_overflow;
1456 if (ret != BZ_STREAM_END) goto errhandler;
1458 /* normal termination */
1459 *destLen -= strm.avail_out;
1460 (void) BZ2_bzCompressEnd ( &strm );
1461 return BZ_OK;
1463 output_overflow:
1464 (void) BZ2_bzCompressEnd ( &strm );
1465 return BZ_OUTBUFF_FULL;
1467 errhandler:
1468 (void) BZ2_bzCompressEnd ( &strm );
1469 return ret;
1473 /*---------------------------------------------------*/
1474 int BZ_API(BZ2_bzBuffToBuffDecompress)
1475 ( char* dest,
1476 unsigned int* destLen,
1477 char* source,
1478 unsigned int sourceLen,
1479 int small,
1480 int verbosity )
1482 bz_stream strm;
1483 int ret;
1485 if (dest == NULL || destLen == NULL ||
1486 source == NULL ||
1487 (small != 0 && small != 1) ||
1488 verbosity < 0 || verbosity > 4)
1489 return BZ_PARAM_ERROR;
1491 strm.bzalloc = NULL;
1492 strm.bzfree = NULL;
1493 strm.opaque = NULL;
1494 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1495 if (ret != BZ_OK) return ret;
1497 strm.next_in = source;
1498 strm.next_out = dest;
1499 strm.avail_in = sourceLen;
1500 strm.avail_out = *destLen;
1502 ret = BZ2_bzDecompress ( &strm );
1503 if (ret == BZ_OK) goto output_overflow_or_eof;
1504 if (ret != BZ_STREAM_END) goto errhandler;
1506 /* normal termination */
1507 *destLen -= strm.avail_out;
1508 (void) BZ2_bzDecompressEnd ( &strm );
1509 return BZ_OK;
1511 output_overflow_or_eof:
1512 if (strm.avail_out > 0) {
1513 (void) BZ2_bzDecompressEnd ( &strm );
1514 return BZ_UNEXPECTED_EOF;
1515 } else {
1516 (void) BZ2_bzDecompressEnd ( &strm );
1517 return BZ_OUTBUFF_FULL;
1520 errhandler:
1521 (void) BZ2_bzDecompressEnd ( &strm );
1522 return ret;
1526 /*---------------------------------------------------*/
1527 /*--
1528 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1529 to support better zlib compatibility.
1530 This code is not _officially_ part of libbzip2 (yet);
1531 I haven't tested it, documented it, or considered the
1532 threading-safeness of it.
1533 If this code breaks, please contact both Yoshioka and me.
1534 --*/
1535 /*---------------------------------------------------*/
1537 /*---------------------------------------------------*/
1538 /*--
1539 return version like "0.9.5d, 4-Sept-1999".
1540 --*/
1541 const char * BZ_API(BZ2_bzlibVersion)(void)
1543 return BZ_VERSION;
1547 #ifndef BZ_NO_STDIO
1548 /*---------------------------------------------------*/
1550 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1551 # include <fcntl.h>
1552 # include <io.h>
1553 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1554 #else
1555 # define SET_BINARY_MODE(file)
1556 #endif
1557 static
1558 BZFILE * bzopen_or_bzdopen
1559 ( const char *path, /* no use when bzdopen */
1560 int fd, /* no use when bzdopen */
1561 const char *mode,
1562 int open_mode) /* bzopen: 0, bzdopen:1 */
1564 int bzerr;
1565 char unused[BZ_MAX_UNUSED];
1566 int blockSize100k = 9;
1567 int writing = 0;
1568 char mode2[10] = "";
1569 FILE *fp = NULL;
1570 BZFILE *bzfp = NULL;
1571 int verbosity = 0;
1572 int workFactor = 30;
1573 int smallMode = 0;
1574 int nUnused = 0;
1576 if (mode == NULL) return NULL;
1577 while (*mode) {
1578 switch (*mode) {
1579 case 'r':
1580 writing = 0; break;
1581 case 'w':
1582 writing = 1; break;
1583 case 's':
1584 smallMode = 1; break;
1585 default:
1586 if (isdigit((int)(*mode))) {
1587 blockSize100k = *mode-BZ_HDR_0;
1590 mode++;
1592 strcat(mode2, writing ? "w" : "r" );
1593 strcat(mode2,"b"); /* binary mode */
1595 if (open_mode==0) {
1596 if (path==NULL || strcmp(path,"")==0) {
1597 fp = (writing ? stdout : stdin);
1598 SET_BINARY_MODE(fp);
1599 } else {
1600 fp = fopen(path,mode2);
1602 } else {
1603 #ifdef BZ_STRICT_ANSI
1604 fp = NULL;
1605 #else
1606 fp = fdopen(fd,mode2);
1607 #endif
1609 if (fp == NULL) return NULL;
1611 if (writing) {
1612 /* Guard against total chaos and anarchy -- JRS */
1613 if (blockSize100k < 1) blockSize100k = 1;
1614 if (blockSize100k > 9) blockSize100k = 9;
1615 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1616 verbosity,workFactor);
1617 } else {
1618 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1619 unused,nUnused);
1621 if (bzfp == NULL) {
1622 if (fp != stdin && fp != stdout) fclose(fp);
1623 return NULL;
1625 return bzfp;
1629 /*---------------------------------------------------*/
1630 /*--
1631 open file for read or write.
1632 ex) bzopen("file","w9")
1633 case path="" or NULL => use stdin or stdout.
1634 --*/
1635 BZFILE * BZ_API(BZ2_bzopen)
1636 ( const char *path,
1637 const char *mode )
1639 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1643 /*---------------------------------------------------*/
1644 BZFILE * BZ_API(BZ2_bzdopen)
1645 ( int fd,
1646 const char *mode )
1648 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1652 /*---------------------------------------------------*/
1653 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1655 int bzerr, nread;
1656 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1657 nread = BZ2_bzRead(&bzerr,b,buf,len);
1658 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1659 return nread;
1660 } else {
1661 return -1;
1666 /*---------------------------------------------------*/
1667 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1669 int bzerr;
1671 BZ2_bzWrite(&bzerr,b,buf,len);
1672 if(bzerr == BZ_OK){
1673 return len;
1674 }else{
1675 return -1;
1680 /*---------------------------------------------------*/
1681 int BZ_API(BZ2_bzflush) (BZFILE *b)
1683 /* do nothing now... */
1684 return 0;
1688 /*---------------------------------------------------*/
1689 void BZ_API(BZ2_bzclose) (BZFILE* b)
1691 int bzerr;
1692 FILE *fp;
1694 if (b==NULL) {return;}
1695 fp = ((bzFile *)b)->handle;
1696 if(((bzFile*)b)->writing){
1697 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1698 if(bzerr != BZ_OK){
1699 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1701 }else{
1702 BZ2_bzReadClose(&bzerr,b);
1704 if(fp!=stdin && fp!=stdout){
1705 fclose(fp);
1710 /*---------------------------------------------------*/
1711 /*--
1712 return last error code
1713 --*/
1714 static const char *bzerrorstrings[] = {
1715 "OK"
1716 ,"SEQUENCE_ERROR"
1717 ,"PARAM_ERROR"
1718 ,"MEM_ERROR"
1719 ,"DATA_ERROR"
1720 ,"DATA_ERROR_MAGIC"
1721 ,"IO_ERROR"
1722 ,"UNEXPECTED_EOF"
1723 ,"OUTBUFF_FULL"
1724 ,"CONFIG_ERROR"
1725 ,"???" /* for future */
1726 ,"???" /* for future */
1727 ,"???" /* for future */
1728 ,"???" /* for future */
1729 ,"???" /* for future */
1730 ,"???" /* for future */
1734 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1736 int err = ((bzFile *)b)->lastErr;
1738 if(err>0) err = 0;
1739 *errnum = err;
1740 return bzerrorstrings[err*-1];
1742 #endif
1744 #endif /* BZ_NO_COMPRESS */
1746 /*-------------------------------------------------------------*/
1747 /*--- end bzlib.c ---*/
1748 /*-------------------------------------------------------------*/