xref: /plan9/sys/src/cmd/bzip2/lib/bzcompress.c (revision 59cc4ca53493a3c6d2349fe2b7f7c40f7dce7294)
1*59cc4ca5SDavid du Colombier /*
2*59cc4ca5SDavid du Colombier  * THIS FILE IS NOT IDENTICAL TO THE ORIGINAL
3*59cc4ca5SDavid du Colombier  * FROM THE BZIP2 DISTRIBUTION.
4*59cc4ca5SDavid du Colombier  *
5*59cc4ca5SDavid du Colombier  * It has been modified, mainly to break the library
6*59cc4ca5SDavid du Colombier  * into smaller pieces.
7*59cc4ca5SDavid du Colombier  *
8*59cc4ca5SDavid du Colombier  * Russ Cox
9*59cc4ca5SDavid du Colombier  * rsc@plan9.bell-labs.com
10*59cc4ca5SDavid du Colombier  * July 2000
11*59cc4ca5SDavid du Colombier  */
12*59cc4ca5SDavid du Colombier 
13*59cc4ca5SDavid du Colombier /*-------------------------------------------------------------*/
14*59cc4ca5SDavid du Colombier /*--- Library top-level functions.                          ---*/
15*59cc4ca5SDavid du Colombier /*---                                               bzlib.c ---*/
16*59cc4ca5SDavid du Colombier /*-------------------------------------------------------------*/
17*59cc4ca5SDavid du Colombier 
18*59cc4ca5SDavid du Colombier /*--
19*59cc4ca5SDavid du Colombier   This file is a part of bzip2 and/or libbzip2, a program and
20*59cc4ca5SDavid du Colombier   library for lossless, block-sorting data compression.
21*59cc4ca5SDavid du Colombier 
22*59cc4ca5SDavid du Colombier   Copyright (C) 1996-2000 Julian R Seward.  All rights reserved.
23*59cc4ca5SDavid du Colombier 
24*59cc4ca5SDavid du Colombier   Redistribution and use in source and binary forms, with or without
25*59cc4ca5SDavid du Colombier   modification, are permitted provided that the following conditions
26*59cc4ca5SDavid du Colombier   are met:
27*59cc4ca5SDavid du Colombier 
28*59cc4ca5SDavid du Colombier   1. Redistributions of source code must retain the above copyright
29*59cc4ca5SDavid du Colombier      notice, this list of conditions and the following disclaimer.
30*59cc4ca5SDavid du Colombier 
31*59cc4ca5SDavid du Colombier   2. The origin of this software must not be misrepresented; you must
32*59cc4ca5SDavid du Colombier      not claim that you wrote the original software.  If you use this
33*59cc4ca5SDavid du Colombier      software in a product, an acknowledgment in the product
34*59cc4ca5SDavid du Colombier      documentation would be appreciated but is not required.
35*59cc4ca5SDavid du Colombier 
36*59cc4ca5SDavid du Colombier   3. Altered source versions must be plainly marked as such, and must
37*59cc4ca5SDavid du Colombier      not be misrepresented as being the original software.
38*59cc4ca5SDavid du Colombier 
39*59cc4ca5SDavid du Colombier   4. The name of the author may not be used to endorse or promote
40*59cc4ca5SDavid du Colombier      products derived from this software without specific prior written
41*59cc4ca5SDavid du Colombier      permission.
42*59cc4ca5SDavid du Colombier 
43*59cc4ca5SDavid du Colombier   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
44*59cc4ca5SDavid du Colombier   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45*59cc4ca5SDavid du Colombier   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46*59cc4ca5SDavid du Colombier   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
47*59cc4ca5SDavid du Colombier   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48*59cc4ca5SDavid du Colombier   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
49*59cc4ca5SDavid du Colombier   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
50*59cc4ca5SDavid du Colombier   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51*59cc4ca5SDavid du Colombier   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
52*59cc4ca5SDavid du Colombier   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
53*59cc4ca5SDavid du Colombier   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54*59cc4ca5SDavid du Colombier 
55*59cc4ca5SDavid du Colombier   Julian Seward, Cambridge, UK.
56*59cc4ca5SDavid du Colombier   jseward@acm.org
57*59cc4ca5SDavid du Colombier   bzip2/libbzip2 version 1.0 of 21 March 2000
58*59cc4ca5SDavid du Colombier 
59*59cc4ca5SDavid du Colombier   This program is based on (at least) the work of:
60*59cc4ca5SDavid du Colombier      Mike Burrows
61*59cc4ca5SDavid du Colombier      David Wheeler
62*59cc4ca5SDavid du Colombier      Peter Fenwick
63*59cc4ca5SDavid du Colombier      Alistair Moffat
64*59cc4ca5SDavid du Colombier      Radford Neal
65*59cc4ca5SDavid du Colombier      Ian H. Witten
66*59cc4ca5SDavid du Colombier      Robert Sedgewick
67*59cc4ca5SDavid du Colombier      Jon L. Bentley
68*59cc4ca5SDavid du Colombier 
69*59cc4ca5SDavid du Colombier   For more information on these sources, see the manual.
70*59cc4ca5SDavid du Colombier --*/
71*59cc4ca5SDavid du Colombier 
72*59cc4ca5SDavid du Colombier /*--
73*59cc4ca5SDavid du Colombier    CHANGES
74*59cc4ca5SDavid du Colombier    ~~~~~~~
75*59cc4ca5SDavid du Colombier    0.9.0 -- original version.
76*59cc4ca5SDavid du Colombier 
77*59cc4ca5SDavid du Colombier    0.9.0a/b -- no changes in this file.
78*59cc4ca5SDavid du Colombier 
79*59cc4ca5SDavid du Colombier    0.9.0c
80*59cc4ca5SDavid du Colombier       * made zero-length BZ_FLUSH work correctly in bzCompress().
81*59cc4ca5SDavid du Colombier       * fixed bzWrite/bzRead to ignore zero-length requests.
82*59cc4ca5SDavid du Colombier       * fixed bzread to correctly handle read requests after EOF.
83*59cc4ca5SDavid du Colombier       * wrong parameter order in call to bzDecompressInit in
84*59cc4ca5SDavid du Colombier         bzBuffToBuffDecompress.  Fixed.
85*59cc4ca5SDavid du Colombier --*/
86*59cc4ca5SDavid du Colombier 
87*59cc4ca5SDavid du Colombier #include "os.h"
88*59cc4ca5SDavid du Colombier #include "bzlib.h"
89*59cc4ca5SDavid du Colombier #include "bzlib_private.h"
90*59cc4ca5SDavid du Colombier 
91*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
92*59cc4ca5SDavid du Colombier /*--- Compression stuff                           ---*/
93*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
94*59cc4ca5SDavid du Colombier 
95*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
96*59cc4ca5SDavid du Colombier static
prepare_new_block(EState * s)97*59cc4ca5SDavid du Colombier void prepare_new_block ( EState* s )
98*59cc4ca5SDavid du Colombier {
99*59cc4ca5SDavid du Colombier    Int32 i;
100*59cc4ca5SDavid du Colombier    s->nblock = 0;
101*59cc4ca5SDavid du Colombier    s->numZ = 0;
102*59cc4ca5SDavid du Colombier    s->state_out_pos = 0;
103*59cc4ca5SDavid du Colombier    BZ_INITIALISE_CRC ( s->blockCRC );
104*59cc4ca5SDavid du Colombier    for (i = 0; i < 256; i++) s->inUse[i] = False;
105*59cc4ca5SDavid du Colombier    s->blockNo++;
106*59cc4ca5SDavid du Colombier }
107*59cc4ca5SDavid du Colombier 
108*59cc4ca5SDavid du Colombier 
109*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
110*59cc4ca5SDavid du Colombier static
init_RL(EState * s)111*59cc4ca5SDavid du Colombier void init_RL ( EState* s )
112*59cc4ca5SDavid du Colombier {
113*59cc4ca5SDavid du Colombier    s->state_in_ch  = 256;
114*59cc4ca5SDavid du Colombier    s->state_in_len = 0;
115*59cc4ca5SDavid du Colombier }
116*59cc4ca5SDavid du Colombier 
117*59cc4ca5SDavid du Colombier 
118*59cc4ca5SDavid du Colombier static
isempty_RL(EState * s)119*59cc4ca5SDavid du Colombier Bool isempty_RL ( EState* s )
120*59cc4ca5SDavid du Colombier {
121*59cc4ca5SDavid du Colombier    if (s->state_in_ch < 256 && s->state_in_len > 0)
122*59cc4ca5SDavid du Colombier       return False; else
123*59cc4ca5SDavid du Colombier       return True;
124*59cc4ca5SDavid du Colombier }
125*59cc4ca5SDavid du Colombier 
126*59cc4ca5SDavid du Colombier 
127*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzCompressInit)128*59cc4ca5SDavid du Colombier int BZ_API(BZ2_bzCompressInit)
129*59cc4ca5SDavid du Colombier                     ( bz_stream* strm,
130*59cc4ca5SDavid du Colombier                      int        blockSize100k,
131*59cc4ca5SDavid du Colombier                      int        verbosity,
132*59cc4ca5SDavid du Colombier                      int        workFactor )
133*59cc4ca5SDavid du Colombier {
134*59cc4ca5SDavid du Colombier    Int32   n;
135*59cc4ca5SDavid du Colombier    EState* s;
136*59cc4ca5SDavid du Colombier 
137*59cc4ca5SDavid du Colombier    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
138*59cc4ca5SDavid du Colombier 
139*59cc4ca5SDavid du Colombier    if (strm == NULL ||
140*59cc4ca5SDavid du Colombier        blockSize100k < 1 || blockSize100k > 9 ||
141*59cc4ca5SDavid du Colombier        workFactor < 0 || workFactor > 250)
142*59cc4ca5SDavid du Colombier      return BZ_PARAM_ERROR;
143*59cc4ca5SDavid du Colombier 
144*59cc4ca5SDavid du Colombier    if (workFactor == 0) workFactor = 30;
145*59cc4ca5SDavid du Colombier    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
146*59cc4ca5SDavid du Colombier    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
147*59cc4ca5SDavid du Colombier 
148*59cc4ca5SDavid du Colombier    s = BZALLOC( sizeof(EState) );
149*59cc4ca5SDavid du Colombier    if (s == NULL) return BZ_MEM_ERROR;
150*59cc4ca5SDavid du Colombier    s->strm = strm;
151*59cc4ca5SDavid du Colombier 
152*59cc4ca5SDavid du Colombier    s->arr1 = NULL;
153*59cc4ca5SDavid du Colombier    s->arr2 = NULL;
154*59cc4ca5SDavid du Colombier    s->ftab = NULL;
155*59cc4ca5SDavid du Colombier 
156*59cc4ca5SDavid du Colombier    n       = 100000 * blockSize100k;
157*59cc4ca5SDavid du Colombier    s->arr1 = BZALLOC( n                  * sizeof(UInt32) );
158*59cc4ca5SDavid du Colombier    s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
159*59cc4ca5SDavid du Colombier    s->ftab = BZALLOC( 65537              * sizeof(UInt32) );
160*59cc4ca5SDavid du Colombier 
161*59cc4ca5SDavid du Colombier    if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
162*59cc4ca5SDavid du Colombier       if (s->arr1 != NULL) BZFREE(s->arr1);
163*59cc4ca5SDavid du Colombier       if (s->arr2 != NULL) BZFREE(s->arr2);
164*59cc4ca5SDavid du Colombier       if (s->ftab != NULL) BZFREE(s->ftab);
165*59cc4ca5SDavid du Colombier       if (s       != NULL) BZFREE(s);
166*59cc4ca5SDavid du Colombier       return BZ_MEM_ERROR;
167*59cc4ca5SDavid du Colombier    }
168*59cc4ca5SDavid du Colombier 
169*59cc4ca5SDavid du Colombier    s->blockNo           = 0;
170*59cc4ca5SDavid du Colombier    s->state             = BZ_S_INPUT;
171*59cc4ca5SDavid du Colombier    s->mode              = BZ_M_RUNNING;
172*59cc4ca5SDavid du Colombier    s->combinedCRC       = 0;
173*59cc4ca5SDavid du Colombier    s->blockSize100k     = blockSize100k;
174*59cc4ca5SDavid du Colombier    s->nblockMAX         = 100000 * blockSize100k - 19;
175*59cc4ca5SDavid du Colombier    s->verbosity         = verbosity;
176*59cc4ca5SDavid du Colombier    s->workFactor        = workFactor;
177*59cc4ca5SDavid du Colombier 
178*59cc4ca5SDavid du Colombier    s->block             = (UChar*)s->arr2;
179*59cc4ca5SDavid du Colombier    s->mtfv              = (UInt16*)s->arr1;
180*59cc4ca5SDavid du Colombier    s->zbits             = NULL;
181*59cc4ca5SDavid du Colombier    s->ptr               = (UInt32*)s->arr1;
182*59cc4ca5SDavid du Colombier 
183*59cc4ca5SDavid du Colombier    strm->state          = s;
184*59cc4ca5SDavid du Colombier    strm->total_in_lo32  = 0;
185*59cc4ca5SDavid du Colombier    strm->total_in_hi32  = 0;
186*59cc4ca5SDavid du Colombier    strm->total_out_lo32 = 0;
187*59cc4ca5SDavid du Colombier    strm->total_out_hi32 = 0;
188*59cc4ca5SDavid du Colombier    init_RL ( s );
189*59cc4ca5SDavid du Colombier    prepare_new_block ( s );
190*59cc4ca5SDavid du Colombier    return BZ_OK;
191*59cc4ca5SDavid du Colombier }
192*59cc4ca5SDavid du Colombier 
193*59cc4ca5SDavid du Colombier 
194*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
195*59cc4ca5SDavid du Colombier static
add_pair_to_block(EState * s)196*59cc4ca5SDavid du Colombier void add_pair_to_block ( EState* s )
197*59cc4ca5SDavid du Colombier {
198*59cc4ca5SDavid du Colombier    Int32 i;
199*59cc4ca5SDavid du Colombier    UChar ch = (UChar)(s->state_in_ch);
200*59cc4ca5SDavid du Colombier    for (i = 0; i < s->state_in_len; i++) {
201*59cc4ca5SDavid du Colombier       BZ_UPDATE_CRC( s->blockCRC, ch );
202*59cc4ca5SDavid du Colombier    }
203*59cc4ca5SDavid du Colombier    s->inUse[s->state_in_ch] = True;
204*59cc4ca5SDavid du Colombier    switch (s->state_in_len) {
205*59cc4ca5SDavid du Colombier       case 1:
206*59cc4ca5SDavid du Colombier          s->block[s->nblock] = (UChar)ch; s->nblock++;
207*59cc4ca5SDavid du Colombier          break;
208*59cc4ca5SDavid du Colombier       case 2:
209*59cc4ca5SDavid du Colombier          s->block[s->nblock] = (UChar)ch; s->nblock++;
210*59cc4ca5SDavid du Colombier          s->block[s->nblock] = (UChar)ch; s->nblock++;
211*59cc4ca5SDavid du Colombier          break;
212*59cc4ca5SDavid du Colombier       case 3:
213*59cc4ca5SDavid du Colombier          s->block[s->nblock] = (UChar)ch; s->nblock++;
214*59cc4ca5SDavid du Colombier          s->block[s->nblock] = (UChar)ch; s->nblock++;
215*59cc4ca5SDavid du Colombier          s->block[s->nblock] = (UChar)ch; s->nblock++;
216*59cc4ca5SDavid du Colombier          break;
217*59cc4ca5SDavid du Colombier       default:
218*59cc4ca5SDavid du Colombier          s->inUse[s->state_in_len-4] = True;
219*59cc4ca5SDavid du Colombier          s->block[s->nblock] = (UChar)ch; s->nblock++;
220*59cc4ca5SDavid du Colombier          s->block[s->nblock] = (UChar)ch; s->nblock++;
221*59cc4ca5SDavid du Colombier          s->block[s->nblock] = (UChar)ch; s->nblock++;
222*59cc4ca5SDavid du Colombier          s->block[s->nblock] = (UChar)ch; s->nblock++;
223*59cc4ca5SDavid du Colombier          s->block[s->nblock] = ((UChar)(s->state_in_len-4));
224*59cc4ca5SDavid du Colombier          s->nblock++;
225*59cc4ca5SDavid du Colombier          break;
226*59cc4ca5SDavid du Colombier    }
227*59cc4ca5SDavid du Colombier }
228*59cc4ca5SDavid du Colombier 
229*59cc4ca5SDavid du Colombier 
230*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
231*59cc4ca5SDavid du Colombier static
flush_RL(EState * s)232*59cc4ca5SDavid du Colombier void flush_RL ( EState* s )
233*59cc4ca5SDavid du Colombier {
234*59cc4ca5SDavid du Colombier    if (s->state_in_ch < 256) add_pair_to_block ( s );
235*59cc4ca5SDavid du Colombier    init_RL ( s );
236*59cc4ca5SDavid du Colombier }
237*59cc4ca5SDavid du Colombier 
238*59cc4ca5SDavid du Colombier 
239*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
240*59cc4ca5SDavid du Colombier #define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
241*59cc4ca5SDavid du Colombier {                                                 \
242*59cc4ca5SDavid du Colombier    UInt32 zchh = (UInt32)(zchh0);                 \
243*59cc4ca5SDavid du Colombier    /*-- fast track the common case --*/           \
244*59cc4ca5SDavid du Colombier    if (zchh != zs->state_in_ch &&                 \
245*59cc4ca5SDavid du Colombier        zs->state_in_len == 1) {                   \
246*59cc4ca5SDavid du Colombier       UChar ch = (UChar)(zs->state_in_ch);        \
247*59cc4ca5SDavid du Colombier       BZ_UPDATE_CRC( zs->blockCRC, ch );          \
248*59cc4ca5SDavid du Colombier       zs->inUse[zs->state_in_ch] = True;          \
249*59cc4ca5SDavid du Colombier       zs->block[zs->nblock] = (UChar)ch;          \
250*59cc4ca5SDavid du Colombier       zs->nblock++;                               \
251*59cc4ca5SDavid du Colombier       zs->state_in_ch = zchh;                     \
252*59cc4ca5SDavid du Colombier    }                                              \
253*59cc4ca5SDavid du Colombier    else                                           \
254*59cc4ca5SDavid du Colombier    /*-- general, uncommon cases --*/              \
255*59cc4ca5SDavid du Colombier    if (zchh != zs->state_in_ch ||                 \
256*59cc4ca5SDavid du Colombier       zs->state_in_len == 255) {                  \
257*59cc4ca5SDavid du Colombier       if (zs->state_in_ch < 256)                  \
258*59cc4ca5SDavid du Colombier          add_pair_to_block ( zs );                \
259*59cc4ca5SDavid du Colombier       zs->state_in_ch = zchh;                     \
260*59cc4ca5SDavid du Colombier       zs->state_in_len = 1;                       \
261*59cc4ca5SDavid du Colombier    } else {                                       \
262*59cc4ca5SDavid du Colombier       zs->state_in_len++;                         \
263*59cc4ca5SDavid du Colombier    }                                              \
264*59cc4ca5SDavid du Colombier }
265*59cc4ca5SDavid du Colombier 
266*59cc4ca5SDavid du Colombier 
267*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
268*59cc4ca5SDavid du Colombier static
copy_input_until_stop(EState * s)269*59cc4ca5SDavid du Colombier Bool copy_input_until_stop ( EState* s )
270*59cc4ca5SDavid du Colombier {
271*59cc4ca5SDavid du Colombier    Bool progress_in = False;
272*59cc4ca5SDavid du Colombier 
273*59cc4ca5SDavid du Colombier    if (s->mode == BZ_M_RUNNING) {
274*59cc4ca5SDavid du Colombier 
275*59cc4ca5SDavid du Colombier       /*-- fast track the common case --*/
276*59cc4ca5SDavid du Colombier       while (True) {
277*59cc4ca5SDavid du Colombier          /*-- block full? --*/
278*59cc4ca5SDavid du Colombier          if (s->nblock >= s->nblockMAX) break;
279*59cc4ca5SDavid du Colombier          /*-- no input? --*/
280*59cc4ca5SDavid du Colombier          if (s->strm->avail_in == 0) break;
281*59cc4ca5SDavid du Colombier          progress_in = True;
282*59cc4ca5SDavid du Colombier          ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
283*59cc4ca5SDavid du Colombier          s->strm->next_in++;
284*59cc4ca5SDavid du Colombier          s->strm->avail_in--;
285*59cc4ca5SDavid du Colombier          s->strm->total_in_lo32++;
286*59cc4ca5SDavid du Colombier          if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
287*59cc4ca5SDavid du Colombier       }
288*59cc4ca5SDavid du Colombier 
289*59cc4ca5SDavid du Colombier    } else {
290*59cc4ca5SDavid du Colombier 
291*59cc4ca5SDavid du Colombier       /*-- general, uncommon case --*/
292*59cc4ca5SDavid du Colombier       while (True) {
293*59cc4ca5SDavid du Colombier          /*-- block full? --*/
294*59cc4ca5SDavid du Colombier          if (s->nblock >= s->nblockMAX) break;
295*59cc4ca5SDavid du Colombier          /*-- no input? --*/
296*59cc4ca5SDavid du Colombier          if (s->strm->avail_in == 0) break;
297*59cc4ca5SDavid du Colombier          /*-- flush/finish end? --*/
298*59cc4ca5SDavid du Colombier          if (s->avail_in_expect == 0) break;
299*59cc4ca5SDavid du Colombier          progress_in = True;
300*59cc4ca5SDavid du Colombier          ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
301*59cc4ca5SDavid du Colombier          s->strm->next_in++;
302*59cc4ca5SDavid du Colombier          s->strm->avail_in--;
303*59cc4ca5SDavid du Colombier          s->strm->total_in_lo32++;
304*59cc4ca5SDavid du Colombier          if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
305*59cc4ca5SDavid du Colombier          s->avail_in_expect--;
306*59cc4ca5SDavid du Colombier       }
307*59cc4ca5SDavid du Colombier    }
308*59cc4ca5SDavid du Colombier    return progress_in;
309*59cc4ca5SDavid du Colombier }
310*59cc4ca5SDavid du Colombier 
311*59cc4ca5SDavid du Colombier 
312*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
313*59cc4ca5SDavid du Colombier static
copy_output_until_stop(EState * s)314*59cc4ca5SDavid du Colombier Bool copy_output_until_stop ( EState* s )
315*59cc4ca5SDavid du Colombier {
316*59cc4ca5SDavid du Colombier    Bool progress_out = False;
317*59cc4ca5SDavid du Colombier 
318*59cc4ca5SDavid du Colombier    while (True) {
319*59cc4ca5SDavid du Colombier 
320*59cc4ca5SDavid du Colombier       /*-- no output space? --*/
321*59cc4ca5SDavid du Colombier       if (s->strm->avail_out == 0) break;
322*59cc4ca5SDavid du Colombier 
323*59cc4ca5SDavid du Colombier       /*-- block done? --*/
324*59cc4ca5SDavid du Colombier       if (s->state_out_pos >= s->numZ) break;
325*59cc4ca5SDavid du Colombier 
326*59cc4ca5SDavid du Colombier       progress_out = True;
327*59cc4ca5SDavid du Colombier       *(s->strm->next_out) = s->zbits[s->state_out_pos];
328*59cc4ca5SDavid du Colombier       s->state_out_pos++;
329*59cc4ca5SDavid du Colombier       s->strm->avail_out--;
330*59cc4ca5SDavid du Colombier       s->strm->next_out++;
331*59cc4ca5SDavid du Colombier       s->strm->total_out_lo32++;
332*59cc4ca5SDavid du Colombier       if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
333*59cc4ca5SDavid du Colombier    }
334*59cc4ca5SDavid du Colombier 
335*59cc4ca5SDavid du Colombier    return progress_out;
336*59cc4ca5SDavid du Colombier }
337*59cc4ca5SDavid du Colombier 
338*59cc4ca5SDavid du Colombier 
339*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
340*59cc4ca5SDavid du Colombier static
handle_compress(bz_stream * strm)341*59cc4ca5SDavid du Colombier Bool handle_compress ( bz_stream* strm )
342*59cc4ca5SDavid du Colombier {
343*59cc4ca5SDavid du Colombier    Bool progress_in  = False;
344*59cc4ca5SDavid du Colombier    Bool progress_out = False;
345*59cc4ca5SDavid du Colombier    EState* s = strm->state;
346*59cc4ca5SDavid du Colombier 
347*59cc4ca5SDavid du Colombier    while (True) {
348*59cc4ca5SDavid du Colombier 
349*59cc4ca5SDavid du Colombier       if (s->state == BZ_S_OUTPUT) {
350*59cc4ca5SDavid du Colombier          progress_out |= copy_output_until_stop ( s );
351*59cc4ca5SDavid du Colombier          if (s->state_out_pos < s->numZ) break;
352*59cc4ca5SDavid du Colombier          if (s->mode == BZ_M_FINISHING &&
353*59cc4ca5SDavid du Colombier              s->avail_in_expect == 0 &&
354*59cc4ca5SDavid du Colombier              isempty_RL(s)) break;
355*59cc4ca5SDavid du Colombier          prepare_new_block ( s );
356*59cc4ca5SDavid du Colombier          s->state = BZ_S_INPUT;
357*59cc4ca5SDavid du Colombier          if (s->mode == BZ_M_FLUSHING &&
358*59cc4ca5SDavid du Colombier              s->avail_in_expect == 0 &&
359*59cc4ca5SDavid du Colombier              isempty_RL(s)) break;
360*59cc4ca5SDavid du Colombier       }
361*59cc4ca5SDavid du Colombier 
362*59cc4ca5SDavid du Colombier       if (s->state == BZ_S_INPUT) {
363*59cc4ca5SDavid du Colombier          progress_in |= copy_input_until_stop ( s );
364*59cc4ca5SDavid du Colombier          if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
365*59cc4ca5SDavid du Colombier             flush_RL ( s );
366*59cc4ca5SDavid du Colombier             BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
367*59cc4ca5SDavid du Colombier             s->state = BZ_S_OUTPUT;
368*59cc4ca5SDavid du Colombier          }
369*59cc4ca5SDavid du Colombier          else
370*59cc4ca5SDavid du Colombier          if (s->nblock >= s->nblockMAX) {
371*59cc4ca5SDavid du Colombier             BZ2_compressBlock ( s, False );
372*59cc4ca5SDavid du Colombier             s->state = BZ_S_OUTPUT;
373*59cc4ca5SDavid du Colombier          }
374*59cc4ca5SDavid du Colombier          else
375*59cc4ca5SDavid du Colombier          if (s->strm->avail_in == 0) {
376*59cc4ca5SDavid du Colombier             break;
377*59cc4ca5SDavid du Colombier          }
378*59cc4ca5SDavid du Colombier       }
379*59cc4ca5SDavid du Colombier 
380*59cc4ca5SDavid du Colombier    }
381*59cc4ca5SDavid du Colombier 
382*59cc4ca5SDavid du Colombier    return progress_in || progress_out;
383*59cc4ca5SDavid du Colombier }
384*59cc4ca5SDavid du Colombier 
385*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzCompress)386*59cc4ca5SDavid du Colombier int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
387*59cc4ca5SDavid du Colombier {
388*59cc4ca5SDavid du Colombier    Bool progress;
389*59cc4ca5SDavid du Colombier    EState* s;
390*59cc4ca5SDavid du Colombier    if (strm == NULL) return BZ_PARAM_ERROR;
391*59cc4ca5SDavid du Colombier    s = strm->state;
392*59cc4ca5SDavid du Colombier    if (s == NULL) return BZ_PARAM_ERROR;
393*59cc4ca5SDavid du Colombier    if (s->strm != strm) return BZ_PARAM_ERROR;
394*59cc4ca5SDavid du Colombier 
395*59cc4ca5SDavid du Colombier    preswitch:
396*59cc4ca5SDavid du Colombier    switch (s->mode) {
397*59cc4ca5SDavid du Colombier 
398*59cc4ca5SDavid du Colombier       case BZ_M_IDLE:
399*59cc4ca5SDavid du Colombier          return BZ_SEQUENCE_ERROR;
400*59cc4ca5SDavid du Colombier 
401*59cc4ca5SDavid du Colombier       case BZ_M_RUNNING:
402*59cc4ca5SDavid du Colombier          if (action == BZ_RUN) {
403*59cc4ca5SDavid du Colombier             progress = handle_compress ( strm );
404*59cc4ca5SDavid du Colombier             return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
405*59cc4ca5SDavid du Colombier          }
406*59cc4ca5SDavid du Colombier          else
407*59cc4ca5SDavid du Colombier 	 if (action == BZ_FLUSH) {
408*59cc4ca5SDavid du Colombier             s->avail_in_expect = strm->avail_in;
409*59cc4ca5SDavid du Colombier             s->mode = BZ_M_FLUSHING;
410*59cc4ca5SDavid du Colombier             goto preswitch;
411*59cc4ca5SDavid du Colombier          }
412*59cc4ca5SDavid du Colombier          else
413*59cc4ca5SDavid du Colombier          if (action == BZ_FINISH) {
414*59cc4ca5SDavid du Colombier             s->avail_in_expect = strm->avail_in;
415*59cc4ca5SDavid du Colombier             s->mode = BZ_M_FINISHING;
416*59cc4ca5SDavid du Colombier             goto preswitch;
417*59cc4ca5SDavid du Colombier          }
418*59cc4ca5SDavid du Colombier          else
419*59cc4ca5SDavid du Colombier             return BZ_PARAM_ERROR;
420*59cc4ca5SDavid du Colombier 
421*59cc4ca5SDavid du Colombier       case BZ_M_FLUSHING:
422*59cc4ca5SDavid du Colombier          if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
423*59cc4ca5SDavid du Colombier          if (s->avail_in_expect != s->strm->avail_in)
424*59cc4ca5SDavid du Colombier             return BZ_SEQUENCE_ERROR;
425*59cc4ca5SDavid du Colombier          progress = handle_compress ( strm );
426*59cc4ca5SDavid du Colombier          if (!progress) return BZ_SEQUENCE_ERROR;	//rsc added
427*59cc4ca5SDavid du Colombier          if (s->avail_in_expect > 0 || !isempty_RL(s) ||
428*59cc4ca5SDavid du Colombier              s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
429*59cc4ca5SDavid du Colombier          s->mode = BZ_M_RUNNING;
430*59cc4ca5SDavid du Colombier          return BZ_RUN_OK;
431*59cc4ca5SDavid du Colombier 
432*59cc4ca5SDavid du Colombier       case BZ_M_FINISHING:
433*59cc4ca5SDavid du Colombier          if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
434*59cc4ca5SDavid du Colombier          if (s->avail_in_expect != s->strm->avail_in)
435*59cc4ca5SDavid du Colombier             return BZ_SEQUENCE_ERROR;
436*59cc4ca5SDavid du Colombier          progress = handle_compress ( strm );
437*59cc4ca5SDavid du Colombier          if (!progress) return BZ_SEQUENCE_ERROR;
438*59cc4ca5SDavid du Colombier          if (s->avail_in_expect > 0 || !isempty_RL(s) ||
439*59cc4ca5SDavid du Colombier              s->state_out_pos < s->numZ) return BZ_FINISH_OK;
440*59cc4ca5SDavid du Colombier          s->mode = BZ_M_IDLE;
441*59cc4ca5SDavid du Colombier          return BZ_STREAM_END;
442*59cc4ca5SDavid du Colombier    }
443*59cc4ca5SDavid du Colombier    return BZ_OK; /*--not reached--*/
444*59cc4ca5SDavid du Colombier }
445*59cc4ca5SDavid du Colombier 
446*59cc4ca5SDavid du Colombier 
447*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzCompressEnd)448*59cc4ca5SDavid du Colombier int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
449*59cc4ca5SDavid du Colombier {
450*59cc4ca5SDavid du Colombier    EState* s;
451*59cc4ca5SDavid du Colombier    if (strm == NULL) return BZ_PARAM_ERROR;
452*59cc4ca5SDavid du Colombier    s = strm->state;
453*59cc4ca5SDavid du Colombier    if (s == NULL) return BZ_PARAM_ERROR;
454*59cc4ca5SDavid du Colombier    if (s->strm != strm) return BZ_PARAM_ERROR;
455*59cc4ca5SDavid du Colombier 
456*59cc4ca5SDavid du Colombier    if (s->arr1 != NULL) BZFREE(s->arr1);
457*59cc4ca5SDavid du Colombier    if (s->arr2 != NULL) BZFREE(s->arr2);
458*59cc4ca5SDavid du Colombier    if (s->ftab != NULL) BZFREE(s->ftab);
459*59cc4ca5SDavid du Colombier    BZFREE(strm->state);
460*59cc4ca5SDavid du Colombier 
461*59cc4ca5SDavid du Colombier    strm->state = NULL;
462*59cc4ca5SDavid du Colombier 
463*59cc4ca5SDavid du Colombier    return BZ_OK;
464*59cc4ca5SDavid du Colombier }
465*59cc4ca5SDavid du Colombier 
466