[BZIP2]
[reactos.git] / reactos / lib / 3rdparty / bzip2 / bzlib.c
1
2 /*-------------------------------------------------------------*/
3 /*--- Library top-level functions. ---*/
4 /*--- bzlib.c ---*/
5 /*-------------------------------------------------------------*/
6
7 /* ------------------------------------------------------------------
8 This file is part of bzip2/libbzip2, a program and library for
9 lossless, block-sorting data compression.
10
11 bzip2/libbzip2 version 1.0.6 of 6 September 2010
12 Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
13
14 Please read the WARNING, DISCLAIMER and PATENTS sections in the
15 README file.
16
17 This program is released under the terms of the license contained
18 in the file LICENSE.
19 ------------------------------------------------------------------ */
20
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.
29 */
30
31 #ifdef BZ_DECOMPRESS_ONLY
32 #ifndef __NTDRIVER__
33 #define __NTDRIVER__
34 #endif
35 #include <wdm.h>
36 #include <debug.h>
37 #endif
38 #include "bzlib_private.h"
39
40
41 /*---------------------------------------------------*/
42 /*--- Compression stuff ---*/
43 /*---------------------------------------------------*/
44
45
46 /*---------------------------------------------------*/
47 #ifndef BZ_NO_STDIO
48 void BZ2_bz__AssertH__fail ( int errcode )
49 {
50 fprintf(stderr,
51 "\n\nbzip2/libbzip2: internal error number %d.\n"
52 "This is a bug in bzip2/libbzip2, %s.\n"
53 "Please report it to me at: jseward@bzip.org. If this happened\n"
54 "when you were using some program which uses libbzip2 as a\n"
55 "component, you should also report this bug to the author(s)\n"
56 "of that program. Please make an effort to report this bug;\n"
57 "timely and accurate bug reports eventually lead to higher\n"
58 "quality software. Thanks. Julian Seward, 10 December 2007.\n\n",
59 errcode,
60 BZ2_bzlibVersion()
61 );
62
63 if (errcode == 1007) {
64 fprintf(stderr,
65 "\n*** A special note about internal error number 1007 ***\n"
66 "\n"
67 "Experience suggests that a common cause of i.e. 1007\n"
68 "is unreliable memory or other hardware. The 1007 assertion\n"
69 "just happens to cross-check the results of huge numbers of\n"
70 "memory reads/writes, and so acts (unintendedly) as a stress\n"
71 "test of your memory system.\n"
72 "\n"
73 "I suggest the following: try compressing the file again,\n"
74 "possibly monitoring progress in detail with the -vv flag.\n"
75 "\n"
76 "* If the error cannot be reproduced, and/or happens at different\n"
77 " points in compression, you may have a flaky memory system.\n"
78 " Try a memory-test program. I have used Memtest86\n"
79 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
80 " Memtest86 tests memory much more thorougly than your BIOSs\n"
81 " power-on test, and may find failures that the BIOS doesn't.\n"
82 "\n"
83 "* If the error can be repeatably reproduced, this is a bug in\n"
84 " bzip2, and I would very much like to hear about it. Please\n"
85 " let me know, and, ideally, save a copy of the file causing the\n"
86 " problem -- without which I will be unable to investigate it.\n"
87 "\n"
88 );
89 }
90
91 exit(3);
92 }
93 #endif
94
95
96 /*---------------------------------------------------*/
97 static
98 int bz_config_ok ( void )
99 {
100 if (sizeof(int) != 4) return 0;
101 if (sizeof(short) != 2) return 0;
102 if (sizeof(char) != 1) return 0;
103 return 1;
104 }
105
106
107 /*---------------------------------------------------*/
108 static
109 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
110 {
111 return ExAllocatePool( PagedPool, items * size );
112 }
113
114 static
115 void default_bzfree ( void* opaque, void* addr )
116 {
117 ExFreePool( addr );
118 }
119
120 #ifndef BZ_DECOMPRESS_ONLY
121
122 /*---------------------------------------------------*/
123 static
124 void prepare_new_block ( EState* s )
125 {
126 Int32 i;
127 s->nblock = 0;
128 s->numZ = 0;
129 s->state_out_pos = 0;
130 BZ_INITIALISE_CRC ( s->blockCRC );
131 for (i = 0; i < 256; i++) s->inUse[i] = False;
132 s->blockNo++;
133 }
134
135
136 /*---------------------------------------------------*/
137 static
138 void init_RL ( EState* s )
139 {
140 s->state_in_ch = 256;
141 s->state_in_len = 0;
142 }
143
144
145 static
146 Bool isempty_RL ( EState* s )
147 {
148 if (s->state_in_ch < 256 && s->state_in_len > 0)
149 return False; else
150 return True;
151 }
152
153
154 /*---------------------------------------------------*/
155 int BZ_API(BZ2_bzCompressInit)
156 ( bz_stream* strm,
157 int blockSize100k,
158 int verbosity,
159 int workFactor )
160 {
161 Int32 n;
162 EState* s;
163
164 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
165
166 if (strm == NULL ||
167 blockSize100k < 1 || blockSize100k > 9 ||
168 workFactor < 0 || workFactor > 250)
169 return BZ_PARAM_ERROR;
170
171 if (workFactor == 0) workFactor = 30;
172 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
173 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
174
175 s = BZALLOC( sizeof(EState) );
176 if (s == NULL) return BZ_MEM_ERROR;
177 s->strm = strm;
178
179 s->arr1 = NULL;
180 s->arr2 = NULL;
181 s->ftab = NULL;
182
183 n = 100000 * blockSize100k;
184 s->arr1 = BZALLOC( n * sizeof(UInt32) );
185 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
186 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
187
188 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
189 if (s->arr1 != NULL) BZFREE(s->arr1);
190 if (s->arr2 != NULL) BZFREE(s->arr2);
191 if (s->ftab != NULL) BZFREE(s->ftab);
192 if (s != NULL) BZFREE(s);
193 return BZ_MEM_ERROR;
194 }
195
196 s->blockNo = 0;
197 s->state = BZ_S_INPUT;
198 s->mode = BZ_M_RUNNING;
199 s->combinedCRC = 0;
200 s->blockSize100k = blockSize100k;
201 s->nblockMAX = 100000 * blockSize100k - 19;
202 s->verbosity = verbosity;
203 s->workFactor = workFactor;
204
205 s->block = (UChar*)s->arr2;
206 s->mtfv = (UInt16*)s->arr1;
207 s->zbits = NULL;
208 s->ptr = (UInt32*)s->arr1;
209
210 strm->state = s;
211 strm->total_in_lo32 = 0;
212 strm->total_in_hi32 = 0;
213 strm->total_out_lo32 = 0;
214 strm->total_out_hi32 = 0;
215 init_RL ( s );
216 prepare_new_block ( s );
217 return BZ_OK;
218 }
219
220
221 /*---------------------------------------------------*/
222 static
223 void add_pair_to_block ( EState* s )
224 {
225 Int32 i;
226 UChar ch = (UChar)(s->state_in_ch);
227 for (i = 0; i < s->state_in_len; i++) {
228 BZ_UPDATE_CRC( s->blockCRC, ch );
229 }
230 s->inUse[s->state_in_ch] = True;
231 switch (s->state_in_len) {
232 case 1:
233 s->block[s->nblock] = (UChar)ch; s->nblock++;
234 break;
235 case 2:
236 s->block[s->nblock] = (UChar)ch; s->nblock++;
237 s->block[s->nblock] = (UChar)ch; s->nblock++;
238 break;
239 case 3:
240 s->block[s->nblock] = (UChar)ch; s->nblock++;
241 s->block[s->nblock] = (UChar)ch; s->nblock++;
242 s->block[s->nblock] = (UChar)ch; s->nblock++;
243 break;
244 default:
245 s->inUse[s->state_in_len-4] = True;
246 s->block[s->nblock] = (UChar)ch; s->nblock++;
247 s->block[s->nblock] = (UChar)ch; s->nblock++;
248 s->block[s->nblock] = (UChar)ch; s->nblock++;
249 s->block[s->nblock] = (UChar)ch; s->nblock++;
250 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
251 s->nblock++;
252 break;
253 }
254 }
255
256
257 /*---------------------------------------------------*/
258 static
259 void flush_RL ( EState* s )
260 {
261 if (s->state_in_ch < 256) add_pair_to_block ( s );
262 init_RL ( s );
263 }
264
265
266 /*---------------------------------------------------*/
267 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
268 { \
269 UInt32 zchh = (UInt32)(zchh0); \
270 /*-- fast track the common case --*/ \
271 if (zchh != zs->state_in_ch && \
272 zs->state_in_len == 1) { \
273 UChar ch = (UChar)(zs->state_in_ch); \
274 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
275 zs->inUse[zs->state_in_ch] = True; \
276 zs->block[zs->nblock] = (UChar)ch; \
277 zs->nblock++; \
278 zs->state_in_ch = zchh; \
279 } \
280 else \
281 /*-- general, uncommon cases --*/ \
282 if (zchh != zs->state_in_ch || \
283 zs->state_in_len == 255) { \
284 if (zs->state_in_ch < 256) \
285 add_pair_to_block ( zs ); \
286 zs->state_in_ch = zchh; \
287 zs->state_in_len = 1; \
288 } else { \
289 zs->state_in_len++; \
290 } \
291 }
292
293
294 /*---------------------------------------------------*/
295 static
296 Bool copy_input_until_stop ( EState* s )
297 {
298 Bool progress_in = False;
299
300 if (s->mode == BZ_M_RUNNING) {
301
302 /*-- fast track the common case --*/
303 while (True) {
304 /*-- block full? --*/
305 if (s->nblock >= s->nblockMAX) break;
306 /*-- no input? --*/
307 if (s->strm->avail_in == 0) break;
308 progress_in = True;
309 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
310 s->strm->next_in++;
311 s->strm->avail_in--;
312 s->strm->total_in_lo32++;
313 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
314 }
315
316 } else {
317
318 /*-- general, uncommon case --*/
319 while (True) {
320 /*-- block full? --*/
321 if (s->nblock >= s->nblockMAX) break;
322 /*-- no input? --*/
323 if (s->strm->avail_in == 0) break;
324 /*-- flush/finish end? --*/
325 if (s->avail_in_expect == 0) break;
326 progress_in = True;
327 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
328 s->strm->next_in++;
329 s->strm->avail_in--;
330 s->strm->total_in_lo32++;
331 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
332 s->avail_in_expect--;
333 }
334 }
335 return progress_in;
336 }
337
338
339 /*---------------------------------------------------*/
340 static
341 Bool copy_output_until_stop ( EState* s )
342 {
343 Bool progress_out = False;
344
345 while (True) {
346
347 /*-- no output space? --*/
348 if (s->strm->avail_out == 0) break;
349
350 /*-- block done? --*/
351 if (s->state_out_pos >= s->numZ) break;
352
353 progress_out = True;
354 *(s->strm->next_out) = s->zbits[s->state_out_pos];
355 s->state_out_pos++;
356 s->strm->avail_out--;
357 s->strm->next_out++;
358 s->strm->total_out_lo32++;
359 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
360 }
361
362 return progress_out;
363 }
364
365
366 /*---------------------------------------------------*/
367 static
368 Bool handle_compress ( bz_stream* strm )
369 {
370 Bool progress_in = False;
371 Bool progress_out = False;
372 EState* s = strm->state;
373
374 while (True) {
375
376 if (s->state == BZ_S_OUTPUT) {
377 progress_out |= copy_output_until_stop ( s );
378 if (s->state_out_pos < s->numZ) break;
379 if (s->mode == BZ_M_FINISHING &&
380 s->avail_in_expect == 0 &&
381 isempty_RL(s)) break;
382 prepare_new_block ( s );
383 s->state = BZ_S_INPUT;
384 if (s->mode == BZ_M_FLUSHING &&
385 s->avail_in_expect == 0 &&
386 isempty_RL(s)) break;
387 }
388
389 if (s->state == BZ_S_INPUT) {
390 progress_in |= copy_input_until_stop ( s );
391 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
392 flush_RL ( s );
393 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
394 s->state = BZ_S_OUTPUT;
395 }
396 else
397 if (s->nblock >= s->nblockMAX) {
398 BZ2_compressBlock ( s, False );
399 s->state = BZ_S_OUTPUT;
400 }
401 else
402 if (s->strm->avail_in == 0) {
403 break;
404 }
405 }
406
407 }
408
409 return progress_in || progress_out;
410 }
411
412
413 /*---------------------------------------------------*/
414 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
415 {
416 Bool progress;
417 EState* s;
418 if (strm == NULL) return BZ_PARAM_ERROR;
419 s = strm->state;
420 if (s == NULL) return BZ_PARAM_ERROR;
421 if (s->strm != strm) return BZ_PARAM_ERROR;
422
423 preswitch:
424 switch (s->mode) {
425
426 case BZ_M_IDLE:
427 return BZ_SEQUENCE_ERROR;
428
429 case BZ_M_RUNNING:
430 if (action == BZ_RUN) {
431 progress = handle_compress ( strm );
432 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
433 }
434 else
435 if (action == BZ_FLUSH) {
436 s->avail_in_expect = strm->avail_in;
437 s->mode = BZ_M_FLUSHING;
438 goto preswitch;
439 }
440 else
441 if (action == BZ_FINISH) {
442 s->avail_in_expect = strm->avail_in;
443 s->mode = BZ_M_FINISHING;
444 goto preswitch;
445 }
446 else
447 return BZ_PARAM_ERROR;
448
449 case BZ_M_FLUSHING:
450 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
451 if (s->avail_in_expect != s->strm->avail_in)
452 return BZ_SEQUENCE_ERROR;
453 progress = handle_compress ( strm );
454 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
455 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
456 s->mode = BZ_M_RUNNING;
457 return BZ_RUN_OK;
458
459 case BZ_M_FINISHING:
460 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
461 if (s->avail_in_expect != s->strm->avail_in)
462 return BZ_SEQUENCE_ERROR;
463 progress = handle_compress ( strm );
464 if (!progress) return BZ_SEQUENCE_ERROR;
465 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
466 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
467 s->mode = BZ_M_IDLE;
468 return BZ_STREAM_END;
469 }
470 return BZ_OK; /*--not reached--*/
471 }
472
473
474 /*---------------------------------------------------*/
475 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
476 {
477 EState* s;
478 if (strm == NULL) return BZ_PARAM_ERROR;
479 s = strm->state;
480 if (s == NULL) return BZ_PARAM_ERROR;
481 if (s->strm != strm) return BZ_PARAM_ERROR;
482
483 if (s->arr1 != NULL) BZFREE(s->arr1);
484 if (s->arr2 != NULL) BZFREE(s->arr2);
485 if (s->ftab != NULL) BZFREE(s->ftab);
486 BZFREE(strm->state);
487
488 strm->state = NULL;
489
490 return BZ_OK;
491 }
492
493 #endif // BZ_DECOMPRESS_ONLY
494
495 /*---------------------------------------------------*/
496 /*--- Decompression stuff ---*/
497 /*---------------------------------------------------*/
498
499 /*---------------------------------------------------*/
500 int BZ_API(BZ2_bzDecompressInit)
501 ( bz_stream* strm,
502 int verbosity,
503 int small )
504 {
505 DState* s;
506
507 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
508
509 if (strm == NULL) return BZ_PARAM_ERROR;
510 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
511 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
512
513 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
514 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
515
516 s = BZALLOC( sizeof(DState) );
517 if (s == NULL) return BZ_MEM_ERROR;
518 s->strm = strm;
519 strm->state = s;
520 s->state = BZ_X_MAGIC_1;
521 s->bsLive = 0;
522 s->bsBuff = 0;
523 s->calculatedCombinedCRC = 0;
524 strm->total_in_lo32 = 0;
525 strm->total_in_hi32 = 0;
526 strm->total_out_lo32 = 0;
527 strm->total_out_hi32 = 0;
528 s->smallDecompress = (Bool)small;
529 s->ll4 = NULL;
530 s->ll16 = NULL;
531 s->tt = NULL;
532 s->currBlockNo = 0;
533 s->verbosity = verbosity;
534
535 return BZ_OK;
536 }
537
538 #ifndef BZ_DECOMPRESS_ONLY
539
540 /*---------------------------------------------------*/
541 /* Return True iff data corruption is discovered.
542 Returns False if there is no problem.
543 */
544 static
545 Bool unRLE_obuf_to_output_FAST ( DState* s )
546 {
547 UChar k1;
548
549 if (s->blockRandomised) {
550
551 while (True) {
552 /* try to finish existing run */
553 while (True) {
554 if (s->strm->avail_out == 0) return False;
555 if (s->state_out_len == 0) break;
556 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
557 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
558 s->state_out_len--;
559 s->strm->next_out++;
560 s->strm->avail_out--;
561 s->strm->total_out_lo32++;
562 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
563 }
564
565 /* can a new run be started? */
566 if (s->nblock_used == s->save_nblock+1) return False;
567
568 /* Only caused by corrupt data stream? */
569 if (s->nblock_used > s->save_nblock+1)
570 return True;
571
572 s->state_out_len = 1;
573 s->state_out_ch = s->k0;
574 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
575 k1 ^= BZ_RAND_MASK; s->nblock_used++;
576 if (s->nblock_used == s->save_nblock+1) continue;
577 if (k1 != s->k0) { s->k0 = k1; continue; };
578
579 s->state_out_len = 2;
580 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
581 k1 ^= BZ_RAND_MASK; s->nblock_used++;
582 if (s->nblock_used == s->save_nblock+1) continue;
583 if (k1 != s->k0) { s->k0 = k1; continue; };
584
585 s->state_out_len = 3;
586 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
587 k1 ^= BZ_RAND_MASK; s->nblock_used++;
588 if (s->nblock_used == s->save_nblock+1) continue;
589 if (k1 != s->k0) { s->k0 = k1; continue; };
590
591 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
592 k1 ^= BZ_RAND_MASK; s->nblock_used++;
593 s->state_out_len = ((Int32)k1) + 4;
594 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
595 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
596 }
597
598 } else {
599
600 /* restore */
601 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
602 UChar c_state_out_ch = s->state_out_ch;
603 Int32 c_state_out_len = s->state_out_len;
604 Int32 c_nblock_used = s->nblock_used;
605 Int32 c_k0 = s->k0;
606 UInt32* c_tt = s->tt;
607 UInt32 c_tPos = s->tPos;
608 char* cs_next_out = s->strm->next_out;
609 unsigned int cs_avail_out = s->strm->avail_out;
610 Int32 ro_blockSize100k = s->blockSize100k;
611 /* end restore */
612
613 UInt32 avail_out_INIT = cs_avail_out;
614 Int32 s_save_nblockPP = s->save_nblock+1;
615 unsigned int total_out_lo32_old;
616
617 while (True) {
618
619 /* try to finish existing run */
620 if (c_state_out_len > 0) {
621 while (True) {
622 if (cs_avail_out == 0) goto return_notr;
623 if (c_state_out_len == 1) break;
624 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
625 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
626 c_state_out_len--;
627 cs_next_out++;
628 cs_avail_out--;
629 }
630 s_state_out_len_eq_one:
631 {
632 if (cs_avail_out == 0) {
633 c_state_out_len = 1; goto return_notr;
634 };
635 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
636 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
637 cs_next_out++;
638 cs_avail_out--;
639 }
640 }
641 /* Only caused by corrupt data stream? */
642 if (c_nblock_used > s_save_nblockPP)
643 return True;
644
645 /* can a new run be started? */
646 if (c_nblock_used == s_save_nblockPP) {
647 c_state_out_len = 0; goto return_notr;
648 };
649 c_state_out_ch = c_k0;
650 BZ_GET_FAST_C(k1); c_nblock_used++;
651 if (k1 != c_k0) {
652 c_k0 = k1; goto s_state_out_len_eq_one;
653 };
654 if (c_nblock_used == s_save_nblockPP)
655 goto s_state_out_len_eq_one;
656
657 c_state_out_len = 2;
658 BZ_GET_FAST_C(k1); c_nblock_used++;
659 if (c_nblock_used == s_save_nblockPP) continue;
660 if (k1 != c_k0) { c_k0 = k1; continue; };
661
662 c_state_out_len = 3;
663 BZ_GET_FAST_C(k1); c_nblock_used++;
664 if (c_nblock_used == s_save_nblockPP) continue;
665 if (k1 != c_k0) { c_k0 = k1; continue; };
666
667 BZ_GET_FAST_C(k1); c_nblock_used++;
668 c_state_out_len = ((Int32)k1) + 4;
669 BZ_GET_FAST_C(c_k0); c_nblock_used++;
670 }
671
672 return_notr:
673 total_out_lo32_old = s->strm->total_out_lo32;
674 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
675 if (s->strm->total_out_lo32 < total_out_lo32_old)
676 s->strm->total_out_hi32++;
677
678 /* save */
679 s->calculatedBlockCRC = c_calculatedBlockCRC;
680 s->state_out_ch = c_state_out_ch;
681 s->state_out_len = c_state_out_len;
682 s->nblock_used = c_nblock_used;
683 s->k0 = c_k0;
684 s->tt = c_tt;
685 s->tPos = c_tPos;
686 s->strm->next_out = cs_next_out;
687 s->strm->avail_out = cs_avail_out;
688 /* end save */
689 }
690 return False;
691 }
692
693 #endif // BZ_DECOMPRESS_ONLY
694
695
696 /*---------------------------------------------------*/
697 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
698 {
699 Int32 nb, na, mid;
700 nb = 0;
701 na = 256;
702 do {
703 mid = (nb + na) >> 1;
704 if (indx >= cftab[mid]) nb = mid; else na = mid;
705 }
706 while (na - nb != 1);
707 return nb;
708 }
709
710
711 /*---------------------------------------------------*/
712 /* Return True iff data corruption is discovered.
713 Returns False if there is no problem.
714 */
715 static
716 Bool unRLE_obuf_to_output_SMALL ( DState* s )
717 {
718 UChar k1;
719
720 if (s->blockRandomised) {
721
722 while (True) {
723 /* try to finish existing run */
724 while (True) {
725 if (s->strm->avail_out == 0) return False;
726 if (s->state_out_len == 0) break;
727 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
728 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
729 s->state_out_len--;
730 s->strm->next_out++;
731 s->strm->avail_out--;
732 s->strm->total_out_lo32++;
733 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
734 }
735
736 /* can a new run be started? */
737 if (s->nblock_used == s->save_nblock+1) return False;
738
739 /* Only caused by corrupt data stream? */
740 if (s->nblock_used > s->save_nblock+1)
741 return True;
742
743 s->state_out_len = 1;
744 s->state_out_ch = s->k0;
745 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
746 k1 ^= BZ_RAND_MASK; s->nblock_used++;
747 if (s->nblock_used == s->save_nblock+1) continue;
748 if (k1 != s->k0) { s->k0 = k1; continue; };
749
750 s->state_out_len = 2;
751 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
752 k1 ^= BZ_RAND_MASK; s->nblock_used++;
753 if (s->nblock_used == s->save_nblock+1) continue;
754 if (k1 != s->k0) { s->k0 = k1; continue; };
755
756 s->state_out_len = 3;
757 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
758 k1 ^= BZ_RAND_MASK; s->nblock_used++;
759 if (s->nblock_used == s->save_nblock+1) continue;
760 if (k1 != s->k0) { s->k0 = k1; continue; };
761
762 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
763 k1 ^= BZ_RAND_MASK; s->nblock_used++;
764 s->state_out_len = ((Int32)k1) + 4;
765 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
766 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
767 }
768
769 } else {
770
771 while (True) {
772 /* try to finish existing run */
773 while (True) {
774 if (s->strm->avail_out == 0) return False;
775 if (s->state_out_len == 0) break;
776 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
777 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
778 s->state_out_len--;
779 s->strm->next_out++;
780 s->strm->avail_out--;
781 s->strm->total_out_lo32++;
782 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
783 }
784
785 /* can a new run be started? */
786 if (s->nblock_used == s->save_nblock+1) return False;
787
788 /* Only caused by corrupt data stream? */
789 if (s->nblock_used > s->save_nblock+1)
790 return True;
791
792 s->state_out_len = 1;
793 s->state_out_ch = s->k0;
794 BZ_GET_SMALL(k1); s->nblock_used++;
795 if (s->nblock_used == s->save_nblock+1) continue;
796 if (k1 != s->k0) { s->k0 = k1; continue; };
797
798 s->state_out_len = 2;
799 BZ_GET_SMALL(k1); s->nblock_used++;
800 if (s->nblock_used == s->save_nblock+1) continue;
801 if (k1 != s->k0) { s->k0 = k1; continue; };
802
803 s->state_out_len = 3;
804 BZ_GET_SMALL(k1); s->nblock_used++;
805 if (s->nblock_used == s->save_nblock+1) continue;
806 if (k1 != s->k0) { s->k0 = k1; continue; };
807
808 BZ_GET_SMALL(k1); s->nblock_used++;
809 s->state_out_len = ((Int32)k1) + 4;
810 BZ_GET_SMALL(s->k0); s->nblock_used++;
811 }
812
813 }
814 }
815
816
817 /*---------------------------------------------------*/
818 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
819 {
820 Bool corrupt;
821 DState* s;
822 if (strm == NULL) return BZ_PARAM_ERROR;
823 s = strm->state;
824 if (s == NULL) return BZ_PARAM_ERROR;
825 if (s->strm != strm) return BZ_PARAM_ERROR;
826
827 while (True) {
828 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
829 if (s->state == BZ_X_OUTPUT) {
830 #ifndef BZ_DECOMPRESS_ONLY
831 if (s->smallDecompress)
832 corrupt = unRLE_obuf_to_output_SMALL ( s ); else
833 corrupt = unRLE_obuf_to_output_FAST ( s );
834 if (corrupt) return BZ_DATA_ERROR;
835 #else
836 corrupt = unRLE_obuf_to_output_SMALL ( s );
837 if (corrupt) return BZ_DATA_ERROR;
838 #endif
839 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
840 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
841 if (s->verbosity >= 3)
842 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
843 s->calculatedBlockCRC );
844 if (s->verbosity >= 2) VPrintf0 ( "]" );
845 if (s->calculatedBlockCRC != s->storedBlockCRC)
846 return BZ_DATA_ERROR;
847 s->calculatedCombinedCRC
848 = (s->calculatedCombinedCRC << 1) |
849 (s->calculatedCombinedCRC >> 31);
850 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
851 s->state = BZ_X_BLKHDR_1;
852 } else {
853 return BZ_OK;
854 }
855 }
856 if (s->state >= BZ_X_MAGIC_1) {
857 Int32 r = BZ2_decompress ( s );
858 if (r == BZ_STREAM_END) {
859 if (s->verbosity >= 3)
860 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
861 s->storedCombinedCRC, s->calculatedCombinedCRC );
862 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
863 return BZ_DATA_ERROR;
864 return r;
865 }
866 if (s->state != BZ_X_OUTPUT) return r;
867 }
868 }
869
870 AssertH ( 0, 6001 );
871
872 return 0; /*NOTREACHED*/
873 }
874
875
876 /*---------------------------------------------------*/
877 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
878 {
879 DState* s;
880 if (strm == NULL) return BZ_PARAM_ERROR;
881 s = strm->state;
882 if (s == NULL) return BZ_PARAM_ERROR;
883 if (s->strm != strm) return BZ_PARAM_ERROR;
884
885 if (s->tt != NULL) BZFREE(s->tt);
886 if (s->ll16 != NULL) BZFREE(s->ll16);
887 if (s->ll4 != NULL) BZFREE(s->ll4);
888
889 BZFREE(strm->state);
890 strm->state = NULL;
891
892 return BZ_OK;
893 }
894
895
896 #ifndef BZ_NO_STDIO
897 /*---------------------------------------------------*/
898 /*--- File I/O stuff ---*/
899 /*---------------------------------------------------*/
900
901 #define BZ_SETERR(eee) \
902 { \
903 if (bzerror != NULL) *bzerror = eee; \
904 if (bzf != NULL) bzf->lastErr = eee; \
905 }
906
907 typedef
908 struct {
909 FILE* handle;
910 Char buf[BZ_MAX_UNUSED];
911 Int32 bufN;
912 Bool writing;
913 bz_stream strm;
914 Int32 lastErr;
915 Bool initialisedOk;
916 }
917 bzFile;
918
919
920 /*---------------------------------------------*/
921 static Bool myfeof ( FILE* f )
922 {
923 Int32 c = fgetc ( f );
924 if (c == EOF) return True;
925 ungetc ( c, f );
926 return False;
927 }
928
929
930 /*---------------------------------------------------*/
931 BZFILE* BZ_API(BZ2_bzWriteOpen)
932 ( int* bzerror,
933 FILE* f,
934 int blockSize100k,
935 int verbosity,
936 int workFactor )
937 {
938 Int32 ret;
939 bzFile* bzf = NULL;
940
941 BZ_SETERR(BZ_OK);
942
943 if (f == NULL ||
944 (blockSize100k < 1 || blockSize100k > 9) ||
945 (workFactor < 0 || workFactor > 250) ||
946 (verbosity < 0 || verbosity > 4))
947 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
948
949 if (ferror(f))
950 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
951
952 bzf = malloc ( sizeof(bzFile) );
953 if (bzf == NULL)
954 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
955
956 BZ_SETERR(BZ_OK);
957 bzf->initialisedOk = False;
958 bzf->bufN = 0;
959 bzf->handle = f;
960 bzf->writing = True;
961 bzf->strm.bzalloc = NULL;
962 bzf->strm.bzfree = NULL;
963 bzf->strm.opaque = NULL;
964
965 if (workFactor == 0) workFactor = 30;
966 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
967 verbosity, workFactor );
968 if (ret != BZ_OK)
969 { BZ_SETERR(ret); free(bzf); return NULL; };
970
971 bzf->strm.avail_in = 0;
972 bzf->initialisedOk = True;
973 return bzf;
974 }
975
976
977
978 /*---------------------------------------------------*/
979 void BZ_API(BZ2_bzWrite)
980 ( int* bzerror,
981 BZFILE* b,
982 void* buf,
983 int len )
984 {
985 Int32 n, n2, ret;
986 bzFile* bzf = (bzFile*)b;
987
988 BZ_SETERR(BZ_OK);
989 if (bzf == NULL || buf == NULL || len < 0)
990 { BZ_SETERR(BZ_PARAM_ERROR); return; };
991 if (!(bzf->writing))
992 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
993 if (ferror(bzf->handle))
994 { BZ_SETERR(BZ_IO_ERROR); return; };
995
996 if (len == 0)
997 { BZ_SETERR(BZ_OK); return; };
998
999 bzf->strm.avail_in = len;
1000 bzf->strm.next_in = buf;
1001
1002 while (True) {
1003 bzf->strm.avail_out = BZ_MAX_UNUSED;
1004 bzf->strm.next_out = bzf->buf;
1005 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
1006 if (ret != BZ_RUN_OK)
1007 { BZ_SETERR(ret); return; };
1008
1009 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1010 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1011 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1012 n, bzf->handle );
1013 if (n != n2 || ferror(bzf->handle))
1014 { BZ_SETERR(BZ_IO_ERROR); return; };
1015 }
1016
1017 if (bzf->strm.avail_in == 0)
1018 { BZ_SETERR(BZ_OK); return; };
1019 }
1020 }
1021
1022
1023 /*---------------------------------------------------*/
1024 void BZ_API(BZ2_bzWriteClose)
1025 ( int* bzerror,
1026 BZFILE* b,
1027 int abandon,
1028 unsigned int* nbytes_in,
1029 unsigned int* nbytes_out )
1030 {
1031 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1032 nbytes_in, NULL, nbytes_out, NULL );
1033 }
1034
1035
1036 void BZ_API(BZ2_bzWriteClose64)
1037 ( int* bzerror,
1038 BZFILE* b,
1039 int abandon,
1040 unsigned int* nbytes_in_lo32,
1041 unsigned int* nbytes_in_hi32,
1042 unsigned int* nbytes_out_lo32,
1043 unsigned int* nbytes_out_hi32 )
1044 {
1045 Int32 n, n2, ret;
1046 bzFile* bzf = (bzFile*)b;
1047
1048 if (bzf == NULL)
1049 { BZ_SETERR(BZ_OK); return; };
1050 if (!(bzf->writing))
1051 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1052 if (ferror(bzf->handle))
1053 { BZ_SETERR(BZ_IO_ERROR); return; };
1054
1055 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1056 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1057 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1058 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1059
1060 if ((!abandon) && bzf->lastErr == BZ_OK) {
1061 while (True) {
1062 bzf->strm.avail_out = BZ_MAX_UNUSED;
1063 bzf->strm.next_out = bzf->buf;
1064 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1065 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1066 { BZ_SETERR(ret); return; };
1067
1068 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1069 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1070 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1071 n, bzf->handle );
1072 if (n != n2 || ferror(bzf->handle))
1073 { BZ_SETERR(BZ_IO_ERROR); return; };
1074 }
1075
1076 if (ret == BZ_STREAM_END) break;
1077 }
1078 }
1079
1080 if ( !abandon && !ferror ( bzf->handle ) ) {
1081 fflush ( bzf->handle );
1082 if (ferror(bzf->handle))
1083 { BZ_SETERR(BZ_IO_ERROR); return; };
1084 }
1085
1086 if (nbytes_in_lo32 != NULL)
1087 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1088 if (nbytes_in_hi32 != NULL)
1089 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1090 if (nbytes_out_lo32 != NULL)
1091 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1092 if (nbytes_out_hi32 != NULL)
1093 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1094
1095 BZ_SETERR(BZ_OK);
1096 BZ2_bzCompressEnd ( &(bzf->strm) );
1097 free ( bzf );
1098 }
1099
1100
1101 /*---------------------------------------------------*/
1102 BZFILE* BZ_API(BZ2_bzReadOpen)
1103 ( int* bzerror,
1104 FILE* f,
1105 int verbosity,
1106 int small,
1107 void* unused,
1108 int nUnused )
1109 {
1110 bzFile* bzf = NULL;
1111 int ret;
1112
1113 BZ_SETERR(BZ_OK);
1114
1115 if (f == NULL ||
1116 (small != 0 && small != 1) ||
1117 (verbosity < 0 || verbosity > 4) ||
1118 (unused == NULL && nUnused != 0) ||
1119 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1120 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1121
1122 if (ferror(f))
1123 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1124
1125 bzf = malloc ( sizeof(bzFile) );
1126 if (bzf == NULL)
1127 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1128
1129 BZ_SETERR(BZ_OK);
1130
1131 bzf->initialisedOk = False;
1132 bzf->handle = f;
1133 bzf->bufN = 0;
1134 bzf->writing = False;
1135 bzf->strm.bzalloc = NULL;
1136 bzf->strm.bzfree = NULL;
1137 bzf->strm.opaque = NULL;
1138
1139 while (nUnused > 0) {
1140 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1141 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1142 nUnused--;
1143 }
1144
1145 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1146 if (ret != BZ_OK)
1147 { BZ_SETERR(ret); free(bzf); return NULL; };
1148
1149 bzf->strm.avail_in = bzf->bufN;
1150 bzf->strm.next_in = bzf->buf;
1151
1152 bzf->initialisedOk = True;
1153 return bzf;
1154 }
1155
1156
1157 /*---------------------------------------------------*/
1158 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1159 {
1160 bzFile* bzf = (bzFile*)b;
1161
1162 BZ_SETERR(BZ_OK);
1163 if (bzf == NULL)
1164 { BZ_SETERR(BZ_OK); return; };
1165
1166 if (bzf->writing)
1167 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1168
1169 if (bzf->initialisedOk)
1170 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1171 free ( bzf );
1172 }
1173
1174
1175 /*---------------------------------------------------*/
1176 int BZ_API(BZ2_bzRead)
1177 ( int* bzerror,
1178 BZFILE* b,
1179 void* buf,
1180 int len )
1181 {
1182 Int32 n, ret;
1183 bzFile* bzf = (bzFile*)b;
1184
1185 BZ_SETERR(BZ_OK);
1186
1187 if (bzf == NULL || buf == NULL || len < 0)
1188 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1189
1190 if (bzf->writing)
1191 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1192
1193 if (len == 0)
1194 { BZ_SETERR(BZ_OK); return 0; };
1195
1196 bzf->strm.avail_out = len;
1197 bzf->strm.next_out = buf;
1198
1199 while (True) {
1200
1201 if (ferror(bzf->handle))
1202 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1203
1204 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1205 n = fread ( bzf->buf, sizeof(UChar),
1206 BZ_MAX_UNUSED, bzf->handle );
1207 if (ferror(bzf->handle))
1208 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1209 bzf->bufN = n;
1210 bzf->strm.avail_in = bzf->bufN;
1211 bzf->strm.next_in = bzf->buf;
1212 }
1213
1214 ret = BZ2_bzDecompress ( &(bzf->strm) );
1215
1216 if (ret != BZ_OK && ret != BZ_STREAM_END)
1217 { BZ_SETERR(ret); return 0; };
1218
1219 if (ret == BZ_OK && myfeof(bzf->handle) &&
1220 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1221 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1222
1223 if (ret == BZ_STREAM_END)
1224 { BZ_SETERR(BZ_STREAM_END);
1225 return len - bzf->strm.avail_out; };
1226 if (bzf->strm.avail_out == 0)
1227 { BZ_SETERR(BZ_OK); return len; };
1228
1229 }
1230
1231 return 0; /*not reached*/
1232 }
1233
1234
1235 /*---------------------------------------------------*/
1236 void BZ_API(BZ2_bzReadGetUnused)
1237 ( int* bzerror,
1238 BZFILE* b,
1239 void** unused,
1240 int* nUnused )
1241 {
1242 bzFile* bzf = (bzFile*)b;
1243 if (bzf == NULL)
1244 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1245 if (bzf->lastErr != BZ_STREAM_END)
1246 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1247 if (unused == NULL || nUnused == NULL)
1248 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1249
1250 BZ_SETERR(BZ_OK);
1251 *nUnused = bzf->strm.avail_in;
1252 *unused = bzf->strm.next_in;
1253 }
1254 #endif
1255
1256 #ifndef BZ_DECOMPRESS_ONLY
1257
1258 /*---------------------------------------------------*/
1259 /*--- Misc convenience stuff ---*/
1260 /*---------------------------------------------------*/
1261
1262 /*---------------------------------------------------*/
1263 int BZ_API(BZ2_bzBuffToBuffCompress)
1264 ( char* dest,
1265 unsigned int* destLen,
1266 char* source,
1267 unsigned int sourceLen,
1268 int blockSize100k,
1269 int verbosity,
1270 int workFactor )
1271 {
1272 bz_stream strm;
1273 int ret;
1274
1275 if (dest == NULL || destLen == NULL ||
1276 source == NULL ||
1277 blockSize100k < 1 || blockSize100k > 9 ||
1278 verbosity < 0 || verbosity > 4 ||
1279 workFactor < 0 || workFactor > 250)
1280 return BZ_PARAM_ERROR;
1281
1282 if (workFactor == 0) workFactor = 30;
1283 strm.bzalloc = NULL;
1284 strm.bzfree = NULL;
1285 strm.opaque = NULL;
1286 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1287 verbosity, workFactor );
1288 if (ret != BZ_OK) return ret;
1289
1290 strm.next_in = source;
1291 strm.next_out = dest;
1292 strm.avail_in = sourceLen;
1293 strm.avail_out = *destLen;
1294
1295 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1296 if (ret == BZ_FINISH_OK) goto output_overflow;
1297 if (ret != BZ_STREAM_END) goto errhandler;
1298
1299 /* normal termination */
1300 *destLen -= strm.avail_out;
1301 BZ2_bzCompressEnd ( &strm );
1302 return BZ_OK;
1303
1304 output_overflow:
1305 BZ2_bzCompressEnd ( &strm );
1306 return BZ_OUTBUFF_FULL;
1307
1308 errhandler:
1309 BZ2_bzCompressEnd ( &strm );
1310 return ret;
1311 }
1312
1313 #endif // BZ_DECOMPRESS_0NLY
1314
1315 /*---------------------------------------------------*/
1316 int BZ_API(BZ2_bzBuffToBuffDecompress)
1317 ( char* dest,
1318 unsigned int* destLen,
1319 char* source,
1320 unsigned int sourceLen,
1321 int small,
1322 int verbosity )
1323 {
1324 bz_stream strm;
1325 int ret;
1326
1327 if (dest == NULL || destLen == NULL ||
1328 source == NULL ||
1329 (small != 0 && small != 1) ||
1330 verbosity < 0 || verbosity > 4)
1331 return BZ_PARAM_ERROR;
1332
1333 strm.bzalloc = NULL;
1334 strm.bzfree = NULL;
1335 strm.opaque = NULL;
1336 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1337 if (ret != BZ_OK) return ret;
1338
1339 strm.next_in = source;
1340 strm.next_out = dest;
1341 strm.avail_in = sourceLen;
1342 strm.avail_out = *destLen;
1343
1344 ret = BZ2_bzDecompress ( &strm );
1345 if (ret == BZ_OK) goto output_overflow_or_eof;
1346 if (ret != BZ_STREAM_END) goto errhandler;
1347
1348 /* normal termination */
1349 *destLen -= strm.avail_out;
1350 BZ2_bzDecompressEnd ( &strm );
1351 return BZ_OK;
1352
1353 output_overflow_or_eof:
1354 if (strm.avail_out > 0) {
1355 BZ2_bzDecompressEnd ( &strm );
1356 return BZ_UNEXPECTED_EOF;
1357 } else {
1358 BZ2_bzDecompressEnd ( &strm );
1359 return BZ_OUTBUFF_FULL;
1360 };
1361
1362 errhandler:
1363 BZ2_bzDecompressEnd ( &strm );
1364 return ret;
1365 }
1366
1367
1368 /*---------------------------------------------------*/
1369 /*--
1370 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1371 to support better zlib compatibility.
1372 This code is not _officially_ part of libbzip2 (yet);
1373 I haven't tested it, documented it, or considered the
1374 threading-safeness of it.
1375 If this code breaks, please contact both Yoshioka and me.
1376 --*/
1377 /*---------------------------------------------------*/
1378
1379 /*---------------------------------------------------*/
1380 /*--
1381 return version like "0.9.5d, 4-Sept-1999".
1382 --*/
1383 const char * BZ_API(BZ2_bzlibVersion)(void)
1384 {
1385 return BZ_VERSION;
1386 }
1387
1388
1389 #ifndef BZ_NO_STDIO
1390 /*---------------------------------------------------*/
1391
1392 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1393 # include <fcntl.h>
1394 # include <io.h>
1395 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1396 #else
1397 # define SET_BINARY_MODE(file)
1398 #endif
1399 static
1400 BZFILE * bzopen_or_bzdopen
1401 ( const char *path, /* no use when bzdopen */
1402 int fd, /* no use when bzdopen */
1403 const char *mode,
1404 int open_mode) /* bzopen: 0, bzdopen:1 */
1405 {
1406 int bzerr;
1407 char unused[BZ_MAX_UNUSED];
1408 int blockSize100k = 9;
1409 int writing = 0;
1410 char mode2[10] = "";
1411 FILE *fp = NULL;
1412 BZFILE *bzfp = NULL;
1413 int verbosity = 0;
1414 int workFactor = 30;
1415 int smallMode = 0;
1416 int nUnused = 0;
1417
1418 if (mode == NULL) return NULL;
1419 while (*mode) {
1420 switch (*mode) {
1421 case 'r':
1422 writing = 0; break;
1423 case 'w':
1424 writing = 1; break;
1425 case 's':
1426 smallMode = 1; break;
1427 default:
1428 if (isdigit((int)(*mode))) {
1429 blockSize100k = *mode-BZ_HDR_0;
1430 }
1431 }
1432 mode++;
1433 }
1434 strcat(mode2, writing ? "w" : "r" );
1435 strcat(mode2,"b"); /* binary mode */
1436
1437 if (open_mode==0) {
1438 if (path==NULL || strcmp(path,"")==0) {
1439 fp = (writing ? stdout : stdin);
1440 SET_BINARY_MODE(fp);
1441 } else {
1442 fp = fopen(path,mode2);
1443 }
1444 } else {
1445 #ifdef BZ_STRICT_ANSI
1446 fp = NULL;
1447 #else
1448 fp = fdopen(fd,mode2);
1449 #endif
1450 }
1451 if (fp == NULL) return NULL;
1452
1453 if (writing) {
1454 /* Guard against total chaos and anarchy -- JRS */
1455 if (blockSize100k < 1) blockSize100k = 1;
1456 if (blockSize100k > 9) blockSize100k = 9;
1457 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1458 verbosity,workFactor);
1459 } else {
1460 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1461 unused,nUnused);
1462 }
1463 if (bzfp == NULL) {
1464 if (fp != stdin && fp != stdout) fclose(fp);
1465 return NULL;
1466 }
1467 return bzfp;
1468 }
1469
1470
1471 /*---------------------------------------------------*/
1472 /*--
1473 open file for read or write.
1474 ex) bzopen("file","w9")
1475 case path="" or NULL => use stdin or stdout.
1476 --*/
1477 BZFILE * BZ_API(BZ2_bzopen)
1478 ( const char *path,
1479 const char *mode )
1480 {
1481 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1482 }
1483
1484
1485 /*---------------------------------------------------*/
1486 BZFILE * BZ_API(BZ2_bzdopen)
1487 ( int fd,
1488 const char *mode )
1489 {
1490 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1491 }
1492
1493
1494 /*---------------------------------------------------*/
1495 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1496 {
1497 int bzerr, nread;
1498 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1499 nread = BZ2_bzRead(&bzerr,b,buf,len);
1500 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1501 return nread;
1502 } else {
1503 return -1;
1504 }
1505 }
1506
1507
1508 /*---------------------------------------------------*/
1509 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1510 {
1511 int bzerr;
1512
1513 BZ2_bzWrite(&bzerr,b,buf,len);
1514 if(bzerr == BZ_OK){
1515 return len;
1516 }else{
1517 return -1;
1518 }
1519 }
1520
1521
1522 /*---------------------------------------------------*/
1523 int BZ_API(BZ2_bzflush) (BZFILE *b)
1524 {
1525 /* do nothing now... */
1526 return 0;
1527 }
1528
1529
1530 /*---------------------------------------------------*/
1531 void BZ_API(BZ2_bzclose) (BZFILE* b)
1532 {
1533 int bzerr;
1534 FILE *fp;
1535
1536 if (b==NULL) {return;}
1537 fp = ((bzFile *)b)->handle;
1538 if(((bzFile*)b)->writing){
1539 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1540 if(bzerr != BZ_OK){
1541 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1542 }
1543 }else{
1544 BZ2_bzReadClose(&bzerr,b);
1545 }
1546 if(fp!=stdin && fp!=stdout){
1547 fclose(fp);
1548 }
1549 }
1550
1551
1552 /*---------------------------------------------------*/
1553 /*--
1554 return last error code
1555 --*/
1556 static const char *bzerrorstrings[] = {
1557 "OK"
1558 ,"SEQUENCE_ERROR"
1559 ,"PARAM_ERROR"
1560 ,"MEM_ERROR"
1561 ,"DATA_ERROR"
1562 ,"DATA_ERROR_MAGIC"
1563 ,"IO_ERROR"
1564 ,"UNEXPECTED_EOF"
1565 ,"OUTBUFF_FULL"
1566 ,"CONFIG_ERROR"
1567 ,"???" /* for future */
1568 ,"???" /* for future */
1569 ,"???" /* for future */
1570 ,"???" /* for future */
1571 ,"???" /* for future */
1572 ,"???" /* for future */
1573 };
1574
1575
1576 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1577 {
1578 int err = ((bzFile *)b)->lastErr;
1579
1580 if(err>0) err = 0;
1581 *errnum = err;
1582 return bzerrorstrings[err*-1];
1583 }
1584 #endif
1585
1586
1587 /*-------------------------------------------------------------*/
1588 /*--- end bzlib.c ---*/
1589 /*-------------------------------------------------------------*/