root/trunk/orca/support/bzip2/bzlib.c

Revision 1, 46.4 kB (checked in by krobillard, 3 years ago)

Import orca & thune.

Line 
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          Â