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