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