LLVM API Documentation
00001 00002 /*-------------------------------------------------------------*/ 00003 /*--- Library top-level functions. ---*/ 00004 /*--- bzlib.c ---*/ 00005 /*-------------------------------------------------------------*/ 00006 00007 /*-- 00008 This file is a part of bzip2 and/or libbzip2, a program and 00009 library for lossless, block-sorting data compression. 00010 00011 Copyright (C) 1996-2002 Julian R Seward. All rights reserved. 00012 00013 Redistribution and use in source and binary forms, with or without 00014 modification, are permitted provided that the following conditions 00015 are met: 00016 00017 1. Redistributions of source code must retain the above copyright 00018 notice, this list of conditions and the following disclaimer. 00019 00020 2. The origin of this software must not be misrepresented; you must 00021 not claim that you wrote the original software. If you use this 00022 software in a product, an acknowledgment in the product 00023 documentation would be appreciated but is not required. 00024 00025 3. Altered source versions must be plainly marked as such, and must 00026 not be misrepresented as being the original software. 00027 00028 4. The name of the author may not be used to endorse or promote 00029 products derived from this software without specific prior written 00030 permission. 00031 00032 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 00033 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00034 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00035 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00036 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00037 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00038 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00039 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00040 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00041 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00042 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00043 00044 Julian Seward, Cambridge, UK. 00045 jseward@acm.org 00046 bzip2/libbzip2 version 1.0 of 21 March 2000 00047 00048 This program is based on (at least) the work of: 00049 Mike Burrows 00050 David Wheeler 00051 Peter Fenwick 00052 Alistair Moffat 00053 Radford Neal 00054 Ian H. Witten 00055 Robert Sedgewick 00056 Jon L. Bentley 00057 00058 For more information on these sources, see the manual. 00059 --*/ 00060 00061 /*-- 00062 CHANGES 00063 ~~~~~~~ 00064 0.9.0 -- original version. 00065 00066 0.9.0a/b -- no changes in this file. 00067 00068 0.9.0c 00069 * made zero-length BZ_FLUSH work correctly in bzCompress(). 00070 * fixed bzWrite/bzRead to ignore zero-length requests. 00071 * fixed bzread to correctly handle read requests after EOF. 00072 * wrong parameter order in call to bzDecompressInit in 00073 bzBuffToBuffDecompress. Fixed. 00074 --*/ 00075 00076 #include "bzlib_private.h" 00077 00078 00079 /*---------------------------------------------------*/ 00080 /*--- Compression stuff ---*/ 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 /*-- fast track the common case --*/ \ 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 /*-- general, uncommon cases --*/ \ 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 /*-- fast track the common case --*/ 00341 while (True) { 00342 /*-- block full? --*/ 00343 if (s->nblock >= s->nblockMAX) break; 00344 /*-- no input? --*/ 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 /*-- general, uncommon case --*/ 00357 while (True) { 00358 /*-- block full? --*/ 00359 if (s->nblock >= s->nblockMAX) break; 00360 /*-- no input? --*/ 00361 if (s->strm->avail_in == 0) break; 00362 /*-- flush/finish end? --*/ 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 /*-- no output space? --*/ 00386 if (s->strm->avail_out == 0) break; 00387 00388 /*-- block done? --*/ 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; /*--not reached--*/ 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 /*--- Decompression stuff ---*/ 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 /* try to finish existing run */ 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 /* can a new run be started? */ 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 /* restore */ 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 /* end restore */ 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 /* try to finish existing run */ 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 /* can a new run be started? */ 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 /* save */ 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 /* end save */ 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 /* try to finish existing run */ 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 /* can a new run be started? */ 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 /* try to finish existing run */ 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 /* can a new run be started? */ 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; /*NOTREACHED*/ 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 /*--- File I/O stuff ---*/ 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; /*not reached*/ 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 /*--- Misc convenience stuff ---*/ 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 /* normal termination */ 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 /* normal termination */ 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 Code contributed by Yoshioka Tsuneo 01375 (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp), 01376 to support better zlib compatibility. 01377 This code is not _officially_ part of libbzip2 (yet); 01378 I haven't tested it, documented it, or considered the 01379 threading-safeness of it. 01380 If this code breaks, please contact both Yoshioka and me. 01381 --*/ 01382 /*---------------------------------------------------*/ 01383 01384 /*---------------------------------------------------*/ 01385 /*-- 01386 return version like "0.9.0c". 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, /* no use when bzdopen */ 01407 int fd, /* no use when bzdopen */ 01408 const char *mode, 01409 int open_mode) /* bzopen: 0, bzdopen:1 */ 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"); /* binary mode */ 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 /* Guard against total chaos and anarchy -- JRS */ 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 open file for read or write. 01479 ex) bzopen("file","w9") 01480 case path="" or NULL => use stdin or stdout. 01481 --*/ 01482 BZFILE * BZ_API(BZ2_bzopen) 01483 ( const char *path, 01484 const char *mode ) 01485 { 01486 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/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,/*bzdopen*/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 /* do nothing now... */ 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 return last error code 01559 --*/ 01560 static const 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 ,"???" /* for future */ 01572 ,"???" /* for future */ 01573 ,"???" /* for future */ 01574 ,"???" /* for future */ 01575 ,"???" /* for future */ 01576 ,"???" /* for future */ 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 /*--- end bzlib.c ---*/ 01593 /*-------------------------------------------------------------*/