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