diff options
author | Mark Adler <madler@alumni.caltech.edu> | 2011-09-11 11:04:49 -0700 |
---|---|---|
committer | Mark Adler <madler@alumni.caltech.edu> | 2011-09-11 11:04:49 -0700 |
commit | 10daf0d4d7815447799d555d04d30325836e1d44 (patch) | |
tree | 75579fbe11e42dc3197acca53f5f887ac3808b57 /contrib/puff | |
parent | 9712272c78b9d9c93746d9c8e156a3728c65ca72 (diff) | |
download | zlib-1.2.5.1.tar.gz zlib-1.2.5.1.tar.bz2 zlib-1.2.5.1.zip |
zlib 1.2.5.1v1.2.5.1
Diffstat (limited to 'contrib/puff')
-rw-r--r-- | contrib/puff/Makefile | 40 | ||||
-rw-r--r-- | contrib/puff/puff.c | 252 | ||||
-rw-r--r-- | contrib/puff/puff.h | 8 | ||||
-rw-r--r-- | contrib/puff/pufftest.c | 165 | ||||
-rw-r--r-- | contrib/puff/zeros.raw | bin | 1213 -> 2517 bytes |
5 files changed, 275 insertions, 190 deletions
diff --git a/contrib/puff/Makefile b/contrib/puff/Makefile index b6b6940..0e2594c 100644 --- a/contrib/puff/Makefile +++ b/contrib/puff/Makefile | |||
@@ -1,8 +1,42 @@ | |||
1 | puff: puff.c puff.h | 1 | CFLAGS=-O |
2 | cc -DTEST -o puff puff.c | 2 | |
3 | puff: puff.o pufftest.o | ||
4 | |||
5 | puff.o: puff.h | ||
6 | |||
7 | pufftest.o: puff.h | ||
3 | 8 | ||
4 | test: puff | 9 | test: puff |
5 | puff zeros.raw | 10 | puff zeros.raw |
6 | 11 | ||
12 | puft: puff.c puff.h pufftest.o | ||
13 | cc -fprofile-arcs -ftest-coverage -o puft puff.c pufftest.o | ||
14 | |||
15 | # puff full coverage test (should say 100%) | ||
16 | cov: puft | ||
17 | @rm -f *.gcov *.gcda | ||
18 | @puft -w zeros.raw 2>&1 | cat > /dev/null | ||
19 | @echo '04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 | ||
20 | @echo '00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 | ||
21 | @echo '00 00 00 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 254 | ||
22 | @echo '00 01 00 fe ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 | ||
23 | @echo '01 01 00 fe ff 0a' | xxd -r -p | puft -f 2>&1 | cat > /dev/null | ||
24 | @echo '02 7e ff ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 | ||
25 | @echo '02' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 | ||
26 | @echo '04 80 49 92 24 49 92 24 0f b4 ff ff c3 04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 | ||
27 | @echo '04 80 49 92 24 49 92 24 71 ff ff 93 11 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 249 | ||
28 | @echo '04 c0 81 08 00 00 00 00 20 7f eb 0b 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 | ||
29 | @echo '0b 00 00' | xxd -r -p | puft -f 2>&1 | cat > /dev/null | ||
30 | @echo '1a 07' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 | ||
31 | @echo '0c c0 81 00 00 00 00 00 90 ff 6b 04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 245 | ||
32 | @puft -f zeros.raw 2>&1 | cat > /dev/null | ||
33 | @echo 'fc 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 253 | ||
34 | @echo '04 00 fe ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 252 | ||
35 | @echo '04 00 24 49' | xxd -r -p | puft 2> /dev/null || test $$? -eq 251 | ||
36 | @echo '04 80 49 92 24 49 92 24 0f b4 ff ff c3 84' | xxd -r -p | puft 2> /dev/null || test $$? -eq 248 | ||
37 | @echo '04 00 24 e9 ff ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 250 | ||
38 | @echo '04 00 24 e9 ff 6d' | xxd -r -p | puft 2> /dev/null || test $$? -eq 247 | ||
39 | @gcov -n puff.c | ||
40 | |||
7 | clean: | 41 | clean: |
8 | rm -f puff puff.o | 42 | rm -f puff puft *.o *.gc* |
diff --git a/contrib/puff/puff.c b/contrib/puff/puff.c index 650694e..df8470c 100644 --- a/contrib/puff/puff.c +++ b/contrib/puff/puff.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * puff.c | 2 | * puff.c |
3 | * Copyright (C) 2002-2010 Mark Adler | 3 | * Copyright (C) 2002-2010 Mark Adler |
4 | * For conditions of distribution and use, see copyright notice in puff.h | 4 | * For conditions of distribution and use, see copyright notice in puff.h |
5 | * version 2.1, 4 Apr 2010 | 5 | * version 2.2, 25 Apr 2010 |
6 | * | 6 | * |
7 | * puff.c is a simple inflate written to be an unambiguous way to specify the | 7 | * puff.c is a simple inflate written to be an unambiguous way to specify the |
8 | * deflate format. It is not written for speed but rather simplicity. As a | 8 | * deflate format. It is not written for speed but rather simplicity. As a |
@@ -49,9 +49,9 @@ | |||
49 | * - Fix fixed codes table error | 49 | * - Fix fixed codes table error |
50 | * - Provide a scanning mode for determining size of | 50 | * - Provide a scanning mode for determining size of |
51 | * uncompressed data | 51 | * uncompressed data |
52 | * 1.3 20 Mar 2002 - Go back to lengths for puff() parameters [Jean-loup] | 52 | * 1.3 20 Mar 2002 - Go back to lengths for puff() parameters [Gailly] |
53 | * - Add a puff.h file for the interface | 53 | * - Add a puff.h file for the interface |
54 | * - Add braces in puff() for else do [Jean-loup] | 54 | * - Add braces in puff() for else do [Gailly] |
55 | * - Use indexes instead of pointers for readability | 55 | * - Use indexes instead of pointers for readability |
56 | * 1.4 31 Mar 2002 - Simplify construct() code set check | 56 | * 1.4 31 Mar 2002 - Simplify construct() code set check |
57 | * - Fix some comments | 57 | * - Fix some comments |
@@ -69,13 +69,19 @@ | |||
69 | * - Allow TEST code to read from piped stdin | 69 | * - Allow TEST code to read from piped stdin |
70 | * 2.1 4 Apr 2010 - Avoid variable initialization for happier compilers | 70 | * 2.1 4 Apr 2010 - Avoid variable initialization for happier compilers |
71 | * - Avoid unsigned comparisons for even happier compilers | 71 | * - Avoid unsigned comparisons for even happier compilers |
72 | * 2.2 25 Apr 2010 - Fix bug in variable initializations [Oberhumer] | ||
73 | * - Add const where appropriate [Oberhumer] | ||
74 | * - Split if's and ?'s for coverage testing | ||
75 | * - Break out test code to separate file | ||
76 | * - Move NIL to puff.h | ||
77 | * - Allow incomplete code only if single code length is 1 | ||
78 | * - Add full code coverage test to Makefile | ||
72 | */ | 79 | */ |
73 | 80 | ||
74 | #include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */ | 81 | #include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */ |
75 | #include "puff.h" /* prototype for puff() */ | 82 | #include "puff.h" /* prototype for puff() */ |
76 | 83 | ||
77 | #define local static /* for local function definitions */ | 84 | #define local static /* for local function definitions */ |
78 | #define NIL ((unsigned char *)0) /* for no output option */ | ||
79 | 85 | ||
80 | /* | 86 | /* |
81 | * Maximums for allocations and loops. It is not useful to change these -- | 87 | * Maximums for allocations and loops. It is not useful to change these -- |
@@ -95,7 +101,7 @@ struct state { | |||
95 | unsigned long outcnt; /* bytes written to out so far */ | 101 | unsigned long outcnt; /* bytes written to out so far */ |
96 | 102 | ||
97 | /* input state */ | 103 | /* input state */ |
98 | unsigned char *in; /* input buffer */ | 104 | const unsigned char *in; /* input buffer */ |
99 | unsigned long inlen; /* available input at in */ | 105 | unsigned long inlen; /* available input at in */ |
100 | unsigned long incnt; /* bytes read so far */ | 106 | unsigned long incnt; /* bytes read so far */ |
101 | int bitbuf; /* bit buffer */ | 107 | int bitbuf; /* bit buffer */ |
@@ -123,7 +129,8 @@ local int bits(struct state *s, int need) | |||
123 | /* load at least need bits into val */ | 129 | /* load at least need bits into val */ |
124 | val = s->bitbuf; | 130 | val = s->bitbuf; |
125 | while (s->bitcnt < need) { | 131 | while (s->bitcnt < need) { |
126 | if (s->incnt == s->inlen) longjmp(s->env, 1); /* out of input */ | 132 | if (s->incnt == s->inlen) |
133 | longjmp(s->env, 1); /* out of input */ | ||
127 | val |= (long)(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */ | 134 | val |= (long)(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */ |
128 | s->bitcnt += 8; | 135 | s->bitcnt += 8; |
129 | } | 136 | } |
@@ -162,7 +169,8 @@ local int stored(struct state *s) | |||
162 | s->bitcnt = 0; | 169 | s->bitcnt = 0; |
163 | 170 | ||
164 | /* get length and check against its one's complement */ | 171 | /* get length and check against its one's complement */ |
165 | if (s->incnt + 4 > s->inlen) return 2; /* not enough input */ | 172 | if (s->incnt + 4 > s->inlen) |
173 | return 2; /* not enough input */ | ||
166 | len = s->in[s->incnt++]; | 174 | len = s->in[s->incnt++]; |
167 | len |= s->in[s->incnt++] << 8; | 175 | len |= s->in[s->incnt++] << 8; |
168 | if (s->in[s->incnt++] != (~len & 0xff) || | 176 | if (s->in[s->incnt++] != (~len & 0xff) || |
@@ -170,7 +178,8 @@ local int stored(struct state *s) | |||
170 | return -2; /* didn't match complement! */ | 178 | return -2; /* didn't match complement! */ |
171 | 179 | ||
172 | /* copy len bytes from in to out */ | 180 | /* copy len bytes from in to out */ |
173 | if (s->incnt + len > s->inlen) return 2; /* not enough input */ | 181 | if (s->incnt + len > s->inlen) |
182 | return 2; /* not enough input */ | ||
174 | if (s->out != NIL) { | 183 | if (s->out != NIL) { |
175 | if (s->outcnt + len > s->outlen) | 184 | if (s->outcnt + len > s->outlen) |
176 | return 1; /* not enough output space */ | 185 | return 1; /* not enough output space */ |
@@ -222,7 +231,7 @@ struct huffman { | |||
222 | * in the deflate format. See the format notes for fixed() and dynamic(). | 231 | * in the deflate format. See the format notes for fixed() and dynamic(). |
223 | */ | 232 | */ |
224 | #ifdef SLOW | 233 | #ifdef SLOW |
225 | local int decode(struct state *s, struct huffman *h) | 234 | local int decode(struct state *s, const struct huffman *h) |
226 | { | 235 | { |
227 | int len; /* current number of bits in code */ | 236 | int len; /* current number of bits in code */ |
228 | int code; /* len bits being decoded */ | 237 | int code; /* len bits being decoded */ |
@@ -250,7 +259,7 @@ local int decode(struct state *s, struct huffman *h) | |||
250 | * a few percent larger. | 259 | * a few percent larger. |
251 | */ | 260 | */ |
252 | #else /* !SLOW */ | 261 | #else /* !SLOW */ |
253 | local int decode(struct state *s, struct huffman *h) | 262 | local int decode(struct state *s, const struct huffman *h) |
254 | { | 263 | { |
255 | int len; /* current number of bits in code */ | 264 | int len; /* current number of bits in code */ |
256 | int code; /* len bits being decoded */ | 265 | int code; /* len bits being decoded */ |
@@ -283,10 +292,13 @@ local int decode(struct state *s, struct huffman *h) | |||
283 | len++; | 292 | len++; |
284 | } | 293 | } |
285 | left = (MAXBITS+1) - len; | 294 | left = (MAXBITS+1) - len; |
286 | if (left == 0) break; | 295 | if (left == 0) |
287 | if (s->incnt == s->inlen) longjmp(s->env, 1); /* out of input */ | 296 | break; |
297 | if (s->incnt == s->inlen) | ||
298 | longjmp(s->env, 1); /* out of input */ | ||
288 | bitbuf = s->in[s->incnt++]; | 299 | bitbuf = s->in[s->incnt++]; |
289 | if (left > 8) left = 8; | 300 | if (left > 8) |
301 | left = 8; | ||
290 | } | 302 | } |
291 | return -10; /* ran out of codes */ | 303 | return -10; /* ran out of codes */ |
292 | } | 304 | } |
@@ -324,7 +336,7 @@ local int decode(struct state *s, struct huffman *h) | |||
324 | * - Within a given code length, the symbols are kept in ascending order for | 336 | * - Within a given code length, the symbols are kept in ascending order for |
325 | * the code bits definition. | 337 | * the code bits definition. |
326 | */ | 338 | */ |
327 | local int construct(struct huffman *h, short *length, int n) | 339 | local int construct(struct huffman *h, const short *length, int n) |
328 | { | 340 | { |
329 | int symbol; /* current symbol when stepping through length[] */ | 341 | int symbol; /* current symbol when stepping through length[] */ |
330 | int len; /* current length when stepping through h->count[] */ | 342 | int len; /* current length when stepping through h->count[] */ |
@@ -344,7 +356,8 @@ local int construct(struct huffman *h, short *length, int n) | |||
344 | for (len = 1; len <= MAXBITS; len++) { | 356 | for (len = 1; len <= MAXBITS; len++) { |
345 | left <<= 1; /* one more bit, double codes left */ | 357 | left <<= 1; /* one more bit, double codes left */ |
346 | left -= h->count[len]; /* deduct count from possible codes */ | 358 | left -= h->count[len]; /* deduct count from possible codes */ |
347 | if (left < 0) return left; /* over-subscribed--return negative */ | 359 | if (left < 0) |
360 | return left; /* over-subscribed--return negative */ | ||
348 | } /* left > 0 means incomplete */ | 361 | } /* left > 0 means incomplete */ |
349 | 362 | ||
350 | /* generate offsets into symbol table for each length for sorting */ | 363 | /* generate offsets into symbol table for each length for sorting */ |
@@ -420,8 +433,8 @@ local int construct(struct huffman *h, short *length, int n) | |||
420 | * defined to do the wrong thing in this case. | 433 | * defined to do the wrong thing in this case. |
421 | */ | 434 | */ |
422 | local int codes(struct state *s, | 435 | local int codes(struct state *s, |
423 | struct huffman *lencode, | 436 | const struct huffman *lencode, |
424 | struct huffman *distcode) | 437 | const struct huffman *distcode) |
425 | { | 438 | { |
426 | int symbol; /* decoded symbol */ | 439 | int symbol; /* decoded symbol */ |
427 | int len; /* length for copy */ | 440 | int len; /* length for copy */ |
@@ -444,11 +457,13 @@ local int codes(struct state *s, | |||
444 | /* decode literals and length/distance pairs */ | 457 | /* decode literals and length/distance pairs */ |
445 | do { | 458 | do { |
446 | symbol = decode(s, lencode); | 459 | symbol = decode(s, lencode); |
447 | if (symbol < 0) return symbol; /* invalid symbol */ | 460 | if (symbol < 0) |
461 | return symbol; /* invalid symbol */ | ||
448 | if (symbol < 256) { /* literal: symbol is the byte */ | 462 | if (symbol < 256) { /* literal: symbol is the byte */ |
449 | /* write out the literal */ | 463 | /* write out the literal */ |
450 | if (s->out != NIL) { | 464 | if (s->out != NIL) { |
451 | if (s->outcnt == s->outlen) return 1; | 465 | if (s->outcnt == s->outlen) |
466 | return 1; | ||
452 | s->out[s->outcnt] = symbol; | 467 | s->out[s->outcnt] = symbol; |
453 | } | 468 | } |
454 | s->outcnt++; | 469 | s->outcnt++; |
@@ -456,12 +471,14 @@ local int codes(struct state *s, | |||
456 | else if (symbol > 256) { /* length */ | 471 | else if (symbol > 256) { /* length */ |
457 | /* get and compute length */ | 472 | /* get and compute length */ |
458 | symbol -= 257; | 473 | symbol -= 257; |
459 | if (symbol >= 29) return -10; /* invalid fixed code */ | 474 | if (symbol >= 29) |
475 | return -10; /* invalid fixed code */ | ||
460 | len = lens[symbol] + bits(s, lext[symbol]); | 476 | len = lens[symbol] + bits(s, lext[symbol]); |
461 | 477 | ||
462 | /* get and check distance */ | 478 | /* get and check distance */ |
463 | symbol = decode(s, distcode); | 479 | symbol = decode(s, distcode); |
464 | if (symbol < 0) return symbol; /* invalid symbol */ | 480 | if (symbol < 0) |
481 | return symbol; /* invalid symbol */ | ||
465 | dist = dists[symbol] + bits(s, dext[symbol]); | 482 | dist = dists[symbol] + bits(s, dext[symbol]); |
466 | #ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR | 483 | #ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR |
467 | if (dist > s->outcnt) | 484 | if (dist > s->outcnt) |
@@ -470,13 +487,15 @@ local int codes(struct state *s, | |||
470 | 487 | ||
471 | /* copy length bytes from distance bytes back */ | 488 | /* copy length bytes from distance bytes back */ |
472 | if (s->out != NIL) { | 489 | if (s->out != NIL) { |
473 | if (s->outcnt + len > s->outlen) return 1; | 490 | if (s->outcnt + len > s->outlen) |
491 | return 1; | ||
474 | while (len--) { | 492 | while (len--) { |
475 | s->out[s->outcnt] = | 493 | s->out[s->outcnt] = |
476 | #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR | 494 | #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR |
477 | dist > s->outcnt ? 0 : | 495 | dist > s->outcnt ? |
496 | 0 : | ||
478 | #endif | 497 | #endif |
479 | s->out[s->outcnt - dist]; | 498 | s->out[s->outcnt - dist]; |
480 | s->outcnt++; | 499 | s->outcnt++; |
481 | } | 500 | } |
482 | } | 501 | } |
@@ -525,6 +544,12 @@ local int fixed(struct state *s) | |||
525 | int symbol; | 544 | int symbol; |
526 | short lengths[FIXLCODES]; | 545 | short lengths[FIXLCODES]; |
527 | 546 | ||
547 | /* construct lencode and distcode */ | ||
548 | lencode.count = lencnt; | ||
549 | lencode.symbol = lensym; | ||
550 | distcode.count = distcnt; | ||
551 | distcode.symbol = distsym; | ||
552 | |||
528 | /* literal/length table */ | 553 | /* literal/length table */ |
529 | for (symbol = 0; symbol < 144; symbol++) | 554 | for (symbol = 0; symbol < 144; symbol++) |
530 | lengths[symbol] = 8; | 555 | lengths[symbol] = 8; |
@@ -541,12 +566,6 @@ local int fixed(struct state *s) | |||
541 | lengths[symbol] = 5; | 566 | lengths[symbol] = 5; |
542 | construct(&distcode, lengths, MAXDCODES); | 567 | construct(&distcode, lengths, MAXDCODES); |
543 | 568 | ||
544 | /* construct lencode and distcode */ | ||
545 | lencode.count = lencnt; | ||
546 | lencode.symbol = lensym; | ||
547 | distcode.count = distcnt; | ||
548 | distcode.symbol = distsym; | ||
549 | |||
550 | /* do this just once */ | 569 | /* do this just once */ |
551 | virgin = 0; | 570 | virgin = 0; |
552 | } | 571 | } |
@@ -675,7 +694,8 @@ local int dynamic(struct state *s) | |||
675 | 694 | ||
676 | /* build huffman table for code lengths codes (use lencode temporarily) */ | 695 | /* build huffman table for code lengths codes (use lencode temporarily) */ |
677 | err = construct(&lencode, lengths, 19); | 696 | err = construct(&lencode, lengths, 19); |
678 | if (err != 0) return -4; /* require complete code set here */ | 697 | if (err != 0) /* require complete code set here */ |
698 | return -4; | ||
679 | 699 | ||
680 | /* read length/literal and distance code length tables */ | 700 | /* read length/literal and distance code length tables */ |
681 | index = 0; | 701 | index = 0; |
@@ -689,7 +709,8 @@ local int dynamic(struct state *s) | |||
689 | else { /* repeat instruction */ | 709 | else { /* repeat instruction */ |
690 | len = 0; /* assume repeating zeros */ | 710 | len = 0; /* assume repeating zeros */ |
691 | if (symbol == 16) { /* repeat last length 3..6 times */ | 711 | if (symbol == 16) { /* repeat last length 3..6 times */ |
692 | if (index == 0) return -5; /* no last length! */ | 712 | if (index == 0) |
713 | return -5; /* no last length! */ | ||
693 | len = lengths[index - 1]; /* last length */ | 714 | len = lengths[index - 1]; /* last length */ |
694 | symbol = 3 + bits(s, 2); | 715 | symbol = 3 + bits(s, 2); |
695 | } | 716 | } |
@@ -710,13 +731,13 @@ local int dynamic(struct state *s) | |||
710 | 731 | ||
711 | /* build huffman table for literal/length codes */ | 732 | /* build huffman table for literal/length codes */ |
712 | err = construct(&lencode, lengths, nlen); | 733 | err = construct(&lencode, lengths, nlen); |
713 | if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1)) | 734 | if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1])) |
714 | return -7; /* only allow incomplete codes if just one code */ | 735 | return -7; /* incomplete code ok only for single length 1 code */ |
715 | 736 | ||
716 | /* build huffman table for distance codes */ | 737 | /* build huffman table for distance codes */ |
717 | err = construct(&distcode, lengths + nlen, ndist); | 738 | err = construct(&distcode, lengths + nlen, ndist); |
718 | if (err < 0 || (err > 0 && ndist - distcode.count[0] != 1)) | 739 | if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1])) |
719 | return -8; /* only allow incomplete codes if just one code */ | 740 | return -8; /* incomplete code ok only for single length 1 code */ |
720 | 741 | ||
721 | /* decode data until end-of-block code */ | 742 | /* decode data until end-of-block code */ |
722 | return codes(s, &lencode, &distcode); | 743 | return codes(s, &lencode, &distcode); |
@@ -768,7 +789,7 @@ local int dynamic(struct state *s) | |||
768 | */ | 789 | */ |
769 | int puff(unsigned char *dest, /* pointer to destination pointer */ | 790 | int puff(unsigned char *dest, /* pointer to destination pointer */ |
770 | unsigned long *destlen, /* amount of output space */ | 791 | unsigned long *destlen, /* amount of output space */ |
771 | unsigned char *source, /* pointer to source data pointer */ | 792 | const unsigned char *source, /* pointer to source data pointer */ |
772 | unsigned long *sourcelen) /* amount of input available */ | 793 | unsigned long *sourcelen) /* amount of input available */ |
773 | { | 794 | { |
774 | struct state s; /* input/output state */ | 795 | struct state s; /* input/output state */ |
@@ -795,11 +816,15 @@ int puff(unsigned char *dest, /* pointer to destination pointer */ | |||
795 | do { | 816 | do { |
796 | last = bits(&s, 1); /* one if last block */ | 817 | last = bits(&s, 1); /* one if last block */ |
797 | type = bits(&s, 2); /* block type 0..3 */ | 818 | type = bits(&s, 2); /* block type 0..3 */ |
798 | err = type == 0 ? stored(&s) : | 819 | err = type == 0 ? |
799 | (type == 1 ? fixed(&s) : | 820 | stored(&s) : |
800 | (type == 2 ? dynamic(&s) : | 821 | (type == 1 ? |
801 | -1)); /* type == 3, invalid */ | 822 | fixed(&s) : |
802 | if (err != 0) break; /* return with error */ | 823 | (type == 2 ? |
824 | dynamic(&s) : | ||
825 | -1)); /* type == 3, invalid */ | ||
826 | if (err != 0) | ||
827 | break; /* return with error */ | ||
803 | } while (!last); | 828 | } while (!last); |
804 | } | 829 | } |
805 | 830 | ||
@@ -810,146 +835,3 @@ int puff(unsigned char *dest, /* pointer to destination pointer */ | |||
810 | } | 835 | } |
811 | return err; | 836 | return err; |
812 | } | 837 | } |
813 | |||
814 | #ifdef TEST | ||
815 | /* Examples of how to use puff(). | ||
816 | |||
817 | Usage: puff [-w] [-nnn] file | ||
818 | ... | puff [-w] [-nnn] | ||
819 | |||
820 | where file is the input file with deflate data, nnn is the number of bytes | ||
821 | of input to skip before inflating (e.g. to skip a zlib or gzip header), and | ||
822 | -w is used to write the decompressed data to stdout */ | ||
823 | |||
824 | #include <stdio.h> | ||
825 | #include <stdlib.h> | ||
826 | |||
827 | /* Return size times approximately the cube root of 2, keeping the result as 1, | ||
828 | 3, or 5 times a power of 2 -- the result is always > size, until the result | ||
829 | is the maximum value of an unsigned long, where it remains. This is useful | ||
830 | to keep reallocations less than ~33% over the actual data. */ | ||
831 | local size_t bythirds(size_t size) | ||
832 | { | ||
833 | int n; | ||
834 | size_t m; | ||
835 | |||
836 | m = size; | ||
837 | for (n = 0; m; n++) | ||
838 | m >>= 1; | ||
839 | if (n < 3) | ||
840 | return size + 1; | ||
841 | n -= 3; | ||
842 | m = size >> n; | ||
843 | m += m == 6 ? 2 : 1; | ||
844 | m <<= n; | ||
845 | return m > size ? m : (size_t)(-1); | ||
846 | } | ||
847 | |||
848 | /* Read the input file *name, or stdin if name is NULL, into allocated memory. | ||
849 | Reallocate to larger buffers until the entire file is read in. Return a | ||
850 | pointer to the allocated data, or NULL if there was a memory allocation | ||
851 | failure. *len is the number of bytes of data read from the input file (even | ||
852 | if load() returns NULL). If the input file was empty or could not be opened | ||
853 | or read, *len is zero. */ | ||
854 | local void *load(char *name, size_t *len) | ||
855 | { | ||
856 | size_t size; | ||
857 | void *buf, *swap; | ||
858 | FILE *in; | ||
859 | |||
860 | *len = 0; | ||
861 | buf = malloc(size = 4096); | ||
862 | if (buf == NULL) | ||
863 | return NULL; | ||
864 | in = name == NULL ? stdin : fopen(name, "rb"); | ||
865 | if (in != NULL) { | ||
866 | for (;;) { | ||
867 | *len += fread((char *)buf + *len, 1, size - *len, in); | ||
868 | if (*len < size) break; | ||
869 | size = bythirds(size); | ||
870 | if (size == *len || (swap = realloc(buf, size)) == NULL) { | ||
871 | free(buf); | ||
872 | buf = NULL; | ||
873 | break; | ||
874 | } | ||
875 | buf = swap; | ||
876 | } | ||
877 | fclose(in); | ||
878 | } | ||
879 | return buf; | ||
880 | } | ||
881 | |||
882 | int main(int argc, char **argv) | ||
883 | { | ||
884 | int ret, put = 0; | ||
885 | unsigned skip = 0; | ||
886 | char *arg, *name = NULL; | ||
887 | unsigned char *source = NULL, *dest; | ||
888 | size_t len = 0; | ||
889 | unsigned long sourcelen, destlen; | ||
890 | |||
891 | /* process arguments */ | ||
892 | while (arg = *++argv, --argc) | ||
893 | if (arg[0] == '-') { | ||
894 | if (arg[1] == 'w' && arg[2] == 0) | ||
895 | put = 1; | ||
896 | else if (arg[1] >= '0' && arg[1] <= '9') | ||
897 | skip = (unsigned)atoi(arg + 1); | ||
898 | else { | ||
899 | fprintf(stderr, "invalid option %s\n", arg); | ||
900 | return 3; | ||
901 | } | ||
902 | } | ||
903 | else if (name != NULL) { | ||
904 | fprintf(stderr, "only one file name allowed\n"); | ||
905 | return 3; | ||
906 | } | ||
907 | else | ||
908 | name = arg; | ||
909 | source = load(name, &len); | ||
910 | if (source == NULL) { | ||
911 | fprintf(stderr, "memory allocation failure\n"); | ||
912 | return 4; | ||
913 | } | ||
914 | if (len == 0) { | ||
915 | fprintf(stderr, "could not read %s, or it was empty\n", | ||
916 | name == NULL ? "<stdin>" : name); | ||
917 | free(source); | ||
918 | return 3; | ||
919 | } | ||
920 | if (skip >= len) { | ||
921 | fprintf(stderr, "skip request of %d leaves no input\n", skip); | ||
922 | free(source); | ||
923 | return 3; | ||
924 | } | ||
925 | |||
926 | /* test inflate data with offset skip */ | ||
927 | len -= skip; | ||
928 | sourcelen = (unsigned long)len; | ||
929 | ret = puff(NIL, &destlen, source + skip, &sourcelen); | ||
930 | if (ret) | ||
931 | fprintf(stderr, "puff() failed with return code %d\n", ret); | ||
932 | else { | ||
933 | fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen); | ||
934 | if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n", | ||
935 | len - sourcelen); | ||
936 | } | ||
937 | |||
938 | /* if requested, inflate again and write decompressd data to stdout */ | ||
939 | if (put) { | ||
940 | dest = malloc(destlen); | ||
941 | if (dest == NULL) { | ||
942 | fprintf(stderr, "memory allocation failure\n"); | ||
943 | free(source); | ||
944 | return 4; | ||
945 | } | ||
946 | puff(dest, &destlen, source + skip, &sourcelen); | ||
947 | fwrite(dest, 1, destlen, stdout); | ||
948 | free(dest); | ||
949 | } | ||
950 | |||
951 | /* clean up */ | ||
952 | free(source); | ||
953 | return ret; | ||
954 | } | ||
955 | #endif | ||
diff --git a/contrib/puff/puff.h b/contrib/puff/puff.h index 88d1b38..6a0080a 100644 --- a/contrib/puff/puff.h +++ b/contrib/puff/puff.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* puff.h | 1 | /* puff.h |
2 | Copyright (C) 2002-2010 Mark Adler, all rights reserved | 2 | Copyright (C) 2002-2010 Mark Adler, all rights reserved |
3 | version 2.1, 4 Apr 2010 | 3 | version 2.2, 25 Apr 2010 |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the author be held liable for any damages | 6 | warranty. In no event will the author be held liable for any damages |
@@ -25,7 +25,11 @@ | |||
25 | /* | 25 | /* |
26 | * See puff.c for purpose and usage. | 26 | * See puff.c for purpose and usage. |
27 | */ | 27 | */ |
28 | #ifndef NIL | ||
29 | # define NIL ((unsigned char *)0) /* for no output option */ | ||
30 | #endif | ||
31 | |||
28 | int puff(unsigned char *dest, /* pointer to destination pointer */ | 32 | int puff(unsigned char *dest, /* pointer to destination pointer */ |
29 | unsigned long *destlen, /* amount of output space */ | 33 | unsigned long *destlen, /* amount of output space */ |
30 | unsigned char *source, /* pointer to source data pointer */ | 34 | const unsigned char *source, /* pointer to source data pointer */ |
31 | unsigned long *sourcelen); /* amount of input available */ | 35 | unsigned long *sourcelen); /* amount of input available */ |
diff --git a/contrib/puff/pufftest.c b/contrib/puff/pufftest.c new file mode 100644 index 0000000..76e35f6 --- /dev/null +++ b/contrib/puff/pufftest.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * pufftest.c | ||
3 | * Copyright (C) 2002-2010 Mark Adler | ||
4 | * For conditions of distribution and use, see copyright notice in puff.h | ||
5 | * version 2.2, 25 Apr 2010 | ||
6 | */ | ||
7 | |||
8 | /* Example of how to use puff(). | ||
9 | |||
10 | Usage: puff [-w] [-f] [-nnn] file | ||
11 | ... | puff [-w] [-f] [-nnn] | ||
12 | |||
13 | where file is the input file with deflate data, nnn is the number of bytes | ||
14 | of input to skip before inflating (e.g. to skip a zlib or gzip header), and | ||
15 | -w is used to write the decompressed data to stdout. -f is for coverage | ||
16 | testing, and causes pufftest to fail with not enough output space (-f does | ||
17 | a write like -w, so -w is not required). */ | ||
18 | |||
19 | #include <stdio.h> | ||
20 | #include <stdlib.h> | ||
21 | #include "puff.h" | ||
22 | |||
23 | #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) | ||
24 | # include <fcntl.h> | ||
25 | # include <io.h> | ||
26 | # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) | ||
27 | #else | ||
28 | # define SET_BINARY_MODE(file) | ||
29 | #endif | ||
30 | |||
31 | #define local static | ||
32 | |||
33 | /* Return size times approximately the cube root of 2, keeping the result as 1, | ||
34 | 3, or 5 times a power of 2 -- the result is always > size, until the result | ||
35 | is the maximum value of an unsigned long, where it remains. This is useful | ||
36 | to keep reallocations less than ~33% over the actual data. */ | ||
37 | local size_t bythirds(size_t size) | ||
38 | { | ||
39 | int n; | ||
40 | size_t m; | ||
41 | |||
42 | m = size; | ||
43 | for (n = 0; m; n++) | ||
44 | m >>= 1; | ||
45 | if (n < 3) | ||
46 | return size + 1; | ||
47 | n -= 3; | ||
48 | m = size >> n; | ||
49 | m += m == 6 ? 2 : 1; | ||
50 | m <<= n; | ||
51 | return m > size ? m : (size_t)(-1); | ||
52 | } | ||
53 | |||
54 | /* Read the input file *name, or stdin if name is NULL, into allocated memory. | ||
55 | Reallocate to larger buffers until the entire file is read in. Return a | ||
56 | pointer to the allocated data, or NULL if there was a memory allocation | ||
57 | failure. *len is the number of bytes of data read from the input file (even | ||
58 | if load() returns NULL). If the input file was empty or could not be opened | ||
59 | or read, *len is zero. */ | ||
60 | local void *load(const char *name, size_t *len) | ||
61 | { | ||
62 | size_t size; | ||
63 | void *buf, *swap; | ||
64 | FILE *in; | ||
65 | |||
66 | *len = 0; | ||
67 | buf = malloc(size = 4096); | ||
68 | if (buf == NULL) | ||
69 | return NULL; | ||
70 | in = name == NULL ? stdin : fopen(name, "rb"); | ||
71 | if (in != NULL) { | ||
72 | for (;;) { | ||
73 | *len += fread((char *)buf + *len, 1, size - *len, in); | ||
74 | if (*len < size) break; | ||
75 | size = bythirds(size); | ||
76 | if (size == *len || (swap = realloc(buf, size)) == NULL) { | ||
77 | free(buf); | ||
78 | buf = NULL; | ||
79 | break; | ||
80 | } | ||
81 | buf = swap; | ||
82 | } | ||
83 | fclose(in); | ||
84 | } | ||
85 | return buf; | ||
86 | } | ||
87 | |||
88 | int main(int argc, char **argv) | ||
89 | { | ||
90 | int ret, put = 0, fail = 0; | ||
91 | unsigned skip = 0; | ||
92 | char *arg, *name = NULL; | ||
93 | unsigned char *source = NULL, *dest; | ||
94 | size_t len = 0; | ||
95 | unsigned long sourcelen, destlen; | ||
96 | |||
97 | /* process arguments */ | ||
98 | while (arg = *++argv, --argc) | ||
99 | if (arg[0] == '-') { | ||
100 | if (arg[1] == 'w' && arg[2] == 0) | ||
101 | put = 1; | ||
102 | else if (arg[1] == 'f' && arg[2] == 0) | ||
103 | fail = 1, put = 1; | ||
104 | else if (arg[1] >= '0' && arg[1] <= '9') | ||
105 | skip = (unsigned)atoi(arg + 1); | ||
106 | else { | ||
107 | fprintf(stderr, "invalid option %s\n", arg); | ||
108 | return 3; | ||
109 | } | ||
110 | } | ||
111 | else if (name != NULL) { | ||
112 | fprintf(stderr, "only one file name allowed\n"); | ||
113 | return 3; | ||
114 | } | ||
115 | else | ||
116 | name = arg; | ||
117 | source = load(name, &len); | ||
118 | if (source == NULL) { | ||
119 | fprintf(stderr, "memory allocation failure\n"); | ||
120 | return 4; | ||
121 | } | ||
122 | if (len == 0) { | ||
123 | fprintf(stderr, "could not read %s, or it was empty\n", | ||
124 | name == NULL ? "<stdin>" : name); | ||
125 | free(source); | ||
126 | return 3; | ||
127 | } | ||
128 | if (skip >= len) { | ||
129 | fprintf(stderr, "skip request of %d leaves no input\n", skip); | ||
130 | free(source); | ||
131 | return 3; | ||
132 | } | ||
133 | |||
134 | /* test inflate data with offset skip */ | ||
135 | len -= skip; | ||
136 | sourcelen = (unsigned long)len; | ||
137 | ret = puff(NIL, &destlen, source + skip, &sourcelen); | ||
138 | if (ret) | ||
139 | fprintf(stderr, "puff() failed with return code %d\n", ret); | ||
140 | else { | ||
141 | fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen); | ||
142 | if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n", | ||
143 | len - sourcelen); | ||
144 | } | ||
145 | |||
146 | /* if requested, inflate again and write decompressd data to stdout */ | ||
147 | if (put && ret == 0) { | ||
148 | if (fail) | ||
149 | destlen >>= 1; | ||
150 | dest = malloc(destlen); | ||
151 | if (dest == NULL) { | ||
152 | fprintf(stderr, "memory allocation failure\n"); | ||
153 | free(source); | ||
154 | return 4; | ||
155 | } | ||
156 | puff(dest, &destlen, source + skip, &sourcelen); | ||
157 | SET_BINARY_MODE(stdout); | ||
158 | fwrite(dest, 1, destlen, stdout); | ||
159 | free(dest); | ||
160 | } | ||
161 | |||
162 | /* clean up */ | ||
163 | free(source); | ||
164 | return ret; | ||
165 | } | ||
diff --git a/contrib/puff/zeros.raw b/contrib/puff/zeros.raw index 637b7be..0a90e76 100644 --- a/contrib/puff/zeros.raw +++ b/contrib/puff/zeros.raw | |||
Binary files differ | |||