Basic gzip/gunzip in memory buffer examples using zlib code.

Dependencies:   mbed-rtos mbed

There are small changes needed to the zconf.h file in the zlib distribution (I used 1.2.7). The zlib license applies to the zlib code - I have only imported a subset of the source.

The MBED has limited memory, so we need the following (near the top of zconf.h) to restrict memory allocation sizes:

#define    MAX_MEM_LEVEL    3
#define    MAX_WBITS        10

Because MAX_MEM_LEVEL and MAX_WBITS are so much lower than the default, there is a danger that the mbed cannot gunzip data compressed by a 'normal' zlib build. My use-case is to gzip on the mbed more than gunzip on the mbed so I have not given much time to this issue.

I also included this (also near the top of zconf.h) to prefix defines with Z_

#define    Z_PREFIX

In zconf.h, in the zlib distribution, the includes for <fcntl.h> and <sys/types.h> need commenting out when using the online compiler. No need when using GCC4MBED.

I also looked at miniz. I chose zlib because I needed the gzip headers and miniz does not implement them.

The sample main.cpp reads source data, compresses it, decompresses it, and finally compares the input data with the output data to confirm they are the same.

    unsigned char input_data[2048];
    unsigned long input_data_length = 0;
    FILE *ifp = fopen("/local/src.txt", "r");
    if (ifp) {
        int br = fread(input_data, 1, sizeof(input_data), ifp);
        fclose(ifp);
        input_data_length = br;
    }
    printf("%s:%d: input_data_length:%lu%s", __FILE__, __LINE__, input_data_length, newline);
 
 
    unsigned char gzip_data[2048];
    unsigned long gzip_data_length = 0;
    if (input_data_length > 0) {
        gzip_data_length = sizeof(gzip_data);
        int rv = gzip(gzip_data, &gzip_data_length, input_data, input_data_length);
        if (Z_OK == rv) {
            FILE *ofp = fopen("/local/dst.gz", "w");
            if (ofp) {
                int bw = fwrite(gzip_data, 1, gzip_data_length, ofp);
                fclose(ofp);
            }
        } else {
            printf("%s:%d: %d%s", __FILE__, __LINE__, rv, newline);
        }
    }
    printf("%s:%d: gzip_data_length:%lu%s", __FILE__, __LINE__, gzip_data_length, newline);
 
 
    unsigned char output_data[2048];
    unsigned long output_data_length = 0;
    if (gzip_data_length > 0) {
        output_data_length = sizeof(output_data);
        int rv = gunzip(output_data, &output_data_length, gzip_data, gzip_data_length);
        if (Z_OK != rv) {
            printf("%s:%d: %d%s", __FILE__, __LINE__, rv, newline);
        }
    }
    printf("%s:%d: output_data_length:%lu%s", __FILE__, __LINE__, output_data_length, newline);
 
 
    if (input_data_length > 0 and input_data_length > 0) {
        bool input_matches_output = false;
        if (input_data_length == output_data_length) {
            input_matches_output = true;
            for ( size_t i = 0 ; input_matches_output && i < input_data_length ; i++ ) {
                if (input_data[i] != output_data[i]) {
                    input_matches_output = false;
                }
            }
        }
        printf("%s:%d: input (%lu bytes) %s output (%lu bytes)%s", __FILE__, __LINE__, input_data_length, input_matches_output?"matches":"does not match", output_data_length, newline);
    } else {
        printf("%s:%d: input and/or output length is 0%s", __FILE__, __LINE__, newline);
    }
