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