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