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