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