PageRenderTime 130ms CodeModel.GetById 42ms app.highlight 77ms RepoModel.GetById 1ms app.codeStats 1ms

/StormLib/stormlib/bzip2/bzlib.c

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