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