LLVM API Documentation

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

bzlib.c

Go to the documentation of this file.
00001 
00002 /*-------------------------------------------------------------*/
00003 /*--- Library top-level functions.                          ---*/
00004 /*---                                               bzlib.c ---*/
00005 /*-------------------------------------------------------------*/
00006 
00007 /*--
00008   This file is a part of bzip2 and/or libbzip2, a program and
00009   library for lossless, block-sorting data compression.
00010 
00011   Copyright (C) 1996-2002 Julian R Seward.  All rights reserved.
00012 
00013   Redistribution and use in source and binary forms, with or without
00014   modification, are permitted provided that the following conditions
00015   are met:
00016 
00017   1. Redistributions of source code must retain the above copyright
00018      notice, this list of conditions and the following disclaimer.
00019 
00020   2. The origin of this software must not be misrepresented; you must 
00021      not claim that you wrote the original software.  If you use this 
00022      software in a product, an acknowledgment in the product 
00023      documentation would be appreciated but is not required.
00024 
00025   3. Altered source versions must be plainly marked as such, and must
00026      not be misrepresented as being the original software.
00027 
00028   4. The name of the author may not be used to endorse or promote 
00029      products derived from this software without specific prior written 
00030      permission.
00031 
00032   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00033   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00034   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00035   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00036   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00037   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00038   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00039   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00040   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00041   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00042   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00043 
00044   Julian Seward, Cambridge, UK.
00045   jseward@acm.org
00046   bzip2/libbzip2 version 1.0 of 21 March 2000
00047 
00048   This program is based on (at least) the work of:
00049      Mike Burrows
00050      David Wheeler
00051      Peter Fenwick
00052      Alistair Moffat
00053      Radford Neal
00054      Ian H. Witten
00055      Robert Sedgewick
00056      Jon L. Bentley
00057 
00058   For more information on these sources, see the manual.
00059 --*/
00060 
00061 /*--
00062    CHANGES
00063    ~~~~~~~
00064    0.9.0 -- original version.
00065 
00066    0.9.0a/b -- no changes in this file.
00067 
00068    0.9.0c
00069       * made zero-length BZ_FLUSH work correctly in bzCompress().
00070       * fixed bzWrite/bzRead to ignore zero-length requests.
00071       * fixed bzread to correctly handle read requests after EOF.
00072       * wrong parameter order in call to bzDecompressInit in
00073         bzBuffToBuffDecompress.  Fixed.
00074 --*/
00075 
00076 #include "bzlib_private.h"
00077 
00078 
00079 /*---------------------------------------------------*/
00080 /*--- Compression stuff                           ---*/
00081 /*---------------------------------------------------*/
00082 
00083 
00084 /*---------------------------------------------------*/
00085 #ifndef BZ_NO_STDIO
00086 void BZ2_bz__AssertH__fail ( int errcode )
00087 {
00088    fprintf(stderr, 
00089       "\n\nbzip2/libbzip2: internal error number %d.\n"
00090       "This is a bug in bzip2/libbzip2, %s.\n"
00091       "Please report it to me at: jseward@acm.org.  If this happened\n"
00092       "when you were using some program which uses libbzip2 as a\n"
00093       "component, you should also report this bug to the author(s)\n"
00094       "of that program.  Please make an effort to report this bug;\n"
00095       "timely and accurate bug reports eventually lead to higher\n"
00096       "quality software.  Thanks.  Julian Seward, 30 December 2001.\n\n",
00097       errcode,
00098       BZ2_bzlibVersion()
00099    );
00100 
00101    if (errcode == 1007) {
00102    fprintf(stderr,
00103       "\n*** A special note about internal error number 1007 ***\n"
00104       "\n"
00105       "Experience suggests that a common cause of i.e. 1007\n"
00106       "is unreliable memory or other hardware.  The 1007 assertion\n"
00107       "just happens to cross-check the results of huge numbers of\n"
00108       "memory reads/writes, and so acts (unintendedly) as a stress\n"
00109       "test of your memory system.\n"
00110       "\n"
00111       "I suggest the following: try compressing the file again,\n"
00112       "possibly monitoring progress in detail with the -vv flag.\n"
00113       "\n"
00114       "* If the error cannot be reproduced, and/or happens at different\n"
00115       "  points in compression, you may have a flaky memory system.\n"
00116       "  Try a memory-test program.  I have used Memtest86\n"
00117       "  (www.memtest86.com).  At the time of writing it is free (GPLd).\n"
00118       "  Memtest86 tests memory much more thorougly than your BIOSs\n"
00119       "  power-on test, and may find failures that the BIOS doesn't.\n"
00120       "\n"
00121       "* If the error can be repeatably reproduced, this is a bug in\n"
00122       "  bzip2, and I would very much like to hear about it.  Please\n"
00123       "  let me know, and, ideally, save a copy of the file causing the\n"
00124       "  problem -- without which I will be unable to investigate it.\n"
00125       "\n"
00126    );
00127    }
00128 
00129    exit(3);
00130 }
00131 #endif
00132 
00133 
00134 /*---------------------------------------------------*/
00135 static
00136 int bz_config_ok ( void )
00137 {
00138    if (sizeof(int)   != 4) return 0;
00139    if (sizeof(short) != 2) return 0;
00140    if (sizeof(char)  != 1) return 0;
00141    return 1;
00142 }
00143 
00144 
00145 /*---------------------------------------------------*/
00146 static
00147 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
00148 {
00149    void* v = malloc ( items * size );
00150    return v;
00151 }
00152 
00153 static
00154 void default_bzfree ( void* opaque, void* addr )
00155 {
00156    if (addr != NULL) free ( addr );
00157 }
00158 
00159 
00160 /*---------------------------------------------------*/
00161 static
00162 void prepare_new_block ( EState* s )
00163 {
00164    Int32 i;
00165    s->nblock = 0;
00166    s->numZ = 0;
00167    s->state_out_pos = 0;
00168    BZ_INITIALISE_CRC ( s->blockCRC );
00169    for (i = 0; i < 256; i++) s->inUse[i] = False;
00170    s->blockNo++;
00171 }
00172 
00173 
00174 /*---------------------------------------------------*/
00175 static
00176 void init_RL ( EState* s )
00177 {
00178    s->state_in_ch  = 256;
00179    s->state_in_len = 0;
00180 }
00181 
00182 
00183 static
00184 Bool isempty_RL ( EState* s )
00185 {
00186    if (s->state_in_ch < 256 && s->state_in_len > 0)
00187       return False; else
00188       return True;
00189 }
00190 
00191 
00192 /*---------------------------------------------------*/
00193 int BZ_API(BZ2_bzCompressInit) 
00194                     ( bz_stream* strm, 
00195                      int        blockSize100k,
00196                      int        verbosity,
00197                      int        workFactor )
00198 {
00199    Int32   n;
00200    EState* s;
00201 
00202    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
00203 
00204    if (strm == NULL || 
00205        blockSize100k < 1 || blockSize100k > 9 ||
00206        workFactor < 0 || workFactor > 250)
00207      return BZ_PARAM_ERROR;
00208 
00209    if (workFactor == 0) workFactor = 30;
00210    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
00211    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
00212 
00213    s = BZALLOC( sizeof(EState) );
00214    if (s == NULL) return BZ_MEM_ERROR;
00215    s->strm = strm;
00216 
00217    s->arr1 = NULL;
00218    s->arr2 = NULL;
00219    s->ftab = NULL;
00220 
00221    n       = 100000 * blockSize100k;
00222    s->arr1 = BZALLOC( n                  * sizeof(UInt32) );
00223    s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
00224    s->ftab = BZALLOC( 65537              * sizeof(UInt32) );
00225 
00226    if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
00227       if (s->arr1 != NULL) BZFREE(s->arr1);
00228       if (s->arr2 != NULL) BZFREE(s->arr2);
00229       if (s->ftab != NULL) BZFREE(s->ftab);
00230       if (s       != NULL) BZFREE(s);
00231       return BZ_MEM_ERROR;
00232    }
00233 
00234    s->blockNo           = 0;
00235    s->state             = BZ_S_INPUT;
00236    s->mode              = BZ_M_RUNNING;
00237    s->combinedCRC       = 0;
00238    s->blockSize100k     = blockSize100k;
00239    s->nblockMAX         = 100000 * blockSize100k - 19;
00240    s->verbosity         = verbosity;
00241    s->workFactor        = workFactor;
00242 
00243    s->block             = (UChar*)s->arr2;
00244    s->mtfv              = (UInt16*)s->arr1;
00245    s->zbits             = NULL;
00246    s->ptr               = (UInt32*)s->arr1;
00247 
00248    strm->state          = s;
00249    strm->total_in_lo32  = 0;
00250    strm->total_in_hi32  = 0;
00251    strm->total_out_lo32 = 0;
00252    strm->total_out_hi32 = 0;
00253    init_RL ( s );
00254    prepare_new_block ( s );
00255    return BZ_OK;
00256 }
00257 
00258 
00259 /*---------------------------------------------------*/
00260 static
00261 void add_pair_to_block ( EState* s )
00262 {
00263    Int32 i;
00264    UChar ch = (UChar)(s->state_in_ch);
00265    for (i = 0; i < s->state_in_len; i++) {
00266       BZ_UPDATE_CRC( s->blockCRC, ch );
00267    }
00268    s->inUse[s->state_in_ch] = True;
00269    switch (s->state_in_len) {
00270       case 1:
00271          s->block[s->nblock] = (UChar)ch; s->nblock++;
00272          break;
00273       case 2:
00274          s->block[s->nblock] = (UChar)ch; s->nblock++;
00275          s->block[s->nblock] = (UChar)ch; s->nblock++;
00276          break;
00277       case 3:
00278          s->block[s->nblock] = (UChar)ch; s->nblock++;
00279          s->block[s->nblock] = (UChar)ch; s->nblock++;
00280          s->block[s->nblock] = (UChar)ch; s->nblock++;
00281          break;
00282       default:
00283          s->inUse[s->state_in_len-4] = True;
00284          s->block[s->nblock] = (UChar)ch; s->nblock++;
00285          s->block[s->nblock] = (UChar)ch; s->nblock++;
00286          s->block[s->nblock] = (UChar)ch; s->nblock++;
00287          s->block[s->nblock] = (UChar)ch; s->nblock++;
00288          s->block[s->nblock] = ((UChar)(s->state_in_len-4));
00289          s->nblock++;
00290          break;
00291    }
00292 }
00293 
00294 
00295 /*---------------------------------------------------*/
00296 static
00297 void flush_RL ( EState* s )
00298 {
00299    if (s->state_in_ch < 256) add_pair_to_block ( s );
00300    init_RL ( s );
00301 }
00302 
00303 
00304 /*---------------------------------------------------*/
00305 #define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
00306 {                                                 \
00307    UInt32 zchh = (UInt32)(zchh0);                 \
00308    /*-- fast track the common case --*/           \
00309    if (zchh != zs->state_in_ch &&                 \
00310        zs->state_in_len == 1) {                   \
00311       UChar ch = (UChar)(zs->state_in_ch);        \
00312       BZ_UPDATE_CRC( zs->blockCRC, ch );          \
00313       zs->inUse[zs->state_in_ch] = True;          \
00314       zs->block[zs->nblock] = (UChar)ch;          \
00315       zs->nblock++;                               \
00316       zs->state_in_ch = zchh;                     \
00317    }                                              \
00318    else                                           \
00319    /*-- general, uncommon cases --*/              \
00320    if (zchh != zs->state_in_ch ||                 \
00321       zs->state_in_len == 255) {                  \
00322       if (zs->state_in_ch < 256)                  \
00323          add_pair_to_block ( zs );                \
00324       zs->state_in_ch = zchh;                     \
00325       zs->state_in_len = 1;                       \
00326    } else {                                       \
00327       zs->state_in_len++;                         \
00328    }                                              \
00329 }
00330 
00331 
00332 /*---------------------------------------------------*/
00333 static
00334 Bool copy_input_until_stop ( EState* s )
00335 {
00336    Bool progress_in = False;
00337 
00338    if (s->mode == BZ_M_RUNNING) {
00339 
00340       /*-- fast track the common case --*/
00341       while (True) {
00342          /*-- block full? --*/
00343          if (s->nblock >= s->nblockMAX) break;
00344          /*-- no input? --*/
00345          if (s->strm->avail_in == 0) break;
00346          progress_in = True;
00347          ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
00348          s->strm->next_in++;
00349          s->strm->avail_in--;
00350          s->strm->total_in_lo32++;
00351          if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
00352       }
00353 
00354    } else {
00355 
00356       /*-- general, uncommon case --*/
00357       while (True) {
00358          /*-- block full? --*/
00359          if (s->nblock >= s->nblockMAX) break;
00360          /*-- no input? --*/
00361          if (s->strm->avail_in == 0) break;
00362          /*-- flush/finish end? --*/
00363          if (s->avail_in_expect == 0) break;
00364          progress_in = True;
00365          ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
00366          s->strm->next_in++;
00367          s->strm->avail_in--;
00368          s->strm->total_in_lo32++;
00369          if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
00370          s->avail_in_expect--;
00371       }
00372    }
00373    return progress_in;
00374 }
00375 
00376 
00377 /*---------------------------------------------------*/
00378 static
00379 Bool copy_output_until_stop ( EState* s )
00380 {
00381    Bool progress_out = False;
00382 
00383    while (True) {
00384 
00385       /*-- no output space? --*/
00386       if (s->strm->avail_out == 0) break;
00387 
00388       /*-- block done? --*/
00389       if (s->state_out_pos >= s->numZ) break;
00390 
00391       progress_out = True;
00392       *(s->strm->next_out) = s->zbits[s->state_out_pos];
00393       s->state_out_pos++;
00394       s->strm->avail_out--;
00395       s->strm->next_out++;
00396       s->strm->total_out_lo32++;
00397       if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
00398    }
00399 
00400    return progress_out;
00401 }
00402 
00403 
00404 /*---------------------------------------------------*/
00405 static
00406 Bool handle_compress ( bz_stream* strm )
00407 {
00408    Bool progress_in  = False;
00409    Bool progress_out = False;
00410    EState* s = strm->state;
00411    
00412    while (True) {
00413 
00414       if (s->state == BZ_S_OUTPUT) {
00415          progress_out |= copy_output_until_stop ( s );
00416          if (s->state_out_pos < s->numZ) break;
00417          if (s->mode == BZ_M_FINISHING && 
00418              s->avail_in_expect == 0 &&
00419              isempty_RL(s)) break;
00420          prepare_new_block ( s );
00421          s->state = BZ_S_INPUT;
00422          if (s->mode == BZ_M_FLUSHING && 
00423              s->avail_in_expect == 0 &&
00424              isempty_RL(s)) break;
00425       }
00426 
00427       if (s->state == BZ_S_INPUT) {
00428          progress_in |= copy_input_until_stop ( s );
00429          if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
00430             flush_RL ( s );
00431             BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
00432             s->state = BZ_S_OUTPUT;
00433          }
00434          else
00435          if (s->nblock >= s->nblockMAX) {
00436             BZ2_compressBlock ( s, False );
00437             s->state = BZ_S_OUTPUT;
00438          }
00439          else
00440          if (s->strm->avail_in == 0) {
00441             break;
00442          }
00443       }
00444 
00445    }
00446 
00447    return progress_in || progress_out;
00448 }
00449 
00450 
00451 /*---------------------------------------------------*/
00452 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
00453 {
00454    Bool progress;
00455    EState* s;
00456    if (strm == NULL) return BZ_PARAM_ERROR;
00457    s = strm->state;
00458    if (s == NULL) return BZ_PARAM_ERROR;
00459    if (s->strm != strm) return BZ_PARAM_ERROR;
00460 
00461    preswitch:
00462    switch (s->mode) {
00463 
00464       case BZ_M_IDLE:
00465          return BZ_SEQUENCE_ERROR;
00466 
00467       case BZ_M_RUNNING:
00468          if (action == BZ_RUN) {
00469             progress = handle_compress ( strm );
00470             return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
00471          } 
00472          else
00473    if (action == BZ_FLUSH) {
00474             s->avail_in_expect = strm->avail_in;
00475             s->mode = BZ_M_FLUSHING;
00476             goto preswitch;
00477          }
00478          else
00479          if (action == BZ_FINISH) {
00480             s->avail_in_expect = strm->avail_in;
00481             s->mode = BZ_M_FINISHING;
00482             goto preswitch;
00483          }
00484          else 
00485             return BZ_PARAM_ERROR;
00486 
00487       case BZ_M_FLUSHING:
00488          if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
00489          if (s->avail_in_expect != s->strm->avail_in) 
00490             return BZ_SEQUENCE_ERROR;
00491          progress = handle_compress ( strm );
00492          if (s->avail_in_expect > 0 || !isempty_RL(s) ||
00493              s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
00494          s->mode = BZ_M_RUNNING;
00495          return BZ_RUN_OK;
00496 
00497       case BZ_M_FINISHING:
00498          if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
00499          if (s->avail_in_expect != s->strm->avail_in) 
00500             return BZ_SEQUENCE_ERROR;
00501          progress = handle_compress ( strm );
00502          if (!progress) return BZ_SEQUENCE_ERROR;
00503          if (s->avail_in_expect > 0 || !isempty_RL(s) ||
00504              s->state_out_pos < s->numZ) return BZ_FINISH_OK;
00505          s->mode = BZ_M_IDLE;
00506          return BZ_STREAM_END;
00507    }
00508    return BZ_OK; /*--not reached--*/
00509 }
00510 
00511 
00512 /*---------------------------------------------------*/
00513 int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
00514 {
00515    EState* s;
00516    if (strm == NULL) return BZ_PARAM_ERROR;
00517    s = strm->state;
00518    if (s == NULL) return BZ_PARAM_ERROR;
00519    if (s->strm != strm) return BZ_PARAM_ERROR;
00520 
00521    if (s->arr1 != NULL) BZFREE(s->arr1);
00522    if (s->arr2 != NULL) BZFREE(s->arr2);
00523    if (s->ftab != NULL) BZFREE(s->ftab);
00524    BZFREE(strm->state);
00525 
00526    strm->state = NULL;   
00527 
00528    return BZ_OK;
00529 }
00530 
00531 
00532 /*---------------------------------------------------*/
00533 /*--- Decompression stuff                         ---*/
00534 /*---------------------------------------------------*/
00535 
00536 /*---------------------------------------------------*/
00537 int BZ_API(BZ2_bzDecompressInit) 
00538                      ( bz_stream* strm, 
00539                        int        verbosity,
00540                        int        small )
00541 {
00542    DState* s;
00543 
00544    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
00545 
00546    if (strm == NULL) return BZ_PARAM_ERROR;
00547    if (small != 0 && small != 1) return BZ_PARAM_ERROR;
00548    if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
00549 
00550    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
00551    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
00552 
00553    s = BZALLOC( sizeof(DState) );
00554    if (s == NULL) return BZ_MEM_ERROR;
00555    s->strm                  = strm;
00556    strm->state              = s;
00557    s->state                 = BZ_X_MAGIC_1;
00558    s->bsLive                = 0;
00559    s->bsBuff                = 0;
00560    s->calculatedCombinedCRC = 0;
00561    strm->total_in_lo32      = 0;
00562    strm->total_in_hi32      = 0;
00563    strm->total_out_lo32     = 0;
00564    strm->total_out_hi32     = 0;
00565    s->smallDecompress       = (Bool)small;
00566    s->ll4                   = NULL;
00567    s->ll16                  = NULL;
00568    s->tt                    = NULL;
00569    s->currBlockNo           = 0;
00570    s->verbosity             = verbosity;
00571 
00572    return BZ_OK;
00573 }
00574 
00575 
00576 /*---------------------------------------------------*/
00577 static
00578 void unRLE_obuf_to_output_FAST ( DState* s )
00579 {
00580    UChar k1;
00581 
00582    if (s->blockRandomised) {
00583 
00584       while (True) {
00585          /* try to finish existing run */
00586          while (True) {
00587             if (s->strm->avail_out == 0) return;
00588             if (s->state_out_len == 0) break;
00589             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
00590             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
00591             s->state_out_len--;
00592             s->strm->next_out++;
00593             s->strm->avail_out--;
00594             s->strm->total_out_lo32++;
00595             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
00596          }
00597    
00598          /* can a new run be started? */
00599          if (s->nblock_used == s->save_nblock+1) return;
00600                
00601    
00602          s->state_out_len = 1;
00603          s->state_out_ch = s->k0;
00604          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
00605          k1 ^= BZ_RAND_MASK; s->nblock_used++;
00606          if (s->nblock_used == s->save_nblock+1) continue;
00607          if (k1 != s->k0) { s->k0 = k1; continue; };
00608    
00609          s->state_out_len = 2;
00610          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
00611          k1 ^= BZ_RAND_MASK; s->nblock_used++;
00612          if (s->nblock_used == s->save_nblock+1) continue;
00613          if (k1 != s->k0) { s->k0 = k1; continue; };
00614    
00615          s->state_out_len = 3;
00616          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
00617          k1 ^= BZ_RAND_MASK; s->nblock_used++;
00618          if (s->nblock_used == s->save_nblock+1) continue;
00619          if (k1 != s->k0) { s->k0 = k1; continue; };
00620    
00621          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
00622          k1 ^= BZ_RAND_MASK; s->nblock_used++;
00623          s->state_out_len = ((Int32)k1) + 4;
00624          BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; 
00625          s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
00626       }
00627 
00628    } else {
00629 
00630       /* restore */
00631       UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC;
00632       UChar         c_state_out_ch       = s->state_out_ch;
00633       Int32         c_state_out_len      = s->state_out_len;
00634       Int32         c_nblock_used        = s->nblock_used;
00635       Int32         c_k0                 = s->k0;
00636       UInt32*       c_tt                 = s->tt;
00637       UInt32        c_tPos               = s->tPos;
00638       char*         cs_next_out          = s->strm->next_out;
00639       unsigned int  cs_avail_out         = s->strm->avail_out;
00640       /* end restore */
00641 
00642       UInt32       avail_out_INIT = cs_avail_out;
00643       Int32        s_save_nblockPP = s->save_nblock+1;
00644       unsigned int total_out_lo32_old;
00645 
00646       while (True) {
00647 
00648          /* try to finish existing run */
00649          if (c_state_out_len > 0) {
00650             while (True) {
00651                if (cs_avail_out == 0) goto return_notr;
00652                if (c_state_out_len == 1) break;
00653                *( (UChar*)(cs_next_out) ) = c_state_out_ch;
00654                BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
00655                c_state_out_len--;
00656                cs_next_out++;
00657                cs_avail_out--;
00658             }
00659             s_state_out_len_eq_one:
00660             {
00661                if (cs_avail_out == 0) { 
00662                   c_state_out_len = 1; goto return_notr;
00663                };
00664                *( (UChar*)(cs_next_out) ) = c_state_out_ch;
00665                BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
00666                cs_next_out++;
00667                cs_avail_out--;
00668             }
00669          }   
00670          /* can a new run be started? */
00671          if (c_nblock_used == s_save_nblockPP) {
00672             c_state_out_len = 0; goto return_notr;
00673          };   
00674          c_state_out_ch = c_k0;
00675          BZ_GET_FAST_C(k1); c_nblock_used++;
00676          if (k1 != c_k0) { 
00677             c_k0 = k1; goto s_state_out_len_eq_one; 
00678          };
00679          if (c_nblock_used == s_save_nblockPP) 
00680             goto s_state_out_len_eq_one;
00681    
00682          c_state_out_len = 2;
00683          BZ_GET_FAST_C(k1); c_nblock_used++;
00684          if (c_nblock_used == s_save_nblockPP) continue;
00685          if (k1 != c_k0) { c_k0 = k1; continue; };
00686    
00687          c_state_out_len = 3;
00688          BZ_GET_FAST_C(k1); c_nblock_used++;
00689          if (c_nblock_used == s_save_nblockPP) continue;
00690          if (k1 != c_k0) { c_k0 = k1; continue; };
00691    
00692          BZ_GET_FAST_C(k1); c_nblock_used++;
00693          c_state_out_len = ((Int32)k1) + 4;
00694          BZ_GET_FAST_C(c_k0); c_nblock_used++;
00695       }
00696 
00697       return_notr:
00698       total_out_lo32_old = s->strm->total_out_lo32;
00699       s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
00700       if (s->strm->total_out_lo32 < total_out_lo32_old)
00701          s->strm->total_out_hi32++;
00702 
00703       /* save */
00704       s->calculatedBlockCRC = c_calculatedBlockCRC;
00705       s->state_out_ch       = c_state_out_ch;
00706       s->state_out_len      = c_state_out_len;
00707       s->nblock_used        = c_nblock_used;
00708       s->k0                 = c_k0;
00709       s->tt                 = c_tt;
00710       s->tPos               = c_tPos;
00711       s->strm->next_out     = cs_next_out;
00712       s->strm->avail_out    = cs_avail_out;
00713       /* end save */
00714    }
00715 }
00716 
00717 
00718 
00719 /*---------------------------------------------------*/
00720 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
00721 {
00722    Int32 nb, na, mid;
00723    nb = 0;
00724    na = 256;
00725    do {
00726       mid = (nb + na) >> 1;
00727       if (indx >= cftab[mid]) nb = mid; else na = mid;
00728    }
00729    while (na - nb != 1);
00730    return nb;
00731 }
00732 
00733 
00734 /*---------------------------------------------------*/
00735 static
00736 void unRLE_obuf_to_output_SMALL ( DState* s )
00737 {
00738    UChar k1;
00739 
00740    if (s->blockRandomised) {
00741 
00742       while (True) {
00743          /* try to finish existing run */
00744          while (True) {
00745             if (s->strm->avail_out == 0) return;
00746             if (s->state_out_len == 0) break;
00747             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
00748             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
00749             s->state_out_len--;
00750             s->strm->next_out++;
00751             s->strm->avail_out--;
00752             s->strm->total_out_lo32++;
00753             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
00754          }
00755    
00756          /* can a new run be started? */
00757          if (s->nblock_used == s->save_nblock+1) return;
00758                
00759    
00760          s->state_out_len = 1;
00761          s->state_out_ch = s->k0;
00762          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
00763          k1 ^= BZ_RAND_MASK; s->nblock_used++;
00764          if (s->nblock_used == s->save_nblock+1) continue;
00765          if (k1 != s->k0) { s->k0 = k1; continue; };
00766    
00767          s->state_out_len = 2;
00768          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
00769          k1 ^= BZ_RAND_MASK; s->nblock_used++;
00770          if (s->nblock_used == s->save_nblock+1) continue;
00771          if (k1 != s->k0) { s->k0 = k1; continue; };
00772    
00773          s->state_out_len = 3;
00774          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
00775          k1 ^= BZ_RAND_MASK; s->nblock_used++;
00776          if (s->nblock_used == s->save_nblock+1) continue;
00777          if (k1 != s->k0) { s->k0 = k1; continue; };
00778    
00779          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
00780          k1 ^= BZ_RAND_MASK; s->nblock_used++;
00781          s->state_out_len = ((Int32)k1) + 4;
00782          BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; 
00783          s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
00784       }
00785 
00786    } else {
00787 
00788       while (True) {
00789          /* try to finish existing run */
00790          while (True) {
00791             if (s->strm->avail_out == 0) return;
00792             if (s->state_out_len == 0) break;
00793             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
00794             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
00795             s->state_out_len--;
00796             s->strm->next_out++;
00797             s->strm->avail_out--;
00798             s->strm->total_out_lo32++;
00799             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
00800          }
00801    
00802          /* can a new run be started? */
00803          if (s->nblock_used == s->save_nblock+1) return;
00804    
00805          s->state_out_len = 1;
00806          s->state_out_ch = s->k0;
00807          BZ_GET_SMALL(k1); s->nblock_used++;
00808          if (s->nblock_used == s->save_nblock+1) continue;
00809          if (k1 != s->k0) { s->k0 = k1; continue; };
00810    
00811          s->state_out_len = 2;
00812          BZ_GET_SMALL(k1); s->nblock_used++;
00813          if (s->nblock_used == s->save_nblock+1) continue;
00814          if (k1 != s->k0) { s->k0 = k1; continue; };
00815    
00816          s->state_out_len = 3;
00817          BZ_GET_SMALL(k1); s->nblock_used++;
00818          if (s->nblock_used == s->save_nblock+1) continue;
00819          if (k1 != s->k0) { s->k0 = k1; continue; };
00820    
00821          BZ_GET_SMALL(k1); s->nblock_used++;
00822          s->state_out_len = ((Int32)k1) + 4;
00823          BZ_GET_SMALL(s->k0); s->nblock_used++;
00824       }
00825 
00826    }
00827 }
00828 
00829 
00830 /*---------------------------------------------------*/
00831 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
00832 {
00833    DState* s;
00834    if (strm == NULL) return BZ_PARAM_ERROR;
00835    s = strm->state;
00836    if (s == NULL) return BZ_PARAM_ERROR;
00837    if (s->strm != strm) return BZ_PARAM_ERROR;
00838 
00839    while (True) {
00840       if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
00841       if (s->state == BZ_X_OUTPUT) {
00842          if (s->smallDecompress)
00843             unRLE_obuf_to_output_SMALL ( s ); else
00844             unRLE_obuf_to_output_FAST  ( s );
00845          if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
00846             BZ_FINALISE_CRC ( s->calculatedBlockCRC );
00847             if (s->verbosity >= 3) 
00848                VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC, 
00849                           s->calculatedBlockCRC );
00850             if (s->verbosity >= 2) VPrintf0 ( "]" );
00851             if (s->calculatedBlockCRC != s->storedBlockCRC)
00852                return BZ_DATA_ERROR;
00853             s->calculatedCombinedCRC 
00854                = (s->calculatedCombinedCRC << 1) | 
00855                     (s->calculatedCombinedCRC >> 31);
00856             s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
00857             s->state = BZ_X_BLKHDR_1;
00858          } else {
00859             return BZ_OK;
00860          }
00861       }
00862       if (s->state >= BZ_X_MAGIC_1) {
00863          Int32 r = BZ2_decompress ( s );
00864          if (r == BZ_STREAM_END) {
00865             if (s->verbosity >= 3)
00866                VPrintf2 ( "\n    combined CRCs: stored = 0x%x, computed = 0x%x", 
00867                           s->storedCombinedCRC, s->calculatedCombinedCRC );
00868             if (s->calculatedCombinedCRC != s->storedCombinedCRC)
00869                return BZ_DATA_ERROR;
00870             return r;
00871          }
00872          if (s->state != BZ_X_OUTPUT) return r;
00873       }
00874    }
00875 
00876    AssertH ( 0, 6001 );
00877 
00878    return 0;  /*NOTREACHED*/
00879 }
00880 
00881 
00882 /*---------------------------------------------------*/
00883 int BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm )
00884 {
00885    DState* s;
00886    if (strm == NULL) return BZ_PARAM_ERROR;
00887    s = strm->state;
00888    if (s == NULL) return BZ_PARAM_ERROR;
00889    if (s->strm != strm) return BZ_PARAM_ERROR;
00890 
00891    if (s->tt   != NULL) BZFREE(s->tt);
00892    if (s->ll16 != NULL) BZFREE(s->ll16);
00893    if (s->ll4  != NULL) BZFREE(s->ll4);
00894 
00895    BZFREE(strm->state);
00896    strm->state = NULL;
00897 
00898    return BZ_OK;
00899 }
00900 
00901 
00902 #ifndef BZ_NO_STDIO
00903 /*---------------------------------------------------*/
00904 /*--- File I/O stuff                              ---*/
00905 /*---------------------------------------------------*/
00906 
00907 #define BZ_SETERR(eee)                    \
00908 {                                         \
00909    if (bzerror != NULL) *bzerror = eee;   \
00910    if (bzf != NULL) bzf->lastErr = eee;   \
00911 }
00912 
00913 typedef 
00914    struct {
00915       FILE*     handle;
00916       Char      buf[BZ_MAX_UNUSED];
00917       Int32     bufN;
00918       Bool      writing;
00919       bz_stream strm;
00920       Int32     lastErr;
00921       Bool      initialisedOk;
00922    }
00923    bzFile;
00924 
00925 
00926 /*---------------------------------------------*/
00927 static Bool myfeof ( FILE* f )
00928 {
00929    Int32 c = fgetc ( f );
00930    if (c == EOF) return True;
00931    ungetc ( c, f );
00932    return False;
00933 }
00934 
00935 
00936 /*---------------------------------------------------*/
00937 BZFILE* BZ_API(BZ2_bzWriteOpen) 
00938                     ( int*  bzerror,      
00939                       FILE* f, 
00940                       int   blockSize100k, 
00941                       int   verbosity,
00942                       int   workFactor )
00943 {
00944    Int32   ret;
00945    bzFile* bzf = NULL;
00946 
00947    BZ_SETERR(BZ_OK);
00948 
00949    if (f == NULL ||
00950        (blockSize100k < 1 || blockSize100k > 9) ||
00951        (workFactor < 0 || workFactor > 250) ||
00952        (verbosity < 0 || verbosity > 4))
00953       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
00954 
00955    if (ferror(f))
00956       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
00957 
00958    bzf = malloc ( sizeof(bzFile) );
00959    if (bzf == NULL)
00960       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
00961 
00962    BZ_SETERR(BZ_OK);
00963    bzf->initialisedOk = False;
00964    bzf->bufN          = 0;
00965    bzf->handle        = f;
00966    bzf->writing       = True;
00967    bzf->strm.bzalloc  = NULL;
00968    bzf->strm.bzfree   = NULL;
00969    bzf->strm.opaque   = NULL;
00970 
00971    if (workFactor == 0) workFactor = 30;
00972    ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, 
00973                               verbosity, workFactor );
00974    if (ret != BZ_OK)
00975       { BZ_SETERR(ret); free(bzf); return NULL; };
00976 
00977    bzf->strm.avail_in = 0;
00978    bzf->initialisedOk = True;
00979    return bzf;   
00980 }
00981 
00982 
00983 
00984 /*---------------------------------------------------*/
00985 void BZ_API(BZ2_bzWrite)
00986              ( int*    bzerror, 
00987                BZFILE* b, 
00988                void*   buf, 
00989                int     len )
00990 {
00991    Int32 n, n2, ret;
00992    bzFile* bzf = (bzFile*)b;
00993 
00994    BZ_SETERR(BZ_OK);
00995    if (bzf == NULL || buf == NULL || len < 0)
00996       { BZ_SETERR(BZ_PARAM_ERROR); return; };
00997    if (!(bzf->writing))
00998       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
00999    if (ferror(bzf->handle))
01000       { BZ_SETERR(BZ_IO_ERROR); return; };
01001 
01002    if (len == 0)
01003       { BZ_SETERR(BZ_OK); return; };
01004 
01005    bzf->strm.avail_in = len;
01006    bzf->strm.next_in  = buf;
01007 
01008    while (True) {
01009       bzf->strm.avail_out = BZ_MAX_UNUSED;
01010       bzf->strm.next_out = bzf->buf;
01011       ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
01012       if (ret != BZ_RUN_OK)
01013          { BZ_SETERR(ret); return; };
01014 
01015       if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
01016          n = BZ_MAX_UNUSED - bzf->strm.avail_out;
01017          n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
01018                        n, bzf->handle );
01019          if (n != n2 || ferror(bzf->handle))
01020             { BZ_SETERR(BZ_IO_ERROR); return; };
01021       }
01022 
01023       if (bzf->strm.avail_in == 0)
01024          { BZ_SETERR(BZ_OK); return; };
01025    }
01026 }
01027 
01028 
01029 /*---------------------------------------------------*/
01030 void BZ_API(BZ2_bzWriteClose)
01031                   ( int*          bzerror, 
01032                     BZFILE*       b, 
01033                     int           abandon,
01034                     unsigned int* nbytes_in,
01035                     unsigned int* nbytes_out )
01036 {
01037    BZ2_bzWriteClose64 ( bzerror, b, abandon, 
01038                         nbytes_in, NULL, nbytes_out, NULL );
01039 }
01040 
01041 
01042 void BZ_API(BZ2_bzWriteClose64)
01043                   ( int*          bzerror, 
01044                     BZFILE*       b, 
01045                     int           abandon,
01046                     unsigned int* nbytes_in_lo32,
01047                     unsigned int* nbytes_in_hi32,
01048                     unsigned int* nbytes_out_lo32,
01049                     unsigned int* nbytes_out_hi32 )
01050 {
01051    Int32   n, n2, ret;
01052    bzFile* bzf = (bzFile*)b;
01053 
01054    if (bzf == NULL)
01055       { BZ_SETERR(BZ_OK); return; };
01056    if (!(bzf->writing))
01057       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
01058    if (ferror(bzf->handle))
01059       { BZ_SETERR(BZ_IO_ERROR); return; };
01060 
01061    if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
01062    if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
01063    if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
01064    if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
01065 
01066    if ((!abandon) && bzf->lastErr == BZ_OK) {
01067       while (True) {
01068          bzf->strm.avail_out = BZ_MAX_UNUSED;
01069          bzf->strm.next_out = bzf->buf;
01070          ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
01071          if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
01072             { BZ_SETERR(ret); return; };
01073 
01074          if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
01075             n = BZ_MAX_UNUSED - bzf->strm.avail_out;
01076             n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
01077                           n, bzf->handle );
01078             if (n != n2 || ferror(bzf->handle))
01079                { BZ_SETERR(BZ_IO_ERROR); return; };
01080          }
01081 
01082          if (ret == BZ_STREAM_END) break;
01083       }
01084    }
01085 
01086    if ( !abandon && !ferror ( bzf->handle ) ) {
01087       fflush ( bzf->handle );
01088       if (ferror(bzf->handle))
01089          { BZ_SETERR(BZ_IO_ERROR); return; };
01090    }
01091 
01092    if (nbytes_in_lo32 != NULL)
01093       *nbytes_in_lo32 = bzf->strm.total_in_lo32;
01094    if (nbytes_in_hi32 != NULL)
01095       *nbytes_in_hi32 = bzf->strm.total_in_hi32;
01096    if (nbytes_out_lo32 != NULL)
01097       *nbytes_out_lo32 = bzf->strm.total_out_lo32;
01098    if (nbytes_out_hi32 != NULL)
01099       *nbytes_out_hi32 = bzf->strm.total_out_hi32;
01100 
01101    BZ_SETERR(BZ_OK);
01102    BZ2_bzCompressEnd ( &(bzf->strm) );
01103    free ( bzf );
01104 }
01105 
01106 
01107 /*---------------------------------------------------*/
01108 BZFILE* BZ_API(BZ2_bzReadOpen) 
01109                    ( int*  bzerror, 
01110                      FILE* f, 
01111                      int   verbosity,
01112                      int   small,
01113                      void* unused,
01114                      int   nUnused )
01115 {
01116    bzFile* bzf = NULL;
01117    int     ret;
01118 
01119    BZ_SETERR(BZ_OK);
01120 
01121    if (f == NULL || 
01122        (small != 0 && small != 1) ||
01123        (verbosity < 0 || verbosity > 4) ||
01124        (unused == NULL && nUnused != 0) ||
01125        (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
01126       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
01127 
01128    if (ferror(f))
01129       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
01130 
01131    bzf = malloc ( sizeof(bzFile) );
01132    if (bzf == NULL) 
01133       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
01134 
01135    BZ_SETERR(BZ_OK);
01136 
01137    bzf->initialisedOk = False;
01138    bzf->handle        = f;
01139    bzf->bufN          = 0;
01140    bzf->writing       = False;
01141    bzf->strm.bzalloc  = NULL;
01142    bzf->strm.bzfree   = NULL;
01143    bzf->strm.opaque   = NULL;
01144    
01145    while (nUnused > 0) {
01146       bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
01147       unused = ((void*)( 1 + ((UChar*)(unused))  ));
01148       nUnused--;
01149    }
01150 
01151    ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
01152    if (ret != BZ_OK)
01153       { BZ_SETERR(ret); free(bzf); return NULL; };
01154 
01155    bzf->strm.avail_in = bzf->bufN;
01156    bzf->strm.next_in  = bzf->buf;
01157 
01158    bzf->initialisedOk = True;
01159    return bzf;   
01160 }
01161 
01162 
01163 /*---------------------------------------------------*/
01164 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
01165 {
01166    bzFile* bzf = (bzFile*)b;
01167 
01168    BZ_SETERR(BZ_OK);
01169    if (bzf == NULL)
01170       { BZ_SETERR(BZ_OK); return; };
01171 
01172    if (bzf->writing)
01173       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
01174 
01175    if (bzf->initialisedOk)
01176       (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
01177    free ( bzf );
01178 }
01179 
01180 
01181 /*---------------------------------------------------*/
01182 int BZ_API(BZ2_bzRead) 
01183            ( int*    bzerror, 
01184              BZFILE* b, 
01185              void*   buf, 
01186              int     len )
01187 {
01188    Int32   n, ret;
01189    bzFile* bzf = (bzFile*)b;
01190 
01191    BZ_SETERR(BZ_OK);
01192 
01193    if (bzf == NULL || buf == NULL || len < 0)
01194       { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
01195 
01196    if (bzf->writing)
01197       { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
01198 
01199    if (len == 0)
01200       { BZ_SETERR(BZ_OK); return 0; };
01201 
01202    bzf->strm.avail_out = len;
01203    bzf->strm.next_out = buf;
01204 
01205    while (True) {
01206 
01207       if (ferror(bzf->handle)) 
01208          { BZ_SETERR(BZ_IO_ERROR); return 0; };
01209 
01210       if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
01211          n = fread ( bzf->buf, sizeof(UChar), 
01212                      BZ_MAX_UNUSED, bzf->handle );
01213          if (ferror(bzf->handle))
01214             { BZ_SETERR(BZ_IO_ERROR); return 0; };
01215          bzf->bufN = n;
01216          bzf->strm.avail_in = bzf->bufN;
01217          bzf->strm.next_in = bzf->buf;
01218       }
01219 
01220       ret = BZ2_bzDecompress ( &(bzf->strm) );
01221 
01222       if (ret != BZ_OK && ret != BZ_STREAM_END)
01223          { BZ_SETERR(ret); return 0; };
01224 
01225       if (ret == BZ_OK && myfeof(bzf->handle) && 
01226           bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
01227          { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
01228 
01229       if (ret == BZ_STREAM_END)
01230          { BZ_SETERR(BZ_STREAM_END);
01231            return len - bzf->strm.avail_out; };
01232       if (bzf->strm.avail_out == 0)
01233          { BZ_SETERR(BZ_OK); return len; };
01234       
01235    }
01236 
01237    return 0; /*not reached*/
01238 }
01239 
01240 
01241 /*---------------------------------------------------*/
01242 void BZ_API(BZ2_bzReadGetUnused) 
01243                      ( int*    bzerror, 
01244                        BZFILE* b, 
01245                        void**  unused, 
01246                        int*    nUnused )
01247 {
01248    bzFile* bzf = (bzFile*)b;
01249    if (bzf == NULL)
01250       { BZ_SETERR(BZ_PARAM_ERROR); return; };
01251    if (bzf->lastErr != BZ_STREAM_END)
01252       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
01253    if (unused == NULL || nUnused == NULL)
01254       { BZ_SETERR(BZ_PARAM_ERROR); return; };
01255 
01256    BZ_SETERR(BZ_OK);
01257    *nUnused = bzf->strm.avail_in;
01258    *unused = bzf->strm.next_in;
01259 }
01260 #endif
01261 
01262 
01263 /*---------------------------------------------------*/
01264 /*--- Misc convenience stuff                      ---*/
01265 /*---------------------------------------------------*/
01266 
01267 /*---------------------------------------------------*/
01268 int BZ_API(BZ2_bzBuffToBuffCompress) 
01269                          ( char*         dest, 
01270                            unsigned int* destLen,
01271                            char*         source, 
01272                            unsigned int  sourceLen,
01273                            int           blockSize100k, 
01274                            int           verbosity, 
01275                            int           workFactor )
01276 {
01277    bz_stream strm;
01278    int ret;
01279 
01280    if (dest == NULL || destLen == NULL || 
01281        source == NULL ||
01282        blockSize100k < 1 || blockSize100k > 9 ||
01283        verbosity < 0 || verbosity > 4 ||
01284        workFactor < 0 || workFactor > 250) 
01285       return BZ_PARAM_ERROR;
01286 
01287    if (workFactor == 0) workFactor = 30;
01288    strm.bzalloc = NULL;
01289    strm.bzfree = NULL;
01290    strm.opaque = NULL;
01291    ret = BZ2_bzCompressInit ( &strm, blockSize100k, 
01292                               verbosity, workFactor );
01293    if (ret != BZ_OK) return ret;
01294 
01295    strm.next_in = source;
01296    strm.next_out = dest;
01297    strm.avail_in = sourceLen;
01298    strm.avail_out = *destLen;
01299 
01300    ret = BZ2_bzCompress ( &strm, BZ_FINISH );
01301    if (ret == BZ_FINISH_OK) goto output_overflow;
01302    if (ret != BZ_STREAM_END) goto errhandler;
01303 
01304    /* normal termination */
01305    *destLen -= strm.avail_out;   
01306    BZ2_bzCompressEnd ( &strm );
01307    return BZ_OK;
01308 
01309    output_overflow:
01310    BZ2_bzCompressEnd ( &strm );
01311    return BZ_OUTBUFF_FULL;
01312 
01313    errhandler:
01314    BZ2_bzCompressEnd ( &strm );
01315    return ret;
01316 }
01317 
01318 
01319 /*---------------------------------------------------*/
01320 int BZ_API(BZ2_bzBuffToBuffDecompress) 
01321                            ( char*         dest, 
01322                              unsigned int* destLen,
01323                              char*         source, 
01324                              unsigned int  sourceLen,
01325                              int           small,
01326                              int           verbosity )
01327 {
01328    bz_stream strm;
01329    int ret;
01330 
01331    if (dest == NULL || destLen == NULL || 
01332        source == NULL ||
01333        (small != 0 && small != 1) ||
01334        verbosity < 0 || verbosity > 4) 
01335           return BZ_PARAM_ERROR;
01336 
01337    strm.bzalloc = NULL;
01338    strm.bzfree = NULL;
01339    strm.opaque = NULL;
01340    ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
01341    if (ret != BZ_OK) return ret;
01342 
01343    strm.next_in = source;
01344    strm.next_out = dest;
01345    strm.avail_in = sourceLen;
01346    strm.avail_out = *destLen;
01347 
01348    ret = BZ2_bzDecompress ( &strm );
01349    if (ret == BZ_OK) goto output_overflow_or_eof;
01350    if (ret != BZ_STREAM_END) goto errhandler;
01351 
01352    /* normal termination */
01353    *destLen -= strm.avail_out;
01354    BZ2_bzDecompressEnd ( &strm );
01355    return BZ_OK;
01356 
01357    output_overflow_or_eof:
01358    if (strm.avail_out > 0) {
01359       BZ2_bzDecompressEnd ( &strm );
01360       return BZ_UNEXPECTED_EOF;
01361    } else {
01362       BZ2_bzDecompressEnd ( &strm );
01363       return BZ_OUTBUFF_FULL;
01364    };      
01365 
01366    errhandler:
01367    BZ2_bzDecompressEnd ( &strm );
01368    return ret; 
01369 }
01370 
01371 
01372 /*---------------------------------------------------*/
01373 /*--
01374    Code contributed by Yoshioka Tsuneo
01375    (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
01376    to support better zlib compatibility.
01377    This code is not _officially_ part of libbzip2 (yet);
01378    I haven't tested it, documented it, or considered the
01379    threading-safeness of it.
01380    If this code breaks, please contact both Yoshioka and me.
01381 --*/
01382 /*---------------------------------------------------*/
01383 
01384 /*---------------------------------------------------*/
01385 /*--
01386    return version like "0.9.0c".
01387 --*/
01388 const char * BZ_API(BZ2_bzlibVersion)(void)
01389 {
01390    return BZ_VERSION;
01391 }
01392 
01393 
01394 #ifndef BZ_NO_STDIO
01395 /*---------------------------------------------------*/
01396 
01397 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
01398 #   include <fcntl.h>
01399 #   include <io.h>
01400 #   define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
01401 #else
01402 #   define SET_BINARY_MODE(file)
01403 #endif
01404 static
01405 BZFILE * bzopen_or_bzdopen
01406                ( const char *path,   /* no use when bzdopen */
01407                  int fd,             /* no use when bzdopen */
01408                  const char *mode,
01409                  int open_mode)      /* bzopen: 0, bzdopen:1 */
01410 {
01411    int    bzerr;
01412    char   unused[BZ_MAX_UNUSED];
01413    int    blockSize100k = 9;
01414    int    writing       = 0;
01415    char   mode2[10]     = "";
01416    FILE   *fp           = NULL;
01417    BZFILE *bzfp         = NULL;
01418    int    verbosity     = 0;
01419    int    workFactor    = 30;
01420    int    smallMode     = 0;
01421    int    nUnused       = 0; 
01422 
01423    if (mode == NULL) return NULL;
01424    while (*mode) {
01425       switch (*mode) {
01426       case 'r':
01427          writing = 0; break;
01428       case 'w':
01429          writing = 1; break;
01430       case 's':
01431          smallMode = 1; break;
01432       default:
01433          if (isdigit((int)(*mode))) {
01434             blockSize100k = *mode-BZ_HDR_0;
01435          }
01436       }
01437       mode++;
01438    }
01439    strcat(mode2, writing ? "w" : "r" );
01440    strcat(mode2,"b");   /* binary mode */
01441 
01442    if (open_mode==0) {
01443       if (path==NULL || strcmp(path,"")==0) {
01444         fp = (writing ? stdout : stdin);
01445         SET_BINARY_MODE(fp);
01446       } else {
01447         fp = fopen(path,mode2);
01448       }
01449    } else {
01450 #ifdef BZ_STRICT_ANSI
01451       fp = NULL;
01452 #else
01453       fp = fdopen(fd,mode2);
01454 #endif
01455    }
01456    if (fp == NULL) return NULL;
01457 
01458    if (writing) {
01459       /* Guard against total chaos and anarchy -- JRS */
01460       if (blockSize100k < 1) blockSize100k = 1;
01461       if (blockSize100k > 9) blockSize100k = 9; 
01462       bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
01463                              verbosity,workFactor);
01464    } else {
01465       bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
01466                             unused,nUnused);
01467    }
01468    if (bzfp == NULL) {
01469       if (fp != stdin && fp != stdout) fclose(fp);
01470       return NULL;
01471    }
01472    return bzfp;
01473 }
01474 
01475 
01476 /*---------------------------------------------------*/
01477 /*--
01478    open file for read or write.
01479       ex) bzopen("file","w9")
01480       case path="" or NULL => use stdin or stdout.
01481 --*/
01482 BZFILE * BZ_API(BZ2_bzopen)
01483                ( const char *path,
01484                  const char *mode )
01485 {
01486    return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
01487 }
01488 
01489 
01490 /*---------------------------------------------------*/
01491 BZFILE * BZ_API(BZ2_bzdopen)
01492                ( int fd,
01493                  const char *mode )
01494 {
01495    return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
01496 }
01497 
01498 
01499 /*---------------------------------------------------*/
01500 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
01501 {
01502    int bzerr, nread;
01503    if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
01504    nread = BZ2_bzRead(&bzerr,b,buf,len);
01505    if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
01506       return nread;
01507    } else {
01508       return -1;
01509    }
01510 }
01511 
01512 
01513 /*---------------------------------------------------*/
01514 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
01515 {
01516    int bzerr;
01517 
01518    BZ2_bzWrite(&bzerr,b,buf,len);
01519    if(bzerr == BZ_OK){
01520       return len;
01521    }else{
01522       return -1;
01523    }
01524 }
01525 
01526 
01527 /*---------------------------------------------------*/
01528 int BZ_API(BZ2_bzflush) (BZFILE *b)
01529 {
01530    /* do nothing now... */
01531    return 0;
01532 }
01533 
01534 
01535 /*---------------------------------------------------*/
01536 void BZ_API(BZ2_bzclose) (BZFILE* b)
01537 {
01538    int bzerr;
01539    FILE *fp = ((bzFile *)b)->handle;
01540    
01541    if (b==NULL) {return;}
01542    if(((bzFile*)b)->writing){
01543       BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
01544       if(bzerr != BZ_OK){
01545          BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
01546       }
01547    }else{
01548       BZ2_bzReadClose(&bzerr,b);
01549    }
01550    if(fp!=stdin && fp!=stdout){
01551       fclose(fp);
01552    }
01553 }
01554 
01555 
01556 /*---------------------------------------------------*/
01557 /*--
01558    return last error code 
01559 --*/
01560 static const char *bzerrorstrings[] = {
01561        "OK"
01562       ,"SEQUENCE_ERROR"
01563       ,"PARAM_ERROR"
01564       ,"MEM_ERROR"
01565       ,"DATA_ERROR"
01566       ,"DATA_ERROR_MAGIC"
01567       ,"IO_ERROR"
01568       ,"UNEXPECTED_EOF"
01569       ,"OUTBUFF_FULL"
01570       ,"CONFIG_ERROR"
01571       ,"???"   /* for future */
01572       ,"???"   /* for future */
01573       ,"???"   /* for future */
01574       ,"???"   /* for future */
01575       ,"???"   /* for future */
01576       ,"???"   /* for future */
01577 };
01578 
01579 
01580 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
01581 {
01582    int err = ((bzFile *)b)->lastErr;
01583 
01584    if(err>0) err = 0;
01585    *errnum = err;
01586    return bzerrorstrings[err*-1];
01587 }
01588 #endif
01589 
01590 
01591 /*-------------------------------------------------------------*/
01592 /*--- end                                           bzlib.c ---*/
01593 /*-------------------------------------------------------------*/