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