source: trunk/src/libbz2/bzlib2.c@ 249

Last change on this file since 249 was 249, checked in by umoeller, 23 years ago

Build updates, moved files from warpin.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 32.0 KB
Line 
1
2/*-------------------------------------------------------------*/
3/*--- Library top-level functions. ---*/
4/*--- bzlib.c ---*/
5/*-------------------------------------------------------------*/
6
7/*--
8 This file is a part of bzip2 and/or libbzip2, a program and
9 library for lossless, block-sorting data compression.
10
11 Copyright (C) 1996-2000 Julian R Seward. All rights reserved.
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
15 are met:
16
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
19
20 2. The origin of this software must not be misrepresented; you must
21 not claim that you wrote the original software. If you use this
22 software in a product, an acknowledgment in the product
23 documentation would be appreciated but is not required.
24
25 3. Altered source versions must be plainly marked as such, and must
26 not be misrepresented as being the original software.
27
28 4. The name of the author may not be used to endorse or promote
29 products derived from this software without specific prior written
30 permission.
31
32 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
33 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
36 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
40 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
44 Julian Seward, Cambridge, UK.
45 jseward@acm.org
46 bzip2/libbzip2 version 1.0 of 21 March 2000
47
48 This program is based on (at least) the work of:
49 Mike Burrows
50 David Wheeler
51 Peter Fenwick
52 Alistair Moffat
53 Radford Neal
54 Ian H. Witten
55 Robert Sedgewick
56 Jon L. Bentley
57
58 For more information on these sources, see the manual.
59--*/
60
61/*--
62 CHANGES
63 ~~~~~~~
64 0.9.0 -- original version.
65
66 0.9.0a/b -- no changes in this file.
67
68 0.9.0c
69 * made zero-length BZ_FLUSH work correctly in bzCompress().
70 * fixed bzWrite/bzRead to ignore zero-length requests.
71 * fixed bzread to correctly handle read requests after EOF.
72 * wrong parameter order in call to bzDecompressInit in
73 bzBuffToBuffDecompress. Fixed.
74--*/
75
76#include "bzlib_private.h"
77
78
79extern
80int bz_config_ok ( void );
81extern
82void* default_bzalloc ( void* opaque, Int32 items, Int32 size );
83extern
84void default_bzfree ( void* opaque, void* addr );
85
86/*---------------------------------------------------*/
87/*--- Compression stuff ---*/
88/*---------------------------------------------------*/
89
90
91
92/*---------------------------------------------------*/
93static
94void prepare_new_block ( EState* s )
95{
96 Int32 i;
97 s->nblock = 0;
98 s->numZ = 0;
99 s->state_out_pos = 0;
100 BZ_INITIALISE_CRC ( s->blockCRC );
101 for (i = 0; i < 256; i++) s->inUse[i] = False;
102 s->blockNo++;
103}
104
105
106/*---------------------------------------------------*/
107static
108void init_RL ( EState* s )
109{
110 s->state_in_ch = 256;
111 s->state_in_len = 0;
112}
113
114
115static
116Bool isempty_RL ( EState* s )
117{
118 if (s->state_in_ch < 256 && s->state_in_len > 0)
119 return False; else
120 return True;
121}
122
123
124/*---------------------------------------------------*/
125int BZ2_bzCompressInit
126 ( bz_stream* strm,
127 int blockSize100k,
128 int verbosity,
129 int workFactor )
130{
131 Int32 n;
132 EState* s;
133
134 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
135
136 if (strm == NULL ||
137 blockSize100k < 1 || blockSize100k > 9 ||
138 workFactor < 0 || workFactor > 250)
139 return BZ_PARAM_ERROR;
140
141 if (workFactor == 0) workFactor = 30;
142 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
143 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
144
145 s = BZALLOC( sizeof(EState) );
146 if (s == NULL) return BZ_MEM_ERROR;
147 s->strm = strm;
148
149 s->arr1 = NULL;
150 s->arr2 = NULL;
151 s->ftab = NULL;
152
153 n = 100000 * blockSize100k;
154 s->arr1 = BZALLOC( n * sizeof(UInt32) );
155 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
156 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
157
158 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
159 if (s->arr1 != NULL) BZFREE(s->arr1);
160 if (s->arr2 != NULL) BZFREE(s->arr2);
161 if (s->ftab != NULL) BZFREE(s->ftab);
162 if (s != NULL) BZFREE(s);
163 return BZ_MEM_ERROR;
164 }
165
166 s->blockNo = 0;
167 s->state = BZ_S_INPUT;
168 s->mode = BZ_M_RUNNING;
169 s->combinedCRC = 0;
170 s->blockSize100k = blockSize100k;
171 s->nblockMAX = 100000 * blockSize100k - 19;
172 s->verbosity = verbosity;
173 s->workFactor = workFactor;
174
175 s->block = (UChar*)s->arr2;
176 s->mtfv = (UInt16*)s->arr1;
177 s->zbits = NULL;
178 s->ptr = (UInt32*)s->arr1;
179
180 strm->state = s;
181 strm->total_in_lo32 = 0;
182 strm->total_in_hi32 = 0;
183 strm->total_out_lo32 = 0;
184 strm->total_out_hi32 = 0;
185 init_RL ( s );
186 prepare_new_block ( s );
187 return BZ_OK;
188}
189
190
191/*---------------------------------------------------*/
192static
193void add_pair_to_block ( EState* s )
194{
195 Int32 i;
196 UChar ch = (UChar)(s->state_in_ch);
197 for (i = 0; i < s->state_in_len; i++) {
198 BZ_UPDATE_CRC( s->blockCRC, ch );
199 }
200 s->inUse[s->state_in_ch] = True;
201 switch (s->state_in_len) {
202 case 1:
203 s->block[s->nblock] = (UChar)ch; s->nblock++;
204 break;
205 case 2:
206 s->block[s->nblock] = (UChar)ch; s->nblock++;
207 s->block[s->nblock] = (UChar)ch; s->nblock++;
208 break;
209 case 3:
210 s->block[s->nblock] = (UChar)ch; s->nblock++;
211 s->block[s->nblock] = (UChar)ch; s->nblock++;
212 s->block[s->nblock] = (UChar)ch; s->nblock++;
213 break;
214 default:
215 s->inUse[s->state_in_len-4] = True;
216 s->block[s->nblock] = (UChar)ch; s->nblock++;
217 s->block[s->nblock] = (UChar)ch; s->nblock++;
218 s->block[s->nblock] = (UChar)ch; s->nblock++;
219 s->block[s->nblock] = (UChar)ch; s->nblock++;
220 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
221 s->nblock++;
222 break;
223 }
224}
225
226
227/*---------------------------------------------------*/
228static
229void flush_RL ( EState* s )
230{
231 if (s->state_in_ch < 256) add_pair_to_block ( s );
232 init_RL ( s );
233}
234
235
236/*---------------------------------------------------*/
237#define ADD_CHAR_TO_BLOCK(zs,zchh0) \
238{ \
239 UInt32 zchh = (UInt32)(zchh0); \
240 /*-- fast track the common case --*/ \
241 if (zchh != zs->state_in_ch && \
242 zs->state_in_len == 1) { \
243 UChar ch = (UChar)(zs->state_in_ch); \
244 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
245 zs->inUse[zs->state_in_ch] = True; \
246 zs->block[zs->nblock] = (UChar)ch; \
247 zs->nblock++; \
248 zs->state_in_ch = zchh; \
249 } \
250 else \
251 /*-- general, uncommon cases --*/ \
252 if (zchh != zs->state_in_ch || \
253 zs->state_in_len == 255) { \
254 if (zs->state_in_ch < 256) \
255 add_pair_to_block ( zs ); \
256 zs->state_in_ch = zchh; \
257 zs->state_in_len = 1; \
258 } else { \
259 zs->state_in_len++; \
260 } \
261}
262
263
264/*---------------------------------------------------*/
265static
266Bool copy_input_until_stop ( EState* s )
267{
268 Bool progress_in = False;
269
270 if (s->mode == BZ_M_RUNNING) {
271
272 /*-- fast track the common case --*/
273 while (True) {
274 /*-- block full? --*/
275 if (s->nblock >= s->nblockMAX) break;
276 /*-- no input? --*/
277 if (s->strm->avail_in == 0) break;
278 progress_in = True;
279 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
280 s->strm->next_in++;
281 s->strm->avail_in--;
282 s->strm->total_in_lo32++;
283 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
284 }
285
286 } else {
287
288 /*-- general, uncommon case --*/
289 while (True) {
290 /*-- block full? --*/
291 if (s->nblock >= s->nblockMAX) break;
292 /*-- no input? --*/
293 if (s->strm->avail_in == 0) break;
294 /*-- flush/finish end? --*/
295 if (s->avail_in_expect == 0) break;
296 progress_in = True;
297 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
298 s->strm->next_in++;
299 s->strm->avail_in--;
300 s->strm->total_in_lo32++;
301 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
302 s->avail_in_expect--;
303 }
304 }
305 return progress_in;
306}
307
308
309/*---------------------------------------------------*/
310static
311Bool copy_output_until_stop ( EState* s )
312{
313 Bool progress_out = False;
314
315 while (True) {
316
317 /*-- no output space? --*/
318 if (s->strm->avail_out == 0) break;
319
320 /*-- block done? --*/
321 if (s->state_out_pos >= s->numZ) break;
322
323 progress_out = True;
324 *(s->strm->next_out) = s->zbits[s->state_out_pos];
325 s->state_out_pos++;
326 s->strm->avail_out--;
327 s->strm->next_out++;
328 s->strm->total_out_lo32++;
329 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
330 }
331
332 return progress_out;
333}
334
335
336/*---------------------------------------------------*/
337static
338Bool handle_compress ( bz_stream* strm )
339{
340 Bool progress_in = False;
341 Bool progress_out = False;
342 EState* s = strm->state;
343
344 while (True) {
345
346 if (s->state == BZ_S_OUTPUT) {
347 progress_out |= copy_output_until_stop ( s );
348 if (s->state_out_pos < s->numZ) break;
349 if (s->mode == BZ_M_FINISHING &&
350 s->avail_in_expect == 0 &&
351 isempty_RL(s)) break;
352 prepare_new_block ( s );
353 s->state = BZ_S_INPUT;
354 if (s->mode == BZ_M_FLUSHING &&
355 s->avail_in_expect == 0 &&
356 isempty_RL(s)) break;
357 }
358
359 if (s->state == BZ_S_INPUT) {
360 progress_in |= copy_input_until_stop ( s );
361 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
362 flush_RL ( s );
363 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
364 s->state = BZ_S_OUTPUT;
365 }
366 else
367 if (s->nblock >= s->nblockMAX) {
368 BZ2_compressBlock ( s, False );
369 s->state = BZ_S_OUTPUT;
370 }
371 else
372 if (s->strm->avail_in == 0) {
373 break;
374 }
375 }
376
377 }
378
379 return progress_in || progress_out;
380}
381
382
383/*---------------------------------------------------*/
384int BZ2_bzCompress ( bz_stream *strm, int action )
385{
386 Bool progress;
387 EState* s;
388 if (strm == NULL) return BZ_PARAM_ERROR;
389 s = strm->state;
390 if (s == NULL) return BZ_PARAM_ERROR;
391 if (s->strm != strm) return BZ_PARAM_ERROR;
392
393 preswitch:
394 switch (s->mode) {
395
396 case BZ_M_IDLE:
397 return BZ_SEQUENCE_ERROR;
398
399 case BZ_M_RUNNING:
400 if (action == BZ_RUN) {
401 progress = handle_compress ( strm );
402 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
403 }
404 else
405 if (action == BZ_FLUSH) {
406 s->avail_in_expect = strm->avail_in;
407 s->mode = BZ_M_FLUSHING;
408 goto preswitch;
409 }
410 else
411 if (action == BZ_FINISH) {
412 s->avail_in_expect = strm->avail_in;
413 s->mode = BZ_M_FINISHING;
414 goto preswitch;
415 }
416 else
417 return BZ_PARAM_ERROR;
418
419 case BZ_M_FLUSHING:
420 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
421 if (s->avail_in_expect != s->strm->avail_in)
422 return BZ_SEQUENCE_ERROR;
423 progress = handle_compress ( strm );
424 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
425 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
426 s->mode = BZ_M_RUNNING;
427 return BZ_RUN_OK;
428
429 case BZ_M_FINISHING:
430 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
431 if (s->avail_in_expect != s->strm->avail_in)
432 return BZ_SEQUENCE_ERROR;
433 progress = handle_compress ( strm );
434 if (!progress) return BZ_SEQUENCE_ERROR;
435 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
436 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
437 s->mode = BZ_M_IDLE;
438 return BZ_STREAM_END;
439 }
440 return BZ_OK; /*--not reached--*/
441}
442
443
444/*---------------------------------------------------*/
445int BZ2_bzCompressEnd ( bz_stream *strm )
446{
447 EState* s;
448 if (strm == NULL) return BZ_PARAM_ERROR;
449 s = strm->state;
450 if (s == NULL) return BZ_PARAM_ERROR;
451 if (s->strm != strm) return BZ_PARAM_ERROR;
452
453 if (s->arr1 != NULL) BZFREE(s->arr1);
454 if (s->arr2 != NULL) BZFREE(s->arr2);
455 if (s->ftab != NULL) BZFREE(s->ftab);
456 BZFREE(strm->state);
457
458 strm->state = NULL;
459
460 return BZ_OK;
461}
462
463
464#ifndef BZ_NO_STDIO
465/*---------------------------------------------------*/
466/*--- File I/O stuff ---*/
467/*---------------------------------------------------*/
468
469#define BZ_SETERR(eee) \
470{ \
471 if (bzerror != NULL) *bzerror = eee; \
472 if (bzf != NULL) bzf->lastErr = eee; \
473}
474
475typedef
476 struct {
477 FILE* handle;
478 Char buf[BZ_MAX_UNUSED];
479 Int32 bufN;
480 Bool writing;
481 bz_stream strm;
482 Int32 lastErr;
483 Bool initialisedOk;
484 }
485 bzFile;
486
487
488/*---------------------------------------------*/
489static Bool myfeof ( FILE* f )
490{
491 Int32 c = fgetc ( f );
492 if (c == EOF) return True;
493 ungetc ( c, f );
494 return False;
495}
496
497
498/*---------------------------------------------------*/
499BZFILE* BZ2_bzWriteOpen
500 ( int* bzerror,
501 FILE* f,
502 int blockSize100k,
503 int verbosity,
504 int workFactor )
505{
506 Int32 ret;
507 bzFile* bzf = NULL;
508
509 BZ_SETERR(BZ_OK);
510
511 if (f == NULL ||
512 (blockSize100k < 1 || blockSize100k > 9) ||
513 (workFactor < 0 || workFactor > 250) ||
514 (verbosity < 0 || verbosity > 4))
515 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
516
517 if (ferror(f))
518 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
519
520 bzf = malloc ( sizeof(bzFile) );
521 if (bzf == NULL)
522 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
523
524 BZ_SETERR(BZ_OK);
525 bzf->initialisedOk = False;
526 bzf->bufN = 0;
527 bzf->handle = f;
528 bzf->writing = True;
529 bzf->strm.bzalloc = NULL;
530 bzf->strm.bzfree = NULL;
531 bzf->strm.opaque = NULL;
532
533 if (workFactor == 0) workFactor = 30;
534 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
535 verbosity, workFactor );
536 if (ret != BZ_OK)
537 { BZ_SETERR(ret); free(bzf); return NULL; };
538
539 bzf->strm.avail_in = 0;
540 bzf->initialisedOk = True;
541 return bzf;
542}
543
544
545
546/*---------------------------------------------------*/
547void BZ2_bzWrite
548 ( int* bzerror,
549 BZFILE* b,
550 void* buf,
551 int len )
552{
553 Int32 n, n2, ret;
554 bzFile* bzf = (bzFile*)b;
555
556 BZ_SETERR(BZ_OK);
557 if (bzf == NULL || buf == NULL || len < 0)
558 { BZ_SETERR(BZ_PARAM_ERROR); return; };
559 if (!(bzf->writing))
560 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
561 if (ferror(bzf->handle))
562 { BZ_SETERR(BZ_IO_ERROR); return; };
563
564 if (len == 0)
565 { BZ_SETERR(BZ_OK); return; };
566
567 bzf->strm.avail_in = len;
568 bzf->strm.next_in = buf;
569
570 while (True) {
571 bzf->strm.avail_out = BZ_MAX_UNUSED;
572 bzf->strm.next_out = bzf->buf;
573 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
574 if (ret != BZ_RUN_OK)
575 { BZ_SETERR(ret); return; };
576
577 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
578 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
579 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
580 n, bzf->handle );
581 if (n != n2 || ferror(bzf->handle))
582 { BZ_SETERR(BZ_IO_ERROR); return; };
583 }
584
585 if (bzf->strm.avail_in == 0)
586 { BZ_SETERR(BZ_OK); return; };
587 }
588}
589
590
591/*---------------------------------------------------*/
592void BZ2_bzWriteClose
593 ( int* bzerror,
594 BZFILE* b,
595 int abandon,
596 unsigned int* nbytes_in,
597 unsigned int* nbytes_out )
598{
599 BZ2_bzWriteClose64 ( bzerror, b, abandon,
600 nbytes_in, NULL, nbytes_out, NULL );
601}
602
603
604void BZ2_bzWriteClose64
605 ( int* bzerror,
606 BZFILE* b,
607 int abandon,
608 unsigned int* nbytes_in_lo32,
609 unsigned int* nbytes_in_hi32,
610 unsigned int* nbytes_out_lo32,
611 unsigned int* nbytes_out_hi32 )
612{
613 Int32 n, n2, ret;
614 bzFile* bzf = (bzFile*)b;
615
616 if (bzf == NULL)
617 { BZ_SETERR(BZ_OK); return; };
618 if (!(bzf->writing))
619 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
620 if (ferror(bzf->handle))
621 { BZ_SETERR(BZ_IO_ERROR); return; };
622
623 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
624 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
625 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
626 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
627
628 if ((!abandon) && bzf->lastErr == BZ_OK) {
629 while (True) {
630 bzf->strm.avail_out = BZ_MAX_UNUSED;
631 bzf->strm.next_out = bzf->buf;
632 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
633 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
634 { BZ_SETERR(ret); return; };
635
636 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
637 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
638 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
639 n, bzf->handle );
640 if (n != n2 || ferror(bzf->handle))
641 { BZ_SETERR(BZ_IO_ERROR); return; };
642 }
643
644 if (ret == BZ_STREAM_END) break;
645 }
646 }
647
648 if ( !abandon && !ferror ( bzf->handle ) ) {
649 fflush ( bzf->handle );
650 if (ferror(bzf->handle))
651 { BZ_SETERR(BZ_IO_ERROR); return; };
652 }
653
654 if (nbytes_in_lo32 != NULL)
655 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
656 if (nbytes_in_hi32 != NULL)
657 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
658 if (nbytes_out_lo32 != NULL)
659 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
660 if (nbytes_out_hi32 != NULL)
661 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
662
663 BZ_SETERR(BZ_OK);
664 BZ2_bzCompressEnd ( &(bzf->strm) );
665 free ( bzf );
666}
667
668
669/*---------------------------------------------------*/
670BZFILE* BZ2_bzReadOpen
671 ( int* bzerror,
672 FILE* f,
673 int verbosity,
674 int small,
675 void* unused,
676 int nUnused )
677{
678 bzFile* bzf = NULL;
679 int ret;
680
681 BZ_SETERR(BZ_OK);
682
683 if (f == NULL ||
684 (small != 0 && small != 1) ||
685 (verbosity < 0 || verbosity > 4) ||
686 (unused == NULL && nUnused != 0) ||
687 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
688 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
689
690 if (ferror(f))
691 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
692
693 bzf = malloc ( sizeof(bzFile) );
694 if (bzf == NULL)
695 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
696
697 BZ_SETERR(BZ_OK);
698
699 bzf->initialisedOk = False;
700 bzf->handle = f;
701 bzf->bufN = 0;
702 bzf->writing = False;
703 bzf->strm.bzalloc = NULL;
704 bzf->strm.bzfree = NULL;
705 bzf->strm.opaque = NULL;
706
707 while (nUnused > 0) {
708 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
709 unused = ((void*)( 1 + ((UChar*)(unused)) ));
710 nUnused--;
711 }
712
713 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
714 if (ret != BZ_OK)
715 { BZ_SETERR(ret); free(bzf); return NULL; };
716
717 bzf->strm.avail_in = bzf->bufN;
718 bzf->strm.next_in = bzf->buf;
719
720 bzf->initialisedOk = True;
721 return bzf;
722}
723
724
725/*---------------------------------------------------*/
726void BZ2_bzReadClose ( int *bzerror, BZFILE *b )
727{
728 bzFile* bzf = (bzFile*)b;
729
730 BZ_SETERR(BZ_OK);
731 if (bzf == NULL)
732 { BZ_SETERR(BZ_OK); return; };
733
734 if (bzf->writing)
735 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
736
737 if (bzf->initialisedOk)
738 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
739 free ( bzf );
740}
741
742
743/*---------------------------------------------------*/
744int BZ2_bzRead
745 ( int* bzerror,
746 BZFILE* b,
747 void* buf,
748 int len )
749{
750 Int32 n, ret;
751 bzFile* bzf = (bzFile*)b;
752
753 BZ_SETERR(BZ_OK);
754
755 if (bzf == NULL || buf == NULL || len < 0)
756 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
757
758 if (bzf->writing)
759 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
760
761 if (len == 0)
762 { BZ_SETERR(BZ_OK); return 0; };
763
764 bzf->strm.avail_out = len;
765 bzf->strm.next_out = buf;
766
767 while (True) {
768
769 if (ferror(bzf->handle))
770 { BZ_SETERR(BZ_IO_ERROR); return 0; };
771
772 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
773 n = fread ( bzf->buf, sizeof(UChar),
774 BZ_MAX_UNUSED, bzf->handle );
775 if (ferror(bzf->handle))
776 { BZ_SETERR(BZ_IO_ERROR); return 0; };
777 bzf->bufN = n;
778 bzf->strm.avail_in = bzf->bufN;
779 bzf->strm.next_in = bzf->buf;
780 }
781
782 ret = BZ2_bzDecompress ( &(bzf->strm) );
783
784 if (ret != BZ_OK && ret != BZ_STREAM_END)
785 { BZ_SETERR(ret); return 0; };
786
787 if (ret == BZ_OK && myfeof(bzf->handle) &&
788 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
789 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
790
791 if (ret == BZ_STREAM_END)
792 { BZ_SETERR(BZ_STREAM_END);
793 return len - bzf->strm.avail_out; };
794 if (bzf->strm.avail_out == 0)
795 { BZ_SETERR(BZ_OK); return len; };
796
797 }
798
799 return 0; /*not reached*/
800}
801
802
803/*---------------------------------------------------*/
804void BZ2_bzReadGetUnused
805 ( int* bzerror,
806 BZFILE* b,
807 void** unused,
808 int* nUnused )
809{
810 bzFile* bzf = (bzFile*)b;
811 if (bzf == NULL)
812 { BZ_SETERR(BZ_PARAM_ERROR); return; };
813 if (bzf->lastErr != BZ_STREAM_END)
814 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
815 if (unused == NULL || nUnused == NULL)
816 { BZ_SETERR(BZ_PARAM_ERROR); return; };
817
818 BZ_SETERR(BZ_OK);
819 *nUnused = bzf->strm.avail_in;
820 *unused = bzf->strm.next_in;
821}
822#endif
823
824
825/*---------------------------------------------------*/
826/*--- Misc convenience stuff ---*/
827/*---------------------------------------------------*/
828
829/*---------------------------------------------------*/
830int BZ2_bzBuffToBuffCompress
831 ( char* dest,
832 unsigned int* destLen,
833 char* source,
834 unsigned int sourceLen,
835 int blockSize100k,
836 int verbosity,
837 int workFactor )
838{
839 bz_stream strm;
840 int ret;
841
842 if (dest == NULL || destLen == NULL ||
843 source == NULL ||
844 blockSize100k < 1 || blockSize100k > 9 ||
845 verbosity < 0 || verbosity > 4 ||
846 workFactor < 0 || workFactor > 250)
847 return BZ_PARAM_ERROR;
848
849 if (workFactor == 0) workFactor = 30;
850 strm.bzalloc = NULL;
851 strm.bzfree = NULL;
852 strm.opaque = NULL;
853 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
854 verbosity, workFactor );
855 if (ret != BZ_OK) return ret;
856
857 strm.next_in = source;
858 strm.next_out = dest;
859 strm.avail_in = sourceLen;
860 strm.avail_out = *destLen;
861
862 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
863 if (ret == BZ_FINISH_OK) goto output_overflow;
864 if (ret != BZ_STREAM_END) goto errhandler;
865
866 /* normal termination */
867 *destLen -= strm.avail_out;
868 BZ2_bzCompressEnd ( &strm );
869 return BZ_OK;
870
871 output_overflow:
872 BZ2_bzCompressEnd ( &strm );
873 return BZ_OUTBUFF_FULL;
874
875 errhandler:
876 BZ2_bzCompressEnd ( &strm );
877 return ret;
878}
879
880
881/*---------------------------------------------------*/
882int BZ2_bzBuffToBuffDecompress
883 ( char* dest,
884 unsigned int* destLen,
885 char* source,
886 unsigned int sourceLen,
887 int small,
888 int verbosity )
889{
890 bz_stream strm;
891 int ret;
892
893 if (dest == NULL || destLen == NULL ||
894 source == NULL ||
895 (small != 0 && small != 1) ||
896 verbosity < 0 || verbosity > 4)
897 return BZ_PARAM_ERROR;
898
899 strm.bzalloc = NULL;
900 strm.bzfree = NULL;
901 strm.opaque = NULL;
902 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
903 if (ret != BZ_OK) return ret;
904
905 strm.next_in = source;
906 strm.next_out = dest;
907 strm.avail_in = sourceLen;
908 strm.avail_out = *destLen;
909
910 ret = BZ2_bzDecompress ( &strm );
911 if (ret == BZ_OK) goto output_overflow_or_eof;
912 if (ret != BZ_STREAM_END) goto errhandler;
913
914 /* normal termination */
915 *destLen -= strm.avail_out;
916 BZ2_bzDecompressEnd ( &strm );
917 return BZ_OK;
918
919 output_overflow_or_eof:
920 if (strm.avail_out > 0) {
921 BZ2_bzDecompressEnd ( &strm );
922 return BZ_UNEXPECTED_EOF;
923 } else {
924 BZ2_bzDecompressEnd ( &strm );
925 return BZ_OUTBUFF_FULL;
926 };
927
928 errhandler:
929 BZ2_bzDecompressEnd ( &strm );
930 return ret;
931}
932
933
934/*---------------------------------------------------*/
935/*--
936 Code contributed by Yoshioka Tsuneo
937 (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
938 to support better zlib compatibility.
939 This code is not _officially_ part of libbzip2 (yet);
940 I haven't tested it, documented it, or considered the
941 threading-safeness of it.
942 If this code breaks, please contact both Yoshioka and me.
943--*/
944/*---------------------------------------------------*/
945
946/*---------------------------------------------------*/
947/*--
948 return version like "0.9.0c".
949--*/
950const char * BZ2_bzlibVersion(void)
951{
952 return BZ_VERSION;
953}
954
955
956#ifndef BZ_NO_STDIO
957/*---------------------------------------------------*/
958
959#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
960# include <fcntl.h>
961# include <io.h>
962# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
963#else
964# define SET_BINARY_MODE(file)
965#endif
966static
967BZFILE * bzopen_or_bzdopen
968 ( const char *path, /* no use when bzdopen */
969 int fd, /* no use when bzdopen */
970 const char *mode,
971 int open_mode) /* bzopen: 0, bzdopen:1 */
972{
973 int bzerr;
974 char unused[BZ_MAX_UNUSED];
975 int blockSize100k = 9;
976 int writing = 0;
977 char mode2[10] = "";
978 FILE *fp = NULL;
979 BZFILE *bzfp = NULL;
980 int verbosity = 0;
981 int workFactor = 30;
982 int smallMode = 0;
983 int nUnused = 0;
984
985 if (mode == NULL) return NULL;
986 while (*mode) {
987 switch (*mode) {
988 case 'r':
989 writing = 0; break;
990 case 'w':
991 writing = 1; break;
992 case 's':
993 smallMode = 1; break;
994 default:
995 if (isdigit((int)(*mode))) {
996 blockSize100k = *mode-'0';
997 }
998 }
999 mode++;
1000 }
1001 strcat(mode2, writing ? "w" : "r" );
1002 strcat(mode2,"b"); /* binary mode */
1003
1004 if (open_mode==0) {
1005 if (path==NULL || strcmp(path,"")==0) {
1006 fp = (writing ? stdout : stdin);
1007 SET_BINARY_MODE(fp);
1008 } else {
1009 fp = fopen(path,mode2);
1010 }
1011 } else {
1012#ifdef BZ_STRICT_ANSI
1013 fp = NULL;
1014#else
1015 fp = fdopen(fd,mode2);
1016#endif
1017 }
1018 if (fp == NULL) return NULL;
1019
1020 if (writing) {
1021 /* Guard against total chaos and anarchy -- JRS */
1022 if (blockSize100k < 1) blockSize100k = 1;
1023 if (blockSize100k > 9) blockSize100k = 9;
1024 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1025 verbosity,workFactor);
1026 } else {
1027 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1028 unused,nUnused);
1029 }
1030 if (bzfp == NULL) {
1031 if (fp != stdin && fp != stdout) fclose(fp);
1032 return NULL;
1033 }
1034 return bzfp;
1035}
1036
1037
1038/*---------------------------------------------------*/
1039/*--
1040 open file for read or write.
1041 ex) bzopen("file","w9")
1042 case path="" or NULL => use stdin or stdout.
1043--*/
1044BZFILE * BZ2_bzopen
1045 ( const char *path,
1046 const char *mode )
1047{
1048 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1049}
1050
1051
1052/*---------------------------------------------------*/
1053BZFILE * BZ2_bzdopen
1054 ( int fd,
1055 const char *mode )
1056{
1057 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1058}
1059
1060
1061/*---------------------------------------------------*/
1062int BZ2_bzread (BZFILE* b, void* buf, int len )
1063{
1064 int bzerr, nread;
1065 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1066 nread = BZ2_bzRead(&bzerr,b,buf,len);
1067 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1068 return nread;
1069 } else {
1070 return -1;
1071 }
1072}
1073
1074
1075/*---------------------------------------------------*/
1076int BZ2_bzwrite (BZFILE* b, void* buf, int len )
1077{
1078 int bzerr;
1079
1080 BZ2_bzWrite(&bzerr,b,buf,len);
1081 if(bzerr == BZ_OK){
1082 return len;
1083 }else{
1084 return -1;
1085 }
1086}
1087
1088
1089/*---------------------------------------------------*/
1090int BZ2_bzflush (BZFILE *b)
1091{
1092 /* do nothing now... */
1093 return 0;
1094}
1095
1096
1097/*---------------------------------------------------*/
1098void BZ2_bzclose (BZFILE* b)
1099{
1100 int bzerr;
1101 FILE *fp = ((bzFile *)b)->handle;
1102
1103 if (b==NULL) {return;}
1104 if(((bzFile*)b)->writing){
1105 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1106 if(bzerr != BZ_OK){
1107 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1108 }
1109 }else{
1110 BZ2_bzReadClose(&bzerr,b);
1111 }
1112 if(fp!=stdin && fp!=stdout){
1113 fclose(fp);
1114 }
1115}
1116
1117
1118/*---------------------------------------------------*/
1119/*--
1120 return last error code
1121--*/
1122static char *bzerrorstrings[] = {
1123 "OK"
1124 ,"SEQUENCE_ERROR"
1125 ,"PARAM_ERROR"
1126 ,"MEM_ERROR"
1127 ,"DATA_ERROR"
1128 ,"DATA_ERROR_MAGIC"
1129 ,"IO_ERROR"
1130 ,"UNEXPECTED_EOF"
1131 ,"OUTBUFF_FULL"
1132 ,"CONFIG_ERROR"
1133 ,"???" /* for future */
1134 ,"???" /* for future */
1135 ,"???" /* for future */
1136 ,"???" /* for future */
1137 ,"???" /* for future */
1138 ,"???" /* for future */
1139};
1140
1141
1142const char * BZ2_bzerror (BZFILE *b, int *errnum)
1143{
1144 int err = ((bzFile *)b)->lastErr;
1145
1146 if(err>0) err = 0;
1147 *errnum = err;
1148 return bzerrorstrings[err*-1];
1149}
1150#endif
1151
1152
Note: See TracBrowser for help on using the repository browser.