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