bzlib.c
资源名称:bzip.tar.gz [点击查看]
上传用户:zswatin
上传日期:2007-01-06
资源大小:440k
文件大小:42k
源码类别:
压缩解压
开发平台:
C/C++
- /*-------------------------------------------------------------*/
- /*--- 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-1998 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, Guildford, Surrey, UK.
- jseward@acm.org
- bzip2/libbzip2 version 0.9.0c of 18 October 1998
- 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 bz__AssertH__fail ( int errcode )
- {
- fprintf(stderr,
- "nnbzip2/libbzip2, v0.9.0c: internal error number %d.n"
- "This is a bug in bzip2/libbzip2, v0.9.0c. Please reportn"
- "it to me at: jseward@acm.org. If this happened whenn"
- "you were using some program which uses libbzip2 as an"
- "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 highern"
- "quality software. Thx. Julian Seward, 18 October 1998.nn",
- errcode
- );
- exit(3);
- }
- #endif
- /*---------------------------------------------------*/
- 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 );
- }
- /*---------------------------------------------------*/
- 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(bzCompressInit)
- ( bz_stream* strm,
- int blockSize100k,
- int verbosity,
- int workFactor )
- {
- Int32 n;
- EState* s;
- 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->block = NULL;
- s->quadrant = NULL;
- s->zptr = NULL;
- s->ftab = NULL;
- n = 100000 * blockSize100k;
- s->block = BZALLOC( (n + BZ_NUM_OVERSHOOT_BYTES) * sizeof(UChar) );
- s->quadrant = BZALLOC( (n + BZ_NUM_OVERSHOOT_BYTES) * sizeof(Int16) );
- s->zptr = BZALLOC( n * sizeof(Int32) );
- s->ftab = BZALLOC( 65537 * sizeof(Int32) );
- if (s->block == NULL || s->quadrant == NULL ||
- s->zptr == NULL || s->ftab == NULL) {
- if (s->block != NULL) BZFREE(s->block);
- if (s->quadrant != NULL) BZFREE(s->quadrant);
- if (s->zptr != NULL) BZFREE(s->zptr);
- if (s->ftab != NULL) BZFREE(s->ftab);
- if (s != NULL) BZFREE(s);
- return BZ_MEM_ERROR;
- }
- s->szptr = (UInt16*)(s->zptr);
- 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->nBlocksRandomised = 0;
- strm->state = s;
- strm->total_in = 0;
- strm->total_out = 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++;
- }
- } 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++;
- 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) = ((UChar*)(s->quadrant))[s->state_out_pos];
- s->state_out_pos++;
- s->strm->avail_out--;
- s->strm->next_out++;
- s->strm->total_out++;
- }
- 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 );
- compressBlock ( s, s->mode == BZ_M_FINISHING );
- s->state = BZ_S_OUTPUT;
- }
- else
- if (s->nblock >= s->nblockMAX) {
- compressBlock ( s, False );
- s->state = BZ_S_OUTPUT;
- }
- else
- if (s->strm->avail_in == 0) {
- break;
- }
- }
- }
- return progress_in || progress_out;
- }
- /*---------------------------------------------------*/
- int BZ_API(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(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->block != NULL) BZFREE(s->block);
- if (s->quadrant != NULL) BZFREE(s->quadrant);
- if (s->zptr != NULL) BZFREE(s->zptr);
- if (s->ftab != NULL) BZFREE(s->ftab);
- BZFREE(strm->state);
- strm->state = NULL;
- return BZ_OK;
- }
- /*---------------------------------------------------*/
- /*--- Decompression stuff ---*/
- /*---------------------------------------------------*/
- /*---------------------------------------------------*/
- int BZ_API(bzDecompressInit)
- ( bz_stream* strm,
- int verbosity,
- int small )
- {
- DState* s;
- 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 = 0;
- strm->total_out = 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++;
- }
- /* 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;
- 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:
- s->strm->total_out += (avail_out_INIT - cs_avail_out);
- /* 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 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++;
- }
- /* 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++;
- }
- /* 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(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 (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 = 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 );
- /*notreached*/
- }
- /*---------------------------------------------------*/
- int BZ_API(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(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 = 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(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 = 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(bzWriteClose)
- ( int* bzerror,
- BZFILE* b,
- int abandon,
- unsigned int* nbytes_in,
- unsigned int* nbytes_out )
- {
- 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 != NULL) *nbytes_in = 0;
- if (nbytes_out != NULL) *nbytes_out = 0;
- if ((!abandon) && bzf->lastErr == BZ_OK) {
- while (True) {
- bzf->strm.avail_out = BZ_MAX_UNUSED;
- bzf->strm.next_out = bzf->buf;
- ret = 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 != NULL) *nbytes_in = bzf->strm.total_in;
- if (nbytes_out != NULL) *nbytes_out = bzf->strm.total_out;
- BZ_SETERR(BZ_OK);
- bzCompressEnd ( &(bzf->strm) );
- free ( bzf );
- }
- /*---------------------------------------------------*/
- BZFILE* BZ_API(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 = 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(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)bzDecompressEnd ( &(bzf->strm) );
- free ( bzf );
- }
- /*---------------------------------------------------*/
- int BZ_API(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 = 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(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 ---*/
- /*---------------------------------------------------*/
- /*---------------------------------------------------*/
- int BZ_API(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 = 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 = 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;
- bzCompressEnd ( &strm );
- return BZ_OK;
- output_overflow:
- bzCompressEnd ( &strm );
- return BZ_OUTBUFF_FULL;
- errhandler:
- bzCompressEnd ( &strm );
- return ret;
- }
- /*---------------------------------------------------*/
- int BZ_API(bzBuffToBuffDecompress)
- ( char* dest,
- unsigned int* destLen,
- char* source,
- unsigned int sourceLen,
- int small,
- int verbosity )
- {
- bz_stream strm;
- int ret;
- if (dest == NULL || destLen == NULL ||
- source == NULL ||
- (small != 0 && small != 1) ||
- verbosity < 0 || verbosity > 4)
- return BZ_PARAM_ERROR;
- strm.bzalloc = NULL;
- strm.bzfree = NULL;
- strm.opaque = NULL;
- ret = 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 = bzDecompress ( &strm );
- if (ret == BZ_OK) goto output_overflow_or_eof;
- if (ret != BZ_STREAM_END) goto errhandler;
- /* normal termination */
- *destLen -= strm.avail_out;
- bzDecompressEnd ( &strm );
- return BZ_OK;
- output_overflow_or_eof:
- if (strm.avail_out > 0) {
- bzDecompressEnd ( &strm );
- return BZ_UNEXPECTED_EOF;
- } else {
- bzDecompressEnd ( &strm );
- return BZ_OUTBUFF_FULL;
- };
- errhandler:
- bzDecompressEnd ( &strm );
- return BZ_SEQUENCE_ERROR;
- }
- /*---------------------------------------------------*/
- /*--
- 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(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(*mode)){
- blockSize100k = 0;
- while(isdigit(*mode)){
- blockSize100k = blockSize100k*10 + *mode-'0';
- mode++;
- }
- }else{
- /* ignore */
- }
- }
- 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){
- bzfp = bzWriteOpen(&bzerr,fp,blockSize100k,verbosity,workFactor);
- }else{
- bzfp = 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(bzopen)
- ( const char *path,
- const char *mode )
- {
- return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
- }
- /*---------------------------------------------------*/
- BZFILE * BZ_API(bzdopen)
- ( int fd,
- const char *mode )
- {
- return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
- }
- /*---------------------------------------------------*/
- int BZ_API(bzread) (BZFILE* b, void* buf, int len )
- {
- int bzerr, nread;
- if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
- nread = bzRead(&bzerr,b,buf,len);
- if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
- return nread;
- } else {
- return -1;
- }
- }
- /*---------------------------------------------------*/
- int BZ_API(bzwrite) (BZFILE* b, void* buf, int len )
- {
- int bzerr;
- bzWrite(&bzerr,b,buf,len);
- if(bzerr == BZ_OK){
- return len;
- }else{
- return -1;
- }
- }
- /*---------------------------------------------------*/
- int BZ_API(bzflush) (BZFILE *b)
- {
- /* do nothing now... */
- return 0;
- }
- /*---------------------------------------------------*/
- void BZ_API(bzclose) (BZFILE* b)
- {
- int bzerr;
- FILE *fp = ((bzFile *)b)->handle;
- if(b==NULL){return;}
- if(((bzFile*)b)->writing){
- bzWriteClose(&bzerr,b,0,NULL,NULL);
- if(bzerr != BZ_OK){
- bzWriteClose(NULL,b,1,NULL,NULL);
- }
- }else{
- 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"
- ,"???" /* for future */
- ,"???" /* for future */
- ,"???" /* for future */
- ,"???" /* for future */
- ,"???" /* for future */
- ,"???" /* for future */
- };
- const char * BZ_API(bzerror) (BZFILE *b, int *errnum)
- {
- int err = ((bzFile *)b)->lastErr;
- if(err>0) err = 0;
- *errnum = err;
- return bzerrorstrings[err*-1];
- }
- #endif
- /*-------------------------------------------------------------*/
- /*--- end bzlib.c ---*/
- /*-------------------------------------------------------------*/