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