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@acm.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, 30 December 2001.\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 static
00578 void unRLE_obuf_to_output_FAST ( DState* s )
00579 {
00580 UChar k1;
00581
00582 if (s->blockRandomised) {
00583
00584 while (True) {
00585
00586 while (True) {
00587 if (s->strm->avail_out == 0) return;
00588 if (s->state_out_len == 0) break;
00589 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
00590 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
00591 s->state_out_len--;
00592 s->strm->next_out++;
00593 s->strm->avail_out--;
00594 s->strm->total_out_lo32++;
00595 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
00596 }
00597
00598
00599 if (s->nblock_used == s->save_nblock+1) return;
00600
00601
00602 s->state_out_len = 1;
00603 s->state_out_ch = s->k0;
00604 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
00605 k1 ^= BZ_RAND_MASK; s->nblock_used++;
00606 if (s->nblock_used == s->save_nblock+1) continue;
00607 if (k1 != s->k0) { s->k0 = k1; continue; };
00608
00609 s->state_out_len = 2;
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 = 3;
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 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
00622 k1 ^= BZ_RAND_MASK; s->nblock_used++;
00623 s->state_out_len = ((Int32)k1) + 4;
00624 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
00625 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
00626 }
00627
00628 } else {
00629
00630
00631 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
00632 UChar c_state_out_ch = s->state_out_ch;
00633 Int32 c_state_out_len = s->state_out_len;
00634 Int32 c_nblock_used = s->nblock_used;
00635 Int32 c_k0 = s->k0;
00636 UInt32* c_tt = s->tt;
00637 UInt32 c_tPos = s->tPos;
00638 char* cs_next_out = s->strm->next_out;
00639 unsigned int cs_avail_out = s->strm->avail_out;
00640
00641
00642 UInt32 avail_out_INIT = cs_avail_out;
00643 Int32 s_save_nblockPP = s->save_nblock+1;
00644 unsigned int total_out_lo32_old;
00645
00646 while (True) {
00647
00648
00649 if (c_state_out_len > 0) {
00650 while (True) {
00651 if (cs_avail_out == 0) goto return_notr;
00652 if (c_state_out_len == 1) break;
00653 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
00654 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
00655 c_state_out_len--;
00656 cs_next_out++;
00657 cs_avail_out--;
00658 }
00659 s_state_out_len_eq_one:
00660 {
00661 if (cs_avail_out == 0) {
00662 c_state_out_len = 1; goto return_notr;
00663 };
00664 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
00665 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
00666 cs_next_out++;
00667 cs_avail_out--;
00668 }
00669 }
00670
00671 if (c_nblock_used == s_save_nblockPP) {
00672 c_state_out_len = 0; goto return_notr;
00673 };
00674 c_state_out_ch = c_k0;
00675 BZ_GET_FAST_C(k1); c_nblock_used++;
00676 if (k1 != c_k0) {
00677 c_k0 = k1; goto s_state_out_len_eq_one;
00678 };
00679 if (c_nblock_used == s_save_nblockPP)
00680 goto s_state_out_len_eq_one;
00681
00682 c_state_out_len = 2;
00683 BZ_GET_FAST_C(k1); c_nblock_used++;
00684 if (c_nblock_used == s_save_nblockPP) continue;
00685 if (k1 != c_k0) { c_k0 = k1; continue; };
00686
00687 c_state_out_len = 3;
00688 BZ_GET_FAST_C(k1); c_nblock_used++;
00689 if (c_nblock_used == s_save_nblockPP) continue;
00690 if (k1 != c_k0) { c_k0 = k1; continue; };
00691
00692 BZ_GET_FAST_C(k1); c_nblock_used++;
00693 c_state_out_len = ((Int32)k1) + 4;
00694 BZ_GET_FAST_C(c_k0); c_nblock_used++;
00695 }
00696
00697 return_notr:
00698 total_out_lo32_old = s->strm->total_out_lo32;
00699 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
00700 if (s->strm->total_out_lo32 < total_out_lo32_old)
00701 s->strm->total_out_hi32++;
00702
00703
00704 s->calculatedBlockCRC = c_calculatedBlockCRC;
00705 s->state_out_ch = c_state_out_ch;
00706 s->state_out_len = c_state_out_len;
00707 s->nblock_used = c_nblock_used;
00708 s->k0 = c_k0;
00709 s->tt = c_tt;
00710 s->tPos = c_tPos;
00711 s->strm->next_out = cs_next_out;
00712 s->strm->avail_out = cs_avail_out;
00713
00714 }
00715 }
00716
00717
00718
00719
00720 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
00721 {
00722 Int32 nb, na, mid;
00723 nb = 0;
00724 na = 256;
00725 do {
00726 mid = (nb + na) >> 1;
00727 if (indx >= cftab[mid]) nb = mid; else na = mid;
00728 }
00729 while (na - nb != 1);
00730 return nb;
00731 }
00732
00733
00734
00735 static
00736 void unRLE_obuf_to_output_SMALL ( DState* s )
00737 {
00738 UChar k1;
00739
00740 if (s->blockRandomised) {
00741
00742 while (True) {
00743
00744 while (True) {
00745 if (s->strm->avail_out == 0) return;
00746 if (s->state_out_len == 0) break;
00747 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
00748 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
00749 s->state_out_len--;
00750 s->strm->next_out++;
00751 s->strm->avail_out--;
00752 s->strm->total_out_lo32++;
00753 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
00754 }
00755
00756
00757 if (s->nblock_used == s->save_nblock+1) return;
00758
00759
00760 s->state_out_len = 1;
00761 s->state_out_ch = s->k0;
00762 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
00763 k1 ^= BZ_RAND_MASK; s->nblock_used++;
00764 if (s->nblock_used == s->save_nblock+1) continue;
00765 if (k1 != s->k0) { s->k0 = k1; continue; };
00766
00767 s->state_out_len = 2;
00768 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
00769 k1 ^= BZ_RAND_MASK; s->nblock_used++;
00770 if (s->nblock_used == s->save_nblock+1) continue;
00771 if (k1 != s->k0) { s->k0 = k1; continue; };
00772
00773 s->state_out_len = 3;
00774 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
00775 k1 ^= BZ_RAND_MASK; s->nblock_used++;
00776 if (s->nblock_used == s->save_nblock+1) continue;
00777 if (k1 != s->k0) { s->k0 = k1; continue; };
00778
00779 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
00780 k1 ^= BZ_RAND_MASK; s->nblock_used++;
00781 s->state_out_len = ((Int32)k1) + 4;
00782 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
00783 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
00784 }
00785
00786 } else {
00787
00788 while (True) {
00789
00790 while (True) {
00791 if (s->strm->avail_out == 0) return;
00792 if (s->state_out_len == 0) break;
00793 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
00794 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
00795 s->state_out_len--;
00796 s->strm->next_out++;
00797 s->strm->avail_out--;
00798 s->strm->total_out_lo32++;
00799 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
00800 }
00801
00802
00803 if (s->nblock_used == s->save_nblock+1) return;
00804
00805 s->state_out_len = 1;
00806 s->state_out_ch = s->k0;
00807 BZ_GET_SMALL(k1); s->nblock_used++;
00808 if (s->nblock_used == s->save_nblock+1) continue;
00809 if (k1 != s->k0) { s->k0 = k1; continue; };
00810
00811 s->state_out_len = 2;
00812 BZ_GET_SMALL(k1); s->nblock_used++;
00813 if (s->nblock_used == s->save_nblock+1) continue;
00814 if (k1 != s->k0) { s->k0 = k1; continue; };
00815
00816 s->state_out_len = 3;
00817 BZ_GET_SMALL(k1); s->nblock_used++;
00818 if (s->nblock_used == s->save_nblock+1) continue;
00819 if (k1 != s->k0) { s->k0 = k1; continue; };
00820
00821 BZ_GET_SMALL(k1); s->nblock_used++;
00822 s->state_out_len = ((Int32)k1) + 4;
00823 BZ_GET_SMALL(s->k0); s->nblock_used++;
00824 }
00825
00826 }
00827 }
00828
00829
00830
00831 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
00832 {
00833 DState* s;
00834 if (strm == NULL) return BZ_PARAM_ERROR;
00835 s = strm->state;
00836 if (s == NULL) return BZ_PARAM_ERROR;
00837 if (s->strm != strm) return BZ_PARAM_ERROR;
00838
00839 while (True) {
00840 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
00841 if (s->state == BZ_X_OUTPUT) {
00842 if (s->smallDecompress)
00843 unRLE_obuf_to_output_SMALL ( s ); else
00844 unRLE_obuf_to_output_FAST ( s );
00845 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
00846 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
00847 if (s->verbosity >= 3)
00848 VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC,
00849 s->calculatedBlockCRC );
00850 if (s->verbosity >= 2) VPrintf0 ( "]" );
00851 if (s->calculatedBlockCRC != s->storedBlockCRC)
00852 return BZ_DATA_ERROR;
00853 s->calculatedCombinedCRC
00854 = (s->calculatedCombinedCRC << 1) |
00855 (s->calculatedCombinedCRC >> 31);
00856 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
00857 s->state = BZ_X_BLKHDR_1;
00858 } else {
00859 return BZ_OK;
00860 }
00861 }
00862 if (s->state >= BZ_X_MAGIC_1) {
00863 Int32 r = BZ2_decompress ( s );
00864 if (r == BZ_STREAM_END) {
00865 if (s->verbosity >= 3)
00866 VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x",
00867 s->storedCombinedCRC, s->calculatedCombinedCRC );
00868 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
00869 return BZ_DATA_ERROR;
00870 return r;
00871 }
00872 if (s->state != BZ_X_OUTPUT) return r;
00873 }
00874 }
00875
00876 AssertH ( 0, 6001 );
00877
00878 return 0;
00879 }
00880
00881
00882
00883 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
00884 {
00885 DState* s;
00886 if (strm == NULL) return BZ_PARAM_ERROR;
00887 s = strm->state;
00888 if (s == NULL) return BZ_PARAM_ERROR;
00889 if (s->strm != strm) return BZ_PARAM_ERROR;
00890
00891 if (s->tt != NULL) BZFREE(s->tt);
00892 if (s->ll16 != NULL) BZFREE(s->ll16);
00893 if (s->ll4 != NULL) BZFREE(s->ll4);
00894
00895 BZFREE(strm->state);
00896 strm->state = NULL;
00897
00898 return BZ_OK;
00899 }
00900
00901
00902 #ifndef BZ_NO_STDIO
00903
00904
00905
00906
00907 #define BZ_SETERR(eee) \
00908 { \
00909 if (bzerror != NULL) *bzerror = eee; \
00910 if (bzf != NULL) bzf->lastErr = eee; \
00911 }
00912
00913 typedef
00914 struct {
00915 FILE* handle;
00916 Char buf[BZ_MAX_UNUSED];
00917 Int32 bufN;
00918 Bool writing;
00919 bz_stream strm;
00920 Int32 lastErr;
00921 Bool initialisedOk;
00922 }
00923 bzFile;
00924
00925
00926
00927 static Bool myfeof ( FILE* f )
00928 {
00929 Int32 c = fgetc ( f );
00930 if (c == EOF) return True;
00931 ungetc ( c, f );
00932 return False;
00933 }
00934
00935
00936
00937 BZFILE* BZ_API(BZ2_bzWriteOpen)
00938 ( int* bzerror,
00939 FILE* f,
00940 int blockSize100k,
00941 int verbosity,
00942 int workFactor )
00943 {
00944 Int32 ret;
00945 bzFile* bzf = NULL;
00946
00947 BZ_SETERR(BZ_OK);
00948
00949 if (f == NULL ||
00950 (blockSize100k < 1 || blockSize100k > 9) ||
00951 (workFactor < 0 || workFactor > 250) ||
00952 (verbosity < 0 || verbosity > 4))
00953 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
00954
00955 if (ferror(f))
00956 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
00957
00958 bzf = malloc ( sizeof(bzFile) );
00959 if (bzf == NULL)
00960 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
00961
00962 BZ_SETERR(BZ_OK);
00963 bzf->initialisedOk = False;
00964 bzf->bufN = 0;
00965 bzf->handle = f;
00966 bzf->writing = True;
00967 bzf->strm.bzalloc = NULL;
00968 bzf->strm.bzfree = NULL;
00969 bzf->strm.opaque = NULL;
00970
00971 if (workFactor == 0) workFactor = 30;
00972 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
00973 verbosity, workFactor );
00974 if (ret != BZ_OK)
00975 { BZ_SETERR(ret); free(bzf); return NULL; };
00976
00977 bzf->strm.avail_in = 0;
00978 bzf->initialisedOk = True;
00979 return bzf;
00980 }
00981
00982
00983
00984
00985 void BZ_API(BZ2_bzWrite)
00986 ( int* bzerror,
00987 BZFILE* b,
00988 void* buf,
00989 int len )
00990 {
00991 Int32 n, n2, ret;
00992 bzFile* bzf = (bzFile*)b;
00993
00994 BZ_SETERR(BZ_OK);
00995 if (bzf == NULL || buf == NULL || len < 0)
00996 { BZ_SETERR(BZ_PARAM_ERROR); return; };
00997 if (!(bzf->writing))
00998 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
00999 if (ferror(bzf->handle))
01000 { BZ_SETERR(BZ_IO_ERROR); return; };
01001
01002 if (len == 0)
01003 { BZ_SETERR(BZ_OK); return; };
01004
01005 bzf->strm.avail_in = len;
01006 bzf->strm.next_in = buf;
01007
01008 while (True) {
01009 bzf->strm.avail_out = BZ_MAX_UNUSED;
01010 bzf->strm.next_out = bzf->buf;
01011 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
01012 if (ret != BZ_RUN_OK)
01013 { BZ_SETERR(ret); return; };
01014
01015 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
01016 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
01017 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
01018 n, bzf->handle );
01019 if (n != n2 || ferror(bzf->handle))
01020 { BZ_SETERR(BZ_IO_ERROR); return; };
01021 }
01022
01023 if (bzf->strm.avail_in == 0)
01024 { BZ_SETERR(BZ_OK); return; };
01025 }
01026 }
01027
01028
01029
01030 void BZ_API(BZ2_bzWriteClose)
01031 ( int* bzerror,
01032 BZFILE* b,
01033 int abandon,
01034 unsigned int* nbytes_in,
01035 unsigned int* nbytes_out )
01036 {
01037 BZ2_bzWriteClose64 ( bzerror, b, abandon,
01038 nbytes_in, NULL, nbytes_out, NULL );
01039 }
01040
01041
01042 void BZ_API(BZ2_bzWriteClose64)
01043 ( int* bzerror,
01044 BZFILE* b,
01045 int abandon,
01046 unsigned int* nbytes_in_lo32,
01047 unsigned int* nbytes_in_hi32,
01048 unsigned int* nbytes_out_lo32,
01049 unsigned int* nbytes_out_hi32 )
01050 {
01051 Int32 n, n2, ret;
01052 bzFile* bzf = (bzFile*)b;
01053
01054 if (bzf == NULL)
01055 { BZ_SETERR(BZ_OK); return; };
01056 if (!(bzf->writing))
01057 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
01058 if (ferror(bzf->handle))
01059 { BZ_SETERR(BZ_IO_ERROR); return; };
01060
01061 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
01062 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
01063 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
01064 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
01065
01066 if ((!abandon) && bzf->lastErr == BZ_OK) {
01067 while (True) {
01068 bzf->strm.avail_out = BZ_MAX_UNUSED;
01069 bzf->strm.next_out = bzf->buf;
01070 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
01071 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
01072 { BZ_SETERR(ret); return; };
01073
01074 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
01075 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
01076 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
01077 n, bzf->handle );
01078 if (n != n2 || ferror(bzf->handle))
01079 { BZ_SETERR(BZ_IO_ERROR); return; };
01080 }
01081
01082 if (ret == BZ_STREAM_END) break;
01083 }
01084 }
01085
01086 if ( !abandon && !ferror ( bzf->handle ) ) {
01087 fflush ( bzf->handle );
01088 if (ferror(bzf->handle))
01089 { BZ_SETERR(BZ_IO_ERROR); return; };
01090 }
01091
01092 if (nbytes_in_lo32 != NULL)
01093 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
01094 if (nbytes_in_hi32 != NULL)
01095 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
01096 if (nbytes_out_lo32 != NULL)
01097 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
01098 if (nbytes_out_hi32 != NULL)
01099 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
01100
01101 BZ_SETERR(BZ_OK);
01102 BZ2_bzCompressEnd ( &(bzf->strm) );
01103 free ( bzf );
01104 }
01105
01106
01107
01108 BZFILE* BZ_API(BZ2_bzReadOpen)
01109 ( int* bzerror,
01110 FILE* f,
01111 int verbosity,
01112 int small,
01113 void* unused,
01114 int nUnused )
01115 {
01116 bzFile* bzf = NULL;
01117 int ret;
01118
01119 BZ_SETERR(BZ_OK);
01120
01121 if (f == NULL ||
01122 (small != 0 && small != 1) ||
01123 (verbosity < 0 || verbosity > 4) ||
01124 (unused == NULL && nUnused != 0) ||
01125 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
01126 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
01127
01128 if (ferror(f))
01129 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
01130
01131 bzf = malloc ( sizeof(bzFile) );
01132 if (bzf == NULL)
01133 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
01134
01135 BZ_SETERR(BZ_OK);
01136
01137 bzf->initialisedOk = False;
01138 bzf->handle = f;
01139 bzf->bufN = 0;
01140 bzf->writing = False;
01141 bzf->strm.bzalloc = NULL;
01142 bzf->strm.bzfree = NULL;
01143 bzf->strm.opaque = NULL;
01144
01145 while (nUnused > 0) {
01146 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
01147 unused = ((void*)( 1 + ((UChar*)(unused)) ));
01148 nUnused--;
01149 }
01150
01151 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
01152 if (ret != BZ_OK)
01153 { BZ_SETERR(ret); free(bzf); return NULL; };
01154
01155 bzf->strm.avail_in = bzf->bufN;
01156 bzf->strm.next_in = bzf->buf;
01157
01158 bzf->initialisedOk = True;
01159 return bzf;
01160 }
01161
01162
01163
01164 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
01165 {
01166 bzFile* bzf = (bzFile*)b;
01167
01168 BZ_SETERR(BZ_OK);
01169 if (bzf == NULL)
01170 { BZ_SETERR(BZ_OK); return; };
01171
01172 if (bzf->writing)
01173 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
01174
01175 if (bzf->initialisedOk)
01176 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
01177 free ( bzf );
01178 }
01179
01180
01181
01182 int BZ_API(BZ2_bzRead)
01183 ( int* bzerror,
01184 BZFILE* b,
01185 void* buf,
01186 int len )
01187 {
01188 Int32 n, ret;
01189 bzFile* bzf = (bzFile*)b;
01190
01191 BZ_SETERR(BZ_OK);
01192
01193 if (bzf == NULL || buf == NULL || len < 0)
01194 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
01195
01196 if (bzf->writing)
01197 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
01198
01199 if (len == 0)
01200 { BZ_SETERR(BZ_OK); return 0; };
01201
01202 bzf->strm.avail_out = len;
01203 bzf->strm.next_out = buf;
01204
01205 while (True) {
01206
01207 if (ferror(bzf->handle))
01208 { BZ_SETERR(BZ_IO_ERROR); return 0; };
01209
01210 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
01211 n = fread ( bzf->buf, sizeof(UChar),
01212 BZ_MAX_UNUSED, bzf->handle );
01213 if (ferror(bzf->handle))
01214 { BZ_SETERR(BZ_IO_ERROR); return 0; };
01215 bzf->bufN = n;
01216 bzf->strm.avail_in = bzf->bufN;
01217 bzf->strm.next_in = bzf->buf;
01218 }
01219
01220 ret = BZ2_bzDecompress ( &(bzf->strm) );
01221
01222 if (ret != BZ_OK && ret != BZ_STREAM_END)
01223 { BZ_SETERR(ret); return 0; };
01224
01225 if (ret == BZ_OK && myfeof(bzf->handle) &&
01226 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
01227 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
01228
01229 if (ret == BZ_STREAM_END)
01230 { BZ_SETERR(BZ_STREAM_END);
01231 return len - bzf->strm.avail_out; };
01232 if (bzf->strm.avail_out == 0)
01233 { BZ_SETERR(BZ_OK); return len; };
01234
01235 }
01236
01237 return 0;
01238 }
01239
01240
01241
01242 void BZ_API(BZ2_bzReadGetUnused)
01243 ( int* bzerror,
01244 BZFILE* b,
01245 void** unused,
01246 int* nUnused )
01247 {
01248 bzFile* bzf = (bzFile*)b;
01249 if (bzf == NULL)
01250 { BZ_SETERR(BZ_PARAM_ERROR); return; };
01251 if (bzf->lastErr != BZ_STREAM_END)
01252 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
01253 if (unused == NULL || nUnused == NULL)
01254 { BZ_SETERR(BZ_PARAM_ERROR); return; };
01255
01256 BZ_SETERR(BZ_OK);
01257 *nUnused = bzf->strm.avail_in;
01258 *unused = bzf->strm.next_in;
01259 }
01260 #endif
01261
01262
01263
01264
01265
01266
01267
01268 int BZ_API(BZ2_bzBuffToBuffCompress)
01269 ( char* dest,
01270 unsigned int* destLen,
01271 char* source,
01272 unsigned int sourceLen,
01273 int blockSize100k,
01274 int verbosity,
01275 int workFactor )
01276 {
01277 bz_stream strm;
01278 int ret;
01279
01280 if (dest == NULL || destLen == NULL ||
01281 source == NULL ||
01282 blockSize100k < 1 || blockSize100k > 9 ||
01283 verbosity < 0 || verbosity > 4 ||
01284 workFactor < 0 || workFactor > 250)
01285 return BZ_PARAM_ERROR;
01286
01287 if (workFactor == 0) workFactor = 30;
01288 strm.bzalloc = NULL;
01289 strm.bzfree = NULL;
01290 strm.opaque = NULL;
01291 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
01292 verbosity, workFactor );
01293 if (ret != BZ_OK) return ret;
01294
01295 strm.next_in = source;
01296 strm.next_out = dest;
01297 strm.avail_in = sourceLen;
01298 strm.avail_out = *destLen;
01299
01300 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
01301 if (ret == BZ_FINISH_OK) goto output_overflow;
01302 if (ret != BZ_STREAM_END) goto errhandler;
01303
01304
01305 *destLen -= strm.avail_out;
01306 BZ2_bzCompressEnd ( &strm );
01307 return BZ_OK;
01308
01309 output_overflow:
01310 BZ2_bzCompressEnd ( &strm );
01311 return BZ_OUTBUFF_FULL;
01312
01313 errhandler:
01314 BZ2_bzCompressEnd ( &strm );
01315 return ret;
01316 }
01317
01318
01319
01320 int BZ_API(BZ2_bzBuffToBuffDecompress)
01321 ( char* dest,
01322 unsigned int* destLen,
01323 char* source,
01324 unsigned int sourceLen,
01325 int small,
01326 int verbosity )
01327 {
01328 bz_stream strm;
01329 int ret;
01330
01331 if (dest == NULL || destLen == NULL ||
01332 source == NULL ||
01333 (small != 0 && small != 1) ||
01334 verbosity < 0 || verbosity > 4)
01335 return BZ_PARAM_ERROR;
01336
01337 strm.bzalloc = NULL;
01338 strm.bzfree = NULL;
01339 strm.opaque = NULL;
01340 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
01341 if (ret != BZ_OK) return ret;
01342
01343 strm.next_in = source;
01344 strm.next_out = dest;
01345 strm.avail_in = sourceLen;
01346 strm.avail_out = *destLen;
01347
01348 ret = BZ2_bzDecompress ( &strm );
01349 if (ret == BZ_OK) goto output_overflow_or_eof;
01350 if (ret != BZ_STREAM_END) goto errhandler;
01351
01352
01353 *destLen -= strm.avail_out;
01354 BZ2_bzDecompressEnd ( &strm );
01355 return BZ_OK;
01356
01357 output_overflow_or_eof:
01358 if (strm.avail_out > 0) {
01359 BZ2_bzDecompressEnd ( &strm );
01360 return BZ_UNEXPECTED_EOF;
01361 } else {
01362 BZ2_bzDecompressEnd ( &strm );
01363 return BZ_OUTBUFF_FULL;
01364 };
01365
01366 errhandler:
01367 BZ2_bzDecompressEnd ( &strm );
01368 return ret;
01369 }
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388 const char * BZ_API(BZ2_bzlibVersion)(void)
01389 {
01390 return BZ_VERSION;
01391 }
01392
01393
01394 #ifndef BZ_NO_STDIO
01395
01396
01397 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
01398 # include <fcntl.h>
01399 # include <io.h>
01400 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
01401 #else
01402 # define SET_BINARY_MODE(file)
01403 #endif
01404 static
01405 BZFILE * bzopen_or_bzdopen
01406 ( const char *path,
01407 int fd,
01408 const char *mode,
01409 int open_mode)
01410 {
01411 int bzerr;
01412 char unused[BZ_MAX_UNUSED];
01413 int blockSize100k = 9;
01414 int writing = 0;
01415 char mode2[10] = "";
01416 FILE *fp = NULL;
01417 BZFILE *bzfp = NULL;
01418 int verbosity = 0;
01419 int workFactor = 30;
01420 int smallMode = 0;
01421 int nUnused = 0;
01422
01423 if (mode == NULL) return NULL;
01424 while (*mode) {
01425 switch (*mode) {
01426 case 'r':
01427 writing = 0; break;
01428 case 'w':
01429 writing = 1; break;
01430 case 's':
01431 smallMode = 1; break;
01432 default:
01433 if (isdigit((int)(*mode))) {
01434 blockSize100k = *mode-BZ_HDR_0;
01435 }
01436 }
01437 mode++;
01438 }
01439 strcat(mode2, writing ? "w" : "r" );
01440 strcat(mode2,"b");
01441
01442 if (open_mode==0) {
01443 if (path==NULL || strcmp(path,"")==0) {
01444 fp = (writing ? stdout : stdin);
01445 SET_BINARY_MODE(fp);
01446 } else {
01447 fp = fopen(path,mode2);
01448 }
01449 } else {
01450 #ifdef BZ_STRICT_ANSI
01451 fp = NULL;
01452 #else
01453 fp = fdopen(fd,mode2);
01454 #endif
01455 }
01456 if (fp == NULL) return NULL;
01457
01458 if (writing) {
01459
01460 if (blockSize100k < 1) blockSize100k = 1;
01461 if (blockSize100k > 9) blockSize100k = 9;
01462 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
01463 verbosity,workFactor);
01464 } else {
01465 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
01466 unused,nUnused);
01467 }
01468 if (bzfp == NULL) {
01469 if (fp != stdin && fp != stdout) fclose(fp);
01470 return NULL;
01471 }
01472 return bzfp;
01473 }
01474
01475
01476
01477
01478
01479
01480
01481
01482 BZFILE * BZ_API(BZ2_bzopen)
01483 ( const char *path,
01484 const char *mode )
01485 {
01486 return bzopen_or_bzdopen(path,-1,mode,0);
01487 }
01488
01489
01490
01491 BZFILE * BZ_API(BZ2_bzdopen)
01492 ( int fd,
01493 const char *mode )
01494 {
01495 return bzopen_or_bzdopen(NULL,fd,mode,1);
01496 }
01497
01498
01499
01500 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
01501 {
01502 int bzerr, nread;
01503 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
01504 nread = BZ2_bzRead(&bzerr,b,buf,len);
01505 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
01506 return nread;
01507 } else {
01508 return -1;
01509 }
01510 }
01511
01512
01513
01514 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
01515 {
01516 int bzerr;
01517
01518 BZ2_bzWrite(&bzerr,b,buf,len);
01519 if(bzerr == BZ_OK){
01520 return len;
01521 }else{
01522 return -1;
01523 }
01524 }
01525
01526
01527
01528 int BZ_API(BZ2_bzflush) (BZFILE *b)
01529 {
01530
01531 return 0;
01532 }
01533
01534
01535
01536 void BZ_API(BZ2_bzclose) (BZFILE* b)
01537 {
01538 int bzerr;
01539 FILE *fp = ((bzFile *)b)->handle;
01540
01541 if (b==NULL) {return;}
01542 if(((bzFile*)b)->writing){
01543 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
01544 if(bzerr != BZ_OK){
01545 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
01546 }
01547 }else{
01548 BZ2_bzReadClose(&bzerr,b);
01549 }
01550 if(fp!=stdin && fp!=stdout){
01551 fclose(fp);
01552 }
01553 }
01554
01555
01556
01557
01558
01559
01560 static char *bzerrorstrings[] = {
01561 "OK"
01562 ,"SEQUENCE_ERROR"
01563 ,"PARAM_ERROR"
01564 ,"MEM_ERROR"
01565 ,"DATA_ERROR"
01566 ,"DATA_ERROR_MAGIC"
01567 ,"IO_ERROR"
01568 ,"UNEXPECTED_EOF"
01569 ,"OUTBUFF_FULL"
01570 ,"CONFIG_ERROR"
01571 ,"???"
01572 ,"???"
01573 ,"???"
01574 ,"???"
01575 ,"???"
01576 ,"???"
01577 };
01578
01579
01580 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
01581 {
01582 int err = ((bzFile *)b)->lastErr;
01583
01584 if(err>0) err = 0;
01585 *errnum = err;
01586 return bzerrorstrings[err*-1];
01587 }
01588 #endif
01589
01590
01591
01592
01593
01594
01595