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


win_bzip2
Author(s): Daniel Stonier
autogenerated on Wed Sep 16 2015 07:14:10