PageRenderTime 98ms CodeModel.GetById 9ms app.highlight 78ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/bzip2/bzlib.c

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