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