diff options
Diffstat (limited to 'lib/bzip2/bzlib.c')
| -rw-r--r-- | lib/bzip2/bzlib.c | 1601 | 
1 files changed, 1601 insertions, 0 deletions
| diff --git a/lib/bzip2/bzlib.c b/lib/bzip2/bzlib.c new file mode 100644 index 00000000000..5844e187c09 --- /dev/null +++ b/lib/bzip2/bzlib.c @@ -0,0 +1,1601 @@ +#include <config.h> +#include <common.h> +#include <watchdog.h> + +/* + * This file is a modified version of bzlib.c from the bzip2-1.0.2 + * distribution which can be found at http://sources.redhat.com/bzip2/ + */ + +/*-------------------------------------------------------------*/ +/*--- Library top-level functions.                          ---*/ +/*---                                               bzlib.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- +  This file is a part of bzip2 and/or libbzip2, a program and +  library for lossless, block-sorting data compression. + +  Copyright (C) 1996-2002 Julian R Seward.  All rights reserved. + +  Redistribution and use in source and binary forms, with or without +  modification, are permitted provided that the following conditions +  are met: + +  1. Redistributions of source code must retain the above copyright +     notice, this list of conditions and the following disclaimer. + +  2. The origin of this software must not be misrepresented; you must +     not claim that you wrote the original software.  If you use this +     software in a product, an acknowledgment in the product +     documentation would be appreciated but is not required. + +  3. Altered source versions must be plainly marked as such, and must +     not be misrepresented as being the original software. + +  4. The name of the author may not be used to endorse or promote +     products derived from this software without specific prior written +     permission. + +  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +  Julian Seward, Cambridge, UK. +  jseward@acm.org +  bzip2/libbzip2 version 1.0 of 21 March 2000 + +  This program is based on (at least) the work of: +     Mike Burrows +     David Wheeler +     Peter Fenwick +     Alistair Moffat +     Radford Neal +     Ian H. Witten +     Robert Sedgewick +     Jon L. Bentley + +  For more information on these sources, see the manual. +--*/ + +/*-- +   CHANGES +   ~~~~~~~ +   0.9.0 -- original version. + +   0.9.0a/b -- no changes in this file. + +   0.9.0c +      * made zero-length BZ_FLUSH work correctly in bzCompress(). +      * fixed bzWrite/bzRead to ignore zero-length requests. +      * fixed bzread to correctly handle read requests after EOF. +      * wrong parameter order in call to bzDecompressInit in +	bzBuffToBuffDecompress.  Fixed. +--*/ + +#include "bzlib_private.h" + +/*---------------------------------------------------*/ +/*--- Compression stuff                           ---*/ +/*---------------------------------------------------*/ + + +/*---------------------------------------------------*/ +#ifndef BZ_NO_STDIO +void BZ2_bz__AssertH__fail ( int errcode ) +{ +   fprintf(stderr, +      "\n\nbzip2/libbzip2: internal error number %d.\n" +      "This is a bug in bzip2/libbzip2, %s.\n" +      "Please report it to me at: jseward@acm.org.  If this happened\n" +      "when you were using some program which uses libbzip2 as a\n" +      "component, you should also report this bug to the author(s)\n" +      "of that program.  Please make an effort to report this bug;\n" +      "timely and accurate bug reports eventually lead to higher\n" +      "quality software.  Thanks.  Julian Seward, 30 December 2001.\n\n", +      errcode, +      BZ2_bzlibVersion() +   ); + +   if (errcode == 1007) { +   fprintf(stderr, +      "\n*** A special note about internal error number 1007 ***\n" +      "\n" +      "Experience suggests that a common cause of i.e. 1007\n" +      "is unreliable memory or other hardware.  The 1007 assertion\n" +      "just happens to cross-check the results of huge numbers of\n" +      "memory reads/writes, and so acts (unintendedly) as a stress\n" +      "test of your memory system.\n" +      "\n" +      "I suggest the following: try compressing the file again,\n" +      "possibly monitoring progress in detail with the -vv flag.\n" +      "\n" +      "* If the error cannot be reproduced, and/or happens at different\n" +      "  points in compression, you may have a flaky memory system.\n" +      "  Try a memory-test program.  I have used Memtest86\n" +      "  (www.memtest86.com).  At the time of writing it is free (GPLd).\n" +      "  Memtest86 tests memory much more thorougly than your BIOSs\n" +      "  power-on test, and may find failures that the BIOS doesn't.\n" +      "\n" +      "* If the error can be repeatably reproduced, this is a bug in\n" +      "  bzip2, and I would very much like to hear about it.  Please\n" +      "  let me know, and, ideally, save a copy of the file causing the\n" +      "  problem -- without which I will be unable to investigate it.\n" +      "\n" +   ); +   } + +   exit(3); +} +#endif + + +/*---------------------------------------------------*/ +static +int bz_config_ok ( void ) +{ +   if (sizeof(int)   != 4) return 0; +   if (sizeof(short) != 2) return 0; +   if (sizeof(char)  != 1) return 0; +   return 1; +} + + +/*---------------------------------------------------*/ +static +void* default_bzalloc ( void* opaque, Int32 items, Int32 size ) +{ +   void* v = malloc ( items * size ); +   return v; +} + +static +void default_bzfree ( void* opaque, void* addr ) +{ +   if (addr != NULL) free ( addr ); +} + +#ifndef BZ_NO_COMPRESS +/*---------------------------------------------------*/ +static +void prepare_new_block ( EState* s ) +{ +   Int32 i; +   s->nblock = 0; +   s->numZ = 0; +   s->state_out_pos = 0; +   BZ_INITIALISE_CRC ( s->blockCRC ); +   for (i = 0; i < 256; i++) s->inUse[i] = False; +   s->blockNo++; +} + + +/*---------------------------------------------------*/ +static +void init_RL ( EState* s ) +{ +   s->state_in_ch  = 256; +   s->state_in_len = 0; +} + + +static +Bool isempty_RL ( EState* s ) +{ +   if (s->state_in_ch < 256 && s->state_in_len > 0) +      return False; else +      return True; +} + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompressInit) +		    ( bz_stream* strm, +		     int        blockSize100k, +		     int        verbosity, +		     int        workFactor ) +{ +   Int32   n; +   EState* s; + +   if (!bz_config_ok()) return BZ_CONFIG_ERROR; + +   if (strm == NULL || +       blockSize100k < 1 || blockSize100k > 9 || +       workFactor < 0 || workFactor > 250) +     return BZ_PARAM_ERROR; + +   if (workFactor == 0) workFactor = 30; +   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; +   if (strm->bzfree == NULL) strm->bzfree = default_bzfree; + +   s = BZALLOC( sizeof(EState) ); +   if (s == NULL) return BZ_MEM_ERROR; +   s->strm = strm; + +   s->arr1 = NULL; +   s->arr2 = NULL; +   s->ftab = NULL; + +   n       = 100000 * blockSize100k; +   s->arr1 = BZALLOC( n                  * sizeof(UInt32) ); +   s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) ); +   s->ftab = BZALLOC( 65537              * sizeof(UInt32) ); + +   if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) { +      if (s->arr1 != NULL) BZFREE(s->arr1); +      if (s->arr2 != NULL) BZFREE(s->arr2); +      if (s->ftab != NULL) BZFREE(s->ftab); +      if (s       != NULL) BZFREE(s); +      return BZ_MEM_ERROR; +   } + +   s->blockNo           = 0; +   s->state             = BZ_S_INPUT; +   s->mode              = BZ_M_RUNNING; +   s->combinedCRC       = 0; +   s->blockSize100k     = blockSize100k; +   s->nblockMAX         = 100000 * blockSize100k - 19; +   s->verbosity         = verbosity; +   s->workFactor        = workFactor; + +   s->block             = (UChar*)s->arr2; +   s->mtfv              = (UInt16*)s->arr1; +   s->zbits             = NULL; +   s->ptr               = (UInt32*)s->arr1; + +   strm->state          = s; +   strm->total_in_lo32  = 0; +   strm->total_in_hi32  = 0; +   strm->total_out_lo32 = 0; +   strm->total_out_hi32 = 0; +   init_RL ( s ); +   prepare_new_block ( s ); +   return BZ_OK; +} + + +/*---------------------------------------------------*/ +static +void add_pair_to_block ( EState* s ) +{ +   Int32 i; +   UChar ch = (UChar)(s->state_in_ch); +   for (i = 0; i < s->state_in_len; i++) { +      BZ_UPDATE_CRC( s->blockCRC, ch ); +   } +   s->inUse[s->state_in_ch] = True; +   switch (s->state_in_len) { +      case 1: +	 s->block[s->nblock] = (UChar)ch; s->nblock++; +	 break; +      case 2: +	 s->block[s->nblock] = (UChar)ch; s->nblock++; +	 s->block[s->nblock] = (UChar)ch; s->nblock++; +	 break; +      case 3: +	 s->block[s->nblock] = (UChar)ch; s->nblock++; +	 s->block[s->nblock] = (UChar)ch; s->nblock++; +	 s->block[s->nblock] = (UChar)ch; s->nblock++; +	 break; +      default: +	 s->inUse[s->state_in_len-4] = True; +	 s->block[s->nblock] = (UChar)ch; s->nblock++; +	 s->block[s->nblock] = (UChar)ch; s->nblock++; +	 s->block[s->nblock] = (UChar)ch; s->nblock++; +	 s->block[s->nblock] = (UChar)ch; s->nblock++; +	 s->block[s->nblock] = ((UChar)(s->state_in_len-4)); +	 s->nblock++; +	 break; +   } +} + + +/*---------------------------------------------------*/ +static +void flush_RL ( EState* s ) +{ +   if (s->state_in_ch < 256) add_pair_to_block ( s ); +   init_RL ( s ); +} + + +/*---------------------------------------------------*/ +#define ADD_CHAR_TO_BLOCK(zs,zchh0)               \ +{                                                 \ +   UInt32 zchh = (UInt32)(zchh0);                 \ +   /*-- fast track the common case --*/           \ +   if (zchh != zs->state_in_ch &&                 \ +       zs->state_in_len == 1) {                   \ +      UChar ch = (UChar)(zs->state_in_ch);        \ +      BZ_UPDATE_CRC( zs->blockCRC, ch );          \ +      zs->inUse[zs->state_in_ch] = True;          \ +      zs->block[zs->nblock] = (UChar)ch;          \ +      zs->nblock++;                               \ +      zs->state_in_ch = zchh;                     \ +   }                                              \ +   else                                           \ +   /*-- general, uncommon cases --*/              \ +   if (zchh != zs->state_in_ch ||                 \ +      zs->state_in_len == 255) {                  \ +      if (zs->state_in_ch < 256)                  \ +	 add_pair_to_block ( zs );                \ +      zs->state_in_ch = zchh;                     \ +      zs->state_in_len = 1;                       \ +   } else {                                       \ +      zs->state_in_len++;                         \ +   }                                              \ +} + + +/*---------------------------------------------------*/ +static +Bool copy_input_until_stop ( EState* s ) +{ +   Bool progress_in = False; + +   if (s->mode == BZ_M_RUNNING) { + +      /*-- fast track the common case --*/ +      while (True) { +	 /*-- block full? --*/ +	 if (s->nblock >= s->nblockMAX) break; +	 /*-- no input? --*/ +	 if (s->strm->avail_in == 0) break; +	 progress_in = True; +	 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); +	 s->strm->next_in++; +	 s->strm->avail_in--; +	 s->strm->total_in_lo32++; +	 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; +      } + +   } else { + +      /*-- general, uncommon case --*/ +      while (True) { +	 /*-- block full? --*/ +	 if (s->nblock >= s->nblockMAX) break; +	 /*-- no input? --*/ +	 if (s->strm->avail_in == 0) break; +	 /*-- flush/finish end? --*/ +	 if (s->avail_in_expect == 0) break; +	 progress_in = True; +	 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); +	 s->strm->next_in++; +	 s->strm->avail_in--; +	 s->strm->total_in_lo32++; +	 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; +	 s->avail_in_expect--; +      } +   } +   return progress_in; +} + + +/*---------------------------------------------------*/ +static +Bool copy_output_until_stop ( EState* s ) +{ +   Bool progress_out = False; + +   while (True) { + +      /*-- no output space? --*/ +      if (s->strm->avail_out == 0) break; + +      /*-- block done? --*/ +      if (s->state_out_pos >= s->numZ) break; + +      progress_out = True; +      *(s->strm->next_out) = s->zbits[s->state_out_pos]; +      s->state_out_pos++; +      s->strm->avail_out--; +      s->strm->next_out++; +      s->strm->total_out_lo32++; +      if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; +   } + +   return progress_out; +} + + +/*---------------------------------------------------*/ +static +Bool handle_compress ( bz_stream* strm ) +{ +   Bool progress_in  = False; +   Bool progress_out = False; +   EState* s = strm->state; + +   while (True) { + +      if (s->state == BZ_S_OUTPUT) { +	 progress_out |= copy_output_until_stop ( s ); +	 if (s->state_out_pos < s->numZ) break; +	 if (s->mode == BZ_M_FINISHING && +	     s->avail_in_expect == 0 && +	     isempty_RL(s)) break; +	 prepare_new_block ( s ); +	 s->state = BZ_S_INPUT; +	 if (s->mode == BZ_M_FLUSHING && +	     s->avail_in_expect == 0 && +	     isempty_RL(s)) break; +      } + +      if (s->state == BZ_S_INPUT) { +	 progress_in |= copy_input_until_stop ( s ); +	 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) { +	    flush_RL ( s ); +	    BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) ); +	    s->state = BZ_S_OUTPUT; +	 } +	 else +	 if (s->nblock >= s->nblockMAX) { +	    BZ2_compressBlock ( s, False ); +	    s->state = BZ_S_OUTPUT; +	 } +	 else +	 if (s->strm->avail_in == 0) { +	    break; +	 } +      } + +   } + +   return progress_in || progress_out; +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action ) +{ +   Bool progress; +   EState* s; +   if (strm == NULL) return BZ_PARAM_ERROR; +   s = strm->state; +   if (s == NULL) return BZ_PARAM_ERROR; +   if (s->strm != strm) return BZ_PARAM_ERROR; + +   preswitch: +   switch (s->mode) { + +      case BZ_M_IDLE: +	 return BZ_SEQUENCE_ERROR; + +      case BZ_M_RUNNING: +	 if (action == BZ_RUN) { +	    progress = handle_compress ( strm ); +	    return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; +	 } +	 else +	 if (action == BZ_FLUSH) { +	    s->avail_in_expect = strm->avail_in; +	    s->mode = BZ_M_FLUSHING; +	    goto preswitch; +	 } +	 else +	 if (action == BZ_FINISH) { +	    s->avail_in_expect = strm->avail_in; +	    s->mode = BZ_M_FINISHING; +	    goto preswitch; +	 } +	 else +	    return BZ_PARAM_ERROR; + +      case BZ_M_FLUSHING: +	 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR; +	 if (s->avail_in_expect != s->strm->avail_in) +	    return BZ_SEQUENCE_ERROR; +	 progress = handle_compress ( strm ); +	 if (s->avail_in_expect > 0 || !isempty_RL(s) || +	     s->state_out_pos < s->numZ) return BZ_FLUSH_OK; +	 s->mode = BZ_M_RUNNING; +	 return BZ_RUN_OK; + +      case BZ_M_FINISHING: +	 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR; +	 if (s->avail_in_expect != s->strm->avail_in) +	    return BZ_SEQUENCE_ERROR; +	 progress = handle_compress ( strm ); +	 if (!progress) return BZ_SEQUENCE_ERROR; +	 if (s->avail_in_expect > 0 || !isempty_RL(s) || +	     s->state_out_pos < s->numZ) return BZ_FINISH_OK; +	 s->mode = BZ_M_IDLE; +	 return BZ_STREAM_END; +   } +   return BZ_OK; /*--not reached--*/ +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm ) +{ +   EState* s; +   if (strm == NULL) return BZ_PARAM_ERROR; +   s = strm->state; +   if (s == NULL) return BZ_PARAM_ERROR; +   if (s->strm != strm) return BZ_PARAM_ERROR; + +   if (s->arr1 != NULL) BZFREE(s->arr1); +   if (s->arr2 != NULL) BZFREE(s->arr2); +   if (s->ftab != NULL) BZFREE(s->ftab); +   BZFREE(strm->state); + +   strm->state = NULL; + +   return BZ_OK; +} +#endif /* BZ_NO_COMPRESS */ + +/*---------------------------------------------------*/ +/*--- Decompression stuff                         ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompressInit) +		     ( bz_stream* strm, +		       int        verbosity, +		       int        small ) +{ +   DState* s; + +   if (!bz_config_ok()) return BZ_CONFIG_ERROR; + +   if (strm == NULL) return BZ_PARAM_ERROR; +   if (small != 0 && small != 1) return BZ_PARAM_ERROR; +   if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR; + +   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; +   if (strm->bzfree == NULL) strm->bzfree = default_bzfree; + +   s = BZALLOC( sizeof(DState) ); +   if (s == NULL) return BZ_MEM_ERROR; +   s->strm                  = strm; +   strm->state              = s; +   s->state                 = BZ_X_MAGIC_1; +   s->bsLive                = 0; +   s->bsBuff                = 0; +   s->calculatedCombinedCRC = 0; +   strm->total_in_lo32      = 0; +   strm->total_in_hi32      = 0; +   strm->total_out_lo32     = 0; +   strm->total_out_hi32     = 0; +   s->smallDecompress       = (Bool)small; +   s->ll4                   = NULL; +   s->ll16                  = NULL; +   s->tt                    = NULL; +   s->currBlockNo           = 0; +   s->verbosity             = verbosity; + +   return BZ_OK; +} + + +/*---------------------------------------------------*/ +static +void unRLE_obuf_to_output_FAST ( DState* s ) +{ +   UChar k1; + +   if (s->blockRandomised) { + +      while (True) { +	 /* try to finish existing run */ +	 while (True) { +	    if (s->strm->avail_out == 0) return; +	    if (s->state_out_len == 0) break; +	    *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; +	    BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); +	    s->state_out_len--; +	    s->strm->next_out++; +	    s->strm->avail_out--; +	    s->strm->total_out_lo32++; +	    if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; +	 } + +	 /* can a new run be started? */ +	 if (s->nblock_used == s->save_nblock+1) return; + + +	 s->state_out_len = 1; +	 s->state_out_ch = s->k0; +	 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; +	 k1 ^= BZ_RAND_MASK; s->nblock_used++; +	 if (s->nblock_used == s->save_nblock+1) continue; +	 if (k1 != s->k0) { s->k0 = k1; continue; }; + +	 s->state_out_len = 2; +	 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; +	 k1 ^= BZ_RAND_MASK; s->nblock_used++; +	 if (s->nblock_used == s->save_nblock+1) continue; +	 if (k1 != s->k0) { s->k0 = k1; continue; }; + +	 s->state_out_len = 3; +	 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; +	 k1 ^= BZ_RAND_MASK; s->nblock_used++; +	 if (s->nblock_used == s->save_nblock+1) continue; +	 if (k1 != s->k0) { s->k0 = k1; continue; }; + +	 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; +	 k1 ^= BZ_RAND_MASK; s->nblock_used++; +	 s->state_out_len = ((Int32)k1) + 4; +	 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; +	 s->k0 ^= BZ_RAND_MASK; s->nblock_used++; +      } + +   } else { + +      /* restore */ +      UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC; +      UChar         c_state_out_ch       = s->state_out_ch; +      Int32         c_state_out_len      = s->state_out_len; +      Int32         c_nblock_used        = s->nblock_used; +      Int32         c_k0                 = s->k0; +      UInt32*       c_tt                 = s->tt; +      UInt32        c_tPos               = s->tPos; +      char*         cs_next_out          = s->strm->next_out; +      unsigned int  cs_avail_out         = s->strm->avail_out; +      /* end restore */ + +      UInt32       avail_out_INIT = cs_avail_out; +      Int32        s_save_nblockPP = s->save_nblock+1; +      unsigned int total_out_lo32_old; + +      while (True) { + +	 /* try to finish existing run */ +	 if (c_state_out_len > 0) { +	    while (True) { +	       if (cs_avail_out == 0) goto return_notr; +	       if (c_state_out_len == 1) break; +	       *( (UChar*)(cs_next_out) ) = c_state_out_ch; +	       BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); +	       c_state_out_len--; +	       cs_next_out++; +	       cs_avail_out--; +	    } +	    s_state_out_len_eq_one: +	    { +	       if (cs_avail_out == 0) { +		  c_state_out_len = 1; goto return_notr; +	       }; +	       *( (UChar*)(cs_next_out) ) = c_state_out_ch; +	       BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); +	       cs_next_out++; +	       cs_avail_out--; +	    } +	 } +	 /* can a new run be started? */ +	 if (c_nblock_used == s_save_nblockPP) { +	    c_state_out_len = 0; goto return_notr; +	 }; +	 c_state_out_ch = c_k0; +	 BZ_GET_FAST_C(k1); c_nblock_used++; +	 if (k1 != c_k0) { +	    c_k0 = k1; goto s_state_out_len_eq_one; +	 }; +	 if (c_nblock_used == s_save_nblockPP) +	    goto s_state_out_len_eq_one; + +	 c_state_out_len = 2; +	 BZ_GET_FAST_C(k1); c_nblock_used++; +	 if (c_nblock_used == s_save_nblockPP) continue; +	 if (k1 != c_k0) { c_k0 = k1; continue; }; + +	 c_state_out_len = 3; +	 BZ_GET_FAST_C(k1); c_nblock_used++; +	 if (c_nblock_used == s_save_nblockPP) continue; +	 if (k1 != c_k0) { c_k0 = k1; continue; }; + +	 BZ_GET_FAST_C(k1); c_nblock_used++; +	 c_state_out_len = ((Int32)k1) + 4; +	 BZ_GET_FAST_C(c_k0); c_nblock_used++; +      } + +      return_notr: +      total_out_lo32_old = s->strm->total_out_lo32; +      s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); +      if (s->strm->total_out_lo32 < total_out_lo32_old) +	 s->strm->total_out_hi32++; + +      /* save */ +      s->calculatedBlockCRC = c_calculatedBlockCRC; +      s->state_out_ch       = c_state_out_ch; +      s->state_out_len      = c_state_out_len; +      s->nblock_used        = c_nblock_used; +      s->k0                 = c_k0; +      s->tt                 = c_tt; +      s->tPos               = c_tPos; +      s->strm->next_out     = cs_next_out; +      s->strm->avail_out    = cs_avail_out; +      /* end save */ +   } +} + + +/*---------------------------------------------------*/ +__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) +{ +   Int32 nb, na, mid; +   nb = 0; +   na = 256; +   do { +      mid = (nb + na) >> 1; +      if (indx >= cftab[mid]) nb = mid; else na = mid; +   } +   while (na - nb != 1); +   return nb; +} + + +/*---------------------------------------------------*/ +static +void unRLE_obuf_to_output_SMALL ( DState* s ) +{ +   UChar k1; + +   if (s->blockRandomised) { + +      while (True) { +	 /* try to finish existing run */ +	 while (True) { +	    if (s->strm->avail_out == 0) return; +	    if (s->state_out_len == 0) break; +	    *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; +	    BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); +	    s->state_out_len--; +	    s->strm->next_out++; +	    s->strm->avail_out--; +	    s->strm->total_out_lo32++; +	    if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; +	 } + +	 /* can a new run be started? */ +	 if (s->nblock_used == s->save_nblock+1) return; + + +	 s->state_out_len = 1; +	 s->state_out_ch = s->k0; +	 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; +	 k1 ^= BZ_RAND_MASK; s->nblock_used++; +	 if (s->nblock_used == s->save_nblock+1) continue; +	 if (k1 != s->k0) { s->k0 = k1; continue; }; + +	 s->state_out_len = 2; +	 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; +	 k1 ^= BZ_RAND_MASK; s->nblock_used++; +	 if (s->nblock_used == s->save_nblock+1) continue; +	 if (k1 != s->k0) { s->k0 = k1; continue; }; + +	 s->state_out_len = 3; +	 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; +	 k1 ^= BZ_RAND_MASK; s->nblock_used++; +	 if (s->nblock_used == s->save_nblock+1) continue; +	 if (k1 != s->k0) { s->k0 = k1; continue; }; + +	 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; +	 k1 ^= BZ_RAND_MASK; s->nblock_used++; +	 s->state_out_len = ((Int32)k1) + 4; +	 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; +	 s->k0 ^= BZ_RAND_MASK; s->nblock_used++; +      } + +   } else { + +      while (True) { +	 /* try to finish existing run */ +	 while (True) { +	    if (s->strm->avail_out == 0) return; +	    if (s->state_out_len == 0) break; +	    *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; +	    BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); +	    s->state_out_len--; +	    s->strm->next_out++; +	    s->strm->avail_out--; +	    s->strm->total_out_lo32++; +	    if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; +	 } + +	 /* can a new run be started? */ +	 if (s->nblock_used == s->save_nblock+1) return; + +	 s->state_out_len = 1; +	 s->state_out_ch = s->k0; +	 BZ_GET_SMALL(k1); s->nblock_used++; +	 if (s->nblock_used == s->save_nblock+1) continue; +	 if (k1 != s->k0) { s->k0 = k1; continue; }; + +	 s->state_out_len = 2; +	 BZ_GET_SMALL(k1); s->nblock_used++; +	 if (s->nblock_used == s->save_nblock+1) continue; +	 if (k1 != s->k0) { s->k0 = k1; continue; }; + +	 s->state_out_len = 3; +	 BZ_GET_SMALL(k1); s->nblock_used++; +	 if (s->nblock_used == s->save_nblock+1) continue; +	 if (k1 != s->k0) { s->k0 = k1; continue; }; + +	 BZ_GET_SMALL(k1); s->nblock_used++; +	 s->state_out_len = ((Int32)k1) + 4; +	 BZ_GET_SMALL(s->k0); s->nblock_used++; +      } + +   } +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) +{ +   DState* s; +   if (strm == NULL) return BZ_PARAM_ERROR; +   s = strm->state; +   if (s == NULL) return BZ_PARAM_ERROR; +   if (s->strm != strm) return BZ_PARAM_ERROR; + +   while (True) { +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) +	WATCHDOG_RESET(); +#endif +      if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; +      if (s->state == BZ_X_OUTPUT) { +	 if (s->smallDecompress) +	    unRLE_obuf_to_output_SMALL ( s ); else +	    unRLE_obuf_to_output_FAST  ( s ); +	 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { +	    BZ_FINALISE_CRC ( s->calculatedBlockCRC ); +	    if (s->verbosity >= 3) +	       VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC, +			  s->calculatedBlockCRC ); +	    if (s->verbosity >= 2) VPrintf0 ( "]" ); +	    if (s->calculatedBlockCRC != s->storedBlockCRC) +	       return BZ_DATA_ERROR; +	    s->calculatedCombinedCRC +	       = (s->calculatedCombinedCRC << 1) | +		    (s->calculatedCombinedCRC >> 31); +	    s->calculatedCombinedCRC ^= s->calculatedBlockCRC; +	    s->state = BZ_X_BLKHDR_1; +	 } else { +	    return BZ_OK; +	 } +      } +      if (s->state >= BZ_X_MAGIC_1) { +	 Int32 r = BZ2_decompress ( s ); +	 if (r == BZ_STREAM_END) { +	    if (s->verbosity >= 3) +	       VPrintf2 ( "\n    combined CRCs: stored = 0x%x, computed = 0x%x", +			  s->storedCombinedCRC, s->calculatedCombinedCRC ); +	    if (s->calculatedCombinedCRC != s->storedCombinedCRC) +	       return BZ_DATA_ERROR; +	    return r; +	 } +	 if (s->state != BZ_X_OUTPUT) return r; +      } +   } + +   AssertH ( 0, 6001 ); + +   return 0;  /*NOTREACHED*/ +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm ) +{ +   DState* s; +   if (strm == NULL) return BZ_PARAM_ERROR; +   s = strm->state; +   if (s == NULL) return BZ_PARAM_ERROR; +   if (s->strm != strm) return BZ_PARAM_ERROR; + +   if (s->tt   != NULL) BZFREE(s->tt); +   if (s->ll16 != NULL) BZFREE(s->ll16); +   if (s->ll4  != NULL) BZFREE(s->ll4); + +   BZFREE(strm->state); +   strm->state = NULL; + +   return BZ_OK; +} + + +#ifndef BZ_NO_STDIO +/*---------------------------------------------------*/ +/*--- File I/O stuff                              ---*/ +/*---------------------------------------------------*/ + +#define BZ_SETERR(eee)                    \ +{                                         \ +   if (bzerror != NULL) *bzerror = eee;   \ +   if (bzf != NULL) bzf->lastErr = eee;   \ +} + +typedef +   struct { +      FILE*     handle; +      Char      buf[BZ_MAX_UNUSED]; +      Int32     bufN; +      Bool      writing; +      bz_stream strm; +      Int32     lastErr; +      Bool      initialisedOk; +   } +   bzFile; + + +/*---------------------------------------------*/ +static Bool myfeof ( FILE* f ) +{ +   Int32 c = fgetc ( f ); +   if (c == EOF) return True; +   ungetc ( c, f ); +   return False; +} + + +/*---------------------------------------------------*/ +BZFILE* BZ_API(BZ2_bzWriteOpen) +		    ( int*  bzerror, +		      FILE* f, +		      int   blockSize100k, +		      int   verbosity, +		      int   workFactor ) +{ +   Int32   ret; +   bzFile* bzf = NULL; + +   BZ_SETERR(BZ_OK); + +   if (f == NULL || +       (blockSize100k < 1 || blockSize100k > 9) || +       (workFactor < 0 || workFactor > 250) || +       (verbosity < 0 || verbosity > 4)) +      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; + +   if (ferror(f)) +      { BZ_SETERR(BZ_IO_ERROR); return NULL; }; + +   bzf = malloc ( sizeof(bzFile) ); +   if (bzf == NULL) +      { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; + +   BZ_SETERR(BZ_OK); +   bzf->initialisedOk = False; +   bzf->bufN          = 0; +   bzf->handle        = f; +   bzf->writing       = True; +   bzf->strm.bzalloc  = NULL; +   bzf->strm.bzfree   = NULL; +   bzf->strm.opaque   = NULL; + +   if (workFactor == 0) workFactor = 30; +   ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, +			      verbosity, workFactor ); +   if (ret != BZ_OK) +      { BZ_SETERR(ret); free(bzf); return NULL; }; + +   bzf->strm.avail_in = 0; +   bzf->initialisedOk = True; +   return bzf; +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzWrite) +	     ( int*    bzerror, +	       BZFILE* b, +	       void*   buf, +	       int     len ) +{ +   Int32 n, n2, ret; +   bzFile* bzf = (bzFile*)b; + +   BZ_SETERR(BZ_OK); +   if (bzf == NULL || buf == NULL || len < 0) +      { BZ_SETERR(BZ_PARAM_ERROR); return; }; +   if (!(bzf->writing)) +      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; +   if (ferror(bzf->handle)) +      { BZ_SETERR(BZ_IO_ERROR); return; }; + +   if (len == 0) +      { BZ_SETERR(BZ_OK); return; }; + +   bzf->strm.avail_in = len; +   bzf->strm.next_in  = buf; + +   while (True) { +      bzf->strm.avail_out = BZ_MAX_UNUSED; +      bzf->strm.next_out = bzf->buf; +      ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN ); +      if (ret != BZ_RUN_OK) +	 { BZ_SETERR(ret); return; }; + +      if (bzf->strm.avail_out < BZ_MAX_UNUSED) { +	 n = BZ_MAX_UNUSED - bzf->strm.avail_out; +	 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), +		       n, bzf->handle ); +	 if (n != n2 || ferror(bzf->handle)) +	    { BZ_SETERR(BZ_IO_ERROR); return; }; +      } + +      if (bzf->strm.avail_in == 0) +	 { BZ_SETERR(BZ_OK); return; }; +   } +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzWriteClose) +		  ( int*          bzerror, +		    BZFILE*       b, +		    int           abandon, +		    unsigned int* nbytes_in, +		    unsigned int* nbytes_out ) +{ +   BZ2_bzWriteClose64 ( bzerror, b, abandon, +			nbytes_in, NULL, nbytes_out, NULL ); +} + + +void BZ_API(BZ2_bzWriteClose64) +		  ( int*          bzerror, +		    BZFILE*       b, +		    int           abandon, +		    unsigned int* nbytes_in_lo32, +		    unsigned int* nbytes_in_hi32, +		    unsigned int* nbytes_out_lo32, +		    unsigned int* nbytes_out_hi32 ) +{ +   Int32   n, n2, ret; +   bzFile* bzf = (bzFile*)b; + +   if (bzf == NULL) +      { BZ_SETERR(BZ_OK); return; }; +   if (!(bzf->writing)) +      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; +   if (ferror(bzf->handle)) +      { BZ_SETERR(BZ_IO_ERROR); return; }; + +   if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0; +   if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0; +   if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0; +   if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0; + +   if ((!abandon) && bzf->lastErr == BZ_OK) { +      while (True) { +	 bzf->strm.avail_out = BZ_MAX_UNUSED; +	 bzf->strm.next_out = bzf->buf; +	 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH ); +	 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) +	    { BZ_SETERR(ret); return; }; + +	 if (bzf->strm.avail_out < BZ_MAX_UNUSED) { +	    n = BZ_MAX_UNUSED - bzf->strm.avail_out; +	    n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), +			  n, bzf->handle ); +	    if (n != n2 || ferror(bzf->handle)) +	       { BZ_SETERR(BZ_IO_ERROR); return; }; +	 } + +	 if (ret == BZ_STREAM_END) break; +      } +   } + +   if ( !abandon && !ferror ( bzf->handle ) ) { +      fflush ( bzf->handle ); +      if (ferror(bzf->handle)) +	 { BZ_SETERR(BZ_IO_ERROR); return; }; +   } + +   if (nbytes_in_lo32 != NULL) +      *nbytes_in_lo32 = bzf->strm.total_in_lo32; +   if (nbytes_in_hi32 != NULL) +      *nbytes_in_hi32 = bzf->strm.total_in_hi32; +   if (nbytes_out_lo32 != NULL) +      *nbytes_out_lo32 = bzf->strm.total_out_lo32; +   if (nbytes_out_hi32 != NULL) +      *nbytes_out_hi32 = bzf->strm.total_out_hi32; + +   BZ_SETERR(BZ_OK); +   BZ2_bzCompressEnd ( &(bzf->strm) ); +   free ( bzf ); +} + + +/*---------------------------------------------------*/ +BZFILE* BZ_API(BZ2_bzReadOpen) +		   ( int*  bzerror, +		     FILE* f, +		     int   verbosity, +		     int   small, +		     void* unused, +		     int   nUnused ) +{ +   bzFile* bzf = NULL; +   int     ret; + +   BZ_SETERR(BZ_OK); + +   if (f == NULL || +       (small != 0 && small != 1) || +       (verbosity < 0 || verbosity > 4) || +       (unused == NULL && nUnused != 0) || +       (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED))) +      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; + +   if (ferror(f)) +      { BZ_SETERR(BZ_IO_ERROR); return NULL; }; + +   bzf = malloc ( sizeof(bzFile) ); +   if (bzf == NULL) +      { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; + +   BZ_SETERR(BZ_OK); + +   bzf->initialisedOk = False; +   bzf->handle        = f; +   bzf->bufN          = 0; +   bzf->writing       = False; +   bzf->strm.bzalloc  = NULL; +   bzf->strm.bzfree   = NULL; +   bzf->strm.opaque   = NULL; + +   while (nUnused > 0) { +      bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++; +      unused = ((void*)( 1 + ((UChar*)(unused))  )); +      nUnused--; +   } + +   ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small ); +   if (ret != BZ_OK) +      { BZ_SETERR(ret); free(bzf); return NULL; }; + +   bzf->strm.avail_in = bzf->bufN; +   bzf->strm.next_in  = bzf->buf; + +   bzf->initialisedOk = True; +   return bzf; +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b ) +{ +   bzFile* bzf = (bzFile*)b; + +   BZ_SETERR(BZ_OK); +   if (bzf == NULL) +      { BZ_SETERR(BZ_OK); return; }; + +   if (bzf->writing) +      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + +   if (bzf->initialisedOk) +      (void)BZ2_bzDecompressEnd ( &(bzf->strm) ); +   free ( bzf ); +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzRead) +	   ( int*    bzerror, +	     BZFILE* b, +	     void*   buf, +	     int     len ) +{ +   Int32   n, ret; +   bzFile* bzf = (bzFile*)b; + +   BZ_SETERR(BZ_OK); + +   if (bzf == NULL || buf == NULL || len < 0) +      { BZ_SETERR(BZ_PARAM_ERROR); return 0; }; + +   if (bzf->writing) +      { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; }; + +   if (len == 0) +      { BZ_SETERR(BZ_OK); return 0; }; + +   bzf->strm.avail_out = len; +   bzf->strm.next_out = buf; + +   while (True) { + +      if (ferror(bzf->handle)) +	 { BZ_SETERR(BZ_IO_ERROR); return 0; }; + +      if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) { +	 n = fread ( bzf->buf, sizeof(UChar), +		     BZ_MAX_UNUSED, bzf->handle ); +	 if (ferror(bzf->handle)) +	    { BZ_SETERR(BZ_IO_ERROR); return 0; }; +	 bzf->bufN = n; +	 bzf->strm.avail_in = bzf->bufN; +	 bzf->strm.next_in = bzf->buf; +      } + +      ret = BZ2_bzDecompress ( &(bzf->strm) ); + +      if (ret != BZ_OK && ret != BZ_STREAM_END) +	 { BZ_SETERR(ret); return 0; }; + +      if (ret == BZ_OK && myfeof(bzf->handle) && +	  bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0) +	 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; }; + +      if (ret == BZ_STREAM_END) +	 { BZ_SETERR(BZ_STREAM_END); +	   return len - bzf->strm.avail_out; }; +      if (bzf->strm.avail_out == 0) +	 { BZ_SETERR(BZ_OK); return len; }; + +   } + +   return 0; /*not reached*/ +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzReadGetUnused) +		     ( int*    bzerror, +		       BZFILE* b, +		       void**  unused, +		       int*    nUnused ) +{ +   bzFile* bzf = (bzFile*)b; +   if (bzf == NULL) +      { BZ_SETERR(BZ_PARAM_ERROR); return; }; +   if (bzf->lastErr != BZ_STREAM_END) +      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; +   if (unused == NULL || nUnused == NULL) +      { BZ_SETERR(BZ_PARAM_ERROR); return; }; + +   BZ_SETERR(BZ_OK); +   *nUnused = bzf->strm.avail_in; +   *unused = bzf->strm.next_in; +} +#endif + + +/*---------------------------------------------------*/ +/*--- Misc convenience stuff                      ---*/ +/*---------------------------------------------------*/ +#ifndef BZ_NO_COMPRESS +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzBuffToBuffCompress) +			 ( char*         dest, +			   unsigned int* destLen, +			   char*         source, +			   unsigned int  sourceLen, +			   int           blockSize100k, +			   int           verbosity, +			   int           workFactor ) +{ +   bz_stream strm; +   int ret; + +   if (dest == NULL || destLen == NULL || +       source == NULL || +       blockSize100k < 1 || blockSize100k > 9 || +       verbosity < 0 || verbosity > 4 || +       workFactor < 0 || workFactor > 250) +      return BZ_PARAM_ERROR; + +   if (workFactor == 0) workFactor = 30; +   strm.bzalloc = NULL; +   strm.bzfree = NULL; +   strm.opaque = NULL; +   ret = BZ2_bzCompressInit ( &strm, blockSize100k, +			      verbosity, workFactor ); +   if (ret != BZ_OK) return ret; + +   strm.next_in = source; +   strm.next_out = dest; +   strm.avail_in = sourceLen; +   strm.avail_out = *destLen; + +   ret = BZ2_bzCompress ( &strm, BZ_FINISH ); +   if (ret == BZ_FINISH_OK) goto output_overflow; +   if (ret != BZ_STREAM_END) goto errhandler; + +   /* normal termination */ +   *destLen -= strm.avail_out; +   BZ2_bzCompressEnd ( &strm ); +   return BZ_OK; + +   output_overflow: +   BZ2_bzCompressEnd ( &strm ); +   return BZ_OUTBUFF_FULL; + +   errhandler: +   BZ2_bzCompressEnd ( &strm ); +   return ret; +} +#endif /* BZ_NO_COMPRESS */ + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzBuffToBuffDecompress) +			   ( char*         dest, +			     unsigned int* destLen, +			     char*         source, +			     unsigned int  sourceLen, +			     int           small, +			     int           verbosity ) +{ +   bz_stream strm; +   int ret; + +   if (destLen == NULL || source == NULL) +	  return BZ_PARAM_ERROR; + +   strm.bzalloc = NULL; +   strm.bzfree = NULL; +   strm.opaque = NULL; +   ret = BZ2_bzDecompressInit ( &strm, verbosity, small ); +   if (ret != BZ_OK) return ret; + +   strm.next_in = source; +   strm.next_out = dest; +   strm.avail_in = sourceLen; +   strm.avail_out = *destLen; + +   ret = BZ2_bzDecompress ( &strm ); +   if (ret == BZ_OK) goto output_overflow_or_eof; +   if (ret != BZ_STREAM_END) goto errhandler; + +   /* normal termination */ +   *destLen -= strm.avail_out; +   BZ2_bzDecompressEnd ( &strm ); +   return BZ_OK; + +   output_overflow_or_eof: +   if (strm.avail_out > 0) { +      BZ2_bzDecompressEnd ( &strm ); +      return BZ_UNEXPECTED_EOF; +   } else { +      BZ2_bzDecompressEnd ( &strm ); +      return BZ_OUTBUFF_FULL; +   }; + +   errhandler: +   BZ2_bzDecompressEnd ( &strm ); +   return ret; +} + + +/*---------------------------------------------------*/ +/*-- +   Code contributed by Yoshioka Tsuneo +   (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp), +   to support better zlib compatibility. +   This code is not _officially_ part of libbzip2 (yet); +   I haven't tested it, documented it, or considered the +   threading-safeness of it. +   If this code breaks, please contact both Yoshioka and me. +--*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +/*-- +   return version like "0.9.0c". +--*/ +const char * BZ_API(BZ2_bzlibVersion)(void) +{ +   return BZ_VERSION; +} + + +#ifndef BZ_NO_STDIO +/*---------------------------------------------------*/ + +#if defined(_WIN32) || defined(OS2) || defined(MSDOS) +#   include <fcntl.h> +#   include <io.h> +#   define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) +#else +#   define SET_BINARY_MODE(file) +#endif +static +BZFILE * bzopen_or_bzdopen +	       ( const char *path,   /* no use when bzdopen */ +		 int fd,             /* no use when bzdopen */ +		 const char *mode, +		 int open_mode)      /* bzopen: 0, bzdopen:1 */ +{ +   int    bzerr; +   char   unused[BZ_MAX_UNUSED]; +   int    blockSize100k = 9; +   int    writing       = 0; +   char   mode2[10]     = ""; +   FILE   *fp           = NULL; +   BZFILE *bzfp         = NULL; +   int    verbosity     = 0; +   int    workFactor    = 30; +   int    smallMode     = 0; +   int    nUnused       = 0; + +   if (mode == NULL) return NULL; +   while (*mode) { +      switch (*mode) { +      case 'r': +	 writing = 0; break; +      case 'w': +	 writing = 1; break; +      case 's': +	 smallMode = 1; break; +      default: +	 if (isdigit((int)(*mode))) { +	    blockSize100k = *mode-BZ_HDR_0; +	 } +      } +      mode++; +   } +   strcat(mode2, writing ? "w" : "r" ); +   strcat(mode2,"b");   /* binary mode */ + +   if (open_mode==0) { +      if (path==NULL || strcmp(path,"")==0) { +	fp = (writing ? stdout : stdin); +	SET_BINARY_MODE(fp); +      } else { +	fp = fopen(path,mode2); +      } +   } else { +#ifdef BZ_STRICT_ANSI +      fp = NULL; +#else +      fp = fdopen(fd,mode2); +#endif +   } +   if (fp == NULL) return NULL; + +   if (writing) { +      /* Guard against total chaos and anarchy -- JRS */ +      if (blockSize100k < 1) blockSize100k = 1; +      if (blockSize100k > 9) blockSize100k = 9; +      bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k, +			     verbosity,workFactor); +   } else { +      bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode, +			    unused,nUnused); +   } +   if (bzfp == NULL) { +      if (fp != stdin && fp != stdout) fclose(fp); +      return NULL; +   } +   return bzfp; +} + + +/*---------------------------------------------------*/ +/*-- +   open file for read or write. +      ex) bzopen("file","w9") +      case path="" or NULL => use stdin or stdout. +--*/ +BZFILE * BZ_API(BZ2_bzopen) +	       ( const char *path, +		 const char *mode ) +{ +   return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0); +} + + +/*---------------------------------------------------*/ +BZFILE * BZ_API(BZ2_bzdopen) +	       ( int fd, +		 const char *mode ) +{ +   return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1); +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len ) +{ +   int bzerr, nread; +   if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0; +   nread = BZ2_bzRead(&bzerr,b,buf,len); +   if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) { +      return nread; +   } else { +      return -1; +   } +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len ) +{ +   int bzerr; + +   BZ2_bzWrite(&bzerr,b,buf,len); +   if(bzerr == BZ_OK){ +      return len; +   }else{ +      return -1; +   } +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzflush) (BZFILE *b) +{ +   /* do nothing now... */ +   return 0; +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzclose) (BZFILE* b) +{ +   int bzerr; +   FILE *fp = ((bzFile *)b)->handle; + +   if (b==NULL) {return;} +   if(((bzFile*)b)->writing){ +      BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL); +      if(bzerr != BZ_OK){ +	 BZ2_bzWriteClose(NULL,b,1,NULL,NULL); +      } +   }else{ +      BZ2_bzReadClose(&bzerr,b); +   } +   if(fp!=stdin && fp!=stdout){ +      fclose(fp); +   } +} + + +/*---------------------------------------------------*/ +/*-- +   return last error code +--*/ +static char *bzerrorstrings[] = { +       "OK" +      ,"SEQUENCE_ERROR" +      ,"PARAM_ERROR" +      ,"MEM_ERROR" +      ,"DATA_ERROR" +      ,"DATA_ERROR_MAGIC" +      ,"IO_ERROR" +      ,"UNEXPECTED_EOF" +      ,"OUTBUFF_FULL" +      ,"CONFIG_ERROR" +      ,"???"   /* for future */ +      ,"???"   /* for future */ +      ,"???"   /* for future */ +      ,"???"   /* for future */ +      ,"???"   /* for future */ +      ,"???"   /* for future */ +}; + + +const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum) +{ +   int err = ((bzFile *)b)->lastErr; + +   if(err>0) err = 0; +   *errnum = err; +   return bzerrorstrings[err*-1]; +} +#endif + +void bz_internal_error(int errcode) +{ +	printf ("BZIP2 internal error %d\n", errcode); +} + +/*-------------------------------------------------------------*/ +/*--- end                                           bzlib.c ---*/ +/*-------------------------------------------------------------*/ | 
