Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

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

Generated on Sat Oct 13 16:08:34 2001 for XMILL by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001