ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitCommon/OptIO/src/bzlib.c
Revision: 1.1
Committed: Tue Feb 24 11:56:42 2009 UTC (16 years, 2 months ago) by loizides
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_032, Mit_031, Mit_025c_branch2, Mit_025c_branch1, Mit_030, Mit_029c, Mit_030_pre1, Mit_029a, Mit_029, Mit_029_pre1, Mit_028a, Mit_025c_branch0, Mit_028, Mit_027a, Mit_027, Mit_026, Mit_025e, Mit_025d, Mit_025c, Mit_025b, Mit_025a, Mit_025, Mit_025pre2, Mit_024b, Mit_025pre1, Mit_024a, Mit_024, Mit_023, Mit_022a, Mit_022, Mit_020d, TMit_020d, Mit_020c, Mit_021, Mit_021pre2, Mit_021pre1, Mit_020b, Mit_020a, Mit_020, Mit_020pre1, Mit_018, Mit_017, Mit_017pre3, Mit_017pre2, Mit_017pre1, V07-05-00, Mit_016, Mit_015b, Mit_015a, Mit_015, Mit_014e, Mit_014d, Mit_014c, Mit_014b, ConvRejection-10-06-09, Mit_014a, Mit_014, Mit_014pre3, Mit_014pre2, Mit_014pre1, Mit_013d, Mit_013c, Mit_013b, Mit_013a, Mit_013, Mit_013pre1, Mit_012i, Mit_012g, Mit_012f, Mit_012e, Mit_012d, Mit_012c, Mit_012b, Mit_012a, Mit_012, Mit_011a, Mit_011, Mit_010a, Mit_010, Mit_009c, Mit_009b, Mit_009a, Mit_009, Mit_008, Mit_008pre2, Mit_008pre1, HEAD
Branch point for: Mit_025c_branch
Log Message:
Preload lib for compression improvements.

File Contents

