vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

bzlib.c (47556B)


      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
     86 void BZ2_bz__AssertH__fail ( int errcode )
     87 {
     88    fprintf(stderr, 
     89       "\n\nbzip2/libbzip2: internal error number %d.\n"
     90       "This is a bug in bzip2/libbzip2, %s.\n"
     91       "Please report it to me at: jseward@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 /*---------------------------------------------------*/
    135 static
    136 int bz_config_ok ( void )
    137 {
    138    if (sizeof(int)   != 4) return 0;
    139    if (sizeof(short) != 2) return 0;
    140    if (sizeof(char)  != 1) return 0;
    141    return 1;
    142 }
    143 
    144 
    145 /*---------------------------------------------------*/
    146 static
    147 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
    148 {
    149    void* v = malloc ( items * size );
    150    return v;
    151 }
    152 
    153 static
    154 void default_bzfree ( void* opaque, void* addr )
    155 {
    156    if (addr != NULL) free ( addr );
    157 }
    158 
    159 
    160 /*---------------------------------------------------*/
    161 static
    162 void prepare_new_block ( EState* s )
    163 {
    164    Int32 i;
    165    s->nblock = 0;
    166    s->numZ = 0;
    167    s->state_out_pos = 0;
    168    BZ_INITIALISE_CRC ( s->blockCRC );
    169    for (i = 0; i < 256; i++) s->inUse[i] = False;
    170    s->blockNo++;
    171 }
    172 
    173 
    174 /*---------------------------------------------------*/
    175 static
    176 void init_RL ( EState* s )
    177 {
    178    s->state_in_ch  = 256;
    179    s->state_in_len = 0;
    180 }
    181 
    182 
    183 static
    184 Bool isempty_RL ( EState* s )
    185 {
    186    if (s->state_in_ch < 256 && s->state_in_len > 0)
    187       return False; else
    188       return True;
    189 }
    190 
    191 
    192 /*---------------------------------------------------*/
    193 int BZ_API(BZ2_bzCompressInit) 
    194                     ( bz_stream* strm, 
    195                      int        blockSize100k,
    196                      int        verbosity,
    197                      int        workFactor )
    198 {
    199    Int32   n;
    200    EState* s;
    201 
    202    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
    203 
    204    if (strm == NULL || 
    205        blockSize100k < 1 || blockSize100k > 9 ||
    206        workFactor < 0 || workFactor > 250)
    207      return BZ_PARAM_ERROR;
    208 
    209    if (workFactor == 0) workFactor = 30;
    210    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
    211    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
    212 
    213    s = BZALLOC( sizeof(EState) );
    214    if (s == NULL) return BZ_MEM_ERROR;
    215    s->strm = strm;
    216 
    217    s->arr1 = NULL;
    218    s->arr2 = NULL;
    219    s->ftab = NULL;
    220 
    221    n       = 100000 * blockSize100k;
    222    s->arr1 = BZALLOC( n                  * sizeof(UInt32) );
    223    s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
    224    s->ftab = BZALLOC( 65537              * sizeof(UInt32) );
    225 
    226    if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
    227       if (s->arr1 != NULL) BZFREE(s->arr1);
    228       if (s->arr2 != NULL) BZFREE(s->arr2);
    229       if (s->ftab != NULL) BZFREE(s->ftab);
    230       if (s       != NULL) BZFREE(s);
    231       return BZ_MEM_ERROR;
    232    }
    233 
    234    s->blockNo           = 0;
    235    s->state             = BZ_S_INPUT;
    236    s->mode              = BZ_M_RUNNING;
    237    s->combinedCRC       = 0;
    238    s->blockSize100k     = blockSize100k;
    239    s->nblockMAX         = 100000 * blockSize100k - 19;
    240    s->verbosity         = verbosity;
    241    s->workFactor        = workFactor;
    242 
    243    s->block             = (UChar*)s->arr2;
    244    s->mtfv              = (UInt16*)s->arr1;
    245    s->zbits             = NULL;
    246    s->ptr               = (UInt32*)s->arr1;
    247 
    248    strm->state          = s;
    249    strm->total_in_lo32  = 0;
    250    strm->total_in_hi32  = 0;
    251    strm->total_out_lo32 = 0;
    252    strm->total_out_hi32 = 0;
    253    init_RL ( s );
    254    prepare_new_block ( s );
    255    return BZ_OK;
    256 }
    257 
    258 
    259 /*---------------------------------------------------*/
    260 static
    261 void add_pair_to_block ( EState* s )
    262 {
    263    Int32 i;
    264    UChar ch = (UChar)(s->state_in_ch);
    265    for (i = 0; i < s->state_in_len; i++) {
    266       BZ_UPDATE_CRC( s->blockCRC, ch );
    267    }
    268    s->inUse[s->state_in_ch] = True;
    269    switch (s->state_in_len) {
    270       case 1:
    271          s->block[s->nblock] = (UChar)ch; s->nblock++;
    272          break;
    273       case 2:
    274          s->block[s->nblock] = (UChar)ch; s->nblock++;
    275          s->block[s->nblock] = (UChar)ch; s->nblock++;
    276          break;
    277       case 3:
    278          s->block[s->nblock] = (UChar)ch; s->nblock++;
    279          s->block[s->nblock] = (UChar)ch; s->nblock++;
    280          s->block[s->nblock] = (UChar)ch; s->nblock++;
    281          break;
    282       default:
    283          s->inUse[s->state_in_len-4] = True;
    284          s->block[s->nblock] = (UChar)ch; s->nblock++;
    285          s->block[s->nblock] = (UChar)ch; s->nblock++;
    286          s->block[s->nblock] = (UChar)ch; s->nblock++;
    287          s->block[s->nblock] = (UChar)ch; s->nblock++;
    288          s->block[s->nblock] = ((UChar)(s->state_in_len-4));
    289          s->nblock++;
    290          break;
    291    }
    292 }
    293 
    294 
    295 /*---------------------------------------------------*/
    296 static
    297 void flush_RL ( EState* s )
    298 {
    299    if (s->state_in_ch < 256) add_pair_to_block ( s );
    300    init_RL ( s );
    301 }
    302 
    303 
    304 /*---------------------------------------------------*/
    305 #define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
    306 {                                                 \
    307    UInt32 zchh = (UInt32)(zchh0);                 \
    308    /*-- fast track the common case --*/           \
    309    if (zchh != zs->state_in_ch &&                 \
    310        zs->state_in_len == 1) {                   \
    311       UChar ch = (UChar)(zs->state_in_ch);        \
    312       BZ_UPDATE_CRC( zs->blockCRC, ch );          \
    313       zs->inUse[zs->state_in_ch] = True;          \
    314       zs->block[zs->nblock] = (UChar)ch;          \
    315       zs->nblock++;                               \
    316       zs->state_in_ch = zchh;                     \
    317    }                                              \
    318    else                                           \
    319    /*-- general, uncommon cases --*/              \
    320    if (zchh != zs->state_in_ch ||                 \
    321       zs->state_in_len == 255) {                  \
    322       if (zs->state_in_ch < 256)                  \
    323          add_pair_to_block ( zs );                \
    324       zs->state_in_ch = zchh;                     \
    325       zs->state_in_len = 1;                       \
    326    } else {                                       \
    327       zs->state_in_len++;                         \
    328    }                                              \
    329 }
    330 
    331 
    332 /*---------------------------------------------------*/
    333 static
    334 Bool copy_input_until_stop ( EState* s )
    335 {
    336    Bool progress_in = False;
    337 
    338    if (s->mode == BZ_M_RUNNING) {
    339 
    340       /*-- fast track the common case --*/
    341       while (True) {
    342          /*-- block full? --*/
    343          if (s->nblock >= s->nblockMAX) break;
    344          /*-- no input? --*/
    345          if (s->strm->avail_in == 0) break;
    346          progress_in = True;
    347          ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
    348          s->strm->next_in++;
    349          s->strm->avail_in--;
    350          s->strm->total_in_lo32++;
    351          if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
    352       }
    353 
    354    } else {
    355 
    356       /*-- general, uncommon case --*/
    357       while (True) {
    358          /*-- block full? --*/
    359          if (s->nblock >= s->nblockMAX) break;
    360          /*-- no input? --*/
    361          if (s->strm->avail_in == 0) break;
    362          /*-- flush/finish end? --*/
    363          if (s->avail_in_expect == 0) break;
    364          progress_in = True;
    365          ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
    366          s->strm->next_in++;
    367          s->strm->avail_in--;
    368          s->strm->total_in_lo32++;
    369          if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
    370          s->avail_in_expect--;
    371       }
    372    }
    373    return progress_in;
    374 }
    375 
    376 
    377 /*---------------------------------------------------*/
    378 static
    379 Bool copy_output_until_stop ( EState* s )
    380 {
    381    Bool progress_out = False;
    382 
    383    while (True) {
    384 
    385       /*-- no output space? --*/
    386       if (s->strm->avail_out == 0) break;
    387 
    388       /*-- block done? --*/
    389       if (s->state_out_pos >= s->numZ) break;
    390 
    391       progress_out = True;
    392       *(s->strm->next_out) = s->zbits[s->state_out_pos];
    393       s->state_out_pos++;
    394       s->strm->avail_out--;
    395       s->strm->next_out++;
    396       s->strm->total_out_lo32++;
    397       if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
    398    }
    399 
    400    return progress_out;
    401 }
    402 
    403 
    404 /*---------------------------------------------------*/
    405 static
    406 Bool handle_compress ( bz_stream* strm )
    407 {
    408    Bool progress_in  = False;
    409    Bool progress_out = False;
    410    EState* s = strm->state;
    411    
    412    while (True) {
    413 
    414       if (s->state == BZ_S_OUTPUT) {
    415          progress_out |= copy_output_until_stop ( s );
    416          if (s->state_out_pos < s->numZ) break;
    417          if (s->mode == BZ_M_FINISHING && 
    418              s->avail_in_expect == 0 &&
    419              isempty_RL(s)) break;
    420          prepare_new_block ( s );
    421          s->state = BZ_S_INPUT;
    422          if (s->mode == BZ_M_FLUSHING && 
    423              s->avail_in_expect == 0 &&
    424              isempty_RL(s)) break;
    425       }
    426 
    427       if (s->state == BZ_S_INPUT) {
    428          progress_in |= copy_input_until_stop ( s );
    429          if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
    430             flush_RL ( s );
    431             BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
    432             s->state = BZ_S_OUTPUT;
    433          }
    434          else
    435          if (s->nblock >= s->nblockMAX) {
    436             BZ2_compressBlock ( s, False );
    437             s->state = BZ_S_OUTPUT;
    438          }
    439          else
    440          if (s->strm->avail_in == 0) {
    441             break;
    442          }
    443       }
    444 
    445    }
    446 
    447    return progress_in || progress_out;
    448 }
    449 
    450 
    451 /*---------------------------------------------------*/
    452 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
    453 {
    454    Bool progress;
    455    EState* s;
    456    if (strm == NULL) return BZ_PARAM_ERROR;
    457    s = strm->state;
    458    if (s == NULL) return BZ_PARAM_ERROR;
    459    if (s->strm != strm) return BZ_PARAM_ERROR;
    460 
    461    preswitch:
    462    switch (s->mode) {
    463 
    464       case BZ_M_IDLE:
    465          return BZ_SEQUENCE_ERROR;
    466 
    467       case BZ_M_RUNNING:
    468          if (action == BZ_RUN) {
    469             progress = handle_compress ( strm );
    470             return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
    471          } 
    472          else
    473 	 if (action == BZ_FLUSH) {
    474             s->avail_in_expect = strm->avail_in;
    475             s->mode = BZ_M_FLUSHING;
    476             goto preswitch;
    477          }
    478          else
    479          if (action == BZ_FINISH) {
    480             s->avail_in_expect = strm->avail_in;
    481             s->mode = BZ_M_FINISHING;
    482             goto preswitch;
    483          }
    484          else 
    485             return BZ_PARAM_ERROR;
    486 
    487       case BZ_M_FLUSHING:
    488          if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
    489          if (s->avail_in_expect != s->strm->avail_in) 
    490             return BZ_SEQUENCE_ERROR;
    491          progress = handle_compress ( strm );
    492          if (s->avail_in_expect > 0 || !isempty_RL(s) ||
    493              s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
    494          s->mode = BZ_M_RUNNING;
    495          return BZ_RUN_OK;
    496 
    497       case BZ_M_FINISHING:
    498          if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
    499          if (s->avail_in_expect != s->strm->avail_in) 
    500             return BZ_SEQUENCE_ERROR;
    501          progress = handle_compress ( strm );
    502          if (!progress) return BZ_SEQUENCE_ERROR;
    503          if (s->avail_in_expect > 0 || !isempty_RL(s) ||
    504              s->state_out_pos < s->numZ) return BZ_FINISH_OK;
    505          s->mode = BZ_M_IDLE;
    506          return BZ_STREAM_END;
    507    }
    508    return BZ_OK; /*--not reached--*/
    509 }
    510 
    511 
    512 /*---------------------------------------------------*/
    513 int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
    514 {
    515    EState* s;
    516    if (strm == NULL) return BZ_PARAM_ERROR;
    517    s = strm->state;
    518    if (s == NULL) return BZ_PARAM_ERROR;
    519    if (s->strm != strm) return BZ_PARAM_ERROR;
    520 
    521    if (s->arr1 != NULL) BZFREE(s->arr1);
    522    if (s->arr2 != NULL) BZFREE(s->arr2);
    523    if (s->ftab != NULL) BZFREE(s->ftab);
    524    BZFREE(strm->state);
    525 
    526    strm->state = NULL;   
    527 
    528    return BZ_OK;
    529 }
    530 
    531 
    532 /*---------------------------------------------------*/
    533 /*--- Decompression stuff                         ---*/
    534 /*---------------------------------------------------*/
    535 
    536 /*---------------------------------------------------*/
    537 int BZ_API(BZ2_bzDecompressInit) 
    538                      ( bz_stream* strm, 
    539                        int        verbosity,
    540                        int        small )
    541 {
    542    DState* s;
    543 
    544    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
    545 
    546    if (strm == NULL) return BZ_PARAM_ERROR;
    547    if (small != 0 && small != 1) return BZ_PARAM_ERROR;
    548    if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
    549 
    550    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
    551    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
    552 
    553    s = BZALLOC( sizeof(DState) );
    554    if (s == NULL) return BZ_MEM_ERROR;
    555    s->strm                  = strm;
    556    strm->state              = s;
    557    s->state                 = BZ_X_MAGIC_1;
    558    s->bsLive                = 0;
    559    s->bsBuff                = 0;
    560    s->calculatedCombinedCRC = 0;
    561    strm->total_in_lo32      = 0;
    562    strm->total_in_hi32      = 0;
    563    strm->total_out_lo32     = 0;
    564    strm->total_out_hi32     = 0;
    565    s->smallDecompress       = (Bool)small;
    566    s->ll4                   = NULL;
    567    s->ll16                  = NULL;
    568    s->tt                    = NULL;
    569    s->currBlockNo           = 0;
    570    s->verbosity             = verbosity;
    571 
    572    return BZ_OK;
    573 }
    574 
    575 
    576 /*---------------------------------------------------*/
    577 /* Return  True iff data corruption is discovered.
    578    Returns False if there is no problem.
    579 */
    580 static
    581 Bool 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 */
    749 static
    750 Bool 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 /*---------------------------------------------------*/
    852 int 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 /*---------------------------------------------------*/
    906 int 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 
    936 typedef 
    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 /*---------------------------------------------*/
    950 static 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 /*---------------------------------------------------*/
    960 BZFILE* 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 /*---------------------------------------------------*/
   1008 void 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 /*---------------------------------------------------*/
   1053 void 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 
   1065 void 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 /*---------------------------------------------------*/
   1131 BZFILE* 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 /*---------------------------------------------------*/
   1187 void 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 /*---------------------------------------------------*/
   1205 int 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 /*---------------------------------------------------*/
   1265 void 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 /*---------------------------------------------------*/
   1291 int 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 /*---------------------------------------------------*/
   1343 int 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 --*/
   1411 const 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
   1427 static
   1428 BZFILE * 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 --*/
   1505 BZFILE * 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 /*---------------------------------------------------*/
   1514 BZFILE * 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 /*---------------------------------------------------*/
   1523 int 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 /*---------------------------------------------------*/
   1537 int 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 /*---------------------------------------------------*/
   1551 int BZ_API(BZ2_bzflush) (BZFILE *b)
   1552 {
   1553    /* do nothing now... */
   1554    return 0;
   1555 }
   1556 
   1557 
   1558 /*---------------------------------------------------*/
   1559 void 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 --*/
   1583 static 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 
   1603 const 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 /*-------------------------------------------------------------*/