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