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