/[pcsx2_0.9.7]/trunk/3rdparty/bzip2/bzlib.c
ViewVC logotype

Contents of /trunk/3rdparty/bzip2/bzlib.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.22