LLVM API Documentation

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