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