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