Committer:
jonathonfletcher
Date:
Sun Oct 21 07:46:41 2012 +0000
Revision:
0:54f5be781526
initial checkin

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jonathonfletcher 0:54f5be781526 1 /* inflate.c -- zlib decompression
jonathonfletcher 0:54f5be781526 2 * Copyright (C) 1995-2012 Mark Adler
jonathonfletcher 0:54f5be781526 3 * For conditions of distribution and use, see copyright notice in zlib.h
jonathonfletcher 0:54f5be781526 4 */
jonathonfletcher 0:54f5be781526 5
jonathonfletcher 0:54f5be781526 6 /*
jonathonfletcher 0:54f5be781526 7 * Change history:
jonathonfletcher 0:54f5be781526 8 *
jonathonfletcher 0:54f5be781526 9 * 1.2.beta0 24 Nov 2002
jonathonfletcher 0:54f5be781526 10 * - First version -- complete rewrite of inflate to simplify code, avoid
jonathonfletcher 0:54f5be781526 11 * creation of window when not needed, minimize use of window when it is
jonathonfletcher 0:54f5be781526 12 * needed, make inffast.c even faster, implement gzip decoding, and to
jonathonfletcher 0:54f5be781526 13 * improve code readability and style over the previous zlib inflate code
jonathonfletcher 0:54f5be781526 14 *
jonathonfletcher 0:54f5be781526 15 * 1.2.beta1 25 Nov 2002
jonathonfletcher 0:54f5be781526 16 * - Use pointers for available input and output checking in inffast.c
jonathonfletcher 0:54f5be781526 17 * - Remove input and output counters in inffast.c
jonathonfletcher 0:54f5be781526 18 * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
jonathonfletcher 0:54f5be781526 19 * - Remove unnecessary second byte pull from length extra in inffast.c
jonathonfletcher 0:54f5be781526 20 * - Unroll direct copy to three copies per loop in inffast.c
jonathonfletcher 0:54f5be781526 21 *
jonathonfletcher 0:54f5be781526 22 * 1.2.beta2 4 Dec 2002
jonathonfletcher 0:54f5be781526 23 * - Change external routine names to reduce potential conflicts
jonathonfletcher 0:54f5be781526 24 * - Correct filename to inffixed.h for fixed tables in inflate.c
jonathonfletcher 0:54f5be781526 25 * - Make hbuf[] unsigned char to match parameter type in inflate.c
jonathonfletcher 0:54f5be781526 26 * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
jonathonfletcher 0:54f5be781526 27 * to avoid negation problem on Alphas (64 bit) in inflate.c
jonathonfletcher 0:54f5be781526 28 *
jonathonfletcher 0:54f5be781526 29 * 1.2.beta3 22 Dec 2002
jonathonfletcher 0:54f5be781526 30 * - Add comments on state->bits assertion in inffast.c
jonathonfletcher 0:54f5be781526 31 * - Add comments on op field in inftrees.h
jonathonfletcher 0:54f5be781526 32 * - Fix bug in reuse of allocated window after inflateReset()
jonathonfletcher 0:54f5be781526 33 * - Remove bit fields--back to byte structure for speed
jonathonfletcher 0:54f5be781526 34 * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
jonathonfletcher 0:54f5be781526 35 * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
jonathonfletcher 0:54f5be781526 36 * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
jonathonfletcher 0:54f5be781526 37 * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
jonathonfletcher 0:54f5be781526 38 * - Use local copies of stream next and avail values, as well as local bit
jonathonfletcher 0:54f5be781526 39 * buffer and bit count in inflate()--for speed when inflate_fast() not used
jonathonfletcher 0:54f5be781526 40 *
jonathonfletcher 0:54f5be781526 41 * 1.2.beta4 1 Jan 2003
jonathonfletcher 0:54f5be781526 42 * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
jonathonfletcher 0:54f5be781526 43 * - Move a comment on output buffer sizes from inffast.c to inflate.c
jonathonfletcher 0:54f5be781526 44 * - Add comments in inffast.c to introduce the inflate_fast() routine
jonathonfletcher 0:54f5be781526 45 * - Rearrange window copies in inflate_fast() for speed and simplification
jonathonfletcher 0:54f5be781526 46 * - Unroll last copy for window match in inflate_fast()
jonathonfletcher 0:54f5be781526 47 * - Use local copies of window variables in inflate_fast() for speed
jonathonfletcher 0:54f5be781526 48 * - Pull out common wnext == 0 case for speed in inflate_fast()
jonathonfletcher 0:54f5be781526 49 * - Make op and len in inflate_fast() unsigned for consistency
jonathonfletcher 0:54f5be781526 50 * - Add FAR to lcode and dcode declarations in inflate_fast()
jonathonfletcher 0:54f5be781526 51 * - Simplified bad distance check in inflate_fast()
jonathonfletcher 0:54f5be781526 52 * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
jonathonfletcher 0:54f5be781526 53 * source file infback.c to provide a call-back interface to inflate for
jonathonfletcher 0:54f5be781526 54 * programs like gzip and unzip -- uses window as output buffer to avoid
jonathonfletcher 0:54f5be781526 55 * window copying
jonathonfletcher 0:54f5be781526 56 *
jonathonfletcher 0:54f5be781526 57 * 1.2.beta5 1 Jan 2003
jonathonfletcher 0:54f5be781526 58 * - Improved inflateBack() interface to allow the caller to provide initial
jonathonfletcher 0:54f5be781526 59 * input in strm.
jonathonfletcher 0:54f5be781526 60 * - Fixed stored blocks bug in inflateBack()
jonathonfletcher 0:54f5be781526 61 *
jonathonfletcher 0:54f5be781526 62 * 1.2.beta6 4 Jan 2003
jonathonfletcher 0:54f5be781526 63 * - Added comments in inffast.c on effectiveness of POSTINC
jonathonfletcher 0:54f5be781526 64 * - Typecasting all around to reduce compiler warnings
jonathonfletcher 0:54f5be781526 65 * - Changed loops from while (1) or do {} while (1) to for (;;), again to
jonathonfletcher 0:54f5be781526 66 * make compilers happy
jonathonfletcher 0:54f5be781526 67 * - Changed type of window in inflateBackInit() to unsigned char *
jonathonfletcher 0:54f5be781526 68 *
jonathonfletcher 0:54f5be781526 69 * 1.2.beta7 27 Jan 2003
jonathonfletcher 0:54f5be781526 70 * - Changed many types to unsigned or unsigned short to avoid warnings
jonathonfletcher 0:54f5be781526 71 * - Added inflateCopy() function
jonathonfletcher 0:54f5be781526 72 *
jonathonfletcher 0:54f5be781526 73 * 1.2.0 9 Mar 2003
jonathonfletcher 0:54f5be781526 74 * - Changed inflateBack() interface to provide separate opaque descriptors
jonathonfletcher 0:54f5be781526 75 * for the in() and out() functions
jonathonfletcher 0:54f5be781526 76 * - Changed inflateBack() argument and in_func typedef to swap the length
jonathonfletcher 0:54f5be781526 77 * and buffer address return values for the input function
jonathonfletcher 0:54f5be781526 78 * - Check next_in and next_out for Z_NULL on entry to inflate()
jonathonfletcher 0:54f5be781526 79 *
jonathonfletcher 0:54f5be781526 80 * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
jonathonfletcher 0:54f5be781526 81 */
jonathonfletcher 0:54f5be781526 82
jonathonfletcher 0:54f5be781526 83 #include "zutil.h"
jonathonfletcher 0:54f5be781526 84 #include "inftrees.h"
jonathonfletcher 0:54f5be781526 85 #include "inflate.h"
jonathonfletcher 0:54f5be781526 86 #include "inffast.h"
jonathonfletcher 0:54f5be781526 87
jonathonfletcher 0:54f5be781526 88 #ifdef MAKEFIXED
jonathonfletcher 0:54f5be781526 89 # ifndef BUILDFIXED
jonathonfletcher 0:54f5be781526 90 # define BUILDFIXED
jonathonfletcher 0:54f5be781526 91 # endif
jonathonfletcher 0:54f5be781526 92 #endif
jonathonfletcher 0:54f5be781526 93
jonathonfletcher 0:54f5be781526 94 /* function prototypes */
jonathonfletcher 0:54f5be781526 95 local void fixedtables OF((struct inflate_state FAR *state));
jonathonfletcher 0:54f5be781526 96 local int updatewindow OF((z_streamp strm, unsigned out));
jonathonfletcher 0:54f5be781526 97 #ifdef BUILDFIXED
jonathonfletcher 0:54f5be781526 98 void makefixed OF((void));
jonathonfletcher 0:54f5be781526 99 #endif
jonathonfletcher 0:54f5be781526 100 local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
jonathonfletcher 0:54f5be781526 101 unsigned len));
jonathonfletcher 0:54f5be781526 102
jonathonfletcher 0:54f5be781526 103 int ZEXPORT inflateResetKeep(strm)
jonathonfletcher 0:54f5be781526 104 z_streamp strm;
jonathonfletcher 0:54f5be781526 105 {
jonathonfletcher 0:54f5be781526 106 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 107
jonathonfletcher 0:54f5be781526 108 if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 109 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 110 strm->total_in = strm->total_out = state->total = 0;
jonathonfletcher 0:54f5be781526 111 strm->msg = Z_NULL;
jonathonfletcher 0:54f5be781526 112 if (state->wrap) /* to support ill-conceived Java test suite */
jonathonfletcher 0:54f5be781526 113 strm->adler = state->wrap & 1;
jonathonfletcher 0:54f5be781526 114 state->mode = HEAD;
jonathonfletcher 0:54f5be781526 115 state->last = 0;
jonathonfletcher 0:54f5be781526 116 state->havedict = 0;
jonathonfletcher 0:54f5be781526 117 state->dmax = 32768U;
jonathonfletcher 0:54f5be781526 118 state->head = Z_NULL;
jonathonfletcher 0:54f5be781526 119 state->hold = 0;
jonathonfletcher 0:54f5be781526 120 state->bits = 0;
jonathonfletcher 0:54f5be781526 121 state->lencode = state->distcode = state->next = state->codes;
jonathonfletcher 0:54f5be781526 122 state->sane = 1;
jonathonfletcher 0:54f5be781526 123 state->back = -1;
jonathonfletcher 0:54f5be781526 124 Tracev((stderr, "inflate: reset\n"));
jonathonfletcher 0:54f5be781526 125 return Z_OK;
jonathonfletcher 0:54f5be781526 126 }
jonathonfletcher 0:54f5be781526 127
jonathonfletcher 0:54f5be781526 128 int ZEXPORT inflateReset(strm)
jonathonfletcher 0:54f5be781526 129 z_streamp strm;
jonathonfletcher 0:54f5be781526 130 {
jonathonfletcher 0:54f5be781526 131 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 132
jonathonfletcher 0:54f5be781526 133 if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 134 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 135 state->wsize = 0;
jonathonfletcher 0:54f5be781526 136 state->whave = 0;
jonathonfletcher 0:54f5be781526 137 state->wnext = 0;
jonathonfletcher 0:54f5be781526 138 return inflateResetKeep(strm);
jonathonfletcher 0:54f5be781526 139 }
jonathonfletcher 0:54f5be781526 140
jonathonfletcher 0:54f5be781526 141 int ZEXPORT inflateReset2(strm, windowBits)
jonathonfletcher 0:54f5be781526 142 z_streamp strm;
jonathonfletcher 0:54f5be781526 143 int windowBits;
jonathonfletcher 0:54f5be781526 144 {
jonathonfletcher 0:54f5be781526 145 int wrap;
jonathonfletcher 0:54f5be781526 146 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 147
jonathonfletcher 0:54f5be781526 148 /* get the state */
jonathonfletcher 0:54f5be781526 149 if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 150 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 151
jonathonfletcher 0:54f5be781526 152 /* extract wrap request from windowBits parameter */
jonathonfletcher 0:54f5be781526 153 if (windowBits < 0) {
jonathonfletcher 0:54f5be781526 154 wrap = 0;
jonathonfletcher 0:54f5be781526 155 windowBits = -windowBits;
jonathonfletcher 0:54f5be781526 156 }
jonathonfletcher 0:54f5be781526 157 else {
jonathonfletcher 0:54f5be781526 158 wrap = (windowBits >> 4) + 1;
jonathonfletcher 0:54f5be781526 159 #ifdef GUNZIP
jonathonfletcher 0:54f5be781526 160 if (windowBits < 48)
jonathonfletcher 0:54f5be781526 161 windowBits &= 15;
jonathonfletcher 0:54f5be781526 162 #endif
jonathonfletcher 0:54f5be781526 163 }
jonathonfletcher 0:54f5be781526 164
jonathonfletcher 0:54f5be781526 165 /* set number of window bits, free window if different */
jonathonfletcher 0:54f5be781526 166 if (windowBits && (windowBits < 8 || windowBits > 15))
jonathonfletcher 0:54f5be781526 167 return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 168 if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
jonathonfletcher 0:54f5be781526 169 ZFREE(strm, state->window);
jonathonfletcher 0:54f5be781526 170 state->window = Z_NULL;
jonathonfletcher 0:54f5be781526 171 }
jonathonfletcher 0:54f5be781526 172
jonathonfletcher 0:54f5be781526 173 /* update state and reset the rest of it */
jonathonfletcher 0:54f5be781526 174 state->wrap = wrap;
jonathonfletcher 0:54f5be781526 175 state->wbits = (unsigned)windowBits;
jonathonfletcher 0:54f5be781526 176 return inflateReset(strm);
jonathonfletcher 0:54f5be781526 177 }
jonathonfletcher 0:54f5be781526 178
jonathonfletcher 0:54f5be781526 179 int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
jonathonfletcher 0:54f5be781526 180 z_streamp strm;
jonathonfletcher 0:54f5be781526 181 int windowBits;
jonathonfletcher 0:54f5be781526 182 const char *version;
jonathonfletcher 0:54f5be781526 183 int stream_size;
jonathonfletcher 0:54f5be781526 184 {
jonathonfletcher 0:54f5be781526 185 int ret;
jonathonfletcher 0:54f5be781526 186 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 187
jonathonfletcher 0:54f5be781526 188 if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
jonathonfletcher 0:54f5be781526 189 stream_size != (int)(sizeof(z_stream)))
jonathonfletcher 0:54f5be781526 190 return Z_VERSION_ERROR;
jonathonfletcher 0:54f5be781526 191 if (strm == Z_NULL) return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 192 strm->msg = Z_NULL; /* in case we return an error */
jonathonfletcher 0:54f5be781526 193 if (strm->zalloc == (alloc_func)0) {
jonathonfletcher 0:54f5be781526 194 #ifdef Z_SOLO
jonathonfletcher 0:54f5be781526 195 return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 196 #else
jonathonfletcher 0:54f5be781526 197 strm->zalloc = zcalloc;
jonathonfletcher 0:54f5be781526 198 strm->opaque = (voidpf)0;
jonathonfletcher 0:54f5be781526 199 #endif
jonathonfletcher 0:54f5be781526 200 }
jonathonfletcher 0:54f5be781526 201 if (strm->zfree == (free_func)0)
jonathonfletcher 0:54f5be781526 202 #ifdef Z_SOLO
jonathonfletcher 0:54f5be781526 203 return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 204 #else
jonathonfletcher 0:54f5be781526 205 strm->zfree = zcfree;
jonathonfletcher 0:54f5be781526 206 #endif
jonathonfletcher 0:54f5be781526 207 state = (struct inflate_state FAR *)
jonathonfletcher 0:54f5be781526 208 ZALLOC(strm, 1, sizeof(struct inflate_state));
jonathonfletcher 0:54f5be781526 209 if (state == Z_NULL) return Z_MEM_ERROR;
jonathonfletcher 0:54f5be781526 210 Tracev((stderr, "inflate: allocated\n"));
jonathonfletcher 0:54f5be781526 211 strm->state = (struct internal_state FAR *)state;
jonathonfletcher 0:54f5be781526 212 state->window = Z_NULL;
jonathonfletcher 0:54f5be781526 213 ret = inflateReset2(strm, windowBits);
jonathonfletcher 0:54f5be781526 214 if (ret != Z_OK) {
jonathonfletcher 0:54f5be781526 215 ZFREE(strm, state);
jonathonfletcher 0:54f5be781526 216 strm->state = Z_NULL;
jonathonfletcher 0:54f5be781526 217 }
jonathonfletcher 0:54f5be781526 218 return ret;
jonathonfletcher 0:54f5be781526 219 }
jonathonfletcher 0:54f5be781526 220
jonathonfletcher 0:54f5be781526 221 int ZEXPORT inflateInit_(strm, version, stream_size)
jonathonfletcher 0:54f5be781526 222 z_streamp strm;
jonathonfletcher 0:54f5be781526 223 const char *version;
jonathonfletcher 0:54f5be781526 224 int stream_size;
jonathonfletcher 0:54f5be781526 225 {
jonathonfletcher 0:54f5be781526 226 return inflateInit2_(strm, DEF_WBITS, version, stream_size);
jonathonfletcher 0:54f5be781526 227 }
jonathonfletcher 0:54f5be781526 228
jonathonfletcher 0:54f5be781526 229 int ZEXPORT inflatePrime(strm, bits, value)
jonathonfletcher 0:54f5be781526 230 z_streamp strm;
jonathonfletcher 0:54f5be781526 231 int bits;
jonathonfletcher 0:54f5be781526 232 int value;
jonathonfletcher 0:54f5be781526 233 {
jonathonfletcher 0:54f5be781526 234 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 235
jonathonfletcher 0:54f5be781526 236 if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 237 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 238 if (bits < 0) {
jonathonfletcher 0:54f5be781526 239 state->hold = 0;
jonathonfletcher 0:54f5be781526 240 state->bits = 0;
jonathonfletcher 0:54f5be781526 241 return Z_OK;
jonathonfletcher 0:54f5be781526 242 }
jonathonfletcher 0:54f5be781526 243 if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 244 value &= (1L << bits) - 1;
jonathonfletcher 0:54f5be781526 245 state->hold += value << state->bits;
jonathonfletcher 0:54f5be781526 246 state->bits += bits;
jonathonfletcher 0:54f5be781526 247 return Z_OK;
jonathonfletcher 0:54f5be781526 248 }
jonathonfletcher 0:54f5be781526 249
jonathonfletcher 0:54f5be781526 250 /*
jonathonfletcher 0:54f5be781526 251 Return state with length and distance decoding tables and index sizes set to
jonathonfletcher 0:54f5be781526 252 fixed code decoding. Normally this returns fixed tables from inffixed.h.
jonathonfletcher 0:54f5be781526 253 If BUILDFIXED is defined, then instead this routine builds the tables the
jonathonfletcher 0:54f5be781526 254 first time it's called, and returns those tables the first time and
jonathonfletcher 0:54f5be781526 255 thereafter. This reduces the size of the code by about 2K bytes, in
jonathonfletcher 0:54f5be781526 256 exchange for a little execution time. However, BUILDFIXED should not be
jonathonfletcher 0:54f5be781526 257 used for threaded applications, since the rewriting of the tables and virgin
jonathonfletcher 0:54f5be781526 258 may not be thread-safe.
jonathonfletcher 0:54f5be781526 259 */
jonathonfletcher 0:54f5be781526 260 local void fixedtables(state)
jonathonfletcher 0:54f5be781526 261 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 262 {
jonathonfletcher 0:54f5be781526 263 #ifdef BUILDFIXED
jonathonfletcher 0:54f5be781526 264 static int virgin = 1;
jonathonfletcher 0:54f5be781526 265 static code *lenfix, *distfix;
jonathonfletcher 0:54f5be781526 266 static code fixed[544];
jonathonfletcher 0:54f5be781526 267
jonathonfletcher 0:54f5be781526 268 /* build fixed huffman tables if first call (may not be thread safe) */
jonathonfletcher 0:54f5be781526 269 if (virgin) {
jonathonfletcher 0:54f5be781526 270 unsigned sym, bits;
jonathonfletcher 0:54f5be781526 271 static code *next;
jonathonfletcher 0:54f5be781526 272
jonathonfletcher 0:54f5be781526 273 /* literal/length table */
jonathonfletcher 0:54f5be781526 274 sym = 0;
jonathonfletcher 0:54f5be781526 275 while (sym < 144) state->lens[sym++] = 8;
jonathonfletcher 0:54f5be781526 276 while (sym < 256) state->lens[sym++] = 9;
jonathonfletcher 0:54f5be781526 277 while (sym < 280) state->lens[sym++] = 7;
jonathonfletcher 0:54f5be781526 278 while (sym < 288) state->lens[sym++] = 8;
jonathonfletcher 0:54f5be781526 279 next = fixed;
jonathonfletcher 0:54f5be781526 280 lenfix = next;
jonathonfletcher 0:54f5be781526 281 bits = 9;
jonathonfletcher 0:54f5be781526 282 inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
jonathonfletcher 0:54f5be781526 283
jonathonfletcher 0:54f5be781526 284 /* distance table */
jonathonfletcher 0:54f5be781526 285 sym = 0;
jonathonfletcher 0:54f5be781526 286 while (sym < 32) state->lens[sym++] = 5;
jonathonfletcher 0:54f5be781526 287 distfix = next;
jonathonfletcher 0:54f5be781526 288 bits = 5;
jonathonfletcher 0:54f5be781526 289 inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
jonathonfletcher 0:54f5be781526 290
jonathonfletcher 0:54f5be781526 291 /* do this just once */
jonathonfletcher 0:54f5be781526 292 virgin = 0;
jonathonfletcher 0:54f5be781526 293 }
jonathonfletcher 0:54f5be781526 294 #else /* !BUILDFIXED */
jonathonfletcher 0:54f5be781526 295 # include "inffixed.h"
jonathonfletcher 0:54f5be781526 296 #endif /* BUILDFIXED */
jonathonfletcher 0:54f5be781526 297 state->lencode = lenfix;
jonathonfletcher 0:54f5be781526 298 state->lenbits = 9;
jonathonfletcher 0:54f5be781526 299 state->distcode = distfix;
jonathonfletcher 0:54f5be781526 300 state->distbits = 5;
jonathonfletcher 0:54f5be781526 301 }
jonathonfletcher 0:54f5be781526 302
jonathonfletcher 0:54f5be781526 303 #ifdef MAKEFIXED
jonathonfletcher 0:54f5be781526 304 #include <stdio.h>
jonathonfletcher 0:54f5be781526 305
jonathonfletcher 0:54f5be781526 306 /*
jonathonfletcher 0:54f5be781526 307 Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also
jonathonfletcher 0:54f5be781526 308 defines BUILDFIXED, so the tables are built on the fly. makefixed() writes
jonathonfletcher 0:54f5be781526 309 those tables to stdout, which would be piped to inffixed.h. A small program
jonathonfletcher 0:54f5be781526 310 can simply call makefixed to do this:
jonathonfletcher 0:54f5be781526 311
jonathonfletcher 0:54f5be781526 312 void makefixed(void);
jonathonfletcher 0:54f5be781526 313
jonathonfletcher 0:54f5be781526 314 int main(void)
jonathonfletcher 0:54f5be781526 315 {
jonathonfletcher 0:54f5be781526 316 makefixed();
jonathonfletcher 0:54f5be781526 317 return 0;
jonathonfletcher 0:54f5be781526 318 }
jonathonfletcher 0:54f5be781526 319
jonathonfletcher 0:54f5be781526 320 Then that can be linked with zlib built with MAKEFIXED defined and run:
jonathonfletcher 0:54f5be781526 321
jonathonfletcher 0:54f5be781526 322 a.out > inffixed.h
jonathonfletcher 0:54f5be781526 323 */
jonathonfletcher 0:54f5be781526 324 void makefixed()
jonathonfletcher 0:54f5be781526 325 {
jonathonfletcher 0:54f5be781526 326 unsigned low, size;
jonathonfletcher 0:54f5be781526 327 struct inflate_state state;
jonathonfletcher 0:54f5be781526 328
jonathonfletcher 0:54f5be781526 329 fixedtables(&state);
jonathonfletcher 0:54f5be781526 330 puts(" /* inffixed.h -- table for decoding fixed codes");
jonathonfletcher 0:54f5be781526 331 puts(" * Generated automatically by makefixed().");
jonathonfletcher 0:54f5be781526 332 puts(" */");
jonathonfletcher 0:54f5be781526 333 puts("");
jonathonfletcher 0:54f5be781526 334 puts(" /* WARNING: this file should *not* be used by applications.");
jonathonfletcher 0:54f5be781526 335 puts(" It is part of the implementation of this library and is");
jonathonfletcher 0:54f5be781526 336 puts(" subject to change. Applications should only use zlib.h.");
jonathonfletcher 0:54f5be781526 337 puts(" */");
jonathonfletcher 0:54f5be781526 338 puts("");
jonathonfletcher 0:54f5be781526 339 size = 1U << 9;
jonathonfletcher 0:54f5be781526 340 printf(" static const code lenfix[%u] = {", size);
jonathonfletcher 0:54f5be781526 341 low = 0;
jonathonfletcher 0:54f5be781526 342 for (;;) {
jonathonfletcher 0:54f5be781526 343 if ((low % 7) == 0) printf("\n ");
jonathonfletcher 0:54f5be781526 344 printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
jonathonfletcher 0:54f5be781526 345 state.lencode[low].bits, state.lencode[low].val);
jonathonfletcher 0:54f5be781526 346 if (++low == size) break;
jonathonfletcher 0:54f5be781526 347 putchar(',');
jonathonfletcher 0:54f5be781526 348 }
jonathonfletcher 0:54f5be781526 349 puts("\n };");
jonathonfletcher 0:54f5be781526 350 size = 1U << 5;
jonathonfletcher 0:54f5be781526 351 printf("\n static const code distfix[%u] = {", size);
jonathonfletcher 0:54f5be781526 352 low = 0;
jonathonfletcher 0:54f5be781526 353 for (;;) {
jonathonfletcher 0:54f5be781526 354 if ((low % 6) == 0) printf("\n ");
jonathonfletcher 0:54f5be781526 355 printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
jonathonfletcher 0:54f5be781526 356 state.distcode[low].val);
jonathonfletcher 0:54f5be781526 357 if (++low == size) break;
jonathonfletcher 0:54f5be781526 358 putchar(',');
jonathonfletcher 0:54f5be781526 359 }
jonathonfletcher 0:54f5be781526 360 puts("\n };");
jonathonfletcher 0:54f5be781526 361 }
jonathonfletcher 0:54f5be781526 362 #endif /* MAKEFIXED */
jonathonfletcher 0:54f5be781526 363
jonathonfletcher 0:54f5be781526 364 /*
jonathonfletcher 0:54f5be781526 365 Update the window with the last wsize (normally 32K) bytes written before
jonathonfletcher 0:54f5be781526 366 returning. If window does not exist yet, create it. This is only called
jonathonfletcher 0:54f5be781526 367 when a window is already in use, or when output has been written during this
jonathonfletcher 0:54f5be781526 368 inflate call, but the end of the deflate stream has not been reached yet.
jonathonfletcher 0:54f5be781526 369 It is also called to create a window for dictionary data when a dictionary
jonathonfletcher 0:54f5be781526 370 is loaded.
jonathonfletcher 0:54f5be781526 371
jonathonfletcher 0:54f5be781526 372 Providing output buffers larger than 32K to inflate() should provide a speed
jonathonfletcher 0:54f5be781526 373 advantage, since only the last 32K of output is copied to the sliding window
jonathonfletcher 0:54f5be781526 374 upon return from inflate(), and since all distances after the first 32K of
jonathonfletcher 0:54f5be781526 375 output will fall in the output data, making match copies simpler and faster.
jonathonfletcher 0:54f5be781526 376 The advantage may be dependent on the size of the processor's data caches.
jonathonfletcher 0:54f5be781526 377 */
jonathonfletcher 0:54f5be781526 378 local int updatewindow(strm, out)
jonathonfletcher 0:54f5be781526 379 z_streamp strm;
jonathonfletcher 0:54f5be781526 380 unsigned out;
jonathonfletcher 0:54f5be781526 381 {
jonathonfletcher 0:54f5be781526 382 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 383 unsigned copy, dist;
jonathonfletcher 0:54f5be781526 384
jonathonfletcher 0:54f5be781526 385 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 386
jonathonfletcher 0:54f5be781526 387 /* if it hasn't been done already, allocate space for the window */
jonathonfletcher 0:54f5be781526 388 if (state->window == Z_NULL) {
jonathonfletcher 0:54f5be781526 389 state->window = (unsigned char FAR *)
jonathonfletcher 0:54f5be781526 390 ZALLOC(strm, 1U << state->wbits,
jonathonfletcher 0:54f5be781526 391 sizeof(unsigned char));
jonathonfletcher 0:54f5be781526 392 if (state->window == Z_NULL) return 1;
jonathonfletcher 0:54f5be781526 393 }
jonathonfletcher 0:54f5be781526 394
jonathonfletcher 0:54f5be781526 395 /* if window not in use yet, initialize */
jonathonfletcher 0:54f5be781526 396 if (state->wsize == 0) {
jonathonfletcher 0:54f5be781526 397 state->wsize = 1U << state->wbits;
jonathonfletcher 0:54f5be781526 398 state->wnext = 0;
jonathonfletcher 0:54f5be781526 399 state->whave = 0;
jonathonfletcher 0:54f5be781526 400 }
jonathonfletcher 0:54f5be781526 401
jonathonfletcher 0:54f5be781526 402 /* copy state->wsize or less output bytes into the circular window */
jonathonfletcher 0:54f5be781526 403 copy = out - strm->avail_out;
jonathonfletcher 0:54f5be781526 404 if (copy >= state->wsize) {
jonathonfletcher 0:54f5be781526 405 zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
jonathonfletcher 0:54f5be781526 406 state->wnext = 0;
jonathonfletcher 0:54f5be781526 407 state->whave = state->wsize;
jonathonfletcher 0:54f5be781526 408 }
jonathonfletcher 0:54f5be781526 409 else {
jonathonfletcher 0:54f5be781526 410 dist = state->wsize - state->wnext;
jonathonfletcher 0:54f5be781526 411 if (dist > copy) dist = copy;
jonathonfletcher 0:54f5be781526 412 zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
jonathonfletcher 0:54f5be781526 413 copy -= dist;
jonathonfletcher 0:54f5be781526 414 if (copy) {
jonathonfletcher 0:54f5be781526 415 zmemcpy(state->window, strm->next_out - copy, copy);
jonathonfletcher 0:54f5be781526 416 state->wnext = copy;
jonathonfletcher 0:54f5be781526 417 state->whave = state->wsize;
jonathonfletcher 0:54f5be781526 418 }
jonathonfletcher 0:54f5be781526 419 else {
jonathonfletcher 0:54f5be781526 420 state->wnext += dist;
jonathonfletcher 0:54f5be781526 421 if (state->wnext == state->wsize) state->wnext = 0;
jonathonfletcher 0:54f5be781526 422 if (state->whave < state->wsize) state->whave += dist;
jonathonfletcher 0:54f5be781526 423 }
jonathonfletcher 0:54f5be781526 424 }
jonathonfletcher 0:54f5be781526 425 return 0;
jonathonfletcher 0:54f5be781526 426 }
jonathonfletcher 0:54f5be781526 427
jonathonfletcher 0:54f5be781526 428 /* Macros for inflate(): */
jonathonfletcher 0:54f5be781526 429
jonathonfletcher 0:54f5be781526 430 /* check function to use adler32() for zlib or crc32() for gzip */
jonathonfletcher 0:54f5be781526 431 #ifdef GUNZIP
jonathonfletcher 0:54f5be781526 432 # define UPDATE(check, buf, len) \
jonathonfletcher 0:54f5be781526 433 (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
jonathonfletcher 0:54f5be781526 434 #else
jonathonfletcher 0:54f5be781526 435 # define UPDATE(check, buf, len) adler32(check, buf, len)
jonathonfletcher 0:54f5be781526 436 #endif
jonathonfletcher 0:54f5be781526 437
jonathonfletcher 0:54f5be781526 438 /* check macros for header crc */
jonathonfletcher 0:54f5be781526 439 #ifdef GUNZIP
jonathonfletcher 0:54f5be781526 440 # define CRC2(check, word) \
jonathonfletcher 0:54f5be781526 441 do { \
jonathonfletcher 0:54f5be781526 442 hbuf[0] = (unsigned char)(word); \
jonathonfletcher 0:54f5be781526 443 hbuf[1] = (unsigned char)((word) >> 8); \
jonathonfletcher 0:54f5be781526 444 check = crc32(check, hbuf, 2); \
jonathonfletcher 0:54f5be781526 445 } while (0)
jonathonfletcher 0:54f5be781526 446
jonathonfletcher 0:54f5be781526 447 # define CRC4(check, word) \
jonathonfletcher 0:54f5be781526 448 do { \
jonathonfletcher 0:54f5be781526 449 hbuf[0] = (unsigned char)(word); \
jonathonfletcher 0:54f5be781526 450 hbuf[1] = (unsigned char)((word) >> 8); \
jonathonfletcher 0:54f5be781526 451 hbuf[2] = (unsigned char)((word) >> 16); \
jonathonfletcher 0:54f5be781526 452 hbuf[3] = (unsigned char)((word) >> 24); \
jonathonfletcher 0:54f5be781526 453 check = crc32(check, hbuf, 4); \
jonathonfletcher 0:54f5be781526 454 } while (0)
jonathonfletcher 0:54f5be781526 455 #endif
jonathonfletcher 0:54f5be781526 456
jonathonfletcher 0:54f5be781526 457 /* Load registers with state in inflate() for speed */
jonathonfletcher 0:54f5be781526 458 #define LOAD() \
jonathonfletcher 0:54f5be781526 459 do { \
jonathonfletcher 0:54f5be781526 460 put = strm->next_out; \
jonathonfletcher 0:54f5be781526 461 left = strm->avail_out; \
jonathonfletcher 0:54f5be781526 462 next = strm->next_in; \
jonathonfletcher 0:54f5be781526 463 have = strm->avail_in; \
jonathonfletcher 0:54f5be781526 464 hold = state->hold; \
jonathonfletcher 0:54f5be781526 465 bits = state->bits; \
jonathonfletcher 0:54f5be781526 466 } while (0)
jonathonfletcher 0:54f5be781526 467
jonathonfletcher 0:54f5be781526 468 /* Restore state from registers in inflate() */
jonathonfletcher 0:54f5be781526 469 #define RESTORE() \
jonathonfletcher 0:54f5be781526 470 do { \
jonathonfletcher 0:54f5be781526 471 strm->next_out = put; \
jonathonfletcher 0:54f5be781526 472 strm->avail_out = left; \
jonathonfletcher 0:54f5be781526 473 strm->next_in = next; \
jonathonfletcher 0:54f5be781526 474 strm->avail_in = have; \
jonathonfletcher 0:54f5be781526 475 state->hold = hold; \
jonathonfletcher 0:54f5be781526 476 state->bits = bits; \
jonathonfletcher 0:54f5be781526 477 } while (0)
jonathonfletcher 0:54f5be781526 478
jonathonfletcher 0:54f5be781526 479 /* Clear the input bit accumulator */
jonathonfletcher 0:54f5be781526 480 #define INITBITS() \
jonathonfletcher 0:54f5be781526 481 do { \
jonathonfletcher 0:54f5be781526 482 hold = 0; \
jonathonfletcher 0:54f5be781526 483 bits = 0; \
jonathonfletcher 0:54f5be781526 484 } while (0)
jonathonfletcher 0:54f5be781526 485
jonathonfletcher 0:54f5be781526 486 /* Get a byte of input into the bit accumulator, or return from inflate()
jonathonfletcher 0:54f5be781526 487 if there is no input available. */
jonathonfletcher 0:54f5be781526 488 #define PULLBYTE() \
jonathonfletcher 0:54f5be781526 489 do { \
jonathonfletcher 0:54f5be781526 490 if (have == 0) goto inf_leave; \
jonathonfletcher 0:54f5be781526 491 have--; \
jonathonfletcher 0:54f5be781526 492 hold += (unsigned long)(*next++) << bits; \
jonathonfletcher 0:54f5be781526 493 bits += 8; \
jonathonfletcher 0:54f5be781526 494 } while (0)
jonathonfletcher 0:54f5be781526 495
jonathonfletcher 0:54f5be781526 496 /* Assure that there are at least n bits in the bit accumulator. If there is
jonathonfletcher 0:54f5be781526 497 not enough available input to do that, then return from inflate(). */
jonathonfletcher 0:54f5be781526 498 #define NEEDBITS(n) \
jonathonfletcher 0:54f5be781526 499 do { \
jonathonfletcher 0:54f5be781526 500 while (bits < (unsigned)(n)) \
jonathonfletcher 0:54f5be781526 501 PULLBYTE(); \
jonathonfletcher 0:54f5be781526 502 } while (0)
jonathonfletcher 0:54f5be781526 503
jonathonfletcher 0:54f5be781526 504 /* Return the low n bits of the bit accumulator (n < 16) */
jonathonfletcher 0:54f5be781526 505 #define BITS(n) \
jonathonfletcher 0:54f5be781526 506 ((unsigned)hold & ((1U << (n)) - 1))
jonathonfletcher 0:54f5be781526 507
jonathonfletcher 0:54f5be781526 508 /* Remove n bits from the bit accumulator */
jonathonfletcher 0:54f5be781526 509 #define DROPBITS(n) \
jonathonfletcher 0:54f5be781526 510 do { \
jonathonfletcher 0:54f5be781526 511 hold >>= (n); \
jonathonfletcher 0:54f5be781526 512 bits -= (unsigned)(n); \
jonathonfletcher 0:54f5be781526 513 } while (0)
jonathonfletcher 0:54f5be781526 514
jonathonfletcher 0:54f5be781526 515 /* Remove zero to seven bits as needed to go to a byte boundary */
jonathonfletcher 0:54f5be781526 516 #define BYTEBITS() \
jonathonfletcher 0:54f5be781526 517 do { \
jonathonfletcher 0:54f5be781526 518 hold >>= bits & 7; \
jonathonfletcher 0:54f5be781526 519 bits -= bits & 7; \
jonathonfletcher 0:54f5be781526 520 } while (0)
jonathonfletcher 0:54f5be781526 521
jonathonfletcher 0:54f5be781526 522 /*
jonathonfletcher 0:54f5be781526 523 inflate() uses a state machine to process as much input data and generate as
jonathonfletcher 0:54f5be781526 524 much output data as possible before returning. The state machine is
jonathonfletcher 0:54f5be781526 525 structured roughly as follows:
jonathonfletcher 0:54f5be781526 526
jonathonfletcher 0:54f5be781526 527 for (;;) switch (state) {
jonathonfletcher 0:54f5be781526 528 ...
jonathonfletcher 0:54f5be781526 529 case STATEn:
jonathonfletcher 0:54f5be781526 530 if (not enough input data or output space to make progress)
jonathonfletcher 0:54f5be781526 531 return;
jonathonfletcher 0:54f5be781526 532 ... make progress ...
jonathonfletcher 0:54f5be781526 533 state = STATEm;
jonathonfletcher 0:54f5be781526 534 break;
jonathonfletcher 0:54f5be781526 535 ...
jonathonfletcher 0:54f5be781526 536 }
jonathonfletcher 0:54f5be781526 537
jonathonfletcher 0:54f5be781526 538 so when inflate() is called again, the same case is attempted again, and
jonathonfletcher 0:54f5be781526 539 if the appropriate resources are provided, the machine proceeds to the
jonathonfletcher 0:54f5be781526 540 next state. The NEEDBITS() macro is usually the way the state evaluates
jonathonfletcher 0:54f5be781526 541 whether it can proceed or should return. NEEDBITS() does the return if
jonathonfletcher 0:54f5be781526 542 the requested bits are not available. The typical use of the BITS macros
jonathonfletcher 0:54f5be781526 543 is:
jonathonfletcher 0:54f5be781526 544
jonathonfletcher 0:54f5be781526 545 NEEDBITS(n);
jonathonfletcher 0:54f5be781526 546 ... do something with BITS(n) ...
jonathonfletcher 0:54f5be781526 547 DROPBITS(n);
jonathonfletcher 0:54f5be781526 548
jonathonfletcher 0:54f5be781526 549 where NEEDBITS(n) either returns from inflate() if there isn't enough
jonathonfletcher 0:54f5be781526 550 input left to load n bits into the accumulator, or it continues. BITS(n)
jonathonfletcher 0:54f5be781526 551 gives the low n bits in the accumulator. When done, DROPBITS(n) drops
jonathonfletcher 0:54f5be781526 552 the low n bits off the accumulator. INITBITS() clears the accumulator
jonathonfletcher 0:54f5be781526 553 and sets the number of available bits to zero. BYTEBITS() discards just
jonathonfletcher 0:54f5be781526 554 enough bits to put the accumulator on a byte boundary. After BYTEBITS()
jonathonfletcher 0:54f5be781526 555 and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
jonathonfletcher 0:54f5be781526 556
jonathonfletcher 0:54f5be781526 557 NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
jonathonfletcher 0:54f5be781526 558 if there is no input available. The decoding of variable length codes uses
jonathonfletcher 0:54f5be781526 559 PULLBYTE() directly in order to pull just enough bytes to decode the next
jonathonfletcher 0:54f5be781526 560 code, and no more.
jonathonfletcher 0:54f5be781526 561
jonathonfletcher 0:54f5be781526 562 Some states loop until they get enough input, making sure that enough
jonathonfletcher 0:54f5be781526 563 state information is maintained to continue the loop where it left off
jonathonfletcher 0:54f5be781526 564 if NEEDBITS() returns in the loop. For example, want, need, and keep
jonathonfletcher 0:54f5be781526 565 would all have to actually be part of the saved state in case NEEDBITS()
jonathonfletcher 0:54f5be781526 566 returns:
jonathonfletcher 0:54f5be781526 567
jonathonfletcher 0:54f5be781526 568 case STATEw:
jonathonfletcher 0:54f5be781526 569 while (want < need) {
jonathonfletcher 0:54f5be781526 570 NEEDBITS(n);
jonathonfletcher 0:54f5be781526 571 keep[want++] = BITS(n);
jonathonfletcher 0:54f5be781526 572 DROPBITS(n);
jonathonfletcher 0:54f5be781526 573 }
jonathonfletcher 0:54f5be781526 574 state = STATEx;
jonathonfletcher 0:54f5be781526 575 case STATEx:
jonathonfletcher 0:54f5be781526 576
jonathonfletcher 0:54f5be781526 577 As shown above, if the next state is also the next case, then the break
jonathonfletcher 0:54f5be781526 578 is omitted.
jonathonfletcher 0:54f5be781526 579
jonathonfletcher 0:54f5be781526 580 A state may also return if there is not enough output space available to
jonathonfletcher 0:54f5be781526 581 complete that state. Those states are copying stored data, writing a
jonathonfletcher 0:54f5be781526 582 literal byte, and copying a matching string.
jonathonfletcher 0:54f5be781526 583
jonathonfletcher 0:54f5be781526 584 When returning, a "goto inf_leave" is used to update the total counters,
jonathonfletcher 0:54f5be781526 585 update the check value, and determine whether any progress has been made
jonathonfletcher 0:54f5be781526 586 during that inflate() call in order to return the proper return code.
jonathonfletcher 0:54f5be781526 587 Progress is defined as a change in either strm->avail_in or strm->avail_out.
jonathonfletcher 0:54f5be781526 588 When there is a window, goto inf_leave will update the window with the last
jonathonfletcher 0:54f5be781526 589 output written. If a goto inf_leave occurs in the middle of decompression
jonathonfletcher 0:54f5be781526 590 and there is no window currently, goto inf_leave will create one and copy
jonathonfletcher 0:54f5be781526 591 output to the window for the next call of inflate().
jonathonfletcher 0:54f5be781526 592
jonathonfletcher 0:54f5be781526 593 In this implementation, the flush parameter of inflate() only affects the
jonathonfletcher 0:54f5be781526 594 return code (per zlib.h). inflate() always writes as much as possible to
jonathonfletcher 0:54f5be781526 595 strm->next_out, given the space available and the provided input--the effect
jonathonfletcher 0:54f5be781526 596 documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
jonathonfletcher 0:54f5be781526 597 the allocation of and copying into a sliding window until necessary, which
jonathonfletcher 0:54f5be781526 598 provides the effect documented in zlib.h for Z_FINISH when the entire input
jonathonfletcher 0:54f5be781526 599 stream available. So the only thing the flush parameter actually does is:
jonathonfletcher 0:54f5be781526 600 when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
jonathonfletcher 0:54f5be781526 601 will return Z_BUF_ERROR if it has not reached the end of the stream.
jonathonfletcher 0:54f5be781526 602 */
jonathonfletcher 0:54f5be781526 603
jonathonfletcher 0:54f5be781526 604 int ZEXPORT inflate(strm, flush)
jonathonfletcher 0:54f5be781526 605 z_streamp strm;
jonathonfletcher 0:54f5be781526 606 int flush;
jonathonfletcher 0:54f5be781526 607 {
jonathonfletcher 0:54f5be781526 608 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 609 unsigned char FAR *next; /* next input */
jonathonfletcher 0:54f5be781526 610 unsigned char FAR *put; /* next output */
jonathonfletcher 0:54f5be781526 611 unsigned have, left; /* available input and output */
jonathonfletcher 0:54f5be781526 612 unsigned long hold; /* bit buffer */
jonathonfletcher 0:54f5be781526 613 unsigned bits; /* bits in bit buffer */
jonathonfletcher 0:54f5be781526 614 unsigned in, out; /* save starting available input and output */
jonathonfletcher 0:54f5be781526 615 unsigned copy; /* number of stored or match bytes to copy */
jonathonfletcher 0:54f5be781526 616 unsigned char FAR *from; /* where to copy match bytes from */
jonathonfletcher 0:54f5be781526 617 code here; /* current decoding table entry */
jonathonfletcher 0:54f5be781526 618 code last; /* parent table entry */
jonathonfletcher 0:54f5be781526 619 unsigned len; /* length to copy for repeats, bits to drop */
jonathonfletcher 0:54f5be781526 620 int ret; /* return code */
jonathonfletcher 0:54f5be781526 621 #ifdef GUNZIP
jonathonfletcher 0:54f5be781526 622 unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
jonathonfletcher 0:54f5be781526 623 #endif
jonathonfletcher 0:54f5be781526 624 static const unsigned short order[19] = /* permutation of code lengths */
jonathonfletcher 0:54f5be781526 625 {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
jonathonfletcher 0:54f5be781526 626
jonathonfletcher 0:54f5be781526 627 if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
jonathonfletcher 0:54f5be781526 628 (strm->next_in == Z_NULL && strm->avail_in != 0))
jonathonfletcher 0:54f5be781526 629 return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 630
jonathonfletcher 0:54f5be781526 631 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 632 if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
jonathonfletcher 0:54f5be781526 633 LOAD();
jonathonfletcher 0:54f5be781526 634 in = have;
jonathonfletcher 0:54f5be781526 635 out = left;
jonathonfletcher 0:54f5be781526 636 ret = Z_OK;
jonathonfletcher 0:54f5be781526 637 for (;;)
jonathonfletcher 0:54f5be781526 638 switch (state->mode) {
jonathonfletcher 0:54f5be781526 639 case HEAD:
jonathonfletcher 0:54f5be781526 640 if (state->wrap == 0) {
jonathonfletcher 0:54f5be781526 641 state->mode = TYPEDO;
jonathonfletcher 0:54f5be781526 642 break;
jonathonfletcher 0:54f5be781526 643 }
jonathonfletcher 0:54f5be781526 644 NEEDBITS(16);
jonathonfletcher 0:54f5be781526 645 #ifdef GUNZIP
jonathonfletcher 0:54f5be781526 646 if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
jonathonfletcher 0:54f5be781526 647 state->check = crc32(0L, Z_NULL, 0);
jonathonfletcher 0:54f5be781526 648 CRC2(state->check, hold);
jonathonfletcher 0:54f5be781526 649 INITBITS();
jonathonfletcher 0:54f5be781526 650 state->mode = FLAGS;
jonathonfletcher 0:54f5be781526 651 break;
jonathonfletcher 0:54f5be781526 652 }
jonathonfletcher 0:54f5be781526 653 state->flags = 0; /* expect zlib header */
jonathonfletcher 0:54f5be781526 654 if (state->head != Z_NULL)
jonathonfletcher 0:54f5be781526 655 state->head->done = -1;
jonathonfletcher 0:54f5be781526 656 if (!(state->wrap & 1) || /* check if zlib header allowed */
jonathonfletcher 0:54f5be781526 657 #else
jonathonfletcher 0:54f5be781526 658 if (
jonathonfletcher 0:54f5be781526 659 #endif
jonathonfletcher 0:54f5be781526 660 ((BITS(8) << 8) + (hold >> 8)) % 31) {
jonathonfletcher 0:54f5be781526 661 strm->msg = (char *)"incorrect header check";
jonathonfletcher 0:54f5be781526 662 state->mode = BAD;
jonathonfletcher 0:54f5be781526 663 break;
jonathonfletcher 0:54f5be781526 664 }
jonathonfletcher 0:54f5be781526 665 if (BITS(4) != Z_DEFLATED) {
jonathonfletcher 0:54f5be781526 666 strm->msg = (char *)"unknown compression method";
jonathonfletcher 0:54f5be781526 667 state->mode = BAD;
jonathonfletcher 0:54f5be781526 668 break;
jonathonfletcher 0:54f5be781526 669 }
jonathonfletcher 0:54f5be781526 670 DROPBITS(4);
jonathonfletcher 0:54f5be781526 671 len = BITS(4) + 8;
jonathonfletcher 0:54f5be781526 672 if (state->wbits == 0)
jonathonfletcher 0:54f5be781526 673 state->wbits = len;
jonathonfletcher 0:54f5be781526 674 else if (len > state->wbits) {
jonathonfletcher 0:54f5be781526 675 strm->msg = (char *)"invalid window size";
jonathonfletcher 0:54f5be781526 676 state->mode = BAD;
jonathonfletcher 0:54f5be781526 677 break;
jonathonfletcher 0:54f5be781526 678 }
jonathonfletcher 0:54f5be781526 679 state->dmax = 1U << len;
jonathonfletcher 0:54f5be781526 680 Tracev((stderr, "inflate: zlib header ok\n"));
jonathonfletcher 0:54f5be781526 681 strm->adler = state->check = adler32(0L, Z_NULL, 0);
jonathonfletcher 0:54f5be781526 682 state->mode = hold & 0x200 ? DICTID : TYPE;
jonathonfletcher 0:54f5be781526 683 INITBITS();
jonathonfletcher 0:54f5be781526 684 break;
jonathonfletcher 0:54f5be781526 685 #ifdef GUNZIP
jonathonfletcher 0:54f5be781526 686 case FLAGS:
jonathonfletcher 0:54f5be781526 687 NEEDBITS(16);
jonathonfletcher 0:54f5be781526 688 state->flags = (int)(hold);
jonathonfletcher 0:54f5be781526 689 if ((state->flags & 0xff) != Z_DEFLATED) {
jonathonfletcher 0:54f5be781526 690 strm->msg = (char *)"unknown compression method";
jonathonfletcher 0:54f5be781526 691 state->mode = BAD;
jonathonfletcher 0:54f5be781526 692 break;
jonathonfletcher 0:54f5be781526 693 }
jonathonfletcher 0:54f5be781526 694 if (state->flags & 0xe000) {
jonathonfletcher 0:54f5be781526 695 strm->msg = (char *)"unknown header flags set";
jonathonfletcher 0:54f5be781526 696 state->mode = BAD;
jonathonfletcher 0:54f5be781526 697 break;
jonathonfletcher 0:54f5be781526 698 }
jonathonfletcher 0:54f5be781526 699 if (state->head != Z_NULL)
jonathonfletcher 0:54f5be781526 700 state->head->text = (int)((hold >> 8) & 1);
jonathonfletcher 0:54f5be781526 701 if (state->flags & 0x0200) CRC2(state->check, hold);
jonathonfletcher 0:54f5be781526 702 INITBITS();
jonathonfletcher 0:54f5be781526 703 state->mode = TIME;
jonathonfletcher 0:54f5be781526 704 case TIME:
jonathonfletcher 0:54f5be781526 705 NEEDBITS(32);
jonathonfletcher 0:54f5be781526 706 if (state->head != Z_NULL)
jonathonfletcher 0:54f5be781526 707 state->head->time = hold;
jonathonfletcher 0:54f5be781526 708 if (state->flags & 0x0200) CRC4(state->check, hold);
jonathonfletcher 0:54f5be781526 709 INITBITS();
jonathonfletcher 0:54f5be781526 710 state->mode = OS;
jonathonfletcher 0:54f5be781526 711 case OS:
jonathonfletcher 0:54f5be781526 712 NEEDBITS(16);
jonathonfletcher 0:54f5be781526 713 if (state->head != Z_NULL) {
jonathonfletcher 0:54f5be781526 714 state->head->xflags = (int)(hold & 0xff);
jonathonfletcher 0:54f5be781526 715 state->head->os = (int)(hold >> 8);
jonathonfletcher 0:54f5be781526 716 }
jonathonfletcher 0:54f5be781526 717 if (state->flags & 0x0200) CRC2(state->check, hold);
jonathonfletcher 0:54f5be781526 718 INITBITS();
jonathonfletcher 0:54f5be781526 719 state->mode = EXLEN;
jonathonfletcher 0:54f5be781526 720 case EXLEN:
jonathonfletcher 0:54f5be781526 721 if (state->flags & 0x0400) {
jonathonfletcher 0:54f5be781526 722 NEEDBITS(16);
jonathonfletcher 0:54f5be781526 723 state->length = (unsigned)(hold);
jonathonfletcher 0:54f5be781526 724 if (state->head != Z_NULL)
jonathonfletcher 0:54f5be781526 725 state->head->extra_len = (unsigned)hold;
jonathonfletcher 0:54f5be781526 726 if (state->flags & 0x0200) CRC2(state->check, hold);
jonathonfletcher 0:54f5be781526 727 INITBITS();
jonathonfletcher 0:54f5be781526 728 }
jonathonfletcher 0:54f5be781526 729 else if (state->head != Z_NULL)
jonathonfletcher 0:54f5be781526 730 state->head->extra = Z_NULL;
jonathonfletcher 0:54f5be781526 731 state->mode = EXTRA;
jonathonfletcher 0:54f5be781526 732 case EXTRA:
jonathonfletcher 0:54f5be781526 733 if (state->flags & 0x0400) {
jonathonfletcher 0:54f5be781526 734 copy = state->length;
jonathonfletcher 0:54f5be781526 735 if (copy > have) copy = have;
jonathonfletcher 0:54f5be781526 736 if (copy) {
jonathonfletcher 0:54f5be781526 737 if (state->head != Z_NULL &&
jonathonfletcher 0:54f5be781526 738 state->head->extra != Z_NULL) {
jonathonfletcher 0:54f5be781526 739 len = state->head->extra_len - state->length;
jonathonfletcher 0:54f5be781526 740 zmemcpy(state->head->extra + len, next,
jonathonfletcher 0:54f5be781526 741 len + copy > state->head->extra_max ?
jonathonfletcher 0:54f5be781526 742 state->head->extra_max - len : copy);
jonathonfletcher 0:54f5be781526 743 }
jonathonfletcher 0:54f5be781526 744 if (state->flags & 0x0200)
jonathonfletcher 0:54f5be781526 745 state->check = crc32(state->check, next, copy);
jonathonfletcher 0:54f5be781526 746 have -= copy;
jonathonfletcher 0:54f5be781526 747 next += copy;
jonathonfletcher 0:54f5be781526 748 state->length -= copy;
jonathonfletcher 0:54f5be781526 749 }
jonathonfletcher 0:54f5be781526 750 if (state->length) goto inf_leave;
jonathonfletcher 0:54f5be781526 751 }
jonathonfletcher 0:54f5be781526 752 state->length = 0;
jonathonfletcher 0:54f5be781526 753 state->mode = NAME;
jonathonfletcher 0:54f5be781526 754 case NAME:
jonathonfletcher 0:54f5be781526 755 if (state->flags & 0x0800) {
jonathonfletcher 0:54f5be781526 756 if (have == 0) goto inf_leave;
jonathonfletcher 0:54f5be781526 757 copy = 0;
jonathonfletcher 0:54f5be781526 758 do {
jonathonfletcher 0:54f5be781526 759 len = (unsigned)(next[copy++]);
jonathonfletcher 0:54f5be781526 760 if (state->head != Z_NULL &&
jonathonfletcher 0:54f5be781526 761 state->head->name != Z_NULL &&
jonathonfletcher 0:54f5be781526 762 state->length < state->head->name_max)
jonathonfletcher 0:54f5be781526 763 state->head->name[state->length++] = len;
jonathonfletcher 0:54f5be781526 764 } while (len && copy < have);
jonathonfletcher 0:54f5be781526 765 if (state->flags & 0x0200)
jonathonfletcher 0:54f5be781526 766 state->check = crc32(state->check, next, copy);
jonathonfletcher 0:54f5be781526 767 have -= copy;
jonathonfletcher 0:54f5be781526 768 next += copy;
jonathonfletcher 0:54f5be781526 769 if (len) goto inf_leave;
jonathonfletcher 0:54f5be781526 770 }
jonathonfletcher 0:54f5be781526 771 else if (state->head != Z_NULL)
jonathonfletcher 0:54f5be781526 772 state->head->name = Z_NULL;
jonathonfletcher 0:54f5be781526 773 state->length = 0;
jonathonfletcher 0:54f5be781526 774 state->mode = COMMENT;
jonathonfletcher 0:54f5be781526 775 case COMMENT:
jonathonfletcher 0:54f5be781526 776 if (state->flags & 0x1000) {
jonathonfletcher 0:54f5be781526 777 if (have == 0) goto inf_leave;
jonathonfletcher 0:54f5be781526 778 copy = 0;
jonathonfletcher 0:54f5be781526 779 do {
jonathonfletcher 0:54f5be781526 780 len = (unsigned)(next[copy++]);
jonathonfletcher 0:54f5be781526 781 if (state->head != Z_NULL &&
jonathonfletcher 0:54f5be781526 782 state->head->comment != Z_NULL &&
jonathonfletcher 0:54f5be781526 783 state->length < state->head->comm_max)
jonathonfletcher 0:54f5be781526 784 state->head->comment[state->length++] = len;
jonathonfletcher 0:54f5be781526 785 } while (len && copy < have);
jonathonfletcher 0:54f5be781526 786 if (state->flags & 0x0200)
jonathonfletcher 0:54f5be781526 787 state->check = crc32(state->check, next, copy);
jonathonfletcher 0:54f5be781526 788 have -= copy;
jonathonfletcher 0:54f5be781526 789 next += copy;
jonathonfletcher 0:54f5be781526 790 if (len) goto inf_leave;
jonathonfletcher 0:54f5be781526 791 }
jonathonfletcher 0:54f5be781526 792 else if (state->head != Z_NULL)
jonathonfletcher 0:54f5be781526 793 state->head->comment = Z_NULL;
jonathonfletcher 0:54f5be781526 794 state->mode = HCRC;
jonathonfletcher 0:54f5be781526 795 case HCRC:
jonathonfletcher 0:54f5be781526 796 if (state->flags & 0x0200) {
jonathonfletcher 0:54f5be781526 797 NEEDBITS(16);
jonathonfletcher 0:54f5be781526 798 if (hold != (state->check & 0xffff)) {
jonathonfletcher 0:54f5be781526 799 strm->msg = (char *)"header crc mismatch";
jonathonfletcher 0:54f5be781526 800 state->mode = BAD;
jonathonfletcher 0:54f5be781526 801 break;
jonathonfletcher 0:54f5be781526 802 }
jonathonfletcher 0:54f5be781526 803 INITBITS();
jonathonfletcher 0:54f5be781526 804 }
jonathonfletcher 0:54f5be781526 805 if (state->head != Z_NULL) {
jonathonfletcher 0:54f5be781526 806 state->head->hcrc = (int)((state->flags >> 9) & 1);
jonathonfletcher 0:54f5be781526 807 state->head->done = 1;
jonathonfletcher 0:54f5be781526 808 }
jonathonfletcher 0:54f5be781526 809 strm->adler = state->check = crc32(0L, Z_NULL, 0);
jonathonfletcher 0:54f5be781526 810 state->mode = TYPE;
jonathonfletcher 0:54f5be781526 811 break;
jonathonfletcher 0:54f5be781526 812 #endif
jonathonfletcher 0:54f5be781526 813 case DICTID:
jonathonfletcher 0:54f5be781526 814 NEEDBITS(32);
jonathonfletcher 0:54f5be781526 815 strm->adler = state->check = ZSWAP32(hold);
jonathonfletcher 0:54f5be781526 816 INITBITS();
jonathonfletcher 0:54f5be781526 817 state->mode = DICT;
jonathonfletcher 0:54f5be781526 818 case DICT:
jonathonfletcher 0:54f5be781526 819 if (state->havedict == 0) {
jonathonfletcher 0:54f5be781526 820 RESTORE();
jonathonfletcher 0:54f5be781526 821 return Z_NEED_DICT;
jonathonfletcher 0:54f5be781526 822 }
jonathonfletcher 0:54f5be781526 823 strm->adler = state->check = adler32(0L, Z_NULL, 0);
jonathonfletcher 0:54f5be781526 824 state->mode = TYPE;
jonathonfletcher 0:54f5be781526 825 case TYPE:
jonathonfletcher 0:54f5be781526 826 if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
jonathonfletcher 0:54f5be781526 827 case TYPEDO:
jonathonfletcher 0:54f5be781526 828 if (state->last) {
jonathonfletcher 0:54f5be781526 829 BYTEBITS();
jonathonfletcher 0:54f5be781526 830 state->mode = CHECK;
jonathonfletcher 0:54f5be781526 831 break;
jonathonfletcher 0:54f5be781526 832 }
jonathonfletcher 0:54f5be781526 833 NEEDBITS(3);
jonathonfletcher 0:54f5be781526 834 state->last = BITS(1);
jonathonfletcher 0:54f5be781526 835 DROPBITS(1);
jonathonfletcher 0:54f5be781526 836 switch (BITS(2)) {
jonathonfletcher 0:54f5be781526 837 case 0: /* stored block */
jonathonfletcher 0:54f5be781526 838 Tracev((stderr, "inflate: stored block%s\n",
jonathonfletcher 0:54f5be781526 839 state->last ? " (last)" : ""));
jonathonfletcher 0:54f5be781526 840 state->mode = STORED;
jonathonfletcher 0:54f5be781526 841 break;
jonathonfletcher 0:54f5be781526 842 case 1: /* fixed block */
jonathonfletcher 0:54f5be781526 843 fixedtables(state);
jonathonfletcher 0:54f5be781526 844 Tracev((stderr, "inflate: fixed codes block%s\n",
jonathonfletcher 0:54f5be781526 845 state->last ? " (last)" : ""));
jonathonfletcher 0:54f5be781526 846 state->mode = LEN_; /* decode codes */
jonathonfletcher 0:54f5be781526 847 if (flush == Z_TREES) {
jonathonfletcher 0:54f5be781526 848 DROPBITS(2);
jonathonfletcher 0:54f5be781526 849 goto inf_leave;
jonathonfletcher 0:54f5be781526 850 }
jonathonfletcher 0:54f5be781526 851 break;
jonathonfletcher 0:54f5be781526 852 case 2: /* dynamic block */
jonathonfletcher 0:54f5be781526 853 Tracev((stderr, "inflate: dynamic codes block%s\n",
jonathonfletcher 0:54f5be781526 854 state->last ? " (last)" : ""));
jonathonfletcher 0:54f5be781526 855 state->mode = TABLE;
jonathonfletcher 0:54f5be781526 856 break;
jonathonfletcher 0:54f5be781526 857 case 3:
jonathonfletcher 0:54f5be781526 858 strm->msg = (char *)"invalid block type";
jonathonfletcher 0:54f5be781526 859 state->mode = BAD;
jonathonfletcher 0:54f5be781526 860 }
jonathonfletcher 0:54f5be781526 861 DROPBITS(2);
jonathonfletcher 0:54f5be781526 862 break;
jonathonfletcher 0:54f5be781526 863 case STORED:
jonathonfletcher 0:54f5be781526 864 BYTEBITS(); /* go to byte boundary */
jonathonfletcher 0:54f5be781526 865 NEEDBITS(32);
jonathonfletcher 0:54f5be781526 866 if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
jonathonfletcher 0:54f5be781526 867 strm->msg = (char *)"invalid stored block lengths";
jonathonfletcher 0:54f5be781526 868 state->mode = BAD;
jonathonfletcher 0:54f5be781526 869 break;
jonathonfletcher 0:54f5be781526 870 }
jonathonfletcher 0:54f5be781526 871 state->length = (unsigned)hold & 0xffff;
jonathonfletcher 0:54f5be781526 872 Tracev((stderr, "inflate: stored length %u\n",
jonathonfletcher 0:54f5be781526 873 state->length));
jonathonfletcher 0:54f5be781526 874 INITBITS();
jonathonfletcher 0:54f5be781526 875 state->mode = COPY_;
jonathonfletcher 0:54f5be781526 876 if (flush == Z_TREES) goto inf_leave;
jonathonfletcher 0:54f5be781526 877 case COPY_:
jonathonfletcher 0:54f5be781526 878 state->mode = COPY;
jonathonfletcher 0:54f5be781526 879 case COPY:
jonathonfletcher 0:54f5be781526 880 copy = state->length;
jonathonfletcher 0:54f5be781526 881 if (copy) {
jonathonfletcher 0:54f5be781526 882 if (copy > have) copy = have;
jonathonfletcher 0:54f5be781526 883 if (copy > left) copy = left;
jonathonfletcher 0:54f5be781526 884 if (copy == 0) goto inf_leave;
jonathonfletcher 0:54f5be781526 885 zmemcpy(put, next, copy);
jonathonfletcher 0:54f5be781526 886 have -= copy;
jonathonfletcher 0:54f5be781526 887 next += copy;
jonathonfletcher 0:54f5be781526 888 left -= copy;
jonathonfletcher 0:54f5be781526 889 put += copy;
jonathonfletcher 0:54f5be781526 890 state->length -= copy;
jonathonfletcher 0:54f5be781526 891 break;
jonathonfletcher 0:54f5be781526 892 }
jonathonfletcher 0:54f5be781526 893 Tracev((stderr, "inflate: stored end\n"));
jonathonfletcher 0:54f5be781526 894 state->mode = TYPE;
jonathonfletcher 0:54f5be781526 895 break;
jonathonfletcher 0:54f5be781526 896 case TABLE:
jonathonfletcher 0:54f5be781526 897 NEEDBITS(14);
jonathonfletcher 0:54f5be781526 898 state->nlen = BITS(5) + 257;
jonathonfletcher 0:54f5be781526 899 DROPBITS(5);
jonathonfletcher 0:54f5be781526 900 state->ndist = BITS(5) + 1;
jonathonfletcher 0:54f5be781526 901 DROPBITS(5);
jonathonfletcher 0:54f5be781526 902 state->ncode = BITS(4) + 4;
jonathonfletcher 0:54f5be781526 903 DROPBITS(4);
jonathonfletcher 0:54f5be781526 904 #ifndef PKZIP_BUG_WORKAROUND
jonathonfletcher 0:54f5be781526 905 if (state->nlen > 286 || state->ndist > 30) {
jonathonfletcher 0:54f5be781526 906 strm->msg = (char *)"too many length or distance symbols";
jonathonfletcher 0:54f5be781526 907 state->mode = BAD;
jonathonfletcher 0:54f5be781526 908 break;
jonathonfletcher 0:54f5be781526 909 }
jonathonfletcher 0:54f5be781526 910 #endif
jonathonfletcher 0:54f5be781526 911 Tracev((stderr, "inflate: table sizes ok\n"));
jonathonfletcher 0:54f5be781526 912 state->have = 0;
jonathonfletcher 0:54f5be781526 913 state->mode = LENLENS;
jonathonfletcher 0:54f5be781526 914 case LENLENS:
jonathonfletcher 0:54f5be781526 915 while (state->have < state->ncode) {
jonathonfletcher 0:54f5be781526 916 NEEDBITS(3);
jonathonfletcher 0:54f5be781526 917 state->lens[order[state->have++]] = (unsigned short)BITS(3);
jonathonfletcher 0:54f5be781526 918 DROPBITS(3);
jonathonfletcher 0:54f5be781526 919 }
jonathonfletcher 0:54f5be781526 920 while (state->have < 19)
jonathonfletcher 0:54f5be781526 921 state->lens[order[state->have++]] = 0;
jonathonfletcher 0:54f5be781526 922 state->next = state->codes;
jonathonfletcher 0:54f5be781526 923 state->lencode = (code const FAR *)(state->next);
jonathonfletcher 0:54f5be781526 924 state->lenbits = 7;
jonathonfletcher 0:54f5be781526 925 ret = inflate_table(CODES, state->lens, 19, &(state->next),
jonathonfletcher 0:54f5be781526 926 &(state->lenbits), state->work);
jonathonfletcher 0:54f5be781526 927 if (ret) {
jonathonfletcher 0:54f5be781526 928 strm->msg = (char *)"invalid code lengths set";
jonathonfletcher 0:54f5be781526 929 state->mode = BAD;
jonathonfletcher 0:54f5be781526 930 break;
jonathonfletcher 0:54f5be781526 931 }
jonathonfletcher 0:54f5be781526 932 Tracev((stderr, "inflate: code lengths ok\n"));
jonathonfletcher 0:54f5be781526 933 state->have = 0;
jonathonfletcher 0:54f5be781526 934 state->mode = CODELENS;
jonathonfletcher 0:54f5be781526 935 case CODELENS:
jonathonfletcher 0:54f5be781526 936 while (state->have < state->nlen + state->ndist) {
jonathonfletcher 0:54f5be781526 937 for (;;) {
jonathonfletcher 0:54f5be781526 938 here = state->lencode[BITS(state->lenbits)];
jonathonfletcher 0:54f5be781526 939 if ((unsigned)(here.bits) <= bits) break;
jonathonfletcher 0:54f5be781526 940 PULLBYTE();
jonathonfletcher 0:54f5be781526 941 }
jonathonfletcher 0:54f5be781526 942 if (here.val < 16) {
jonathonfletcher 0:54f5be781526 943 DROPBITS(here.bits);
jonathonfletcher 0:54f5be781526 944 state->lens[state->have++] = here.val;
jonathonfletcher 0:54f5be781526 945 }
jonathonfletcher 0:54f5be781526 946 else {
jonathonfletcher 0:54f5be781526 947 if (here.val == 16) {
jonathonfletcher 0:54f5be781526 948 NEEDBITS(here.bits + 2);
jonathonfletcher 0:54f5be781526 949 DROPBITS(here.bits);
jonathonfletcher 0:54f5be781526 950 if (state->have == 0) {
jonathonfletcher 0:54f5be781526 951 strm->msg = (char *)"invalid bit length repeat";
jonathonfletcher 0:54f5be781526 952 state->mode = BAD;
jonathonfletcher 0:54f5be781526 953 break;
jonathonfletcher 0:54f5be781526 954 }
jonathonfletcher 0:54f5be781526 955 len = state->lens[state->have - 1];
jonathonfletcher 0:54f5be781526 956 copy = 3 + BITS(2);
jonathonfletcher 0:54f5be781526 957 DROPBITS(2);
jonathonfletcher 0:54f5be781526 958 }
jonathonfletcher 0:54f5be781526 959 else if (here.val == 17) {
jonathonfletcher 0:54f5be781526 960 NEEDBITS(here.bits + 3);
jonathonfletcher 0:54f5be781526 961 DROPBITS(here.bits);
jonathonfletcher 0:54f5be781526 962 len = 0;
jonathonfletcher 0:54f5be781526 963 copy = 3 + BITS(3);
jonathonfletcher 0:54f5be781526 964 DROPBITS(3);
jonathonfletcher 0:54f5be781526 965 }
jonathonfletcher 0:54f5be781526 966 else {
jonathonfletcher 0:54f5be781526 967 NEEDBITS(here.bits + 7);
jonathonfletcher 0:54f5be781526 968 DROPBITS(here.bits);
jonathonfletcher 0:54f5be781526 969 len = 0;
jonathonfletcher 0:54f5be781526 970 copy = 11 + BITS(7);
jonathonfletcher 0:54f5be781526 971 DROPBITS(7);
jonathonfletcher 0:54f5be781526 972 }
jonathonfletcher 0:54f5be781526 973 if (state->have + copy > state->nlen + state->ndist) {
jonathonfletcher 0:54f5be781526 974 strm->msg = (char *)"invalid bit length repeat";
jonathonfletcher 0:54f5be781526 975 state->mode = BAD;
jonathonfletcher 0:54f5be781526 976 break;
jonathonfletcher 0:54f5be781526 977 }
jonathonfletcher 0:54f5be781526 978 while (copy--)
jonathonfletcher 0:54f5be781526 979 state->lens[state->have++] = (unsigned short)len;
jonathonfletcher 0:54f5be781526 980 }
jonathonfletcher 0:54f5be781526 981 }
jonathonfletcher 0:54f5be781526 982
jonathonfletcher 0:54f5be781526 983 /* handle error breaks in while */
jonathonfletcher 0:54f5be781526 984 if (state->mode == BAD) break;
jonathonfletcher 0:54f5be781526 985
jonathonfletcher 0:54f5be781526 986 /* check for end-of-block code (better have one) */
jonathonfletcher 0:54f5be781526 987 if (state->lens[256] == 0) {
jonathonfletcher 0:54f5be781526 988 strm->msg = (char *)"invalid code -- missing end-of-block";
jonathonfletcher 0:54f5be781526 989 state->mode = BAD;
jonathonfletcher 0:54f5be781526 990 break;
jonathonfletcher 0:54f5be781526 991 }
jonathonfletcher 0:54f5be781526 992
jonathonfletcher 0:54f5be781526 993 /* build code tables -- note: do not change the lenbits or distbits
jonathonfletcher 0:54f5be781526 994 values here (9 and 6) without reading the comments in inftrees.h
jonathonfletcher 0:54f5be781526 995 concerning the ENOUGH constants, which depend on those values */
jonathonfletcher 0:54f5be781526 996 state->next = state->codes;
jonathonfletcher 0:54f5be781526 997 state->lencode = (code const FAR *)(state->next);
jonathonfletcher 0:54f5be781526 998 state->lenbits = 9;
jonathonfletcher 0:54f5be781526 999 ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
jonathonfletcher 0:54f5be781526 1000 &(state->lenbits), state->work);
jonathonfletcher 0:54f5be781526 1001 if (ret) {
jonathonfletcher 0:54f5be781526 1002 strm->msg = (char *)"invalid literal/lengths set";
jonathonfletcher 0:54f5be781526 1003 state->mode = BAD;
jonathonfletcher 0:54f5be781526 1004 break;
jonathonfletcher 0:54f5be781526 1005 }
jonathonfletcher 0:54f5be781526 1006 state->distcode = (code const FAR *)(state->next);
jonathonfletcher 0:54f5be781526 1007 state->distbits = 6;
jonathonfletcher 0:54f5be781526 1008 ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
jonathonfletcher 0:54f5be781526 1009 &(state->next), &(state->distbits), state->work);
jonathonfletcher 0:54f5be781526 1010 if (ret) {
jonathonfletcher 0:54f5be781526 1011 strm->msg = (char *)"invalid distances set";
jonathonfletcher 0:54f5be781526 1012 state->mode = BAD;
jonathonfletcher 0:54f5be781526 1013 break;
jonathonfletcher 0:54f5be781526 1014 }
jonathonfletcher 0:54f5be781526 1015 Tracev((stderr, "inflate: codes ok\n"));
jonathonfletcher 0:54f5be781526 1016 state->mode = LEN_;
jonathonfletcher 0:54f5be781526 1017 if (flush == Z_TREES) goto inf_leave;
jonathonfletcher 0:54f5be781526 1018 case LEN_:
jonathonfletcher 0:54f5be781526 1019 state->mode = LEN;
jonathonfletcher 0:54f5be781526 1020 case LEN:
jonathonfletcher 0:54f5be781526 1021 if (have >= 6 && left >= 258) {
jonathonfletcher 0:54f5be781526 1022 RESTORE();
jonathonfletcher 0:54f5be781526 1023 inflate_fast(strm, out);
jonathonfletcher 0:54f5be781526 1024 LOAD();
jonathonfletcher 0:54f5be781526 1025 if (state->mode == TYPE)
jonathonfletcher 0:54f5be781526 1026 state->back = -1;
jonathonfletcher 0:54f5be781526 1027 break;
jonathonfletcher 0:54f5be781526 1028 }
jonathonfletcher 0:54f5be781526 1029 state->back = 0;
jonathonfletcher 0:54f5be781526 1030 for (;;) {
jonathonfletcher 0:54f5be781526 1031 here = state->lencode[BITS(state->lenbits)];
jonathonfletcher 0:54f5be781526 1032 if ((unsigned)(here.bits) <= bits) break;
jonathonfletcher 0:54f5be781526 1033 PULLBYTE();
jonathonfletcher 0:54f5be781526 1034 }
jonathonfletcher 0:54f5be781526 1035 if (here.op && (here.op & 0xf0) == 0) {
jonathonfletcher 0:54f5be781526 1036 last = here;
jonathonfletcher 0:54f5be781526 1037 for (;;) {
jonathonfletcher 0:54f5be781526 1038 here = state->lencode[last.val +
jonathonfletcher 0:54f5be781526 1039 (BITS(last.bits + last.op) >> last.bits)];
jonathonfletcher 0:54f5be781526 1040 if ((unsigned)(last.bits + here.bits) <= bits) break;
jonathonfletcher 0:54f5be781526 1041 PULLBYTE();
jonathonfletcher 0:54f5be781526 1042 }
jonathonfletcher 0:54f5be781526 1043 DROPBITS(last.bits);
jonathonfletcher 0:54f5be781526 1044 state->back += last.bits;
jonathonfletcher 0:54f5be781526 1045 }
jonathonfletcher 0:54f5be781526 1046 DROPBITS(here.bits);
jonathonfletcher 0:54f5be781526 1047 state->back += here.bits;
jonathonfletcher 0:54f5be781526 1048 state->length = (unsigned)here.val;
jonathonfletcher 0:54f5be781526 1049 if ((int)(here.op) == 0) {
jonathonfletcher 0:54f5be781526 1050 Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
jonathonfletcher 0:54f5be781526 1051 "inflate: literal '%c'\n" :
jonathonfletcher 0:54f5be781526 1052 "inflate: literal 0x%02x\n", here.val));
jonathonfletcher 0:54f5be781526 1053 state->mode = LIT;
jonathonfletcher 0:54f5be781526 1054 break;
jonathonfletcher 0:54f5be781526 1055 }
jonathonfletcher 0:54f5be781526 1056 if (here.op & 32) {
jonathonfletcher 0:54f5be781526 1057 Tracevv((stderr, "inflate: end of block\n"));
jonathonfletcher 0:54f5be781526 1058 state->back = -1;
jonathonfletcher 0:54f5be781526 1059 state->mode = TYPE;
jonathonfletcher 0:54f5be781526 1060 break;
jonathonfletcher 0:54f5be781526 1061 }
jonathonfletcher 0:54f5be781526 1062 if (here.op & 64) {
jonathonfletcher 0:54f5be781526 1063 strm->msg = (char *)"invalid literal/length code";
jonathonfletcher 0:54f5be781526 1064 state->mode = BAD;
jonathonfletcher 0:54f5be781526 1065 break;
jonathonfletcher 0:54f5be781526 1066 }
jonathonfletcher 0:54f5be781526 1067 state->extra = (unsigned)(here.op) & 15;
jonathonfletcher 0:54f5be781526 1068 state->mode = LENEXT;
jonathonfletcher 0:54f5be781526 1069 case LENEXT:
jonathonfletcher 0:54f5be781526 1070 if (state->extra) {
jonathonfletcher 0:54f5be781526 1071 NEEDBITS(state->extra);
jonathonfletcher 0:54f5be781526 1072 state->length += BITS(state->extra);
jonathonfletcher 0:54f5be781526 1073 DROPBITS(state->extra);
jonathonfletcher 0:54f5be781526 1074 state->back += state->extra;
jonathonfletcher 0:54f5be781526 1075 }
jonathonfletcher 0:54f5be781526 1076 Tracevv((stderr, "inflate: length %u\n", state->length));
jonathonfletcher 0:54f5be781526 1077 state->was = state->length;
jonathonfletcher 0:54f5be781526 1078 state->mode = DIST;
jonathonfletcher 0:54f5be781526 1079 case DIST:
jonathonfletcher 0:54f5be781526 1080 for (;;) {
jonathonfletcher 0:54f5be781526 1081 here = state->distcode[BITS(state->distbits)];
jonathonfletcher 0:54f5be781526 1082 if ((unsigned)(here.bits) <= bits) break;
jonathonfletcher 0:54f5be781526 1083 PULLBYTE();
jonathonfletcher 0:54f5be781526 1084 }
jonathonfletcher 0:54f5be781526 1085 if ((here.op & 0xf0) == 0) {
jonathonfletcher 0:54f5be781526 1086 last = here;
jonathonfletcher 0:54f5be781526 1087 for (;;) {
jonathonfletcher 0:54f5be781526 1088 here = state->distcode[last.val +
jonathonfletcher 0:54f5be781526 1089 (BITS(last.bits + last.op) >> last.bits)];
jonathonfletcher 0:54f5be781526 1090 if ((unsigned)(last.bits + here.bits) <= bits) break;
jonathonfletcher 0:54f5be781526 1091 PULLBYTE();
jonathonfletcher 0:54f5be781526 1092 }
jonathonfletcher 0:54f5be781526 1093 DROPBITS(last.bits);
jonathonfletcher 0:54f5be781526 1094 state->back += last.bits;
jonathonfletcher 0:54f5be781526 1095 }
jonathonfletcher 0:54f5be781526 1096 DROPBITS(here.bits);
jonathonfletcher 0:54f5be781526 1097 state->back += here.bits;
jonathonfletcher 0:54f5be781526 1098 if (here.op & 64) {
jonathonfletcher 0:54f5be781526 1099 strm->msg = (char *)"invalid distance code";
jonathonfletcher 0:54f5be781526 1100 state->mode = BAD;
jonathonfletcher 0:54f5be781526 1101 break;
jonathonfletcher 0:54f5be781526 1102 }
jonathonfletcher 0:54f5be781526 1103 state->offset = (unsigned)here.val;
jonathonfletcher 0:54f5be781526 1104 state->extra = (unsigned)(here.op) & 15;
jonathonfletcher 0:54f5be781526 1105 state->mode = DISTEXT;
jonathonfletcher 0:54f5be781526 1106 case DISTEXT:
jonathonfletcher 0:54f5be781526 1107 if (state->extra) {
jonathonfletcher 0:54f5be781526 1108 NEEDBITS(state->extra);
jonathonfletcher 0:54f5be781526 1109 state->offset += BITS(state->extra);
jonathonfletcher 0:54f5be781526 1110 DROPBITS(state->extra);
jonathonfletcher 0:54f5be781526 1111 state->back += state->extra;
jonathonfletcher 0:54f5be781526 1112 }
jonathonfletcher 0:54f5be781526 1113 #ifdef INFLATE_STRICT
jonathonfletcher 0:54f5be781526 1114 if (state->offset > state->dmax) {
jonathonfletcher 0:54f5be781526 1115 strm->msg = (char *)"invalid distance too far back";
jonathonfletcher 0:54f5be781526 1116 state->mode = BAD;
jonathonfletcher 0:54f5be781526 1117 break;
jonathonfletcher 0:54f5be781526 1118 }
jonathonfletcher 0:54f5be781526 1119 #endif
jonathonfletcher 0:54f5be781526 1120 Tracevv((stderr, "inflate: distance %u\n", state->offset));
jonathonfletcher 0:54f5be781526 1121 state->mode = MATCH;
jonathonfletcher 0:54f5be781526 1122 case MATCH:
jonathonfletcher 0:54f5be781526 1123 if (left == 0) goto inf_leave;
jonathonfletcher 0:54f5be781526 1124 copy = out - left;
jonathonfletcher 0:54f5be781526 1125 if (state->offset > copy) { /* copy from window */
jonathonfletcher 0:54f5be781526 1126 copy = state->offset - copy;
jonathonfletcher 0:54f5be781526 1127 if (copy > state->whave) {
jonathonfletcher 0:54f5be781526 1128 if (state->sane) {
jonathonfletcher 0:54f5be781526 1129 strm->msg = (char *)"invalid distance too far back";
jonathonfletcher 0:54f5be781526 1130 state->mode = BAD;
jonathonfletcher 0:54f5be781526 1131 break;
jonathonfletcher 0:54f5be781526 1132 }
jonathonfletcher 0:54f5be781526 1133 #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
jonathonfletcher 0:54f5be781526 1134 Trace((stderr, "inflate.c too far\n"));
jonathonfletcher 0:54f5be781526 1135 copy -= state->whave;
jonathonfletcher 0:54f5be781526 1136 if (copy > state->length) copy = state->length;
jonathonfletcher 0:54f5be781526 1137 if (copy > left) copy = left;
jonathonfletcher 0:54f5be781526 1138 left -= copy;
jonathonfletcher 0:54f5be781526 1139 state->length -= copy;
jonathonfletcher 0:54f5be781526 1140 do {
jonathonfletcher 0:54f5be781526 1141 *put++ = 0;
jonathonfletcher 0:54f5be781526 1142 } while (--copy);
jonathonfletcher 0:54f5be781526 1143 if (state->length == 0) state->mode = LEN;
jonathonfletcher 0:54f5be781526 1144 break;
jonathonfletcher 0:54f5be781526 1145 #endif
jonathonfletcher 0:54f5be781526 1146 }
jonathonfletcher 0:54f5be781526 1147 if (copy > state->wnext) {
jonathonfletcher 0:54f5be781526 1148 copy -= state->wnext;
jonathonfletcher 0:54f5be781526 1149 from = state->window + (state->wsize - copy);
jonathonfletcher 0:54f5be781526 1150 }
jonathonfletcher 0:54f5be781526 1151 else
jonathonfletcher 0:54f5be781526 1152 from = state->window + (state->wnext - copy);
jonathonfletcher 0:54f5be781526 1153 if (copy > state->length) copy = state->length;
jonathonfletcher 0:54f5be781526 1154 }
jonathonfletcher 0:54f5be781526 1155 else { /* copy from output */
jonathonfletcher 0:54f5be781526 1156 from = put - state->offset;
jonathonfletcher 0:54f5be781526 1157 copy = state->length;
jonathonfletcher 0:54f5be781526 1158 }
jonathonfletcher 0:54f5be781526 1159 if (copy > left) copy = left;
jonathonfletcher 0:54f5be781526 1160 left -= copy;
jonathonfletcher 0:54f5be781526 1161 state->length -= copy;
jonathonfletcher 0:54f5be781526 1162 do {
jonathonfletcher 0:54f5be781526 1163 *put++ = *from++;
jonathonfletcher 0:54f5be781526 1164 } while (--copy);
jonathonfletcher 0:54f5be781526 1165 if (state->length == 0) state->mode = LEN;
jonathonfletcher 0:54f5be781526 1166 break;
jonathonfletcher 0:54f5be781526 1167 case LIT:
jonathonfletcher 0:54f5be781526 1168 if (left == 0) goto inf_leave;
jonathonfletcher 0:54f5be781526 1169 *put++ = (unsigned char)(state->length);
jonathonfletcher 0:54f5be781526 1170 left--;
jonathonfletcher 0:54f5be781526 1171 state->mode = LEN;
jonathonfletcher 0:54f5be781526 1172 break;
jonathonfletcher 0:54f5be781526 1173 case CHECK:
jonathonfletcher 0:54f5be781526 1174 if (state->wrap) {
jonathonfletcher 0:54f5be781526 1175 NEEDBITS(32);
jonathonfletcher 0:54f5be781526 1176 out -= left;
jonathonfletcher 0:54f5be781526 1177 strm->total_out += out;
jonathonfletcher 0:54f5be781526 1178 state->total += out;
jonathonfletcher 0:54f5be781526 1179 if (out)
jonathonfletcher 0:54f5be781526 1180 strm->adler = state->check =
jonathonfletcher 0:54f5be781526 1181 UPDATE(state->check, put - out, out);
jonathonfletcher 0:54f5be781526 1182 out = left;
jonathonfletcher 0:54f5be781526 1183 if ((
jonathonfletcher 0:54f5be781526 1184 #ifdef GUNZIP
jonathonfletcher 0:54f5be781526 1185 state->flags ? hold :
jonathonfletcher 0:54f5be781526 1186 #endif
jonathonfletcher 0:54f5be781526 1187 ZSWAP32(hold)) != state->check) {
jonathonfletcher 0:54f5be781526 1188 strm->msg = (char *)"incorrect data check";
jonathonfletcher 0:54f5be781526 1189 state->mode = BAD;
jonathonfletcher 0:54f5be781526 1190 break;
jonathonfletcher 0:54f5be781526 1191 }
jonathonfletcher 0:54f5be781526 1192 INITBITS();
jonathonfletcher 0:54f5be781526 1193 Tracev((stderr, "inflate: check matches trailer\n"));
jonathonfletcher 0:54f5be781526 1194 }
jonathonfletcher 0:54f5be781526 1195 #ifdef GUNZIP
jonathonfletcher 0:54f5be781526 1196 state->mode = LENGTH;
jonathonfletcher 0:54f5be781526 1197 case LENGTH:
jonathonfletcher 0:54f5be781526 1198 if (state->wrap && state->flags) {
jonathonfletcher 0:54f5be781526 1199 NEEDBITS(32);
jonathonfletcher 0:54f5be781526 1200 if (hold != (state->total & 0xffffffffUL)) {
jonathonfletcher 0:54f5be781526 1201 strm->msg = (char *)"incorrect length check";
jonathonfletcher 0:54f5be781526 1202 state->mode = BAD;
jonathonfletcher 0:54f5be781526 1203 break;
jonathonfletcher 0:54f5be781526 1204 }
jonathonfletcher 0:54f5be781526 1205 INITBITS();
jonathonfletcher 0:54f5be781526 1206 Tracev((stderr, "inflate: length matches trailer\n"));
jonathonfletcher 0:54f5be781526 1207 }
jonathonfletcher 0:54f5be781526 1208 #endif
jonathonfletcher 0:54f5be781526 1209 state->mode = DONE;
jonathonfletcher 0:54f5be781526 1210 case DONE:
jonathonfletcher 0:54f5be781526 1211 ret = Z_STREAM_END;
jonathonfletcher 0:54f5be781526 1212 goto inf_leave;
jonathonfletcher 0:54f5be781526 1213 case BAD:
jonathonfletcher 0:54f5be781526 1214 ret = Z_DATA_ERROR;
jonathonfletcher 0:54f5be781526 1215 goto inf_leave;
jonathonfletcher 0:54f5be781526 1216 case MEM:
jonathonfletcher 0:54f5be781526 1217 return Z_MEM_ERROR;
jonathonfletcher 0:54f5be781526 1218 case SYNC:
jonathonfletcher 0:54f5be781526 1219 default:
jonathonfletcher 0:54f5be781526 1220 return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 1221 }
jonathonfletcher 0:54f5be781526 1222
jonathonfletcher 0:54f5be781526 1223 /*
jonathonfletcher 0:54f5be781526 1224 Return from inflate(), updating the total counts and the check value.
jonathonfletcher 0:54f5be781526 1225 If there was no progress during the inflate() call, return a buffer
jonathonfletcher 0:54f5be781526 1226 error. Call updatewindow() to create and/or update the window state.
jonathonfletcher 0:54f5be781526 1227 Note: a memory error from inflate() is non-recoverable.
jonathonfletcher 0:54f5be781526 1228 */
jonathonfletcher 0:54f5be781526 1229 inf_leave:
jonathonfletcher 0:54f5be781526 1230 RESTORE();
jonathonfletcher 0:54f5be781526 1231 if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
jonathonfletcher 0:54f5be781526 1232 (state->mode < CHECK || flush != Z_FINISH)))
jonathonfletcher 0:54f5be781526 1233 if (updatewindow(strm, out)) {
jonathonfletcher 0:54f5be781526 1234 state->mode = MEM;
jonathonfletcher 0:54f5be781526 1235 return Z_MEM_ERROR;
jonathonfletcher 0:54f5be781526 1236 }
jonathonfletcher 0:54f5be781526 1237 in -= strm->avail_in;
jonathonfletcher 0:54f5be781526 1238 out -= strm->avail_out;
jonathonfletcher 0:54f5be781526 1239 strm->total_in += in;
jonathonfletcher 0:54f5be781526 1240 strm->total_out += out;
jonathonfletcher 0:54f5be781526 1241 state->total += out;
jonathonfletcher 0:54f5be781526 1242 if (state->wrap && out)
jonathonfletcher 0:54f5be781526 1243 strm->adler = state->check =
jonathonfletcher 0:54f5be781526 1244 UPDATE(state->check, strm->next_out - out, out);
jonathonfletcher 0:54f5be781526 1245 strm->data_type = state->bits + (state->last ? 64 : 0) +
jonathonfletcher 0:54f5be781526 1246 (state->mode == TYPE ? 128 : 0) +
jonathonfletcher 0:54f5be781526 1247 (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
jonathonfletcher 0:54f5be781526 1248 if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
jonathonfletcher 0:54f5be781526 1249 ret = Z_BUF_ERROR;
jonathonfletcher 0:54f5be781526 1250 return ret;
jonathonfletcher 0:54f5be781526 1251 }
jonathonfletcher 0:54f5be781526 1252
jonathonfletcher 0:54f5be781526 1253 int ZEXPORT inflateEnd(strm)
jonathonfletcher 0:54f5be781526 1254 z_streamp strm;
jonathonfletcher 0:54f5be781526 1255 {
jonathonfletcher 0:54f5be781526 1256 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 1257 if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
jonathonfletcher 0:54f5be781526 1258 return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 1259 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 1260 if (state->window != Z_NULL) ZFREE(strm, state->window);
jonathonfletcher 0:54f5be781526 1261 ZFREE(strm, strm->state);
jonathonfletcher 0:54f5be781526 1262 strm->state = Z_NULL;
jonathonfletcher 0:54f5be781526 1263 Tracev((stderr, "inflate: end\n"));
jonathonfletcher 0:54f5be781526 1264 return Z_OK;
jonathonfletcher 0:54f5be781526 1265 }
jonathonfletcher 0:54f5be781526 1266
jonathonfletcher 0:54f5be781526 1267 int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
jonathonfletcher 0:54f5be781526 1268 z_streamp strm;
jonathonfletcher 0:54f5be781526 1269 const Bytef *dictionary;
jonathonfletcher 0:54f5be781526 1270 uInt dictLength;
jonathonfletcher 0:54f5be781526 1271 {
jonathonfletcher 0:54f5be781526 1272 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 1273 unsigned long dictid;
jonathonfletcher 0:54f5be781526 1274 unsigned char *next;
jonathonfletcher 0:54f5be781526 1275 unsigned avail;
jonathonfletcher 0:54f5be781526 1276 int ret;
jonathonfletcher 0:54f5be781526 1277
jonathonfletcher 0:54f5be781526 1278 /* check state */
jonathonfletcher 0:54f5be781526 1279 if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 1280 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 1281 if (state->wrap != 0 && state->mode != DICT)
jonathonfletcher 0:54f5be781526 1282 return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 1283
jonathonfletcher 0:54f5be781526 1284 /* check for correct dictionary identifier */
jonathonfletcher 0:54f5be781526 1285 if (state->mode == DICT) {
jonathonfletcher 0:54f5be781526 1286 dictid = adler32(0L, Z_NULL, 0);
jonathonfletcher 0:54f5be781526 1287 dictid = adler32(dictid, dictionary, dictLength);
jonathonfletcher 0:54f5be781526 1288 if (dictid != state->check)
jonathonfletcher 0:54f5be781526 1289 return Z_DATA_ERROR;
jonathonfletcher 0:54f5be781526 1290 }
jonathonfletcher 0:54f5be781526 1291
jonathonfletcher 0:54f5be781526 1292 /* copy dictionary to window using updatewindow(), which will amend the
jonathonfletcher 0:54f5be781526 1293 existing dictionary if appropriate */
jonathonfletcher 0:54f5be781526 1294 next = strm->next_out;
jonathonfletcher 0:54f5be781526 1295 avail = strm->avail_out;
jonathonfletcher 0:54f5be781526 1296 strm->next_out = (Bytef *)dictionary + dictLength;
jonathonfletcher 0:54f5be781526 1297 strm->avail_out = 0;
jonathonfletcher 0:54f5be781526 1298 ret = updatewindow(strm, dictLength);
jonathonfletcher 0:54f5be781526 1299 strm->avail_out = avail;
jonathonfletcher 0:54f5be781526 1300 strm->next_out = next;
jonathonfletcher 0:54f5be781526 1301 if (ret) {
jonathonfletcher 0:54f5be781526 1302 state->mode = MEM;
jonathonfletcher 0:54f5be781526 1303 return Z_MEM_ERROR;
jonathonfletcher 0:54f5be781526 1304 }
jonathonfletcher 0:54f5be781526 1305 state->havedict = 1;
jonathonfletcher 0:54f5be781526 1306 Tracev((stderr, "inflate: dictionary set\n"));
jonathonfletcher 0:54f5be781526 1307 return Z_OK;
jonathonfletcher 0:54f5be781526 1308 }
jonathonfletcher 0:54f5be781526 1309
jonathonfletcher 0:54f5be781526 1310 int ZEXPORT inflateGetHeader(strm, head)
jonathonfletcher 0:54f5be781526 1311 z_streamp strm;
jonathonfletcher 0:54f5be781526 1312 gz_headerp head;
jonathonfletcher 0:54f5be781526 1313 {
jonathonfletcher 0:54f5be781526 1314 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 1315
jonathonfletcher 0:54f5be781526 1316 /* check state */
jonathonfletcher 0:54f5be781526 1317 if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 1318 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 1319 if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 1320
jonathonfletcher 0:54f5be781526 1321 /* save header structure */
jonathonfletcher 0:54f5be781526 1322 state->head = head;
jonathonfletcher 0:54f5be781526 1323 head->done = 0;
jonathonfletcher 0:54f5be781526 1324 return Z_OK;
jonathonfletcher 0:54f5be781526 1325 }
jonathonfletcher 0:54f5be781526 1326
jonathonfletcher 0:54f5be781526 1327 /*
jonathonfletcher 0:54f5be781526 1328 Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
jonathonfletcher 0:54f5be781526 1329 or when out of input. When called, *have is the number of pattern bytes
jonathonfletcher 0:54f5be781526 1330 found in order so far, in 0..3. On return *have is updated to the new
jonathonfletcher 0:54f5be781526 1331 state. If on return *have equals four, then the pattern was found and the
jonathonfletcher 0:54f5be781526 1332 return value is how many bytes were read including the last byte of the
jonathonfletcher 0:54f5be781526 1333 pattern. If *have is less than four, then the pattern has not been found
jonathonfletcher 0:54f5be781526 1334 yet and the return value is len. In the latter case, syncsearch() can be
jonathonfletcher 0:54f5be781526 1335 called again with more data and the *have state. *have is initialized to
jonathonfletcher 0:54f5be781526 1336 zero for the first call.
jonathonfletcher 0:54f5be781526 1337 */
jonathonfletcher 0:54f5be781526 1338 local unsigned syncsearch(have, buf, len)
jonathonfletcher 0:54f5be781526 1339 unsigned FAR *have;
jonathonfletcher 0:54f5be781526 1340 unsigned char FAR *buf;
jonathonfletcher 0:54f5be781526 1341 unsigned len;
jonathonfletcher 0:54f5be781526 1342 {
jonathonfletcher 0:54f5be781526 1343 unsigned got;
jonathonfletcher 0:54f5be781526 1344 unsigned next;
jonathonfletcher 0:54f5be781526 1345
jonathonfletcher 0:54f5be781526 1346 got = *have;
jonathonfletcher 0:54f5be781526 1347 next = 0;
jonathonfletcher 0:54f5be781526 1348 while (next < len && got < 4) {
jonathonfletcher 0:54f5be781526 1349 if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
jonathonfletcher 0:54f5be781526 1350 got++;
jonathonfletcher 0:54f5be781526 1351 else if (buf[next])
jonathonfletcher 0:54f5be781526 1352 got = 0;
jonathonfletcher 0:54f5be781526 1353 else
jonathonfletcher 0:54f5be781526 1354 got = 4 - got;
jonathonfletcher 0:54f5be781526 1355 next++;
jonathonfletcher 0:54f5be781526 1356 }
jonathonfletcher 0:54f5be781526 1357 *have = got;
jonathonfletcher 0:54f5be781526 1358 return next;
jonathonfletcher 0:54f5be781526 1359 }
jonathonfletcher 0:54f5be781526 1360
jonathonfletcher 0:54f5be781526 1361 int ZEXPORT inflateSync(strm)
jonathonfletcher 0:54f5be781526 1362 z_streamp strm;
jonathonfletcher 0:54f5be781526 1363 {
jonathonfletcher 0:54f5be781526 1364 unsigned len; /* number of bytes to look at or looked at */
jonathonfletcher 0:54f5be781526 1365 unsigned long in, out; /* temporary to save total_in and total_out */
jonathonfletcher 0:54f5be781526 1366 unsigned char buf[4]; /* to restore bit buffer to byte string */
jonathonfletcher 0:54f5be781526 1367 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 1368
jonathonfletcher 0:54f5be781526 1369 /* check parameters */
jonathonfletcher 0:54f5be781526 1370 if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 1371 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 1372 if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
jonathonfletcher 0:54f5be781526 1373
jonathonfletcher 0:54f5be781526 1374 /* if first time, start search in bit buffer */
jonathonfletcher 0:54f5be781526 1375 if (state->mode != SYNC) {
jonathonfletcher 0:54f5be781526 1376 state->mode = SYNC;
jonathonfletcher 0:54f5be781526 1377 state->hold <<= state->bits & 7;
jonathonfletcher 0:54f5be781526 1378 state->bits -= state->bits & 7;
jonathonfletcher 0:54f5be781526 1379 len = 0;
jonathonfletcher 0:54f5be781526 1380 while (state->bits >= 8) {
jonathonfletcher 0:54f5be781526 1381 buf[len++] = (unsigned char)(state->hold);
jonathonfletcher 0:54f5be781526 1382 state->hold >>= 8;
jonathonfletcher 0:54f5be781526 1383 state->bits -= 8;
jonathonfletcher 0:54f5be781526 1384 }
jonathonfletcher 0:54f5be781526 1385 state->have = 0;
jonathonfletcher 0:54f5be781526 1386 syncsearch(&(state->have), buf, len);
jonathonfletcher 0:54f5be781526 1387 }
jonathonfletcher 0:54f5be781526 1388
jonathonfletcher 0:54f5be781526 1389 /* search available input */
jonathonfletcher 0:54f5be781526 1390 len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
jonathonfletcher 0:54f5be781526 1391 strm->avail_in -= len;
jonathonfletcher 0:54f5be781526 1392 strm->next_in += len;
jonathonfletcher 0:54f5be781526 1393 strm->total_in += len;
jonathonfletcher 0:54f5be781526 1394
jonathonfletcher 0:54f5be781526 1395 /* return no joy or set up to restart inflate() on a new block */
jonathonfletcher 0:54f5be781526 1396 if (state->have != 4) return Z_DATA_ERROR;
jonathonfletcher 0:54f5be781526 1397 in = strm->total_in; out = strm->total_out;
jonathonfletcher 0:54f5be781526 1398 inflateReset(strm);
jonathonfletcher 0:54f5be781526 1399 strm->total_in = in; strm->total_out = out;
jonathonfletcher 0:54f5be781526 1400 state->mode = TYPE;
jonathonfletcher 0:54f5be781526 1401 return Z_OK;
jonathonfletcher 0:54f5be781526 1402 }
jonathonfletcher 0:54f5be781526 1403
jonathonfletcher 0:54f5be781526 1404 /*
jonathonfletcher 0:54f5be781526 1405 Returns true if inflate is currently at the end of a block generated by
jonathonfletcher 0:54f5be781526 1406 Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
jonathonfletcher 0:54f5be781526 1407 implementation to provide an additional safety check. PPP uses
jonathonfletcher 0:54f5be781526 1408 Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
jonathonfletcher 0:54f5be781526 1409 block. When decompressing, PPP checks that at the end of input packet,
jonathonfletcher 0:54f5be781526 1410 inflate is waiting for these length bytes.
jonathonfletcher 0:54f5be781526 1411 */
jonathonfletcher 0:54f5be781526 1412 int ZEXPORT inflateSyncPoint(strm)
jonathonfletcher 0:54f5be781526 1413 z_streamp strm;
jonathonfletcher 0:54f5be781526 1414 {
jonathonfletcher 0:54f5be781526 1415 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 1416
jonathonfletcher 0:54f5be781526 1417 if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 1418 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 1419 return state->mode == STORED && state->bits == 0;
jonathonfletcher 0:54f5be781526 1420 }
jonathonfletcher 0:54f5be781526 1421
jonathonfletcher 0:54f5be781526 1422 int ZEXPORT inflateCopy(dest, source)
jonathonfletcher 0:54f5be781526 1423 z_streamp dest;
jonathonfletcher 0:54f5be781526 1424 z_streamp source;
jonathonfletcher 0:54f5be781526 1425 {
jonathonfletcher 0:54f5be781526 1426 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 1427 struct inflate_state FAR *copy;
jonathonfletcher 0:54f5be781526 1428 unsigned char FAR *window;
jonathonfletcher 0:54f5be781526 1429 unsigned wsize;
jonathonfletcher 0:54f5be781526 1430
jonathonfletcher 0:54f5be781526 1431 /* check input */
jonathonfletcher 0:54f5be781526 1432 if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
jonathonfletcher 0:54f5be781526 1433 source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
jonathonfletcher 0:54f5be781526 1434 return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 1435 state = (struct inflate_state FAR *)source->state;
jonathonfletcher 0:54f5be781526 1436
jonathonfletcher 0:54f5be781526 1437 /* allocate space */
jonathonfletcher 0:54f5be781526 1438 copy = (struct inflate_state FAR *)
jonathonfletcher 0:54f5be781526 1439 ZALLOC(source, 1, sizeof(struct inflate_state));
jonathonfletcher 0:54f5be781526 1440 if (copy == Z_NULL) return Z_MEM_ERROR;
jonathonfletcher 0:54f5be781526 1441 window = Z_NULL;
jonathonfletcher 0:54f5be781526 1442 if (state->window != Z_NULL) {
jonathonfletcher 0:54f5be781526 1443 window = (unsigned char FAR *)
jonathonfletcher 0:54f5be781526 1444 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
jonathonfletcher 0:54f5be781526 1445 if (window == Z_NULL) {
jonathonfletcher 0:54f5be781526 1446 ZFREE(source, copy);
jonathonfletcher 0:54f5be781526 1447 return Z_MEM_ERROR;
jonathonfletcher 0:54f5be781526 1448 }
jonathonfletcher 0:54f5be781526 1449 }
jonathonfletcher 0:54f5be781526 1450
jonathonfletcher 0:54f5be781526 1451 /* copy state */
jonathonfletcher 0:54f5be781526 1452 zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
jonathonfletcher 0:54f5be781526 1453 zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
jonathonfletcher 0:54f5be781526 1454 if (state->lencode >= state->codes &&
jonathonfletcher 0:54f5be781526 1455 state->lencode <= state->codes + ENOUGH - 1) {
jonathonfletcher 0:54f5be781526 1456 copy->lencode = copy->codes + (state->lencode - state->codes);
jonathonfletcher 0:54f5be781526 1457 copy->distcode = copy->codes + (state->distcode - state->codes);
jonathonfletcher 0:54f5be781526 1458 }
jonathonfletcher 0:54f5be781526 1459 copy->next = copy->codes + (state->next - state->codes);
jonathonfletcher 0:54f5be781526 1460 if (window != Z_NULL) {
jonathonfletcher 0:54f5be781526 1461 wsize = 1U << state->wbits;
jonathonfletcher 0:54f5be781526 1462 zmemcpy(window, state->window, wsize);
jonathonfletcher 0:54f5be781526 1463 }
jonathonfletcher 0:54f5be781526 1464 copy->window = window;
jonathonfletcher 0:54f5be781526 1465 dest->state = (struct internal_state FAR *)copy;
jonathonfletcher 0:54f5be781526 1466 return Z_OK;
jonathonfletcher 0:54f5be781526 1467 }
jonathonfletcher 0:54f5be781526 1468
jonathonfletcher 0:54f5be781526 1469 int ZEXPORT inflateUndermine(strm, subvert)
jonathonfletcher 0:54f5be781526 1470 z_streamp strm;
jonathonfletcher 0:54f5be781526 1471 int subvert;
jonathonfletcher 0:54f5be781526 1472 {
jonathonfletcher 0:54f5be781526 1473 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 1474
jonathonfletcher 0:54f5be781526 1475 if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 1476 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 1477 state->sane = !subvert;
jonathonfletcher 0:54f5be781526 1478 #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
jonathonfletcher 0:54f5be781526 1479 return Z_OK;
jonathonfletcher 0:54f5be781526 1480 #else
jonathonfletcher 0:54f5be781526 1481 state->sane = 1;
jonathonfletcher 0:54f5be781526 1482 return Z_DATA_ERROR;
jonathonfletcher 0:54f5be781526 1483 #endif
jonathonfletcher 0:54f5be781526 1484 }
jonathonfletcher 0:54f5be781526 1485
jonathonfletcher 0:54f5be781526 1486 long ZEXPORT inflateMark(strm)
jonathonfletcher 0:54f5be781526 1487 z_streamp strm;
jonathonfletcher 0:54f5be781526 1488 {
jonathonfletcher 0:54f5be781526 1489 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 1490
jonathonfletcher 0:54f5be781526 1491 if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16;
jonathonfletcher 0:54f5be781526 1492 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 1493 return ((long)(state->back) << 16) +
jonathonfletcher 0:54f5be781526 1494 (state->mode == COPY ? state->length :
jonathonfletcher 0:54f5be781526 1495 (state->mode == MATCH ? state->was - state->length : 0));
jonathonfletcher 0:54f5be781526 1496 }