bzlib.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) 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 /*-------------------------------------------------------------*/