xref: /rk3399_rockchip-uboot/lib/bzip2/bzlib.c (revision f071c501901281ae2de7a372ec12270dce91c426)
1*f071c501SMasahiro Yamada #include <config.h>
2*f071c501SMasahiro Yamada #include <common.h>
3*f071c501SMasahiro Yamada #include <watchdog.h>
4*f071c501SMasahiro Yamada 
5*f071c501SMasahiro Yamada /*
6*f071c501SMasahiro Yamada  * This file is a modified version of bzlib.c from the bzip2-1.0.2
7*f071c501SMasahiro Yamada  * distribution which can be found at http://sources.redhat.com/bzip2/
8*f071c501SMasahiro Yamada  */
9*f071c501SMasahiro Yamada 
10*f071c501SMasahiro Yamada /*-------------------------------------------------------------*/
11*f071c501SMasahiro Yamada /*--- Library top-level functions.                          ---*/
12*f071c501SMasahiro Yamada /*---                                               bzlib.c ---*/
13*f071c501SMasahiro Yamada /*-------------------------------------------------------------*/
14*f071c501SMasahiro Yamada 
15*f071c501SMasahiro Yamada /*--
16*f071c501SMasahiro Yamada   This file is a part of bzip2 and/or libbzip2, a program and
17*f071c501SMasahiro Yamada   library for lossless, block-sorting data compression.
18*f071c501SMasahiro Yamada 
19*f071c501SMasahiro Yamada   Copyright (C) 1996-2002 Julian R Seward.  All rights reserved.
20*f071c501SMasahiro Yamada 
21*f071c501SMasahiro Yamada   Redistribution and use in source and binary forms, with or without
22*f071c501SMasahiro Yamada   modification, are permitted provided that the following conditions
23*f071c501SMasahiro Yamada   are met:
24*f071c501SMasahiro Yamada 
25*f071c501SMasahiro Yamada   1. Redistributions of source code must retain the above copyright
26*f071c501SMasahiro Yamada      notice, this list of conditions and the following disclaimer.
27*f071c501SMasahiro Yamada 
28*f071c501SMasahiro Yamada   2. The origin of this software must not be misrepresented; you must
29*f071c501SMasahiro Yamada      not claim that you wrote the original software.  If you use this
30*f071c501SMasahiro Yamada      software in a product, an acknowledgment in the product
31*f071c501SMasahiro Yamada      documentation would be appreciated but is not required.
32*f071c501SMasahiro Yamada 
33*f071c501SMasahiro Yamada   3. Altered source versions must be plainly marked as such, and must
34*f071c501SMasahiro Yamada      not be misrepresented as being the original software.
35*f071c501SMasahiro Yamada 
36*f071c501SMasahiro Yamada   4. The name of the author may not be used to endorse or promote
37*f071c501SMasahiro Yamada      products derived from this software without specific prior written
38*f071c501SMasahiro Yamada      permission.
39*f071c501SMasahiro Yamada 
40*f071c501SMasahiro Yamada   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
41*f071c501SMasahiro Yamada   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
42*f071c501SMasahiro Yamada   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43*f071c501SMasahiro Yamada   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
44*f071c501SMasahiro Yamada   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45*f071c501SMasahiro Yamada   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
46*f071c501SMasahiro Yamada   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
47*f071c501SMasahiro Yamada   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
48*f071c501SMasahiro Yamada   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
49*f071c501SMasahiro Yamada   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50*f071c501SMasahiro Yamada   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51*f071c501SMasahiro Yamada 
52*f071c501SMasahiro Yamada   Julian Seward, Cambridge, UK.
53*f071c501SMasahiro Yamada   jseward@acm.org
54*f071c501SMasahiro Yamada   bzip2/libbzip2 version 1.0 of 21 March 2000
55*f071c501SMasahiro Yamada 
56*f071c501SMasahiro Yamada   This program is based on (at least) the work of:
57*f071c501SMasahiro Yamada      Mike Burrows
58*f071c501SMasahiro Yamada      David Wheeler
59*f071c501SMasahiro Yamada      Peter Fenwick
60*f071c501SMasahiro Yamada      Alistair Moffat
61*f071c501SMasahiro Yamada      Radford Neal
62*f071c501SMasahiro Yamada      Ian H. Witten
63*f071c501SMasahiro Yamada      Robert Sedgewick
64*f071c501SMasahiro Yamada      Jon L. Bentley
65*f071c501SMasahiro Yamada 
66*f071c501SMasahiro Yamada   For more information on these sources, see the manual.
67*f071c501SMasahiro Yamada --*/
68*f071c501SMasahiro Yamada 
69*f071c501SMasahiro Yamada /*--
70*f071c501SMasahiro Yamada    CHANGES
71*f071c501SMasahiro Yamada    ~~~~~~~
72*f071c501SMasahiro Yamada    0.9.0 -- original version.
73*f071c501SMasahiro Yamada 
74*f071c501SMasahiro Yamada    0.9.0a/b -- no changes in this file.
75*f071c501SMasahiro Yamada 
76*f071c501SMasahiro Yamada    0.9.0c
77*f071c501SMasahiro Yamada       * made zero-length BZ_FLUSH work correctly in bzCompress().
78*f071c501SMasahiro Yamada       * fixed bzWrite/bzRead to ignore zero-length requests.
79*f071c501SMasahiro Yamada       * fixed bzread to correctly handle read requests after EOF.
80*f071c501SMasahiro Yamada       * wrong parameter order in call to bzDecompressInit in
81*f071c501SMasahiro Yamada 	bzBuffToBuffDecompress.  Fixed.
82*f071c501SMasahiro Yamada --*/
83*f071c501SMasahiro Yamada 
84*f071c501SMasahiro Yamada #include "bzlib_private.h"
85*f071c501SMasahiro Yamada 
86*f071c501SMasahiro Yamada /*---------------------------------------------------*/
87*f071c501SMasahiro Yamada /*--- Compression stuff                           ---*/
88*f071c501SMasahiro Yamada /*---------------------------------------------------*/
89*f071c501SMasahiro Yamada 
90*f071c501SMasahiro Yamada 
91*f071c501SMasahiro Yamada /*---------------------------------------------------*/
92*f071c501SMasahiro Yamada #ifndef BZ_NO_STDIO
93*f071c501SMasahiro Yamada void BZ2_bz__AssertH__fail ( int errcode )
94*f071c501SMasahiro Yamada {
95*f071c501SMasahiro Yamada    fprintf(stderr,
96*f071c501SMasahiro Yamada       "\n\nbzip2/libbzip2: internal error number %d.\n"
97*f071c501SMasahiro Yamada       "This is a bug in bzip2/libbzip2, %s.\n"
98*f071c501SMasahiro Yamada       "Please report it to me at: jseward@acm.org.  If this happened\n"
99*f071c501SMasahiro Yamada       "when you were using some program which uses libbzip2 as a\n"
100*f071c501SMasahiro Yamada       "component, you should also report this bug to the author(s)\n"
101*f071c501SMasahiro Yamada       "of that program.  Please make an effort to report this bug;\n"
102*f071c501SMasahiro Yamada       "timely and accurate bug reports eventually lead to higher\n"
103*f071c501SMasahiro Yamada       "quality software.  Thanks.  Julian Seward, 30 December 2001.\n\n",
104*f071c501SMasahiro Yamada       errcode,
105*f071c501SMasahiro Yamada       BZ2_bzlibVersion()
106*f071c501SMasahiro Yamada    );
107*f071c501SMasahiro Yamada 
108*f071c501SMasahiro Yamada    if (errcode == 1007) {
109*f071c501SMasahiro Yamada    fprintf(stderr,
110*f071c501SMasahiro Yamada       "\n*** A special note about internal error number 1007 ***\n"
111*f071c501SMasahiro Yamada       "\n"
112*f071c501SMasahiro Yamada       "Experience suggests that a common cause of i.e. 1007\n"
113*f071c501SMasahiro Yamada       "is unreliable memory or other hardware.  The 1007 assertion\n"
114*f071c501SMasahiro Yamada       "just happens to cross-check the results of huge numbers of\n"
115*f071c501SMasahiro Yamada       "memory reads/writes, and so acts (unintendedly) as a stress\n"
116*f071c501SMasahiro Yamada       "test of your memory system.\n"
117*f071c501SMasahiro Yamada       "\n"
118*f071c501SMasahiro Yamada       "I suggest the following: try compressing the file again,\n"
119*f071c501SMasahiro Yamada       "possibly monitoring progress in detail with the -vv flag.\n"
120*f071c501SMasahiro Yamada       "\n"
121*f071c501SMasahiro Yamada       "* If the error cannot be reproduced, and/or happens at different\n"
122*f071c501SMasahiro Yamada       "  points in compression, you may have a flaky memory system.\n"
123*f071c501SMasahiro Yamada       "  Try a memory-test program.  I have used Memtest86\n"
124*f071c501SMasahiro Yamada       "  (www.memtest86.com).  At the time of writing it is free (GPLd).\n"
125*f071c501SMasahiro Yamada       "  Memtest86 tests memory much more thorougly than your BIOSs\n"
126*f071c501SMasahiro Yamada       "  power-on test, and may find failures that the BIOS doesn't.\n"
127*f071c501SMasahiro Yamada       "\n"
128*f071c501SMasahiro Yamada       "* If the error can be repeatably reproduced, this is a bug in\n"
129*f071c501SMasahiro Yamada       "  bzip2, and I would very much like to hear about it.  Please\n"
130*f071c501SMasahiro Yamada       "  let me know, and, ideally, save a copy of the file causing the\n"
131*f071c501SMasahiro Yamada       "  problem -- without which I will be unable to investigate it.\n"
132*f071c501SMasahiro Yamada       "\n"
133*f071c501SMasahiro Yamada    );
134*f071c501SMasahiro Yamada    }
135*f071c501SMasahiro Yamada 
136*f071c501SMasahiro Yamada    exit(3);
137*f071c501SMasahiro Yamada }
138*f071c501SMasahiro Yamada #endif
139*f071c501SMasahiro Yamada 
140*f071c501SMasahiro Yamada 
141*f071c501SMasahiro Yamada /*---------------------------------------------------*/
142*f071c501SMasahiro Yamada static
143*f071c501SMasahiro Yamada int bz_config_ok ( void )
144*f071c501SMasahiro Yamada {
145*f071c501SMasahiro Yamada    if (sizeof(int)   != 4) return 0;
146*f071c501SMasahiro Yamada    if (sizeof(short) != 2) return 0;
147*f071c501SMasahiro Yamada    if (sizeof(char)  != 1) return 0;
148*f071c501SMasahiro Yamada    return 1;
149*f071c501SMasahiro Yamada }
150*f071c501SMasahiro Yamada 
151*f071c501SMasahiro Yamada 
152*f071c501SMasahiro Yamada /*---------------------------------------------------*/
153*f071c501SMasahiro Yamada static
154*f071c501SMasahiro Yamada void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
155*f071c501SMasahiro Yamada {
156*f071c501SMasahiro Yamada    void* v = malloc ( items * size );
157*f071c501SMasahiro Yamada    return v;
158*f071c501SMasahiro Yamada }
159*f071c501SMasahiro Yamada 
160*f071c501SMasahiro Yamada static
161*f071c501SMasahiro Yamada void default_bzfree ( void* opaque, void* addr )
162*f071c501SMasahiro Yamada {
163*f071c501SMasahiro Yamada    if (addr != NULL) free ( addr );
164*f071c501SMasahiro Yamada }
165*f071c501SMasahiro Yamada 
166*f071c501SMasahiro Yamada #ifndef BZ_NO_COMPRESS
167*f071c501SMasahiro Yamada /*---------------------------------------------------*/
168*f071c501SMasahiro Yamada static
169*f071c501SMasahiro Yamada void prepare_new_block ( EState* s )
170*f071c501SMasahiro Yamada {
171*f071c501SMasahiro Yamada    Int32 i;
172*f071c501SMasahiro Yamada    s->nblock = 0;
173*f071c501SMasahiro Yamada    s->numZ = 0;
174*f071c501SMasahiro Yamada    s->state_out_pos = 0;
175*f071c501SMasahiro Yamada    BZ_INITIALISE_CRC ( s->blockCRC );
176*f071c501SMasahiro Yamada    for (i = 0; i < 256; i++) s->inUse[i] = False;
177*f071c501SMasahiro Yamada    s->blockNo++;
178*f071c501SMasahiro Yamada }
179*f071c501SMasahiro Yamada 
180*f071c501SMasahiro Yamada 
181*f071c501SMasahiro Yamada /*---------------------------------------------------*/
182*f071c501SMasahiro Yamada static
183*f071c501SMasahiro Yamada void init_RL ( EState* s )
184*f071c501SMasahiro Yamada {
185*f071c501SMasahiro Yamada    s->state_in_ch  = 256;
186*f071c501SMasahiro Yamada    s->state_in_len = 0;
187*f071c501SMasahiro Yamada }
188*f071c501SMasahiro Yamada 
189*f071c501SMasahiro Yamada 
190*f071c501SMasahiro Yamada static
191*f071c501SMasahiro Yamada Bool isempty_RL ( EState* s )
192*f071c501SMasahiro Yamada {
193*f071c501SMasahiro Yamada    if (s->state_in_ch < 256 && s->state_in_len > 0)
194*f071c501SMasahiro Yamada       return False; else
195*f071c501SMasahiro Yamada       return True;
196*f071c501SMasahiro Yamada }
197*f071c501SMasahiro Yamada 
198*f071c501SMasahiro Yamada /*---------------------------------------------------*/
199*f071c501SMasahiro Yamada int BZ_API(BZ2_bzCompressInit)
200*f071c501SMasahiro Yamada 		    ( bz_stream* strm,
201*f071c501SMasahiro Yamada 		     int        blockSize100k,
202*f071c501SMasahiro Yamada 		     int        verbosity,
203*f071c501SMasahiro Yamada 		     int        workFactor )
204*f071c501SMasahiro Yamada {
205*f071c501SMasahiro Yamada    Int32   n;
206*f071c501SMasahiro Yamada    EState* s;
207*f071c501SMasahiro Yamada 
208*f071c501SMasahiro Yamada    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
209*f071c501SMasahiro Yamada 
210*f071c501SMasahiro Yamada    if (strm == NULL ||
211*f071c501SMasahiro Yamada        blockSize100k < 1 || blockSize100k > 9 ||
212*f071c501SMasahiro Yamada        workFactor < 0 || workFactor > 250)
213*f071c501SMasahiro Yamada      return BZ_PARAM_ERROR;
214*f071c501SMasahiro Yamada 
215*f071c501SMasahiro Yamada    if (workFactor == 0) workFactor = 30;
216*f071c501SMasahiro Yamada    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
217*f071c501SMasahiro Yamada    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
218*f071c501SMasahiro Yamada 
219*f071c501SMasahiro Yamada    s = BZALLOC( sizeof(EState) );
220*f071c501SMasahiro Yamada    if (s == NULL) return BZ_MEM_ERROR;
221*f071c501SMasahiro Yamada    s->strm = strm;
222*f071c501SMasahiro Yamada 
223*f071c501SMasahiro Yamada    s->arr1 = NULL;
224*f071c501SMasahiro Yamada    s->arr2 = NULL;
225*f071c501SMasahiro Yamada    s->ftab = NULL;
226*f071c501SMasahiro Yamada 
227*f071c501SMasahiro Yamada    n       = 100000 * blockSize100k;
228*f071c501SMasahiro Yamada    s->arr1 = BZALLOC( n                  * sizeof(UInt32) );
229*f071c501SMasahiro Yamada    s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
230*f071c501SMasahiro Yamada    s->ftab = BZALLOC( 65537              * sizeof(UInt32) );
231*f071c501SMasahiro Yamada 
232*f071c501SMasahiro Yamada    if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
233*f071c501SMasahiro Yamada       if (s->arr1 != NULL) BZFREE(s->arr1);
234*f071c501SMasahiro Yamada       if (s->arr2 != NULL) BZFREE(s->arr2);
235*f071c501SMasahiro Yamada       if (s->ftab != NULL) BZFREE(s->ftab);
236*f071c501SMasahiro Yamada       if (s       != NULL) BZFREE(s);
237*f071c501SMasahiro Yamada       return BZ_MEM_ERROR;
238*f071c501SMasahiro Yamada    }
239*f071c501SMasahiro Yamada 
240*f071c501SMasahiro Yamada    s->blockNo           = 0;
241*f071c501SMasahiro Yamada    s->state             = BZ_S_INPUT;
242*f071c501SMasahiro Yamada    s->mode              = BZ_M_RUNNING;
243*f071c501SMasahiro Yamada    s->combinedCRC       = 0;
244*f071c501SMasahiro Yamada    s->blockSize100k     = blockSize100k;
245*f071c501SMasahiro Yamada    s->nblockMAX         = 100000 * blockSize100k - 19;
246*f071c501SMasahiro Yamada    s->verbosity         = verbosity;
247*f071c501SMasahiro Yamada    s->workFactor        = workFactor;
248*f071c501SMasahiro Yamada 
249*f071c501SMasahiro Yamada    s->block             = (UChar*)s->arr2;
250*f071c501SMasahiro Yamada    s->mtfv              = (UInt16*)s->arr1;
251*f071c501SMasahiro Yamada    s->zbits             = NULL;
252*f071c501SMasahiro Yamada    s->ptr               = (UInt32*)s->arr1;
253*f071c501SMasahiro Yamada 
254*f071c501SMasahiro Yamada    strm->state          = s;
255*f071c501SMasahiro Yamada    strm->total_in_lo32  = 0;
256*f071c501SMasahiro Yamada    strm->total_in_hi32  = 0;
257*f071c501SMasahiro Yamada    strm->total_out_lo32 = 0;
258*f071c501SMasahiro Yamada    strm->total_out_hi32 = 0;
259*f071c501SMasahiro Yamada    init_RL ( s );
260*f071c501SMasahiro Yamada    prepare_new_block ( s );
261*f071c501SMasahiro Yamada    return BZ_OK;
262*f071c501SMasahiro Yamada }
263*f071c501SMasahiro Yamada 
264*f071c501SMasahiro Yamada 
265*f071c501SMasahiro Yamada /*---------------------------------------------------*/
266*f071c501SMasahiro Yamada static
267*f071c501SMasahiro Yamada void add_pair_to_block ( EState* s )
268*f071c501SMasahiro Yamada {
269*f071c501SMasahiro Yamada    Int32 i;
270*f071c501SMasahiro Yamada    UChar ch = (UChar)(s->state_in_ch);
271*f071c501SMasahiro Yamada    for (i = 0; i < s->state_in_len; i++) {
272*f071c501SMasahiro Yamada       BZ_UPDATE_CRC( s->blockCRC, ch );
273*f071c501SMasahiro Yamada    }
274*f071c501SMasahiro Yamada    s->inUse[s->state_in_ch] = True;
275*f071c501SMasahiro Yamada    switch (s->state_in_len) {
276*f071c501SMasahiro Yamada       case 1:
277*f071c501SMasahiro Yamada 	 s->block[s->nblock] = (UChar)ch; s->nblock++;
278*f071c501SMasahiro Yamada 	 break;
279*f071c501SMasahiro Yamada       case 2:
280*f071c501SMasahiro Yamada 	 s->block[s->nblock] = (UChar)ch; s->nblock++;
281*f071c501SMasahiro Yamada 	 s->block[s->nblock] = (UChar)ch; s->nblock++;
282*f071c501SMasahiro Yamada 	 break;
283*f071c501SMasahiro Yamada       case 3:
284*f071c501SMasahiro Yamada 	 s->block[s->nblock] = (UChar)ch; s->nblock++;
285*f071c501SMasahiro Yamada 	 s->block[s->nblock] = (UChar)ch; s->nblock++;
286*f071c501SMasahiro Yamada 	 s->block[s->nblock] = (UChar)ch; s->nblock++;
287*f071c501SMasahiro Yamada 	 break;
288*f071c501SMasahiro Yamada       default:
289*f071c501SMasahiro Yamada 	 s->inUse[s->state_in_len-4] = True;
290*f071c501SMasahiro Yamada 	 s->block[s->nblock] = (UChar)ch; s->nblock++;
291*f071c501SMasahiro Yamada 	 s->block[s->nblock] = (UChar)ch; s->nblock++;
292*f071c501SMasahiro Yamada 	 s->block[s->nblock] = (UChar)ch; s->nblock++;
293*f071c501SMasahiro Yamada 	 s->block[s->nblock] = (UChar)ch; s->nblock++;
294*f071c501SMasahiro Yamada 	 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
295*f071c501SMasahiro Yamada 	 s->nblock++;
296*f071c501SMasahiro Yamada 	 break;
297*f071c501SMasahiro Yamada    }
298*f071c501SMasahiro Yamada }
299*f071c501SMasahiro Yamada 
300*f071c501SMasahiro Yamada 
301*f071c501SMasahiro Yamada /*---------------------------------------------------*/
302*f071c501SMasahiro Yamada static
303*f071c501SMasahiro Yamada void flush_RL ( EState* s )
304*f071c501SMasahiro Yamada {
305*f071c501SMasahiro Yamada    if (s->state_in_ch < 256) add_pair_to_block ( s );
306*f071c501SMasahiro Yamada    init_RL ( s );
307*f071c501SMasahiro Yamada }
308*f071c501SMasahiro Yamada 
309*f071c501SMasahiro Yamada 
310*f071c501SMasahiro Yamada /*---------------------------------------------------*/
311*f071c501SMasahiro Yamada #define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
312*f071c501SMasahiro Yamada {                                                 \
313*f071c501SMasahiro Yamada    UInt32 zchh = (UInt32)(zchh0);                 \
314*f071c501SMasahiro Yamada    /*-- fast track the common case --*/           \
315*f071c501SMasahiro Yamada    if (zchh != zs->state_in_ch &&                 \
316*f071c501SMasahiro Yamada        zs->state_in_len == 1) {                   \
317*f071c501SMasahiro Yamada       UChar ch = (UChar)(zs->state_in_ch);        \
318*f071c501SMasahiro Yamada       BZ_UPDATE_CRC( zs->blockCRC, ch );          \
319*f071c501SMasahiro Yamada       zs->inUse[zs->state_in_ch] = True;          \
320*f071c501SMasahiro Yamada       zs->block[zs->nblock] = (UChar)ch;          \
321*f071c501SMasahiro Yamada       zs->nblock++;                               \
322*f071c501SMasahiro Yamada       zs->state_in_ch = zchh;                     \
323*f071c501SMasahiro Yamada    }                                              \
324*f071c501SMasahiro Yamada    else                                           \
325*f071c501SMasahiro Yamada    /*-- general, uncommon cases --*/              \
326*f071c501SMasahiro Yamada    if (zchh != zs->state_in_ch ||                 \
327*f071c501SMasahiro Yamada       zs->state_in_len == 255) {                  \
328*f071c501SMasahiro Yamada       if (zs->state_in_ch < 256)                  \
329*f071c501SMasahiro Yamada 	 add_pair_to_block ( zs );                \
330*f071c501SMasahiro Yamada       zs->state_in_ch = zchh;                     \
331*f071c501SMasahiro Yamada       zs->state_in_len = 1;                       \
332*f071c501SMasahiro Yamada    } else {                                       \
333*f071c501SMasahiro Yamada       zs->state_in_len++;                         \
334*f071c501SMasahiro Yamada    }                                              \
335*f071c501SMasahiro Yamada }
336*f071c501SMasahiro Yamada 
337*f071c501SMasahiro Yamada 
338*f071c501SMasahiro Yamada /*---------------------------------------------------*/
339*f071c501SMasahiro Yamada static
340*f071c501SMasahiro Yamada Bool copy_input_until_stop ( EState* s )
341*f071c501SMasahiro Yamada {
342*f071c501SMasahiro Yamada    Bool progress_in = False;
343*f071c501SMasahiro Yamada 
344*f071c501SMasahiro Yamada    if (s->mode == BZ_M_RUNNING) {
345*f071c501SMasahiro Yamada 
346*f071c501SMasahiro Yamada       /*-- fast track the common case --*/
347*f071c501SMasahiro Yamada       while (True) {
348*f071c501SMasahiro Yamada 	 /*-- block full? --*/
349*f071c501SMasahiro Yamada 	 if (s->nblock >= s->nblockMAX) break;
350*f071c501SMasahiro Yamada 	 /*-- no input? --*/
351*f071c501SMasahiro Yamada 	 if (s->strm->avail_in == 0) break;
352*f071c501SMasahiro Yamada 	 progress_in = True;
353*f071c501SMasahiro Yamada 	 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
354*f071c501SMasahiro Yamada 	 s->strm->next_in++;
355*f071c501SMasahiro Yamada 	 s->strm->avail_in--;
356*f071c501SMasahiro Yamada 	 s->strm->total_in_lo32++;
357*f071c501SMasahiro Yamada 	 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
358*f071c501SMasahiro Yamada       }
359*f071c501SMasahiro Yamada 
360*f071c501SMasahiro Yamada    } else {
361*f071c501SMasahiro Yamada 
362*f071c501SMasahiro Yamada       /*-- general, uncommon case --*/
363*f071c501SMasahiro Yamada       while (True) {
364*f071c501SMasahiro Yamada 	 /*-- block full? --*/
365*f071c501SMasahiro Yamada 	 if (s->nblock >= s->nblockMAX) break;
366*f071c501SMasahiro Yamada 	 /*-- no input? --*/
367*f071c501SMasahiro Yamada 	 if (s->strm->avail_in == 0) break;
368*f071c501SMasahiro Yamada 	 /*-- flush/finish end? --*/
369*f071c501SMasahiro Yamada 	 if (s->avail_in_expect == 0) break;
370*f071c501SMasahiro Yamada 	 progress_in = True;
371*f071c501SMasahiro Yamada 	 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
372*f071c501SMasahiro Yamada 	 s->strm->next_in++;
373*f071c501SMasahiro Yamada 	 s->strm->avail_in--;
374*f071c501SMasahiro Yamada 	 s->strm->total_in_lo32++;
375*f071c501SMasahiro Yamada 	 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
376*f071c501SMasahiro Yamada 	 s->avail_in_expect--;
377*f071c501SMasahiro Yamada       }
378*f071c501SMasahiro Yamada    }
379*f071c501SMasahiro Yamada    return progress_in;
380*f071c501SMasahiro Yamada }
381*f071c501SMasahiro Yamada 
382*f071c501SMasahiro Yamada 
383*f071c501SMasahiro Yamada /*---------------------------------------------------*/
384*f071c501SMasahiro Yamada static
385*f071c501SMasahiro Yamada Bool copy_output_until_stop ( EState* s )
386*f071c501SMasahiro Yamada {
387*f071c501SMasahiro Yamada    Bool progress_out = False;
388*f071c501SMasahiro Yamada 
389*f071c501SMasahiro Yamada    while (True) {
390*f071c501SMasahiro Yamada 
391*f071c501SMasahiro Yamada       /*-- no output space? --*/
392*f071c501SMasahiro Yamada       if (s->strm->avail_out == 0) break;
393*f071c501SMasahiro Yamada 
394*f071c501SMasahiro Yamada       /*-- block done? --*/
395*f071c501SMasahiro Yamada       if (s->state_out_pos >= s->numZ) break;
396*f071c501SMasahiro Yamada 
397*f071c501SMasahiro Yamada       progress_out = True;
398*f071c501SMasahiro Yamada       *(s->strm->next_out) = s->zbits[s->state_out_pos];
399*f071c501SMasahiro Yamada       s->state_out_pos++;
400*f071c501SMasahiro Yamada       s->strm->avail_out--;
401*f071c501SMasahiro Yamada       s->strm->next_out++;
402*f071c501SMasahiro Yamada       s->strm->total_out_lo32++;
403*f071c501SMasahiro Yamada       if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
404*f071c501SMasahiro Yamada    }
405*f071c501SMasahiro Yamada 
406*f071c501SMasahiro Yamada    return progress_out;
407*f071c501SMasahiro Yamada }
408*f071c501SMasahiro Yamada 
409*f071c501SMasahiro Yamada 
410*f071c501SMasahiro Yamada /*---------------------------------------------------*/
411*f071c501SMasahiro Yamada static
412*f071c501SMasahiro Yamada Bool handle_compress ( bz_stream* strm )
413*f071c501SMasahiro Yamada {
414*f071c501SMasahiro Yamada    Bool progress_in  = False;
415*f071c501SMasahiro Yamada    Bool progress_out = False;
416*f071c501SMasahiro Yamada    EState* s = strm->state;
417*f071c501SMasahiro Yamada 
418*f071c501SMasahiro Yamada    while (True) {
419*f071c501SMasahiro Yamada 
420*f071c501SMasahiro Yamada       if (s->state == BZ_S_OUTPUT) {
421*f071c501SMasahiro Yamada 	 progress_out |= copy_output_until_stop ( s );
422*f071c501SMasahiro Yamada 	 if (s->state_out_pos < s->numZ) break;
423*f071c501SMasahiro Yamada 	 if (s->mode == BZ_M_FINISHING &&
424*f071c501SMasahiro Yamada 	     s->avail_in_expect == 0 &&
425*f071c501SMasahiro Yamada 	     isempty_RL(s)) break;
426*f071c501SMasahiro Yamada 	 prepare_new_block ( s );
427*f071c501SMasahiro Yamada 	 s->state = BZ_S_INPUT;
428*f071c501SMasahiro Yamada 	 if (s->mode == BZ_M_FLUSHING &&
429*f071c501SMasahiro Yamada 	     s->avail_in_expect == 0 &&
430*f071c501SMasahiro Yamada 	     isempty_RL(s)) break;
431*f071c501SMasahiro Yamada       }
432*f071c501SMasahiro Yamada 
433*f071c501SMasahiro Yamada       if (s->state == BZ_S_INPUT) {
434*f071c501SMasahiro Yamada 	 progress_in |= copy_input_until_stop ( s );
435*f071c501SMasahiro Yamada 	 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
436*f071c501SMasahiro Yamada 	    flush_RL ( s );
437*f071c501SMasahiro Yamada 	    BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
438*f071c501SMasahiro Yamada 	    s->state = BZ_S_OUTPUT;
439*f071c501SMasahiro Yamada 	 }
440*f071c501SMasahiro Yamada 	 else
441*f071c501SMasahiro Yamada 	 if (s->nblock >= s->nblockMAX) {
442*f071c501SMasahiro Yamada 	    BZ2_compressBlock ( s, False );
443*f071c501SMasahiro Yamada 	    s->state = BZ_S_OUTPUT;
444*f071c501SMasahiro Yamada 	 }
445*f071c501SMasahiro Yamada 	 else
446*f071c501SMasahiro Yamada 	 if (s->strm->avail_in == 0) {
447*f071c501SMasahiro Yamada 	    break;
448*f071c501SMasahiro Yamada 	 }
449*f071c501SMasahiro Yamada       }
450*f071c501SMasahiro Yamada 
451*f071c501SMasahiro Yamada    }
452*f071c501SMasahiro Yamada 
453*f071c501SMasahiro Yamada    return progress_in || progress_out;
454*f071c501SMasahiro Yamada }
455*f071c501SMasahiro Yamada 
456*f071c501SMasahiro Yamada 
457*f071c501SMasahiro Yamada /*---------------------------------------------------*/
458*f071c501SMasahiro Yamada int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
459*f071c501SMasahiro Yamada {
460*f071c501SMasahiro Yamada    Bool progress;
461*f071c501SMasahiro Yamada    EState* s;
462*f071c501SMasahiro Yamada    if (strm == NULL) return BZ_PARAM_ERROR;
463*f071c501SMasahiro Yamada    s = strm->state;
464*f071c501SMasahiro Yamada    if (s == NULL) return BZ_PARAM_ERROR;
465*f071c501SMasahiro Yamada    if (s->strm != strm) return BZ_PARAM_ERROR;
466*f071c501SMasahiro Yamada 
467*f071c501SMasahiro Yamada    preswitch:
468*f071c501SMasahiro Yamada    switch (s->mode) {
469*f071c501SMasahiro Yamada 
470*f071c501SMasahiro Yamada       case BZ_M_IDLE:
471*f071c501SMasahiro Yamada 	 return BZ_SEQUENCE_ERROR;
472*f071c501SMasahiro Yamada 
473*f071c501SMasahiro Yamada       case BZ_M_RUNNING:
474*f071c501SMasahiro Yamada 	 if (action == BZ_RUN) {
475*f071c501SMasahiro Yamada 	    progress = handle_compress ( strm );
476*f071c501SMasahiro Yamada 	    return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
477*f071c501SMasahiro Yamada 	 }
478*f071c501SMasahiro Yamada 	 else
479*f071c501SMasahiro Yamada 	 if (action == BZ_FLUSH) {
480*f071c501SMasahiro Yamada 	    s->avail_in_expect = strm->avail_in;
481*f071c501SMasahiro Yamada 	    s->mode = BZ_M_FLUSHING;
482*f071c501SMasahiro Yamada 	    goto preswitch;
483*f071c501SMasahiro Yamada 	 }
484*f071c501SMasahiro Yamada 	 else
485*f071c501SMasahiro Yamada 	 if (action == BZ_FINISH) {
486*f071c501SMasahiro Yamada 	    s->avail_in_expect = strm->avail_in;
487*f071c501SMasahiro Yamada 	    s->mode = BZ_M_FINISHING;
488*f071c501SMasahiro Yamada 	    goto preswitch;
489*f071c501SMasahiro Yamada 	 }
490*f071c501SMasahiro Yamada 	 else
491*f071c501SMasahiro Yamada 	    return BZ_PARAM_ERROR;
492*f071c501SMasahiro Yamada 
493*f071c501SMasahiro Yamada       case BZ_M_FLUSHING:
494*f071c501SMasahiro Yamada 	 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
495*f071c501SMasahiro Yamada 	 if (s->avail_in_expect != s->strm->avail_in)
496*f071c501SMasahiro Yamada 	    return BZ_SEQUENCE_ERROR;
497*f071c501SMasahiro Yamada 	 progress = handle_compress ( strm );
498*f071c501SMasahiro Yamada 	 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
499*f071c501SMasahiro Yamada 	     s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
500*f071c501SMasahiro Yamada 	 s->mode = BZ_M_RUNNING;
501*f071c501SMasahiro Yamada 	 return BZ_RUN_OK;
502*f071c501SMasahiro Yamada 
503*f071c501SMasahiro Yamada       case BZ_M_FINISHING:
504*f071c501SMasahiro Yamada 	 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
505*f071c501SMasahiro Yamada 	 if (s->avail_in_expect != s->strm->avail_in)
506*f071c501SMasahiro Yamada 	    return BZ_SEQUENCE_ERROR;
507*f071c501SMasahiro Yamada 	 progress = handle_compress ( strm );
508*f071c501SMasahiro Yamada 	 if (!progress) return BZ_SEQUENCE_ERROR;
509*f071c501SMasahiro Yamada 	 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
510*f071c501SMasahiro Yamada 	     s->state_out_pos < s->numZ) return BZ_FINISH_OK;
511*f071c501SMasahiro Yamada 	 s->mode = BZ_M_IDLE;
512*f071c501SMasahiro Yamada 	 return BZ_STREAM_END;
513*f071c501SMasahiro Yamada    }
514*f071c501SMasahiro Yamada    return BZ_OK; /*--not reached--*/
515*f071c501SMasahiro Yamada }
516*f071c501SMasahiro Yamada 
517*f071c501SMasahiro Yamada 
518*f071c501SMasahiro Yamada /*---------------------------------------------------*/
519*f071c501SMasahiro Yamada int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
520*f071c501SMasahiro Yamada {
521*f071c501SMasahiro Yamada    EState* s;
522*f071c501SMasahiro Yamada    if (strm == NULL) return BZ_PARAM_ERROR;
523*f071c501SMasahiro Yamada    s = strm->state;
524*f071c501SMasahiro Yamada    if (s == NULL) return BZ_PARAM_ERROR;
525*f071c501SMasahiro Yamada    if (s->strm != strm) return BZ_PARAM_ERROR;
526*f071c501SMasahiro Yamada 
527*f071c501SMasahiro Yamada    if (s->arr1 != NULL) BZFREE(s->arr1);
528*f071c501SMasahiro Yamada    if (s->arr2 != NULL) BZFREE(s->arr2);
529*f071c501SMasahiro Yamada    if (s->ftab != NULL) BZFREE(s->ftab);
530*f071c501SMasahiro Yamada    BZFREE(strm->state);
531*f071c501SMasahiro Yamada 
532*f071c501SMasahiro Yamada    strm->state = NULL;
533*f071c501SMasahiro Yamada 
534*f071c501SMasahiro Yamada    return BZ_OK;
535*f071c501SMasahiro Yamada }
536*f071c501SMasahiro Yamada #endif /* BZ_NO_COMPRESS */
537*f071c501SMasahiro Yamada 
538*f071c501SMasahiro Yamada /*---------------------------------------------------*/
539*f071c501SMasahiro Yamada /*--- Decompression stuff                         ---*/
540*f071c501SMasahiro Yamada /*---------------------------------------------------*/
541*f071c501SMasahiro Yamada 
542*f071c501SMasahiro Yamada /*---------------------------------------------------*/
543*f071c501SMasahiro Yamada int BZ_API(BZ2_bzDecompressInit)
544*f071c501SMasahiro Yamada 		     ( bz_stream* strm,
545*f071c501SMasahiro Yamada 		       int        verbosity,
546*f071c501SMasahiro Yamada 		       int        small )
547*f071c501SMasahiro Yamada {
548*f071c501SMasahiro Yamada    DState* s;
549*f071c501SMasahiro Yamada 
550*f071c501SMasahiro Yamada    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
551*f071c501SMasahiro Yamada 
552*f071c501SMasahiro Yamada    if (strm == NULL) return BZ_PARAM_ERROR;
553*f071c501SMasahiro Yamada    if (small != 0 && small != 1) return BZ_PARAM_ERROR;
554*f071c501SMasahiro Yamada    if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
555*f071c501SMasahiro Yamada 
556*f071c501SMasahiro Yamada    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
557*f071c501SMasahiro Yamada    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
558*f071c501SMasahiro Yamada 
559*f071c501SMasahiro Yamada    s = BZALLOC( sizeof(DState) );
560*f071c501SMasahiro Yamada    if (s == NULL) return BZ_MEM_ERROR;
561*f071c501SMasahiro Yamada    s->strm                  = strm;
562*f071c501SMasahiro Yamada    strm->state              = s;
563*f071c501SMasahiro Yamada    s->state                 = BZ_X_MAGIC_1;
564*f071c501SMasahiro Yamada    s->bsLive                = 0;
565*f071c501SMasahiro Yamada    s->bsBuff                = 0;
566*f071c501SMasahiro Yamada    s->calculatedCombinedCRC = 0;
567*f071c501SMasahiro Yamada    strm->total_in_lo32      = 0;
568*f071c501SMasahiro Yamada    strm->total_in_hi32      = 0;
569*f071c501SMasahiro Yamada    strm->total_out_lo32     = 0;
570*f071c501SMasahiro Yamada    strm->total_out_hi32     = 0;
571*f071c501SMasahiro Yamada    s->smallDecompress       = (Bool)small;
572*f071c501SMasahiro Yamada    s->ll4                   = NULL;
573*f071c501SMasahiro Yamada    s->ll16                  = NULL;
574*f071c501SMasahiro Yamada    s->tt                    = NULL;
575*f071c501SMasahiro Yamada    s->currBlockNo           = 0;
576*f071c501SMasahiro Yamada    s->verbosity             = verbosity;
577*f071c501SMasahiro Yamada 
578*f071c501SMasahiro Yamada    return BZ_OK;
579*f071c501SMasahiro Yamada }
580*f071c501SMasahiro Yamada 
581*f071c501SMasahiro Yamada 
582*f071c501SMasahiro Yamada /*---------------------------------------------------*/
583*f071c501SMasahiro Yamada static
584*f071c501SMasahiro Yamada void unRLE_obuf_to_output_FAST ( DState* s )
585*f071c501SMasahiro Yamada {
586*f071c501SMasahiro Yamada    UChar k1;
587*f071c501SMasahiro Yamada 
588*f071c501SMasahiro Yamada    if (s->blockRandomised) {
589*f071c501SMasahiro Yamada 
590*f071c501SMasahiro Yamada       while (True) {
591*f071c501SMasahiro Yamada 	 /* try to finish existing run */
592*f071c501SMasahiro Yamada 	 while (True) {
593*f071c501SMasahiro Yamada 	    if (s->strm->avail_out == 0) return;
594*f071c501SMasahiro Yamada 	    if (s->state_out_len == 0) break;
595*f071c501SMasahiro Yamada 	    *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
596*f071c501SMasahiro Yamada 	    BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
597*f071c501SMasahiro Yamada 	    s->state_out_len--;
598*f071c501SMasahiro Yamada 	    s->strm->next_out++;
599*f071c501SMasahiro Yamada 	    s->strm->avail_out--;
600*f071c501SMasahiro Yamada 	    s->strm->total_out_lo32++;
601*f071c501SMasahiro Yamada 	    if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
602*f071c501SMasahiro Yamada 	 }
603*f071c501SMasahiro Yamada 
604*f071c501SMasahiro Yamada 	 /* can a new run be started? */
605*f071c501SMasahiro Yamada 	 if (s->nblock_used == s->save_nblock+1) return;
606*f071c501SMasahiro Yamada 
607*f071c501SMasahiro Yamada 
608*f071c501SMasahiro Yamada 	 s->state_out_len = 1;
609*f071c501SMasahiro Yamada 	 s->state_out_ch = s->k0;
610*f071c501SMasahiro Yamada 	 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
611*f071c501SMasahiro Yamada 	 k1 ^= BZ_RAND_MASK; s->nblock_used++;
612*f071c501SMasahiro Yamada 	 if (s->nblock_used == s->save_nblock+1) continue;
613*f071c501SMasahiro Yamada 	 if (k1 != s->k0) { s->k0 = k1; continue; };
614*f071c501SMasahiro Yamada 
615*f071c501SMasahiro Yamada 	 s->state_out_len = 2;
616*f071c501SMasahiro Yamada 	 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
617*f071c501SMasahiro Yamada 	 k1 ^= BZ_RAND_MASK; s->nblock_used++;
618*f071c501SMasahiro Yamada 	 if (s->nblock_used == s->save_nblock+1) continue;
619*f071c501SMasahiro Yamada 	 if (k1 != s->k0) { s->k0 = k1; continue; };
620*f071c501SMasahiro Yamada 
621*f071c501SMasahiro Yamada 	 s->state_out_len = 3;
622*f071c501SMasahiro Yamada 	 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
623*f071c501SMasahiro Yamada 	 k1 ^= BZ_RAND_MASK; s->nblock_used++;
624*f071c501SMasahiro Yamada 	 if (s->nblock_used == s->save_nblock+1) continue;
625*f071c501SMasahiro Yamada 	 if (k1 != s->k0) { s->k0 = k1; continue; };
626*f071c501SMasahiro Yamada 
627*f071c501SMasahiro Yamada 	 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
628*f071c501SMasahiro Yamada 	 k1 ^= BZ_RAND_MASK; s->nblock_used++;
629*f071c501SMasahiro Yamada 	 s->state_out_len = ((Int32)k1) + 4;
630*f071c501SMasahiro Yamada 	 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
631*f071c501SMasahiro Yamada 	 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
632*f071c501SMasahiro Yamada       }
633*f071c501SMasahiro Yamada 
634*f071c501SMasahiro Yamada    } else {
635*f071c501SMasahiro Yamada 
636*f071c501SMasahiro Yamada       /* restore */
637*f071c501SMasahiro Yamada       UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC;
638*f071c501SMasahiro Yamada       UChar         c_state_out_ch       = s->state_out_ch;
639*f071c501SMasahiro Yamada       Int32         c_state_out_len      = s->state_out_len;
640*f071c501SMasahiro Yamada       Int32         c_nblock_used        = s->nblock_used;
641*f071c501SMasahiro Yamada       Int32         c_k0                 = s->k0;
642*f071c501SMasahiro Yamada       UInt32*       c_tt                 = s->tt;
643*f071c501SMasahiro Yamada       UInt32        c_tPos               = s->tPos;
644*f071c501SMasahiro Yamada       char*         cs_next_out          = s->strm->next_out;
645*f071c501SMasahiro Yamada       unsigned int  cs_avail_out         = s->strm->avail_out;
646*f071c501SMasahiro Yamada       /* end restore */
647*f071c501SMasahiro Yamada 
648*f071c501SMasahiro Yamada       UInt32       avail_out_INIT = cs_avail_out;
649*f071c501SMasahiro Yamada       Int32        s_save_nblockPP = s->save_nblock+1;
650*f071c501SMasahiro Yamada       unsigned int total_out_lo32_old;
651*f071c501SMasahiro Yamada 
652*f071c501SMasahiro Yamada       while (True) {
653*f071c501SMasahiro Yamada 
654*f071c501SMasahiro Yamada 	 /* try to finish existing run */
655*f071c501SMasahiro Yamada 	 if (c_state_out_len > 0) {
656*f071c501SMasahiro Yamada 	    while (True) {
657*f071c501SMasahiro Yamada 	       if (cs_avail_out == 0) goto return_notr;
658*f071c501SMasahiro Yamada 	       if (c_state_out_len == 1) break;
659*f071c501SMasahiro Yamada 	       *( (UChar*)(cs_next_out) ) = c_state_out_ch;
660*f071c501SMasahiro Yamada 	       BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
661*f071c501SMasahiro Yamada 	       c_state_out_len--;
662*f071c501SMasahiro Yamada 	       cs_next_out++;
663*f071c501SMasahiro Yamada 	       cs_avail_out--;
664*f071c501SMasahiro Yamada 	    }
665*f071c501SMasahiro Yamada 	    s_state_out_len_eq_one:
666*f071c501SMasahiro Yamada 	    {
667*f071c501SMasahiro Yamada 	       if (cs_avail_out == 0) {
668*f071c501SMasahiro Yamada 		  c_state_out_len = 1; goto return_notr;
669*f071c501SMasahiro Yamada 	       };
670*f071c501SMasahiro Yamada 	       *( (UChar*)(cs_next_out) ) = c_state_out_ch;
671*f071c501SMasahiro Yamada 	       BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
672*f071c501SMasahiro Yamada 	       cs_next_out++;
673*f071c501SMasahiro Yamada 	       cs_avail_out--;
674*f071c501SMasahiro Yamada 	    }
675*f071c501SMasahiro Yamada 	 }
676*f071c501SMasahiro Yamada 	 /* can a new run be started? */
677*f071c501SMasahiro Yamada 	 if (c_nblock_used == s_save_nblockPP) {
678*f071c501SMasahiro Yamada 	    c_state_out_len = 0; goto return_notr;
679*f071c501SMasahiro Yamada 	 };
680*f071c501SMasahiro Yamada 	 c_state_out_ch = c_k0;
681*f071c501SMasahiro Yamada 	 BZ_GET_FAST_C(k1); c_nblock_used++;
682*f071c501SMasahiro Yamada 	 if (k1 != c_k0) {
683*f071c501SMasahiro Yamada 	    c_k0 = k1; goto s_state_out_len_eq_one;
684*f071c501SMasahiro Yamada 	 };
685*f071c501SMasahiro Yamada 	 if (c_nblock_used == s_save_nblockPP)
686*f071c501SMasahiro Yamada 	    goto s_state_out_len_eq_one;
687*f071c501SMasahiro Yamada 
688*f071c501SMasahiro Yamada 	 c_state_out_len = 2;
689*f071c501SMasahiro Yamada 	 BZ_GET_FAST_C(k1); c_nblock_used++;
690*f071c501SMasahiro Yamada 	 if (c_nblock_used == s_save_nblockPP) continue;
691*f071c501SMasahiro Yamada 	 if (k1 != c_k0) { c_k0 = k1; continue; };
692*f071c501SMasahiro Yamada 
693*f071c501SMasahiro Yamada 	 c_state_out_len = 3;
694*f071c501SMasahiro Yamada 	 BZ_GET_FAST_C(k1); c_nblock_used++;
695*f071c501SMasahiro Yamada 	 if (c_nblock_used == s_save_nblockPP) continue;
696*f071c501SMasahiro Yamada 	 if (k1 != c_k0) { c_k0 = k1; continue; };
697*f071c501SMasahiro Yamada 
698*f071c501SMasahiro Yamada 	 BZ_GET_FAST_C(k1); c_nblock_used++;
699*f071c501SMasahiro Yamada 	 c_state_out_len = ((Int32)k1) + 4;
700*f071c501SMasahiro Yamada 	 BZ_GET_FAST_C(c_k0); c_nblock_used++;
701*f071c501SMasahiro Yamada       }
702*f071c501SMasahiro Yamada 
703*f071c501SMasahiro Yamada       return_notr:
704*f071c501SMasahiro Yamada       total_out_lo32_old = s->strm->total_out_lo32;
705*f071c501SMasahiro Yamada       s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
706*f071c501SMasahiro Yamada       if (s->strm->total_out_lo32 < total_out_lo32_old)
707*f071c501SMasahiro Yamada 	 s->strm->total_out_hi32++;
708*f071c501SMasahiro Yamada 
709*f071c501SMasahiro Yamada       /* save */
710*f071c501SMasahiro Yamada       s->calculatedBlockCRC = c_calculatedBlockCRC;
711*f071c501SMasahiro Yamada       s->state_out_ch       = c_state_out_ch;
712*f071c501SMasahiro Yamada       s->state_out_len      = c_state_out_len;
713*f071c501SMasahiro Yamada       s->nblock_used        = c_nblock_used;
714*f071c501SMasahiro Yamada       s->k0                 = c_k0;
715*f071c501SMasahiro Yamada       s->tt                 = c_tt;
716*f071c501SMasahiro Yamada       s->tPos               = c_tPos;
717*f071c501SMasahiro Yamada       s->strm->next_out     = cs_next_out;
718*f071c501SMasahiro Yamada       s->strm->avail_out    = cs_avail_out;
719*f071c501SMasahiro Yamada       /* end save */
720*f071c501SMasahiro Yamada    }
721*f071c501SMasahiro Yamada }
722*f071c501SMasahiro Yamada 
723*f071c501SMasahiro Yamada 
724*f071c501SMasahiro Yamada /*---------------------------------------------------*/
725*f071c501SMasahiro Yamada __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
726*f071c501SMasahiro Yamada {
727*f071c501SMasahiro Yamada    Int32 nb, na, mid;
728*f071c501SMasahiro Yamada    nb = 0;
729*f071c501SMasahiro Yamada    na = 256;
730*f071c501SMasahiro Yamada    do {
731*f071c501SMasahiro Yamada       mid = (nb + na) >> 1;
732*f071c501SMasahiro Yamada       if (indx >= cftab[mid]) nb = mid; else na = mid;
733*f071c501SMasahiro Yamada    }
734*f071c501SMasahiro Yamada    while (na - nb != 1);
735*f071c501SMasahiro Yamada    return nb;
736*f071c501SMasahiro Yamada }
737*f071c501SMasahiro Yamada 
738*f071c501SMasahiro Yamada 
739*f071c501SMasahiro Yamada /*---------------------------------------------------*/
740*f071c501SMasahiro Yamada static
741*f071c501SMasahiro Yamada void unRLE_obuf_to_output_SMALL ( DState* s )
742*f071c501SMasahiro Yamada {
743*f071c501SMasahiro Yamada    UChar k1;
744*f071c501SMasahiro Yamada 
745*f071c501SMasahiro Yamada    if (s->blockRandomised) {
746*f071c501SMasahiro Yamada 
747*f071c501SMasahiro Yamada       while (True) {
748*f071c501SMasahiro Yamada 	 /* try to finish existing run */
749*f071c501SMasahiro Yamada 	 while (True) {
750*f071c501SMasahiro Yamada 	    if (s->strm->avail_out == 0) return;
751*f071c501SMasahiro Yamada 	    if (s->state_out_len == 0) break;
752*f071c501SMasahiro Yamada 	    *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
753*f071c501SMasahiro Yamada 	    BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
754*f071c501SMasahiro Yamada 	    s->state_out_len--;
755*f071c501SMasahiro Yamada 	    s->strm->next_out++;
756*f071c501SMasahiro Yamada 	    s->strm->avail_out--;
757*f071c501SMasahiro Yamada 	    s->strm->total_out_lo32++;
758*f071c501SMasahiro Yamada 	    if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
759*f071c501SMasahiro Yamada 	 }
760*f071c501SMasahiro Yamada 
761*f071c501SMasahiro Yamada 	 /* can a new run be started? */
762*f071c501SMasahiro Yamada 	 if (s->nblock_used == s->save_nblock+1) return;
763*f071c501SMasahiro Yamada 
764*f071c501SMasahiro Yamada 
765*f071c501SMasahiro Yamada 	 s->state_out_len = 1;
766*f071c501SMasahiro Yamada 	 s->state_out_ch = s->k0;
767*f071c501SMasahiro Yamada 	 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
768*f071c501SMasahiro Yamada 	 k1 ^= BZ_RAND_MASK; s->nblock_used++;
769*f071c501SMasahiro Yamada 	 if (s->nblock_used == s->save_nblock+1) continue;
770*f071c501SMasahiro Yamada 	 if (k1 != s->k0) { s->k0 = k1; continue; };
771*f071c501SMasahiro Yamada 
772*f071c501SMasahiro Yamada 	 s->state_out_len = 2;
773*f071c501SMasahiro Yamada 	 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
774*f071c501SMasahiro Yamada 	 k1 ^= BZ_RAND_MASK; s->nblock_used++;
775*f071c501SMasahiro Yamada 	 if (s->nblock_used == s->save_nblock+1) continue;
776*f071c501SMasahiro Yamada 	 if (k1 != s->k0) { s->k0 = k1; continue; };
777*f071c501SMasahiro Yamada 
778*f071c501SMasahiro Yamada 	 s->state_out_len = 3;
779*f071c501SMasahiro Yamada 	 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
780*f071c501SMasahiro Yamada 	 k1 ^= BZ_RAND_MASK; s->nblock_used++;
781*f071c501SMasahiro Yamada 	 if (s->nblock_used == s->save_nblock+1) continue;
782*f071c501SMasahiro Yamada 	 if (k1 != s->k0) { s->k0 = k1; continue; };
783*f071c501SMasahiro Yamada 
784*f071c501SMasahiro Yamada 	 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
785*f071c501SMasahiro Yamada 	 k1 ^= BZ_RAND_MASK; s->nblock_used++;
786*f071c501SMasahiro Yamada 	 s->state_out_len = ((Int32)k1) + 4;
787*f071c501SMasahiro Yamada 	 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
788*f071c501SMasahiro Yamada 	 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
789*f071c501SMasahiro Yamada       }
790*f071c501SMasahiro Yamada 
791*f071c501SMasahiro Yamada    } else {
792*f071c501SMasahiro Yamada 
793*f071c501SMasahiro Yamada       while (True) {
794*f071c501SMasahiro Yamada 	 /* try to finish existing run */
795*f071c501SMasahiro Yamada 	 while (True) {
796*f071c501SMasahiro Yamada 	    if (s->strm->avail_out == 0) return;
797*f071c501SMasahiro Yamada 	    if (s->state_out_len == 0) break;
798*f071c501SMasahiro Yamada 	    *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
799*f071c501SMasahiro Yamada 	    BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
800*f071c501SMasahiro Yamada 	    s->state_out_len--;
801*f071c501SMasahiro Yamada 	    s->strm->next_out++;
802*f071c501SMasahiro Yamada 	    s->strm->avail_out--;
803*f071c501SMasahiro Yamada 	    s->strm->total_out_lo32++;
804*f071c501SMasahiro Yamada 	    if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
805*f071c501SMasahiro Yamada 	 }
806*f071c501SMasahiro Yamada 
807*f071c501SMasahiro Yamada 	 /* can a new run be started? */
808*f071c501SMasahiro Yamada 	 if (s->nblock_used == s->save_nblock+1) return;
809*f071c501SMasahiro Yamada 
810*f071c501SMasahiro Yamada 	 s->state_out_len = 1;
811*f071c501SMasahiro Yamada 	 s->state_out_ch = s->k0;
812*f071c501SMasahiro Yamada 	 BZ_GET_SMALL(k1); s->nblock_used++;
813*f071c501SMasahiro Yamada 	 if (s->nblock_used == s->save_nblock+1) continue;
814*f071c501SMasahiro Yamada 	 if (k1 != s->k0) { s->k0 = k1; continue; };
815*f071c501SMasahiro Yamada 
816*f071c501SMasahiro Yamada 	 s->state_out_len = 2;
817*f071c501SMasahiro Yamada 	 BZ_GET_SMALL(k1); s->nblock_used++;
818*f071c501SMasahiro Yamada 	 if (s->nblock_used == s->save_nblock+1) continue;
819*f071c501SMasahiro Yamada 	 if (k1 != s->k0) { s->k0 = k1; continue; };
820*f071c501SMasahiro Yamada 
821*f071c501SMasahiro Yamada 	 s->state_out_len = 3;
822*f071c501SMasahiro Yamada 	 BZ_GET_SMALL(k1); s->nblock_used++;
823*f071c501SMasahiro Yamada 	 if (s->nblock_used == s->save_nblock+1) continue;
824*f071c501SMasahiro Yamada 	 if (k1 != s->k0) { s->k0 = k1; continue; };
825*f071c501SMasahiro Yamada 
826*f071c501SMasahiro Yamada 	 BZ_GET_SMALL(k1); s->nblock_used++;
827*f071c501SMasahiro Yamada 	 s->state_out_len = ((Int32)k1) + 4;
828*f071c501SMasahiro Yamada 	 BZ_GET_SMALL(s->k0); s->nblock_used++;
829*f071c501SMasahiro Yamada       }
830*f071c501SMasahiro Yamada 
831*f071c501SMasahiro Yamada    }
832*f071c501SMasahiro Yamada }
833*f071c501SMasahiro Yamada 
834*f071c501SMasahiro Yamada 
835*f071c501SMasahiro Yamada /*---------------------------------------------------*/
836*f071c501SMasahiro Yamada int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
837*f071c501SMasahiro Yamada {
838*f071c501SMasahiro Yamada    DState* s;
839*f071c501SMasahiro Yamada    if (strm == NULL) return BZ_PARAM_ERROR;
840*f071c501SMasahiro Yamada    s = strm->state;
841*f071c501SMasahiro Yamada    if (s == NULL) return BZ_PARAM_ERROR;
842*f071c501SMasahiro Yamada    if (s->strm != strm) return BZ_PARAM_ERROR;
843*f071c501SMasahiro Yamada 
844*f071c501SMasahiro Yamada    while (True) {
845*f071c501SMasahiro Yamada #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
846*f071c501SMasahiro Yamada 	WATCHDOG_RESET();
847*f071c501SMasahiro Yamada #endif
848*f071c501SMasahiro Yamada       if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
849*f071c501SMasahiro Yamada       if (s->state == BZ_X_OUTPUT) {
850*f071c501SMasahiro Yamada 	 if (s->smallDecompress)
851*f071c501SMasahiro Yamada 	    unRLE_obuf_to_output_SMALL ( s ); else
852*f071c501SMasahiro Yamada 	    unRLE_obuf_to_output_FAST  ( s );
853*f071c501SMasahiro Yamada 	 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
854*f071c501SMasahiro Yamada 	    BZ_FINALISE_CRC ( s->calculatedBlockCRC );
855*f071c501SMasahiro Yamada 	    if (s->verbosity >= 3)
856*f071c501SMasahiro Yamada 	       VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC,
857*f071c501SMasahiro Yamada 			  s->calculatedBlockCRC );
858*f071c501SMasahiro Yamada 	    if (s->verbosity >= 2) VPrintf0 ( "]" );
859*f071c501SMasahiro Yamada 	    if (s->calculatedBlockCRC != s->storedBlockCRC)
860*f071c501SMasahiro Yamada 	       return BZ_DATA_ERROR;
861*f071c501SMasahiro Yamada 	    s->calculatedCombinedCRC
862*f071c501SMasahiro Yamada 	       = (s->calculatedCombinedCRC << 1) |
863*f071c501SMasahiro Yamada 		    (s->calculatedCombinedCRC >> 31);
864*f071c501SMasahiro Yamada 	    s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
865*f071c501SMasahiro Yamada 	    s->state = BZ_X_BLKHDR_1;
866*f071c501SMasahiro Yamada 	 } else {
867*f071c501SMasahiro Yamada 	    return BZ_OK;
868*f071c501SMasahiro Yamada 	 }
869*f071c501SMasahiro Yamada       }
870*f071c501SMasahiro Yamada       if (s->state >= BZ_X_MAGIC_1) {
871*f071c501SMasahiro Yamada 	 Int32 r = BZ2_decompress ( s );
872*f071c501SMasahiro Yamada 	 if (r == BZ_STREAM_END) {
873*f071c501SMasahiro Yamada 	    if (s->verbosity >= 3)
874*f071c501SMasahiro Yamada 	       VPrintf2 ( "\n    combined CRCs: stored = 0x%x, computed = 0x%x",
875*f071c501SMasahiro Yamada 			  s->storedCombinedCRC, s->calculatedCombinedCRC );
876*f071c501SMasahiro Yamada 	    if (s->calculatedCombinedCRC != s->storedCombinedCRC)
877*f071c501SMasahiro Yamada 	       return BZ_DATA_ERROR;
878*f071c501SMasahiro Yamada 	    return r;
879*f071c501SMasahiro Yamada 	 }
880*f071c501SMasahiro Yamada 	 if (s->state != BZ_X_OUTPUT) return r;
881*f071c501SMasahiro Yamada       }
882*f071c501SMasahiro Yamada    }
883*f071c501SMasahiro Yamada 
884*f071c501SMasahiro Yamada    AssertH ( 0, 6001 );
885*f071c501SMasahiro Yamada 
886*f071c501SMasahiro Yamada    return 0;  /*NOTREACHED*/
887*f071c501SMasahiro Yamada }
888*f071c501SMasahiro Yamada 
889*f071c501SMasahiro Yamada 
890*f071c501SMasahiro Yamada /*---------------------------------------------------*/
891*f071c501SMasahiro Yamada int BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm )
892*f071c501SMasahiro Yamada {
893*f071c501SMasahiro Yamada    DState* s;
894*f071c501SMasahiro Yamada    if (strm == NULL) return BZ_PARAM_ERROR;
895*f071c501SMasahiro Yamada    s = strm->state;
896*f071c501SMasahiro Yamada    if (s == NULL) return BZ_PARAM_ERROR;
897*f071c501SMasahiro Yamada    if (s->strm != strm) return BZ_PARAM_ERROR;
898*f071c501SMasahiro Yamada 
899*f071c501SMasahiro Yamada    if (s->tt   != NULL) BZFREE(s->tt);
900*f071c501SMasahiro Yamada    if (s->ll16 != NULL) BZFREE(s->ll16);
901*f071c501SMasahiro Yamada    if (s->ll4  != NULL) BZFREE(s->ll4);
902*f071c501SMasahiro Yamada 
903*f071c501SMasahiro Yamada    BZFREE(strm->state);
904*f071c501SMasahiro Yamada    strm->state = NULL;
905*f071c501SMasahiro Yamada 
906*f071c501SMasahiro Yamada    return BZ_OK;
907*f071c501SMasahiro Yamada }
908*f071c501SMasahiro Yamada 
909*f071c501SMasahiro Yamada 
910*f071c501SMasahiro Yamada #ifndef BZ_NO_STDIO
911*f071c501SMasahiro Yamada /*---------------------------------------------------*/
912*f071c501SMasahiro Yamada /*--- File I/O stuff                              ---*/
913*f071c501SMasahiro Yamada /*---------------------------------------------------*/
914*f071c501SMasahiro Yamada 
915*f071c501SMasahiro Yamada #define BZ_SETERR(eee)                    \
916*f071c501SMasahiro Yamada {                                         \
917*f071c501SMasahiro Yamada    if (bzerror != NULL) *bzerror = eee;   \
918*f071c501SMasahiro Yamada    if (bzf != NULL) bzf->lastErr = eee;   \
919*f071c501SMasahiro Yamada }
920*f071c501SMasahiro Yamada 
921*f071c501SMasahiro Yamada typedef
922*f071c501SMasahiro Yamada    struct {
923*f071c501SMasahiro Yamada       FILE*     handle;
924*f071c501SMasahiro Yamada       Char      buf[BZ_MAX_UNUSED];
925*f071c501SMasahiro Yamada       Int32     bufN;
926*f071c501SMasahiro Yamada       Bool      writing;
927*f071c501SMasahiro Yamada       bz_stream strm;
928*f071c501SMasahiro Yamada       Int32     lastErr;
929*f071c501SMasahiro Yamada       Bool      initialisedOk;
930*f071c501SMasahiro Yamada    }
931*f071c501SMasahiro Yamada    bzFile;
932*f071c501SMasahiro Yamada 
933*f071c501SMasahiro Yamada 
934*f071c501SMasahiro Yamada /*---------------------------------------------*/
935*f071c501SMasahiro Yamada static Bool myfeof ( FILE* f )
936*f071c501SMasahiro Yamada {
937*f071c501SMasahiro Yamada    Int32 c = fgetc ( f );
938*f071c501SMasahiro Yamada    if (c == EOF) return True;
939*f071c501SMasahiro Yamada    ungetc ( c, f );
940*f071c501SMasahiro Yamada    return False;
941*f071c501SMasahiro Yamada }
942*f071c501SMasahiro Yamada 
943*f071c501SMasahiro Yamada 
944*f071c501SMasahiro Yamada /*---------------------------------------------------*/
945*f071c501SMasahiro Yamada BZFILE* BZ_API(BZ2_bzWriteOpen)
946*f071c501SMasahiro Yamada 		    ( int*  bzerror,
947*f071c501SMasahiro Yamada 		      FILE* f,
948*f071c501SMasahiro Yamada 		      int   blockSize100k,
949*f071c501SMasahiro Yamada 		      int   verbosity,
950*f071c501SMasahiro Yamada 		      int   workFactor )
951*f071c501SMasahiro Yamada {
952*f071c501SMasahiro Yamada    Int32   ret;
953*f071c501SMasahiro Yamada    bzFile* bzf = NULL;
954*f071c501SMasahiro Yamada 
955*f071c501SMasahiro Yamada    BZ_SETERR(BZ_OK);
956*f071c501SMasahiro Yamada 
957*f071c501SMasahiro Yamada    if (f == NULL ||
958*f071c501SMasahiro Yamada        (blockSize100k < 1 || blockSize100k > 9) ||
959*f071c501SMasahiro Yamada        (workFactor < 0 || workFactor > 250) ||
960*f071c501SMasahiro Yamada        (verbosity < 0 || verbosity > 4))
961*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
962*f071c501SMasahiro Yamada 
963*f071c501SMasahiro Yamada    if (ferror(f))
964*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
965*f071c501SMasahiro Yamada 
966*f071c501SMasahiro Yamada    bzf = malloc ( sizeof(bzFile) );
967*f071c501SMasahiro Yamada    if (bzf == NULL)
968*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
969*f071c501SMasahiro Yamada 
970*f071c501SMasahiro Yamada    BZ_SETERR(BZ_OK);
971*f071c501SMasahiro Yamada    bzf->initialisedOk = False;
972*f071c501SMasahiro Yamada    bzf->bufN          = 0;
973*f071c501SMasahiro Yamada    bzf->handle        = f;
974*f071c501SMasahiro Yamada    bzf->writing       = True;
975*f071c501SMasahiro Yamada    bzf->strm.bzalloc  = NULL;
976*f071c501SMasahiro Yamada    bzf->strm.bzfree   = NULL;
977*f071c501SMasahiro Yamada    bzf->strm.opaque   = NULL;
978*f071c501SMasahiro Yamada 
979*f071c501SMasahiro Yamada    if (workFactor == 0) workFactor = 30;
980*f071c501SMasahiro Yamada    ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
981*f071c501SMasahiro Yamada 			      verbosity, workFactor );
982*f071c501SMasahiro Yamada    if (ret != BZ_OK)
983*f071c501SMasahiro Yamada       { BZ_SETERR(ret); free(bzf); return NULL; };
984*f071c501SMasahiro Yamada 
985*f071c501SMasahiro Yamada    bzf->strm.avail_in = 0;
986*f071c501SMasahiro Yamada    bzf->initialisedOk = True;
987*f071c501SMasahiro Yamada    return bzf;
988*f071c501SMasahiro Yamada }
989*f071c501SMasahiro Yamada 
990*f071c501SMasahiro Yamada 
991*f071c501SMasahiro Yamada /*---------------------------------------------------*/
992*f071c501SMasahiro Yamada void BZ_API(BZ2_bzWrite)
993*f071c501SMasahiro Yamada 	     ( int*    bzerror,
994*f071c501SMasahiro Yamada 	       BZFILE* b,
995*f071c501SMasahiro Yamada 	       void*   buf,
996*f071c501SMasahiro Yamada 	       int     len )
997*f071c501SMasahiro Yamada {
998*f071c501SMasahiro Yamada    Int32 n, n2, ret;
999*f071c501SMasahiro Yamada    bzFile* bzf = (bzFile*)b;
1000*f071c501SMasahiro Yamada 
1001*f071c501SMasahiro Yamada    BZ_SETERR(BZ_OK);
1002*f071c501SMasahiro Yamada    if (bzf == NULL || buf == NULL || len < 0)
1003*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_PARAM_ERROR); return; };
1004*f071c501SMasahiro Yamada    if (!(bzf->writing))
1005*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1006*f071c501SMasahiro Yamada    if (ferror(bzf->handle))
1007*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_IO_ERROR); return; };
1008*f071c501SMasahiro Yamada 
1009*f071c501SMasahiro Yamada    if (len == 0)
1010*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_OK); return; };
1011*f071c501SMasahiro Yamada 
1012*f071c501SMasahiro Yamada    bzf->strm.avail_in = len;
1013*f071c501SMasahiro Yamada    bzf->strm.next_in  = buf;
1014*f071c501SMasahiro Yamada 
1015*f071c501SMasahiro Yamada    while (True) {
1016*f071c501SMasahiro Yamada       bzf->strm.avail_out = BZ_MAX_UNUSED;
1017*f071c501SMasahiro Yamada       bzf->strm.next_out = bzf->buf;
1018*f071c501SMasahiro Yamada       ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
1019*f071c501SMasahiro Yamada       if (ret != BZ_RUN_OK)
1020*f071c501SMasahiro Yamada 	 { BZ_SETERR(ret); return; };
1021*f071c501SMasahiro Yamada 
1022*f071c501SMasahiro Yamada       if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1023*f071c501SMasahiro Yamada 	 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1024*f071c501SMasahiro Yamada 	 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1025*f071c501SMasahiro Yamada 		       n, bzf->handle );
1026*f071c501SMasahiro Yamada 	 if (n != n2 || ferror(bzf->handle))
1027*f071c501SMasahiro Yamada 	    { BZ_SETERR(BZ_IO_ERROR); return; };
1028*f071c501SMasahiro Yamada       }
1029*f071c501SMasahiro Yamada 
1030*f071c501SMasahiro Yamada       if (bzf->strm.avail_in == 0)
1031*f071c501SMasahiro Yamada 	 { BZ_SETERR(BZ_OK); return; };
1032*f071c501SMasahiro Yamada    }
1033*f071c501SMasahiro Yamada }
1034*f071c501SMasahiro Yamada 
1035*f071c501SMasahiro Yamada 
1036*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1037*f071c501SMasahiro Yamada void BZ_API(BZ2_bzWriteClose)
1038*f071c501SMasahiro Yamada 		  ( int*          bzerror,
1039*f071c501SMasahiro Yamada 		    BZFILE*       b,
1040*f071c501SMasahiro Yamada 		    int           abandon,
1041*f071c501SMasahiro Yamada 		    unsigned int* nbytes_in,
1042*f071c501SMasahiro Yamada 		    unsigned int* nbytes_out )
1043*f071c501SMasahiro Yamada {
1044*f071c501SMasahiro Yamada    BZ2_bzWriteClose64 ( bzerror, b, abandon,
1045*f071c501SMasahiro Yamada 			nbytes_in, NULL, nbytes_out, NULL );
1046*f071c501SMasahiro Yamada }
1047*f071c501SMasahiro Yamada 
1048*f071c501SMasahiro Yamada 
1049*f071c501SMasahiro Yamada void BZ_API(BZ2_bzWriteClose64)
1050*f071c501SMasahiro Yamada 		  ( int*          bzerror,
1051*f071c501SMasahiro Yamada 		    BZFILE*       b,
1052*f071c501SMasahiro Yamada 		    int           abandon,
1053*f071c501SMasahiro Yamada 		    unsigned int* nbytes_in_lo32,
1054*f071c501SMasahiro Yamada 		    unsigned int* nbytes_in_hi32,
1055*f071c501SMasahiro Yamada 		    unsigned int* nbytes_out_lo32,
1056*f071c501SMasahiro Yamada 		    unsigned int* nbytes_out_hi32 )
1057*f071c501SMasahiro Yamada {
1058*f071c501SMasahiro Yamada    Int32   n, n2, ret;
1059*f071c501SMasahiro Yamada    bzFile* bzf = (bzFile*)b;
1060*f071c501SMasahiro Yamada 
1061*f071c501SMasahiro Yamada    if (bzf == NULL)
1062*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_OK); return; };
1063*f071c501SMasahiro Yamada    if (!(bzf->writing))
1064*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1065*f071c501SMasahiro Yamada    if (ferror(bzf->handle))
1066*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_IO_ERROR); return; };
1067*f071c501SMasahiro Yamada 
1068*f071c501SMasahiro Yamada    if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1069*f071c501SMasahiro Yamada    if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1070*f071c501SMasahiro Yamada    if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1071*f071c501SMasahiro Yamada    if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1072*f071c501SMasahiro Yamada 
1073*f071c501SMasahiro Yamada    if ((!abandon) && bzf->lastErr == BZ_OK) {
1074*f071c501SMasahiro Yamada       while (True) {
1075*f071c501SMasahiro Yamada 	 bzf->strm.avail_out = BZ_MAX_UNUSED;
1076*f071c501SMasahiro Yamada 	 bzf->strm.next_out = bzf->buf;
1077*f071c501SMasahiro Yamada 	 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1078*f071c501SMasahiro Yamada 	 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1079*f071c501SMasahiro Yamada 	    { BZ_SETERR(ret); return; };
1080*f071c501SMasahiro Yamada 
1081*f071c501SMasahiro Yamada 	 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1082*f071c501SMasahiro Yamada 	    n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1083*f071c501SMasahiro Yamada 	    n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1084*f071c501SMasahiro Yamada 			  n, bzf->handle );
1085*f071c501SMasahiro Yamada 	    if (n != n2 || ferror(bzf->handle))
1086*f071c501SMasahiro Yamada 	       { BZ_SETERR(BZ_IO_ERROR); return; };
1087*f071c501SMasahiro Yamada 	 }
1088*f071c501SMasahiro Yamada 
1089*f071c501SMasahiro Yamada 	 if (ret == BZ_STREAM_END) break;
1090*f071c501SMasahiro Yamada       }
1091*f071c501SMasahiro Yamada    }
1092*f071c501SMasahiro Yamada 
1093*f071c501SMasahiro Yamada    if ( !abandon && !ferror ( bzf->handle ) ) {
1094*f071c501SMasahiro Yamada       fflush ( bzf->handle );
1095*f071c501SMasahiro Yamada       if (ferror(bzf->handle))
1096*f071c501SMasahiro Yamada 	 { BZ_SETERR(BZ_IO_ERROR); return; };
1097*f071c501SMasahiro Yamada    }
1098*f071c501SMasahiro Yamada 
1099*f071c501SMasahiro Yamada    if (nbytes_in_lo32 != NULL)
1100*f071c501SMasahiro Yamada       *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1101*f071c501SMasahiro Yamada    if (nbytes_in_hi32 != NULL)
1102*f071c501SMasahiro Yamada       *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1103*f071c501SMasahiro Yamada    if (nbytes_out_lo32 != NULL)
1104*f071c501SMasahiro Yamada       *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1105*f071c501SMasahiro Yamada    if (nbytes_out_hi32 != NULL)
1106*f071c501SMasahiro Yamada       *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1107*f071c501SMasahiro Yamada 
1108*f071c501SMasahiro Yamada    BZ_SETERR(BZ_OK);
1109*f071c501SMasahiro Yamada    BZ2_bzCompressEnd ( &(bzf->strm) );
1110*f071c501SMasahiro Yamada    free ( bzf );
1111*f071c501SMasahiro Yamada }
1112*f071c501SMasahiro Yamada 
1113*f071c501SMasahiro Yamada 
1114*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1115*f071c501SMasahiro Yamada BZFILE* BZ_API(BZ2_bzReadOpen)
1116*f071c501SMasahiro Yamada 		   ( int*  bzerror,
1117*f071c501SMasahiro Yamada 		     FILE* f,
1118*f071c501SMasahiro Yamada 		     int   verbosity,
1119*f071c501SMasahiro Yamada 		     int   small,
1120*f071c501SMasahiro Yamada 		     void* unused,
1121*f071c501SMasahiro Yamada 		     int   nUnused )
1122*f071c501SMasahiro Yamada {
1123*f071c501SMasahiro Yamada    bzFile* bzf = NULL;
1124*f071c501SMasahiro Yamada    int     ret;
1125*f071c501SMasahiro Yamada 
1126*f071c501SMasahiro Yamada    BZ_SETERR(BZ_OK);
1127*f071c501SMasahiro Yamada 
1128*f071c501SMasahiro Yamada    if (f == NULL ||
1129*f071c501SMasahiro Yamada        (small != 0 && small != 1) ||
1130*f071c501SMasahiro Yamada        (verbosity < 0 || verbosity > 4) ||
1131*f071c501SMasahiro Yamada        (unused == NULL && nUnused != 0) ||
1132*f071c501SMasahiro Yamada        (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1133*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1134*f071c501SMasahiro Yamada 
1135*f071c501SMasahiro Yamada    if (ferror(f))
1136*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1137*f071c501SMasahiro Yamada 
1138*f071c501SMasahiro Yamada    bzf = malloc ( sizeof(bzFile) );
1139*f071c501SMasahiro Yamada    if (bzf == NULL)
1140*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1141*f071c501SMasahiro Yamada 
1142*f071c501SMasahiro Yamada    BZ_SETERR(BZ_OK);
1143*f071c501SMasahiro Yamada 
1144*f071c501SMasahiro Yamada    bzf->initialisedOk = False;
1145*f071c501SMasahiro Yamada    bzf->handle        = f;
1146*f071c501SMasahiro Yamada    bzf->bufN          = 0;
1147*f071c501SMasahiro Yamada    bzf->writing       = False;
1148*f071c501SMasahiro Yamada    bzf->strm.bzalloc  = NULL;
1149*f071c501SMasahiro Yamada    bzf->strm.bzfree   = NULL;
1150*f071c501SMasahiro Yamada    bzf->strm.opaque   = NULL;
1151*f071c501SMasahiro Yamada 
1152*f071c501SMasahiro Yamada    while (nUnused > 0) {
1153*f071c501SMasahiro Yamada       bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1154*f071c501SMasahiro Yamada       unused = ((void*)( 1 + ((UChar*)(unused))  ));
1155*f071c501SMasahiro Yamada       nUnused--;
1156*f071c501SMasahiro Yamada    }
1157*f071c501SMasahiro Yamada 
1158*f071c501SMasahiro Yamada    ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1159*f071c501SMasahiro Yamada    if (ret != BZ_OK)
1160*f071c501SMasahiro Yamada       { BZ_SETERR(ret); free(bzf); return NULL; };
1161*f071c501SMasahiro Yamada 
1162*f071c501SMasahiro Yamada    bzf->strm.avail_in = bzf->bufN;
1163*f071c501SMasahiro Yamada    bzf->strm.next_in  = bzf->buf;
1164*f071c501SMasahiro Yamada 
1165*f071c501SMasahiro Yamada    bzf->initialisedOk = True;
1166*f071c501SMasahiro Yamada    return bzf;
1167*f071c501SMasahiro Yamada }
1168*f071c501SMasahiro Yamada 
1169*f071c501SMasahiro Yamada 
1170*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1171*f071c501SMasahiro Yamada void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1172*f071c501SMasahiro Yamada {
1173*f071c501SMasahiro Yamada    bzFile* bzf = (bzFile*)b;
1174*f071c501SMasahiro Yamada 
1175*f071c501SMasahiro Yamada    BZ_SETERR(BZ_OK);
1176*f071c501SMasahiro Yamada    if (bzf == NULL)
1177*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_OK); return; };
1178*f071c501SMasahiro Yamada 
1179*f071c501SMasahiro Yamada    if (bzf->writing)
1180*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1181*f071c501SMasahiro Yamada 
1182*f071c501SMasahiro Yamada    if (bzf->initialisedOk)
1183*f071c501SMasahiro Yamada       (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1184*f071c501SMasahiro Yamada    free ( bzf );
1185*f071c501SMasahiro Yamada }
1186*f071c501SMasahiro Yamada 
1187*f071c501SMasahiro Yamada 
1188*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1189*f071c501SMasahiro Yamada int BZ_API(BZ2_bzRead)
1190*f071c501SMasahiro Yamada 	   ( int*    bzerror,
1191*f071c501SMasahiro Yamada 	     BZFILE* b,
1192*f071c501SMasahiro Yamada 	     void*   buf,
1193*f071c501SMasahiro Yamada 	     int     len )
1194*f071c501SMasahiro Yamada {
1195*f071c501SMasahiro Yamada    Int32   n, ret;
1196*f071c501SMasahiro Yamada    bzFile* bzf = (bzFile*)b;
1197*f071c501SMasahiro Yamada 
1198*f071c501SMasahiro Yamada    BZ_SETERR(BZ_OK);
1199*f071c501SMasahiro Yamada 
1200*f071c501SMasahiro Yamada    if (bzf == NULL || buf == NULL || len < 0)
1201*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1202*f071c501SMasahiro Yamada 
1203*f071c501SMasahiro Yamada    if (bzf->writing)
1204*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1205*f071c501SMasahiro Yamada 
1206*f071c501SMasahiro Yamada    if (len == 0)
1207*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_OK); return 0; };
1208*f071c501SMasahiro Yamada 
1209*f071c501SMasahiro Yamada    bzf->strm.avail_out = len;
1210*f071c501SMasahiro Yamada    bzf->strm.next_out = buf;
1211*f071c501SMasahiro Yamada 
1212*f071c501SMasahiro Yamada    while (True) {
1213*f071c501SMasahiro Yamada 
1214*f071c501SMasahiro Yamada       if (ferror(bzf->handle))
1215*f071c501SMasahiro Yamada 	 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1216*f071c501SMasahiro Yamada 
1217*f071c501SMasahiro Yamada       if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1218*f071c501SMasahiro Yamada 	 n = fread ( bzf->buf, sizeof(UChar),
1219*f071c501SMasahiro Yamada 		     BZ_MAX_UNUSED, bzf->handle );
1220*f071c501SMasahiro Yamada 	 if (ferror(bzf->handle))
1221*f071c501SMasahiro Yamada 	    { BZ_SETERR(BZ_IO_ERROR); return 0; };
1222*f071c501SMasahiro Yamada 	 bzf->bufN = n;
1223*f071c501SMasahiro Yamada 	 bzf->strm.avail_in = bzf->bufN;
1224*f071c501SMasahiro Yamada 	 bzf->strm.next_in = bzf->buf;
1225*f071c501SMasahiro Yamada       }
1226*f071c501SMasahiro Yamada 
1227*f071c501SMasahiro Yamada       ret = BZ2_bzDecompress ( &(bzf->strm) );
1228*f071c501SMasahiro Yamada 
1229*f071c501SMasahiro Yamada       if (ret != BZ_OK && ret != BZ_STREAM_END)
1230*f071c501SMasahiro Yamada 	 { BZ_SETERR(ret); return 0; };
1231*f071c501SMasahiro Yamada 
1232*f071c501SMasahiro Yamada       if (ret == BZ_OK && myfeof(bzf->handle) &&
1233*f071c501SMasahiro Yamada 	  bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1234*f071c501SMasahiro Yamada 	 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1235*f071c501SMasahiro Yamada 
1236*f071c501SMasahiro Yamada       if (ret == BZ_STREAM_END)
1237*f071c501SMasahiro Yamada 	 { BZ_SETERR(BZ_STREAM_END);
1238*f071c501SMasahiro Yamada 	   return len - bzf->strm.avail_out; };
1239*f071c501SMasahiro Yamada       if (bzf->strm.avail_out == 0)
1240*f071c501SMasahiro Yamada 	 { BZ_SETERR(BZ_OK); return len; };
1241*f071c501SMasahiro Yamada 
1242*f071c501SMasahiro Yamada    }
1243*f071c501SMasahiro Yamada 
1244*f071c501SMasahiro Yamada    return 0; /*not reached*/
1245*f071c501SMasahiro Yamada }
1246*f071c501SMasahiro Yamada 
1247*f071c501SMasahiro Yamada 
1248*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1249*f071c501SMasahiro Yamada void BZ_API(BZ2_bzReadGetUnused)
1250*f071c501SMasahiro Yamada 		     ( int*    bzerror,
1251*f071c501SMasahiro Yamada 		       BZFILE* b,
1252*f071c501SMasahiro Yamada 		       void**  unused,
1253*f071c501SMasahiro Yamada 		       int*    nUnused )
1254*f071c501SMasahiro Yamada {
1255*f071c501SMasahiro Yamada    bzFile* bzf = (bzFile*)b;
1256*f071c501SMasahiro Yamada    if (bzf == NULL)
1257*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_PARAM_ERROR); return; };
1258*f071c501SMasahiro Yamada    if (bzf->lastErr != BZ_STREAM_END)
1259*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1260*f071c501SMasahiro Yamada    if (unused == NULL || nUnused == NULL)
1261*f071c501SMasahiro Yamada       { BZ_SETERR(BZ_PARAM_ERROR); return; };
1262*f071c501SMasahiro Yamada 
1263*f071c501SMasahiro Yamada    BZ_SETERR(BZ_OK);
1264*f071c501SMasahiro Yamada    *nUnused = bzf->strm.avail_in;
1265*f071c501SMasahiro Yamada    *unused = bzf->strm.next_in;
1266*f071c501SMasahiro Yamada }
1267*f071c501SMasahiro Yamada #endif
1268*f071c501SMasahiro Yamada 
1269*f071c501SMasahiro Yamada 
1270*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1271*f071c501SMasahiro Yamada /*--- Misc convenience stuff                      ---*/
1272*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1273*f071c501SMasahiro Yamada #ifndef BZ_NO_COMPRESS
1274*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1275*f071c501SMasahiro Yamada int BZ_API(BZ2_bzBuffToBuffCompress)
1276*f071c501SMasahiro Yamada 			 ( char*         dest,
1277*f071c501SMasahiro Yamada 			   unsigned int* destLen,
1278*f071c501SMasahiro Yamada 			   char*         source,
1279*f071c501SMasahiro Yamada 			   unsigned int  sourceLen,
1280*f071c501SMasahiro Yamada 			   int           blockSize100k,
1281*f071c501SMasahiro Yamada 			   int           verbosity,
1282*f071c501SMasahiro Yamada 			   int           workFactor )
1283*f071c501SMasahiro Yamada {
1284*f071c501SMasahiro Yamada    bz_stream strm;
1285*f071c501SMasahiro Yamada    int ret;
1286*f071c501SMasahiro Yamada 
1287*f071c501SMasahiro Yamada    if (dest == NULL || destLen == NULL ||
1288*f071c501SMasahiro Yamada        source == NULL ||
1289*f071c501SMasahiro Yamada        blockSize100k < 1 || blockSize100k > 9 ||
1290*f071c501SMasahiro Yamada        verbosity < 0 || verbosity > 4 ||
1291*f071c501SMasahiro Yamada        workFactor < 0 || workFactor > 250)
1292*f071c501SMasahiro Yamada       return BZ_PARAM_ERROR;
1293*f071c501SMasahiro Yamada 
1294*f071c501SMasahiro Yamada    if (workFactor == 0) workFactor = 30;
1295*f071c501SMasahiro Yamada    strm.bzalloc = NULL;
1296*f071c501SMasahiro Yamada    strm.bzfree = NULL;
1297*f071c501SMasahiro Yamada    strm.opaque = NULL;
1298*f071c501SMasahiro Yamada    ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1299*f071c501SMasahiro Yamada 			      verbosity, workFactor );
1300*f071c501SMasahiro Yamada    if (ret != BZ_OK) return ret;
1301*f071c501SMasahiro Yamada 
1302*f071c501SMasahiro Yamada    strm.next_in = source;
1303*f071c501SMasahiro Yamada    strm.next_out = dest;
1304*f071c501SMasahiro Yamada    strm.avail_in = sourceLen;
1305*f071c501SMasahiro Yamada    strm.avail_out = *destLen;
1306*f071c501SMasahiro Yamada 
1307*f071c501SMasahiro Yamada    ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1308*f071c501SMasahiro Yamada    if (ret == BZ_FINISH_OK) goto output_overflow;
1309*f071c501SMasahiro Yamada    if (ret != BZ_STREAM_END) goto errhandler;
1310*f071c501SMasahiro Yamada 
1311*f071c501SMasahiro Yamada    /* normal termination */
1312*f071c501SMasahiro Yamada    *destLen -= strm.avail_out;
1313*f071c501SMasahiro Yamada    BZ2_bzCompressEnd ( &strm );
1314*f071c501SMasahiro Yamada    return BZ_OK;
1315*f071c501SMasahiro Yamada 
1316*f071c501SMasahiro Yamada    output_overflow:
1317*f071c501SMasahiro Yamada    BZ2_bzCompressEnd ( &strm );
1318*f071c501SMasahiro Yamada    return BZ_OUTBUFF_FULL;
1319*f071c501SMasahiro Yamada 
1320*f071c501SMasahiro Yamada    errhandler:
1321*f071c501SMasahiro Yamada    BZ2_bzCompressEnd ( &strm );
1322*f071c501SMasahiro Yamada    return ret;
1323*f071c501SMasahiro Yamada }
1324*f071c501SMasahiro Yamada #endif /* BZ_NO_COMPRESS */
1325*f071c501SMasahiro Yamada 
1326*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1327*f071c501SMasahiro Yamada int BZ_API(BZ2_bzBuffToBuffDecompress)
1328*f071c501SMasahiro Yamada 			   ( char*         dest,
1329*f071c501SMasahiro Yamada 			     unsigned int* destLen,
1330*f071c501SMasahiro Yamada 			     char*         source,
1331*f071c501SMasahiro Yamada 			     unsigned int  sourceLen,
1332*f071c501SMasahiro Yamada 			     int           small,
1333*f071c501SMasahiro Yamada 			     int           verbosity )
1334*f071c501SMasahiro Yamada {
1335*f071c501SMasahiro Yamada    bz_stream strm;
1336*f071c501SMasahiro Yamada    int ret;
1337*f071c501SMasahiro Yamada 
1338*f071c501SMasahiro Yamada    if (destLen == NULL || source == NULL)
1339*f071c501SMasahiro Yamada 	  return BZ_PARAM_ERROR;
1340*f071c501SMasahiro Yamada 
1341*f071c501SMasahiro Yamada    strm.bzalloc = NULL;
1342*f071c501SMasahiro Yamada    strm.bzfree = NULL;
1343*f071c501SMasahiro Yamada    strm.opaque = NULL;
1344*f071c501SMasahiro Yamada    ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1345*f071c501SMasahiro Yamada    if (ret != BZ_OK) return ret;
1346*f071c501SMasahiro Yamada 
1347*f071c501SMasahiro Yamada    strm.next_in = source;
1348*f071c501SMasahiro Yamada    strm.next_out = dest;
1349*f071c501SMasahiro Yamada    strm.avail_in = sourceLen;
1350*f071c501SMasahiro Yamada    strm.avail_out = *destLen;
1351*f071c501SMasahiro Yamada 
1352*f071c501SMasahiro Yamada    ret = BZ2_bzDecompress ( &strm );
1353*f071c501SMasahiro Yamada    if (ret == BZ_OK) goto output_overflow_or_eof;
1354*f071c501SMasahiro Yamada    if (ret != BZ_STREAM_END) goto errhandler;
1355*f071c501SMasahiro Yamada 
1356*f071c501SMasahiro Yamada    /* normal termination */
1357*f071c501SMasahiro Yamada    *destLen -= strm.avail_out;
1358*f071c501SMasahiro Yamada    BZ2_bzDecompressEnd ( &strm );
1359*f071c501SMasahiro Yamada    return BZ_OK;
1360*f071c501SMasahiro Yamada 
1361*f071c501SMasahiro Yamada    output_overflow_or_eof:
1362*f071c501SMasahiro Yamada    if (strm.avail_out > 0) {
1363*f071c501SMasahiro Yamada       BZ2_bzDecompressEnd ( &strm );
1364*f071c501SMasahiro Yamada       return BZ_UNEXPECTED_EOF;
1365*f071c501SMasahiro Yamada    } else {
1366*f071c501SMasahiro Yamada       BZ2_bzDecompressEnd ( &strm );
1367*f071c501SMasahiro Yamada       return BZ_OUTBUFF_FULL;
1368*f071c501SMasahiro Yamada    };
1369*f071c501SMasahiro Yamada 
1370*f071c501SMasahiro Yamada    errhandler:
1371*f071c501SMasahiro Yamada    BZ2_bzDecompressEnd ( &strm );
1372*f071c501SMasahiro Yamada    return ret;
1373*f071c501SMasahiro Yamada }
1374*f071c501SMasahiro Yamada 
1375*f071c501SMasahiro Yamada 
1376*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1377*f071c501SMasahiro Yamada /*--
1378*f071c501SMasahiro Yamada    Code contributed by Yoshioka Tsuneo
1379*f071c501SMasahiro Yamada    (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
1380*f071c501SMasahiro Yamada    to support better zlib compatibility.
1381*f071c501SMasahiro Yamada    This code is not _officially_ part of libbzip2 (yet);
1382*f071c501SMasahiro Yamada    I haven't tested it, documented it, or considered the
1383*f071c501SMasahiro Yamada    threading-safeness of it.
1384*f071c501SMasahiro Yamada    If this code breaks, please contact both Yoshioka and me.
1385*f071c501SMasahiro Yamada --*/
1386*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1387*f071c501SMasahiro Yamada 
1388*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1389*f071c501SMasahiro Yamada /*--
1390*f071c501SMasahiro Yamada    return version like "0.9.0c".
1391*f071c501SMasahiro Yamada --*/
1392*f071c501SMasahiro Yamada const char * BZ_API(BZ2_bzlibVersion)(void)
1393*f071c501SMasahiro Yamada {
1394*f071c501SMasahiro Yamada    return BZ_VERSION;
1395*f071c501SMasahiro Yamada }
1396*f071c501SMasahiro Yamada 
1397*f071c501SMasahiro Yamada 
1398*f071c501SMasahiro Yamada #ifndef BZ_NO_STDIO
1399*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1400*f071c501SMasahiro Yamada 
1401*f071c501SMasahiro Yamada #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1402*f071c501SMasahiro Yamada #   include <fcntl.h>
1403*f071c501SMasahiro Yamada #   include <io.h>
1404*f071c501SMasahiro Yamada #   define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1405*f071c501SMasahiro Yamada #else
1406*f071c501SMasahiro Yamada #   define SET_BINARY_MODE(file)
1407*f071c501SMasahiro Yamada #endif
1408*f071c501SMasahiro Yamada static
1409*f071c501SMasahiro Yamada BZFILE * bzopen_or_bzdopen
1410*f071c501SMasahiro Yamada 	       ( const char *path,   /* no use when bzdopen */
1411*f071c501SMasahiro Yamada 		 int fd,             /* no use when bzdopen */
1412*f071c501SMasahiro Yamada 		 const char *mode,
1413*f071c501SMasahiro Yamada 		 int open_mode)      /* bzopen: 0, bzdopen:1 */
1414*f071c501SMasahiro Yamada {
1415*f071c501SMasahiro Yamada    int    bzerr;
1416*f071c501SMasahiro Yamada    char   unused[BZ_MAX_UNUSED];
1417*f071c501SMasahiro Yamada    int    blockSize100k = 9;
1418*f071c501SMasahiro Yamada    int    writing       = 0;
1419*f071c501SMasahiro Yamada    char   mode2[10]     = "";
1420*f071c501SMasahiro Yamada    FILE   *fp           = NULL;
1421*f071c501SMasahiro Yamada    BZFILE *bzfp         = NULL;
1422*f071c501SMasahiro Yamada    int    verbosity     = 0;
1423*f071c501SMasahiro Yamada    int    workFactor    = 30;
1424*f071c501SMasahiro Yamada    int    smallMode     = 0;
1425*f071c501SMasahiro Yamada    int    nUnused       = 0;
1426*f071c501SMasahiro Yamada 
1427*f071c501SMasahiro Yamada    if (mode == NULL) return NULL;
1428*f071c501SMasahiro Yamada    while (*mode) {
1429*f071c501SMasahiro Yamada       switch (*mode) {
1430*f071c501SMasahiro Yamada       case 'r':
1431*f071c501SMasahiro Yamada 	 writing = 0; break;
1432*f071c501SMasahiro Yamada       case 'w':
1433*f071c501SMasahiro Yamada 	 writing = 1; break;
1434*f071c501SMasahiro Yamada       case 's':
1435*f071c501SMasahiro Yamada 	 smallMode = 1; break;
1436*f071c501SMasahiro Yamada       default:
1437*f071c501SMasahiro Yamada 	 if (isdigit((int)(*mode))) {
1438*f071c501SMasahiro Yamada 	    blockSize100k = *mode-BZ_HDR_0;
1439*f071c501SMasahiro Yamada 	 }
1440*f071c501SMasahiro Yamada       }
1441*f071c501SMasahiro Yamada       mode++;
1442*f071c501SMasahiro Yamada    }
1443*f071c501SMasahiro Yamada    strcat(mode2, writing ? "w" : "r" );
1444*f071c501SMasahiro Yamada    strcat(mode2,"b");   /* binary mode */
1445*f071c501SMasahiro Yamada 
1446*f071c501SMasahiro Yamada    if (open_mode==0) {
1447*f071c501SMasahiro Yamada       if (path==NULL || strcmp(path,"")==0) {
1448*f071c501SMasahiro Yamada 	fp = (writing ? stdout : stdin);
1449*f071c501SMasahiro Yamada 	SET_BINARY_MODE(fp);
1450*f071c501SMasahiro Yamada       } else {
1451*f071c501SMasahiro Yamada 	fp = fopen(path,mode2);
1452*f071c501SMasahiro Yamada       }
1453*f071c501SMasahiro Yamada    } else {
1454*f071c501SMasahiro Yamada #ifdef BZ_STRICT_ANSI
1455*f071c501SMasahiro Yamada       fp = NULL;
1456*f071c501SMasahiro Yamada #else
1457*f071c501SMasahiro Yamada       fp = fdopen(fd,mode2);
1458*f071c501SMasahiro Yamada #endif
1459*f071c501SMasahiro Yamada    }
1460*f071c501SMasahiro Yamada    if (fp == NULL) return NULL;
1461*f071c501SMasahiro Yamada 
1462*f071c501SMasahiro Yamada    if (writing) {
1463*f071c501SMasahiro Yamada       /* Guard against total chaos and anarchy -- JRS */
1464*f071c501SMasahiro Yamada       if (blockSize100k < 1) blockSize100k = 1;
1465*f071c501SMasahiro Yamada       if (blockSize100k > 9) blockSize100k = 9;
1466*f071c501SMasahiro Yamada       bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1467*f071c501SMasahiro Yamada 			     verbosity,workFactor);
1468*f071c501SMasahiro Yamada    } else {
1469*f071c501SMasahiro Yamada       bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1470*f071c501SMasahiro Yamada 			    unused,nUnused);
1471*f071c501SMasahiro Yamada    }
1472*f071c501SMasahiro Yamada    if (bzfp == NULL) {
1473*f071c501SMasahiro Yamada       if (fp != stdin && fp != stdout) fclose(fp);
1474*f071c501SMasahiro Yamada       return NULL;
1475*f071c501SMasahiro Yamada    }
1476*f071c501SMasahiro Yamada    return bzfp;
1477*f071c501SMasahiro Yamada }
1478*f071c501SMasahiro Yamada 
1479*f071c501SMasahiro Yamada 
1480*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1481*f071c501SMasahiro Yamada /*--
1482*f071c501SMasahiro Yamada    open file for read or write.
1483*f071c501SMasahiro Yamada       ex) bzopen("file","w9")
1484*f071c501SMasahiro Yamada       case path="" or NULL => use stdin or stdout.
1485*f071c501SMasahiro Yamada --*/
1486*f071c501SMasahiro Yamada BZFILE * BZ_API(BZ2_bzopen)
1487*f071c501SMasahiro Yamada 	       ( const char *path,
1488*f071c501SMasahiro Yamada 		 const char *mode )
1489*f071c501SMasahiro Yamada {
1490*f071c501SMasahiro Yamada    return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1491*f071c501SMasahiro Yamada }
1492*f071c501SMasahiro Yamada 
1493*f071c501SMasahiro Yamada 
1494*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1495*f071c501SMasahiro Yamada BZFILE * BZ_API(BZ2_bzdopen)
1496*f071c501SMasahiro Yamada 	       ( int fd,
1497*f071c501SMasahiro Yamada 		 const char *mode )
1498*f071c501SMasahiro Yamada {
1499*f071c501SMasahiro Yamada    return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1500*f071c501SMasahiro Yamada }
1501*f071c501SMasahiro Yamada 
1502*f071c501SMasahiro Yamada 
1503*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1504*f071c501SMasahiro Yamada int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1505*f071c501SMasahiro Yamada {
1506*f071c501SMasahiro Yamada    int bzerr, nread;
1507*f071c501SMasahiro Yamada    if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1508*f071c501SMasahiro Yamada    nread = BZ2_bzRead(&bzerr,b,buf,len);
1509*f071c501SMasahiro Yamada    if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1510*f071c501SMasahiro Yamada       return nread;
1511*f071c501SMasahiro Yamada    } else {
1512*f071c501SMasahiro Yamada       return -1;
1513*f071c501SMasahiro Yamada    }
1514*f071c501SMasahiro Yamada }
1515*f071c501SMasahiro Yamada 
1516*f071c501SMasahiro Yamada 
1517*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1518*f071c501SMasahiro Yamada int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1519*f071c501SMasahiro Yamada {
1520*f071c501SMasahiro Yamada    int bzerr;
1521*f071c501SMasahiro Yamada 
1522*f071c501SMasahiro Yamada    BZ2_bzWrite(&bzerr,b,buf,len);
1523*f071c501SMasahiro Yamada    if(bzerr == BZ_OK){
1524*f071c501SMasahiro Yamada       return len;
1525*f071c501SMasahiro Yamada    }else{
1526*f071c501SMasahiro Yamada       return -1;
1527*f071c501SMasahiro Yamada    }
1528*f071c501SMasahiro Yamada }
1529*f071c501SMasahiro Yamada 
1530*f071c501SMasahiro Yamada 
1531*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1532*f071c501SMasahiro Yamada int BZ_API(BZ2_bzflush) (BZFILE *b)
1533*f071c501SMasahiro Yamada {
1534*f071c501SMasahiro Yamada    /* do nothing now... */
1535*f071c501SMasahiro Yamada    return 0;
1536*f071c501SMasahiro Yamada }
1537*f071c501SMasahiro Yamada 
1538*f071c501SMasahiro Yamada 
1539*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1540*f071c501SMasahiro Yamada void BZ_API(BZ2_bzclose) (BZFILE* b)
1541*f071c501SMasahiro Yamada {
1542*f071c501SMasahiro Yamada    int bzerr;
1543*f071c501SMasahiro Yamada    FILE *fp = ((bzFile *)b)->handle;
1544*f071c501SMasahiro Yamada 
1545*f071c501SMasahiro Yamada    if (b==NULL) {return;}
1546*f071c501SMasahiro Yamada    if(((bzFile*)b)->writing){
1547*f071c501SMasahiro Yamada       BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1548*f071c501SMasahiro Yamada       if(bzerr != BZ_OK){
1549*f071c501SMasahiro Yamada 	 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1550*f071c501SMasahiro Yamada       }
1551*f071c501SMasahiro Yamada    }else{
1552*f071c501SMasahiro Yamada       BZ2_bzReadClose(&bzerr,b);
1553*f071c501SMasahiro Yamada    }
1554*f071c501SMasahiro Yamada    if(fp!=stdin && fp!=stdout){
1555*f071c501SMasahiro Yamada       fclose(fp);
1556*f071c501SMasahiro Yamada    }
1557*f071c501SMasahiro Yamada }
1558*f071c501SMasahiro Yamada 
1559*f071c501SMasahiro Yamada 
1560*f071c501SMasahiro Yamada /*---------------------------------------------------*/
1561*f071c501SMasahiro Yamada /*--
1562*f071c501SMasahiro Yamada    return last error code
1563*f071c501SMasahiro Yamada --*/
1564*f071c501SMasahiro Yamada static char *bzerrorstrings[] = {
1565*f071c501SMasahiro Yamada        "OK"
1566*f071c501SMasahiro Yamada       ,"SEQUENCE_ERROR"
1567*f071c501SMasahiro Yamada       ,"PARAM_ERROR"
1568*f071c501SMasahiro Yamada       ,"MEM_ERROR"
1569*f071c501SMasahiro Yamada       ,"DATA_ERROR"
1570*f071c501SMasahiro Yamada       ,"DATA_ERROR_MAGIC"
1571*f071c501SMasahiro Yamada       ,"IO_ERROR"
1572*f071c501SMasahiro Yamada       ,"UNEXPECTED_EOF"
1573*f071c501SMasahiro Yamada       ,"OUTBUFF_FULL"
1574*f071c501SMasahiro Yamada       ,"CONFIG_ERROR"
1575*f071c501SMasahiro Yamada       ,"???"   /* for future */
1576*f071c501SMasahiro Yamada       ,"???"   /* for future */
1577*f071c501SMasahiro Yamada       ,"???"   /* for future */
1578*f071c501SMasahiro Yamada       ,"???"   /* for future */
1579*f071c501SMasahiro Yamada       ,"???"   /* for future */
1580*f071c501SMasahiro Yamada       ,"???"   /* for future */
1581*f071c501SMasahiro Yamada };
1582*f071c501SMasahiro Yamada 
1583*f071c501SMasahiro Yamada 
1584*f071c501SMasahiro Yamada const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1585*f071c501SMasahiro Yamada {
1586*f071c501SMasahiro Yamada    int err = ((bzFile *)b)->lastErr;
1587*f071c501SMasahiro Yamada 
1588*f071c501SMasahiro Yamada    if(err>0) err = 0;
1589*f071c501SMasahiro Yamada    *errnum = err;
1590*f071c501SMasahiro Yamada    return bzerrorstrings[err*-1];
1591*f071c501SMasahiro Yamada }
1592*f071c501SMasahiro Yamada #endif
1593*f071c501SMasahiro Yamada 
1594*f071c501SMasahiro Yamada void bz_internal_error(int errcode)
1595*f071c501SMasahiro Yamada {
1596*f071c501SMasahiro Yamada 	printf ("BZIP2 internal error %d\n", errcode);
1597*f071c501SMasahiro Yamada }
1598*f071c501SMasahiro Yamada 
1599*f071c501SMasahiro Yamada /*-------------------------------------------------------------*/
1600*f071c501SMasahiro Yamada /*--- end                                           bzlib.c ---*/
1601*f071c501SMasahiro Yamada /*-------------------------------------------------------------*/
1602