| #include <config.h> | |
| #include <common.h> | |
| #include <watchdog.h> | |
| /* | |
| * This file is a modified version of bzlib.c from the bzip2-1.0.2 | |
| * distribution which can be found at http://sources.redhat.com/bzip2/ | |
| */ | |
| /*-------------------------------------------------------------*/ | |
| /*--- Library top-level functions. ---*/ | |
| /*--- bzlib.c ---*/ | |
| /*-------------------------------------------------------------*/ | |
| /*-- | |
| This file is a part of bzip2 and/or libbzip2, a program and | |
| library for lossless, block-sorting data compression. | |
| Copyright (C) 1996-2002 Julian R Seward. All rights reserved. | |
| Redistribution and use in source and binary forms, with or without | |
| modification, are permitted provided that the following conditions | |
| are met: | |
| 1. Redistributions of source code must retain the above copyright | |
| notice, this list of conditions and the following disclaimer. | |
| 2. The origin of this software must not be misrepresented; you must | |
| not claim that you wrote the original software. If you use this | |
| software in a product, an acknowledgment in the product | |
| documentation would be appreciated but is not required. | |
| 3. Altered source versions must be plainly marked as such, and must | |
| not be misrepresented as being the original software. | |
| 4. The name of the author may not be used to endorse or promote | |
| products derived from this software without specific prior written | |
| permission. | |
| THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS | |
| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | |
| GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
| INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
| WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| Julian Seward, Cambridge, UK. | |
| jseward@acm.org | |
| bzip2/libbzip2 version 1.0 of 21 March 2000 | |
| This program is based on (at least) the work of: | |
| Mike Burrows | |
| David Wheeler | |
| Peter Fenwick | |
| Alistair Moffat | |
| Radford Neal | |
| Ian H. Witten | |
| Robert Sedgewick | |
| Jon L. Bentley | |
| For more information on these sources, see the manual. | |
| --*/ | |
| /*-- | |
| CHANGES | |
| ~~~~~~~ | |
| 0.9.0 -- original version. | |
| 0.9.0a/b -- no changes in this file. | |
| 0.9.0c | |
| * made zero-length BZ_FLUSH work correctly in bzCompress(). | |
| * fixed bzWrite/bzRead to ignore zero-length requests. | |
| * fixed bzread to correctly handle read requests after EOF. | |
| * wrong parameter order in call to bzDecompressInit in | |
| bzBuffToBuffDecompress. Fixed. | |
| --*/ | |
| #include "bzlib_private.h" | |
| /*---------------------------------------------------*/ | |
| /*--- Compression stuff ---*/ | |
| /*---------------------------------------------------*/ | |
| /*---------------------------------------------------*/ | |
| #ifndef BZ_NO_STDIO | |
| void BZ2_bz__AssertH__fail ( int errcode ) | |
| { | |
| fprintf(stderr, | |
| "\n\nbzip2/libbzip2: internal error number %d.\n" | |
| "This is a bug in bzip2/libbzip2, %s.\n" | |
| "Please report it to me at: jseward@acm.org. If this happened\n" | |
| "when you were using some program which uses libbzip2 as a\n" | |
| "component, you should also report this bug to the author(s)\n" | |
| "of that program. Please make an effort to report this bug;\n" | |
| "timely and accurate bug reports eventually lead to higher\n" | |
| "quality software. Thanks. Julian Seward, 30 December 2001.\n\n", | |
| errcode, | |
| BZ2_bzlibVersion() | |
| ); | |
| if (errcode == 1007) { | |
| fprintf(stderr, | |
| "\n*** A special note about internal error number 1007 ***\n" | |
| "\n" | |
| "Experience suggests that a common cause of i.e. 1007\n" | |
| "is unreliable memory or other hardware. The 1007 assertion\n" | |
| "just happens to cross-check the results of huge numbers of\n" | |
| "memory reads/writes, and so acts (unintendedly) as a stress\n" | |
| "test of your memory system.\n" | |
| "\n" | |
| "I suggest the following: try compressing the file again,\n" | |
| "possibly monitoring progress in detail with the -vv flag.\n" | |
| "\n" | |
| "* If the error cannot be reproduced, and/or happens at different\n" | |
| " points in compression, you may have a flaky memory system.\n" | |
| " Try a memory-test program. I have used Memtest86\n" | |
| " (www.memtest86.com). At the time of writing it is free (GPLd).\n" | |
| " Memtest86 tests memory much more thorougly than your BIOSs\n" | |
| " power-on test, and may find failures that the BIOS doesn't.\n" | |
| "\n" | |
| "* If the error can be repeatably reproduced, this is a bug in\n" | |
| " bzip2, and I would very much like to hear about it. Please\n" | |
| " let me know, and, ideally, save a copy of the file causing the\n" | |
| " problem -- without which I will be unable to investigate it.\n" | |
| "\n" | |
| ); | |
| } | |
| exit(3); | |
| } | |
| #endif | |
| /*---------------------------------------------------*/ | |
| static | |
| int bz_config_ok ( void ) | |
| { | |
| if (sizeof(int) != 4) return 0; | |
| if (sizeof(short) != 2) return 0; | |
| if (sizeof(char) != 1) return 0; | |
| return 1; | |
| } | |
| /*---------------------------------------------------*/ | |
| static | |
| void* default_bzalloc ( void* opaque, Int32 items, Int32 size ) | |
| { | |
| void* v = malloc ( items * size ); | |
| return v; | |
| } | |
| static | |
| void default_bzfree ( void* opaque, void* addr ) | |
| { | |
| if (addr != NULL) free ( addr ); | |
| } | |
| #ifndef BZ_NO_COMPRESS | |
| /*---------------------------------------------------*/ | |
| static | |
| void prepare_new_block ( EState* s ) | |
| { | |
| Int32 i; | |
| s->nblock = 0; | |
| s->numZ = 0; | |
| s->state_out_pos = 0; | |
| BZ_INITIALISE_CRC ( s->blockCRC ); | |
| for (i = 0; i < 256; i++) s->inUse[i] = False; | |
| s->blockNo++; | |
| } | |
| /*---------------------------------------------------*/ | |
| static | |
| void init_RL ( EState* s ) | |
| { | |
| s->state_in_ch = 256; | |
| s->state_in_len = 0; | |
| } | |
| static | |
| Bool isempty_RL ( EState* s ) | |
| { | |
| if (s->state_in_ch < 256 && s->state_in_len > 0) | |
| return False; else | |
| return True; | |
| } | |
| /*---------------------------------------------------*/ | |
| int BZ_API(BZ2_bzCompressInit) | |
| ( bz_stream* strm, | |
| int blockSize100k, | |
| int verbosity, | |
| int workFactor ) | |
| { | |
| Int32 n; | |
| EState* s; | |
| if (!bz_config_ok()) return BZ_CONFIG_ERROR; | |
| if (strm == NULL || | |
| blockSize100k < 1 || blockSize100k > 9 || | |
| workFactor < 0 || workFactor > 250) | |
| return BZ_PARAM_ERROR; | |
| if (workFactor == 0) workFactor = 30; | |
| if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; | |
| if (strm->bzfree == NULL) strm->bzfree = default_bzfree; | |
| s = BZALLOC( sizeof(EState) ); | |
| if (s == NULL) return BZ_MEM_ERROR; | |
| s->strm = strm; | |
| s->arr1 = NULL; | |
| s->arr2 = NULL; | |
| s->ftab = NULL; | |
| n = 100000 * blockSize100k; | |
| s->arr1 = BZALLOC( n * sizeof(UInt32) ); | |
| s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) ); | |
| s->ftab = BZALLOC( 65537 * sizeof(UInt32) ); | |
| if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) { | |
| if (s->arr1 != NULL) BZFREE(s->arr1); | |
| if (s->arr2 != NULL) BZFREE(s->arr2); | |
| if (s->ftab != NULL) BZFREE(s->ftab); | |
| if (s != NULL) BZFREE(s); | |
| return BZ_MEM_ERROR; | |
| } | |
| s->blockNo = 0; | |
| s->state = BZ_S_INPUT; | |
| s->mode = BZ_M_RUNNING; | |
| s->combinedCRC = 0; | |
| s->blockSize100k = blockSize100k; | |
| s->nblockMAX = 100000 * blockSize100k - 19; | |
| s->verbosity = verbosity; | |
| s->workFactor = workFactor; | |
| s->block = (UChar*)s->arr2; | |
| s->mtfv = (UInt16*)s->arr1; | |
| s->zbits = NULL; | |
| s->ptr = (UInt32*)s->arr1; | |
| strm->state = s; | |
| strm->total_in_lo32 = 0; | |
| strm->total_in_hi32 = 0; | |
| strm->total_out_lo32 = 0; | |
| strm->total_out_hi32 = 0; | |
| init_RL ( s ); | |
| prepare_new_block ( s ); | |
| return BZ_OK; | |
| } | |
| /*---------------------------------------------------*/ | |
| static | |
| void add_pair_to_block ( EState* s ) | |
| { | |
| Int32 i; | |
| UChar ch = (UChar)(s->state_in_ch); | |
| for (i = 0; i < s->state_in_len; i++) { | |
| BZ_UPDATE_CRC( s->blockCRC, ch ); | |
| } | |
| s->inUse[s->state_in_ch] = True; | |
| switch (s->state_in_len) { | |
| case 1: | |
| s->block[s->nblock] = (UChar)ch; s->nblock++; | |
| break; | |
| case 2: | |
| s->block[s->nblock] = (UChar)ch; s->nblock++; | |
| s->block[s->nblock] = (UChar)ch; s->nblock++; | |
| break; | |
| case 3: | |
| s->block[s->nblock] = (UChar)ch; s->nblock++; | |
| s->block[s->nblock] = (UChar)ch; s->nblock++; | |
| s->block[s->nblock] = (UChar)ch; s->nblock++; | |
| break; | |
| default: | |
| s->inUse[s->state_in_len-4] = True; | |
| s->block[s->nblock] = (UChar)ch; s->nblock++; | |
| s->block[s->nblock] = (UChar)ch; s->nblock++; | |
| s->block[s->nblock] = (UChar)ch; s->nblock++; | |
| s->block[s->nblock] = (UChar)ch; s->nblock++; | |
| s->block[s->nblock] = ((UChar)(s->state_in_len-4)); | |
| s->nblock++; | |
| break; | |
| } | |
| } | |
| /*---------------------------------------------------*/ | |
| static | |
| void flush_RL ( EState* s ) | |
| { | |
| if (s->state_in_ch < 256) add_pair_to_block ( s ); | |
| init_RL ( s ); | |
| } | |
| /*---------------------------------------------------*/ | |
| #define ADD_CHAR_TO_BLOCK(zs,zchh0) \ | |
| { \ | |
| UInt32 zchh = (UInt32)(zchh0); \ | |
| /*-- fast track the common case --*/ \ | |
| if (zchh != zs->state_in_ch && \ | |
| zs->state_in_len == 1) { \ | |
| UChar ch = (UChar)(zs->state_in_ch); \ | |
| BZ_UPDATE_CRC( zs->blockCRC, ch ); \ | |
| zs->inUse[zs->state_in_ch] = True; \ | |
| zs->block[zs->nblock] = (UChar)ch; \ | |
| zs->nblock++; \ | |
| zs->state_in_ch = zchh; \ | |
| } \ | |
| else \ | |
| /*-- general, uncommon cases --*/ \ | |
| if (zchh != zs->state_in_ch || \ | |
| zs->state_in_len == 255) { \ | |
| if (zs->state_in_ch < 256) \ | |
| add_pair_to_block ( zs ); \ | |
| zs->state_in_ch = zchh; \ | |
| zs->state_in_len = 1; \ | |
| } else { \ | |
| zs->state_in_len++; \ | |
| } \ | |
| } | |
| /*---------------------------------------------------*/ | |
| static | |
| Bool copy_input_until_stop ( EState* s ) | |
| { | |
| Bool progress_in = False; | |
| if (s->mode == BZ_M_RUNNING) { | |
| /*-- fast track the common case --*/ | |
| while (True) { | |
| /*-- block full? --*/ | |
| if (s->nblock >= s->nblockMAX) break; | |
| /*-- no input? --*/ | |
| if (s->strm->avail_in == 0) break; | |
| progress_in = True; | |
| ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); | |
| s->strm->next_in++; | |
| s->strm->avail_in--; | |
| s->strm->total_in_lo32++; | |
| if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; | |
| } | |
| } else { | |
| /*-- general, uncommon case --*/ | |
| while (True) { | |
| /*-- block full? --*/ | |
| if (s->nblock >= s->nblockMAX) break; | |
| /*-- no input? --*/ | |
| if (s->strm->avail_in == 0) break; | |
| /*-- flush/finish end? --*/ | |
| if (s->avail_in_expect == 0) break; | |
| progress_in = True; | |
| ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); | |
| s->strm->next_in++; | |
| s->strm->avail_in--; | |
| s->strm->total_in_lo32++; | |
| if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; | |
| s->avail_in_expect--; | |
| } | |
| } | |
| return progress_in; | |
| } | |
| /*---------------------------------------------------*/ | |
| static | |
| Bool copy_output_until_stop ( EState* s ) | |
| { | |
| Bool progress_out = False; | |
| while (True) { | |
| /*-- no output space? --*/ | |
| if (s->strm->avail_out == 0) break; | |
| /*-- block done? --*/ | |
| if (s->state_out_pos >= s->numZ) break; | |
| progress_out = True; | |
| *(s->strm->next_out) = s->zbits[s->state_out_pos]; | |
| s->state_out_pos++; | |
| s->strm->avail_out--; | |
| s->strm->next_out++; | |
| s->strm->total_out_lo32++; | |
| if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; | |
| } | |
| return progress_out; | |
| } | |
| /*---------------------------------------------------*/ | |
| static | |
| Bool handle_compress ( bz_stream* strm ) | |
| { | |
| Bool progress_in = False; | |
| Bool progress_out = False; | |
| EState* s = strm->state; | |
| while (True) { | |
| if (s->state == BZ_S_OUTPUT) { | |
| progress_out |= copy_output_until_stop ( s ); | |
| if (s->state_out_pos < s->numZ) break; | |
| if (s->mode == BZ_M_FINISHING && | |
| s->avail_in_expect == 0 && | |
| isempty_RL(s)) break; | |
| prepare_new_block ( s ); | |
| s->state = BZ_S_INPUT; | |
| if (s->mode == BZ_M_FLUSHING && | |
| s->avail_in_expect == 0 && | |
| isempty_RL(s)) break; | |
| } | |
| if (s->state == BZ_S_INPUT) { | |
| progress_in |= copy_input_until_stop ( s ); | |
| if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) { | |
| flush_RL ( s ); | |
| BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) ); | |
| s->state = BZ_S_OUTPUT; | |
| } | |
| else | |
| if (s->nblock >= s->nblockMAX) { | |
| BZ2_compressBlock ( s, False ); | |
| s->state = BZ_S_OUTPUT; | |
| } | |
| else | |
| if (s->strm->avail_in == 0) { | |
| break; | |
| } | |
| } | |
| } | |
| return progress_in || progress_out; | |
| } | |
| /*---------------------------------------------------*/ | |
| int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action ) | |
| { | |
| Bool progress; | |
| EState* s; | |
| if (strm == NULL) return BZ_PARAM_ERROR; | |
| s = strm->state; | |
| if (s == NULL) return BZ_PARAM_ERROR; | |
| if (s->strm != strm) return BZ_PARAM_ERROR; | |
| preswitch: | |
| switch (s->mode) { | |
| case BZ_M_IDLE: | |
| return BZ_SEQUENCE_ERROR; | |
| case BZ_M_RUNNING: | |
| if (action == BZ_RUN) { | |
| progress = handle_compress ( strm ); | |
| return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; | |
| } | |
| else | |
| if (action == BZ_FLUSH) { | |
| s->avail_in_expect = strm->avail_in; | |
| s->mode = BZ_M_FLUSHING; | |
| goto preswitch; | |
| } | |
| else | |
| if (action == BZ_FINISH) { | |
| s->avail_in_expect = strm->avail_in; | |
| s->mode = BZ_M_FINISHING; | |
| goto preswitch; | |
| } | |
| else | |
| return BZ_PARAM_ERROR; | |
| case BZ_M_FLUSHING: | |
| if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR; | |
| if (s->avail_in_expect != s->strm->avail_in) | |
| return BZ_SEQUENCE_ERROR; | |
| progress = handle_compress ( strm ); | |
| if (s->avail_in_expect > 0 || !isempty_RL(s) || | |
| s->state_out_pos < s->numZ) return BZ_FLUSH_OK; | |
| s->mode = BZ_M_RUNNING; | |
| return BZ_RUN_OK; | |
| case BZ_M_FINISHING: | |
| if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR; | |
| if (s->avail_in_expect != s->strm->avail_in) | |
| return BZ_SEQUENCE_ERROR; | |
| progress = handle_compress ( strm ); | |
| if (!progress) return BZ_SEQUENCE_ERROR; | |
| if (s->avail_in_expect > 0 || !isempty_RL(s) || | |
| s->state_out_pos < s->numZ) return BZ_FINISH_OK; | |
| s->mode = BZ_M_IDLE; | |
| return BZ_STREAM_END; | |
| } | |
| return BZ_OK; /*--not reached--*/ | |
| } | |
| /*---------------------------------------------------*/ | |
| int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm ) | |
| { | |
| EState* s; | |
| if (strm == NULL) return BZ_PARAM_ERROR; | |
| s = strm->state; | |
| if (s == NULL) return BZ_PARAM_ERROR; | |
| if (s->strm != strm) return BZ_PARAM_ERROR; | |
| if (s->arr1 != NULL) BZFREE(s->arr1); | |
| if (s->arr2 != NULL) BZFREE(s->arr2); | |
| if (s->ftab != NULL) BZFREE(s->ftab); | |
| BZFREE(strm->state); | |
| strm->state = NULL; | |
| return BZ_OK; | |
| } | |
| #endif /* BZ_NO_COMPRESS */ | |
| /*---------------------------------------------------*/ | |
| /*--- Decompression stuff ---*/ | |
| /*---------------------------------------------------*/ | |
| /*---------------------------------------------------*/ | |
| int BZ_API(BZ2_bzDecompressInit) | |
| ( bz_stream* strm, | |
| int verbosity, | |
| int small ) | |
| { | |
| DState* s; | |
| if (!bz_config_ok()) return BZ_CONFIG_ERROR; | |
| if (strm == NULL) return BZ_PARAM_ERROR; | |
| if (small != 0 && small != 1) return BZ_PARAM_ERROR; | |
| if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR; | |
| if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; | |
| if (strm->bzfree == NULL) strm->bzfree = default_bzfree; | |
| s = BZALLOC( sizeof(DState) ); | |
| if (s == NULL) return BZ_MEM_ERROR; | |
| s->strm = strm; | |
| strm->state = s; | |
| s->state = BZ_X_MAGIC_1; | |
| s->bsLive = 0; | |
| s->bsBuff = 0; | |
| s->calculatedCombinedCRC = 0; | |
| strm->total_in_lo32 = 0; | |
| strm->total_in_hi32 = 0; | |
| strm->total_out_lo32 = 0; | |
| strm->total_out_hi32 = 0; | |
| s->smallDecompress = (Bool)small; | |
| s->ll4 = NULL; | |
| s->ll16 = NULL; | |
| s->tt = NULL; | |
| s->currBlockNo = 0; | |
| s->verbosity = verbosity; | |
| return BZ_OK; | |
| } | |
| /*---------------------------------------------------*/ | |
| static | |
| void unRLE_obuf_to_output_FAST ( DState* s ) | |
| { | |
| UChar k1; | |
| if (s->blockRandomised) { | |
| while (True) { | |
| /* try to finish existing run */ | |
| while (True) { | |
| if (s->strm->avail_out == 0) return; | |
| if (s->state_out_len == 0) break; | |
| *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; | |
| BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); | |
| s->state_out_len--; | |
| s->strm->next_out++; | |
| s->strm->avail_out--; | |
| s->strm->total_out_lo32++; | |
| if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; | |
| } | |
| /* can a new run be started? */ | |
| if (s->nblock_used == s->save_nblock+1) return; | |
| s->state_out_len = 1; | |
| s->state_out_ch = s->k0; | |
| BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; | |
| k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
| if (s->nblock_used == s->save_nblock+1) continue; | |
| if (k1 != s->k0) { s->k0 = k1; continue; }; | |
| s->state_out_len = 2; | |
| BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; | |
| k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
| if (s->nblock_used == s->save_nblock+1) continue; | |
| if (k1 != s->k0) { s->k0 = k1; continue; }; | |
| s->state_out_len = 3; | |
| BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; | |
| k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
| if (s->nblock_used == s->save_nblock+1) continue; | |
| if (k1 != s->k0) { s->k0 = k1; continue; }; | |
| BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; | |
| k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
| s->state_out_len = ((Int32)k1) + 4; | |
| BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; | |
| s->k0 ^= BZ_RAND_MASK; s->nblock_used++; | |
| } | |
| } else { | |
| /* restore */ | |
| UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC; | |
| UChar c_state_out_ch = s->state_out_ch; | |
| Int32 c_state_out_len = s->state_out_len; | |
| Int32 c_nblock_used = s->nblock_used; | |
| Int32 c_k0 = s->k0; | |
| UInt32* c_tt = s->tt; | |
| UInt32 c_tPos = s->tPos; | |
| char* cs_next_out = s->strm->next_out; | |
| unsigned int cs_avail_out = s->strm->avail_out; | |
| /* end restore */ | |
| UInt32 avail_out_INIT = cs_avail_out; | |
| Int32 s_save_nblockPP = s->save_nblock+1; | |
| unsigned int total_out_lo32_old; | |
| while (True) { | |
| /* try to finish existing run */ | |
| if (c_state_out_len > 0) { | |
| while (True) { | |
| if (cs_avail_out == 0) goto return_notr; | |
| if (c_state_out_len == 1) break; | |
| *( (UChar*)(cs_next_out) ) = c_state_out_ch; | |
| BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); | |
| c_state_out_len--; | |
| cs_next_out++; | |
| cs_avail_out--; | |
| } | |
| s_state_out_len_eq_one: | |
| { | |
| if (cs_avail_out == 0) { | |
| c_state_out_len = 1; goto return_notr; | |
| }; | |
| *( (UChar*)(cs_next_out) ) = c_state_out_ch; | |
| BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); | |
| cs_next_out++; | |
| cs_avail_out--; | |
| } | |
| } | |
| /* can a new run be started? */ | |
| if (c_nblock_used == s_save_nblockPP) { | |
| c_state_out_len = 0; goto return_notr; | |
| }; | |
| c_state_out_ch = c_k0; | |
| BZ_GET_FAST_C(k1); c_nblock_used++; | |
| if (k1 != c_k0) { | |
| c_k0 = k1; goto s_state_out_len_eq_one; | |
| }; | |
| if (c_nblock_used == s_save_nblockPP) | |
| goto s_state_out_len_eq_one; | |
| c_state_out_len = 2; | |
| BZ_GET_FAST_C(k1); c_nblock_used++; | |
| if (c_nblock_used == s_save_nblockPP) continue; | |
| if (k1 != c_k0) { c_k0 = k1; continue; }; | |
| c_state_out_len = 3; | |
| BZ_GET_FAST_C(k1); c_nblock_used++; | |
| if (c_nblock_used == s_save_nblockPP) continue; | |
| if (k1 != c_k0) { c_k0 = k1; continue; }; | |
| BZ_GET_FAST_C(k1); c_nblock_used++; | |
| c_state_out_len = ((Int32)k1) + 4; | |
| BZ_GET_FAST_C(c_k0); c_nblock_used++; | |
| } | |
| return_notr: | |
| total_out_lo32_old = s->strm->total_out_lo32; | |
| s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); | |
| if (s->strm->total_out_lo32 < total_out_lo32_old) | |
| s->strm->total_out_hi32++; | |
| /* save */ | |
| s->calculatedBlockCRC = c_calculatedBlockCRC; | |
| s->state_out_ch = c_state_out_ch; | |
| s->state_out_len = c_state_out_len; | |
| s->nblock_used = c_nblock_used; | |
| s->k0 = c_k0; | |
| s->tt = c_tt; | |
| s->tPos = c_tPos; | |
| s->strm->next_out = cs_next_out; | |
| s->strm->avail_out = cs_avail_out; | |
| /* end save */ | |
| } | |
| } | |
| /*---------------------------------------------------*/ | |
| __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) | |
| { | |
| Int32 nb, na, mid; | |
| nb = 0; | |
| na = 256; | |
| do { | |
| mid = (nb + na) >> 1; | |
| if (indx >= cftab[mid]) nb = mid; else na = mid; | |
| } | |
| while (na - nb != 1); | |
| return nb; | |
| } | |
| /*---------------------------------------------------*/ | |
| static | |
| void unRLE_obuf_to_output_SMALL ( DState* s ) | |
| { | |
| UChar k1; | |
| if (s->blockRandomised) { | |
| while (True) { | |
| /* try to finish existing run */ | |
| while (True) { | |
| if (s->strm->avail_out == 0) return; | |
| if (s->state_out_len == 0) break; | |
| *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; | |
| BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); | |
| s->state_out_len--; | |
| s->strm->next_out++; | |
| s->strm->avail_out--; | |
| s->strm->total_out_lo32++; | |
| if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; | |
| } | |
| /* can a new run be started? */ | |
| if (s->nblock_used == s->save_nblock+1) return; | |
| s->state_out_len = 1; | |
| s->state_out_ch = s->k0; | |
| BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; | |
| k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
| if (s->nblock_used == s->save_nblock+1) continue; | |
| if (k1 != s->k0) { s->k0 = k1; continue; }; | |
| s->state_out_len = 2; | |
| BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; | |
| k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
| if (s->nblock_used == s->save_nblock+1) continue; | |
| if (k1 != s->k0) { s->k0 = k1; continue; }; | |
| s->state_out_len = 3; | |
| BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; | |
| k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
| if (s->nblock_used == s->save_nblock+1) continue; | |
| if (k1 != s->k0) { s->k0 = k1; continue; }; | |
| BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; | |
| k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
| s->state_out_len = ((Int32)k1) + 4; | |
| BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; | |
| s->k0 ^= BZ_RAND_MASK; s->nblock_used++; | |
| } | |
| } else { | |
| while (True) { | |
| /* try to finish existing run */ | |
| while (True) { | |
| if (s->strm->avail_out == 0) return; | |
| if (s->state_out_len == 0) break; | |
| *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; | |
| BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); | |
| s->state_out_len--; | |
| s->strm->next_out++; | |
| s->strm->avail_out--; | |
| s->strm->total_out_lo32++; | |
| if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; | |
| } | |
| /* can a new run be started? */ | |
| if (s->nblock_used == s->save_nblock+1) return; | |
| s->state_out_len = 1; | |
| s->state_out_ch = s->k0; | |
| BZ_GET_SMALL(k1); s->nblock_used++; | |
| if (s->nblock_used == s->save_nblock+1) continue; | |
| if (k1 != s->k0) { s->k0 = k1; continue; }; | |
| s->state_out_len = 2; | |
| BZ_GET_SMALL(k1); s->nblock_used++; | |
| if (s->nblock_used == s->save_nblock+1) continue; | |
| if (k1 != s->k0) { s->k0 = k1; continue; }; | |
| s->state_out_len = 3; | |
| BZ_GET_SMALL(k1); s->nblock_used++; | |
| if (s->nblock_used == s->save_nblock+1) continue; | |
| if (k1 != s->k0) { s->k0 = k1; continue; }; | |
| BZ_GET_SMALL(k1); s->nblock_used++; | |
| s->state_out_len = ((Int32)k1) + 4; | |
| BZ_GET_SMALL(s->k0); s->nblock_used++; | |
| } | |
| } | |
| } | |
| /*---------------------------------------------------*/ | |
| int BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) | |
| { | |
| DState* s; | |
| if (strm == NULL) return BZ_PARAM_ERROR; | |
| s = strm->state; | |
| if (s == NULL) return BZ_PARAM_ERROR; | |
| if (s->strm != strm) return BZ_PARAM_ERROR; | |
| while (True) { | |
| #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) | |
| WATCHDOG_RESET(); | |
| #endif | |
| if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; | |
| if (s->state == BZ_X_OUTPUT) { | |
| if (s->smallDecompress) | |
| unRLE_obuf_to_output_SMALL ( s ); else | |
| unRLE_obuf_to_output_FAST ( s ); | |
| if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { | |
| BZ_FINALISE_CRC ( s->calculatedBlockCRC ); | |
| if (s->verbosity >= 3) | |
| VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC, | |
| s->calculatedBlockCRC ); | |
| if (s->verbosity >= 2) VPrintf0 ( "]" ); | |
| if (s->calculatedBlockCRC != s->storedBlockCRC) | |
| return BZ_DATA_ERROR; | |
| s->calculatedCombinedCRC | |
| = (s->calculatedCombinedCRC << 1) | | |
| (s->calculatedCombinedCRC >> 31); | |
| s->calculatedCombinedCRC ^= s->calculatedBlockCRC; | |
| s->state = BZ_X_BLKHDR_1; | |
| } else { | |
| return BZ_OK; | |
| } | |
| } | |
| if (s->state >= BZ_X_MAGIC_1) { | |
| Int32 r = BZ2_decompress ( s ); | |
| if (r == BZ_STREAM_END) { | |
| if (s->verbosity >= 3) | |
| VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x", | |
| s->storedCombinedCRC, s->calculatedCombinedCRC ); | |
| if (s->calculatedCombinedCRC != s->storedCombinedCRC) | |
| return BZ_DATA_ERROR; | |
| return r; | |
| } | |
| if (s->state != BZ_X_OUTPUT) return r; | |
| } | |
| } | |
| AssertH ( 0, 6001 ); | |
| return 0; /*NOTREACHED*/ | |
| } | |
| /*---------------------------------------------------*/ | |
| int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm ) | |
| { | |
| DState* s; | |
| if (strm == NULL) return BZ_PARAM_ERROR; | |
| s = strm->state; | |
| if (s == NULL) return BZ_PARAM_ERROR; | |
| if (s->strm != strm) return BZ_PARAM_ERROR; | |
| if (s->tt != NULL) BZFREE(s->tt); | |
| if (s->ll16 != NULL) BZFREE(s->ll16); | |
| if (s->ll4 != NULL) BZFREE(s->ll4); | |
| BZFREE(strm->state); | |
| strm->state = NULL; | |
| return BZ_OK; | |
| } | |
| #ifndef BZ_NO_STDIO | |
| /*---------------------------------------------------*/ | |
| /*--- File I/O stuff ---*/ | |
| /*---------------------------------------------------*/ | |
| #define BZ_SETERR(eee) \ | |
| { \ | |
| if (bzerror != NULL) *bzerror = eee; \ | |
| if (bzf != NULL) bzf->lastErr = eee; \ | |
| } | |
| typedef | |
| struct { | |
| FILE* handle; | |
| Char buf[BZ_MAX_UNUSED]; | |
| Int32 bufN; | |
| Bool writing; | |
| bz_stream strm; | |
| Int32 lastErr; | |
| Bool initialisedOk; | |
| } | |
| bzFile; | |
| /*---------------------------------------------*/ | |
| static Bool myfeof ( FILE* f ) | |
| { | |
| Int32 c = fgetc ( f ); | |
| if (c == EOF) return True; | |
| ungetc ( c, f ); | |
| return False; | |
| } | |
| /*---------------------------------------------------*/ | |
| BZFILE* BZ_API(BZ2_bzWriteOpen) | |
| ( int* bzerror, | |
| FILE* f, | |
| int blockSize100k, | |
| int verbosity, | |
| int workFactor ) | |
| { | |
| Int32 ret; | |
| bzFile* bzf = NULL; | |
| BZ_SETERR(BZ_OK); | |
| if (f == NULL || | |
| (blockSize100k < 1 || blockSize100k > 9) || | |
| (workFactor < 0 || workFactor > 250) || | |
| (verbosity < 0 || verbosity > 4)) | |
| { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; | |
| if (ferror(f)) | |
| { BZ_SETERR(BZ_IO_ERROR); return NULL; }; | |
| bzf = malloc ( sizeof(bzFile) ); | |
| if (bzf == NULL) | |
| { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; | |
| BZ_SETERR(BZ_OK); | |
| bzf->initialisedOk = False; | |
| bzf->bufN = 0; | |
| bzf->handle = f; | |
| bzf->writing = True; | |
| bzf->strm.bzalloc = NULL; | |
| bzf->strm.bzfree = NULL; | |
| bzf->strm.opaque = NULL; | |
| if (workFactor == 0) workFactor = 30; | |
| ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, | |
| verbosity, workFactor ); | |
| if (ret != BZ_OK) | |
| { BZ_SETERR(ret); free(bzf); return NULL; }; | |
| bzf->strm.avail_in = 0; | |
| bzf->initialisedOk = True; | |
| return bzf; | |
| } | |
| /*---------------------------------------------------*/ | |
| void BZ_API(BZ2_bzWrite) | |
| ( int* bzerror, | |
| BZFILE* b, | |
| void* buf, | |
| int len ) | |
| { | |
| Int32 n, n2, ret; | |
| bzFile* bzf = (bzFile*)b; | |
| BZ_SETERR(BZ_OK); | |
| if (bzf == NULL || buf == NULL || len < 0) | |
| { BZ_SETERR(BZ_PARAM_ERROR); return; }; | |
| if (!(bzf->writing)) | |
| { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; | |
| if (ferror(bzf->handle)) | |
| { BZ_SETERR(BZ_IO_ERROR); return; }; | |
| if (len == 0) | |
| { BZ_SETERR(BZ_OK); return; }; | |
| bzf->strm.avail_in = len; | |
| bzf->strm.next_in = buf; | |
| while (True) { | |
| bzf->strm.avail_out = BZ_MAX_UNUSED; | |
| bzf->strm.next_out = bzf->buf; | |
| ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN ); | |
| if (ret != BZ_RUN_OK) | |
| { BZ_SETERR(ret); return; }; | |
| if (bzf->strm.avail_out < BZ_MAX_UNUSED) { | |
| n = BZ_MAX_UNUSED - bzf->strm.avail_out; | |
| n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), | |
| n, bzf->handle ); | |
| if (n != n2 || ferror(bzf->handle)) | |
| { BZ_SETERR(BZ_IO_ERROR); return; }; | |
| } | |
| if (bzf->strm.avail_in == 0) | |
| { BZ_SETERR(BZ_OK); return; }; | |
| } | |
| } | |
| /*---------------------------------------------------*/ | |
| void BZ_API(BZ2_bzWriteClose) | |
| ( int* bzerror, | |
| BZFILE* b, | |
| int abandon, | |
| unsigned int* nbytes_in, | |
| unsigned int* nbytes_out ) | |
| { | |
| BZ2_bzWriteClose64 ( bzerror, b, abandon, | |
| nbytes_in, NULL, nbytes_out, NULL ); | |
| } | |
| void BZ_API(BZ2_bzWriteClose64) | |
| ( int* bzerror, | |
| BZFILE* b, | |
| int abandon, | |
| unsigned int* nbytes_in_lo32, | |
| unsigned int* nbytes_in_hi32, | |
| unsigned int* nbytes_out_lo32, | |
| unsigned int* nbytes_out_hi32 ) | |
| { | |
| Int32 n, n2, ret; | |
| bzFile* bzf = (bzFile*)b; | |
| if (bzf == NULL) | |
| { BZ_SETERR(BZ_OK); return; }; | |
| if (!(bzf->writing)) | |
| { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; | |
| if (ferror(bzf->handle)) | |
| { BZ_SETERR(BZ_IO_ERROR); return; }; | |
| if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0; | |
| if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0; | |
| if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0; | |
| if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0; | |
| if ((!abandon) && bzf->lastErr == BZ_OK) { | |
| while (True) { | |
| bzf->strm.avail_out = BZ_MAX_UNUSED; | |
| bzf->strm.next_out = bzf->buf; | |
| ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH ); | |
| if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) | |
| { BZ_SETERR(ret); return; }; | |
| if (bzf->strm.avail_out < BZ_MAX_UNUSED) { | |
| n = BZ_MAX_UNUSED - bzf->strm.avail_out; | |
| n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), | |
| n, bzf->handle ); | |
| if (n != n2 || ferror(bzf->handle)) | |
| { BZ_SETERR(BZ_IO_ERROR); return; }; | |
| } | |
| if (ret == BZ_STREAM_END) break; | |
| } | |
| } | |
| if ( !abandon && !ferror ( bzf->handle ) ) { | |
| fflush ( bzf->handle ); | |
| if (ferror(bzf->handle)) | |
| { BZ_SETERR(BZ_IO_ERROR); return; }; | |
| } | |
| if (nbytes_in_lo32 != NULL) | |
| *nbytes_in_lo32 = bzf->strm.total_in_lo32; | |
| if (nbytes_in_hi32 != NULL) | |
| *nbytes_in_hi32 = bzf->strm.total_in_hi32; | |
| if (nbytes_out_lo32 != NULL) | |
| *nbytes_out_lo32 = bzf->strm.total_out_lo32; | |
| if (nbytes_out_hi32 != NULL) | |
| *nbytes_out_hi32 = bzf->strm.total_out_hi32; | |
| BZ_SETERR(BZ_OK); | |
| BZ2_bzCompressEnd ( &(bzf->strm) ); | |
| free ( bzf ); | |
| } | |
| /*---------------------------------------------------*/ | |
| BZFILE* BZ_API(BZ2_bzReadOpen) | |
| ( int* bzerror, | |
| FILE* f, | |
| int verbosity, | |
| int small, | |
| void* unused, | |
| int nUnused ) | |
| { | |
| bzFile* bzf = NULL; | |
| int ret; | |
| BZ_SETERR(BZ_OK); | |
| if (f == NULL || | |
| (small != 0 && small != 1) || | |
| (verbosity < 0 || verbosity > 4) || | |
| (unused == NULL && nUnused != 0) || | |
| (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED))) | |
| { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; | |
| if (ferror(f)) | |
| { BZ_SETERR(BZ_IO_ERROR); return NULL; }; | |
| bzf = malloc ( sizeof(bzFile) ); | |
| if (bzf == NULL) | |
| { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; | |
| BZ_SETERR(BZ_OK); | |
| bzf->initialisedOk = False; | |
| bzf->handle = f; | |
| bzf->bufN = 0; | |
| bzf->writing = False; | |
| bzf->strm.bzalloc = NULL; | |
| bzf->strm.bzfree = NULL; | |
| bzf->strm.opaque = NULL; | |
| while (nUnused > 0) { | |
| bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++; | |
| unused = ((void*)( 1 + ((UChar*)(unused)) )); | |
| nUnused--; | |
| } | |
| ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small ); | |
| if (ret != BZ_OK) | |
| { BZ_SETERR(ret); free(bzf); return NULL; }; | |
| bzf->strm.avail_in = bzf->bufN; | |
| bzf->strm.next_in = bzf->buf; | |
| bzf->initialisedOk = True; | |
| return bzf; | |
| } | |
| /*---------------------------------------------------*/ | |
| void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b ) | |
| { | |
| bzFile* bzf = (bzFile*)b; | |
| BZ_SETERR(BZ_OK); | |
| if (bzf == NULL) | |
| { BZ_SETERR(BZ_OK); return; }; | |
| if (bzf->writing) | |
| { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; | |
| if (bzf->initialisedOk) | |
| (void)BZ2_bzDecompressEnd ( &(bzf->strm) ); | |
| free ( bzf ); | |
| } | |
| /*---------------------------------------------------*/ | |
| int BZ_API(BZ2_bzRead) | |
| ( int* bzerror, | |
| BZFILE* b, | |
| void* buf, | |
| int len ) | |
| { | |
| Int32 n, ret; | |
| bzFile* bzf = (bzFile*)b; | |
| BZ_SETERR(BZ_OK); | |
| if (bzf == NULL || buf == NULL || len < 0) | |
| { BZ_SETERR(BZ_PARAM_ERROR); return 0; }; | |
| if (bzf->writing) | |
| { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; }; | |
| if (len == 0) | |
| { BZ_SETERR(BZ_OK); return 0; }; | |
| bzf->strm.avail_out = len; | |
| bzf->strm.next_out = buf; | |
| while (True) { | |
| if (ferror(bzf->handle)) | |
| { BZ_SETERR(BZ_IO_ERROR); return 0; }; | |
| if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) { | |
| n = fread ( bzf->buf, sizeof(UChar), | |
| BZ_MAX_UNUSED, bzf->handle ); | |
| if (ferror(bzf->handle)) | |
| { BZ_SETERR(BZ_IO_ERROR); return 0; }; | |
| bzf->bufN = n; | |
| bzf->strm.avail_in = bzf->bufN; | |
| bzf->strm.next_in = bzf->buf; | |
| } | |
| ret = BZ2_bzDecompress ( &(bzf->strm) ); | |
| if (ret != BZ_OK && ret != BZ_STREAM_END) | |
| { BZ_SETERR(ret); return 0; }; | |
| if (ret == BZ_OK && myfeof(bzf->handle) && | |
| bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0) | |
| { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; }; | |
| if (ret == BZ_STREAM_END) | |
| { BZ_SETERR(BZ_STREAM_END); | |
| return len - bzf->strm.avail_out; }; | |
| if (bzf->strm.avail_out == 0) | |
| { BZ_SETERR(BZ_OK); return len; }; | |
| } | |
| return 0; /*not reached*/ | |
| } | |
| /*---------------------------------------------------*/ | |
| void BZ_API(BZ2_bzReadGetUnused) | |
| ( int* bzerror, | |
| BZFILE* b, | |
| void** unused, | |
| int* nUnused ) | |
| { | |
| bzFile* bzf = (bzFile*)b; | |
| if (bzf == NULL) | |
| { BZ_SETERR(BZ_PARAM_ERROR); return; }; | |
| if (bzf->lastErr != BZ_STREAM_END) | |
| { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; | |
| if (unused == NULL || nUnused == NULL) | |
| { BZ_SETERR(BZ_PARAM_ERROR); return; }; | |
| BZ_SETERR(BZ_OK); | |
| *nUnused = bzf->strm.avail_in; | |
| *unused = bzf->strm.next_in; | |
| } | |
| #endif | |
| /*---------------------------------------------------*/ | |
| /*--- Misc convenience stuff ---*/ | |
| /*---------------------------------------------------*/ | |
| #ifndef BZ_NO_COMPRESS | |
| /*---------------------------------------------------*/ | |
| int BZ_API(BZ2_bzBuffToBuffCompress) | |
| ( char* dest, | |
| unsigned int* destLen, | |
| char* source, | |
| unsigned int sourceLen, | |
| int blockSize100k, | |
| int verbosity, | |
| int workFactor ) | |
| { | |
| bz_stream strm; | |
| int ret; | |
| if (dest == NULL || destLen == NULL || | |
| source == NULL || | |
| blockSize100k < 1 || blockSize100k > 9 || | |
| verbosity < 0 || verbosity > 4 || | |
| workFactor < 0 || workFactor > 250) | |
| return BZ_PARAM_ERROR; | |
| if (workFactor == 0) workFactor = 30; | |
| strm.bzalloc = NULL; | |
| strm.bzfree = NULL; | |
| strm.opaque = NULL; | |
| ret = BZ2_bzCompressInit ( &strm, blockSize100k, | |
| verbosity, workFactor ); | |
| if (ret != BZ_OK) return ret; | |
| strm.next_in = source; | |
| strm.next_out = dest; | |
| strm.avail_in = sourceLen; | |
| strm.avail_out = *destLen; | |
| ret = BZ2_bzCompress ( &strm, BZ_FINISH ); | |
| if (ret == BZ_FINISH_OK) goto output_overflow; | |
| if (ret != BZ_STREAM_END) goto errhandler; | |
| /* normal termination */ | |
| *destLen -= strm.avail_out; | |
| BZ2_bzCompressEnd ( &strm ); | |
| return BZ_OK; | |
| output_overflow: | |
| BZ2_bzCompressEnd ( &strm ); | |
| return BZ_OUTBUFF_FULL; | |
| errhandler: | |
| BZ2_bzCompressEnd ( &strm ); | |
| return ret; | |
| } | |
| #endif /* BZ_NO_COMPRESS */ | |
| /*---------------------------------------------------*/ | |
| int BZ_API(BZ2_bzBuffToBuffDecompress) | |
| ( char* dest, | |
| unsigned int* destLen, | |
| char* source, | |
| unsigned int sourceLen, | |
| int small, | |
| int verbosity ) | |
| { | |
| bz_stream strm; | |
| int ret; | |
| if (destLen == NULL || source == NULL) | |
| return BZ_PARAM_ERROR; | |
| strm.bzalloc = NULL; | |
| strm.bzfree = NULL; | |
| strm.opaque = NULL; | |
| ret = BZ2_bzDecompressInit ( &strm, verbosity, small ); | |
| if (ret != BZ_OK) return ret; | |
| strm.next_in = source; | |
| strm.next_out = dest; | |
| strm.avail_in = sourceLen; | |
| strm.avail_out = *destLen; | |
| ret = BZ2_bzDecompress ( &strm ); | |
| if (ret == BZ_OK) goto output_overflow_or_eof; | |
| if (ret != BZ_STREAM_END) goto errhandler; | |
| /* normal termination */ | |
| *destLen -= strm.avail_out; | |
| BZ2_bzDecompressEnd ( &strm ); | |
| return BZ_OK; | |
| output_overflow_or_eof: | |
| if (strm.avail_out > 0) { | |
| BZ2_bzDecompressEnd ( &strm ); | |
| return BZ_UNEXPECTED_EOF; | |
| } else { | |
| BZ2_bzDecompressEnd ( &strm ); | |
| return BZ_OUTBUFF_FULL; | |
| }; | |
| errhandler: | |
| BZ2_bzDecompressEnd ( &strm ); | |
| return ret; | |
| } | |
| /*---------------------------------------------------*/ | |
| /*-- | |
| Code contributed by Yoshioka Tsuneo | |
| (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp), | |
| to support better zlib compatibility. | |
| This code is not _officially_ part of libbzip2 (yet); | |
| I haven't tested it, documented it, or considered the | |
| threading-safeness of it. | |
| If this code breaks, please contact both Yoshioka and me. | |
| --*/ | |
| /*---------------------------------------------------*/ | |
| /*---------------------------------------------------*/ | |
| /*-- | |
| return version like "0.9.0c". | |
| --*/ | |
| const char * BZ_API(BZ2_bzlibVersion)(void) | |
| { | |
| return BZ_VERSION; | |
| } | |
| #ifndef BZ_NO_STDIO | |
| /*---------------------------------------------------*/ | |
| #if defined(_WIN32) || defined(OS2) || defined(MSDOS) | |
| # include <fcntl.h> | |
| # include <io.h> | |
| # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) | |
| #else | |
| # define SET_BINARY_MODE(file) | |
| #endif | |
| static | |
| BZFILE * bzopen_or_bzdopen | |
| ( const char *path, /* no use when bzdopen */ | |
| int fd, /* no use when bzdopen */ | |
| const char *mode, | |
| int open_mode) /* bzopen: 0, bzdopen:1 */ | |
| { | |
| int bzerr; | |
| char unused[BZ_MAX_UNUSED]; | |
| int blockSize100k = 9; | |
| int writing = 0; | |
| char mode2[10] = ""; | |
| FILE *fp = NULL; | |
| BZFILE *bzfp = NULL; | |
| int verbosity = 0; | |
| int workFactor = 30; | |
| int smallMode = 0; | |
| int nUnused = 0; | |
| if (mode == NULL) return NULL; | |
| while (*mode) { | |
| switch (*mode) { | |
| case 'r': | |
| writing = 0; break; | |
| case 'w': | |
| writing = 1; break; | |
| case 's': | |
| smallMode = 1; break; | |
| default: | |
| if (isdigit((int)(*mode))) { | |
| blockSize100k = *mode-BZ_HDR_0; | |
| } | |
| } | |
| mode++; | |
| } | |
| strcat(mode2, writing ? "w" : "r" ); | |
| strcat(mode2,"b"); /* binary mode */ | |
| if (open_mode==0) { | |
| if (path==NULL || strcmp(path,"")==0) { | |
| fp = (writing ? stdout : stdin); | |
| SET_BINARY_MODE(fp); | |
| } else { | |
| fp = fopen(path,mode2); | |
| } | |
| } else { | |
| #ifdef BZ_STRICT_ANSI | |
| fp = NULL; | |
| #else | |
| fp = fdopen(fd,mode2); | |
| #endif | |
| } | |
| if (fp == NULL) return NULL; | |
| if (writing) { | |
| /* Guard against total chaos and anarchy -- JRS */ | |
| if (blockSize100k < 1) blockSize100k = 1; | |
| if (blockSize100k > 9) blockSize100k = 9; | |
| bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k, | |
| verbosity,workFactor); | |
| } else { | |
| bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode, | |
| unused,nUnused); | |
| } | |
| if (bzfp == NULL) { | |
| if (fp != stdin && fp != stdout) fclose(fp); | |
| return NULL; | |
| } | |
| return bzfp; | |
| } | |
| /*---------------------------------------------------*/ | |
| /*-- | |
| open file for read or write. | |
| ex) bzopen("file","w9") | |
| case path="" or NULL => use stdin or stdout. | |
| --*/ | |
| BZFILE * BZ_API(BZ2_bzopen) | |
| ( const char *path, | |
| const char *mode ) | |
| { | |
| return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0); | |
| } | |
| /*---------------------------------------------------*/ | |
| BZFILE * BZ_API(BZ2_bzdopen) | |
| ( int fd, | |
| const char *mode ) | |
| { | |
| return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1); | |
| } | |
| /*---------------------------------------------------*/ | |
| int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len ) | |
| { | |
| int bzerr, nread; | |
| if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0; | |
| nread = BZ2_bzRead(&bzerr,b,buf,len); | |
| if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) { | |
| return nread; | |
| } else { | |
| return -1; | |
| } | |
| } | |
| /*---------------------------------------------------*/ | |
| int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len ) | |
| { | |
| int bzerr; | |
| BZ2_bzWrite(&bzerr,b,buf,len); | |
| if(bzerr == BZ_OK){ | |
| return len; | |
| }else{ | |
| return -1; | |
| } | |
| } | |
| /*---------------------------------------------------*/ | |
| int BZ_API(BZ2_bzflush) (BZFILE *b) | |
| { | |
| /* do nothing now... */ | |
| return 0; | |
| } | |
| /*---------------------------------------------------*/ | |
| void BZ_API(BZ2_bzclose) (BZFILE* b) | |
| { | |
| int bzerr; | |
| FILE *fp = ((bzFile *)b)->handle; | |
| if (b==NULL) {return;} | |
| if(((bzFile*)b)->writing){ | |
| BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL); | |
| if(bzerr != BZ_OK){ | |
| BZ2_bzWriteClose(NULL,b,1,NULL,NULL); | |
| } | |
| }else{ | |
| BZ2_bzReadClose(&bzerr,b); | |
| } | |
| if(fp!=stdin && fp!=stdout){ | |
| fclose(fp); | |
| } | |
| } | |
| /*---------------------------------------------------*/ | |
| /*-- | |
| return last error code | |
| --*/ | |
| static char *bzerrorstrings[] = { | |
| "OK" | |
| ,"SEQUENCE_ERROR" | |
| ,"PARAM_ERROR" | |
| ,"MEM_ERROR" | |
| ,"DATA_ERROR" | |
| ,"DATA_ERROR_MAGIC" | |
| ,"IO_ERROR" | |
| ,"UNEXPECTED_EOF" | |
| ,"OUTBUFF_FULL" | |
| ,"CONFIG_ERROR" | |
| ,"???" /* for future */ | |
| ,"???" /* for future */ | |
| ,"???" /* for future */ | |
| ,"???" /* for future */ | |
| ,"???" /* for future */ | |
| ,"???" /* for future */ | |
| }; | |
| const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum) | |
| { | |
| int err = ((bzFile *)b)->lastErr; | |
| if(err>0) err = 0; | |
| *errnum = err; | |
| return bzerrorstrings[err*-1]; | |
| } | |
| #endif | |
| void bz_internal_error(int errcode) | |
| { | |
| printf ("BZIP2 internal error %d\n", errcode); | |
| } | |
| /*-------------------------------------------------------------*/ | |
| /*--- end bzlib.c ---*/ | |
| /*-------------------------------------------------------------*/ |