Merge from vendor branch FILE:
[dragonfly.git] / contrib / bzip2 / bzlib.c
1
2 /*-------------------------------------------------------------*/
3 /*--- Library top-level functions.                          ---*/
4 /*---                                               bzlib.c ---*/
5 /*-------------------------------------------------------------*/
6
7 /*--
8   This file is a part of bzip2 and/or libbzip2, a program and
9   library for lossless, block-sorting data compression.
10
11   Copyright (C) 1996-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 /*-------------------------------------------------------------*/