3e5c8d0d40afc180463f71e93a65248bf5dcab19
[reactos.git] / reactos / drivers / lib / bzip2 / bzlib.c
1
2 /*-------------------------------------------------------------*/
3 /*--- Library top-level functions. ---*/
4 /*--- bzlib.c ---*/
5 /*-------------------------------------------------------------*/
6
7 /*--
8 This file is a part of bzip2 and/or libbzip2, a program and
9 library for lossless, block-sorting data compression.
10
11 Copyright (C) 1996-2000 Julian R Seward. All rights reserved.
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
15 are met:
16
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
19
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.
24
25 3. Altered source versions must be plainly marked as such, and must
26 not be misrepresented as being the original software.
27
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
30 permission.
31
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.
43
44 Julian Seward, Cambridge, UK.
45 jseward@acm.org
46 bzip2/libbzip2 version 1.0 of 21 March 2000
47
48 This program is based on (at least) the work of:
49 Mike Burrows
50 David Wheeler
51 Peter Fenwick
52 Alistair Moffat
53 Radford Neal
54 Ian H. Witten
55 Robert Sedgewick
56 Jon L. Bentley
57
58 For more information on these sources, see the manual.
59 --*/
60
61 /*--
62 CHANGES
63 ~~~~~~~
64 0.9.0 -- original version.
65
66 0.9.0a/b -- no changes in this file.
67
68 0.9.0c
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.
74 --*/
75
76 #include "bzlib_private.h"
77
78
79 /*---------------------------------------------------*/
80 /*--- Compression stuff ---*/
81 /*---------------------------------------------------*/
82
83
84 /*---------------------------------------------------*/
85 #ifndef BZ_NO_STDIO
86 void BZ2_bz__AssertH__fail ( int errcode )
87 {
88 fprintf(stderr,
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",
97 errcode,
98 BZ2_bzlibVersion()
99 );
100 exit(3);
101 }
102 #endif
103
104
105 /*---------------------------------------------------*/
106 static
107 int bz_config_ok ( void )
108 {
109 if (sizeof(int) != 4) return 0;
110 if (sizeof(short) != 2) return 0;
111 if (sizeof(char) != 1) return 0;
112 return 1;
113 }
114
115
116 _stdcall void *(*BZ2_malloc)( unsigned long size );
117 _stdcall void (*BZ2_free)( void *ptr );
118
119
120 /*---------------------------------------------------*/
121 static
122 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
123 {
124 void* v = BZ2_malloc ( items * size );
125 return v;
126 }
127
128 static
129 void default_bzfree ( void* opaque, void* addr )
130 {
131 if (addr != NULL) BZ2_free ( addr );
132 }
133
134
135 #ifndef BZ_DECOMPRESS_ONLY
136
137 /*---------------------------------------------------*/
138 static
139 void prepare_new_block ( EState* s )
140 {
141 Int32 i;
142 s->nblock = 0;
143 s->numZ = 0;
144 s->state_out_pos = 0;
145 BZ_INITIALISE_CRC ( s->blockCRC );
146 for (i = 0; i < 256; i++) s->inUse[i] = False;
147 s->blockNo++;
148 }
149
150
151 /*---------------------------------------------------*/
152 static
153 void init_RL ( EState* s )
154 {
155 s->state_in_ch = 256;
156 s->state_in_len = 0;
157 }
158
159
160 static
161 Bool isempty_RL ( EState* s )
162 {
163 if (s->state_in_ch < 256 && s->state_in_len > 0)
164 return False; else
165 return True;
166 }
167
168
169 /*---------------------------------------------------*/
170 int BZ_API(BZ2_bzCompressInit)
171 ( bz_stream* strm,
172 int blockSize100k,
173 int verbosity,
174 int workFactor )
175 {
176 Int32 n;
177 EState* s;
178
179 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
180
181 if (strm == NULL ||
182 blockSize100k < 1 || blockSize100k > 9 ||
183 workFactor < 0 || workFactor > 250)
184 return BZ_PARAM_ERROR;
185
186 if (workFactor == 0) workFactor = 30;
187 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
188 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
189
190 s = BZALLOC( sizeof(EState) );
191 if (s == NULL) return BZ_MEM_ERROR;
192 s->strm = strm;
193
194 s->arr1 = NULL;
195 s->arr2 = NULL;
196 s->ftab = NULL;
197
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) );
202
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);
208 return BZ_MEM_ERROR;
209 }
210
211 s->blockNo = 0;
212 s->state = BZ_S_INPUT;
213 s->mode = BZ_M_RUNNING;
214 s->combinedCRC = 0;
215 s->blockSize100k = blockSize100k;
216 s->nblockMAX = 100000 * blockSize100k - 19;
217 s->verbosity = verbosity;
218 s->workFactor = workFactor;
219
220 s->block = (UChar*)s->arr2;
221 s->mtfv = (UInt16*)s->arr1;
222 s->zbits = NULL;
223 s->ptr = (UInt32*)s->arr1;
224
225 strm->state = s;
226 strm->total_in_lo32 = 0;
227 strm->total_in_hi32 = 0;
228 strm->total_out_lo32 = 0;
229 strm->total_out_hi32 = 0;
230 init_RL ( s );
231 prepare_new_block ( s );
232 return BZ_OK;
233 }
234
235
236 /*---------------------------------------------------*/
237 static
238 void add_pair_to_block ( EState* s )
239 {
240 Int32 i;
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 );
244 }
245 s->inUse[s->state_in_ch] = True;
246 switch (s->state_in_len) {
247 case 1:
248 s->block[s->nblock] = (UChar)ch; s->nblock++;
249 break;
250 case 2:
251 s->block[s->nblock] = (UChar)ch; s->nblock++;
252 s->block[s->nblock] = (UChar)ch; s->nblock++;
253 break;
254 case 3:
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++;
258 break;
259 default:
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));
266 s->nblock++;
267 break;
268 }
269 }
270
271
272 /*---------------------------------------------------*/
273 static
274 void flush_RL ( EState* s )
275 {
276 if (s->state_in_ch < 256) add_pair_to_block ( s );
277 init_RL ( s );
278 }
279
280
281 /*---------------------------------------------------*/
282 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
283 { \
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; \
292 zs->nblock++; \
293 zs->state_in_ch = zchh; \
294 } \
295 else \
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; \
303 } else { \
304 zs->state_in_len++; \
305 } \
306 }
307
308
309 /*---------------------------------------------------*/
310 static
311 Bool copy_input_until_stop ( EState* s )
312 {
313 Bool progress_in = False;
314
315 if (s->mode == BZ_M_RUNNING) {
316
317 /*-- fast track the common case --*/
318 while (True) {
319 /*-- block full? --*/
320 if (s->nblock >= s->nblockMAX) break;
321 /*-- no input? --*/
322 if (s->strm->avail_in == 0) break;
323 progress_in = True;
324 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
325 s->strm->next_in++;
326 s->strm->avail_in--;
327 s->strm->total_in_lo32++;
328 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
329 }
330
331 } else {
332
333 /*-- general, uncommon case --*/
334 while (True) {
335 /*-- block full? --*/
336 if (s->nblock >= s->nblockMAX) break;
337 /*-- no input? --*/
338 if (s->strm->avail_in == 0) break;
339 /*-- flush/finish end? --*/
340 if (s->avail_in_expect == 0) break;
341 progress_in = True;
342 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
343 s->strm->next_in++;
344 s->strm->avail_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--;
348 }
349 }
350 return progress_in;
351 }
352
353
354 /*---------------------------------------------------*/
355 static
356 Bool copy_output_until_stop ( EState* s )
357 {
358 Bool progress_out = False;
359
360 while (True) {
361
362 /*-- no output space? --*/
363 if (s->strm->avail_out == 0) break;
364
365 /*-- block done? --*/
366 if (s->state_out_pos >= s->numZ) break;
367
368 progress_out = True;
369 *(s->strm->next_out) = s->zbits[s->state_out_pos];
370 s->state_out_pos++;
371 s->strm->avail_out--;
372 s->strm->next_out++;
373 s->strm->total_out_lo32++;
374 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
375 }
376
377 return progress_out;
378 }
379
380
381 /*---------------------------------------------------*/
382 static
383 Bool handle_compress ( bz_stream* strm )
384 {
385 Bool progress_in = False;
386 Bool progress_out = False;
387 EState* s = strm->state;
388
389 while (True) {
390
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;
402 }
403
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) {
407 flush_RL ( s );
408 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
409 s->state = BZ_S_OUTPUT;
410 }
411 else
412 if (s->nblock >= s->nblockMAX) {
413 BZ2_compressBlock ( s, False );
414 s->state = BZ_S_OUTPUT;
415 }
416 else
417 if (s->strm->avail_in == 0) {
418 break;
419 }
420 }
421
422 }
423
424 return progress_in || progress_out;
425 }
426
427
428 /*---------------------------------------------------*/
429 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
430 {
431 Bool progress;
432 EState* s;
433 if (strm == NULL) return BZ_PARAM_ERROR;
434 s = strm->state;
435 if (s == NULL) return BZ_PARAM_ERROR;
436 if (s->strm != strm) return BZ_PARAM_ERROR;
437
438 preswitch:
439 switch (s->mode) {
440
441 case BZ_M_IDLE:
442 return BZ_SEQUENCE_ERROR;
443
444 case BZ_M_RUNNING:
445 if (action == BZ_RUN) {
446 progress = handle_compress ( strm );
447 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
448 }
449 else
450 if (action == BZ_FLUSH) {
451 s->avail_in_expect = strm->avail_in;
452 s->mode = BZ_M_FLUSHING;
453 goto preswitch;
454 }
455 else
456 if (action == BZ_FINISH) {
457 s->avail_in_expect = strm->avail_in;
458 s->mode = BZ_M_FINISHING;
459 goto preswitch;
460 }
461 else
462 return BZ_PARAM_ERROR;
463
464 case BZ_M_FLUSHING:
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;
472 return BZ_RUN_OK;
473
474 case BZ_M_FINISHING:
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;
482 s->mode = BZ_M_IDLE;
483 return BZ_STREAM_END;
484 }
485 return BZ_OK; /*--not reached--*/
486 }
487
488
489 /*---------------------------------------------------*/
490 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
491 {
492 EState* s;
493 if (strm == NULL) return BZ_PARAM_ERROR;
494 s = strm->state;
495 if (s == NULL) return BZ_PARAM_ERROR;
496 if (s->strm != strm) return BZ_PARAM_ERROR;
497
498 if (s->arr1 != NULL) BZFREE(s->arr1);
499 if (s->arr2 != NULL) BZFREE(s->arr2);
500 if (s->ftab != NULL) BZFREE(s->ftab);
501 BZFREE(strm->state);
502
503 strm->state = NULL;
504
505 return BZ_OK;
506 }
507
508 #endif // BZ_DECOMPRESS_ONLY
509
510 /*---------------------------------------------------*/
511 /*--- Decompression stuff ---*/
512 /*---------------------------------------------------*/
513
514 /*---------------------------------------------------*/
515 int BZ_API(BZ2_bzDecompressInit)
516 ( bz_stream* strm,
517 int verbosity,
518 int small )
519 {
520 DState* s;
521
522 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
523
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;
527
528 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
529 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
530
531 s = BZALLOC( sizeof(DState) );
532 if (s == NULL) return BZ_MEM_ERROR;
533 s->strm = strm;
534 strm->state = s;
535 s->state = BZ_X_MAGIC_1;
536 s->bsLive = 0;
537 s->bsBuff = 0;
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;
544 s->ll4 = NULL;
545 s->ll16 = NULL;
546 s->tt = NULL;
547 s->currBlockNo = 0;
548 s->verbosity = verbosity;
549
550 return BZ_OK;
551 }
552
553 /*---------------------------------------------------*/
554 static
555 void unRLE_obuf_to_output_FAST ( DState* s )
556 {
557 UChar k1;
558
559 if (s->blockRandomised) {
560
561 while (True) {
562 /* try to finish existing run */
563 while (True) {
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 );
568 s->state_out_len--;
569 s->strm->next_out++;
570 s->strm->avail_out--;
571 s->strm->total_out_lo32++;
572 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
573 }
574
575 /* can a new run be started? */
576 if (s->nblock_used == s->save_nblock+1) return;
577
578
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; };
585
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; };
591
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; };
597
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++;
603 }
604
605 } else {
606
607 /* restore */
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;
612 Int32 c_k0 = s->k0;
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;
617 /* end restore */
618
619 UInt32 avail_out_INIT = cs_avail_out;
620 Int32 s_save_nblockPP = s->save_nblock+1;
621 unsigned int total_out_lo32_old;
622
623 while (True) {
624
625 /* try to finish existing run */
626 if (c_state_out_len > 0) {
627 while (True) {
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 );
632 c_state_out_len--;
633 cs_next_out++;
634 cs_avail_out--;
635 }
636 s_state_out_len_eq_one:
637 {
638 if (cs_avail_out == 0) {
639 c_state_out_len = 1; goto return_notr;
640 };
641 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
642 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
643 cs_next_out++;
644 cs_avail_out--;
645 }
646 }
647 /* can a new run be started? */
648 if (c_nblock_used == s_save_nblockPP) {
649 c_state_out_len = 0; goto return_notr;
650 };
651 c_state_out_ch = c_k0;
652 BZ_GET_FAST_C(k1); c_nblock_used++;
653 if (k1 != c_k0) {
654 c_k0 = k1; goto s_state_out_len_eq_one;
655 };
656 if (c_nblock_used == s_save_nblockPP)
657 goto s_state_out_len_eq_one;
658
659 c_state_out_len = 2;
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; };
663
664 c_state_out_len = 3;
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; };
668
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++;
672 }
673
674 return_notr:
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++;
679
680 /* save */
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;
685 s->k0 = c_k0;
686 s->tt = c_tt;
687 s->tPos = c_tPos;
688 s->strm->next_out = cs_next_out;
689 s->strm->avail_out = cs_avail_out;
690 /* end save */
691 }
692 }
693
694 /*---------------------------------------------------*/
695 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
696 {
697 Int32 nb, na, mid;
698 nb = 0;
699 na = 256;
700 do {
701 mid = (nb + na) >> 1;
702 if (indx >= cftab[mid]) nb = mid; else na = mid;
703 }
704 while (na - nb != 1);
705 return nb;
706 }
707
708 /*---------------------------------------------------*/
709 static
710 void unRLE_obuf_to_output_SMALL ( DState* s )
711 {
712 UChar k1;
713
714 if (s->blockRandomised) {
715
716 while (True) {
717 /* try to finish existing run */
718 while (True) {
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 );
723 s->state_out_len--;
724 s->strm->next_out++;
725 s->strm->avail_out--;
726 s->strm->total_out_lo32++;
727 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
728 }
729
730 /* can a new run be started? */
731 if (s->nblock_used == s->save_nblock+1) return;
732
733
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; };
740
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; };
746
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; };
752
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++;
758 }
759
760 } else {
761
762 while (True) {
763 /* try to finish existing run */
764 while (True) {
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 );
769 s->state_out_len--;
770 s->strm->next_out++;
771 s->strm->avail_out--;
772 s->strm->total_out_lo32++;
773 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
774 }
775
776 /* can a new run be started? */
777 if (s->nblock_used == s->save_nblock+1) return;
778
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; };
784
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; };
789
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; };
794
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++;
798 }
799
800 }
801 }
802
803 /*---------------------------------------------------*/
804 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
805 {
806 DState* s;
807 if (strm == NULL) return BZ_PARAM_ERROR;
808 s = strm->state;
809 if (s == NULL) return BZ_PARAM_ERROR;
810 if (s->strm != strm) return BZ_PARAM_ERROR;
811
812 while (True) {
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;
831 } else {
832 return BZ_OK;
833 }
834 }
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;
843 return r;
844 }
845 if (s->state != BZ_X_OUTPUT) return r;
846 }
847 }
848
849 AssertH ( 0, 6001 );
850
851 return 0; /*NOTREACHED*/
852 }
853
854
855 /*---------------------------------------------------*/
856 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
857 {
858 DState* s;
859 if (strm == NULL) return BZ_PARAM_ERROR;
860 s = strm->state;
861 if (s == NULL) return BZ_PARAM_ERROR;
862 if (s->strm != strm) return BZ_PARAM_ERROR;
863
864 if (s->tt != NULL) BZFREE(s->tt);
865 if (s->ll16 != NULL) BZFREE(s->ll16);
866 if (s->ll4 != NULL) BZFREE(s->ll4);
867
868 BZFREE(strm->state);
869 strm->state = NULL;
870
871 return BZ_OK;
872 }
873
874
875 #ifndef BZ_NO_STDIO
876 /*---------------------------------------------------*/
877 /*--- File I/O stuff ---*/
878 /*---------------------------------------------------*/
879
880 #define BZ_SETERR(eee) \
881 { \
882 if (bzerror != NULL) *bzerror = eee; \
883 if (bzf != NULL) bzf->lastErr = eee; \
884 }
885
886 typedef
887 struct {
888 FILE* handle;
889 Char buf[BZ_MAX_UNUSED];
890 Int32 bufN;
891 Bool writing;
892 bz_stream strm;
893 Int32 lastErr;
894 Bool initialisedOk;
895 }
896 bzFile;
897
898
899 /*---------------------------------------------*/
900 static Bool myfeof ( FILE* f )
901 {
902 Int32 c = fgetc ( f );
903 if (c == EOF) return True;
904 ungetc ( c, f );
905 return False;
906 }
907
908
909 /*---------------------------------------------------*/
910 BZFILE* BZ_API(BZ2_bzWriteOpen)
911 ( int* bzerror,
912 FILE* f,
913 int blockSize100k,
914 int verbosity,
915 int workFactor )
916 {
917 Int32 ret;
918 bzFile* bzf = NULL;
919
920 BZ_SETERR(BZ_OK);
921
922 if (f == NULL ||
923 (blockSize100k < 1 || blockSize100k > 9) ||
924 (workFactor < 0 || workFactor > 250) ||
925 (verbosity < 0 || verbosity > 4))
926 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
927
928 if (ferror(f))
929 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
930
931 bzf = malloc ( sizeof(bzFile) );
932 if (bzf == NULL)
933 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
934
935 BZ_SETERR(BZ_OK);
936 bzf->initialisedOk = False;
937 bzf->bufN = 0;
938 bzf->handle = f;
939 bzf->writing = True;
940 bzf->strm.bzalloc = NULL;
941 bzf->strm.bzfree = NULL;
942 bzf->strm.opaque = NULL;
943
944 if (workFactor == 0) workFactor = 30;
945 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
946 verbosity, workFactor );
947 if (ret != BZ_OK)
948 { BZ_SETERR(ret); free(bzf); return NULL; };
949
950 bzf->strm.avail_in = 0;
951 bzf->initialisedOk = True;
952 return bzf;
953 }
954
955
956
957 /*---------------------------------------------------*/
958 void BZ_API(BZ2_bzWrite)
959 ( int* bzerror,
960 BZFILE* b,
961 void* buf,
962 int len )
963 {
964 Int32 n, n2, ret;
965 bzFile* bzf = (bzFile*)b;
966
967 BZ_SETERR(BZ_OK);
968 if (bzf == NULL || buf == NULL || len < 0)
969 { BZ_SETERR(BZ_PARAM_ERROR); return; };
970 if (!(bzf->writing))
971 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
972 if (ferror(bzf->handle))
973 { BZ_SETERR(BZ_IO_ERROR); return; };
974
975 if (len == 0)
976 { BZ_SETERR(BZ_OK); return; };
977
978 bzf->strm.avail_in = len;
979 bzf->strm.next_in = buf;
980
981 while (True) {
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; };
987
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),
991 n, bzf->handle );
992 if (n != n2 || ferror(bzf->handle))
993 { BZ_SETERR(BZ_IO_ERROR); return; };
994 }
995
996 if (bzf->strm.avail_in == 0)
997 { BZ_SETERR(BZ_OK); return; };
998 }
999 }
1000
1001
1002 /*---------------------------------------------------*/
1003 void BZ_API(BZ2_bzWriteClose)
1004 ( int* bzerror,
1005 BZFILE* b,
1006 int abandon,
1007 unsigned int* nbytes_in,
1008 unsigned int* nbytes_out )
1009 {
1010 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1011 nbytes_in, NULL, nbytes_out, NULL );
1012 }
1013
1014
1015 void BZ_API(BZ2_bzWriteClose64)
1016 ( int* bzerror,
1017 BZFILE* b,
1018 int abandon,
1019 unsigned int* nbytes_in_lo32,
1020 unsigned int* nbytes_in_hi32,
1021 unsigned int* nbytes_out_lo32,
1022 unsigned int* nbytes_out_hi32 )
1023 {
1024 Int32 n, n2, ret;
1025 bzFile* bzf = (bzFile*)b;
1026
1027 if (bzf == NULL)
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; };
1033
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;
1038
1039 if ((!abandon) && bzf->lastErr == BZ_OK) {
1040 while (True) {
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; };
1046
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),
1050 n, bzf->handle );
1051 if (n != n2 || ferror(bzf->handle))
1052 { BZ_SETERR(BZ_IO_ERROR); return; };
1053 }
1054
1055 if (ret == BZ_STREAM_END) break;
1056 }
1057 }
1058
1059 if ( !abandon && !ferror ( bzf->handle ) ) {
1060 fflush ( bzf->handle );
1061 if (ferror(bzf->handle))
1062 { BZ_SETERR(BZ_IO_ERROR); return; };
1063 }
1064
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;
1073
1074 BZ_SETERR(BZ_OK);
1075 BZ2_bzCompressEnd ( &(bzf->strm) );
1076 free ( bzf );
1077 }
1078
1079
1080 /*---------------------------------------------------*/
1081 BZFILE* BZ_API(BZ2_bzReadOpen)
1082 ( int* bzerror,
1083 FILE* f,
1084 int verbosity,
1085 int small,
1086 void* unused,
1087 int nUnused )
1088 {
1089 bzFile* bzf = NULL;
1090 int ret;
1091
1092 BZ_SETERR(BZ_OK);
1093
1094 if (f == NULL ||
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; };
1100
1101 if (ferror(f))
1102 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1103
1104 bzf = malloc ( sizeof(bzFile) );
1105 if (bzf == NULL)
1106 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1107
1108 BZ_SETERR(BZ_OK);
1109
1110 bzf->initialisedOk = False;
1111 bzf->handle = f;
1112 bzf->bufN = 0;
1113 bzf->writing = False;
1114 bzf->strm.bzalloc = NULL;
1115 bzf->strm.bzfree = NULL;
1116 bzf->strm.opaque = NULL;
1117
1118 while (nUnused > 0) {
1119 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1120 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1121 nUnused--;
1122 }
1123
1124 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1125 if (ret != BZ_OK)
1126 { BZ_SETERR(ret); free(bzf); return NULL; };
1127
1128 bzf->strm.avail_in = bzf->bufN;
1129 bzf->strm.next_in = bzf->buf;
1130
1131 bzf->initialisedOk = True;
1132 return bzf;
1133 }
1134
1135
1136 /*---------------------------------------------------*/
1137 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1138 {
1139 bzFile* bzf = (bzFile*)b;
1140
1141 BZ_SETERR(BZ_OK);
1142 if (bzf == NULL)
1143 { BZ_SETERR(BZ_OK); return; };
1144
1145 if (bzf->writing)
1146 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1147
1148 if (bzf->initialisedOk)
1149 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1150 free ( bzf );
1151 }
1152
1153
1154 /*---------------------------------------------------*/
1155 int BZ_API(BZ2_bzRead)
1156 ( int* bzerror,
1157 BZFILE* b,
1158 void* buf,
1159 int len )
1160 {
1161 Int32 n, ret;
1162 bzFile* bzf = (bzFile*)b;
1163
1164 BZ_SETERR(BZ_OK);
1165
1166 if (bzf == NULL || buf == NULL || len < 0)
1167 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1168
1169 if (bzf->writing)
1170 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1171
1172 if (len == 0)
1173 { BZ_SETERR(BZ_OK); return 0; };
1174
1175 bzf->strm.avail_out = len;
1176 bzf->strm.next_out = buf;
1177
1178 while (True) {
1179
1180 if (ferror(bzf->handle))
1181 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1182
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; };
1188 bzf->bufN = n;
1189 bzf->strm.avail_in = bzf->bufN;
1190 bzf->strm.next_in = bzf->buf;
1191 }
1192
1193 ret = BZ2_bzDecompress ( &(bzf->strm) );
1194
1195 if (ret != BZ_OK && ret != BZ_STREAM_END)
1196 { BZ_SETERR(ret); return 0; };
1197
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; };
1201
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; };
1207
1208 }
1209
1210 return 0; /*not reached*/
1211 }
1212
1213
1214 /*---------------------------------------------------*/
1215 void BZ_API(BZ2_bzReadGetUnused)
1216 ( int* bzerror,
1217 BZFILE* b,
1218 void** unused,
1219 int* nUnused )
1220 {
1221 bzFile* bzf = (bzFile*)b;
1222 if (bzf == NULL)
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; };
1228
1229 BZ_SETERR(BZ_OK);
1230 *nUnused = bzf->strm.avail_in;
1231 *unused = bzf->strm.next_in;
1232 }
1233 #endif
1234
1235 #ifndef BZ_DECOMPRESS_ONLY
1236
1237 /*---------------------------------------------------*/
1238 /*--- Misc convenience stuff ---*/
1239 /*---------------------------------------------------*/
1240
1241 /*---------------------------------------------------*/
1242 int BZ_API(BZ2_bzBuffToBuffCompress)
1243 ( char* dest,
1244 unsigned int* destLen,
1245 char* source,
1246 unsigned int sourceLen,
1247 int blockSize100k,
1248 int verbosity,
1249 int workFactor )
1250 {
1251 bz_stream strm;
1252 int ret;
1253
1254 if (dest == NULL || destLen == NULL ||
1255 source == NULL ||
1256 blockSize100k < 1 || blockSize100k > 9 ||
1257 verbosity < 0 || verbosity > 4 ||
1258 workFactor < 0 || workFactor > 250)
1259 return BZ_PARAM_ERROR;
1260
1261 if (workFactor == 0) workFactor = 30;
1262 strm.bzalloc = NULL;
1263 strm.bzfree = NULL;
1264 strm.opaque = NULL;
1265 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1266 verbosity, workFactor );
1267 if (ret != BZ_OK) return ret;
1268
1269 strm.next_in = source;
1270 strm.next_out = dest;
1271 strm.avail_in = sourceLen;
1272 strm.avail_out = *destLen;
1273
1274 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1275 if (ret == BZ_FINISH_OK) goto output_overflow;
1276 if (ret != BZ_STREAM_END) goto errhandler;
1277
1278 /* normal termination */
1279 *destLen -= strm.avail_out;
1280 BZ2_bzCompressEnd ( &strm );
1281 return BZ_OK;
1282
1283 output_overflow:
1284 BZ2_bzCompressEnd ( &strm );
1285 return BZ_OUTBUFF_FULL;
1286
1287 errhandler:
1288 BZ2_bzCompressEnd ( &strm );
1289 return ret;
1290 }
1291
1292 #endif // BZ_DECOMPRESS_0NLY
1293
1294 /*---------------------------------------------------*/
1295 int BZ_API(BZ2_bzBuffToBuffDecompress)
1296 ( char* dest,
1297 unsigned int* destLen,
1298 char* source,
1299 unsigned int sourceLen,
1300 int small,
1301 int verbosity )
1302 {
1303 bz_stream strm;
1304 int ret;
1305
1306 if (dest == NULL || destLen == NULL ||
1307 source == NULL ||
1308 (small != 0 && small != 1) ||
1309 verbosity < 0 || verbosity > 4)
1310 return BZ_PARAM_ERROR;
1311
1312 strm.bzalloc = NULL;
1313 strm.bzfree = NULL;
1314 strm.opaque = NULL;
1315 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1316 if (ret != BZ_OK) return ret;
1317
1318 strm.next_in = source;
1319 strm.next_out = dest;
1320 strm.avail_in = sourceLen;
1321 strm.avail_out = *destLen;
1322
1323 ret = BZ2_bzDecompress ( &strm );
1324 if (ret == BZ_OK) goto output_overflow_or_eof;
1325 if (ret != BZ_STREAM_END) goto errhandler;
1326
1327 /* normal termination */
1328 *destLen -= strm.avail_out;
1329 BZ2_bzDecompressEnd ( &strm );
1330 return BZ_OK;
1331
1332 output_overflow_or_eof:
1333 if (strm.avail_out > 0) {
1334 BZ2_bzDecompressEnd ( &strm );
1335 return BZ_UNEXPECTED_EOF;
1336 } else {
1337 BZ2_bzDecompressEnd ( &strm );
1338 return BZ_OUTBUFF_FULL;
1339 };
1340
1341 errhandler:
1342 BZ2_bzDecompressEnd ( &strm );
1343 return ret;
1344 }
1345
1346
1347 /*---------------------------------------------------*/
1348 /*--
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.
1356 --*/
1357 /*---------------------------------------------------*/
1358
1359 /*---------------------------------------------------*/
1360 /*--
1361 return version like "0.9.0c".
1362 --*/
1363 const char * BZ_API(BZ2_bzlibVersion)(void)
1364 {
1365 return BZ_VERSION;
1366 }
1367
1368
1369 #ifndef BZ_NO_STDIO
1370 /*---------------------------------------------------*/
1371
1372 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1373 # include <fcntl.h>
1374 # include <io.h>
1375 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1376 #else
1377 # define SET_BINARY_MODE(file)
1378 #endif
1379 static
1380 BZFILE * bzopen_or_bzdopen
1381 ( const char *path, /* no use when bzdopen */
1382 int fd, /* no use when bzdopen */
1383 const char *mode,
1384 int open_mode) /* bzopen: 0, bzdopen:1 */
1385 {
1386 int bzerr;
1387 char unused[BZ_MAX_UNUSED];
1388 int blockSize100k = 9;
1389 int writing = 0;
1390 char mode2[10] = "";
1391 FILE *fp = NULL;
1392 BZFILE *bzfp = NULL;
1393 int verbosity = 0;
1394 int workFactor = 30;
1395 int smallMode = 0;
1396 int nUnused = 0;
1397
1398 if (mode == NULL) return NULL;
1399 while (*mode) {
1400 switch (*mode) {
1401 case 'r':
1402 writing = 0; break;
1403 case 'w':
1404 writing = 1; break;
1405 case 's':
1406 smallMode = 1; break;
1407 default:
1408 if (isdigit((int)(*mode))) {
1409 blockSize100k = *mode-'0';
1410 }
1411 }
1412 mode++;
1413 }
1414 strcat(mode2, writing ? "w" : "r" );
1415 strcat(mode2,"b"); /* binary mode */
1416
1417 if (open_mode==0) {
1418 if (path==NULL || strcmp(path,"")==0) {
1419 fp = (writing ? stdout : stdin);
1420 SET_BINARY_MODE(fp);
1421 } else {
1422 fp = fopen(path,mode2);
1423 }
1424 } else {
1425 #ifdef BZ_STRICT_ANSI
1426 fp = NULL;
1427 #else
1428 fp = fdopen(fd,mode2);
1429 #endif
1430 }
1431 if (fp == NULL) return NULL;
1432
1433 if (writing) {
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);
1439 } else {
1440 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1441 unused,nUnused);
1442 }
1443 if (bzfp == NULL) {
1444 if (fp != stdin && fp != stdout) fclose(fp);
1445 return NULL;
1446 }
1447 return bzfp;
1448 }
1449
1450
1451 /*---------------------------------------------------*/
1452 /*--
1453 open file for read or write.
1454 ex) bzopen("file","w9")
1455 case path="" or NULL => use stdin or stdout.
1456 --*/
1457 BZFILE * BZ_API(BZ2_bzopen)
1458 ( const char *path,
1459 const char *mode )
1460 {
1461 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1462 }
1463
1464
1465 /*---------------------------------------------------*/
1466 BZFILE * BZ_API(BZ2_bzdopen)
1467 ( int fd,
1468 const char *mode )
1469 {
1470 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1471 }
1472
1473
1474 /*---------------------------------------------------*/
1475 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1476 {
1477 int bzerr, nread;
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) {
1481 return nread;
1482 } else {
1483 return -1;
1484 }
1485 }
1486
1487
1488 /*---------------------------------------------------*/
1489 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1490 {
1491 int bzerr;
1492
1493 BZ2_bzWrite(&bzerr,b,buf,len);
1494 if(bzerr == BZ_OK){
1495 return len;
1496 }else{
1497 return -1;
1498 }
1499 }
1500
1501
1502 /*---------------------------------------------------*/
1503 int BZ_API(BZ2_bzflush) (BZFILE *b)
1504 {
1505 /* do nothing now... */
1506 return 0;
1507 }
1508
1509
1510 /*---------------------------------------------------*/
1511 void BZ_API(BZ2_bzclose) (BZFILE* b)
1512 {
1513 int bzerr;
1514 FILE *fp = ((bzFile *)b)->handle;
1515
1516 if (b==NULL) {return;}
1517 if(((bzFile*)b)->writing){
1518 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1519 if(bzerr != BZ_OK){
1520 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1521 }
1522 }else{
1523 BZ2_bzReadClose(&bzerr,b);
1524 }
1525 if(fp!=stdin && fp!=stdout){
1526 fclose(fp);
1527 }
1528 }
1529
1530
1531 /*---------------------------------------------------*/
1532 /*--
1533 return last error code
1534 --*/
1535 static char *bzerrorstrings[] = {
1536 "OK"
1537 ,"SEQUENCE_ERROR"
1538 ,"PARAM_ERROR"
1539 ,"MEM_ERROR"
1540 ,"DATA_ERROR"
1541 ,"DATA_ERROR_MAGIC"
1542 ,"IO_ERROR"
1543 ,"UNEXPECTED_EOF"
1544 ,"OUTBUFF_FULL"
1545 ,"CONFIG_ERROR"
1546 ,"???" /* for future */
1547 ,"???" /* for future */
1548 ,"???" /* for future */
1549 ,"???" /* for future */
1550 ,"???" /* for future */
1551 ,"???" /* for future */
1552 };
1553
1554
1555 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1556 {
1557 int err = ((bzFile *)b)->lastErr;
1558
1559 if(err>0) err = 0;
1560 *errnum = err;
1561 return bzerrorstrings[err*-1];
1562 }
1563 #endif
1564
1565
1566 /*-------------------------------------------------------------*/
1567 /*--- end bzlib.c ---*/
1568 /*-------------------------------------------------------------*/