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 /*--- Decompression stuff ---*/
93*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
94*59cc4ca5SDavid du Colombier
95*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompressInit)96*59cc4ca5SDavid du Colombier int BZ_API(BZ2_bzDecompressInit)
97*59cc4ca5SDavid du Colombier ( bz_stream* strm,
98*59cc4ca5SDavid du Colombier int verbosity,
99*59cc4ca5SDavid du Colombier int small )
100*59cc4ca5SDavid du Colombier {
101*59cc4ca5SDavid du Colombier DState* s;
102*59cc4ca5SDavid du Colombier
103*59cc4ca5SDavid du Colombier if (!bz_config_ok()) return BZ_CONFIG_ERROR;
104*59cc4ca5SDavid du Colombier
105*59cc4ca5SDavid du Colombier if (strm == NULL) return BZ_PARAM_ERROR;
106*59cc4ca5SDavid du Colombier if (small != 0 && small != 1) return BZ_PARAM_ERROR;
107*59cc4ca5SDavid du Colombier if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
108*59cc4ca5SDavid du Colombier
109*59cc4ca5SDavid du Colombier if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
110*59cc4ca5SDavid du Colombier if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
111*59cc4ca5SDavid du Colombier
112*59cc4ca5SDavid du Colombier s = BZALLOC( sizeof(DState) );
113*59cc4ca5SDavid du Colombier if (s == NULL) return BZ_MEM_ERROR;
114*59cc4ca5SDavid du Colombier s->strm = strm;
115*59cc4ca5SDavid du Colombier strm->state = s;
116*59cc4ca5SDavid du Colombier s->state = BZ_X_MAGIC_1;
117*59cc4ca5SDavid du Colombier s->bsLive = 0;
118*59cc4ca5SDavid du Colombier s->bsBuff = 0;
119*59cc4ca5SDavid du Colombier s->calculatedCombinedCRC = 0;
120*59cc4ca5SDavid du Colombier strm->total_in_lo32 = 0;
121*59cc4ca5SDavid du Colombier strm->total_in_hi32 = 0;
122*59cc4ca5SDavid du Colombier strm->total_out_lo32 = 0;
123*59cc4ca5SDavid du Colombier strm->total_out_hi32 = 0;
124*59cc4ca5SDavid du Colombier s->smallDecompress = (Bool)small;
125*59cc4ca5SDavid du Colombier s->ll4 = NULL;
126*59cc4ca5SDavid du Colombier s->ll16 = NULL;
127*59cc4ca5SDavid du Colombier s->tt = NULL;
128*59cc4ca5SDavid du Colombier s->currBlockNo = 0;
129*59cc4ca5SDavid du Colombier s->verbosity = verbosity;
130*59cc4ca5SDavid du Colombier
131*59cc4ca5SDavid du Colombier return BZ_OK;
132*59cc4ca5SDavid du Colombier }
133*59cc4ca5SDavid du Colombier
134*59cc4ca5SDavid du Colombier
135*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
136*59cc4ca5SDavid du Colombier static
unRLE_obuf_to_output_FAST(DState * s)137*59cc4ca5SDavid du Colombier void unRLE_obuf_to_output_FAST ( DState* s )
138*59cc4ca5SDavid du Colombier {
139*59cc4ca5SDavid du Colombier UChar k1;
140*59cc4ca5SDavid du Colombier
141*59cc4ca5SDavid du Colombier if (s->blockRandomised) {
142*59cc4ca5SDavid du Colombier
143*59cc4ca5SDavid du Colombier while (True) {
144*59cc4ca5SDavid du Colombier /* try to finish existing run */
145*59cc4ca5SDavid du Colombier while (True) {
146*59cc4ca5SDavid du Colombier if (s->strm->avail_out == 0) return;
147*59cc4ca5SDavid du Colombier if (s->state_out_len == 0) break;
148*59cc4ca5SDavid du Colombier *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
149*59cc4ca5SDavid du Colombier BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
150*59cc4ca5SDavid du Colombier s->state_out_len--;
151*59cc4ca5SDavid du Colombier s->strm->next_out++;
152*59cc4ca5SDavid du Colombier s->strm->avail_out--;
153*59cc4ca5SDavid du Colombier s->strm->total_out_lo32++;
154*59cc4ca5SDavid du Colombier if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
155*59cc4ca5SDavid du Colombier }
156*59cc4ca5SDavid du Colombier
157*59cc4ca5SDavid du Colombier /* can a new run be started? */
158*59cc4ca5SDavid du Colombier if (s->nblock_used == s->save_nblock+1) return;
159*59cc4ca5SDavid du Colombier
160*59cc4ca5SDavid du Colombier
161*59cc4ca5SDavid du Colombier s->state_out_len = 1;
162*59cc4ca5SDavid du Colombier s->state_out_ch = s->k0;
163*59cc4ca5SDavid du Colombier BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
164*59cc4ca5SDavid du Colombier k1 ^= BZ_RAND_MASK; s->nblock_used++;
165*59cc4ca5SDavid du Colombier if (s->nblock_used == s->save_nblock+1) continue;
166*59cc4ca5SDavid du Colombier if (k1 != s->k0) { s->k0 = k1; continue; };
167*59cc4ca5SDavid du Colombier
168*59cc4ca5SDavid du Colombier s->state_out_len = 2;
169*59cc4ca5SDavid du Colombier BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
170*59cc4ca5SDavid du Colombier k1 ^= BZ_RAND_MASK; s->nblock_used++;
171*59cc4ca5SDavid du Colombier if (s->nblock_used == s->save_nblock+1) continue;
172*59cc4ca5SDavid du Colombier if (k1 != s->k0) { s->k0 = k1; continue; };
173*59cc4ca5SDavid du Colombier
174*59cc4ca5SDavid du Colombier s->state_out_len = 3;
175*59cc4ca5SDavid du Colombier BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
176*59cc4ca5SDavid du Colombier k1 ^= BZ_RAND_MASK; s->nblock_used++;
177*59cc4ca5SDavid du Colombier if (s->nblock_used == s->save_nblock+1) continue;
178*59cc4ca5SDavid du Colombier if (k1 != s->k0) { s->k0 = k1; continue; };
179*59cc4ca5SDavid du Colombier
180*59cc4ca5SDavid du Colombier BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
181*59cc4ca5SDavid du Colombier k1 ^= BZ_RAND_MASK; s->nblock_used++;
182*59cc4ca5SDavid du Colombier s->state_out_len = ((Int32)k1) + 4;
183*59cc4ca5SDavid du Colombier BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
184*59cc4ca5SDavid du Colombier s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
185*59cc4ca5SDavid du Colombier }
186*59cc4ca5SDavid du Colombier
187*59cc4ca5SDavid du Colombier } else {
188*59cc4ca5SDavid du Colombier
189*59cc4ca5SDavid du Colombier /* restore */
190*59cc4ca5SDavid du Colombier UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
191*59cc4ca5SDavid du Colombier UChar c_state_out_ch = s->state_out_ch;
192*59cc4ca5SDavid du Colombier Int32 c_state_out_len = s->state_out_len;
193*59cc4ca5SDavid du Colombier Int32 c_nblock_used = s->nblock_used;
194*59cc4ca5SDavid du Colombier Int32 c_k0 = s->k0;
195*59cc4ca5SDavid du Colombier UInt32* c_tt = s->tt;
196*59cc4ca5SDavid du Colombier UInt32 c_tPos = s->tPos;
197*59cc4ca5SDavid du Colombier char* cs_next_out = s->strm->next_out;
198*59cc4ca5SDavid du Colombier unsigned int cs_avail_out = s->strm->avail_out;
199*59cc4ca5SDavid du Colombier /* end restore */
200*59cc4ca5SDavid du Colombier
201*59cc4ca5SDavid du Colombier UInt32 avail_out_INIT = cs_avail_out;
202*59cc4ca5SDavid du Colombier Int32 s_save_nblockPP = s->save_nblock+1;
203*59cc4ca5SDavid du Colombier unsigned int total_out_lo32_old;
204*59cc4ca5SDavid du Colombier
205*59cc4ca5SDavid du Colombier while (True) {
206*59cc4ca5SDavid du Colombier
207*59cc4ca5SDavid du Colombier /* try to finish existing run */
208*59cc4ca5SDavid du Colombier if (c_state_out_len > 0) {
209*59cc4ca5SDavid du Colombier while (True) {
210*59cc4ca5SDavid du Colombier if (cs_avail_out == 0) goto return_notr;
211*59cc4ca5SDavid du Colombier if (c_state_out_len == 1) break;
212*59cc4ca5SDavid du Colombier *( (UChar*)(cs_next_out) ) = c_state_out_ch;
213*59cc4ca5SDavid du Colombier BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
214*59cc4ca5SDavid du Colombier c_state_out_len--;
215*59cc4ca5SDavid du Colombier cs_next_out++;
216*59cc4ca5SDavid du Colombier cs_avail_out--;
217*59cc4ca5SDavid du Colombier }
218*59cc4ca5SDavid du Colombier s_state_out_len_eq_one:
219*59cc4ca5SDavid du Colombier {
220*59cc4ca5SDavid du Colombier if (cs_avail_out == 0) {
221*59cc4ca5SDavid du Colombier c_state_out_len = 1; goto return_notr;
222*59cc4ca5SDavid du Colombier };
223*59cc4ca5SDavid du Colombier *( (UChar*)(cs_next_out) ) = c_state_out_ch;
224*59cc4ca5SDavid du Colombier BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
225*59cc4ca5SDavid du Colombier cs_next_out++;
226*59cc4ca5SDavid du Colombier cs_avail_out--;
227*59cc4ca5SDavid du Colombier }
228*59cc4ca5SDavid du Colombier }
229*59cc4ca5SDavid du Colombier /* can a new run be started? */
230*59cc4ca5SDavid du Colombier if (c_nblock_used == s_save_nblockPP) {
231*59cc4ca5SDavid du Colombier c_state_out_len = 0; goto return_notr;
232*59cc4ca5SDavid du Colombier };
233*59cc4ca5SDavid du Colombier c_state_out_ch = c_k0;
234*59cc4ca5SDavid du Colombier BZ_GET_FAST_C(k1); c_nblock_used++;
235*59cc4ca5SDavid du Colombier if (k1 != c_k0) {
236*59cc4ca5SDavid du Colombier c_k0 = k1; goto s_state_out_len_eq_one;
237*59cc4ca5SDavid du Colombier };
238*59cc4ca5SDavid du Colombier if (c_nblock_used == s_save_nblockPP)
239*59cc4ca5SDavid du Colombier goto s_state_out_len_eq_one;
240*59cc4ca5SDavid du Colombier
241*59cc4ca5SDavid du Colombier c_state_out_len = 2;
242*59cc4ca5SDavid du Colombier BZ_GET_FAST_C(k1); c_nblock_used++;
243*59cc4ca5SDavid du Colombier if (c_nblock_used == s_save_nblockPP) continue;
244*59cc4ca5SDavid du Colombier if (k1 != c_k0) { c_k0 = k1; continue; };
245*59cc4ca5SDavid du Colombier
246*59cc4ca5SDavid du Colombier c_state_out_len = 3;
247*59cc4ca5SDavid du Colombier BZ_GET_FAST_C(k1); c_nblock_used++;
248*59cc4ca5SDavid du Colombier if (c_nblock_used == s_save_nblockPP) continue;
249*59cc4ca5SDavid du Colombier if (k1 != c_k0) { c_k0 = k1; continue; };
250*59cc4ca5SDavid du Colombier
251*59cc4ca5SDavid du Colombier BZ_GET_FAST_C(k1); c_nblock_used++;
252*59cc4ca5SDavid du Colombier c_state_out_len = ((Int32)k1) + 4;
253*59cc4ca5SDavid du Colombier BZ_GET_FAST_C(c_k0); c_nblock_used++;
254*59cc4ca5SDavid du Colombier }
255*59cc4ca5SDavid du Colombier
256*59cc4ca5SDavid du Colombier return_notr:
257*59cc4ca5SDavid du Colombier total_out_lo32_old = s->strm->total_out_lo32;
258*59cc4ca5SDavid du Colombier s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
259*59cc4ca5SDavid du Colombier if (s->strm->total_out_lo32 < total_out_lo32_old)
260*59cc4ca5SDavid du Colombier s->strm->total_out_hi32++;
261*59cc4ca5SDavid du Colombier
262*59cc4ca5SDavid du Colombier /* save */
263*59cc4ca5SDavid du Colombier s->calculatedBlockCRC = c_calculatedBlockCRC;
264*59cc4ca5SDavid du Colombier s->state_out_ch = c_state_out_ch;
265*59cc4ca5SDavid du Colombier s->state_out_len = c_state_out_len;
266*59cc4ca5SDavid du Colombier s->nblock_used = c_nblock_used;
267*59cc4ca5SDavid du Colombier s->k0 = c_k0;
268*59cc4ca5SDavid du Colombier s->tt = c_tt;
269*59cc4ca5SDavid du Colombier s->tPos = c_tPos;
270*59cc4ca5SDavid du Colombier s->strm->next_out = cs_next_out;
271*59cc4ca5SDavid du Colombier s->strm->avail_out = cs_avail_out;
272*59cc4ca5SDavid du Colombier /* end save */
273*59cc4ca5SDavid du Colombier }
274*59cc4ca5SDavid du Colombier }
275*59cc4ca5SDavid du Colombier
276*59cc4ca5SDavid du Colombier
277*59cc4ca5SDavid du Colombier
278*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ2_indexIntoF(Int32 indx,Int32 * cftab)279*59cc4ca5SDavid du Colombier __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
280*59cc4ca5SDavid du Colombier {
281*59cc4ca5SDavid du Colombier Int32 nb, na, mid;
282*59cc4ca5SDavid du Colombier nb = 0;
283*59cc4ca5SDavid du Colombier na = 256;
284*59cc4ca5SDavid du Colombier do {
285*59cc4ca5SDavid du Colombier mid = (nb + na) >> 1;
286*59cc4ca5SDavid du Colombier if (indx >= cftab[mid]) nb = mid; else na = mid;
287*59cc4ca5SDavid du Colombier }
288*59cc4ca5SDavid du Colombier while (na - nb != 1);
289*59cc4ca5SDavid du Colombier return nb;
290*59cc4ca5SDavid du Colombier }
291*59cc4ca5SDavid du Colombier
292*59cc4ca5SDavid du Colombier
293*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
294*59cc4ca5SDavid du Colombier static
unRLE_obuf_to_output_SMALL(DState * s)295*59cc4ca5SDavid du Colombier void unRLE_obuf_to_output_SMALL ( DState* s )
296*59cc4ca5SDavid du Colombier {
297*59cc4ca5SDavid du Colombier UChar k1;
298*59cc4ca5SDavid du Colombier
299*59cc4ca5SDavid du Colombier if (s->blockRandomised) {
300*59cc4ca5SDavid du Colombier
301*59cc4ca5SDavid du Colombier while (True) {
302*59cc4ca5SDavid du Colombier /* try to finish existing run */
303*59cc4ca5SDavid du Colombier while (True) {
304*59cc4ca5SDavid du Colombier if (s->strm->avail_out == 0) return;
305*59cc4ca5SDavid du Colombier if (s->state_out_len == 0) break;
306*59cc4ca5SDavid du Colombier *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
307*59cc4ca5SDavid du Colombier BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
308*59cc4ca5SDavid du Colombier s->state_out_len--;
309*59cc4ca5SDavid du Colombier s->strm->next_out++;
310*59cc4ca5SDavid du Colombier s->strm->avail_out--;
311*59cc4ca5SDavid du Colombier s->strm->total_out_lo32++;
312*59cc4ca5SDavid du Colombier if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
313*59cc4ca5SDavid du Colombier }
314*59cc4ca5SDavid du Colombier
315*59cc4ca5SDavid du Colombier /* can a new run be started? */
316*59cc4ca5SDavid du Colombier if (s->nblock_used == s->save_nblock+1) return;
317*59cc4ca5SDavid du Colombier
318*59cc4ca5SDavid du Colombier
319*59cc4ca5SDavid du Colombier s->state_out_len = 1;
320*59cc4ca5SDavid du Colombier s->state_out_ch = s->k0;
321*59cc4ca5SDavid du Colombier BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
322*59cc4ca5SDavid du Colombier k1 ^= BZ_RAND_MASK; s->nblock_used++;
323*59cc4ca5SDavid du Colombier if (s->nblock_used == s->save_nblock+1) continue;
324*59cc4ca5SDavid du Colombier if (k1 != s->k0) { s->k0 = k1; continue; };
325*59cc4ca5SDavid du Colombier
326*59cc4ca5SDavid du Colombier s->state_out_len = 2;
327*59cc4ca5SDavid du Colombier BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
328*59cc4ca5SDavid du Colombier k1 ^= BZ_RAND_MASK; s->nblock_used++;
329*59cc4ca5SDavid du Colombier if (s->nblock_used == s->save_nblock+1) continue;
330*59cc4ca5SDavid du Colombier if (k1 != s->k0) { s->k0 = k1; continue; };
331*59cc4ca5SDavid du Colombier
332*59cc4ca5SDavid du Colombier s->state_out_len = 3;
333*59cc4ca5SDavid du Colombier BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
334*59cc4ca5SDavid du Colombier k1 ^= BZ_RAND_MASK; s->nblock_used++;
335*59cc4ca5SDavid du Colombier if (s->nblock_used == s->save_nblock+1) continue;
336*59cc4ca5SDavid du Colombier if (k1 != s->k0) { s->k0 = k1; continue; };
337*59cc4ca5SDavid du Colombier
338*59cc4ca5SDavid du Colombier BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
339*59cc4ca5SDavid du Colombier k1 ^= BZ_RAND_MASK; s->nblock_used++;
340*59cc4ca5SDavid du Colombier s->state_out_len = ((Int32)k1) + 4;
341*59cc4ca5SDavid du Colombier BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
342*59cc4ca5SDavid du Colombier s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
343*59cc4ca5SDavid du Colombier }
344*59cc4ca5SDavid du Colombier
345*59cc4ca5SDavid du Colombier } else {
346*59cc4ca5SDavid du Colombier
347*59cc4ca5SDavid du Colombier while (True) {
348*59cc4ca5SDavid du Colombier /* try to finish existing run */
349*59cc4ca5SDavid du Colombier while (True) {
350*59cc4ca5SDavid du Colombier if (s->strm->avail_out == 0) return;
351*59cc4ca5SDavid du Colombier if (s->state_out_len == 0) break;
352*59cc4ca5SDavid du Colombier *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
353*59cc4ca5SDavid du Colombier BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
354*59cc4ca5SDavid du Colombier s->state_out_len--;
355*59cc4ca5SDavid du Colombier s->strm->next_out++;
356*59cc4ca5SDavid du Colombier s->strm->avail_out--;
357*59cc4ca5SDavid du Colombier s->strm->total_out_lo32++;
358*59cc4ca5SDavid du Colombier if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
359*59cc4ca5SDavid du Colombier }
360*59cc4ca5SDavid du Colombier
361*59cc4ca5SDavid du Colombier /* can a new run be started? */
362*59cc4ca5SDavid du Colombier if (s->nblock_used == s->save_nblock+1) return;
363*59cc4ca5SDavid du Colombier
364*59cc4ca5SDavid du Colombier s->state_out_len = 1;
365*59cc4ca5SDavid du Colombier s->state_out_ch = s->k0;
366*59cc4ca5SDavid du Colombier BZ_GET_SMALL(k1); s->nblock_used++;
367*59cc4ca5SDavid du Colombier if (s->nblock_used == s->save_nblock+1) continue;
368*59cc4ca5SDavid du Colombier if (k1 != s->k0) { s->k0 = k1; continue; };
369*59cc4ca5SDavid du Colombier
370*59cc4ca5SDavid du Colombier s->state_out_len = 2;
371*59cc4ca5SDavid du Colombier BZ_GET_SMALL(k1); s->nblock_used++;
372*59cc4ca5SDavid du Colombier if (s->nblock_used == s->save_nblock+1) continue;
373*59cc4ca5SDavid du Colombier if (k1 != s->k0) { s->k0 = k1; continue; };
374*59cc4ca5SDavid du Colombier
375*59cc4ca5SDavid du Colombier s->state_out_len = 3;
376*59cc4ca5SDavid du Colombier BZ_GET_SMALL(k1); s->nblock_used++;
377*59cc4ca5SDavid du Colombier if (s->nblock_used == s->save_nblock+1) continue;
378*59cc4ca5SDavid du Colombier if (k1 != s->k0) { s->k0 = k1; continue; };
379*59cc4ca5SDavid du Colombier
380*59cc4ca5SDavid du Colombier BZ_GET_SMALL(k1); s->nblock_used++;
381*59cc4ca5SDavid du Colombier s->state_out_len = ((Int32)k1) + 4;
382*59cc4ca5SDavid du Colombier BZ_GET_SMALL(s->k0); s->nblock_used++;
383*59cc4ca5SDavid du Colombier }
384*59cc4ca5SDavid du Colombier
385*59cc4ca5SDavid du Colombier }
386*59cc4ca5SDavid du Colombier }
387*59cc4ca5SDavid du Colombier
388*59cc4ca5SDavid du Colombier
389*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompress)390*59cc4ca5SDavid du Colombier int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
391*59cc4ca5SDavid du Colombier {
392*59cc4ca5SDavid du Colombier DState* s;
393*59cc4ca5SDavid du Colombier if (strm == NULL) return BZ_PARAM_ERROR;
394*59cc4ca5SDavid du Colombier s = strm->state;
395*59cc4ca5SDavid du Colombier if (s == NULL) return BZ_PARAM_ERROR;
396*59cc4ca5SDavid du Colombier if (s->strm != strm) return BZ_PARAM_ERROR;
397*59cc4ca5SDavid du Colombier
398*59cc4ca5SDavid du Colombier while (True) {
399*59cc4ca5SDavid du Colombier if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
400*59cc4ca5SDavid du Colombier if (s->state == BZ_X_OUTPUT) {
401*59cc4ca5SDavid du Colombier if (s->smallDecompress)
402*59cc4ca5SDavid du Colombier unRLE_obuf_to_output_SMALL ( s ); else
403*59cc4ca5SDavid du Colombier unRLE_obuf_to_output_FAST ( s );
404*59cc4ca5SDavid du Colombier if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
405*59cc4ca5SDavid du Colombier BZ_FINALISE_CRC ( s->calculatedBlockCRC );
406*59cc4ca5SDavid du Colombier if (s->verbosity >= 3)
407*59cc4ca5SDavid du Colombier VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC,
408*59cc4ca5SDavid du Colombier s->calculatedBlockCRC );
409*59cc4ca5SDavid du Colombier if (s->verbosity >= 2) VPrintf0 ( "]" );
410*59cc4ca5SDavid du Colombier if (s->calculatedBlockCRC != s->storedBlockCRC)
411*59cc4ca5SDavid du Colombier return BZ_DATA_ERROR;
412*59cc4ca5SDavid du Colombier s->calculatedCombinedCRC
413*59cc4ca5SDavid du Colombier = (s->calculatedCombinedCRC << 1) |
414*59cc4ca5SDavid du Colombier (s->calculatedCombinedCRC >> 31);
415*59cc4ca5SDavid du Colombier s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
416*59cc4ca5SDavid du Colombier s->state = BZ_X_BLKHDR_1;
417*59cc4ca5SDavid du Colombier } else {
418*59cc4ca5SDavid du Colombier return BZ_OK;
419*59cc4ca5SDavid du Colombier }
420*59cc4ca5SDavid du Colombier }
421*59cc4ca5SDavid du Colombier if (s->state >= BZ_X_MAGIC_1) {
422*59cc4ca5SDavid du Colombier Int32 r = BZ2_decompress ( s );
423*59cc4ca5SDavid du Colombier if (r == BZ_STREAM_END) {
424*59cc4ca5SDavid du Colombier if (s->verbosity >= 3)
425*59cc4ca5SDavid du Colombier VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x",
426*59cc4ca5SDavid du Colombier s->storedCombinedCRC, s->calculatedCombinedCRC );
427*59cc4ca5SDavid du Colombier if (s->calculatedCombinedCRC != s->storedCombinedCRC)
428*59cc4ca5SDavid du Colombier return BZ_DATA_ERROR;
429*59cc4ca5SDavid du Colombier return r;
430*59cc4ca5SDavid du Colombier }
431*59cc4ca5SDavid du Colombier if (s->state != BZ_X_OUTPUT) return r;
432*59cc4ca5SDavid du Colombier }
433*59cc4ca5SDavid du Colombier }
434*59cc4ca5SDavid du Colombier }
435*59cc4ca5SDavid du Colombier
436*59cc4ca5SDavid du Colombier
437*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompressEnd)438*59cc4ca5SDavid du Colombier int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
439*59cc4ca5SDavid du Colombier {
440*59cc4ca5SDavid du Colombier DState* s;
441*59cc4ca5SDavid du Colombier if (strm == NULL) return BZ_PARAM_ERROR;
442*59cc4ca5SDavid du Colombier s = strm->state;
443*59cc4ca5SDavid du Colombier if (s == NULL) return BZ_PARAM_ERROR;
444*59cc4ca5SDavid du Colombier if (s->strm != strm) return BZ_PARAM_ERROR;
445*59cc4ca5SDavid du Colombier
446*59cc4ca5SDavid du Colombier if (s->tt != NULL) BZFREE(s->tt);
447*59cc4ca5SDavid du Colombier if (s->ll16 != NULL) BZFREE(s->ll16);
448*59cc4ca5SDavid du Colombier if (s->ll4 != NULL) BZFREE(s->ll4);
449*59cc4ca5SDavid du Colombier
450*59cc4ca5SDavid du Colombier BZFREE(strm->state);
451*59cc4ca5SDavid du Colombier strm->state = NULL;
452*59cc4ca5SDavid du Colombier
453*59cc4ca5SDavid du Colombier return BZ_OK;
454*59cc4ca5SDavid du Colombier }
455*59cc4ca5SDavid du Colombier
456