MINI2440: Auto probe for SDRAM size
[u-boot-openmoko/mini2440.git] / lib_generic / bzlib.c
blob0d3f9c2d3ea0e6d379fb220306e1e5375a67553c
1 #include <config.h>
2 #include <common.h>
3 #include <watchdog.h>
4 #ifdef CONFIG_BZIP2
6 /*
7 * This file is a modified version of bzlib.c from the bzip2-1.0.2
8 * distribution which can be found at http://sources.redhat.com/bzip2/
9 */
11 /*-------------------------------------------------------------*/
12 /*--- Library top-level functions. ---*/
13 /*--- bzlib.c ---*/
14 /*-------------------------------------------------------------*/
16 /*--
17 This file is a part of bzip2 and/or libbzip2, a program and
18 library for lossless, block-sorting data compression.
20 Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
22 Redistribution and use in source and binary forms, with or without
23 modification, are permitted provided that the following conditions
24 are met:
26 1. Redistributions of source code must retain the above copyright
27 notice, this list of conditions and the following disclaimer.
29 2. The origin of this software must not be misrepresented; you must
30 not claim that you wrote the original software. If you use this
31 software in a product, an acknowledgment in the product
32 documentation would be appreciated but is not required.
34 3. Altered source versions must be plainly marked as such, and must
35 not be misrepresented as being the original software.
37 4. The name of the author may not be used to endorse or promote
38 products derived from this software without specific prior written
39 permission.
41 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
42 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
45 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
47 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
48 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
50 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
51 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 Julian Seward, Cambridge, UK.
54 jseward@acm.org
55 bzip2/libbzip2 version 1.0 of 21 March 2000
57 This program is based on (at least) the work of:
58 Mike Burrows
59 David Wheeler
60 Peter Fenwick
61 Alistair Moffat
62 Radford Neal
63 Ian H. Witten
64 Robert Sedgewick
65 Jon L. Bentley
67 For more information on these sources, see the manual.
68 --*/
70 /*--
71 CHANGES
72 ~~~~~~~
73 0.9.0 -- original version.
75 0.9.0a/b -- no changes in this file.
77 0.9.0c
78 * made zero-length BZ_FLUSH work correctly in bzCompress().
79 * fixed bzWrite/bzRead to ignore zero-length requests.
80 * fixed bzread to correctly handle read requests after EOF.
81 * wrong parameter order in call to bzDecompressInit in
82 bzBuffToBuffDecompress. Fixed.
83 --*/
85 #include "bzlib_private.h"
87 /*---------------------------------------------------*/
88 /*--- Compression stuff ---*/
89 /*---------------------------------------------------*/
92 /*---------------------------------------------------*/
93 #ifndef BZ_NO_STDIO
94 void BZ2_bz__AssertH__fail ( int errcode )
96 fprintf(stderr,
97 "\n\nbzip2/libbzip2: internal error number %d.\n"
98 "This is a bug in bzip2/libbzip2, %s.\n"
99 "Please report it to me at: jseward@acm.org. If this happened\n"
100 "when you were using some program which uses libbzip2 as a\n"
101 "component, you should also report this bug to the author(s)\n"
102 "of that program. Please make an effort to report this bug;\n"
103 "timely and accurate bug reports eventually lead to higher\n"
104 "quality software. Thanks. Julian Seward, 30 December 2001.\n\n",
105 errcode,
106 BZ2_bzlibVersion()
109 if (errcode == 1007) {
110 fprintf(stderr,
111 "\n*** A special note about internal error number 1007 ***\n"
112 "\n"
113 "Experience suggests that a common cause of i.e. 1007\n"
114 "is unreliable memory or other hardware. The 1007 assertion\n"
115 "just happens to cross-check the results of huge numbers of\n"
116 "memory reads/writes, and so acts (unintendedly) as a stress\n"
117 "test of your memory system.\n"
118 "\n"
119 "I suggest the following: try compressing the file again,\n"
120 "possibly monitoring progress in detail with the -vv flag.\n"
121 "\n"
122 "* If the error cannot be reproduced, and/or happens at different\n"
123 " points in compression, you may have a flaky memory system.\n"
124 " Try a memory-test program. I have used Memtest86\n"
125 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
126 " Memtest86 tests memory much more thorougly than your BIOSs\n"
127 " power-on test, and may find failures that the BIOS doesn't.\n"
128 "\n"
129 "* If the error can be repeatably reproduced, this is a bug in\n"
130 " bzip2, and I would very much like to hear about it. Please\n"
131 " let me know, and, ideally, save a copy of the file causing the\n"
132 " problem -- without which I will be unable to investigate it.\n"
133 "\n"
137 exit(3);
139 #endif
142 /*---------------------------------------------------*/
143 static
144 int bz_config_ok ( void )
146 if (sizeof(int) != 4) return 0;
147 if (sizeof(short) != 2) return 0;
148 if (sizeof(char) != 1) return 0;
149 return 1;
153 /*---------------------------------------------------*/
154 static
155 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
157 void* v = malloc ( items * size );
158 return v;
161 static
162 void default_bzfree ( void* opaque, void* addr )
164 if (addr != NULL) free ( addr );
167 #ifndef BZ_NO_COMPRESS
168 /*---------------------------------------------------*/
169 static
170 void prepare_new_block ( EState* s )
172 Int32 i;
173 s->nblock = 0;
174 s->numZ = 0;
175 s->state_out_pos = 0;
176 BZ_INITIALISE_CRC ( s->blockCRC );
177 for (i = 0; i < 256; i++) s->inUse[i] = False;
178 s->blockNo++;
182 /*---------------------------------------------------*/
183 static
184 void init_RL ( EState* s )
186 s->state_in_ch = 256;
187 s->state_in_len = 0;
191 static
192 Bool isempty_RL ( EState* s )
194 if (s->state_in_ch < 256 && s->state_in_len > 0)
195 return False; else
196 return True;
199 /*---------------------------------------------------*/
200 int BZ_API(BZ2_bzCompressInit)
201 ( bz_stream* strm,
202 int blockSize100k,
203 int verbosity,
204 int workFactor )
206 Int32 n;
207 EState* s;
209 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
211 if (strm == NULL ||
212 blockSize100k < 1 || blockSize100k > 9 ||
213 workFactor < 0 || workFactor > 250)
214 return BZ_PARAM_ERROR;
216 if (workFactor == 0) workFactor = 30;
217 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
218 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
220 s = BZALLOC( sizeof(EState) );
221 if (s == NULL) return BZ_MEM_ERROR;
222 s->strm = strm;
224 s->arr1 = NULL;
225 s->arr2 = NULL;
226 s->ftab = NULL;
228 n = 100000 * blockSize100k;
229 s->arr1 = BZALLOC( n * sizeof(UInt32) );
230 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
231 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
233 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
234 if (s->arr1 != NULL) BZFREE(s->arr1);
235 if (s->arr2 != NULL) BZFREE(s->arr2);
236 if (s->ftab != NULL) BZFREE(s->ftab);
237 if (s != NULL) BZFREE(s);
238 return BZ_MEM_ERROR;
241 s->blockNo = 0;
242 s->state = BZ_S_INPUT;
243 s->mode = BZ_M_RUNNING;
244 s->combinedCRC = 0;
245 s->blockSize100k = blockSize100k;
246 s->nblockMAX = 100000 * blockSize100k - 19;
247 s->verbosity = verbosity;
248 s->workFactor = workFactor;
250 s->block = (UChar*)s->arr2;
251 s->mtfv = (UInt16*)s->arr1;
252 s->zbits = NULL;
253 s->ptr = (UInt32*)s->arr1;
255 strm->state = s;
256 strm->total_in_lo32 = 0;
257 strm->total_in_hi32 = 0;
258 strm->total_out_lo32 = 0;
259 strm->total_out_hi32 = 0;
260 init_RL ( s );
261 prepare_new_block ( s );
262 return BZ_OK;
266 /*---------------------------------------------------*/
267 static
268 void add_pair_to_block ( EState* s )
270 Int32 i;
271 UChar ch = (UChar)(s->state_in_ch);
272 for (i = 0; i < s->state_in_len; i++) {
273 BZ_UPDATE_CRC( s->blockCRC, ch );
275 s->inUse[s->state_in_ch] = True;
276 switch (s->state_in_len) {
277 case 1:
278 s->block[s->nblock] = (UChar)ch; s->nblock++;
279 break;
280 case 2:
281 s->block[s->nblock] = (UChar)ch; s->nblock++;
282 s->block[s->nblock] = (UChar)ch; s->nblock++;
283 break;
284 case 3:
285 s->block[s->nblock] = (UChar)ch; s->nblock++;
286 s->block[s->nblock] = (UChar)ch; s->nblock++;
287 s->block[s->nblock] = (UChar)ch; s->nblock++;
288 break;
289 default:
290 s->inUse[s->state_in_len-4] = True;
291 s->block[s->nblock] = (UChar)ch; s->nblock++;
292 s->block[s->nblock] = (UChar)ch; s->nblock++;
293 s->block[s->nblock] = (UChar)ch; s->nblock++;
294 s->block[s->nblock] = (UChar)ch; s->nblock++;
295 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
296 s->nblock++;
297 break;
302 /*---------------------------------------------------*/
303 static
304 void flush_RL ( EState* s )
306 if (s->state_in_ch < 256) add_pair_to_block ( s );
307 init_RL ( s );
311 /*---------------------------------------------------*/
312 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
314 UInt32 zchh = (UInt32)(zchh0); \
315 /*-- fast track the common case --*/ \
316 if (zchh != zs->state_in_ch && \
317 zs->state_in_len == 1) { \
318 UChar ch = (UChar)(zs->state_in_ch); \
319 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
320 zs->inUse[zs->state_in_ch] = True; \
321 zs->block[zs->nblock] = (UChar)ch; \
322 zs->nblock++; \
323 zs->state_in_ch = zchh; \
325 else \
326 /*-- general, uncommon cases --*/ \
327 if (zchh != zs->state_in_ch || \
328 zs->state_in_len == 255) { \
329 if (zs->state_in_ch < 256) \
330 add_pair_to_block ( zs ); \
331 zs->state_in_ch = zchh; \
332 zs->state_in_len = 1; \
333 } else { \
334 zs->state_in_len++; \
339 /*---------------------------------------------------*/
340 static
341 Bool copy_input_until_stop ( EState* s )
343 Bool progress_in = False;
345 if (s->mode == BZ_M_RUNNING) {
347 /*-- fast track the common case --*/
348 while (True) {
349 /*-- block full? --*/
350 if (s->nblock >= s->nblockMAX) break;
351 /*-- no input? --*/
352 if (s->strm->avail_in == 0) break;
353 progress_in = True;
354 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
355 s->strm->next_in++;
356 s->strm->avail_in--;
357 s->strm->total_in_lo32++;
358 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
361 } else {
363 /*-- general, uncommon case --*/
364 while (True) {
365 /*-- block full? --*/
366 if (s->nblock >= s->nblockMAX) break;
367 /*-- no input? --*/
368 if (s->strm->avail_in == 0) break;
369 /*-- flush/finish end? --*/
370 if (s->avail_in_expect == 0) break;
371 progress_in = True;
372 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
373 s->strm->next_in++;
374 s->strm->avail_in--;
375 s->strm->total_in_lo32++;
376 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
377 s->avail_in_expect--;
380 return progress_in;
384 /*---------------------------------------------------*/
385 static
386 Bool copy_output_until_stop ( EState* s )
388 Bool progress_out = False;
390 while (True) {
392 /*-- no output space? --*/
393 if (s->strm->avail_out == 0) break;
395 /*-- block done? --*/
396 if (s->state_out_pos >= s->numZ) break;
398 progress_out = True;
399 *(s->strm->next_out) = s->zbits[s->state_out_pos];
400 s->state_out_pos++;
401 s->strm->avail_out--;
402 s->strm->next_out++;
403 s->strm->total_out_lo32++;
404 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
407 return progress_out;
411 /*---------------------------------------------------*/
412 static
413 Bool handle_compress ( bz_stream* strm )
415 Bool progress_in = False;
416 Bool progress_out = False;
417 EState* s = strm->state;
419 while (True) {
421 if (s->state == BZ_S_OUTPUT) {
422 progress_out |= copy_output_until_stop ( s );
423 if (s->state_out_pos < s->numZ) break;
424 if (s->mode == BZ_M_FINISHING &&
425 s->avail_in_expect == 0 &&
426 isempty_RL(s)) break;
427 prepare_new_block ( s );
428 s->state = BZ_S_INPUT;
429 if (s->mode == BZ_M_FLUSHING &&
430 s->avail_in_expect == 0 &&
431 isempty_RL(s)) break;
434 if (s->state == BZ_S_INPUT) {
435 progress_in |= copy_input_until_stop ( s );
436 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
437 flush_RL ( s );
438 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
439 s->state = BZ_S_OUTPUT;
441 else
442 if (s->nblock >= s->nblockMAX) {
443 BZ2_compressBlock ( s, False );
444 s->state = BZ_S_OUTPUT;
446 else
447 if (s->strm->avail_in == 0) {
448 break;
454 return progress_in || progress_out;
458 /*---------------------------------------------------*/
459 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
461 Bool progress;
462 EState* s;
463 if (strm == NULL) return BZ_PARAM_ERROR;
464 s = strm->state;
465 if (s == NULL) return BZ_PARAM_ERROR;
466 if (s->strm != strm) return BZ_PARAM_ERROR;
468 preswitch:
469 switch (s->mode) {
471 case BZ_M_IDLE:
472 return BZ_SEQUENCE_ERROR;
474 case BZ_M_RUNNING:
475 if (action == BZ_RUN) {
476 progress = handle_compress ( strm );
477 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
479 else
480 if (action == BZ_FLUSH) {
481 s->avail_in_expect = strm->avail_in;
482 s->mode = BZ_M_FLUSHING;
483 goto preswitch;
485 else
486 if (action == BZ_FINISH) {
487 s->avail_in_expect = strm->avail_in;
488 s->mode = BZ_M_FINISHING;
489 goto preswitch;
491 else
492 return BZ_PARAM_ERROR;
494 case BZ_M_FLUSHING:
495 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
496 if (s->avail_in_expect != s->strm->avail_in)
497 return BZ_SEQUENCE_ERROR;
498 progress = handle_compress ( strm );
499 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
500 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
501 s->mode = BZ_M_RUNNING;
502 return BZ_RUN_OK;
504 case BZ_M_FINISHING:
505 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
506 if (s->avail_in_expect != s->strm->avail_in)
507 return BZ_SEQUENCE_ERROR;
508 progress = handle_compress ( strm );
509 if (!progress) return BZ_SEQUENCE_ERROR;
510 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
511 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
512 s->mode = BZ_M_IDLE;
513 return BZ_STREAM_END;
515 return BZ_OK; /*--not reached--*/
519 /*---------------------------------------------------*/
520 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
522 EState* s;
523 if (strm == NULL) return BZ_PARAM_ERROR;
524 s = strm->state;
525 if (s == NULL) return BZ_PARAM_ERROR;
526 if (s->strm != strm) return BZ_PARAM_ERROR;
528 if (s->arr1 != NULL) BZFREE(s->arr1);
529 if (s->arr2 != NULL) BZFREE(s->arr2);
530 if (s->ftab != NULL) BZFREE(s->ftab);
531 BZFREE(strm->state);
533 strm->state = NULL;
535 return BZ_OK;
537 #endif /* BZ_NO_COMPRESS */
539 /*---------------------------------------------------*/
540 /*--- Decompression stuff ---*/
541 /*---------------------------------------------------*/
543 /*---------------------------------------------------*/
544 int BZ_API(BZ2_bzDecompressInit)
545 ( bz_stream* strm,
546 int verbosity,
547 int small )
549 DState* s;
551 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
553 if (strm == NULL) return BZ_PARAM_ERROR;
554 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
555 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
557 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
558 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
560 s = BZALLOC( sizeof(DState) );
561 if (s == NULL) return BZ_MEM_ERROR;
562 s->strm = strm;
563 strm->state = s;
564 s->state = BZ_X_MAGIC_1;
565 s->bsLive = 0;
566 s->bsBuff = 0;
567 s->calculatedCombinedCRC = 0;
568 strm->total_in_lo32 = 0;
569 strm->total_in_hi32 = 0;
570 strm->total_out_lo32 = 0;
571 strm->total_out_hi32 = 0;
572 s->smallDecompress = (Bool)small;
573 s->ll4 = NULL;
574 s->ll16 = NULL;
575 s->tt = NULL;
576 s->currBlockNo = 0;
577 s->verbosity = verbosity;
579 return BZ_OK;
583 /*---------------------------------------------------*/
584 static
585 void unRLE_obuf_to_output_FAST ( DState* s )
587 UChar k1;
589 if (s->blockRandomised) {
591 while (True) {
592 /* try to finish existing run */
593 while (True) {
594 if (s->strm->avail_out == 0) return;
595 if (s->state_out_len == 0) break;
596 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
597 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
598 s->state_out_len--;
599 s->strm->next_out++;
600 s->strm->avail_out--;
601 s->strm->total_out_lo32++;
602 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
605 /* can a new run be started? */
606 if (s->nblock_used == s->save_nblock+1) return;
609 s->state_out_len = 1;
610 s->state_out_ch = s->k0;
611 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
612 k1 ^= BZ_RAND_MASK; s->nblock_used++;
613 if (s->nblock_used == s->save_nblock+1) continue;
614 if (k1 != s->k0) { s->k0 = k1; continue; };
616 s->state_out_len = 2;
617 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
618 k1 ^= BZ_RAND_MASK; s->nblock_used++;
619 if (s->nblock_used == s->save_nblock+1) continue;
620 if (k1 != s->k0) { s->k0 = k1; continue; };
622 s->state_out_len = 3;
623 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
624 k1 ^= BZ_RAND_MASK; s->nblock_used++;
625 if (s->nblock_used == s->save_nblock+1) continue;
626 if (k1 != s->k0) { s->k0 = k1; continue; };
628 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
629 k1 ^= BZ_RAND_MASK; s->nblock_used++;
630 s->state_out_len = ((Int32)k1) + 4;
631 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
632 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
635 } else {
637 /* restore */
638 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
639 UChar c_state_out_ch = s->state_out_ch;
640 Int32 c_state_out_len = s->state_out_len;
641 Int32 c_nblock_used = s->nblock_used;
642 Int32 c_k0 = s->k0;
643 UInt32* c_tt = s->tt;
644 UInt32 c_tPos = s->tPos;
645 char* cs_next_out = s->strm->next_out;
646 unsigned int cs_avail_out = s->strm->avail_out;
647 /* end restore */
649 UInt32 avail_out_INIT = cs_avail_out;
650 Int32 s_save_nblockPP = s->save_nblock+1;
651 unsigned int total_out_lo32_old;
653 while (True) {
655 /* try to finish existing run */
656 if (c_state_out_len > 0) {
657 while (True) {
658 if (cs_avail_out == 0) goto return_notr;
659 if (c_state_out_len == 1) break;
660 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
661 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
662 c_state_out_len--;
663 cs_next_out++;
664 cs_avail_out--;
666 s_state_out_len_eq_one:
668 if (cs_avail_out == 0) {
669 c_state_out_len = 1; goto return_notr;
671 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
672 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
673 cs_next_out++;
674 cs_avail_out--;
677 /* can a new run be started? */
678 if (c_nblock_used == s_save_nblockPP) {
679 c_state_out_len = 0; goto return_notr;
681 c_state_out_ch = c_k0;
682 BZ_GET_FAST_C(k1); c_nblock_used++;
683 if (k1 != c_k0) {
684 c_k0 = k1; goto s_state_out_len_eq_one;
686 if (c_nblock_used == s_save_nblockPP)
687 goto s_state_out_len_eq_one;
689 c_state_out_len = 2;
690 BZ_GET_FAST_C(k1); c_nblock_used++;
691 if (c_nblock_used == s_save_nblockPP) continue;
692 if (k1 != c_k0) { c_k0 = k1; continue; };
694 c_state_out_len = 3;
695 BZ_GET_FAST_C(k1); c_nblock_used++;
696 if (c_nblock_used == s_save_nblockPP) continue;
697 if (k1 != c_k0) { c_k0 = k1; continue; };
699 BZ_GET_FAST_C(k1); c_nblock_used++;
700 c_state_out_len = ((Int32)k1) + 4;
701 BZ_GET_FAST_C(c_k0); c_nblock_used++;
704 return_notr:
705 total_out_lo32_old = s->strm->total_out_lo32;
706 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
707 if (s->strm->total_out_lo32 < total_out_lo32_old)
708 s->strm->total_out_hi32++;
710 /* save */
711 s->calculatedBlockCRC = c_calculatedBlockCRC;
712 s->state_out_ch = c_state_out_ch;
713 s->state_out_len = c_state_out_len;
714 s->nblock_used = c_nblock_used;
715 s->k0 = c_k0;
716 s->tt = c_tt;
717 s->tPos = c_tPos;
718 s->strm->next_out = cs_next_out;
719 s->strm->avail_out = cs_avail_out;
720 /* end save */
725 /*---------------------------------------------------*/
726 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
728 Int32 nb, na, mid;
729 nb = 0;
730 na = 256;
731 do {
732 mid = (nb + na) >> 1;
733 if (indx >= cftab[mid]) nb = mid; else na = mid;
735 while (na - nb != 1);
736 return nb;
740 /*---------------------------------------------------*/
741 static
742 void unRLE_obuf_to_output_SMALL ( DState* s )
744 UChar k1;
746 if (s->blockRandomised) {
748 while (True) {
749 /* try to finish existing run */
750 while (True) {
751 if (s->strm->avail_out == 0) return;
752 if (s->state_out_len == 0) break;
753 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
754 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
755 s->state_out_len--;
756 s->strm->next_out++;
757 s->strm->avail_out--;
758 s->strm->total_out_lo32++;
759 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
762 /* can a new run be started? */
763 if (s->nblock_used == s->save_nblock+1) return;
766 s->state_out_len = 1;
767 s->state_out_ch = s->k0;
768 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
769 k1 ^= BZ_RAND_MASK; s->nblock_used++;
770 if (s->nblock_used == s->save_nblock+1) continue;
771 if (k1 != s->k0) { s->k0 = k1; continue; };
773 s->state_out_len = 2;
774 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
775 k1 ^= BZ_RAND_MASK; s->nblock_used++;
776 if (s->nblock_used == s->save_nblock+1) continue;
777 if (k1 != s->k0) { s->k0 = k1; continue; };
779 s->state_out_len = 3;
780 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
781 k1 ^= BZ_RAND_MASK; s->nblock_used++;
782 if (s->nblock_used == s->save_nblock+1) continue;
783 if (k1 != s->k0) { s->k0 = k1; continue; };
785 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
786 k1 ^= BZ_RAND_MASK; s->nblock_used++;
787 s->state_out_len = ((Int32)k1) + 4;
788 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
789 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
792 } else {
794 while (True) {
795 /* try to finish existing run */
796 while (True) {
797 if (s->strm->avail_out == 0) return;
798 if (s->state_out_len == 0) break;
799 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
800 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
801 s->state_out_len--;
802 s->strm->next_out++;
803 s->strm->avail_out--;
804 s->strm->total_out_lo32++;
805 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
808 /* can a new run be started? */
809 if (s->nblock_used == s->save_nblock+1) return;
811 s->state_out_len = 1;
812 s->state_out_ch = s->k0;
813 BZ_GET_SMALL(k1); s->nblock_used++;
814 if (s->nblock_used == s->save_nblock+1) continue;
815 if (k1 != s->k0) { s->k0 = k1; continue; };
817 s->state_out_len = 2;
818 BZ_GET_SMALL(k1); s->nblock_used++;
819 if (s->nblock_used == s->save_nblock+1) continue;
820 if (k1 != s->k0) { s->k0 = k1; continue; };
822 s->state_out_len = 3;
823 BZ_GET_SMALL(k1); s->nblock_used++;
824 if (s->nblock_used == s->save_nblock+1) continue;
825 if (k1 != s->k0) { s->k0 = k1; continue; };
827 BZ_GET_SMALL(k1); s->nblock_used++;
828 s->state_out_len = ((Int32)k1) + 4;
829 BZ_GET_SMALL(s->k0); s->nblock_used++;
836 /*---------------------------------------------------*/
837 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
839 DState* s;
840 if (strm == NULL) return BZ_PARAM_ERROR;
841 s = strm->state;
842 if (s == NULL) return BZ_PARAM_ERROR;
843 if (s->strm != strm) return BZ_PARAM_ERROR;
845 while (True) {
846 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
847 WATCHDOG_RESET();
848 #endif
849 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
850 if (s->state == BZ_X_OUTPUT) {
851 if (s->smallDecompress)
852 unRLE_obuf_to_output_SMALL ( s ); else
853 unRLE_obuf_to_output_FAST ( s );
854 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
855 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
856 if (s->verbosity >= 3)
857 VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC,
858 s->calculatedBlockCRC );
859 if (s->verbosity >= 2) VPrintf0 ( "]" );
860 if (s->calculatedBlockCRC != s->storedBlockCRC)
861 return BZ_DATA_ERROR;
862 s->calculatedCombinedCRC
863 = (s->calculatedCombinedCRC << 1) |
864 (s->calculatedCombinedCRC >> 31);
865 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
866 s->state = BZ_X_BLKHDR_1;
867 } else {
868 return BZ_OK;
871 if (s->state >= BZ_X_MAGIC_1) {
872 Int32 r = BZ2_decompress ( s );
873 if (r == BZ_STREAM_END) {
874 if (s->verbosity >= 3)
875 VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x",
876 s->storedCombinedCRC, s->calculatedCombinedCRC );
877 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
878 return BZ_DATA_ERROR;
879 return r;
881 if (s->state != BZ_X_OUTPUT) return r;
885 AssertH ( 0, 6001 );
887 return 0; /*NOTREACHED*/
891 /*---------------------------------------------------*/
892 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
894 DState* s;
895 if (strm == NULL) return BZ_PARAM_ERROR;
896 s = strm->state;
897 if (s == NULL) return BZ_PARAM_ERROR;
898 if (s->strm != strm) return BZ_PARAM_ERROR;
900 if (s->tt != NULL) BZFREE(s->tt);
901 if (s->ll16 != NULL) BZFREE(s->ll16);
902 if (s->ll4 != NULL) BZFREE(s->ll4);
904 BZFREE(strm->state);
905 strm->state = NULL;
907 return BZ_OK;
911 #ifndef BZ_NO_STDIO
912 /*---------------------------------------------------*/
913 /*--- File I/O stuff ---*/
914 /*---------------------------------------------------*/
916 #define BZ_SETERR(eee) \
918 if (bzerror != NULL) *bzerror = eee; \
919 if (bzf != NULL) bzf->lastErr = eee; \
922 typedef
923 struct {
924 FILE* handle;
925 Char buf[BZ_MAX_UNUSED];
926 Int32 bufN;
927 Bool writing;
928 bz_stream strm;
929 Int32 lastErr;
930 Bool initialisedOk;
932 bzFile;
935 /*---------------------------------------------*/
936 static Bool myfeof ( FILE* f )
938 Int32 c = fgetc ( f );
939 if (c == EOF) return True;
940 ungetc ( c, f );
941 return False;
945 /*---------------------------------------------------*/
946 BZFILE* BZ_API(BZ2_bzWriteOpen)
947 ( int* bzerror,
948 FILE* f,
949 int blockSize100k,
950 int verbosity,
951 int workFactor )
953 Int32 ret;
954 bzFile* bzf = NULL;
956 BZ_SETERR(BZ_OK);
958 if (f == NULL ||
959 (blockSize100k < 1 || blockSize100k > 9) ||
960 (workFactor < 0 || workFactor > 250) ||
961 (verbosity < 0 || verbosity > 4))
962 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
964 if (ferror(f))
965 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
967 bzf = malloc ( sizeof(bzFile) );
968 if (bzf == NULL)
969 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
971 BZ_SETERR(BZ_OK);
972 bzf->initialisedOk = False;
973 bzf->bufN = 0;
974 bzf->handle = f;
975 bzf->writing = True;
976 bzf->strm.bzalloc = NULL;
977 bzf->strm.bzfree = NULL;
978 bzf->strm.opaque = NULL;
980 if (workFactor == 0) workFactor = 30;
981 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
982 verbosity, workFactor );
983 if (ret != BZ_OK)
984 { BZ_SETERR(ret); free(bzf); return NULL; };
986 bzf->strm.avail_in = 0;
987 bzf->initialisedOk = True;
988 return bzf;
992 /*---------------------------------------------------*/
993 void BZ_API(BZ2_bzWrite)
994 ( int* bzerror,
995 BZFILE* b,
996 void* buf,
997 int len )
999 Int32 n, n2, ret;
1000 bzFile* bzf = (bzFile*)b;
1002 BZ_SETERR(BZ_OK);
1003 if (bzf == NULL || buf == NULL || len < 0)
1004 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1005 if (!(bzf->writing))
1006 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1007 if (ferror(bzf->handle))
1008 { BZ_SETERR(BZ_IO_ERROR); return; };
1010 if (len == 0)
1011 { BZ_SETERR(BZ_OK); return; };
1013 bzf->strm.avail_in = len;
1014 bzf->strm.next_in = buf;
1016 while (True) {
1017 bzf->strm.avail_out = BZ_MAX_UNUSED;
1018 bzf->strm.next_out = bzf->buf;
1019 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
1020 if (ret != BZ_RUN_OK)
1021 { BZ_SETERR(ret); return; };
1023 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1024 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1025 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1026 n, bzf->handle );
1027 if (n != n2 || ferror(bzf->handle))
1028 { BZ_SETERR(BZ_IO_ERROR); return; };
1031 if (bzf->strm.avail_in == 0)
1032 { BZ_SETERR(BZ_OK); return; };
1037 /*---------------------------------------------------*/
1038 void BZ_API(BZ2_bzWriteClose)
1039 ( int* bzerror,
1040 BZFILE* b,
1041 int abandon,
1042 unsigned int* nbytes_in,
1043 unsigned int* nbytes_out )
1045 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1046 nbytes_in, NULL, nbytes_out, NULL );
1050 void BZ_API(BZ2_bzWriteClose64)
1051 ( int* bzerror,
1052 BZFILE* b,
1053 int abandon,
1054 unsigned int* nbytes_in_lo32,
1055 unsigned int* nbytes_in_hi32,
1056 unsigned int* nbytes_out_lo32,
1057 unsigned int* nbytes_out_hi32 )
1059 Int32 n, n2, ret;
1060 bzFile* bzf = (bzFile*)b;
1062 if (bzf == NULL)
1063 { BZ_SETERR(BZ_OK); return; };
1064 if (!(bzf->writing))
1065 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1066 if (ferror(bzf->handle))
1067 { BZ_SETERR(BZ_IO_ERROR); return; };
1069 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1070 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1071 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1072 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1074 if ((!abandon) && bzf->lastErr == BZ_OK) {
1075 while (True) {
1076 bzf->strm.avail_out = BZ_MAX_UNUSED;
1077 bzf->strm.next_out = bzf->buf;
1078 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1079 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1080 { BZ_SETERR(ret); return; };
1082 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1083 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1084 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1085 n, bzf->handle );
1086 if (n != n2 || ferror(bzf->handle))
1087 { BZ_SETERR(BZ_IO_ERROR); return; };
1090 if (ret == BZ_STREAM_END) break;
1094 if ( !abandon && !ferror ( bzf->handle ) ) {
1095 fflush ( bzf->handle );
1096 if (ferror(bzf->handle))
1097 { BZ_SETERR(BZ_IO_ERROR); return; };
1100 if (nbytes_in_lo32 != NULL)
1101 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1102 if (nbytes_in_hi32 != NULL)
1103 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1104 if (nbytes_out_lo32 != NULL)
1105 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1106 if (nbytes_out_hi32 != NULL)
1107 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1109 BZ_SETERR(BZ_OK);
1110 BZ2_bzCompressEnd ( &(bzf->strm) );
1111 free ( bzf );
1115 /*---------------------------------------------------*/
1116 BZFILE* BZ_API(BZ2_bzReadOpen)
1117 ( int* bzerror,
1118 FILE* f,
1119 int verbosity,
1120 int small,
1121 void* unused,
1122 int nUnused )
1124 bzFile* bzf = NULL;
1125 int ret;
1127 BZ_SETERR(BZ_OK);
1129 if (f == NULL ||
1130 (small != 0 && small != 1) ||
1131 (verbosity < 0 || verbosity > 4) ||
1132 (unused == NULL && nUnused != 0) ||
1133 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1134 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1136 if (ferror(f))
1137 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1139 bzf = malloc ( sizeof(bzFile) );
1140 if (bzf == NULL)
1141 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1143 BZ_SETERR(BZ_OK);
1145 bzf->initialisedOk = False;
1146 bzf->handle = f;
1147 bzf->bufN = 0;
1148 bzf->writing = False;
1149 bzf->strm.bzalloc = NULL;
1150 bzf->strm.bzfree = NULL;
1151 bzf->strm.opaque = NULL;
1153 while (nUnused > 0) {
1154 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1155 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1156 nUnused--;
1159 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1160 if (ret != BZ_OK)
1161 { BZ_SETERR(ret); free(bzf); return NULL; };
1163 bzf->strm.avail_in = bzf->bufN;
1164 bzf->strm.next_in = bzf->buf;
1166 bzf->initialisedOk = True;
1167 return bzf;
1171 /*---------------------------------------------------*/
1172 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1174 bzFile* bzf = (bzFile*)b;
1176 BZ_SETERR(BZ_OK);
1177 if (bzf == NULL)
1178 { BZ_SETERR(BZ_OK); return; };
1180 if (bzf->writing)
1181 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1183 if (bzf->initialisedOk)
1184 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1185 free ( bzf );
1189 /*---------------------------------------------------*/
1190 int BZ_API(BZ2_bzRead)
1191 ( int* bzerror,
1192 BZFILE* b,
1193 void* buf,
1194 int len )
1196 Int32 n, ret;
1197 bzFile* bzf = (bzFile*)b;
1199 BZ_SETERR(BZ_OK);
1201 if (bzf == NULL || buf == NULL || len < 0)
1202 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1204 if (bzf->writing)
1205 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1207 if (len == 0)
1208 { BZ_SETERR(BZ_OK); return 0; };
1210 bzf->strm.avail_out = len;
1211 bzf->strm.next_out = buf;
1213 while (True) {
1215 if (ferror(bzf->handle))
1216 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1218 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1219 n = fread ( bzf->buf, sizeof(UChar),
1220 BZ_MAX_UNUSED, bzf->handle );
1221 if (ferror(bzf->handle))
1222 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1223 bzf->bufN = n;
1224 bzf->strm.avail_in = bzf->bufN;
1225 bzf->strm.next_in = bzf->buf;
1228 ret = BZ2_bzDecompress ( &(bzf->strm) );
1230 if (ret != BZ_OK && ret != BZ_STREAM_END)
1231 { BZ_SETERR(ret); return 0; };
1233 if (ret == BZ_OK && myfeof(bzf->handle) &&
1234 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1235 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1237 if (ret == BZ_STREAM_END)
1238 { BZ_SETERR(BZ_STREAM_END);
1239 return len - bzf->strm.avail_out; };
1240 if (bzf->strm.avail_out == 0)
1241 { BZ_SETERR(BZ_OK); return len; };
1245 return 0; /*not reached*/
1249 /*---------------------------------------------------*/
1250 void BZ_API(BZ2_bzReadGetUnused)
1251 ( int* bzerror,
1252 BZFILE* b,
1253 void** unused,
1254 int* nUnused )
1256 bzFile* bzf = (bzFile*)b;
1257 if (bzf == NULL)
1258 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1259 if (bzf->lastErr != BZ_STREAM_END)
1260 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1261 if (unused == NULL || nUnused == NULL)
1262 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1264 BZ_SETERR(BZ_OK);
1265 *nUnused = bzf->strm.avail_in;
1266 *unused = bzf->strm.next_in;
1268 #endif
1271 /*---------------------------------------------------*/
1272 /*--- Misc convenience stuff ---*/
1273 /*---------------------------------------------------*/
1274 #ifndef BZ_NO_COMPRESS
1275 /*---------------------------------------------------*/
1276 int BZ_API(BZ2_bzBuffToBuffCompress)
1277 ( char* dest,
1278 unsigned int* destLen,
1279 char* source,
1280 unsigned int sourceLen,
1281 int blockSize100k,
1282 int verbosity,
1283 int workFactor )
1285 bz_stream strm;
1286 int ret;
1288 if (dest == NULL || destLen == NULL ||
1289 source == NULL ||
1290 blockSize100k < 1 || blockSize100k > 9 ||
1291 verbosity < 0 || verbosity > 4 ||
1292 workFactor < 0 || workFactor > 250)
1293 return BZ_PARAM_ERROR;
1295 if (workFactor == 0) workFactor = 30;
1296 strm.bzalloc = NULL;
1297 strm.bzfree = NULL;
1298 strm.opaque = NULL;
1299 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1300 verbosity, workFactor );
1301 if (ret != BZ_OK) return ret;
1303 strm.next_in = source;
1304 strm.next_out = dest;
1305 strm.avail_in = sourceLen;
1306 strm.avail_out = *destLen;
1308 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1309 if (ret == BZ_FINISH_OK) goto output_overflow;
1310 if (ret != BZ_STREAM_END) goto errhandler;
1312 /* normal termination */
1313 *destLen -= strm.avail_out;
1314 BZ2_bzCompressEnd ( &strm );
1315 return BZ_OK;
1317 output_overflow:
1318 BZ2_bzCompressEnd ( &strm );
1319 return BZ_OUTBUFF_FULL;
1321 errhandler:
1322 BZ2_bzCompressEnd ( &strm );
1323 return ret;
1325 #endif /* BZ_NO_COMPRESS */
1327 /*---------------------------------------------------*/
1328 int BZ_API(BZ2_bzBuffToBuffDecompress)
1329 ( char* dest,
1330 unsigned int* destLen,
1331 char* source,
1332 unsigned int sourceLen,
1333 int small,
1334 int verbosity )
1336 bz_stream strm;
1337 int ret;
1339 if (destLen == NULL || source == NULL)
1340 return BZ_PARAM_ERROR;
1342 strm.bzalloc = NULL;
1343 strm.bzfree = NULL;
1344 strm.opaque = NULL;
1345 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1346 if (ret != BZ_OK) return ret;
1348 strm.next_in = source;
1349 strm.next_out = dest;
1350 strm.avail_in = sourceLen;
1351 strm.avail_out = *destLen;
1353 ret = BZ2_bzDecompress ( &strm );
1354 if (ret == BZ_OK) goto output_overflow_or_eof;
1355 if (ret != BZ_STREAM_END) goto errhandler;
1357 /* normal termination */
1358 *destLen -= strm.avail_out;
1359 BZ2_bzDecompressEnd ( &strm );
1360 return BZ_OK;
1362 output_overflow_or_eof:
1363 if (strm.avail_out > 0) {
1364 BZ2_bzDecompressEnd ( &strm );
1365 return BZ_UNEXPECTED_EOF;
1366 } else {
1367 BZ2_bzDecompressEnd ( &strm );
1368 return BZ_OUTBUFF_FULL;
1371 errhandler:
1372 BZ2_bzDecompressEnd ( &strm );
1373 return ret;
1377 /*---------------------------------------------------*/
1378 /*--
1379 Code contributed by Yoshioka Tsuneo
1380 (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
1381 to support better zlib compatibility.
1382 This code is not _officially_ part of libbzip2 (yet);
1383 I haven't tested it, documented it, or considered the
1384 threading-safeness of it.
1385 If this code breaks, please contact both Yoshioka and me.
1386 --*/
1387 /*---------------------------------------------------*/
1389 /*---------------------------------------------------*/
1390 /*--
1391 return version like "0.9.0c".
1392 --*/
1393 const char * BZ_API(BZ2_bzlibVersion)(void)
1395 return BZ_VERSION;
1399 #ifndef BZ_NO_STDIO
1400 /*---------------------------------------------------*/
1402 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1403 # include <fcntl.h>
1404 # include <io.h>
1405 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1406 #else
1407 # define SET_BINARY_MODE(file)
1408 #endif
1409 static
1410 BZFILE * bzopen_or_bzdopen
1411 ( const char *path, /* no use when bzdopen */
1412 int fd, /* no use when bzdopen */
1413 const char *mode,
1414 int open_mode) /* bzopen: 0, bzdopen:1 */
1416 int bzerr;
1417 char unused[BZ_MAX_UNUSED];
1418 int blockSize100k = 9;
1419 int writing = 0;
1420 char mode2[10] = "";
1421 FILE *fp = NULL;
1422 BZFILE *bzfp = NULL;
1423 int verbosity = 0;
1424 int workFactor = 30;
1425 int smallMode = 0;
1426 int nUnused = 0;
1428 if (mode == NULL) return NULL;
1429 while (*mode) {
1430 switch (*mode) {
1431 case 'r':
1432 writing = 0; break;
1433 case 'w':
1434 writing = 1; break;
1435 case 's':
1436 smallMode = 1; break;
1437 default:
1438 if (isdigit((int)(*mode))) {
1439 blockSize100k = *mode-BZ_HDR_0;
1442 mode++;
1444 strcat(mode2, writing ? "w" : "r" );
1445 strcat(mode2,"b"); /* binary mode */
1447 if (open_mode==0) {
1448 if (path==NULL || strcmp(path,"")==0) {
1449 fp = (writing ? stdout : stdin);
1450 SET_BINARY_MODE(fp);
1451 } else {
1452 fp = fopen(path,mode2);
1454 } else {
1455 #ifdef BZ_STRICT_ANSI
1456 fp = NULL;
1457 #else
1458 fp = fdopen(fd,mode2);
1459 #endif
1461 if (fp == NULL) return NULL;
1463 if (writing) {
1464 /* Guard against total chaos and anarchy -- JRS */
1465 if (blockSize100k < 1) blockSize100k = 1;
1466 if (blockSize100k > 9) blockSize100k = 9;
1467 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1468 verbosity,workFactor);
1469 } else {
1470 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1471 unused,nUnused);
1473 if (bzfp == NULL) {
1474 if (fp != stdin && fp != stdout) fclose(fp);
1475 return NULL;
1477 return bzfp;
1481 /*---------------------------------------------------*/
1482 /*--
1483 open file for read or write.
1484 ex) bzopen("file","w9")
1485 case path="" or NULL => use stdin or stdout.
1486 --*/
1487 BZFILE * BZ_API(BZ2_bzopen)
1488 ( const char *path,
1489 const char *mode )
1491 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1495 /*---------------------------------------------------*/
1496 BZFILE * BZ_API(BZ2_bzdopen)
1497 ( int fd,
1498 const char *mode )
1500 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1504 /*---------------------------------------------------*/
1505 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1507 int bzerr, nread;
1508 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1509 nread = BZ2_bzRead(&bzerr,b,buf,len);
1510 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1511 return nread;
1512 } else {
1513 return -1;
1518 /*---------------------------------------------------*/
1519 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1521 int bzerr;
1523 BZ2_bzWrite(&bzerr,b,buf,len);
1524 if(bzerr == BZ_OK){
1525 return len;
1526 }else{
1527 return -1;
1532 /*---------------------------------------------------*/
1533 int BZ_API(BZ2_bzflush) (BZFILE *b)
1535 /* do nothing now... */
1536 return 0;
1540 /*---------------------------------------------------*/
1541 void BZ_API(BZ2_bzclose) (BZFILE* b)
1543 int bzerr;
1544 FILE *fp = ((bzFile *)b)->handle;
1546 if (b==NULL) {return;}
1547 if(((bzFile*)b)->writing){
1548 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1549 if(bzerr != BZ_OK){
1550 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1552 }else{
1553 BZ2_bzReadClose(&bzerr,b);
1555 if(fp!=stdin && fp!=stdout){
1556 fclose(fp);
1561 /*---------------------------------------------------*/
1562 /*--
1563 return last error code
1564 --*/
1565 static char *bzerrorstrings[] = {
1566 "OK"
1567 ,"SEQUENCE_ERROR"
1568 ,"PARAM_ERROR"
1569 ,"MEM_ERROR"
1570 ,"DATA_ERROR"
1571 ,"DATA_ERROR_MAGIC"
1572 ,"IO_ERROR"
1573 ,"UNEXPECTED_EOF"
1574 ,"OUTBUFF_FULL"
1575 ,"CONFIG_ERROR"
1576 ,"???" /* for future */
1577 ,"???" /* for future */
1578 ,"???" /* for future */
1579 ,"???" /* for future */
1580 ,"???" /* for future */
1581 ,"???" /* for future */
1585 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1587 int err = ((bzFile *)b)->lastErr;
1589 if(err>0) err = 0;
1590 *errnum = err;
1591 return bzerrorstrings[err*-1];
1593 #endif
1595 void bz_internal_error(int errcode)
1597 printf ("BZIP2 internal error %d\n", errcode);
1600 /*-------------------------------------------------------------*/
1601 /*--- end bzlib.c ---*/
1602 /*-------------------------------------------------------------*/
1604 #endif /* CONFIG_BZIP2 */