# User Rev Content
1 loizides 1.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.5 of 10 December 2007
12     Copyright (C) 1996-2007 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, 10 December 2007.\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     Int32 ro_blockSize100k = s->blockSize100k;
602     /* end restore */
603    
604     UInt32 avail_out_INIT = cs_avail_out;
605     Int32 s_save_nblockPP = s->save_nblock+1;
606     unsigned int total_out_lo32_old;
607    
608     while (True) {
609    
610     /* try to finish existing run */
611     if (c_state_out_len > 0) {
612     while (True) {
613     if (cs_avail_out == 0) goto return_notr;
614     if (c_state_out_len == 1) break;
615     *( (UChar*)(cs_next_out) ) = c_state_out_ch;
616     BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
617     c_state_out_len--;
618     cs_next_out++;
619     cs_avail_out--;
620     }
621     s_state_out_len_eq_one:
622     {
623     if (cs_avail_out == 0) {
624     c_state_out_len = 1; goto return_notr;
625     };
626     *( (UChar*)(cs_next_out) ) = c_state_out_ch;
627     BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
628     cs_next_out++;
629     cs_avail_out--;
630     }
631     }
632     /* Only caused by corrupt data stream? */
633     if (c_nblock_used > s_save_nblockPP)
634     return True;
635    
636     /* can a new run be started? */
637     if (c_nblock_used == s_save_nblockPP) {
638     c_state_out_len = 0; goto return_notr;
639     };
640     c_state_out_ch = c_k0;
641     BZ_GET_FAST_C(k1); c_nblock_used++;
642     if (k1 != c_k0) {
643     c_k0 = k1; goto s_state_out_len_eq_one;
644     };
645     if (c_nblock_used == s_save_nblockPP)
646     goto s_state_out_len_eq_one;
647    
648     c_state_out_len = 2;
649     BZ_GET_FAST_C(k1); c_nblock_used++;
650     if (c_nblock_used == s_save_nblockPP) continue;
651     if (k1 != c_k0) { c_k0 = k1; continue; };
652    
653     c_state_out_len = 3;
654     BZ_GET_FAST_C(k1); c_nblock_used++;
655     if (c_nblock_used == s_save_nblockPP) continue;
656     if (k1 != c_k0) { c_k0 = k1; continue; };
657    
658     BZ_GET_FAST_C(k1); c_nblock_used++;
659     c_state_out_len = ((Int32)k1) + 4;
660     BZ_GET_FAST_C(c_k0); c_nblock_used++;
661     }
662    
663     return_notr:
664     total_out_lo32_old = s->strm->total_out_lo32;
665     s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
666     if (s->strm->total_out_lo32 < total_out_lo32_old)
667     s->strm->total_out_hi32++;
668    
669     /* save */
670     s->calculatedBlockCRC = c_calculatedBlockCRC;
671     s->state_out_ch = c_state_out_ch;
672     s->state_out_len = c_state_out_len;
673     s->nblock_used = c_nblock_used;
674     s->k0 = c_k0;
675     s->tt = c_tt;
676     s->tPos = c_tPos;
677     s->strm->next_out = cs_next_out;
678     s->strm->avail_out = cs_avail_out;
679     /* end save */
680     }
681     return False;
682     }
683    
684    
685    
686     /*---------------------------------------------------*/
687     __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
688     {
689     Int32 nb, na, mid;
690     nb = 0;
691     na = 256;
692     do {
693     mid = (nb + na) >> 1;
694     if (indx >= cftab[mid]) nb = mid; else na = mid;
695     }
696     while (na - nb != 1);
697     return nb;
698     }
699    
700    
701     /*---------------------------------------------------*/
702     /* Return True iff data corruption is discovered.
703     Returns False if there is no problem.
704     */
705     static
706     Bool unRLE_obuf_to_output_SMALL ( DState* s )
707     {
708     UChar k1;
709    
710     if (s->blockRandomised) {
711    
712     while (True) {
713     /* try to finish existing run */
714     while (True) {
715     if (s->strm->avail_out == 0) return False;
716     if (s->state_out_len == 0) break;
717     *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
718     BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
719     s->state_out_len--;
720     s->strm->next_out++;
721     s->strm->avail_out--;
722     s->strm->total_out_lo32++;
723     if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
724     }
725    
726     /* can a new run be started? */
727     if (s->nblock_used == s->save_nblock+1) return False;
728    
729     /* Only caused by corrupt data stream? */
730     if (s->nblock_used > s->save_nblock+1)
731     return True;
732    
733     s->state_out_len = 1;
734     s->state_out_ch = s->k0;
735     BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
736     k1 ^= BZ_RAND_MASK; s->nblock_used++;
737     if (s->nblock_used == s->save_nblock+1) continue;
738     if (k1 != s->k0) { s->k0 = k1; continue; };
739    
740     s->state_out_len = 2;
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 = 3;
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     BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
753     k1 ^= BZ_RAND_MASK; s->nblock_used++;
754     s->state_out_len = ((Int32)k1) + 4;
755     BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
756     s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
757     }
758    
759     } else {
760    
761     while (True) {
762     /* try to finish existing run */
763     while (True) {
764     if (s->strm->avail_out == 0) return False;
765     if (s->state_out_len == 0) break;
766     *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
767     BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
768     s->state_out_len--;
769     s->strm->next_out++;
770     s->strm->avail_out--;
771     s->strm->total_out_lo32++;
772     if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
773     }
774    
775     /* can a new run be started? */
776     if (s->nblock_used == s->save_nblock+1) return False;
777    
778     /* Only caused by corrupt data stream? */
779     if (s->nblock_used > s->save_nblock+1)
780     return True;
781    
782     s->state_out_len = 1;
783     s->state_out_ch = s->k0;
784     BZ_GET_SMALL(k1); s->nblock_used++;
785     if (s->nblock_used == s->save_nblock+1) continue;
786     if (k1 != s->k0) { s->k0 = k1; continue; };
787    
788     s->state_out_len = 2;
789     BZ_GET_SMALL(k1); s->nblock_used++;
790     if (s->nblock_used == s->save_nblock+1) continue;
791     if (k1 != s->k0) { s->k0 = k1; continue; };
792    
793     s->state_out_len = 3;
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     BZ_GET_SMALL(k1); s->nblock_used++;
799     s->state_out_len = ((Int32)k1) + 4;
800     BZ_GET_SMALL(s->k0); s->nblock_used++;
801     }
802    
803     }
804     }
805    
806    
807     /*---------------------------------------------------*/
808     int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
809     {
810     Bool corrupt;
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     if (s->smallDecompress)
821     corrupt = unRLE_obuf_to_output_SMALL ( s ); else
822     corrupt = unRLE_obuf_to_output_FAST ( s );
823     if (corrupt) return BZ_DATA_ERROR;
824     if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
825     BZ_FINALISE_CRC ( s->calculatedBlockCRC );
826     if (s->verbosity >= 3)
827     VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
828     s->calculatedBlockCRC );
829     if (s->verbosity >= 2) VPrintf0 ( "]" );
830     if (s->calculatedBlockCRC != s->storedBlockCRC)
831     return BZ_DATA_ERROR;
832     s->calculatedCombinedCRC
833     = (s->calculatedCombinedCRC << 1) |
834     (s->calculatedCombinedCRC >> 31);
835     s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
836     s->state = BZ_X_BLKHDR_1;
837     } else {
838     return BZ_OK;
839     }
840     }
841     if (s->state >= BZ_X_MAGIC_1) {
842     Int32 r = BZ2_decompress ( s );
843     if (r == BZ_STREAM_END) {
844     if (s->verbosity >= 3)
845     VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
846     s->storedCombinedCRC, s->calculatedCombinedCRC );
847     if (s->calculatedCombinedCRC != s->storedCombinedCRC)
848     return BZ_DATA_ERROR;
849     return r;
850     }
851     if (s->state != BZ_X_OUTPUT) return r;
852     }
853     }
854    
855     AssertH ( 0, 6001 );
856    
857     return 0; /*NOTREACHED*/
858     }
859    
860    
861     /*---------------------------------------------------*/
862     int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
863     {
864     DState* s;
865     if (strm == NULL) return BZ_PARAM_ERROR;
866     s = strm->state;
867     if (s == NULL) return BZ_PARAM_ERROR;
868     if (s->strm != strm) return BZ_PARAM_ERROR;
869    
870     if (s->tt != NULL) BZFREE(s->tt);
871     if (s->ll16 != NULL) BZFREE(s->ll16);
872     if (s->ll4 != NULL) BZFREE(s->ll4);
873    
874     BZFREE(strm->state);
875     strm->state = NULL;
876    
877     return BZ_OK;
878     }
879    
880    
881     #ifndef BZ_NO_STDIO
882     /*---------------------------------------------------*/
883     /*--- File I/O stuff ---*/
884     /*---------------------------------------------------*/
885    
886     #define BZ_SETERR(eee) \
887     { \
888     if (bzerror != NULL) *bzerror = eee; \
889     if (bzf != NULL) bzf->lastErr = eee; \
890     }
891    
892     typedef
893     struct {
894     FILE* handle;
895     Char buf[BZ_MAX_UNUSED];
896     Int32 bufN;
897     Bool writing;
898     bz_stream strm;
899     Int32 lastErr;
900     Bool initialisedOk;
901     }
902     bzFile;
903    
904    
905     /*---------------------------------------------*/
906     static Bool myfeof ( FILE* f )
907     {
908     Int32 c = fgetc ( f );
909     if (c == EOF) return True;
910     ungetc ( c, f );
911     return False;
912     }
913    
914    
915     /*---------------------------------------------------*/
916     BZFILE* BZ_API(BZ2_bzWriteOpen)
917     ( int* bzerror,
918     FILE* f,
919     int blockSize100k,
920     int verbosity,
921     int workFactor )
922     {
923     Int32 ret;
924     bzFile* bzf = NULL;
925    
926     BZ_SETERR(BZ_OK);
927    
928     if (f == NULL ||
929     (blockSize100k < 1 || blockSize100k > 9) ||
930     (workFactor < 0 || workFactor > 250) ||
931     (verbosity < 0 || verbosity > 4))
932     { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
933    
934     if (ferror(f))
935     { BZ_SETERR(BZ_IO_ERROR); return NULL; };
936    
937     bzf = malloc ( sizeof(bzFile) );
938     if (bzf == NULL)
939     { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
940    
941     BZ_SETERR(BZ_OK);
942     bzf->initialisedOk = False;
943     bzf->bufN = 0;
944     bzf->handle = f;
945     bzf->writing = True;
946     bzf->strm.bzalloc = NULL;
947     bzf->strm.bzfree = NULL;
948     bzf->strm.opaque = NULL;
949    
950     if (workFactor == 0) workFactor = 30;
951     ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
952     verbosity, workFactor );
953     if (ret != BZ_OK)
954     { BZ_SETERR(ret); free(bzf); return NULL; };
955    
956     bzf->strm.avail_in = 0;
957     bzf->initialisedOk = True;
958     return bzf;
959     }
960    
961    
962    
963     /*---------------------------------------------------*/
964     void BZ_API(BZ2_bzWrite)
965     ( int* bzerror,
966     BZFILE* b,
967     void* buf,
968     int len )
969     {
970     Int32 n, n2, ret;
971     bzFile* bzf = (bzFile*)b;
972    
973     BZ_SETERR(BZ_OK);
974     if (bzf == NULL || buf == NULL || len < 0)
975     { BZ_SETERR(BZ_PARAM_ERROR); return; };
976     if (!(bzf->writing))
977     { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
978     if (ferror(bzf->handle))
979     { BZ_SETERR(BZ_IO_ERROR); return; };
980    
981     if (len == 0)
982     { BZ_SETERR(BZ_OK); return; };
983    
984     bzf->strm.avail_in = len;
985     bzf->strm.next_in = buf;
986    
987     while (True) {
988     bzf->strm.avail_out = BZ_MAX_UNUSED;
989     bzf->strm.next_out = bzf->buf;
990     ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
991     if (ret != BZ_RUN_OK)
992     { BZ_SETERR(ret); return; };
993    
994     if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
995     n = BZ_MAX_UNUSED - bzf->strm.avail_out;
996     n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
997     n, bzf->handle );
998     if (n != n2 || ferror(bzf->handle))
999     { BZ_SETERR(BZ_IO_ERROR); return; };
1000     }
1001    
1002     if (bzf->strm.avail_in == 0)
1003     { BZ_SETERR(BZ_OK); return; };
1004     }
1005     }
1006    
1007    
1008     /*---------------------------------------------------*/
1009     void BZ_API(BZ2_bzWriteClose)
1010     ( int* bzerror,
1011     BZFILE* b,
1012     int abandon,
1013     unsigned int* nbytes_in,
1014     unsigned int* nbytes_out )
1015     {
1016     BZ2_bzWriteClose64 ( bzerror, b, abandon,
1017     nbytes_in, NULL, nbytes_out, NULL );
1018     }
1019    
1020    
1021     void BZ_API(BZ2_bzWriteClose64)
1022     ( int* bzerror,
1023     BZFILE* b,
1024     int abandon,
1025     unsigned int* nbytes_in_lo32,
1026     unsigned int* nbytes_in_hi32,
1027     unsigned int* nbytes_out_lo32,
1028     unsigned int* nbytes_out_hi32 )
1029     {
1030     Int32 n, n2, ret;
1031     bzFile* bzf = (bzFile*)b;
1032    
1033     if (bzf == NULL)
1034     { BZ_SETERR(BZ_OK); return; };
1035     if (!(bzf->writing))
1036     { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1037     if (ferror(bzf->handle))
1038     { BZ_SETERR(BZ_IO_ERROR); return; };
1039    
1040     if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1041     if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1042     if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1043     if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1044    
1045     if ((!abandon) && bzf->lastErr == BZ_OK) {
1046     while (True) {
1047     bzf->strm.avail_out = BZ_MAX_UNUSED;
1048     bzf->strm.next_out = bzf->buf;
1049     ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1050     if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1051     { BZ_SETERR(ret); return; };
1052    
1053     if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1054     n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1055     n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1056     n, bzf->handle );
1057     if (n != n2 || ferror(bzf->handle))
1058     { BZ_SETERR(BZ_IO_ERROR); return; };
1059     }
1060    
1061     if (ret == BZ_STREAM_END) break;
1062     }
1063     }
1064    
1065     if ( !abandon && !ferror ( bzf->handle ) ) {
1066     fflush ( bzf->handle );
1067     if (ferror(bzf->handle))
1068     { BZ_SETERR(BZ_IO_ERROR); return; };
1069     }
1070    
1071     if (nbytes_in_lo32 != NULL)
1072     *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1073     if (nbytes_in_hi32 != NULL)
1074     *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1075     if (nbytes_out_lo32 != NULL)
1076     *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1077     if (nbytes_out_hi32 != NULL)
1078     *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1079    
1080     BZ_SETERR(BZ_OK);
1081     BZ2_bzCompressEnd ( &(bzf->strm) );
1082     free ( bzf );
1083     }
1084    
1085    
1086     /*---------------------------------------------------*/
1087     BZFILE* BZ_API(BZ2_bzReadOpen)
1088     ( int* bzerror,
1089     FILE* f,
1090     int verbosity,
1091     int small,
1092     void* unused,
1093     int nUnused )
1094     {
1095     bzFile* bzf = NULL;
1096     int ret;
1097    
1098     BZ_SETERR(BZ_OK);
1099    
1100     if (f == NULL ||
1101     (small != 0 && small != 1) ||
1102     (verbosity < 0 || verbosity > 4) ||
1103     (unused == NULL && nUnused != 0) ||
1104     (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1105     { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1106    
1107     if (ferror(f))
1108     { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1109    
1110     bzf = malloc ( sizeof(bzFile) );
1111     if (bzf == NULL)
1112     { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1113    
1114     BZ_SETERR(BZ_OK);
1115    
1116     bzf->initialisedOk = False;
1117     bzf->handle = f;
1118     bzf->bufN = 0;
1119     bzf->writing = False;
1120     bzf->strm.bzalloc = NULL;
1121     bzf->strm.bzfree = NULL;
1122     bzf->strm.opaque = NULL;
1123    
1124     while (nUnused > 0) {
1125     bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1126     unused = ((void*)( 1 + ((UChar*)(unused)) ));
1127     nUnused--;
1128     }
1129    
1130     ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1131     if (ret != BZ_OK)
1132     { BZ_SETERR(ret); free(bzf); return NULL; };
1133    
1134     bzf->strm.avail_in = bzf->bufN;
1135     bzf->strm.next_in = bzf->buf;
1136    
1137     bzf->initialisedOk = True;
1138     return bzf;
1139     }
1140    
1141    
1142     /*---------------------------------------------------*/
1143     void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1144     {
1145     bzFile* bzf = (bzFile*)b;
1146    
1147     BZ_SETERR(BZ_OK);
1148     if (bzf == NULL)
1149     { BZ_SETERR(BZ_OK); return; };
1150    
1151     if (bzf->writing)
1152     { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1153    
1154     if (bzf->initialisedOk)
1155     (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1156     free ( bzf );
1157     }
1158    
1159    
1160     /*---------------------------------------------------*/
1161     int BZ_API(BZ2_bzRead)
1162     ( int* bzerror,
1163     BZFILE* b,
1164     void* buf,
1165     int len )
1166     {
1167     Int32 n, ret;
1168     bzFile* bzf = (bzFile*)b;
1169    
1170     BZ_SETERR(BZ_OK);
1171    
1172     if (bzf == NULL || buf == NULL || len < 0)
1173     { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1174    
1175     if (bzf->writing)
1176     { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1177    
1178     if (len == 0)
1179     { BZ_SETERR(BZ_OK); return 0; };
1180    
1181     bzf->strm.avail_out = len;
1182     bzf->strm.next_out = buf;
1183    
1184     while (True) {
1185    
1186     if (ferror(bzf->handle))
1187     { BZ_SETERR(BZ_IO_ERROR); return 0; };
1188    
1189     if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1190     n = fread ( bzf->buf, sizeof(UChar),
1191     BZ_MAX_UNUSED, bzf->handle );
1192     if (ferror(bzf->handle))
1193     { BZ_SETERR(BZ_IO_ERROR); return 0; };
1194     bzf->bufN = n;
1195     bzf->strm.avail_in = bzf->bufN;
1196     bzf->strm.next_in = bzf->buf;
1197     }
1198    
1199     ret = BZ2_bzDecompress ( &(bzf->strm) );
1200    
1201     if (ret != BZ_OK && ret != BZ_STREAM_END)
1202     { BZ_SETERR(ret); return 0; };
1203    
1204     if (ret == BZ_OK && myfeof(bzf->handle) &&
1205     bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1206     { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1207    
1208     if (ret == BZ_STREAM_END)
1209     { BZ_SETERR(BZ_STREAM_END);
1210     return len - bzf->strm.avail_out; };
1211     if (bzf->strm.avail_out == 0)
1212     { BZ_SETERR(BZ_OK); return len; };
1213    
1214     }
1215    
1216     return 0; /*not reached*/
1217     }
1218    
1219    
1220     /*---------------------------------------------------*/
1221     void BZ_API(BZ2_bzReadGetUnused)
1222     ( int* bzerror,
1223     BZFILE* b,
1224     void** unused,
1225     int* nUnused )
1226     {
1227     bzFile* bzf = (bzFile*)b;
1228     if (bzf == NULL)
1229     { BZ_SETERR(BZ_PARAM_ERROR); return; };
1230     if (bzf->lastErr != BZ_STREAM_END)
1231     { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1232     if (unused == NULL || nUnused == NULL)
1233     { BZ_SETERR(BZ_PARAM_ERROR); return; };
1234    
1235     BZ_SETERR(BZ_OK);
1236     *nUnused = bzf->strm.avail_in;
1237     *unused = bzf->strm.next_in;
1238     }
1239     #endif
1240    
1241    
1242     /*---------------------------------------------------*/
1243     /*--- Misc convenience stuff ---*/
1244     /*---------------------------------------------------*/
1245    
1246     /*---------------------------------------------------*/
1247     int BZ_API(BZ2_bzBuffToBuffCompress)
1248     ( char* dest,
1249     unsigned int* destLen,
1250     char* source,
1251     unsigned int sourceLen,
1252     int blockSize100k,
1253     int verbosity,
1254     int workFactor )
1255     {
1256     bz_stream strm;
1257     int ret;
1258    
1259     if (dest == NULL || destLen == NULL ||
1260     source == NULL ||
1261     blockSize100k < 1 || blockSize100k > 9 ||
1262     verbosity < 0 || verbosity > 4 ||
1263     workFactor < 0 || workFactor > 250)
1264     return BZ_PARAM_ERROR;
1265    
1266     if (workFactor == 0) workFactor = 30;
1267     strm.bzalloc = NULL;
1268     strm.bzfree = NULL;
1269     strm.opaque = NULL;
1270     ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1271     verbosity, workFactor );
1272     if (ret != BZ_OK) return ret;
1273    
1274     strm.next_in = source;
1275     strm.next_out = dest;
1276     strm.avail_in = sourceLen;
1277     strm.avail_out = *destLen;
1278    
1279     ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1280     if (ret == BZ_FINISH_OK) goto output_overflow;
1281     if (ret != BZ_STREAM_END) goto errhandler;
1282    
1283     /* normal termination */
1284     *destLen -= strm.avail_out;
1285     BZ2_bzCompressEnd ( &strm );
1286     return BZ_OK;
1287    
1288     output_overflow:
1289     BZ2_bzCompressEnd ( &strm );
1290     return BZ_OUTBUFF_FULL;
1291    
1292     errhandler:
1293     BZ2_bzCompressEnd ( &strm );
1294     return ret;
1295     }
1296    
1297    
1298     /*---------------------------------------------------*/
1299     int BZ_API(BZ2_bzBuffToBuffDecompress)
1300     ( char* dest,
1301     unsigned int* destLen,
1302     char* source,
1303     unsigned int sourceLen,
1304     int small,
1305     int verbosity )
1306     {
1307     bz_stream strm;
1308     int ret;
1309    
1310     if (dest == NULL || destLen == NULL ||
1311     source == NULL ||
1312     (small != 0 && small != 1) ||
1313     verbosity < 0 || verbosity > 4)
1314     return BZ_PARAM_ERROR;
1315    
1316     strm.bzalloc = NULL;
1317     strm.bzfree = NULL;
1318     strm.opaque = NULL;
1319     ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1320     if (ret != BZ_OK) return ret;
1321    
1322     strm.next_in = source;
1323     strm.next_out = dest;
1324     strm.avail_in = sourceLen;
1325     strm.avail_out = *destLen;
1326    
1327     ret = BZ2_bzDecompress ( &strm );
1328     if (ret == BZ_OK) goto output_overflow_or_eof;
1329     if (ret != BZ_STREAM_END) goto errhandler;
1330    
1331     /* normal termination */
1332     *destLen -= strm.avail_out;
1333     BZ2_bzDecompressEnd ( &strm );
1334     return BZ_OK;
1335    
1336     output_overflow_or_eof:
1337     if (strm.avail_out > 0) {
1338     BZ2_bzDecompressEnd ( &strm );
1339     return BZ_UNEXPECTED_EOF;
1340     } else {
1341     BZ2_bzDecompressEnd ( &strm );
1342     return BZ_OUTBUFF_FULL;
1343     };
1344    
1345     errhandler:
1346     BZ2_bzDecompressEnd ( &strm );
1347     return ret;
1348     }
1349    
1350    
1351     /*---------------------------------------------------*/
1352     /*--
1353     Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1354     to support better zlib compatibility.
1355     This code is not _officially_ part of libbzip2 (yet);
1356     I haven't tested it, documented it, or considered the
1357     threading-safeness of it.
1358     If this code breaks, please contact both Yoshioka and me.
1359     --*/
1360     /*---------------------------------------------------*/
1361    
1362     /*---------------------------------------------------*/
1363     /*--
1364     return version like "0.9.5d, 4-Sept-1999".
1365     --*/
1366     const char * BZ_API(BZ2_bzlibVersion)(void)
1367     {
1368     return BZ_VERSION;
1369     }
1370    
1371    
1372     #ifndef BZ_NO_STDIO
1373     /*---------------------------------------------------*/
1374    
1375     #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1376     # include <fcntl.h>
1377     # include <io.h>
1378     # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1379     #else
1380     # define SET_BINARY_MODE(file)
1381     #endif
1382     static
1383     BZFILE * bzopen_or_bzdopen
1384     ( const char *path, /* no use when bzdopen */
1385     int fd, /* no use when bzdopen */
1386     const char *mode,
1387     int open_mode) /* bzopen: 0, bzdopen:1 */
1388     {
1389     int bzerr;
1390     char unused[BZ_MAX_UNUSED];
1391     int blockSize100k = 9;
1392     int writing = 0;
1393     char mode2[10] = "";
1394     FILE *fp = NULL;
1395     BZFILE *bzfp = NULL;
1396     int verbosity = 0;
1397     int workFactor = 30;
1398     int smallMode = 0;
1399     int nUnused = 0;
1400    
1401     if (mode == NULL) return NULL;
1402     while (*mode) {
1403     switch (*mode) {
1404     case 'r':
1405     writing = 0; break;
1406     case 'w':
1407     writing = 1; break;
1408     case 's':
1409     smallMode = 1; break;
1410     default:
1411     if (isdigit((int)(*mode))) {
1412     blockSize100k = *mode-BZ_HDR_0;
1413     }
1414     }
1415     mode++;
1416     }
1417     strcat(mode2, writing ? "w" : "r" );
1418     strcat(mode2,"b"); /* binary mode */
1419    
1420     if (open_mode==0) {
1421     if (path==NULL || strcmp(path,"")==0) {
1422     fp = (writing ? stdout : stdin);
1423     SET_BINARY_MODE(fp);
1424     } else {
1425     fp = fopen(path,mode2);
1426     }
1427     } else {
1428     #ifdef BZ_STRICT_ANSI
1429     fp = NULL;
1430     #else
1431     fp = fdopen(fd,mode2);
1432     #endif
1433     }
1434     if (fp == NULL) return NULL;
1435    
1436     if (writing) {
1437     /* Guard against total chaos and anarchy -- JRS */
1438     if (blockSize100k < 1) blockSize100k = 1;
1439     if (blockSize100k > 9) blockSize100k = 9;
1440     bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1441     verbosity,workFactor);
1442     } else {
1443     bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1444     unused,nUnused);
1445     }
1446     if (bzfp == NULL) {
1447     if (fp != stdin && fp != stdout) fclose(fp);
1448     return NULL;
1449     }
1450     return bzfp;
1451     }
1452    
1453    
1454     /*---------------------------------------------------*/
1455     /*--
1456     open file for read or write.
1457     ex) bzopen("file","w9")
1458     case path="" or NULL => use stdin or stdout.
1459     --*/
1460     BZFILE * BZ_API(BZ2_bzopen)
1461     ( const char *path,
1462     const char *mode )
1463     {
1464     return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1465     }
1466    
1467    
1468     /*---------------------------------------------------*/
1469     BZFILE * BZ_API(BZ2_bzdopen)
1470     ( int fd,
1471     const char *mode )
1472     {
1473     return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1474     }
1475    
1476    
1477     /*---------------------------------------------------*/
1478     int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1479     {
1480     int bzerr, nread;
1481     if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1482     nread = BZ2_bzRead(&bzerr,b,buf,len);
1483     if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1484     return nread;
1485     } else {
1486     return -1;
1487     }
1488     }
1489    
1490    
1491     /*---------------------------------------------------*/
1492     int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1493     {
1494     int bzerr;
1495    
1496     BZ2_bzWrite(&bzerr,b,buf,len);
1497     if(bzerr == BZ_OK){
1498     return len;
1499     }else{
1500     return -1;
1501     }
1502     }
1503    
1504    
1505     /*---------------------------------------------------*/
1506     int BZ_API(BZ2_bzflush) (BZFILE *b)
1507     {
1508     /* do nothing now... */
1509     return 0;
1510     }
1511    
1512    
1513     /*---------------------------------------------------*/
1514     void BZ_API(BZ2_bzclose) (BZFILE* b)
1515     {
1516     int bzerr;
1517     FILE *fp;
1518    
1519     if (b==NULL) {return;}
1520     fp = ((bzFile *)b)->handle;
1521     if(((bzFile*)b)->writing){
1522     BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1523     if(bzerr != BZ_OK){
1524     BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1525     }
1526     }else{
1527     BZ2_bzReadClose(&bzerr,b);
1528     }
1529     if(fp!=stdin && fp!=stdout){
1530     fclose(fp);
1531     }
1532     }
1533    
1534    
1535     /*---------------------------------------------------*/
1536     /*--
1537     return last error code
1538     --*/
1539     static const char *bzerrorstrings[] = {
1540     "OK"
1541     ,"SEQUENCE_ERROR"
1542     ,"PARAM_ERROR"
1543     ,"MEM_ERROR"
1544     ,"DATA_ERROR"
1545     ,"DATA_ERROR_MAGIC"
1546     ,"IO_ERROR"
1547     ,"UNEXPECTED_EOF"
1548     ,"OUTBUFF_FULL"
1549     ,"CONFIG_ERROR"
1550     ,"???" /* for future */
1551     ,"???" /* for future */
1552     ,"???" /* for future */
1553     ,"???" /* for future */
1554     ,"???" /* for future */
1555     ,"???" /* for future */
1556     };
1557    
1558    
1559     const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1560     {
1561     int err = ((bzFile *)b)->lastErr;
1562    
1563     if(err>0) err = 0;
1564     *errnum = err;
1565     return bzerrorstrings[err*-1];
1566     }
1567     #endif
1568    
1569    
1570     /*-------------------------------------------------------------*/
1571     /*--- end bzlib.c ---*/
1572     /*-------------------------------------------------------------*/