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