diff options
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 b6b69404..0e2594c8 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 650694e9..df8470c9 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 88d1b384..6a0080ae 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 00000000..76e35f66 --- /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 637b7be6..0a90e76b 100644 --- a/contrib/puff/zeros.raw +++ b/contrib/puff/zeros.raw | |||
| Binary files differ | |||
