xref: /dflybsd-src/contrib/bzip2/bzlib.c (revision d8d77baac2714febf36f4ac37afccbbbdcdc8857)
171e7ee59SPeter Avalos 
271e7ee59SPeter Avalos /*-------------------------------------------------------------*/
371e7ee59SPeter Avalos /*--- Library top-level functions.                          ---*/
471e7ee59SPeter Avalos /*---                                               bzlib.c ---*/
571e7ee59SPeter Avalos /*-------------------------------------------------------------*/
671e7ee59SPeter Avalos 
771e7ee59SPeter Avalos /* ------------------------------------------------------------------
871e7ee59SPeter Avalos    This file is part of bzip2/libbzip2, a program and library for
971e7ee59SPeter Avalos    lossless, block-sorting data compression.
1071e7ee59SPeter Avalos 
1186954436SDaniel Fojt    bzip2/libbzip2 version 1.0.8 of 13 July 2019
1286954436SDaniel Fojt    Copyright (C) 1996-2019 Julian Seward <jseward@acm.org>
1371e7ee59SPeter Avalos 
1471e7ee59SPeter Avalos    Please read the WARNING, DISCLAIMER and PATENTS sections in the
1571e7ee59SPeter Avalos    README file.
1671e7ee59SPeter Avalos 
1771e7ee59SPeter Avalos    This program is released under the terms of the license contained
1871e7ee59SPeter Avalos    in the file LICENSE.
1971e7ee59SPeter Avalos    ------------------------------------------------------------------ */
2071e7ee59SPeter Avalos 
2171e7ee59SPeter Avalos /* CHANGES
2271e7ee59SPeter Avalos    0.9.0    -- original version.
2371e7ee59SPeter Avalos    0.9.0a/b -- no changes in this file.
2471e7ee59SPeter Avalos    0.9.0c   -- made zero-length BZ_FLUSH work correctly in bzCompress().
2571e7ee59SPeter Avalos      fixed bzWrite/bzRead to ignore zero-length requests.
2671e7ee59SPeter Avalos      fixed bzread to correctly handle read requests after EOF.
2771e7ee59SPeter Avalos      wrong parameter order in call to bzDecompressInit in
2871e7ee59SPeter Avalos      bzBuffToBuffDecompress.  Fixed.
2971e7ee59SPeter Avalos */
3071e7ee59SPeter Avalos 
3171e7ee59SPeter Avalos #include "bzlib_private.h"
3271e7ee59SPeter Avalos 
33*d8d77baaSSascha Wildner #ifndef BZ_NO_COMPRESS
3471e7ee59SPeter Avalos 
3571e7ee59SPeter Avalos /*---------------------------------------------------*/
3671e7ee59SPeter Avalos /*--- Compression stuff                           ---*/
3771e7ee59SPeter Avalos /*---------------------------------------------------*/
3871e7ee59SPeter Avalos 
3971e7ee59SPeter Avalos 
4071e7ee59SPeter Avalos /*---------------------------------------------------*/
4171e7ee59SPeter Avalos #ifndef BZ_NO_STDIO
BZ2_bz__AssertH__fail(int errcode)4271e7ee59SPeter Avalos void BZ2_bz__AssertH__fail ( int errcode )
4371e7ee59SPeter Avalos {
4471e7ee59SPeter Avalos    fprintf(stderr,
4571e7ee59SPeter Avalos       "\n\nbzip2/libbzip2: internal error number %d.\n"
4671e7ee59SPeter Avalos       "This is a bug in bzip2/libbzip2, %s.\n"
4786954436SDaniel Fojt       "Please report it to: bzip2-devel@sourceware.org.  If this happened\n"
4871e7ee59SPeter Avalos       "when you were using some program which uses libbzip2 as a\n"
4971e7ee59SPeter Avalos       "component, you should also report this bug to the author(s)\n"
5071e7ee59SPeter Avalos       "of that program.  Please make an effort to report this bug;\n"
5171e7ee59SPeter Avalos       "timely and accurate bug reports eventually lead to higher\n"
5286954436SDaniel Fojt       "quality software.  Thanks.\n\n",
5371e7ee59SPeter Avalos       errcode,
5471e7ee59SPeter Avalos       BZ2_bzlibVersion()
5571e7ee59SPeter Avalos    );
5671e7ee59SPeter Avalos 
5771e7ee59SPeter Avalos    if (errcode == 1007) {
5871e7ee59SPeter Avalos    fprintf(stderr,
5971e7ee59SPeter Avalos       "\n*** A special note about internal error number 1007 ***\n"
6071e7ee59SPeter Avalos       "\n"
6171e7ee59SPeter Avalos       "Experience suggests that a common cause of i.e. 1007\n"
6271e7ee59SPeter Avalos       "is unreliable memory or other hardware.  The 1007 assertion\n"
6371e7ee59SPeter Avalos       "just happens to cross-check the results of huge numbers of\n"
6471e7ee59SPeter Avalos       "memory reads/writes, and so acts (unintendedly) as a stress\n"
6571e7ee59SPeter Avalos       "test of your memory system.\n"
6671e7ee59SPeter Avalos       "\n"
6771e7ee59SPeter Avalos       "I suggest the following: try compressing the file again,\n"
6871e7ee59SPeter Avalos       "possibly monitoring progress in detail with the -vv flag.\n"
6971e7ee59SPeter Avalos       "\n"
7071e7ee59SPeter Avalos       "* If the error cannot be reproduced, and/or happens at different\n"
7171e7ee59SPeter Avalos       "  points in compression, you may have a flaky memory system.\n"
7271e7ee59SPeter Avalos       "  Try a memory-test program.  I have used Memtest86\n"
7371e7ee59SPeter Avalos       "  (www.memtest86.com).  At the time of writing it is free (GPLd).\n"
7471e7ee59SPeter Avalos       "  Memtest86 tests memory much more thorougly than your BIOSs\n"
7571e7ee59SPeter Avalos       "  power-on test, and may find failures that the BIOS doesn't.\n"
7671e7ee59SPeter Avalos       "\n"
7771e7ee59SPeter Avalos       "* If the error can be repeatably reproduced, this is a bug in\n"
7871e7ee59SPeter Avalos       "  bzip2, and I would very much like to hear about it.  Please\n"
7971e7ee59SPeter Avalos       "  let me know, and, ideally, save a copy of the file causing the\n"
8071e7ee59SPeter Avalos       "  problem -- without which I will be unable to investigate it.\n"
8171e7ee59SPeter Avalos       "\n"
8271e7ee59SPeter Avalos    );
8371e7ee59SPeter Avalos    }
8471e7ee59SPeter Avalos 
8571e7ee59SPeter Avalos    exit(3);
8671e7ee59SPeter Avalos }
8771e7ee59SPeter Avalos #endif
8871e7ee59SPeter Avalos 
89*d8d77baaSSascha Wildner #endif /* BZ_NO_COMPRESS */
9071e7ee59SPeter Avalos 
9171e7ee59SPeter Avalos /*---------------------------------------------------*/
9271e7ee59SPeter Avalos static
bz_config_ok(void)9371e7ee59SPeter Avalos int bz_config_ok ( void )
9471e7ee59SPeter Avalos {
9571e7ee59SPeter Avalos    if (sizeof(int)   != 4) return 0;
9671e7ee59SPeter Avalos    if (sizeof(short) != 2) return 0;
9771e7ee59SPeter Avalos    if (sizeof(char)  != 1) return 0;
9871e7ee59SPeter Avalos    return 1;
9971e7ee59SPeter Avalos }
10071e7ee59SPeter Avalos 
10171e7ee59SPeter Avalos 
10271e7ee59SPeter Avalos /*---------------------------------------------------*/
10371e7ee59SPeter Avalos static
default_bzalloc(void * opaque,Int32 items,Int32 size)10471e7ee59SPeter Avalos void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
10571e7ee59SPeter Avalos {
10671e7ee59SPeter Avalos    void* v = malloc ( items * size );
10771e7ee59SPeter Avalos    return v;
10871e7ee59SPeter Avalos }
10971e7ee59SPeter Avalos 
11071e7ee59SPeter Avalos static
default_bzfree(void * opaque,void * addr)11171e7ee59SPeter Avalos void default_bzfree ( void* opaque, void* addr )
11271e7ee59SPeter Avalos {
11371e7ee59SPeter Avalos    if (addr != NULL) free ( addr );
11471e7ee59SPeter Avalos }
11571e7ee59SPeter Avalos 
116*d8d77baaSSascha Wildner #ifndef BZ_NO_COMPRESS
11771e7ee59SPeter Avalos 
11871e7ee59SPeter Avalos /*---------------------------------------------------*/
11971e7ee59SPeter Avalos static
prepare_new_block(EState * s)12071e7ee59SPeter Avalos void prepare_new_block ( EState* s )
12171e7ee59SPeter Avalos {
12271e7ee59SPeter Avalos    Int32 i;
12371e7ee59SPeter Avalos    s->nblock = 0;
12471e7ee59SPeter Avalos    s->numZ = 0;
12571e7ee59SPeter Avalos    s->state_out_pos = 0;
12671e7ee59SPeter Avalos    BZ_INITIALISE_CRC ( s->blockCRC );
12771e7ee59SPeter Avalos    for (i = 0; i < 256; i++) s->inUse[i] = False;
12871e7ee59SPeter Avalos    s->blockNo++;
12971e7ee59SPeter Avalos }
13071e7ee59SPeter Avalos 
13171e7ee59SPeter Avalos 
13271e7ee59SPeter Avalos /*---------------------------------------------------*/
13371e7ee59SPeter Avalos static
init_RL(EState * s)13471e7ee59SPeter Avalos void init_RL ( EState* s )
13571e7ee59SPeter Avalos {
13671e7ee59SPeter Avalos    s->state_in_ch  = 256;
13771e7ee59SPeter Avalos    s->state_in_len = 0;
13871e7ee59SPeter Avalos }
13971e7ee59SPeter Avalos 
14071e7ee59SPeter Avalos 
14171e7ee59SPeter Avalos static
isempty_RL(EState * s)14271e7ee59SPeter Avalos Bool isempty_RL ( EState* s )
14371e7ee59SPeter Avalos {
14471e7ee59SPeter Avalos    if (s->state_in_ch < 256 && s->state_in_len > 0)
14571e7ee59SPeter Avalos       return False; else
14671e7ee59SPeter Avalos       return True;
14771e7ee59SPeter Avalos }
14871e7ee59SPeter Avalos 
14971e7ee59SPeter Avalos 
15071e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzCompressInit)15171e7ee59SPeter Avalos int BZ_API(BZ2_bzCompressInit)
15271e7ee59SPeter Avalos                     ( bz_stream* strm,
15371e7ee59SPeter Avalos                      int        blockSize100k,
15471e7ee59SPeter Avalos                      int        verbosity,
15571e7ee59SPeter Avalos                      int        workFactor )
15671e7ee59SPeter Avalos {
15771e7ee59SPeter Avalos    Int32   n;
15871e7ee59SPeter Avalos    EState* s;
15971e7ee59SPeter Avalos 
16071e7ee59SPeter Avalos    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
16171e7ee59SPeter Avalos 
16271e7ee59SPeter Avalos    if (strm == NULL ||
16371e7ee59SPeter Avalos        blockSize100k < 1 || blockSize100k > 9 ||
16471e7ee59SPeter Avalos        workFactor < 0 || workFactor > 250)
16571e7ee59SPeter Avalos      return BZ_PARAM_ERROR;
16671e7ee59SPeter Avalos 
16771e7ee59SPeter Avalos    if (workFactor == 0) workFactor = 30;
16871e7ee59SPeter Avalos    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
16971e7ee59SPeter Avalos    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
17071e7ee59SPeter Avalos 
17171e7ee59SPeter Avalos    s = BZALLOC( sizeof(EState) );
17271e7ee59SPeter Avalos    if (s == NULL) return BZ_MEM_ERROR;
17371e7ee59SPeter Avalos    s->strm = strm;
17471e7ee59SPeter Avalos 
17571e7ee59SPeter Avalos    s->arr1 = NULL;
17671e7ee59SPeter Avalos    s->arr2 = NULL;
17771e7ee59SPeter Avalos    s->ftab = NULL;
17871e7ee59SPeter Avalos 
17971e7ee59SPeter Avalos    n       = 100000 * blockSize100k;
18071e7ee59SPeter Avalos    s->arr1 = BZALLOC( n                  * sizeof(UInt32) );
18171e7ee59SPeter Avalos    s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
18271e7ee59SPeter Avalos    s->ftab = BZALLOC( 65537              * sizeof(UInt32) );
18371e7ee59SPeter Avalos 
18471e7ee59SPeter Avalos    if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
18571e7ee59SPeter Avalos       if (s->arr1 != NULL) BZFREE(s->arr1);
18671e7ee59SPeter Avalos       if (s->arr2 != NULL) BZFREE(s->arr2);
18771e7ee59SPeter Avalos       if (s->ftab != NULL) BZFREE(s->ftab);
18871e7ee59SPeter Avalos       if (s       != NULL) BZFREE(s);
18971e7ee59SPeter Avalos       return BZ_MEM_ERROR;
19071e7ee59SPeter Avalos    }
19171e7ee59SPeter Avalos 
19271e7ee59SPeter Avalos    s->blockNo           = 0;
19371e7ee59SPeter Avalos    s->state             = BZ_S_INPUT;
19471e7ee59SPeter Avalos    s->mode              = BZ_M_RUNNING;
19571e7ee59SPeter Avalos    s->combinedCRC       = 0;
19671e7ee59SPeter Avalos    s->blockSize100k     = blockSize100k;
19771e7ee59SPeter Avalos    s->nblockMAX         = 100000 * blockSize100k - 19;
19871e7ee59SPeter Avalos    s->verbosity         = verbosity;
19971e7ee59SPeter Avalos    s->workFactor        = workFactor;
20071e7ee59SPeter Avalos 
20171e7ee59SPeter Avalos    s->block             = (UChar*)s->arr2;
20271e7ee59SPeter Avalos    s->mtfv              = (UInt16*)s->arr1;
20371e7ee59SPeter Avalos    s->zbits             = NULL;
20471e7ee59SPeter Avalos    s->ptr               = (UInt32*)s->arr1;
20571e7ee59SPeter Avalos 
20671e7ee59SPeter Avalos    strm->state          = s;
20771e7ee59SPeter Avalos    strm->total_in_lo32  = 0;
20871e7ee59SPeter Avalos    strm->total_in_hi32  = 0;
20971e7ee59SPeter Avalos    strm->total_out_lo32 = 0;
21071e7ee59SPeter Avalos    strm->total_out_hi32 = 0;
21171e7ee59SPeter Avalos    init_RL ( s );
21271e7ee59SPeter Avalos    prepare_new_block ( s );
21371e7ee59SPeter Avalos    return BZ_OK;
21471e7ee59SPeter Avalos }
21571e7ee59SPeter Avalos 
21671e7ee59SPeter Avalos 
21771e7ee59SPeter Avalos /*---------------------------------------------------*/
21871e7ee59SPeter Avalos static
add_pair_to_block(EState * s)21971e7ee59SPeter Avalos void add_pair_to_block ( EState* s )
22071e7ee59SPeter Avalos {
22171e7ee59SPeter Avalos    Int32 i;
22271e7ee59SPeter Avalos    UChar ch = (UChar)(s->state_in_ch);
22371e7ee59SPeter Avalos    for (i = 0; i < s->state_in_len; i++) {
22471e7ee59SPeter Avalos       BZ_UPDATE_CRC( s->blockCRC, ch );
22571e7ee59SPeter Avalos    }
22671e7ee59SPeter Avalos    s->inUse[s->state_in_ch] = True;
22771e7ee59SPeter Avalos    switch (s->state_in_len) {
22871e7ee59SPeter Avalos       case 1:
22971e7ee59SPeter Avalos          s->block[s->nblock] = (UChar)ch; s->nblock++;
23071e7ee59SPeter Avalos          break;
23171e7ee59SPeter Avalos       case 2:
23271e7ee59SPeter Avalos          s->block[s->nblock] = (UChar)ch; s->nblock++;
23371e7ee59SPeter Avalos          s->block[s->nblock] = (UChar)ch; s->nblock++;
23471e7ee59SPeter Avalos          break;
23571e7ee59SPeter Avalos       case 3:
23671e7ee59SPeter Avalos          s->block[s->nblock] = (UChar)ch; s->nblock++;
23771e7ee59SPeter Avalos          s->block[s->nblock] = (UChar)ch; s->nblock++;
23871e7ee59SPeter Avalos          s->block[s->nblock] = (UChar)ch; s->nblock++;
23971e7ee59SPeter Avalos          break;
24071e7ee59SPeter Avalos       default:
24171e7ee59SPeter Avalos          s->inUse[s->state_in_len-4] = True;
24271e7ee59SPeter Avalos          s->block[s->nblock] = (UChar)ch; s->nblock++;
24371e7ee59SPeter Avalos          s->block[s->nblock] = (UChar)ch; s->nblock++;
24471e7ee59SPeter Avalos          s->block[s->nblock] = (UChar)ch; s->nblock++;
24571e7ee59SPeter Avalos          s->block[s->nblock] = (UChar)ch; s->nblock++;
24671e7ee59SPeter Avalos          s->block[s->nblock] = ((UChar)(s->state_in_len-4));
24771e7ee59SPeter Avalos          s->nblock++;
24871e7ee59SPeter Avalos          break;
24971e7ee59SPeter Avalos    }
25071e7ee59SPeter Avalos }
25171e7ee59SPeter Avalos 
25271e7ee59SPeter Avalos 
25371e7ee59SPeter Avalos /*---------------------------------------------------*/
25471e7ee59SPeter Avalos static
flush_RL(EState * s)25571e7ee59SPeter Avalos void flush_RL ( EState* s )
25671e7ee59SPeter Avalos {
25771e7ee59SPeter Avalos    if (s->state_in_ch < 256) add_pair_to_block ( s );
25871e7ee59SPeter Avalos    init_RL ( s );
25971e7ee59SPeter Avalos }
26071e7ee59SPeter Avalos 
26171e7ee59SPeter Avalos 
26271e7ee59SPeter Avalos /*---------------------------------------------------*/
26371e7ee59SPeter Avalos #define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
26471e7ee59SPeter Avalos {                                                 \
26571e7ee59SPeter Avalos    UInt32 zchh = (UInt32)(zchh0);                 \
26671e7ee59SPeter Avalos    /*-- fast track the common case --*/           \
26771e7ee59SPeter Avalos    if (zchh != zs->state_in_ch &&                 \
26871e7ee59SPeter Avalos        zs->state_in_len == 1) {                   \
26971e7ee59SPeter Avalos       UChar ch = (UChar)(zs->state_in_ch);        \
27071e7ee59SPeter Avalos       BZ_UPDATE_CRC( zs->blockCRC, ch );          \
27171e7ee59SPeter Avalos       zs->inUse[zs->state_in_ch] = True;          \
27271e7ee59SPeter Avalos       zs->block[zs->nblock] = (UChar)ch;          \
27371e7ee59SPeter Avalos       zs->nblock++;                               \
27471e7ee59SPeter Avalos       zs->state_in_ch = zchh;                     \
27571e7ee59SPeter Avalos    }                                              \
27671e7ee59SPeter Avalos    else                                           \
27771e7ee59SPeter Avalos    /*-- general, uncommon cases --*/              \
27871e7ee59SPeter Avalos    if (zchh != zs->state_in_ch ||                 \
27971e7ee59SPeter Avalos       zs->state_in_len == 255) {                  \
28071e7ee59SPeter Avalos       if (zs->state_in_ch < 256)                  \
28171e7ee59SPeter Avalos          add_pair_to_block ( zs );                \
28271e7ee59SPeter Avalos       zs->state_in_ch = zchh;                     \
28371e7ee59SPeter Avalos       zs->state_in_len = 1;                       \
28471e7ee59SPeter Avalos    } else {                                       \
28571e7ee59SPeter Avalos       zs->state_in_len++;                         \
28671e7ee59SPeter Avalos    }                                              \
28771e7ee59SPeter Avalos }
28871e7ee59SPeter Avalos 
28971e7ee59SPeter Avalos 
29071e7ee59SPeter Avalos /*---------------------------------------------------*/
29171e7ee59SPeter Avalos static
copy_input_until_stop(EState * s)29271e7ee59SPeter Avalos Bool copy_input_until_stop ( EState* s )
29371e7ee59SPeter Avalos {
29471e7ee59SPeter Avalos    Bool progress_in = False;
29571e7ee59SPeter Avalos 
29671e7ee59SPeter Avalos    if (s->mode == BZ_M_RUNNING) {
29771e7ee59SPeter Avalos 
29871e7ee59SPeter Avalos       /*-- fast track the common case --*/
29971e7ee59SPeter Avalos       while (True) {
30071e7ee59SPeter Avalos          /*-- block full? --*/
30171e7ee59SPeter Avalos          if (s->nblock >= s->nblockMAX) break;
30271e7ee59SPeter Avalos          /*-- no input? --*/
30371e7ee59SPeter Avalos          if (s->strm->avail_in == 0) break;
30471e7ee59SPeter Avalos          progress_in = True;
30571e7ee59SPeter Avalos          ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
30671e7ee59SPeter Avalos          s->strm->next_in++;
30771e7ee59SPeter Avalos          s->strm->avail_in--;
30871e7ee59SPeter Avalos          s->strm->total_in_lo32++;
30971e7ee59SPeter Avalos          if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
31071e7ee59SPeter Avalos       }
31171e7ee59SPeter Avalos 
31271e7ee59SPeter Avalos    } else {
31371e7ee59SPeter Avalos 
31471e7ee59SPeter Avalos       /*-- general, uncommon case --*/
31571e7ee59SPeter Avalos       while (True) {
31671e7ee59SPeter Avalos          /*-- block full? --*/
31771e7ee59SPeter Avalos          if (s->nblock >= s->nblockMAX) break;
31871e7ee59SPeter Avalos          /*-- no input? --*/
31971e7ee59SPeter Avalos          if (s->strm->avail_in == 0) break;
32071e7ee59SPeter Avalos          /*-- flush/finish end? --*/
32171e7ee59SPeter Avalos          if (s->avail_in_expect == 0) break;
32271e7ee59SPeter Avalos          progress_in = True;
32371e7ee59SPeter Avalos          ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
32471e7ee59SPeter Avalos          s->strm->next_in++;
32571e7ee59SPeter Avalos          s->strm->avail_in--;
32671e7ee59SPeter Avalos          s->strm->total_in_lo32++;
32771e7ee59SPeter Avalos          if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
32871e7ee59SPeter Avalos          s->avail_in_expect--;
32971e7ee59SPeter Avalos       }
33071e7ee59SPeter Avalos    }
33171e7ee59SPeter Avalos    return progress_in;
33271e7ee59SPeter Avalos }
33371e7ee59SPeter Avalos 
33471e7ee59SPeter Avalos 
33571e7ee59SPeter Avalos /*---------------------------------------------------*/
33671e7ee59SPeter Avalos static
copy_output_until_stop(EState * s)33771e7ee59SPeter Avalos Bool copy_output_until_stop ( EState* s )
33871e7ee59SPeter Avalos {
33971e7ee59SPeter Avalos    Bool progress_out = False;
34071e7ee59SPeter Avalos 
34171e7ee59SPeter Avalos    while (True) {
34271e7ee59SPeter Avalos 
34371e7ee59SPeter Avalos       /*-- no output space? --*/
34471e7ee59SPeter Avalos       if (s->strm->avail_out == 0) break;
34571e7ee59SPeter Avalos 
34671e7ee59SPeter Avalos       /*-- block done? --*/
34771e7ee59SPeter Avalos       if (s->state_out_pos >= s->numZ) break;
34871e7ee59SPeter Avalos 
34971e7ee59SPeter Avalos       progress_out = True;
35071e7ee59SPeter Avalos       *(s->strm->next_out) = s->zbits[s->state_out_pos];
35171e7ee59SPeter Avalos       s->state_out_pos++;
35271e7ee59SPeter Avalos       s->strm->avail_out--;
35371e7ee59SPeter Avalos       s->strm->next_out++;
35471e7ee59SPeter Avalos       s->strm->total_out_lo32++;
35571e7ee59SPeter Avalos       if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
35671e7ee59SPeter Avalos    }
35771e7ee59SPeter Avalos 
35871e7ee59SPeter Avalos    return progress_out;
35971e7ee59SPeter Avalos }
36071e7ee59SPeter Avalos 
36171e7ee59SPeter Avalos 
36271e7ee59SPeter Avalos /*---------------------------------------------------*/
36371e7ee59SPeter Avalos static
handle_compress(bz_stream * strm)36471e7ee59SPeter Avalos Bool handle_compress ( bz_stream* strm )
36571e7ee59SPeter Avalos {
36671e7ee59SPeter Avalos    Bool progress_in  = False;
36771e7ee59SPeter Avalos    Bool progress_out = False;
36871e7ee59SPeter Avalos    EState* s = strm->state;
36971e7ee59SPeter Avalos 
37071e7ee59SPeter Avalos    while (True) {
37171e7ee59SPeter Avalos 
37271e7ee59SPeter Avalos       if (s->state == BZ_S_OUTPUT) {
37371e7ee59SPeter Avalos          progress_out |= copy_output_until_stop ( s );
37471e7ee59SPeter Avalos          if (s->state_out_pos < s->numZ) break;
37571e7ee59SPeter Avalos          if (s->mode == BZ_M_FINISHING &&
37671e7ee59SPeter Avalos              s->avail_in_expect == 0 &&
37771e7ee59SPeter Avalos              isempty_RL(s)) break;
37871e7ee59SPeter Avalos          prepare_new_block ( s );
37971e7ee59SPeter Avalos          s->state = BZ_S_INPUT;
38071e7ee59SPeter Avalos          if (s->mode == BZ_M_FLUSHING &&
38171e7ee59SPeter Avalos              s->avail_in_expect == 0 &&
38271e7ee59SPeter Avalos              isempty_RL(s)) break;
38371e7ee59SPeter Avalos       }
38471e7ee59SPeter Avalos 
38571e7ee59SPeter Avalos       if (s->state == BZ_S_INPUT) {
38671e7ee59SPeter Avalos          progress_in |= copy_input_until_stop ( s );
38771e7ee59SPeter Avalos          if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
38871e7ee59SPeter Avalos             flush_RL ( s );
38971e7ee59SPeter Avalos             BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
39071e7ee59SPeter Avalos             s->state = BZ_S_OUTPUT;
39171e7ee59SPeter Avalos          }
39271e7ee59SPeter Avalos          else
39371e7ee59SPeter Avalos          if (s->nblock >= s->nblockMAX) {
39471e7ee59SPeter Avalos             BZ2_compressBlock ( s, False );
39571e7ee59SPeter Avalos             s->state = BZ_S_OUTPUT;
39671e7ee59SPeter Avalos          }
39771e7ee59SPeter Avalos          else
39871e7ee59SPeter Avalos          if (s->strm->avail_in == 0) {
39971e7ee59SPeter Avalos             break;
40071e7ee59SPeter Avalos          }
40171e7ee59SPeter Avalos       }
40271e7ee59SPeter Avalos 
40371e7ee59SPeter Avalos    }
40471e7ee59SPeter Avalos 
40571e7ee59SPeter Avalos    return progress_in || progress_out;
40671e7ee59SPeter Avalos }
40771e7ee59SPeter Avalos 
40871e7ee59SPeter Avalos 
40971e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzCompress)41071e7ee59SPeter Avalos int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
41171e7ee59SPeter Avalos {
41271e7ee59SPeter Avalos    Bool progress;
41371e7ee59SPeter Avalos    EState* s;
41471e7ee59SPeter Avalos    if (strm == NULL) return BZ_PARAM_ERROR;
41571e7ee59SPeter Avalos    s = strm->state;
41671e7ee59SPeter Avalos    if (s == NULL) return BZ_PARAM_ERROR;
41771e7ee59SPeter Avalos    if (s->strm != strm) return BZ_PARAM_ERROR;
41871e7ee59SPeter Avalos 
41971e7ee59SPeter Avalos    preswitch:
42071e7ee59SPeter Avalos    switch (s->mode) {
42171e7ee59SPeter Avalos 
42271e7ee59SPeter Avalos       case BZ_M_IDLE:
42371e7ee59SPeter Avalos          return BZ_SEQUENCE_ERROR;
42471e7ee59SPeter Avalos 
42571e7ee59SPeter Avalos       case BZ_M_RUNNING:
42671e7ee59SPeter Avalos          if (action == BZ_RUN) {
42771e7ee59SPeter Avalos             progress = handle_compress ( strm );
42871e7ee59SPeter Avalos             return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
42971e7ee59SPeter Avalos          }
43071e7ee59SPeter Avalos          else
43171e7ee59SPeter Avalos 	 if (action == BZ_FLUSH) {
43271e7ee59SPeter Avalos             s->avail_in_expect = strm->avail_in;
43371e7ee59SPeter Avalos             s->mode = BZ_M_FLUSHING;
43471e7ee59SPeter Avalos             goto preswitch;
43571e7ee59SPeter Avalos          }
43671e7ee59SPeter Avalos          else
43771e7ee59SPeter Avalos          if (action == BZ_FINISH) {
43871e7ee59SPeter Avalos             s->avail_in_expect = strm->avail_in;
43971e7ee59SPeter Avalos             s->mode = BZ_M_FINISHING;
44071e7ee59SPeter Avalos             goto preswitch;
44171e7ee59SPeter Avalos          }
44271e7ee59SPeter Avalos          else
44371e7ee59SPeter Avalos             return BZ_PARAM_ERROR;
44471e7ee59SPeter Avalos 
44571e7ee59SPeter Avalos       case BZ_M_FLUSHING:
44671e7ee59SPeter Avalos          if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
44771e7ee59SPeter Avalos          if (s->avail_in_expect != s->strm->avail_in)
44871e7ee59SPeter Avalos             return BZ_SEQUENCE_ERROR;
44971e7ee59SPeter Avalos          progress = handle_compress ( strm );
45071e7ee59SPeter Avalos          if (s->avail_in_expect > 0 || !isempty_RL(s) ||
45171e7ee59SPeter Avalos              s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
45271e7ee59SPeter Avalos          s->mode = BZ_M_RUNNING;
45371e7ee59SPeter Avalos          return BZ_RUN_OK;
45471e7ee59SPeter Avalos 
45571e7ee59SPeter Avalos       case BZ_M_FINISHING:
45671e7ee59SPeter Avalos          if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
45771e7ee59SPeter Avalos          if (s->avail_in_expect != s->strm->avail_in)
45871e7ee59SPeter Avalos             return BZ_SEQUENCE_ERROR;
45971e7ee59SPeter Avalos          progress = handle_compress ( strm );
46071e7ee59SPeter Avalos          if (!progress) return BZ_SEQUENCE_ERROR;
46171e7ee59SPeter Avalos          if (s->avail_in_expect > 0 || !isempty_RL(s) ||
46271e7ee59SPeter Avalos              s->state_out_pos < s->numZ) return BZ_FINISH_OK;
46371e7ee59SPeter Avalos          s->mode = BZ_M_IDLE;
46471e7ee59SPeter Avalos          return BZ_STREAM_END;
46571e7ee59SPeter Avalos    }
46671e7ee59SPeter Avalos    return BZ_OK; /*--not reached--*/
46771e7ee59SPeter Avalos }
46871e7ee59SPeter Avalos 
46971e7ee59SPeter Avalos 
47071e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzCompressEnd)47171e7ee59SPeter Avalos int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
47271e7ee59SPeter Avalos {
47371e7ee59SPeter Avalos    EState* s;
47471e7ee59SPeter Avalos    if (strm == NULL) return BZ_PARAM_ERROR;
47571e7ee59SPeter Avalos    s = strm->state;
47671e7ee59SPeter Avalos    if (s == NULL) return BZ_PARAM_ERROR;
47771e7ee59SPeter Avalos    if (s->strm != strm) return BZ_PARAM_ERROR;
47871e7ee59SPeter Avalos 
47971e7ee59SPeter Avalos    if (s->arr1 != NULL) BZFREE(s->arr1);
48071e7ee59SPeter Avalos    if (s->arr2 != NULL) BZFREE(s->arr2);
48171e7ee59SPeter Avalos    if (s->ftab != NULL) BZFREE(s->ftab);
48271e7ee59SPeter Avalos    BZFREE(strm->state);
48371e7ee59SPeter Avalos 
48471e7ee59SPeter Avalos    strm->state = NULL;
48571e7ee59SPeter Avalos 
48671e7ee59SPeter Avalos    return BZ_OK;
48771e7ee59SPeter Avalos }
48871e7ee59SPeter Avalos 
489*d8d77baaSSascha Wildner #endif /* BZ_NO_COMPRESS */
49071e7ee59SPeter Avalos 
49171e7ee59SPeter Avalos /*---------------------------------------------------*/
49271e7ee59SPeter Avalos /*--- Decompression stuff                         ---*/
49371e7ee59SPeter Avalos /*---------------------------------------------------*/
49471e7ee59SPeter Avalos 
49571e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompressInit)49671e7ee59SPeter Avalos int BZ_API(BZ2_bzDecompressInit)
49771e7ee59SPeter Avalos                      ( bz_stream* strm,
49871e7ee59SPeter Avalos                        int        verbosity,
49971e7ee59SPeter Avalos                        int        small )
50071e7ee59SPeter Avalos {
50171e7ee59SPeter Avalos    DState* s;
50271e7ee59SPeter Avalos 
50371e7ee59SPeter Avalos    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
50471e7ee59SPeter Avalos 
50571e7ee59SPeter Avalos    if (strm == NULL) return BZ_PARAM_ERROR;
50671e7ee59SPeter Avalos    if (small != 0 && small != 1) return BZ_PARAM_ERROR;
50771e7ee59SPeter Avalos    if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
50871e7ee59SPeter Avalos 
50971e7ee59SPeter Avalos    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
51071e7ee59SPeter Avalos    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
51171e7ee59SPeter Avalos 
51271e7ee59SPeter Avalos    s = BZALLOC( sizeof(DState) );
51371e7ee59SPeter Avalos    if (s == NULL) return BZ_MEM_ERROR;
51471e7ee59SPeter Avalos    s->strm                  = strm;
51571e7ee59SPeter Avalos    strm->state              = s;
51671e7ee59SPeter Avalos    s->state                 = BZ_X_MAGIC_1;
51771e7ee59SPeter Avalos    s->bsLive                = 0;
51871e7ee59SPeter Avalos    s->bsBuff                = 0;
51971e7ee59SPeter Avalos    s->calculatedCombinedCRC = 0;
52071e7ee59SPeter Avalos    strm->total_in_lo32      = 0;
52171e7ee59SPeter Avalos    strm->total_in_hi32      = 0;
52271e7ee59SPeter Avalos    strm->total_out_lo32     = 0;
52371e7ee59SPeter Avalos    strm->total_out_hi32     = 0;
52471e7ee59SPeter Avalos    s->smallDecompress       = (Bool)small;
52571e7ee59SPeter Avalos    s->ll4                   = NULL;
52671e7ee59SPeter Avalos    s->ll16                  = NULL;
52771e7ee59SPeter Avalos    s->tt                    = NULL;
52871e7ee59SPeter Avalos    s->currBlockNo           = 0;
52971e7ee59SPeter Avalos    s->verbosity             = verbosity;
53071e7ee59SPeter Avalos 
53171e7ee59SPeter Avalos    return BZ_OK;
53271e7ee59SPeter Avalos }
53371e7ee59SPeter Avalos 
53471e7ee59SPeter Avalos 
53571e7ee59SPeter Avalos /*---------------------------------------------------*/
53671e7ee59SPeter Avalos /* Return  True iff data corruption is discovered.
53771e7ee59SPeter Avalos    Returns False if there is no problem.
53871e7ee59SPeter Avalos */
53971e7ee59SPeter Avalos static
unRLE_obuf_to_output_FAST(DState * s)54071e7ee59SPeter Avalos Bool unRLE_obuf_to_output_FAST ( DState* s )
54171e7ee59SPeter Avalos {
54271e7ee59SPeter Avalos    UChar k1;
54371e7ee59SPeter Avalos 
54471e7ee59SPeter Avalos    if (s->blockRandomised) {
54571e7ee59SPeter Avalos 
54671e7ee59SPeter Avalos       while (True) {
54771e7ee59SPeter Avalos          /* try to finish existing run */
54871e7ee59SPeter Avalos          while (True) {
54971e7ee59SPeter Avalos             if (s->strm->avail_out == 0) return False;
55071e7ee59SPeter Avalos             if (s->state_out_len == 0) break;
55171e7ee59SPeter Avalos             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
55271e7ee59SPeter Avalos             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
55371e7ee59SPeter Avalos             s->state_out_len--;
55471e7ee59SPeter Avalos             s->strm->next_out++;
55571e7ee59SPeter Avalos             s->strm->avail_out--;
55671e7ee59SPeter Avalos             s->strm->total_out_lo32++;
55771e7ee59SPeter Avalos             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
55871e7ee59SPeter Avalos          }
55971e7ee59SPeter Avalos 
56071e7ee59SPeter Avalos          /* can a new run be started? */
56171e7ee59SPeter Avalos          if (s->nblock_used == s->save_nblock+1) return False;
56271e7ee59SPeter Avalos 
56371e7ee59SPeter Avalos          /* Only caused by corrupt data stream? */
56471e7ee59SPeter Avalos          if (s->nblock_used > s->save_nblock+1)
56571e7ee59SPeter Avalos             return True;
56671e7ee59SPeter Avalos 
56771e7ee59SPeter Avalos          s->state_out_len = 1;
56871e7ee59SPeter Avalos          s->state_out_ch = s->k0;
56971e7ee59SPeter Avalos          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
57071e7ee59SPeter Avalos          k1 ^= BZ_RAND_MASK; s->nblock_used++;
57171e7ee59SPeter Avalos          if (s->nblock_used == s->save_nblock+1) continue;
57271e7ee59SPeter Avalos          if (k1 != s->k0) { s->k0 = k1; continue; };
57371e7ee59SPeter Avalos 
57471e7ee59SPeter Avalos          s->state_out_len = 2;
57571e7ee59SPeter Avalos          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
57671e7ee59SPeter Avalos          k1 ^= BZ_RAND_MASK; s->nblock_used++;
57771e7ee59SPeter Avalos          if (s->nblock_used == s->save_nblock+1) continue;
57871e7ee59SPeter Avalos          if (k1 != s->k0) { s->k0 = k1; continue; };
57971e7ee59SPeter Avalos 
58071e7ee59SPeter Avalos          s->state_out_len = 3;
58171e7ee59SPeter Avalos          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
58271e7ee59SPeter Avalos          k1 ^= BZ_RAND_MASK; s->nblock_used++;
58371e7ee59SPeter Avalos          if (s->nblock_used == s->save_nblock+1) continue;
58471e7ee59SPeter Avalos          if (k1 != s->k0) { s->k0 = k1; continue; };
58571e7ee59SPeter Avalos 
58671e7ee59SPeter Avalos          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
58771e7ee59SPeter Avalos          k1 ^= BZ_RAND_MASK; s->nblock_used++;
58871e7ee59SPeter Avalos          s->state_out_len = ((Int32)k1) + 4;
58971e7ee59SPeter Avalos          BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
59071e7ee59SPeter Avalos          s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
59171e7ee59SPeter Avalos       }
59271e7ee59SPeter Avalos 
59371e7ee59SPeter Avalos    } else {
59471e7ee59SPeter Avalos 
59571e7ee59SPeter Avalos       /* restore */
59671e7ee59SPeter Avalos       UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC;
59771e7ee59SPeter Avalos       UChar         c_state_out_ch       = s->state_out_ch;
59871e7ee59SPeter Avalos       Int32         c_state_out_len      = s->state_out_len;
59971e7ee59SPeter Avalos       Int32         c_nblock_used        = s->nblock_used;
60071e7ee59SPeter Avalos       Int32         c_k0                 = s->k0;
60171e7ee59SPeter Avalos       UInt32*       c_tt                 = s->tt;
60271e7ee59SPeter Avalos       UInt32        c_tPos               = s->tPos;
60371e7ee59SPeter Avalos       char*         cs_next_out          = s->strm->next_out;
60471e7ee59SPeter Avalos       unsigned int  cs_avail_out         = s->strm->avail_out;
60571e7ee59SPeter Avalos       Int32         ro_blockSize100k     = s->blockSize100k;
60671e7ee59SPeter Avalos       /* end restore */
60771e7ee59SPeter Avalos 
60871e7ee59SPeter Avalos       UInt32       avail_out_INIT = cs_avail_out;
60971e7ee59SPeter Avalos       Int32        s_save_nblockPP = s->save_nblock+1;
61071e7ee59SPeter Avalos       unsigned int total_out_lo32_old;
61171e7ee59SPeter Avalos 
61271e7ee59SPeter Avalos       while (True) {
61371e7ee59SPeter Avalos 
61471e7ee59SPeter Avalos          /* try to finish existing run */
61571e7ee59SPeter Avalos          if (c_state_out_len > 0) {
61671e7ee59SPeter Avalos             while (True) {
61771e7ee59SPeter Avalos                if (cs_avail_out == 0) goto return_notr;
61871e7ee59SPeter Avalos                if (c_state_out_len == 1) break;
61971e7ee59SPeter Avalos                *( (UChar*)(cs_next_out) ) = c_state_out_ch;
62071e7ee59SPeter Avalos                BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
62171e7ee59SPeter Avalos                c_state_out_len--;
62271e7ee59SPeter Avalos                cs_next_out++;
62371e7ee59SPeter Avalos                cs_avail_out--;
62471e7ee59SPeter Avalos             }
62571e7ee59SPeter Avalos             s_state_out_len_eq_one:
62671e7ee59SPeter Avalos             {
62771e7ee59SPeter Avalos                if (cs_avail_out == 0) {
62871e7ee59SPeter Avalos                   c_state_out_len = 1; goto return_notr;
62971e7ee59SPeter Avalos                };
63071e7ee59SPeter Avalos                *( (UChar*)(cs_next_out) ) = c_state_out_ch;
63171e7ee59SPeter Avalos                BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
63271e7ee59SPeter Avalos                cs_next_out++;
63371e7ee59SPeter Avalos                cs_avail_out--;
63471e7ee59SPeter Avalos             }
63571e7ee59SPeter Avalos          }
63671e7ee59SPeter Avalos          /* Only caused by corrupt data stream? */
63771e7ee59SPeter Avalos          if (c_nblock_used > s_save_nblockPP)
63871e7ee59SPeter Avalos             return True;
63971e7ee59SPeter Avalos 
64071e7ee59SPeter Avalos          /* can a new run be started? */
64171e7ee59SPeter Avalos          if (c_nblock_used == s_save_nblockPP) {
64271e7ee59SPeter Avalos             c_state_out_len = 0; goto return_notr;
64371e7ee59SPeter Avalos          };
64471e7ee59SPeter Avalos          c_state_out_ch = c_k0;
64571e7ee59SPeter Avalos          BZ_GET_FAST_C(k1); c_nblock_used++;
64671e7ee59SPeter Avalos          if (k1 != c_k0) {
64771e7ee59SPeter Avalos             c_k0 = k1; goto s_state_out_len_eq_one;
64871e7ee59SPeter Avalos          };
64971e7ee59SPeter Avalos          if (c_nblock_used == s_save_nblockPP)
65071e7ee59SPeter Avalos             goto s_state_out_len_eq_one;
65171e7ee59SPeter Avalos 
65271e7ee59SPeter Avalos          c_state_out_len = 2;
65371e7ee59SPeter Avalos          BZ_GET_FAST_C(k1); c_nblock_used++;
65471e7ee59SPeter Avalos          if (c_nblock_used == s_save_nblockPP) continue;
65571e7ee59SPeter Avalos          if (k1 != c_k0) { c_k0 = k1; continue; };
65671e7ee59SPeter Avalos 
65771e7ee59SPeter Avalos          c_state_out_len = 3;
65871e7ee59SPeter Avalos          BZ_GET_FAST_C(k1); c_nblock_used++;
65971e7ee59SPeter Avalos          if (c_nblock_used == s_save_nblockPP) continue;
66071e7ee59SPeter Avalos          if (k1 != c_k0) { c_k0 = k1; continue; };
66171e7ee59SPeter Avalos 
66271e7ee59SPeter Avalos          BZ_GET_FAST_C(k1); c_nblock_used++;
66371e7ee59SPeter Avalos          c_state_out_len = ((Int32)k1) + 4;
66471e7ee59SPeter Avalos          BZ_GET_FAST_C(c_k0); c_nblock_used++;
66571e7ee59SPeter Avalos       }
66671e7ee59SPeter Avalos 
66771e7ee59SPeter Avalos       return_notr:
66871e7ee59SPeter Avalos       total_out_lo32_old = s->strm->total_out_lo32;
66971e7ee59SPeter Avalos       s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
67071e7ee59SPeter Avalos       if (s->strm->total_out_lo32 < total_out_lo32_old)
67171e7ee59SPeter Avalos          s->strm->total_out_hi32++;
67271e7ee59SPeter Avalos 
67371e7ee59SPeter Avalos       /* save */
67471e7ee59SPeter Avalos       s->calculatedBlockCRC = c_calculatedBlockCRC;
67571e7ee59SPeter Avalos       s->state_out_ch       = c_state_out_ch;
67671e7ee59SPeter Avalos       s->state_out_len      = c_state_out_len;
67771e7ee59SPeter Avalos       s->nblock_used        = c_nblock_used;
67871e7ee59SPeter Avalos       s->k0                 = c_k0;
67971e7ee59SPeter Avalos       s->tt                 = c_tt;
68071e7ee59SPeter Avalos       s->tPos               = c_tPos;
68171e7ee59SPeter Avalos       s->strm->next_out     = cs_next_out;
68271e7ee59SPeter Avalos       s->strm->avail_out    = cs_avail_out;
68371e7ee59SPeter Avalos       /* end save */
68471e7ee59SPeter Avalos    }
68571e7ee59SPeter Avalos    return False;
68671e7ee59SPeter Avalos }
68771e7ee59SPeter Avalos 
68871e7ee59SPeter Avalos 
68971e7ee59SPeter Avalos 
69071e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ2_indexIntoF(Int32 indx,Int32 * cftab)69171e7ee59SPeter Avalos __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
69271e7ee59SPeter Avalos {
69371e7ee59SPeter Avalos    Int32 nb, na, mid;
69471e7ee59SPeter Avalos    nb = 0;
69571e7ee59SPeter Avalos    na = 256;
69671e7ee59SPeter Avalos    do {
69771e7ee59SPeter Avalos       mid = (nb + na) >> 1;
69871e7ee59SPeter Avalos       if (indx >= cftab[mid]) nb = mid; else na = mid;
69971e7ee59SPeter Avalos    }
70071e7ee59SPeter Avalos    while (na - nb != 1);
70171e7ee59SPeter Avalos    return nb;
70271e7ee59SPeter Avalos }
70371e7ee59SPeter Avalos 
70471e7ee59SPeter Avalos 
70571e7ee59SPeter Avalos /*---------------------------------------------------*/
70671e7ee59SPeter Avalos /* Return  True iff data corruption is discovered.
70771e7ee59SPeter Avalos    Returns False if there is no problem.
70871e7ee59SPeter Avalos */
70971e7ee59SPeter Avalos static
unRLE_obuf_to_output_SMALL(DState * s)71071e7ee59SPeter Avalos Bool unRLE_obuf_to_output_SMALL ( DState* s )
71171e7ee59SPeter Avalos {
71271e7ee59SPeter Avalos    UChar k1;
71371e7ee59SPeter Avalos 
71471e7ee59SPeter Avalos    if (s->blockRandomised) {
71571e7ee59SPeter Avalos 
71671e7ee59SPeter Avalos       while (True) {
71771e7ee59SPeter Avalos          /* try to finish existing run */
71871e7ee59SPeter Avalos          while (True) {
71971e7ee59SPeter Avalos             if (s->strm->avail_out == 0) return False;
72071e7ee59SPeter Avalos             if (s->state_out_len == 0) break;
72171e7ee59SPeter Avalos             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
72271e7ee59SPeter Avalos             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
72371e7ee59SPeter Avalos             s->state_out_len--;
72471e7ee59SPeter Avalos             s->strm->next_out++;
72571e7ee59SPeter Avalos             s->strm->avail_out--;
72671e7ee59SPeter Avalos             s->strm->total_out_lo32++;
72771e7ee59SPeter Avalos             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
72871e7ee59SPeter Avalos          }
72971e7ee59SPeter Avalos 
73071e7ee59SPeter Avalos          /* can a new run be started? */
73171e7ee59SPeter Avalos          if (s->nblock_used == s->save_nblock+1) return False;
73271e7ee59SPeter Avalos 
73371e7ee59SPeter Avalos          /* Only caused by corrupt data stream? */
73471e7ee59SPeter Avalos          if (s->nblock_used > s->save_nblock+1)
73571e7ee59SPeter Avalos             return True;
73671e7ee59SPeter Avalos 
73771e7ee59SPeter Avalos          s->state_out_len = 1;
73871e7ee59SPeter Avalos          s->state_out_ch = s->k0;
73971e7ee59SPeter Avalos          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
74071e7ee59SPeter Avalos          k1 ^= BZ_RAND_MASK; s->nblock_used++;
74171e7ee59SPeter Avalos          if (s->nblock_used == s->save_nblock+1) continue;
74271e7ee59SPeter Avalos          if (k1 != s->k0) { s->k0 = k1; continue; };
74371e7ee59SPeter Avalos 
74471e7ee59SPeter Avalos          s->state_out_len = 2;
74571e7ee59SPeter Avalos          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
74671e7ee59SPeter Avalos          k1 ^= BZ_RAND_MASK; s->nblock_used++;
74771e7ee59SPeter Avalos          if (s->nblock_used == s->save_nblock+1) continue;
74871e7ee59SPeter Avalos          if (k1 != s->k0) { s->k0 = k1; continue; };
74971e7ee59SPeter Avalos 
75071e7ee59SPeter Avalos          s->state_out_len = 3;
75171e7ee59SPeter Avalos          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
75271e7ee59SPeter Avalos          k1 ^= BZ_RAND_MASK; s->nblock_used++;
75371e7ee59SPeter Avalos          if (s->nblock_used == s->save_nblock+1) continue;
75471e7ee59SPeter Avalos          if (k1 != s->k0) { s->k0 = k1; continue; };
75571e7ee59SPeter Avalos 
75671e7ee59SPeter Avalos          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
75771e7ee59SPeter Avalos          k1 ^= BZ_RAND_MASK; s->nblock_used++;
75871e7ee59SPeter Avalos          s->state_out_len = ((Int32)k1) + 4;
75971e7ee59SPeter Avalos          BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
76071e7ee59SPeter Avalos          s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
76171e7ee59SPeter Avalos       }
76271e7ee59SPeter Avalos 
76371e7ee59SPeter Avalos    } else {
76471e7ee59SPeter Avalos 
76571e7ee59SPeter Avalos       while (True) {
76671e7ee59SPeter Avalos          /* try to finish existing run */
76771e7ee59SPeter Avalos          while (True) {
76871e7ee59SPeter Avalos             if (s->strm->avail_out == 0) return False;
76971e7ee59SPeter Avalos             if (s->state_out_len == 0) break;
77071e7ee59SPeter Avalos             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
77171e7ee59SPeter Avalos             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
77271e7ee59SPeter Avalos             s->state_out_len--;
77371e7ee59SPeter Avalos             s->strm->next_out++;
77471e7ee59SPeter Avalos             s->strm->avail_out--;
77571e7ee59SPeter Avalos             s->strm->total_out_lo32++;
77671e7ee59SPeter Avalos             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
77771e7ee59SPeter Avalos          }
77871e7ee59SPeter Avalos 
77971e7ee59SPeter Avalos          /* can a new run be started? */
78071e7ee59SPeter Avalos          if (s->nblock_used == s->save_nblock+1) return False;
78171e7ee59SPeter Avalos 
78271e7ee59SPeter Avalos          /* Only caused by corrupt data stream? */
78371e7ee59SPeter Avalos          if (s->nblock_used > s->save_nblock+1)
78471e7ee59SPeter Avalos             return True;
78571e7ee59SPeter Avalos 
78671e7ee59SPeter Avalos          s->state_out_len = 1;
78771e7ee59SPeter Avalos          s->state_out_ch = s->k0;
78871e7ee59SPeter Avalos          BZ_GET_SMALL(k1); s->nblock_used++;
78971e7ee59SPeter Avalos          if (s->nblock_used == s->save_nblock+1) continue;
79071e7ee59SPeter Avalos          if (k1 != s->k0) { s->k0 = k1; continue; };
79171e7ee59SPeter Avalos 
79271e7ee59SPeter Avalos          s->state_out_len = 2;
79371e7ee59SPeter Avalos          BZ_GET_SMALL(k1); s->nblock_used++;
79471e7ee59SPeter Avalos          if (s->nblock_used == s->save_nblock+1) continue;
79571e7ee59SPeter Avalos          if (k1 != s->k0) { s->k0 = k1; continue; };
79671e7ee59SPeter Avalos 
79771e7ee59SPeter Avalos          s->state_out_len = 3;
79871e7ee59SPeter Avalos          BZ_GET_SMALL(k1); s->nblock_used++;
79971e7ee59SPeter Avalos          if (s->nblock_used == s->save_nblock+1) continue;
80071e7ee59SPeter Avalos          if (k1 != s->k0) { s->k0 = k1; continue; };
80171e7ee59SPeter Avalos 
80271e7ee59SPeter Avalos          BZ_GET_SMALL(k1); s->nblock_used++;
80371e7ee59SPeter Avalos          s->state_out_len = ((Int32)k1) + 4;
80471e7ee59SPeter Avalos          BZ_GET_SMALL(s->k0); s->nblock_used++;
80571e7ee59SPeter Avalos       }
80671e7ee59SPeter Avalos 
80771e7ee59SPeter Avalos    }
80871e7ee59SPeter Avalos }
80971e7ee59SPeter Avalos 
81071e7ee59SPeter Avalos 
81171e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompress)81271e7ee59SPeter Avalos int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
81371e7ee59SPeter Avalos {
81471e7ee59SPeter Avalos    Bool    corrupt;
81571e7ee59SPeter Avalos    DState* s;
81671e7ee59SPeter Avalos    if (strm == NULL) return BZ_PARAM_ERROR;
81771e7ee59SPeter Avalos    s = strm->state;
81871e7ee59SPeter Avalos    if (s == NULL) return BZ_PARAM_ERROR;
81971e7ee59SPeter Avalos    if (s->strm != strm) return BZ_PARAM_ERROR;
82071e7ee59SPeter Avalos 
82171e7ee59SPeter Avalos    while (True) {
82271e7ee59SPeter Avalos       if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
82371e7ee59SPeter Avalos       if (s->state == BZ_X_OUTPUT) {
82471e7ee59SPeter Avalos          if (s->smallDecompress)
82571e7ee59SPeter Avalos             corrupt = unRLE_obuf_to_output_SMALL ( s ); else
82671e7ee59SPeter Avalos             corrupt = unRLE_obuf_to_output_FAST  ( s );
82771e7ee59SPeter Avalos          if (corrupt) return BZ_DATA_ERROR;
82871e7ee59SPeter Avalos          if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
82971e7ee59SPeter Avalos             BZ_FINALISE_CRC ( s->calculatedBlockCRC );
83071e7ee59SPeter Avalos             if (s->verbosity >= 3)
83171e7ee59SPeter Avalos                VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
83271e7ee59SPeter Avalos                           s->calculatedBlockCRC );
83371e7ee59SPeter Avalos             if (s->verbosity >= 2) VPrintf0 ( "]" );
83471e7ee59SPeter Avalos             if (s->calculatedBlockCRC != s->storedBlockCRC)
83571e7ee59SPeter Avalos                return BZ_DATA_ERROR;
83671e7ee59SPeter Avalos             s->calculatedCombinedCRC
83771e7ee59SPeter Avalos                = (s->calculatedCombinedCRC << 1) |
83871e7ee59SPeter Avalos                     (s->calculatedCombinedCRC >> 31);
83971e7ee59SPeter Avalos             s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
84071e7ee59SPeter Avalos             s->state = BZ_X_BLKHDR_1;
84171e7ee59SPeter Avalos          } else {
84271e7ee59SPeter Avalos             return BZ_OK;
84371e7ee59SPeter Avalos          }
84471e7ee59SPeter Avalos       }
84571e7ee59SPeter Avalos       if (s->state >= BZ_X_MAGIC_1) {
84671e7ee59SPeter Avalos          Int32 r = BZ2_decompress ( s );
84771e7ee59SPeter Avalos          if (r == BZ_STREAM_END) {
84871e7ee59SPeter Avalos             if (s->verbosity >= 3)
84971e7ee59SPeter Avalos                VPrintf2 ( "\n    combined CRCs: stored = 0x%08x, computed = 0x%08x",
85071e7ee59SPeter Avalos                           s->storedCombinedCRC, s->calculatedCombinedCRC );
85171e7ee59SPeter Avalos             if (s->calculatedCombinedCRC != s->storedCombinedCRC)
85271e7ee59SPeter Avalos                return BZ_DATA_ERROR;
85371e7ee59SPeter Avalos             return r;
85471e7ee59SPeter Avalos          }
85571e7ee59SPeter Avalos          if (s->state != BZ_X_OUTPUT) return r;
85671e7ee59SPeter Avalos       }
85771e7ee59SPeter Avalos    }
85871e7ee59SPeter Avalos 
85971e7ee59SPeter Avalos    AssertH ( 0, 6001 );
86071e7ee59SPeter Avalos 
86171e7ee59SPeter Avalos    return 0;  /*NOTREACHED*/
86271e7ee59SPeter Avalos }
86371e7ee59SPeter Avalos 
86471e7ee59SPeter Avalos 
86571e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompressEnd)86671e7ee59SPeter Avalos int BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm )
86771e7ee59SPeter Avalos {
86871e7ee59SPeter Avalos    DState* s;
86971e7ee59SPeter Avalos    if (strm == NULL) return BZ_PARAM_ERROR;
87071e7ee59SPeter Avalos    s = strm->state;
87171e7ee59SPeter Avalos    if (s == NULL) return BZ_PARAM_ERROR;
87271e7ee59SPeter Avalos    if (s->strm != strm) return BZ_PARAM_ERROR;
87371e7ee59SPeter Avalos 
87471e7ee59SPeter Avalos    if (s->tt   != NULL) BZFREE(s->tt);
87571e7ee59SPeter Avalos    if (s->ll16 != NULL) BZFREE(s->ll16);
87671e7ee59SPeter Avalos    if (s->ll4  != NULL) BZFREE(s->ll4);
87771e7ee59SPeter Avalos 
87871e7ee59SPeter Avalos    BZFREE(strm->state);
87971e7ee59SPeter Avalos    strm->state = NULL;
88071e7ee59SPeter Avalos 
88171e7ee59SPeter Avalos    return BZ_OK;
88271e7ee59SPeter Avalos }
88371e7ee59SPeter Avalos 
884*d8d77baaSSascha Wildner #ifndef BZ_NO_COMPRESS
88571e7ee59SPeter Avalos 
88671e7ee59SPeter Avalos #ifndef BZ_NO_STDIO
88771e7ee59SPeter Avalos /*---------------------------------------------------*/
88871e7ee59SPeter Avalos /*--- File I/O stuff                              ---*/
88971e7ee59SPeter Avalos /*---------------------------------------------------*/
89071e7ee59SPeter Avalos 
89171e7ee59SPeter Avalos #define BZ_SETERR(eee)                    \
89271e7ee59SPeter Avalos {                                         \
89371e7ee59SPeter Avalos    if (bzerror != NULL) *bzerror = eee;   \
89471e7ee59SPeter Avalos    if (bzf != NULL) bzf->lastErr = eee;   \
89571e7ee59SPeter Avalos }
89671e7ee59SPeter Avalos 
89771e7ee59SPeter Avalos typedef
89871e7ee59SPeter Avalos    struct {
89971e7ee59SPeter Avalos       FILE*     handle;
90071e7ee59SPeter Avalos       Char      buf[BZ_MAX_UNUSED];
90171e7ee59SPeter Avalos       Int32     bufN;
90271e7ee59SPeter Avalos       Bool      writing;
90371e7ee59SPeter Avalos       bz_stream strm;
90471e7ee59SPeter Avalos       Int32     lastErr;
90571e7ee59SPeter Avalos       Bool      initialisedOk;
90671e7ee59SPeter Avalos    }
90771e7ee59SPeter Avalos    bzFile;
90871e7ee59SPeter Avalos 
90971e7ee59SPeter Avalos 
91071e7ee59SPeter Avalos /*---------------------------------------------*/
myfeof(FILE * f)91171e7ee59SPeter Avalos static Bool myfeof ( FILE* f )
91271e7ee59SPeter Avalos {
91371e7ee59SPeter Avalos    Int32 c = fgetc ( f );
91471e7ee59SPeter Avalos    if (c == EOF) return True;
91571e7ee59SPeter Avalos    ungetc ( c, f );
91671e7ee59SPeter Avalos    return False;
91771e7ee59SPeter Avalos }
91871e7ee59SPeter Avalos 
91971e7ee59SPeter Avalos 
92071e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzWriteOpen)92171e7ee59SPeter Avalos BZFILE* BZ_API(BZ2_bzWriteOpen)
92271e7ee59SPeter Avalos                     ( int*  bzerror,
92371e7ee59SPeter Avalos                       FILE* f,
92471e7ee59SPeter Avalos                       int   blockSize100k,
92571e7ee59SPeter Avalos                       int   verbosity,
92671e7ee59SPeter Avalos                       int   workFactor )
92771e7ee59SPeter Avalos {
92871e7ee59SPeter Avalos    Int32   ret;
92971e7ee59SPeter Avalos    bzFile* bzf = NULL;
93071e7ee59SPeter Avalos 
93171e7ee59SPeter Avalos    BZ_SETERR(BZ_OK);
93271e7ee59SPeter Avalos 
93371e7ee59SPeter Avalos    if (f == NULL ||
93471e7ee59SPeter Avalos        (blockSize100k < 1 || blockSize100k > 9) ||
93571e7ee59SPeter Avalos        (workFactor < 0 || workFactor > 250) ||
93671e7ee59SPeter Avalos        (verbosity < 0 || verbosity > 4))
93771e7ee59SPeter Avalos       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
93871e7ee59SPeter Avalos 
93971e7ee59SPeter Avalos    if (ferror(f))
94071e7ee59SPeter Avalos       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
94171e7ee59SPeter Avalos 
94271e7ee59SPeter Avalos    bzf = malloc ( sizeof(bzFile) );
94371e7ee59SPeter Avalos    if (bzf == NULL)
94471e7ee59SPeter Avalos       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
94571e7ee59SPeter Avalos 
94671e7ee59SPeter Avalos    BZ_SETERR(BZ_OK);
94771e7ee59SPeter Avalos    bzf->initialisedOk = False;
94871e7ee59SPeter Avalos    bzf->bufN          = 0;
94971e7ee59SPeter Avalos    bzf->handle        = f;
95071e7ee59SPeter Avalos    bzf->writing       = True;
95171e7ee59SPeter Avalos    bzf->strm.bzalloc  = NULL;
95271e7ee59SPeter Avalos    bzf->strm.bzfree   = NULL;
95371e7ee59SPeter Avalos    bzf->strm.opaque   = NULL;
95471e7ee59SPeter Avalos 
95571e7ee59SPeter Avalos    if (workFactor == 0) workFactor = 30;
95671e7ee59SPeter Avalos    ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
95771e7ee59SPeter Avalos                               verbosity, workFactor );
95871e7ee59SPeter Avalos    if (ret != BZ_OK)
95971e7ee59SPeter Avalos       { BZ_SETERR(ret); free(bzf); return NULL; };
96071e7ee59SPeter Avalos 
96171e7ee59SPeter Avalos    bzf->strm.avail_in = 0;
96271e7ee59SPeter Avalos    bzf->initialisedOk = True;
96371e7ee59SPeter Avalos    return bzf;
96471e7ee59SPeter Avalos }
96571e7ee59SPeter Avalos 
96671e7ee59SPeter Avalos 
96771e7ee59SPeter Avalos 
96871e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzWrite)96971e7ee59SPeter Avalos void BZ_API(BZ2_bzWrite)
97071e7ee59SPeter Avalos              ( int*    bzerror,
97171e7ee59SPeter Avalos                BZFILE* b,
97271e7ee59SPeter Avalos                void*   buf,
97371e7ee59SPeter Avalos                int     len )
97471e7ee59SPeter Avalos {
97571e7ee59SPeter Avalos    Int32 n, n2, ret;
97671e7ee59SPeter Avalos    bzFile* bzf = (bzFile*)b;
97771e7ee59SPeter Avalos 
97871e7ee59SPeter Avalos    BZ_SETERR(BZ_OK);
97971e7ee59SPeter Avalos    if (bzf == NULL || buf == NULL || len < 0)
98071e7ee59SPeter Avalos       { BZ_SETERR(BZ_PARAM_ERROR); return; };
98171e7ee59SPeter Avalos    if (!(bzf->writing))
98271e7ee59SPeter Avalos       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
98371e7ee59SPeter Avalos    if (ferror(bzf->handle))
98471e7ee59SPeter Avalos       { BZ_SETERR(BZ_IO_ERROR); return; };
98571e7ee59SPeter Avalos 
98671e7ee59SPeter Avalos    if (len == 0)
98771e7ee59SPeter Avalos       { BZ_SETERR(BZ_OK); return; };
98871e7ee59SPeter Avalos 
98971e7ee59SPeter Avalos    bzf->strm.avail_in = len;
99071e7ee59SPeter Avalos    bzf->strm.next_in  = buf;
99171e7ee59SPeter Avalos 
99271e7ee59SPeter Avalos    while (True) {
99371e7ee59SPeter Avalos       bzf->strm.avail_out = BZ_MAX_UNUSED;
99471e7ee59SPeter Avalos       bzf->strm.next_out = bzf->buf;
99571e7ee59SPeter Avalos       ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
99671e7ee59SPeter Avalos       if (ret != BZ_RUN_OK)
99771e7ee59SPeter Avalos          { BZ_SETERR(ret); return; };
99871e7ee59SPeter Avalos 
99971e7ee59SPeter Avalos       if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
100071e7ee59SPeter Avalos          n = BZ_MAX_UNUSED - bzf->strm.avail_out;
100171e7ee59SPeter Avalos          n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
100271e7ee59SPeter Avalos                        n, bzf->handle );
100371e7ee59SPeter Avalos          if (n != n2 || ferror(bzf->handle))
100471e7ee59SPeter Avalos             { BZ_SETERR(BZ_IO_ERROR); return; };
100571e7ee59SPeter Avalos       }
100671e7ee59SPeter Avalos 
100771e7ee59SPeter Avalos       if (bzf->strm.avail_in == 0)
100871e7ee59SPeter Avalos          { BZ_SETERR(BZ_OK); return; };
100971e7ee59SPeter Avalos    }
101071e7ee59SPeter Avalos }
101171e7ee59SPeter Avalos 
101271e7ee59SPeter Avalos 
101371e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzWriteClose)101471e7ee59SPeter Avalos void BZ_API(BZ2_bzWriteClose)
101571e7ee59SPeter Avalos                   ( int*          bzerror,
101671e7ee59SPeter Avalos                     BZFILE*       b,
101771e7ee59SPeter Avalos                     int           abandon,
101871e7ee59SPeter Avalos                     unsigned int* nbytes_in,
101971e7ee59SPeter Avalos                     unsigned int* nbytes_out )
102071e7ee59SPeter Avalos {
102171e7ee59SPeter Avalos    BZ2_bzWriteClose64 ( bzerror, b, abandon,
102271e7ee59SPeter Avalos                         nbytes_in, NULL, nbytes_out, NULL );
102371e7ee59SPeter Avalos }
102471e7ee59SPeter Avalos 
102571e7ee59SPeter Avalos 
BZ_API(BZ2_bzWriteClose64)102671e7ee59SPeter Avalos void BZ_API(BZ2_bzWriteClose64)
102771e7ee59SPeter Avalos                   ( int*          bzerror,
102871e7ee59SPeter Avalos                     BZFILE*       b,
102971e7ee59SPeter Avalos                     int           abandon,
103071e7ee59SPeter Avalos                     unsigned int* nbytes_in_lo32,
103171e7ee59SPeter Avalos                     unsigned int* nbytes_in_hi32,
103271e7ee59SPeter Avalos                     unsigned int* nbytes_out_lo32,
103371e7ee59SPeter Avalos                     unsigned int* nbytes_out_hi32 )
103471e7ee59SPeter Avalos {
103571e7ee59SPeter Avalos    Int32   n, n2, ret;
103671e7ee59SPeter Avalos    bzFile* bzf = (bzFile*)b;
103771e7ee59SPeter Avalos 
103871e7ee59SPeter Avalos    if (bzf == NULL)
103971e7ee59SPeter Avalos       { BZ_SETERR(BZ_OK); return; };
104071e7ee59SPeter Avalos    if (!(bzf->writing))
104171e7ee59SPeter Avalos       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
104271e7ee59SPeter Avalos    if (ferror(bzf->handle))
104371e7ee59SPeter Avalos       { BZ_SETERR(BZ_IO_ERROR); return; };
104471e7ee59SPeter Avalos 
104571e7ee59SPeter Avalos    if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
104671e7ee59SPeter Avalos    if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
104771e7ee59SPeter Avalos    if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
104871e7ee59SPeter Avalos    if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
104971e7ee59SPeter Avalos 
105071e7ee59SPeter Avalos    if ((!abandon) && bzf->lastErr == BZ_OK) {
105171e7ee59SPeter Avalos       while (True) {
105271e7ee59SPeter Avalos          bzf->strm.avail_out = BZ_MAX_UNUSED;
105371e7ee59SPeter Avalos          bzf->strm.next_out = bzf->buf;
105471e7ee59SPeter Avalos          ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
105571e7ee59SPeter Avalos          if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
105671e7ee59SPeter Avalos             { BZ_SETERR(ret); return; };
105771e7ee59SPeter Avalos 
105871e7ee59SPeter Avalos          if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
105971e7ee59SPeter Avalos             n = BZ_MAX_UNUSED - bzf->strm.avail_out;
106071e7ee59SPeter Avalos             n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
106171e7ee59SPeter Avalos                           n, bzf->handle );
106271e7ee59SPeter Avalos             if (n != n2 || ferror(bzf->handle))
106371e7ee59SPeter Avalos                { BZ_SETERR(BZ_IO_ERROR); return; };
106471e7ee59SPeter Avalos          }
106571e7ee59SPeter Avalos 
106671e7ee59SPeter Avalos          if (ret == BZ_STREAM_END) break;
106771e7ee59SPeter Avalos       }
106871e7ee59SPeter Avalos    }
106971e7ee59SPeter Avalos 
107071e7ee59SPeter Avalos    if ( !abandon && !ferror ( bzf->handle ) ) {
107171e7ee59SPeter Avalos       fflush ( bzf->handle );
107271e7ee59SPeter Avalos       if (ferror(bzf->handle))
107371e7ee59SPeter Avalos          { BZ_SETERR(BZ_IO_ERROR); return; };
107471e7ee59SPeter Avalos    }
107571e7ee59SPeter Avalos 
107671e7ee59SPeter Avalos    if (nbytes_in_lo32 != NULL)
107771e7ee59SPeter Avalos       *nbytes_in_lo32 = bzf->strm.total_in_lo32;
107871e7ee59SPeter Avalos    if (nbytes_in_hi32 != NULL)
107971e7ee59SPeter Avalos       *nbytes_in_hi32 = bzf->strm.total_in_hi32;
108071e7ee59SPeter Avalos    if (nbytes_out_lo32 != NULL)
108171e7ee59SPeter Avalos       *nbytes_out_lo32 = bzf->strm.total_out_lo32;
108271e7ee59SPeter Avalos    if (nbytes_out_hi32 != NULL)
108371e7ee59SPeter Avalos       *nbytes_out_hi32 = bzf->strm.total_out_hi32;
108471e7ee59SPeter Avalos 
108571e7ee59SPeter Avalos    BZ_SETERR(BZ_OK);
108671e7ee59SPeter Avalos    BZ2_bzCompressEnd ( &(bzf->strm) );
108771e7ee59SPeter Avalos    free ( bzf );
108871e7ee59SPeter Avalos }
108971e7ee59SPeter Avalos 
109071e7ee59SPeter Avalos 
109171e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzReadOpen)109271e7ee59SPeter Avalos BZFILE* BZ_API(BZ2_bzReadOpen)
109371e7ee59SPeter Avalos                    ( int*  bzerror,
109471e7ee59SPeter Avalos                      FILE* f,
109571e7ee59SPeter Avalos                      int   verbosity,
109671e7ee59SPeter Avalos                      int   small,
109771e7ee59SPeter Avalos                      void* unused,
109871e7ee59SPeter Avalos                      int   nUnused )
109971e7ee59SPeter Avalos {
110071e7ee59SPeter Avalos    bzFile* bzf = NULL;
110171e7ee59SPeter Avalos    int     ret;
110271e7ee59SPeter Avalos 
110371e7ee59SPeter Avalos    BZ_SETERR(BZ_OK);
110471e7ee59SPeter Avalos 
110571e7ee59SPeter Avalos    if (f == NULL ||
110671e7ee59SPeter Avalos        (small != 0 && small != 1) ||
110771e7ee59SPeter Avalos        (verbosity < 0 || verbosity > 4) ||
110871e7ee59SPeter Avalos        (unused == NULL && nUnused != 0) ||
110971e7ee59SPeter Avalos        (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
111071e7ee59SPeter Avalos       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
111171e7ee59SPeter Avalos 
111271e7ee59SPeter Avalos    if (ferror(f))
111371e7ee59SPeter Avalos       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
111471e7ee59SPeter Avalos 
111571e7ee59SPeter Avalos    bzf = malloc ( sizeof(bzFile) );
111671e7ee59SPeter Avalos    if (bzf == NULL)
111771e7ee59SPeter Avalos       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
111871e7ee59SPeter Avalos 
111971e7ee59SPeter Avalos    BZ_SETERR(BZ_OK);
112071e7ee59SPeter Avalos 
112171e7ee59SPeter Avalos    bzf->initialisedOk = False;
112271e7ee59SPeter Avalos    bzf->handle        = f;
112371e7ee59SPeter Avalos    bzf->bufN          = 0;
112471e7ee59SPeter Avalos    bzf->writing       = False;
112571e7ee59SPeter Avalos    bzf->strm.bzalloc  = NULL;
112671e7ee59SPeter Avalos    bzf->strm.bzfree   = NULL;
112771e7ee59SPeter Avalos    bzf->strm.opaque   = NULL;
112871e7ee59SPeter Avalos 
112971e7ee59SPeter Avalos    while (nUnused > 0) {
113071e7ee59SPeter Avalos       bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
113171e7ee59SPeter Avalos       unused = ((void*)( 1 + ((UChar*)(unused))  ));
113271e7ee59SPeter Avalos       nUnused--;
113371e7ee59SPeter Avalos    }
113471e7ee59SPeter Avalos 
113571e7ee59SPeter Avalos    ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
113671e7ee59SPeter Avalos    if (ret != BZ_OK)
113771e7ee59SPeter Avalos       { BZ_SETERR(ret); free(bzf); return NULL; };
113871e7ee59SPeter Avalos 
113971e7ee59SPeter Avalos    bzf->strm.avail_in = bzf->bufN;
114071e7ee59SPeter Avalos    bzf->strm.next_in  = bzf->buf;
114171e7ee59SPeter Avalos 
114271e7ee59SPeter Avalos    bzf->initialisedOk = True;
114371e7ee59SPeter Avalos    return bzf;
114471e7ee59SPeter Avalos }
114571e7ee59SPeter Avalos 
114671e7ee59SPeter Avalos 
114771e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzReadClose)114871e7ee59SPeter Avalos void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
114971e7ee59SPeter Avalos {
115071e7ee59SPeter Avalos    bzFile* bzf = (bzFile*)b;
115171e7ee59SPeter Avalos 
115271e7ee59SPeter Avalos    BZ_SETERR(BZ_OK);
115371e7ee59SPeter Avalos    if (bzf == NULL)
115471e7ee59SPeter Avalos       { BZ_SETERR(BZ_OK); return; };
115571e7ee59SPeter Avalos 
115671e7ee59SPeter Avalos    if (bzf->writing)
115771e7ee59SPeter Avalos       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
115871e7ee59SPeter Avalos 
115971e7ee59SPeter Avalos    if (bzf->initialisedOk)
116071e7ee59SPeter Avalos       (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
116171e7ee59SPeter Avalos    free ( bzf );
116271e7ee59SPeter Avalos }
116371e7ee59SPeter Avalos 
116471e7ee59SPeter Avalos 
116571e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzRead)116671e7ee59SPeter Avalos int BZ_API(BZ2_bzRead)
116771e7ee59SPeter Avalos            ( int*    bzerror,
116871e7ee59SPeter Avalos              BZFILE* b,
116971e7ee59SPeter Avalos              void*   buf,
117071e7ee59SPeter Avalos              int     len )
117171e7ee59SPeter Avalos {
117271e7ee59SPeter Avalos    Int32   n, ret;
117371e7ee59SPeter Avalos    bzFile* bzf = (bzFile*)b;
117471e7ee59SPeter Avalos 
117571e7ee59SPeter Avalos    BZ_SETERR(BZ_OK);
117671e7ee59SPeter Avalos 
117771e7ee59SPeter Avalos    if (bzf == NULL || buf == NULL || len < 0)
117871e7ee59SPeter Avalos       { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
117971e7ee59SPeter Avalos 
118071e7ee59SPeter Avalos    if (bzf->writing)
118171e7ee59SPeter Avalos       { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
118271e7ee59SPeter Avalos 
118371e7ee59SPeter Avalos    if (len == 0)
118471e7ee59SPeter Avalos       { BZ_SETERR(BZ_OK); return 0; };
118571e7ee59SPeter Avalos 
118671e7ee59SPeter Avalos    bzf->strm.avail_out = len;
118771e7ee59SPeter Avalos    bzf->strm.next_out = buf;
118871e7ee59SPeter Avalos 
118971e7ee59SPeter Avalos    while (True) {
119071e7ee59SPeter Avalos 
119171e7ee59SPeter Avalos       if (ferror(bzf->handle))
119271e7ee59SPeter Avalos          { BZ_SETERR(BZ_IO_ERROR); return 0; };
119371e7ee59SPeter Avalos 
119471e7ee59SPeter Avalos       if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
119571e7ee59SPeter Avalos          n = fread ( bzf->buf, sizeof(UChar),
119671e7ee59SPeter Avalos                      BZ_MAX_UNUSED, bzf->handle );
119771e7ee59SPeter Avalos          if (ferror(bzf->handle))
119871e7ee59SPeter Avalos             { BZ_SETERR(BZ_IO_ERROR); return 0; };
119971e7ee59SPeter Avalos          bzf->bufN = n;
120071e7ee59SPeter Avalos          bzf->strm.avail_in = bzf->bufN;
120171e7ee59SPeter Avalos          bzf->strm.next_in = bzf->buf;
120271e7ee59SPeter Avalos       }
120371e7ee59SPeter Avalos 
120471e7ee59SPeter Avalos       ret = BZ2_bzDecompress ( &(bzf->strm) );
120571e7ee59SPeter Avalos 
120671e7ee59SPeter Avalos       if (ret != BZ_OK && ret != BZ_STREAM_END)
120771e7ee59SPeter Avalos          { BZ_SETERR(ret); return 0; };
120871e7ee59SPeter Avalos 
120971e7ee59SPeter Avalos       if (ret == BZ_OK && myfeof(bzf->handle) &&
121071e7ee59SPeter Avalos           bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
121171e7ee59SPeter Avalos          { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
121271e7ee59SPeter Avalos 
121371e7ee59SPeter Avalos       if (ret == BZ_STREAM_END)
121471e7ee59SPeter Avalos          { BZ_SETERR(BZ_STREAM_END);
121571e7ee59SPeter Avalos            return len - bzf->strm.avail_out; };
121671e7ee59SPeter Avalos       if (bzf->strm.avail_out == 0)
121771e7ee59SPeter Avalos          { BZ_SETERR(BZ_OK); return len; };
121871e7ee59SPeter Avalos 
121971e7ee59SPeter Avalos    }
122071e7ee59SPeter Avalos 
122171e7ee59SPeter Avalos    return 0; /*not reached*/
122271e7ee59SPeter Avalos }
122371e7ee59SPeter Avalos 
122471e7ee59SPeter Avalos 
122571e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzReadGetUnused)122671e7ee59SPeter Avalos void BZ_API(BZ2_bzReadGetUnused)
122771e7ee59SPeter Avalos                      ( int*    bzerror,
122871e7ee59SPeter Avalos                        BZFILE* b,
122971e7ee59SPeter Avalos                        void**  unused,
123071e7ee59SPeter Avalos                        int*    nUnused )
123171e7ee59SPeter Avalos {
123271e7ee59SPeter Avalos    bzFile* bzf = (bzFile*)b;
123371e7ee59SPeter Avalos    if (bzf == NULL)
123471e7ee59SPeter Avalos       { BZ_SETERR(BZ_PARAM_ERROR); return; };
123571e7ee59SPeter Avalos    if (bzf->lastErr != BZ_STREAM_END)
123671e7ee59SPeter Avalos       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
123771e7ee59SPeter Avalos    if (unused == NULL || nUnused == NULL)
123871e7ee59SPeter Avalos       { BZ_SETERR(BZ_PARAM_ERROR); return; };
123971e7ee59SPeter Avalos 
124071e7ee59SPeter Avalos    BZ_SETERR(BZ_OK);
124171e7ee59SPeter Avalos    *nUnused = bzf->strm.avail_in;
124271e7ee59SPeter Avalos    *unused = bzf->strm.next_in;
124371e7ee59SPeter Avalos }
124471e7ee59SPeter Avalos #endif
124571e7ee59SPeter Avalos 
124671e7ee59SPeter Avalos 
124771e7ee59SPeter Avalos /*---------------------------------------------------*/
124871e7ee59SPeter Avalos /*--- Misc convenience stuff                      ---*/
124971e7ee59SPeter Avalos /*---------------------------------------------------*/
125071e7ee59SPeter Avalos 
125171e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzBuffToBuffCompress)125271e7ee59SPeter Avalos int BZ_API(BZ2_bzBuffToBuffCompress)
125371e7ee59SPeter Avalos                          ( char*         dest,
125471e7ee59SPeter Avalos                            unsigned int* destLen,
125571e7ee59SPeter Avalos                            char*         source,
125671e7ee59SPeter Avalos                            unsigned int  sourceLen,
125771e7ee59SPeter Avalos                            int           blockSize100k,
125871e7ee59SPeter Avalos                            int           verbosity,
125971e7ee59SPeter Avalos                            int           workFactor )
126071e7ee59SPeter Avalos {
126171e7ee59SPeter Avalos    bz_stream strm;
126271e7ee59SPeter Avalos    int ret;
126371e7ee59SPeter Avalos 
126471e7ee59SPeter Avalos    if (dest == NULL || destLen == NULL ||
126571e7ee59SPeter Avalos        source == NULL ||
126671e7ee59SPeter Avalos        blockSize100k < 1 || blockSize100k > 9 ||
126771e7ee59SPeter Avalos        verbosity < 0 || verbosity > 4 ||
126871e7ee59SPeter Avalos        workFactor < 0 || workFactor > 250)
126971e7ee59SPeter Avalos       return BZ_PARAM_ERROR;
127071e7ee59SPeter Avalos 
127171e7ee59SPeter Avalos    if (workFactor == 0) workFactor = 30;
127271e7ee59SPeter Avalos    strm.bzalloc = NULL;
127371e7ee59SPeter Avalos    strm.bzfree = NULL;
127471e7ee59SPeter Avalos    strm.opaque = NULL;
127571e7ee59SPeter Avalos    ret = BZ2_bzCompressInit ( &strm, blockSize100k,
127671e7ee59SPeter Avalos                               verbosity, workFactor );
127771e7ee59SPeter Avalos    if (ret != BZ_OK) return ret;
127871e7ee59SPeter Avalos 
127971e7ee59SPeter Avalos    strm.next_in = source;
128071e7ee59SPeter Avalos    strm.next_out = dest;
128171e7ee59SPeter Avalos    strm.avail_in = sourceLen;
128271e7ee59SPeter Avalos    strm.avail_out = *destLen;
128371e7ee59SPeter Avalos 
128471e7ee59SPeter Avalos    ret = BZ2_bzCompress ( &strm, BZ_FINISH );
128571e7ee59SPeter Avalos    if (ret == BZ_FINISH_OK) goto output_overflow;
128671e7ee59SPeter Avalos    if (ret != BZ_STREAM_END) goto errhandler;
128771e7ee59SPeter Avalos 
128871e7ee59SPeter Avalos    /* normal termination */
128971e7ee59SPeter Avalos    *destLen -= strm.avail_out;
129071e7ee59SPeter Avalos    BZ2_bzCompressEnd ( &strm );
129171e7ee59SPeter Avalos    return BZ_OK;
129271e7ee59SPeter Avalos 
129371e7ee59SPeter Avalos    output_overflow:
129471e7ee59SPeter Avalos    BZ2_bzCompressEnd ( &strm );
129571e7ee59SPeter Avalos    return BZ_OUTBUFF_FULL;
129671e7ee59SPeter Avalos 
129771e7ee59SPeter Avalos    errhandler:
129871e7ee59SPeter Avalos    BZ2_bzCompressEnd ( &strm );
129971e7ee59SPeter Avalos    return ret;
130071e7ee59SPeter Avalos }
130171e7ee59SPeter Avalos 
130271e7ee59SPeter Avalos 
130371e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzBuffToBuffDecompress)130471e7ee59SPeter Avalos int BZ_API(BZ2_bzBuffToBuffDecompress)
130571e7ee59SPeter Avalos                            ( char*         dest,
130671e7ee59SPeter Avalos                              unsigned int* destLen,
130771e7ee59SPeter Avalos                              char*         source,
130871e7ee59SPeter Avalos                              unsigned int  sourceLen,
130971e7ee59SPeter Avalos                              int           small,
131071e7ee59SPeter Avalos                              int           verbosity )
131171e7ee59SPeter Avalos {
131271e7ee59SPeter Avalos    bz_stream strm;
131371e7ee59SPeter Avalos    int ret;
131471e7ee59SPeter Avalos 
131571e7ee59SPeter Avalos    if (dest == NULL || destLen == NULL ||
131671e7ee59SPeter Avalos        source == NULL ||
131771e7ee59SPeter Avalos        (small != 0 && small != 1) ||
131871e7ee59SPeter Avalos        verbosity < 0 || verbosity > 4)
131971e7ee59SPeter Avalos           return BZ_PARAM_ERROR;
132071e7ee59SPeter Avalos 
132171e7ee59SPeter Avalos    strm.bzalloc = NULL;
132271e7ee59SPeter Avalos    strm.bzfree = NULL;
132371e7ee59SPeter Avalos    strm.opaque = NULL;
132471e7ee59SPeter Avalos    ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
132571e7ee59SPeter Avalos    if (ret != BZ_OK) return ret;
132671e7ee59SPeter Avalos 
132771e7ee59SPeter Avalos    strm.next_in = source;
132871e7ee59SPeter Avalos    strm.next_out = dest;
132971e7ee59SPeter Avalos    strm.avail_in = sourceLen;
133071e7ee59SPeter Avalos    strm.avail_out = *destLen;
133171e7ee59SPeter Avalos 
133271e7ee59SPeter Avalos    ret = BZ2_bzDecompress ( &strm );
133371e7ee59SPeter Avalos    if (ret == BZ_OK) goto output_overflow_or_eof;
133471e7ee59SPeter Avalos    if (ret != BZ_STREAM_END) goto errhandler;
133571e7ee59SPeter Avalos 
133671e7ee59SPeter Avalos    /* normal termination */
133771e7ee59SPeter Avalos    *destLen -= strm.avail_out;
133871e7ee59SPeter Avalos    BZ2_bzDecompressEnd ( &strm );
133971e7ee59SPeter Avalos    return BZ_OK;
134071e7ee59SPeter Avalos 
134171e7ee59SPeter Avalos    output_overflow_or_eof:
134271e7ee59SPeter Avalos    if (strm.avail_out > 0) {
134371e7ee59SPeter Avalos       BZ2_bzDecompressEnd ( &strm );
134471e7ee59SPeter Avalos       return BZ_UNEXPECTED_EOF;
134571e7ee59SPeter Avalos    } else {
134671e7ee59SPeter Avalos       BZ2_bzDecompressEnd ( &strm );
134771e7ee59SPeter Avalos       return BZ_OUTBUFF_FULL;
134871e7ee59SPeter Avalos    };
134971e7ee59SPeter Avalos 
135071e7ee59SPeter Avalos    errhandler:
135171e7ee59SPeter Avalos    BZ2_bzDecompressEnd ( &strm );
135271e7ee59SPeter Avalos    return ret;
135371e7ee59SPeter Avalos }
135471e7ee59SPeter Avalos 
135571e7ee59SPeter Avalos 
135671e7ee59SPeter Avalos /*---------------------------------------------------*/
135771e7ee59SPeter Avalos /*--
135871e7ee59SPeter Avalos    Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
135971e7ee59SPeter Avalos    to support better zlib compatibility.
136071e7ee59SPeter Avalos    This code is not _officially_ part of libbzip2 (yet);
136171e7ee59SPeter Avalos    I haven't tested it, documented it, or considered the
136271e7ee59SPeter Avalos    threading-safeness of it.
136371e7ee59SPeter Avalos    If this code breaks, please contact both Yoshioka and me.
136471e7ee59SPeter Avalos --*/
136571e7ee59SPeter Avalos /*---------------------------------------------------*/
136671e7ee59SPeter Avalos 
136771e7ee59SPeter Avalos /*---------------------------------------------------*/
136871e7ee59SPeter Avalos /*--
136971e7ee59SPeter Avalos    return version like "0.9.5d, 4-Sept-1999".
137071e7ee59SPeter Avalos --*/
BZ_API(BZ2_bzlibVersion)137171e7ee59SPeter Avalos const char * BZ_API(BZ2_bzlibVersion)(void)
137271e7ee59SPeter Avalos {
137371e7ee59SPeter Avalos    return BZ_VERSION;
137471e7ee59SPeter Avalos }
137571e7ee59SPeter Avalos 
137671e7ee59SPeter Avalos 
137771e7ee59SPeter Avalos #ifndef BZ_NO_STDIO
137871e7ee59SPeter Avalos /*---------------------------------------------------*/
137971e7ee59SPeter Avalos 
138071e7ee59SPeter Avalos #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
138171e7ee59SPeter Avalos #   include <fcntl.h>
138271e7ee59SPeter Avalos #   include <io.h>
138371e7ee59SPeter Avalos #   define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
138471e7ee59SPeter Avalos #else
138571e7ee59SPeter Avalos #   define SET_BINARY_MODE(file)
138671e7ee59SPeter Avalos #endif
138771e7ee59SPeter Avalos static
bzopen_or_bzdopen(const char * path,int fd,const char * mode,int open_mode)138871e7ee59SPeter Avalos BZFILE * bzopen_or_bzdopen
138971e7ee59SPeter Avalos                ( const char *path,   /* no use when bzdopen */
139071e7ee59SPeter Avalos                  int fd,             /* no use when bzdopen */
139171e7ee59SPeter Avalos                  const char *mode,
139271e7ee59SPeter Avalos                  int open_mode)      /* bzopen: 0, bzdopen:1 */
139371e7ee59SPeter Avalos {
139471e7ee59SPeter Avalos    int    bzerr;
139571e7ee59SPeter Avalos    char   unused[BZ_MAX_UNUSED];
139671e7ee59SPeter Avalos    int    blockSize100k = 9;
139771e7ee59SPeter Avalos    int    writing       = 0;
139871e7ee59SPeter Avalos    char   mode2[10]     = "";
139971e7ee59SPeter Avalos    FILE   *fp           = NULL;
140071e7ee59SPeter Avalos    BZFILE *bzfp         = NULL;
140171e7ee59SPeter Avalos    int    verbosity     = 0;
140271e7ee59SPeter Avalos    int    workFactor    = 30;
140371e7ee59SPeter Avalos    int    smallMode     = 0;
140471e7ee59SPeter Avalos    int    nUnused       = 0;
140571e7ee59SPeter Avalos 
140671e7ee59SPeter Avalos    if (mode == NULL) return NULL;
140771e7ee59SPeter Avalos    while (*mode) {
140871e7ee59SPeter Avalos       switch (*mode) {
140971e7ee59SPeter Avalos       case 'r':
141071e7ee59SPeter Avalos          writing = 0; break;
141171e7ee59SPeter Avalos       case 'w':
141271e7ee59SPeter Avalos          writing = 1; break;
141371e7ee59SPeter Avalos       case 's':
141471e7ee59SPeter Avalos          smallMode = 1; break;
141571e7ee59SPeter Avalos       default:
141671e7ee59SPeter Avalos          if (isdigit((int)(*mode))) {
141771e7ee59SPeter Avalos             blockSize100k = *mode-BZ_HDR_0;
141871e7ee59SPeter Avalos          }
141971e7ee59SPeter Avalos       }
142071e7ee59SPeter Avalos       mode++;
142171e7ee59SPeter Avalos    }
142271e7ee59SPeter Avalos    strcat(mode2, writing ? "w" : "r" );
142371e7ee59SPeter Avalos    strcat(mode2,"b");   /* binary mode */
142471e7ee59SPeter Avalos 
142571e7ee59SPeter Avalos    if (open_mode==0) {
142671e7ee59SPeter Avalos       if (path==NULL || strcmp(path,"")==0) {
142771e7ee59SPeter Avalos         fp = (writing ? stdout : stdin);
142871e7ee59SPeter Avalos         SET_BINARY_MODE(fp);
142971e7ee59SPeter Avalos       } else {
143071e7ee59SPeter Avalos         fp = fopen(path,mode2);
143171e7ee59SPeter Avalos       }
143271e7ee59SPeter Avalos    } else {
143371e7ee59SPeter Avalos #ifdef BZ_STRICT_ANSI
143471e7ee59SPeter Avalos       fp = NULL;
143571e7ee59SPeter Avalos #else
143671e7ee59SPeter Avalos       fp = fdopen(fd,mode2);
143771e7ee59SPeter Avalos #endif
143871e7ee59SPeter Avalos    }
143971e7ee59SPeter Avalos    if (fp == NULL) return NULL;
144071e7ee59SPeter Avalos 
144171e7ee59SPeter Avalos    if (writing) {
144271e7ee59SPeter Avalos       /* Guard against total chaos and anarchy -- JRS */
144371e7ee59SPeter Avalos       if (blockSize100k < 1) blockSize100k = 1;
144471e7ee59SPeter Avalos       if (blockSize100k > 9) blockSize100k = 9;
144571e7ee59SPeter Avalos       bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
144671e7ee59SPeter Avalos                              verbosity,workFactor);
144771e7ee59SPeter Avalos    } else {
144871e7ee59SPeter Avalos       bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
144971e7ee59SPeter Avalos                             unused,nUnused);
145071e7ee59SPeter Avalos    }
145171e7ee59SPeter Avalos    if (bzfp == NULL) {
145271e7ee59SPeter Avalos       if (fp != stdin && fp != stdout) fclose(fp);
145371e7ee59SPeter Avalos       return NULL;
145471e7ee59SPeter Avalos    }
145571e7ee59SPeter Avalos    return bzfp;
145671e7ee59SPeter Avalos }
145771e7ee59SPeter Avalos 
145871e7ee59SPeter Avalos 
145971e7ee59SPeter Avalos /*---------------------------------------------------*/
146071e7ee59SPeter Avalos /*--
146171e7ee59SPeter Avalos    open file for read or write.
146271e7ee59SPeter Avalos       ex) bzopen("file","w9")
146371e7ee59SPeter Avalos       case path="" or NULL => use stdin or stdout.
146471e7ee59SPeter Avalos --*/
BZ_API(BZ2_bzopen)146571e7ee59SPeter Avalos BZFILE * BZ_API(BZ2_bzopen)
146671e7ee59SPeter Avalos                ( const char *path,
146771e7ee59SPeter Avalos                  const char *mode )
146871e7ee59SPeter Avalos {
146971e7ee59SPeter Avalos    return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
147071e7ee59SPeter Avalos }
147171e7ee59SPeter Avalos 
147271e7ee59SPeter Avalos 
147371e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzdopen)147471e7ee59SPeter Avalos BZFILE * BZ_API(BZ2_bzdopen)
147571e7ee59SPeter Avalos                ( int fd,
147671e7ee59SPeter Avalos                  const char *mode )
147771e7ee59SPeter Avalos {
147871e7ee59SPeter Avalos    return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
147971e7ee59SPeter Avalos }
148071e7ee59SPeter Avalos 
148171e7ee59SPeter Avalos 
148271e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzread)148371e7ee59SPeter Avalos int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
148471e7ee59SPeter Avalos {
148571e7ee59SPeter Avalos    int bzerr, nread;
148671e7ee59SPeter Avalos    if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
148771e7ee59SPeter Avalos    nread = BZ2_bzRead(&bzerr,b,buf,len);
148871e7ee59SPeter Avalos    if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
148971e7ee59SPeter Avalos       return nread;
149071e7ee59SPeter Avalos    } else {
149171e7ee59SPeter Avalos       return -1;
149271e7ee59SPeter Avalos    }
149371e7ee59SPeter Avalos }
149471e7ee59SPeter Avalos 
149571e7ee59SPeter Avalos 
149671e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzwrite)149771e7ee59SPeter Avalos int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
149871e7ee59SPeter Avalos {
149971e7ee59SPeter Avalos    int bzerr;
150071e7ee59SPeter Avalos 
150171e7ee59SPeter Avalos    BZ2_bzWrite(&bzerr,b,buf,len);
150271e7ee59SPeter Avalos    if(bzerr == BZ_OK){
150371e7ee59SPeter Avalos       return len;
150471e7ee59SPeter Avalos    }else{
150571e7ee59SPeter Avalos       return -1;
150671e7ee59SPeter Avalos    }
150771e7ee59SPeter Avalos }
150871e7ee59SPeter Avalos 
150971e7ee59SPeter Avalos 
151071e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzflush)151171e7ee59SPeter Avalos int BZ_API(BZ2_bzflush) (BZFILE *b)
151271e7ee59SPeter Avalos {
151371e7ee59SPeter Avalos    /* do nothing now... */
151471e7ee59SPeter Avalos    return 0;
151571e7ee59SPeter Avalos }
151671e7ee59SPeter Avalos 
151771e7ee59SPeter Avalos 
151871e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ_API(BZ2_bzclose)151971e7ee59SPeter Avalos void BZ_API(BZ2_bzclose) (BZFILE* b)
152071e7ee59SPeter Avalos {
152171e7ee59SPeter Avalos    int bzerr;
152271e7ee59SPeter Avalos    FILE *fp;
152371e7ee59SPeter Avalos 
152471e7ee59SPeter Avalos    if (b==NULL) {return;}
152571e7ee59SPeter Avalos    fp = ((bzFile *)b)->handle;
152671e7ee59SPeter Avalos    if(((bzFile*)b)->writing){
152771e7ee59SPeter Avalos       BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
152871e7ee59SPeter Avalos       if(bzerr != BZ_OK){
152971e7ee59SPeter Avalos          BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
153071e7ee59SPeter Avalos       }
153171e7ee59SPeter Avalos    }else{
153271e7ee59SPeter Avalos       BZ2_bzReadClose(&bzerr,b);
153371e7ee59SPeter Avalos    }
153471e7ee59SPeter Avalos    if(fp!=stdin && fp!=stdout){
153571e7ee59SPeter Avalos       fclose(fp);
153671e7ee59SPeter Avalos    }
153771e7ee59SPeter Avalos }
153871e7ee59SPeter Avalos 
153971e7ee59SPeter Avalos 
154071e7ee59SPeter Avalos /*---------------------------------------------------*/
154171e7ee59SPeter Avalos /*--
154271e7ee59SPeter Avalos    return last error code
154371e7ee59SPeter Avalos --*/
154471e7ee59SPeter Avalos static const char *bzerrorstrings[] = {
154571e7ee59SPeter Avalos        "OK"
154671e7ee59SPeter Avalos       ,"SEQUENCE_ERROR"
154771e7ee59SPeter Avalos       ,"PARAM_ERROR"
154871e7ee59SPeter Avalos       ,"MEM_ERROR"
154971e7ee59SPeter Avalos       ,"DATA_ERROR"
155071e7ee59SPeter Avalos       ,"DATA_ERROR_MAGIC"
155171e7ee59SPeter Avalos       ,"IO_ERROR"
155271e7ee59SPeter Avalos       ,"UNEXPECTED_EOF"
155371e7ee59SPeter Avalos       ,"OUTBUFF_FULL"
155471e7ee59SPeter Avalos       ,"CONFIG_ERROR"
155571e7ee59SPeter Avalos       ,"???"   /* for future */
155671e7ee59SPeter Avalos       ,"???"   /* for future */
155771e7ee59SPeter Avalos       ,"???"   /* for future */
155871e7ee59SPeter Avalos       ,"???"   /* for future */
155971e7ee59SPeter Avalos       ,"???"   /* for future */
156071e7ee59SPeter Avalos       ,"???"   /* for future */
156171e7ee59SPeter Avalos };
156271e7ee59SPeter Avalos 
156371e7ee59SPeter Avalos 
BZ_API(BZ2_bzerror)156471e7ee59SPeter Avalos const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
156571e7ee59SPeter Avalos {
156671e7ee59SPeter Avalos    int err = ((bzFile *)b)->lastErr;
156771e7ee59SPeter Avalos 
156871e7ee59SPeter Avalos    if(err>0) err = 0;
156971e7ee59SPeter Avalos    *errnum = err;
157071e7ee59SPeter Avalos    return bzerrorstrings[err*-1];
157171e7ee59SPeter Avalos }
157271e7ee59SPeter Avalos #endif
157371e7ee59SPeter Avalos 
1574*d8d77baaSSascha Wildner #endif /* BZ_NO_COMPRESS */
157571e7ee59SPeter Avalos 
157671e7ee59SPeter Avalos /*-------------------------------------------------------------*/
157771e7ee59SPeter Avalos /*--- end                                           bzlib.c ---*/
157871e7ee59SPeter Avalos /*-------------------------------------------------------------*/
1579