|
7ef7284…
|
drh
|
1 |
Puff -- A Simple Inflate |
|
7ef7284…
|
drh
|
2 |
3 Mar 2003 |
|
7ef7284…
|
drh
|
3 |
Mark Adler |
|
7ef7284…
|
drh
|
4 |
[email protected] |
|
7ef7284…
|
drh
|
5 |
|
|
7ef7284…
|
drh
|
6 |
What this is -- |
|
7ef7284…
|
drh
|
7 |
|
|
7ef7284…
|
drh
|
8 |
puff.c provides the routine puff() to decompress the deflate data format. It |
|
7ef7284…
|
drh
|
9 |
does so more slowly than zlib, but the code is about one-fifth the size of the |
|
7ef7284…
|
drh
|
10 |
inflate code in zlib, and written to be very easy to read. |
|
7ef7284…
|
drh
|
11 |
|
|
7ef7284…
|
drh
|
12 |
Why I wrote this -- |
|
7ef7284…
|
drh
|
13 |
|
|
7ef7284…
|
drh
|
14 |
puff.c was written to document the deflate format unambiguously, by virtue of |
|
7ef7284…
|
drh
|
15 |
being working C code. It is meant to supplement RFC 1951, which formally |
|
7ef7284…
|
drh
|
16 |
describes the deflate format. I have received many questions on details of the |
|
7ef7284…
|
drh
|
17 |
deflate format, and I hope that reading this code will answer those questions. |
|
7ef7284…
|
drh
|
18 |
puff.c is heavily commented with details of the deflate format, especially |
|
7ef7284…
|
drh
|
19 |
those little nooks and cranies of the format that might not be obvious from a |
|
7ef7284…
|
drh
|
20 |
specification. |
|
7ef7284…
|
drh
|
21 |
|
|
7ef7284…
|
drh
|
22 |
puff.c may also be useful in applications where code size or memory usage is a |
|
7ef7284…
|
drh
|
23 |
very limited resource, and speed is not as important. |
|
7ef7284…
|
drh
|
24 |
|
|
7ef7284…
|
drh
|
25 |
How to use it -- |
|
7ef7284…
|
drh
|
26 |
|
|
7ef7284…
|
drh
|
27 |
Well, most likely you should just be reading puff.c and using zlib for actual |
|
7ef7284…
|
drh
|
28 |
applications, but if you must ... |
|
7ef7284…
|
drh
|
29 |
|
|
7ef7284…
|
drh
|
30 |
Include puff.h in your code, which provides this prototype: |
|
7ef7284…
|
drh
|
31 |
|
|
7ef7284…
|
drh
|
32 |
int puff(unsigned char *dest, /* pointer to destination pointer */ |
|
7ef7284…
|
drh
|
33 |
unsigned long *destlen, /* amount of output space */ |
|
7ef7284…
|
drh
|
34 |
unsigned char *source, /* pointer to source data pointer */ |
|
7ef7284…
|
drh
|
35 |
unsigned long *sourcelen); /* amount of input available */ |
|
7ef7284…
|
drh
|
36 |
|
|
7ef7284…
|
drh
|
37 |
Then you can call puff() to decompress a deflate stream that is in memory in |
|
7ef7284…
|
drh
|
38 |
its entirety at source, to a sufficiently sized block of memory for the |
|
7ef7284…
|
drh
|
39 |
decompressed data at dest. puff() is the only external symbol in puff.c The |
|
7ef7284…
|
drh
|
40 |
only C library functions that puff.c needs are setjmp() and longjmp(), which |
|
a9e589c…
|
florian
|
41 |
are used to simplify error checking in the code to improve readability. puff.c |
|
7ef7284…
|
drh
|
42 |
does no memory allocation, and uses less than 2K bytes off of the stack. |
|
7ef7284…
|
drh
|
43 |
|
|
7ef7284…
|
drh
|
44 |
If destlen is not enough space for the uncompressed data, then inflate will |
|
7ef7284…
|
drh
|
45 |
return an error without writing more than destlen bytes. Note that this means |
|
7ef7284…
|
drh
|
46 |
that in order to decompress the deflate data successfully, you need to know |
|
7ef7284…
|
drh
|
47 |
the size of the uncompressed data ahead of time. |
|
7ef7284…
|
drh
|
48 |
|
|
7ef7284…
|
drh
|
49 |
If needed, puff() can determine the size of the uncompressed data with no |
|
7ef7284…
|
drh
|
50 |
output space. This is done by passing dest equal to (unsigned char *)0. Then |
|
7ef7284…
|
drh
|
51 |
the initial value of *destlen is ignored and *destlen is set to the length of |
|
7ef7284…
|
drh
|
52 |
the uncompressed data. So if the size of the uncompressed data is not known, |
|
7ef7284…
|
drh
|
53 |
then two passes of puff() can be used--first to determine the size, and second |
|
7ef7284…
|
drh
|
54 |
to do the actual inflation after allocating the appropriate memory. Not |
|
7ef7284…
|
drh
|
55 |
pretty, but it works. (This is one of the reasons you should be using zlib.) |
|
7ef7284…
|
drh
|
56 |
|
|
7ef7284…
|
drh
|
57 |
The deflate format is self-terminating. If the deflate stream does not end |
|
7ef7284…
|
drh
|
58 |
in *sourcelen bytes, puff() will return an error without reading at or past |
|
7ef7284…
|
drh
|
59 |
endsource. |
|
7ef7284…
|
drh
|
60 |
|
|
7ef7284…
|
drh
|
61 |
On return, *sourcelen is updated to the amount of input data consumed, and |
|
7ef7284…
|
drh
|
62 |
*destlen is updated to the size of the uncompressed data. See the comments |
|
7ef7284…
|
drh
|
63 |
in puff.c for the possible return codes for puff(). |