modules/libbz2/src/bzlib.c

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     2 /*-------------------------------------------------------------*/
     3 /*--- Library top-level functions.                          ---*/
     4 /*---                                               bzlib.c ---*/
     5 /*-------------------------------------------------------------*/
     7 /* ------------------------------------------------------------------
     8    This file is part of bzip2/libbzip2, a program and library for
     9    lossless, block-sorting data compression.
    11    bzip2/libbzip2 version 1.0.4 of 20 December 2006
    12    Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
    14    Please read the WARNING, DISCLAIMER and PATENTS sections in the 
    15    README file.
    17    This program is released under the terms of the license contained
    18    in the file LICENSE.
    19    ------------------------------------------------------------------ */
    21 /* CHANGES
    22    0.9.0    -- original version.
    23    0.9.0a/b -- no changes in this file.
    24    0.9.0c   -- made zero-length BZ_FLUSH work correctly in bzCompress().
    25      fixed bzWrite/bzRead to ignore zero-length requests.
    26      fixed bzread to correctly handle read requests after EOF.
    27      wrong parameter order in call to bzDecompressInit in
    28      bzBuffToBuffDecompress.  Fixed.
    29 */
    31 #include "bzlib_private.h"
    34 /*---------------------------------------------------*/
    35 /*--- Compression stuff                           ---*/
    36 /*---------------------------------------------------*/
    39 /*---------------------------------------------------*/
    40 #ifndef BZ_NO_STDIO
    41 void BZ2_bz__AssertH__fail ( int errcode )
    42 {
    43    fprintf(stderr, 
    44       "\n\nbzip2/libbzip2: internal error number %d.\n"
    45       "This is a bug in bzip2/libbzip2, %s.\n"
    46       "Please report it to me at: jseward@bzip.org.  If this happened\n"
    47       "when you were using some program which uses libbzip2 as a\n"
    48       "component, you should also report this bug to the author(s)\n"
    49       "of that program.  Please make an effort to report this bug;\n"
    50       "timely and accurate bug reports eventually lead to higher\n"
    51       "quality software.  Thanks.  Julian Seward, 15 February 2005.\n\n",
    52       errcode,
    53       BZ2_bzlibVersion()
    54    );
    56    if (errcode == 1007) {
    57    fprintf(stderr,
    58       "\n*** A special note about internal error number 1007 ***\n"
    59       "\n"
    60       "Experience suggests that a common cause of i.e. 1007\n"
    61       "is unreliable memory or other hardware.  The 1007 assertion\n"
    62       "just happens to cross-check the results of huge numbers of\n"
    63       "memory reads/writes, and so acts (unintendedly) as a stress\n"
    64       "test of your memory system.\n"
    65       "\n"
    66       "I suggest the following: try compressing the file again,\n"
    67       "possibly monitoring progress in detail with the -vv flag.\n"
    68       "\n"
    69       "* If the error cannot be reproduced, and/or happens at different\n"
    70       "  points in compression, you may have a flaky memory system.\n"
    71       "  Try a memory-test program.  I have used Memtest86\n"
    72       "  (www.memtest86.com).  At the time of writing it is free (GPLd).\n"
    73       "  Memtest86 tests memory much more thorougly than your BIOSs\n"
    74       "  power-on test, and may find failures that the BIOS doesn't.\n"
    75       "\n"
    76       "* If the error can be repeatably reproduced, this is a bug in\n"
    77       "  bzip2, and I would very much like to hear about it.  Please\n"
    78       "  let me know, and, ideally, save a copy of the file causing the\n"
    79       "  problem -- without which I will be unable to investigate it.\n"
    80       "\n"
    81    );
    82    }
    84    exit(3);
    85 }
    86 #endif
    89 /*---------------------------------------------------*/
    90 static
    91 int bz_config_ok ( void )
    92 {
    93    if (sizeof(int)   != 4) return 0;
    94    if (sizeof(short) != 2) return 0;
    95    if (sizeof(char)  != 1) return 0;
    96    return 1;
    97 }
   100 /*---------------------------------------------------*/
   101 static
   102 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
   103 {
   104    void* v = malloc ( items * size );
   105    return v;
   106 }
   108 static
   109 void default_bzfree ( void* opaque, void* addr )
   110 {
   111    if (addr != NULL) free ( addr );
   112 }
   115 /*---------------------------------------------------*/
   116 static
   117 void prepare_new_block ( EState* s )
   118 {
   119    Int32 i;
   120    s->nblock = 0;
   121    s->numZ = 0;
   122    s->state_out_pos = 0;
   123    BZ_INITIALISE_CRC ( s->blockCRC );
   124    for (i = 0; i < 256; i++) s->inUse[i] = False;
   125    s->blockNo++;
   126 }
   129 /*---------------------------------------------------*/
   130 static
   131 void init_RL ( EState* s )
   132 {
   133    s->state_in_ch  = 256;
   134    s->state_in_len = 0;
   135 }
   138 static
   139 Bool isempty_RL ( EState* s )
   140 {
   141    if (s->state_in_ch < 256 && s->state_in_len > 0)
   142       return False; else
   143       return True;
   144 }
   147 /*---------------------------------------------------*/
   148 int BZ_API(BZ2_bzCompressInit) 
   149                     ( bz_stream* strm, 
   150                      int        blockSize100k,
   151                      int        verbosity,
   152                      int        workFactor )
   153 {
   154    Int32   n;
   155    EState* s;
   157    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
   159    if (strm == NULL || 
   160        blockSize100k < 1 || blockSize100k > 9 ||
   161        workFactor < 0 || workFactor > 250)
   162      return BZ_PARAM_ERROR;
   164    if (workFactor == 0) workFactor = 30;
   165    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
   166    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
   168    s = BZALLOC( sizeof(EState) );
   169    if (s == NULL) return BZ_MEM_ERROR;
   170    s->strm = strm;
   172    s->arr1 = NULL;
   173    s->arr2 = NULL;
   174    s->ftab = NULL;
   176    n       = 100000 * blockSize100k;
   177    s->arr1 = BZALLOC( n                  * sizeof(UInt32) );
   178    s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
   179    s->ftab = BZALLOC( 65537              * sizeof(UInt32) );
   181    if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
   182       if (s->arr1 != NULL) BZFREE(s->arr1);
   183       if (s->arr2 != NULL) BZFREE(s->arr2);
   184       if (s->ftab != NULL) BZFREE(s->ftab);
   185       if (s       != NULL) BZFREE(s);
   186       return BZ_MEM_ERROR;
   187    }
   189    s->blockNo           = 0;
   190    s->state             = BZ_S_INPUT;
   191    s->mode              = BZ_M_RUNNING;
   192    s->combinedCRC       = 0;
   193    s->blockSize100k     = blockSize100k;
   194    s->nblockMAX         = 100000 * blockSize100k - 19;
   195    s->verbosity         = verbosity;
   196    s->workFactor        = workFactor;
   198    s->block             = (UChar*)s->arr2;
   199    s->mtfv              = (UInt16*)s->arr1;
   200    s->zbits             = NULL;
   201    s->ptr               = (UInt32*)s->arr1;
   203    strm->state          = s;
   204    strm->total_in_lo32  = 0;
   205    strm->total_in_hi32  = 0;
   206    strm->total_out_lo32 = 0;
   207    strm->total_out_hi32 = 0;
   208    init_RL ( s );
   209    prepare_new_block ( s );
   210    return BZ_OK;
   211 }
   214 /*---------------------------------------------------*/
   215 static
   216 void add_pair_to_block ( EState* s )
   217 {
   218    Int32 i;
   219    UChar ch = (UChar)(s->state_in_ch);
   220    for (i = 0; i < s->state_in_len; i++) {
   221       BZ_UPDATE_CRC( s->blockCRC, ch );
   222    }
   223    s->inUse[s->state_in_ch] = True;
   224    switch (s->state_in_len) {
   225       case 1:
   226          s->block[s->nblock] = (UChar)ch; s->nblock++;
   227          break;
   228       case 2:
   229          s->block[s->nblock] = (UChar)ch; s->nblock++;
   230          s->block[s->nblock] = (UChar)ch; s->nblock++;
   231          break;
   232       case 3:
   233          s->block[s->nblock] = (UChar)ch; s->nblock++;
   234          s->block[s->nblock] = (UChar)ch; s->nblock++;
   235          s->block[s->nblock] = (UChar)ch; s->nblock++;
   236          break;
   237       default:
   238          s->inUse[s->state_in_len-4] = True;
   239          s->block[s->nblock] = (UChar)ch; s->nblock++;
   240          s->block[s->nblock] = (UChar)ch; s->nblock++;
   241          s->block[s->nblock] = (UChar)ch; s->nblock++;
   242          s->block[s->nblock] = (UChar)ch; s->nblock++;
   243          s->block[s->nblock] = ((UChar)(s->state_in_len-4));
   244          s->nblock++;
   245          break;
   246    }
   247 }
   250 /*---------------------------------------------------*/
   251 static
   252 void flush_RL ( EState* s )
   253 {
   254    if (s->state_in_ch < 256) add_pair_to_block ( s );
   255    init_RL ( s );
   256 }
   259 /*---------------------------------------------------*/
   260 #define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
   261 {                                                 \
   262    UInt32 zchh = (UInt32)(zchh0);                 \
   263    /*-- fast track the common case --*/           \
   264    if (zchh != zs->state_in_ch &&                 \
   265        zs->state_in_len == 1) {                   \
   266       UChar ch = (UChar)(zs->state_in_ch);        \
   267       BZ_UPDATE_CRC( zs->blockCRC, ch );          \
   268       zs->inUse[zs->state_in_ch] = True;          \
   269       zs->block[zs->nblock] = (UChar)ch;          \
   270       zs->nblock++;                               \
   271       zs->state_in_ch = zchh;                     \
   272    }                                              \
   273    else                                           \
   274    /*-- general, uncommon cases --*/              \
   275    if (zchh != zs->state_in_ch ||                 \
   276       zs->state_in_len == 255) {                  \
   277       if (zs->state_in_ch < 256)                  \
   278          add_pair_to_block ( zs );                \
   279       zs->state_in_ch = zchh;                     \
   280       zs->state_in_len = 1;                       \
   281    } else {                                       \
   282       zs->state_in_len++;                         \
   283    }                                              \
   284 }
   287 /*---------------------------------------------------*/
   288 static
   289 Bool copy_input_until_stop ( EState* s )
   290 {
   291    Bool progress_in = False;
   293    if (s->mode == BZ_M_RUNNING) {
   295       /*-- fast track the common case --*/
   296       while (True) {
   297          /*-- block full? --*/
   298          if (s->nblock >= s->nblockMAX) break;
   299          /*-- no input? --*/
   300          if (s->strm->avail_in == 0) break;
   301          progress_in = True;
   302          ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
   303          s->strm->next_in++;
   304          s->strm->avail_in--;
   305          s->strm->total_in_lo32++;
   306          if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
   307       }
   309    } else {
   311       /*-- general, uncommon case --*/
   312       while (True) {
   313          /*-- block full? --*/
   314          if (s->nblock >= s->nblockMAX) break;
   315          /*-- no input? --*/
   316          if (s->strm->avail_in == 0) break;
   317          /*-- flush/finish end? --*/
   318          if (s->avail_in_expect == 0) break;
   319          progress_in = True;
   320          ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
   321          s->strm->next_in++;
   322          s->strm->avail_in--;
   323          s->strm->total_in_lo32++;
   324          if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
   325          s->avail_in_expect--;
   326       }
   327    }
   328    return progress_in;
   329 }
   332 /*---------------------------------------------------*/
   333 static
   334 Bool copy_output_until_stop ( EState* s )
   335 {
   336    Bool progress_out = False;
   338    while (True) {
   340       /*-- no output space? --*/
   341       if (s->strm->avail_out == 0) break;
   343       /*-- block done? --*/
   344       if (s->state_out_pos >= s->numZ) break;
   346       progress_out = True;
   347       *(s->strm->next_out) = s->zbits[s->state_out_pos];
   348       s->state_out_pos++;
   349       s->strm->avail_out--;
   350       s->strm->next_out++;
   351       s->strm->total_out_lo32++;
   352       if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
   353    }
   355    return progress_out;
   356 }
   359 /*---------------------------------------------------*/
   360 static
   361 Bool handle_compress ( bz_stream* strm )
   362 {
   363    Bool progress_in  = False;
   364    Bool progress_out = False;
   365    EState* s = strm->state;
   367    while (True) {
   369       if (s->state == BZ_S_OUTPUT) {
   370          progress_out |= copy_output_until_stop ( s );
   371          if (s->state_out_pos < s->numZ) break;
   372          if (s->mode == BZ_M_FINISHING && 
   373              s->avail_in_expect == 0 &&
   374              isempty_RL(s)) break;
   375          prepare_new_block ( s );
   376          s->state = BZ_S_INPUT;
   377          if (s->mode == BZ_M_FLUSHING && 
   378              s->avail_in_expect == 0 &&
   379              isempty_RL(s)) break;
   380       }
   382       if (s->state == BZ_S_INPUT) {
   383          progress_in |= copy_input_until_stop ( s );
   384          if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
   385             flush_RL ( s );
   386             BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
   387             s->state = BZ_S_OUTPUT;
   388          }
   389          else
   390          if (s->nblock >= s->nblockMAX) {
   391             BZ2_compressBlock ( s, False );
   392             s->state = BZ_S_OUTPUT;
   393          }
   394          else
   395          if (s->strm->avail_in == 0) {
   396             break;
   397          }
   398       }
   400    }
   402    return progress_in || progress_out;
   403 }
   406 /*---------------------------------------------------*/
   407 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
   408 {
   409    Bool progress;
   410    EState* s;
   411    if (strm == NULL) return BZ_PARAM_ERROR;
   412    s = strm->state;
   413    if (s == NULL) return BZ_PARAM_ERROR;
   414    if (s->strm != strm) return BZ_PARAM_ERROR;
   416    preswitch:
   417    switch (s->mode) {
   419       case BZ_M_IDLE:
   420          return BZ_SEQUENCE_ERROR;
   422       case BZ_M_RUNNING:
   423          if (action == BZ_RUN) {
   424             progress = handle_compress ( strm );
   425             return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
   426          } 
   427          else
   428 	 if (action == BZ_FLUSH) {
   429             s->avail_in_expect = strm->avail_in;
   430             s->mode = BZ_M_FLUSHING;
   431             goto preswitch;
   432          }
   433          else
   434          if (action == BZ_FINISH) {
   435             s->avail_in_expect = strm->avail_in;
   436             s->mode = BZ_M_FINISHING;
   437             goto preswitch;
   438          }
   439          else 
   440             return BZ_PARAM_ERROR;
   442       case BZ_M_FLUSHING:
   443          if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
   444          if (s->avail_in_expect != s->strm->avail_in) 
   445             return BZ_SEQUENCE_ERROR;
   446          progress = handle_compress ( strm );
   447          if (s->avail_in_expect > 0 || !isempty_RL(s) ||
   448              s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
   449          s->mode = BZ_M_RUNNING;
   450          return BZ_RUN_OK;
   452       case BZ_M_FINISHING:
   453          if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
   454          if (s->avail_in_expect != s->strm->avail_in) 
   455             return BZ_SEQUENCE_ERROR;
   456          progress = handle_compress ( strm );
   457          if (!progress) return BZ_SEQUENCE_ERROR;
   458          if (s->avail_in_expect > 0 || !isempty_RL(s) ||
   459              s->state_out_pos < s->numZ) return BZ_FINISH_OK;
   460          s->mode = BZ_M_IDLE;
   461          return BZ_STREAM_END;
   462    }
   463    return BZ_OK; /*--not reached--*/
   464 }
   467 /*---------------------------------------------------*/
   468 int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
   469 {
   470    EState* s;
   471    if (strm == NULL) return BZ_PARAM_ERROR;
   472    s = strm->state;
   473    if (s == NULL) return BZ_PARAM_ERROR;
   474    if (s->strm != strm) return BZ_PARAM_ERROR;
   476    if (s->arr1 != NULL) BZFREE(s->arr1);
   477    if (s->arr2 != NULL) BZFREE(s->arr2);
   478    if (s->ftab != NULL) BZFREE(s->ftab);
   479    BZFREE(strm->state);
   481    strm->state = NULL;   
   483    return BZ_OK;
   484 }
   487 /*---------------------------------------------------*/
   488 /*--- Decompression stuff                         ---*/
   489 /*---------------------------------------------------*/
   491 /*---------------------------------------------------*/
   492 int BZ_API(BZ2_bzDecompressInit) 
   493                      ( bz_stream* strm, 
   494                        int        verbosity,
   495                        int        small )
   496 {
   497    DState* s;
   499    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
   501    if (strm == NULL) return BZ_PARAM_ERROR;
   502    if (small != 0 && small != 1) return BZ_PARAM_ERROR;
   503    if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
   505    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
   506    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
   508    s = BZALLOC( sizeof(DState) );
   509    if (s == NULL) return BZ_MEM_ERROR;
   510    s->strm                  = strm;
   511    strm->state              = s;
   512    s->state                 = BZ_X_MAGIC_1;
   513    s->bsLive                = 0;
   514    s->bsBuff                = 0;
   515    s->calculatedCombinedCRC = 0;
   516    strm->total_in_lo32      = 0;
   517    strm->total_in_hi32      = 0;
   518    strm->total_out_lo32     = 0;
   519    strm->total_out_hi32     = 0;
   520    s->smallDecompress       = (Bool)small;
   521    s->ll4                   = NULL;
   522    s->ll16                  = NULL;
   523    s->tt                    = NULL;
   524    s->currBlockNo           = 0;
   525    s->verbosity             = verbosity;
   527    return BZ_OK;
   528 }
   531 /*---------------------------------------------------*/
   532 /* Return  True iff data corruption is discovered.
   533    Returns False if there is no problem.
   534 */
   535 static
   536 Bool unRLE_obuf_to_output_FAST ( DState* s )
   537 {
   538    UChar k1;
   540    if (s->blockRandomised) {
   542       while (True) {
   543          /* try to finish existing run */
   544          while (True) {
   545             if (s->strm->avail_out == 0) return False;
   546             if (s->state_out_len == 0) break;
   547             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
   548             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
   549             s->state_out_len--;
   550             s->strm->next_out++;
   551             s->strm->avail_out--;
   552             s->strm->total_out_lo32++;
   553             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
   554          }
   556          /* can a new run be started? */
   557          if (s->nblock_used == s->save_nblock+1) return False;
   559          /* Only caused by corrupt data stream? */
   560          if (s->nblock_used > s->save_nblock+1)
   561             return True;
   563          s->state_out_len = 1;
   564          s->state_out_ch = s->k0;
   565          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
   566          k1 ^= BZ_RAND_MASK; s->nblock_used++;
   567          if (s->nblock_used == s->save_nblock+1) continue;
   568          if (k1 != s->k0) { s->k0 = k1; continue; };
   570          s->state_out_len = 2;
   571          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
   572          k1 ^= BZ_RAND_MASK; s->nblock_used++;
   573          if (s->nblock_used == s->save_nblock+1) continue;
   574          if (k1 != s->k0) { s->k0 = k1; continue; };
   576          s->state_out_len = 3;
   577          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
   578          k1 ^= BZ_RAND_MASK; s->nblock_used++;
   579          if (s->nblock_used == s->save_nblock+1) continue;
   580          if (k1 != s->k0) { s->k0 = k1; continue; };
   582          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
   583          k1 ^= BZ_RAND_MASK; s->nblock_used++;
   584          s->state_out_len = ((Int32)k1) + 4;
   585          BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; 
   586          s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
   587       }
   589    } else {
   591       /* restore */
   592       UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC;
   593       UChar         c_state_out_ch       = s->state_out_ch;
   594       Int32         c_state_out_len      = s->state_out_len;
   595       Int32         c_nblock_used        = s->nblock_used;
   596       Int32         c_k0                 = s->k0;
   597       UInt32*       c_tt                 = s->tt;
   598       UInt32        c_tPos               = s->tPos;
   599       char*         cs_next_out          = s->strm->next_out;
   600       unsigned int  cs_avail_out         = s->strm->avail_out;
   601       /* end restore */
   603       UInt32       avail_out_INIT = cs_avail_out;
   604       Int32        s_save_nblockPP = s->save_nblock+1;
   605       unsigned int total_out_lo32_old;
   607       while (True) {
   609          /* try to finish existing run */
   610          if (c_state_out_len > 0) {
   611             while (True) {
   612                if (cs_avail_out == 0) goto return_notr;
   613                if (c_state_out_len == 1) break;
   614                *( (UChar*)(cs_next_out) ) = c_state_out_ch;
   615                BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
   616                c_state_out_len--;
   617                cs_next_out++;
   618                cs_avail_out--;
   619             }
   620             s_state_out_len_eq_one:
   621             {
   622                if (cs_avail_out == 0) { 
   623                   c_state_out_len = 1; goto return_notr;
   624                };
   625                *( (UChar*)(cs_next_out) ) = c_state_out_ch;
   626                BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
   627                cs_next_out++;
   628                cs_avail_out--;
   629             }
   630          }   
   631          /* Only caused by corrupt data stream? */
   632          if (c_nblock_used > s_save_nblockPP)
   633             return True;
   635          /* can a new run be started? */
   636          if (c_nblock_used == s_save_nblockPP) {
   637             c_state_out_len = 0; goto return_notr;
   638          };   
   639          c_state_out_ch = c_k0;
   640          BZ_GET_FAST_C(k1); c_nblock_used++;
   641          if (k1 != c_k0) { 
   642             c_k0 = k1; goto s_state_out_len_eq_one; 
   643          };
   644          if (c_nblock_used == s_save_nblockPP) 
   645             goto s_state_out_len_eq_one;
   647          c_state_out_len = 2;
   648          BZ_GET_FAST_C(k1); c_nblock_used++;
   649          if (c_nblock_used == s_save_nblockPP) continue;
   650          if (k1 != c_k0) { c_k0 = k1; continue; };
   652          c_state_out_len = 3;
   653          BZ_GET_FAST_C(k1); c_nblock_used++;
   654          if (c_nblock_used == s_save_nblockPP) continue;
   655          if (k1 != c_k0) { c_k0 = k1; continue; };
   657          BZ_GET_FAST_C(k1); c_nblock_used++;
   658          c_state_out_len = ((Int32)k1) + 4;
   659          BZ_GET_FAST_C(c_k0); c_nblock_used++;
   660       }
   662       return_notr:
   663       total_out_lo32_old = s->strm->total_out_lo32;
   664       s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
   665       if (s->strm->total_out_lo32 < total_out_lo32_old)
   666          s->strm->total_out_hi32++;
   668       /* save */
   669       s->calculatedBlockCRC = c_calculatedBlockCRC;
   670       s->state_out_ch       = c_state_out_ch;
   671       s->state_out_len      = c_state_out_len;
   672       s->nblock_used        = c_nblock_used;
   673       s->k0                 = c_k0;
   674       s->tt                 = c_tt;
   675       s->tPos               = c_tPos;
   676       s->strm->next_out     = cs_next_out;
   677       s->strm->avail_out    = cs_avail_out;
   678       /* end save */
   679    }
   680    return False;
   681 }
   685 /*---------------------------------------------------*/
   686 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
   687 {
   688    Int32 nb, na, mid;
   689    nb = 0;
   690    na = 256;
   691    do {
   692       mid = (nb + na) >> 1;
   693       if (indx >= cftab[mid]) nb = mid; else na = mid;
   694    }
   695    while (na - nb != 1);
   696    return nb;
   697 }
   700 /*---------------------------------------------------*/
   701 /* Return  True iff data corruption is discovered.
   702    Returns False if there is no problem.
   703 */
   704 static
   705 Bool unRLE_obuf_to_output_SMALL ( DState* s )
   706 {
   707    UChar k1;
   709    if (s->blockRandomised) {
   711       while (True) {
   712          /* try to finish existing run */
   713          while (True) {
   714             if (s->strm->avail_out == 0) return False;
   715             if (s->state_out_len == 0) break;
   716             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
   717             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
   718             s->state_out_len--;
   719             s->strm->next_out++;
   720             s->strm->avail_out--;
   721             s->strm->total_out_lo32++;
   722             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
   723          }
   725          /* can a new run be started? */
   726          if (s->nblock_used == s->save_nblock+1) return False;
   728          /* Only caused by corrupt data stream? */
   729          if (s->nblock_used > s->save_nblock+1)
   730             return True;
   732          s->state_out_len = 1;
   733          s->state_out_ch = s->k0;
   734          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
   735          k1 ^= BZ_RAND_MASK; s->nblock_used++;
   736          if (s->nblock_used == s->save_nblock+1) continue;
   737          if (k1 != s->k0) { s->k0 = k1; continue; };
   739          s->state_out_len = 2;
   740          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
   741          k1 ^= BZ_RAND_MASK; s->nblock_used++;
   742          if (s->nblock_used == s->save_nblock+1) continue;
   743          if (k1 != s->k0) { s->k0 = k1; continue; };
   745          s->state_out_len = 3;
   746          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
   747          k1 ^= BZ_RAND_MASK; s->nblock_used++;
   748          if (s->nblock_used == s->save_nblock+1) continue;
   749          if (k1 != s->k0) { s->k0 = k1; continue; };
   751          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
   752          k1 ^= BZ_RAND_MASK; s->nblock_used++;
   753          s->state_out_len = ((Int32)k1) + 4;
   754          BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; 
   755          s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
   756       }
   758    } else {
   760       while (True) {
   761          /* try to finish existing run */
   762          while (True) {
   763             if (s->strm->avail_out == 0) return False;
   764             if (s->state_out_len == 0) break;
   765             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
   766             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
   767             s->state_out_len--;
   768             s->strm->next_out++;
   769             s->strm->avail_out--;
   770             s->strm->total_out_lo32++;
   771             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
   772          }
   774          /* can a new run be started? */
   775          if (s->nblock_used == s->save_nblock+1) return False;
   777          /* Only caused by corrupt data stream? */
   778          if (s->nblock_used > s->save_nblock+1)
   779             return True;
   781          s->state_out_len = 1;
   782          s->state_out_ch = s->k0;
   783          BZ_GET_SMALL(k1); s->nblock_used++;
   784          if (s->nblock_used == s->save_nblock+1) continue;
   785          if (k1 != s->k0) { s->k0 = k1; continue; };
   787          s->state_out_len = 2;
   788          BZ_GET_SMALL(k1); s->nblock_used++;
   789          if (s->nblock_used == s->save_nblock+1) continue;
   790          if (k1 != s->k0) { s->k0 = k1; continue; };
   792          s->state_out_len = 3;
   793          BZ_GET_SMALL(k1); s->nblock_used++;
   794          if (s->nblock_used == s->save_nblock+1) continue;
   795          if (k1 != s->k0) { s->k0 = k1; continue; };
   797          BZ_GET_SMALL(k1); s->nblock_used++;
   798          s->state_out_len = ((Int32)k1) + 4;
   799          BZ_GET_SMALL(s->k0); s->nblock_used++;
   800       }
   802    }
   803 }
   806 /*---------------------------------------------------*/
   807 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
   808 {
   809    Bool    corrupt;
   810    DState* s;
   811    if (strm == NULL) return BZ_PARAM_ERROR;
   812    s = strm->state;
   813    if (s == NULL) return BZ_PARAM_ERROR;
   814    if (s->strm != strm) return BZ_PARAM_ERROR;
   816    while (True) {
   817       if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
   818       if (s->state == BZ_X_OUTPUT) {
   819          if (s->smallDecompress)
   820             corrupt = unRLE_obuf_to_output_SMALL ( s ); else
   821             corrupt = unRLE_obuf_to_output_FAST  ( s );
   822          if (corrupt) return BZ_DATA_ERROR;
   823          if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
   824             BZ_FINALISE_CRC ( s->calculatedBlockCRC );
   825             if (s->verbosity >= 3) 
   826                VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, 
   827                           s->calculatedBlockCRC );
   828             if (s->verbosity >= 2) VPrintf0 ( "]" );
   829             if (s->calculatedBlockCRC != s->storedBlockCRC)
   830                return BZ_DATA_ERROR;
   831             s->calculatedCombinedCRC 
   832                = (s->calculatedCombinedCRC << 1) | 
   833                     (s->calculatedCombinedCRC >> 31);
   834             s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
   835             s->state = BZ_X_BLKHDR_1;
   836          } else {
   837             return BZ_OK;
   838          }
   839       }
   840       if (s->state >= BZ_X_MAGIC_1) {
   841          Int32 r = BZ2_decompress ( s );
   842          if (r == BZ_STREAM_END) {
   843             if (s->verbosity >= 3)
   844                VPrintf2 ( "\n    combined CRCs: stored = 0x%08x, computed = 0x%08x", 
   845                           s->storedCombinedCRC, s->calculatedCombinedCRC );
   846             if (s->calculatedCombinedCRC != s->storedCombinedCRC)
   847                return BZ_DATA_ERROR;
   848             return r;
   849          }
   850          if (s->state != BZ_X_OUTPUT) return r;
   851       }
   852    }
   854    AssertH ( 0, 6001 );
   856    return 0;  /*NOTREACHED*/
   857 }
   860 /*---------------------------------------------------*/
   861 int BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm )
   862 {
   863    DState* s;
   864    if (strm == NULL) return BZ_PARAM_ERROR;
   865    s = strm->state;
   866    if (s == NULL) return BZ_PARAM_ERROR;
   867    if (s->strm != strm) return BZ_PARAM_ERROR;
   869    if (s->tt   != NULL) BZFREE(s->tt);
   870    if (s->ll16 != NULL) BZFREE(s->ll16);
   871    if (s->ll4  != NULL) BZFREE(s->ll4);
   873    BZFREE(strm->state);
   874    strm->state = NULL;
   876    return BZ_OK;
   877 }
   880 #ifndef BZ_NO_STDIO
   881 /*---------------------------------------------------*/
   882 /*--- File I/O stuff                              ---*/
   883 /*---------------------------------------------------*/
   885 #define BZ_SETERR(eee)                    \
   886 {                                         \
   887    if (bzerror != NULL) *bzerror = eee;   \
   888    if (bzf != NULL) bzf->lastErr = eee;   \
   889 }
   891 typedef 
   892    struct {
   893       FILE*     handle;
   894       Char      buf[BZ_MAX_UNUSED];
   895       Int32     bufN;
   896       Bool      writing;
   897       bz_stream strm;
   898       Int32     lastErr;
   899       Bool      initialisedOk;
   900    }
   901    bzFile;
   904 /*---------------------------------------------*/
   905 static Bool myfeof ( FILE* f )
   906 {
   907    Int32 c = fgetc ( f );
   908    if (c == EOF) return True;
   909    ungetc ( c, f );
   910    return False;
   911 }
   914 /*---------------------------------------------------*/
   915 BZFILE* BZ_API(BZ2_bzWriteOpen) 
   916                     ( int*  bzerror,      
   917                       FILE* f, 
   918                       int   blockSize100k, 
   919                       int   verbosity,
   920                       int   workFactor )
   921 {
   922    Int32   ret;
   923    bzFile* bzf = NULL;
   925    BZ_SETERR(BZ_OK);
   927    if (f == NULL ||
   928        (blockSize100k < 1 || blockSize100k > 9) ||
   929        (workFactor < 0 || workFactor > 250) ||
   930        (verbosity < 0 || verbosity > 4))
   931       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
   933    if (ferror(f))
   934       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
   936    bzf = malloc ( sizeof(bzFile) );
   937    if (bzf == NULL)
   938       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
   940    BZ_SETERR(BZ_OK);
   941    bzf->initialisedOk = False;
   942    bzf->bufN          = 0;
   943    bzf->handle        = f;
   944    bzf->writing       = True;
   945    bzf->strm.bzalloc  = NULL;
   946    bzf->strm.bzfree   = NULL;
   947    bzf->strm.opaque   = NULL;
   949    if (workFactor == 0) workFactor = 30;
   950    ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, 
   951                               verbosity, workFactor );
   952    if (ret != BZ_OK)
   953       { BZ_SETERR(ret); free(bzf); return NULL; };
   955    bzf->strm.avail_in = 0;
   956    bzf->initialisedOk = True;
   957    return bzf;   
   958 }
   962 /*---------------------------------------------------*/
   963 void BZ_API(BZ2_bzWrite)
   964              ( int*    bzerror, 
   965                BZFILE* b, 
   966                void*   buf, 
   967                int     len )
   968 {
   969    Int32 n, n2, ret;
   970    bzFile* bzf = (bzFile*)b;
   972    BZ_SETERR(BZ_OK);
   973    if (bzf == NULL || buf == NULL || len < 0)
   974       { BZ_SETERR(BZ_PARAM_ERROR); return; };
   975    if (!(bzf->writing))
   976       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
   977    if (ferror(bzf->handle))
   978       { BZ_SETERR(BZ_IO_ERROR); return; };
   980    if (len == 0)
   981       { BZ_SETERR(BZ_OK); return; };
   983    bzf->strm.avail_in = len;
   984    bzf->strm.next_in  = buf;
   986    while (True) {
   987       bzf->strm.avail_out = BZ_MAX_UNUSED;
   988       bzf->strm.next_out = bzf->buf;
   989       ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
   990       if (ret != BZ_RUN_OK)
   991          { BZ_SETERR(ret); return; };
   993       if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
   994          n = BZ_MAX_UNUSED - bzf->strm.avail_out;
   995          n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
   996                        n, bzf->handle );
   997          if (n != n2 || ferror(bzf->handle))
   998             { BZ_SETERR(BZ_IO_ERROR); return; };
   999       }
  1001       if (bzf->strm.avail_in == 0)
  1002          { BZ_SETERR(BZ_OK); return; };
  1007 /*---------------------------------------------------*/
  1008 void BZ_API(BZ2_bzWriteClose)
  1009                   ( int*          bzerror, 
  1010                     BZFILE*       b, 
  1011                     int           abandon,
  1012                     unsigned int* nbytes_in,
  1013                     unsigned int* nbytes_out )
  1015    BZ2_bzWriteClose64 ( bzerror, b, abandon, 
  1016                         nbytes_in, NULL, nbytes_out, NULL );
  1020 void BZ_API(BZ2_bzWriteClose64)
  1021                   ( int*          bzerror, 
  1022                     BZFILE*       b, 
  1023                     int           abandon,
  1024                     unsigned int* nbytes_in_lo32,
  1025                     unsigned int* nbytes_in_hi32,
  1026                     unsigned int* nbytes_out_lo32,
  1027                     unsigned int* nbytes_out_hi32 )
  1029    Int32   n, n2, ret;
  1030    bzFile* bzf = (bzFile*)b;
  1032    if (bzf == NULL)
  1033       { BZ_SETERR(BZ_OK); return; };
  1034    if (!(bzf->writing))
  1035       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
  1036    if (ferror(bzf->handle))
  1037       { BZ_SETERR(BZ_IO_ERROR); return; };
  1039    if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
  1040    if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
  1041    if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
  1042    if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
  1044    if ((!abandon) && bzf->lastErr == BZ_OK) {
  1045       while (True) {
  1046          bzf->strm.avail_out = BZ_MAX_UNUSED;
  1047          bzf->strm.next_out = bzf->buf;
  1048          ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
  1049          if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
  1050             { BZ_SETERR(ret); return; };
  1052          if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
  1053             n = BZ_MAX_UNUSED - bzf->strm.avail_out;
  1054             n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
  1055                           n, bzf->handle );
  1056             if (n != n2 || ferror(bzf->handle))
  1057                { BZ_SETERR(BZ_IO_ERROR); return; };
  1060          if (ret == BZ_STREAM_END) break;
  1064    if ( !abandon && !ferror ( bzf->handle ) ) {
  1065       fflush ( bzf->handle );
  1066       if (ferror(bzf->handle))
  1067          { BZ_SETERR(BZ_IO_ERROR); return; };
  1070    if (nbytes_in_lo32 != NULL)
  1071       *nbytes_in_lo32 = bzf->strm.total_in_lo32;
  1072    if (nbytes_in_hi32 != NULL)
  1073       *nbytes_in_hi32 = bzf->strm.total_in_hi32;
  1074    if (nbytes_out_lo32 != NULL)
  1075       *nbytes_out_lo32 = bzf->strm.total_out_lo32;
  1076    if (nbytes_out_hi32 != NULL)
  1077       *nbytes_out_hi32 = bzf->strm.total_out_hi32;
  1079    BZ_SETERR(BZ_OK);
  1080    BZ2_bzCompressEnd ( &(bzf->strm) );
  1081    free ( bzf );
  1085 /*---------------------------------------------------*/
  1086 BZFILE* BZ_API(BZ2_bzReadOpen) 
  1087                    ( int*  bzerror, 
  1088                      FILE* f, 
  1089                      int   verbosity,
  1090                      int   small,
  1091                      void* unused,
  1092                      int   nUnused )
  1094    bzFile* bzf = NULL;
  1095    int     ret;
  1097    BZ_SETERR(BZ_OK);
  1099    if (f == NULL || 
  1100        (small != 0 && small != 1) ||
  1101        (verbosity < 0 || verbosity > 4) ||
  1102        (unused == NULL && nUnused != 0) ||
  1103        (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
  1104       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
  1106    if (ferror(f))
  1107       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
  1109    bzf = malloc ( sizeof(bzFile) );
  1110    if (bzf == NULL) 
  1111       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
  1113    BZ_SETERR(BZ_OK);
  1115    bzf->initialisedOk = False;
  1116    bzf->handle        = f;
  1117    bzf->bufN          = 0;
  1118    bzf->writing       = False;
  1119    bzf->strm.bzalloc  = NULL;
  1120    bzf->strm.bzfree   = NULL;
  1121    bzf->strm.opaque   = NULL;
  1123    while (nUnused > 0) {
  1124       bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
  1125       unused = ((void*)( 1 + ((UChar*)(unused))  ));
  1126       nUnused--;
  1129    ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
  1130    if (ret != BZ_OK)
  1131       { BZ_SETERR(ret); free(bzf); return NULL; };
  1133    bzf->strm.avail_in = bzf->bufN;
  1134    bzf->strm.next_in  = bzf->buf;
  1136    bzf->initialisedOk = True;
  1137    return bzf;   
  1141 /*---------------------------------------------------*/
  1142 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
  1144    bzFile* bzf = (bzFile*)b;
  1146    BZ_SETERR(BZ_OK);
  1147    if (bzf == NULL)
  1148       { BZ_SETERR(BZ_OK); return; };
  1150    if (bzf->writing)
  1151       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
  1153    if (bzf->initialisedOk)
  1154       (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
  1155    free ( bzf );
  1159 /*---------------------------------------------------*/
  1160 int BZ_API(BZ2_bzRead) 
  1161            ( int*    bzerror, 
  1162              BZFILE* b, 
  1163              void*   buf, 
  1164              int     len )
  1166    Int32   n, ret;
  1167    bzFile* bzf = (bzFile*)b;
  1169    BZ_SETERR(BZ_OK);
  1171    if (bzf == NULL || buf == NULL || len < 0)
  1172       { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
  1174    if (bzf->writing)
  1175       { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
  1177    if (len == 0)
  1178       { BZ_SETERR(BZ_OK); return 0; };
  1180    bzf->strm.avail_out = len;
  1181    bzf->strm.next_out = buf;
  1183    while (True) {
  1185       if (ferror(bzf->handle)) 
  1186          { BZ_SETERR(BZ_IO_ERROR); return 0; };
  1188       if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
  1189          n = fread ( bzf->buf, sizeof(UChar), 
  1190                      BZ_MAX_UNUSED, bzf->handle );
  1191          if (ferror(bzf->handle))
  1192             { BZ_SETERR(BZ_IO_ERROR); return 0; };
  1193          bzf->bufN = n;
  1194          bzf->strm.avail_in = bzf->bufN;
  1195          bzf->strm.next_in = bzf->buf;
  1198       ret = BZ2_bzDecompress ( &(bzf->strm) );
  1200       if (ret != BZ_OK && ret != BZ_STREAM_END)
  1201          { BZ_SETERR(ret); return 0; };
  1203       if (ret == BZ_OK && myfeof(bzf->handle) && 
  1204           bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
  1205          { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
  1207       if (ret == BZ_STREAM_END)
  1208          { BZ_SETERR(BZ_STREAM_END);
  1209            return len - bzf->strm.avail_out; };
  1210       if (bzf->strm.avail_out == 0)
  1211          { BZ_SETERR(BZ_OK); return len; };
  1215    return 0; /*not reached*/
  1219 /*---------------------------------------------------*/
  1220 void BZ_API(BZ2_bzReadGetUnused) 
  1221                      ( int*    bzerror, 
  1222                        BZFILE* b, 
  1223                        void**  unused, 
  1224                        int*    nUnused )
  1226    bzFile* bzf = (bzFile*)b;
  1227    if (bzf == NULL)
  1228       { BZ_SETERR(BZ_PARAM_ERROR); return; };
  1229    if (bzf->lastErr != BZ_STREAM_END)
  1230       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
  1231    if (unused == NULL || nUnused == NULL)
  1232       { BZ_SETERR(BZ_PARAM_ERROR); return; };
  1234    BZ_SETERR(BZ_OK);
  1235    *nUnused = bzf->strm.avail_in;
  1236    *unused = bzf->strm.next_in;
  1238 #endif
  1241 /*---------------------------------------------------*/
  1242 /*--- Misc convenience stuff                      ---*/
  1243 /*---------------------------------------------------*/
  1245 /*---------------------------------------------------*/
  1246 int BZ_API(BZ2_bzBuffToBuffCompress) 
  1247                          ( char*         dest, 
  1248                            unsigned int* destLen,
  1249                            char*         source, 
  1250                            unsigned int  sourceLen,
  1251                            int           blockSize100k, 
  1252                            int           verbosity, 
  1253                            int           workFactor )
  1255    bz_stream strm;
  1256    int ret;
  1258    if (dest == NULL || destLen == NULL || 
  1259        source == NULL ||
  1260        blockSize100k < 1 || blockSize100k > 9 ||
  1261        verbosity < 0 || verbosity > 4 ||
  1262        workFactor < 0 || workFactor > 250) 
  1263       return BZ_PARAM_ERROR;
  1265    if (workFactor == 0) workFactor = 30;
  1266    strm.bzalloc = NULL;
  1267    strm.bzfree = NULL;
  1268    strm.opaque = NULL;
  1269    ret = BZ2_bzCompressInit ( &strm, blockSize100k, 
  1270                               verbosity, workFactor );
  1271    if (ret != BZ_OK) return ret;
  1273    strm.next_in = source;
  1274    strm.next_out = dest;
  1275    strm.avail_in = sourceLen;
  1276    strm.avail_out = *destLen;
  1278    ret = BZ2_bzCompress ( &strm, BZ_FINISH );
  1279    if (ret == BZ_FINISH_OK) goto output_overflow;
  1280    if (ret != BZ_STREAM_END) goto errhandler;
  1282    /* normal termination */
  1283    *destLen -= strm.avail_out;   
  1284    BZ2_bzCompressEnd ( &strm );
  1285    return BZ_OK;
  1287    output_overflow:
  1288    BZ2_bzCompressEnd ( &strm );
  1289    return BZ_OUTBUFF_FULL;
  1291    errhandler:
  1292    BZ2_bzCompressEnd ( &strm );
  1293    return ret;
  1297 /*---------------------------------------------------*/
  1298 int BZ_API(BZ2_bzBuffToBuffDecompress) 
  1299                            ( char*         dest, 
  1300                              unsigned int* destLen,
  1301                              char*         source, 
  1302                              unsigned int  sourceLen,
  1303                              int           small,
  1304                              int           verbosity )
  1306    bz_stream strm;
  1307    int ret;
  1309    if (dest == NULL || destLen == NULL || 
  1310        source == NULL ||
  1311        (small != 0 && small != 1) ||
  1312        verbosity < 0 || verbosity > 4) 
  1313           return BZ_PARAM_ERROR;
  1315    strm.bzalloc = NULL;
  1316    strm.bzfree = NULL;
  1317    strm.opaque = NULL;
  1318    ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
  1319    if (ret != BZ_OK) return ret;
  1321    strm.next_in = source;
  1322    strm.next_out = dest;
  1323    strm.avail_in = sourceLen;
  1324    strm.avail_out = *destLen;
  1326    ret = BZ2_bzDecompress ( &strm );
  1327    if (ret == BZ_OK) goto output_overflow_or_eof;
  1328    if (ret != BZ_STREAM_END) goto errhandler;
  1330    /* normal termination */
  1331    *destLen -= strm.avail_out;
  1332    BZ2_bzDecompressEnd ( &strm );
  1333    return BZ_OK;
  1335    output_overflow_or_eof:
  1336    if (strm.avail_out > 0) {
  1337       BZ2_bzDecompressEnd ( &strm );
  1338       return BZ_UNEXPECTED_EOF;
  1339    } else {
  1340       BZ2_bzDecompressEnd ( &strm );
  1341       return BZ_OUTBUFF_FULL;
  1342    };      
  1344    errhandler:
  1345    BZ2_bzDecompressEnd ( &strm );
  1346    return ret; 
  1350 /*---------------------------------------------------*/
  1351 /*--
  1352    Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
  1353    to support better zlib compatibility.
  1354    This code is not _officially_ part of libbzip2 (yet);
  1355    I haven't tested it, documented it, or considered the
  1356    threading-safeness of it.
  1357    If this code breaks, please contact both Yoshioka and me.
  1358 --*/
  1359 /*---------------------------------------------------*/
  1361 /*---------------------------------------------------*/
  1362 /*--
  1363    return version like "0.9.5d, 4-Sept-1999".
  1364 --*/
  1365 const char * BZ_API(BZ2_bzlibVersion)(void)
  1367    return BZ_VERSION;
  1371 #ifndef BZ_NO_STDIO
  1372 /*---------------------------------------------------*/
  1374 #ifdef WINCE
  1375 #ifndef setmode
  1376 #define setmode _setmode
  1377 #endif
  1378 #ifndef O_BINARY
  1379 #define O_BINARY _O_BINARY
  1380 #endif
  1381 static
  1382 FILE * fdopen(int fd, const char *mode)
  1384     wchar_t wMode[10];
  1385     MultiByteToWideChar(CP_ACP, 0, mode, -1, wMode, 10);
  1386     return _wfdopen((void*)fd, wMode);
  1388 #endif
  1390 #if (defined(_WIN32) || defined(OS2) || defined(MSDOS))
  1391 #   include <fcntl.h>
  1392 #   include <io.h>
  1393 #   define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
  1394 #else
  1395 #   define SET_BINARY_MODE(file)
  1396 #endif
  1397 static
  1398 BZFILE * bzopen_or_bzdopen
  1399                ( const char *path,   /* no use when bzdopen */
  1400                  int fd,             /* no use when bzdopen */
  1401                  const char *mode,
  1402                  int open_mode)      /* bzopen: 0, bzdopen:1 */
  1404    int    bzerr;
  1405    char   unused[BZ_MAX_UNUSED];
  1406    int    blockSize100k = 9;
  1407    int    writing       = 0;
  1408    char   mode2[10]     = "";
  1409    FILE   *fp           = NULL;
  1410    BZFILE *bzfp         = NULL;
  1411    int    verbosity     = 0;
  1412    int    workFactor    = 30;
  1413    int    smallMode     = 0;
  1414    int    nUnused       = 0; 
  1416    if (mode == NULL) return NULL;
  1417    while (*mode) {
  1418       switch (*mode) {
  1419       case 'r':
  1420          writing = 0; break;
  1421       case 'w':
  1422          writing = 1; break;
  1423       case 's':
  1424          smallMode = 1; break;
  1425       default:
  1426          if (isdigit((int)(*mode))) {
  1427             blockSize100k = *mode-BZ_HDR_0;
  1430       mode++;
  1432    strcat(mode2, writing ? "w" : "r" );
  1433    strcat(mode2,"b");   /* binary mode */
  1435    if (open_mode==0) {
  1436       if (path==NULL || strcmp(path,"")==0) {
  1437         fp = (writing ? stdout : stdin);
  1438         SET_BINARY_MODE(fp);
  1439       } else {
  1440         fp = fopen(path,mode2);
  1442    } else {
  1443 #ifdef BZ_STRICT_ANSI
  1444       fp = NULL;
  1445 #else
  1446       fp = fdopen(fd,mode2);
  1447 #endif
  1449    if (fp == NULL) return NULL;
  1451    if (writing) {
  1452       /* Guard against total chaos and anarchy -- JRS */
  1453       if (blockSize100k < 1) blockSize100k = 1;
  1454       if (blockSize100k > 9) blockSize100k = 9; 
  1455       bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
  1456                              verbosity,workFactor);
  1457    } else {
  1458       bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
  1459                             unused,nUnused);
  1461    if (bzfp == NULL) {
  1462       if (fp != stdin && fp != stdout) fclose(fp);
  1463       return NULL;
  1465    return bzfp;
  1469 /*---------------------------------------------------*/
  1470 /*--
  1471    open file for read or write.
  1472       ex) bzopen("file","w9")
  1473       case path="" or NULL => use stdin or stdout.
  1474 --*/
  1475 BZFILE * BZ_API(BZ2_bzopen)
  1476                ( const char *path,
  1477                  const char *mode )
  1479    return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
  1483 /*---------------------------------------------------*/
  1484 BZFILE * BZ_API(BZ2_bzdopen)
  1485                ( int fd,
  1486                  const char *mode )
  1488    return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
  1492 /*---------------------------------------------------*/
  1493 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
  1495    int bzerr, nread;
  1496    if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
  1497    nread = BZ2_bzRead(&bzerr,b,buf,len);
  1498    if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
  1499       return nread;
  1500    } else {
  1501       return -1;
  1506 /*---------------------------------------------------*/
  1507 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
  1509    int bzerr;
  1511    BZ2_bzWrite(&bzerr,b,buf,len);
  1512    if(bzerr == BZ_OK){
  1513       return len;
  1514    }else{
  1515       return -1;
  1520 /*---------------------------------------------------*/
  1521 int BZ_API(BZ2_bzflush) (BZFILE *b)
  1523    /* do nothing now... */
  1524    return 0;
  1528 /*---------------------------------------------------*/
  1529 void BZ_API(BZ2_bzclose) (BZFILE* b)
  1531    int bzerr;
  1532    FILE *fp;
  1534    if (b==NULL) {return;}
  1535    fp = ((bzFile *)b)->handle;
  1536    if(((bzFile*)b)->writing){
  1537       BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
  1538       if(bzerr != BZ_OK){
  1539          BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
  1541    }else{
  1542       BZ2_bzReadClose(&bzerr,b);
  1544    if(fp!=stdin && fp!=stdout){
  1545       fclose(fp);
  1550 /*---------------------------------------------------*/
  1551 /*--
  1552    return last error code 
  1553 --*/
  1554 static const char *bzerrorstrings[] = {
  1555        "OK"
  1556       ,"SEQUENCE_ERROR"
  1557       ,"PARAM_ERROR"
  1558       ,"MEM_ERROR"
  1559       ,"DATA_ERROR"
  1560       ,"DATA_ERROR_MAGIC"
  1561       ,"IO_ERROR"
  1562       ,"UNEXPECTED_EOF"
  1563       ,"OUTBUFF_FULL"
  1564       ,"CONFIG_ERROR"
  1565       ,"???"   /* for future */
  1566       ,"???"   /* for future */
  1567       ,"???"   /* for future */
  1568       ,"???"   /* for future */
  1569       ,"???"   /* for future */
  1570       ,"???"   /* for future */
  1571 };
  1574 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
  1576    int err = ((bzFile *)b)->lastErr;
  1578    if(err>0) err = 0;
  1579    *errnum = err;
  1580    return bzerrorstrings[err*-1];
  1582 #endif
  1585 /*-------------------------------------------------------------*/
  1586 /*--- end                                           bzlib.c ---*/
  1587 /*-------------------------------------------------------------*/

mercurial