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