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