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 /* infback.c -- inflate using a call-back interface
jonathonfletcher 0:54f5be781526 2 * Copyright (C) 1995-2011 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 This code is largely copied from inflate.c. Normally either infback.o or
jonathonfletcher 0:54f5be781526 8 inflate.o would be linked into an application--not both. The interface
jonathonfletcher 0:54f5be781526 9 with inffast.c is retained so that optimized assembler-coded versions of
jonathonfletcher 0:54f5be781526 10 inflate_fast() can be used with either inflate.c or infback.c.
jonathonfletcher 0:54f5be781526 11 */
jonathonfletcher 0:54f5be781526 12
jonathonfletcher 0:54f5be781526 13 #include "zutil.h"
jonathonfletcher 0:54f5be781526 14 #include "inftrees.h"
jonathonfletcher 0:54f5be781526 15 #include "inflate.h"
jonathonfletcher 0:54f5be781526 16 #include "inffast.h"
jonathonfletcher 0:54f5be781526 17
jonathonfletcher 0:54f5be781526 18 /* function prototypes */
jonathonfletcher 0:54f5be781526 19 local void fixedtables OF((struct inflate_state FAR *state));
jonathonfletcher 0:54f5be781526 20
jonathonfletcher 0:54f5be781526 21 /*
jonathonfletcher 0:54f5be781526 22 strm provides memory allocation functions in zalloc and zfree, or
jonathonfletcher 0:54f5be781526 23 Z_NULL to use the library memory allocation functions.
jonathonfletcher 0:54f5be781526 24
jonathonfletcher 0:54f5be781526 25 windowBits is in the range 8..15, and window is a user-supplied
jonathonfletcher 0:54f5be781526 26 window and output buffer that is 2**windowBits bytes.
jonathonfletcher 0:54f5be781526 27 */
jonathonfletcher 0:54f5be781526 28 int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
jonathonfletcher 0:54f5be781526 29 z_streamp strm;
jonathonfletcher 0:54f5be781526 30 int windowBits;
jonathonfletcher 0:54f5be781526 31 unsigned char FAR *window;
jonathonfletcher 0:54f5be781526 32 const char *version;
jonathonfletcher 0:54f5be781526 33 int stream_size;
jonathonfletcher 0:54f5be781526 34 {
jonathonfletcher 0:54f5be781526 35 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 36
jonathonfletcher 0:54f5be781526 37 if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
jonathonfletcher 0:54f5be781526 38 stream_size != (int)(sizeof(z_stream)))
jonathonfletcher 0:54f5be781526 39 return Z_VERSION_ERROR;
jonathonfletcher 0:54f5be781526 40 if (strm == Z_NULL || window == Z_NULL ||
jonathonfletcher 0:54f5be781526 41 windowBits < 8 || windowBits > 15)
jonathonfletcher 0:54f5be781526 42 return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 43 strm->msg = Z_NULL; /* in case we return an error */
jonathonfletcher 0:54f5be781526 44 if (strm->zalloc == (alloc_func)0) {
jonathonfletcher 0:54f5be781526 45 #ifdef Z_SOLO
jonathonfletcher 0:54f5be781526 46 return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 47 #else
jonathonfletcher 0:54f5be781526 48 strm->zalloc = zcalloc;
jonathonfletcher 0:54f5be781526 49 strm->opaque = (voidpf)0;
jonathonfletcher 0:54f5be781526 50 #endif
jonathonfletcher 0:54f5be781526 51 }
jonathonfletcher 0:54f5be781526 52 if (strm->zfree == (free_func)0)
jonathonfletcher 0:54f5be781526 53 #ifdef Z_SOLO
jonathonfletcher 0:54f5be781526 54 return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 55 #else
jonathonfletcher 0:54f5be781526 56 strm->zfree = zcfree;
jonathonfletcher 0:54f5be781526 57 #endif
jonathonfletcher 0:54f5be781526 58 state = (struct inflate_state FAR *)ZALLOC(strm, 1,
jonathonfletcher 0:54f5be781526 59 sizeof(struct inflate_state));
jonathonfletcher 0:54f5be781526 60 if (state == Z_NULL) return Z_MEM_ERROR;
jonathonfletcher 0:54f5be781526 61 Tracev((stderr, "inflate: allocated\n"));
jonathonfletcher 0:54f5be781526 62 strm->state = (struct internal_state FAR *)state;
jonathonfletcher 0:54f5be781526 63 state->dmax = 32768U;
jonathonfletcher 0:54f5be781526 64 state->wbits = windowBits;
jonathonfletcher 0:54f5be781526 65 state->wsize = 1U << windowBits;
jonathonfletcher 0:54f5be781526 66 state->window = window;
jonathonfletcher 0:54f5be781526 67 state->wnext = 0;
jonathonfletcher 0:54f5be781526 68 state->whave = 0;
jonathonfletcher 0:54f5be781526 69 return Z_OK;
jonathonfletcher 0:54f5be781526 70 }
jonathonfletcher 0:54f5be781526 71
jonathonfletcher 0:54f5be781526 72 /*
jonathonfletcher 0:54f5be781526 73 Return state with length and distance decoding tables and index sizes set to
jonathonfletcher 0:54f5be781526 74 fixed code decoding. Normally this returns fixed tables from inffixed.h.
jonathonfletcher 0:54f5be781526 75 If BUILDFIXED is defined, then instead this routine builds the tables the
jonathonfletcher 0:54f5be781526 76 first time it's called, and returns those tables the first time and
jonathonfletcher 0:54f5be781526 77 thereafter. This reduces the size of the code by about 2K bytes, in
jonathonfletcher 0:54f5be781526 78 exchange for a little execution time. However, BUILDFIXED should not be
jonathonfletcher 0:54f5be781526 79 used for threaded applications, since the rewriting of the tables and virgin
jonathonfletcher 0:54f5be781526 80 may not be thread-safe.
jonathonfletcher 0:54f5be781526 81 */
jonathonfletcher 0:54f5be781526 82 local void fixedtables(state)
jonathonfletcher 0:54f5be781526 83 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 84 {
jonathonfletcher 0:54f5be781526 85 #ifdef BUILDFIXED
jonathonfletcher 0:54f5be781526 86 static int virgin = 1;
jonathonfletcher 0:54f5be781526 87 static code *lenfix, *distfix;
jonathonfletcher 0:54f5be781526 88 static code fixed[544];
jonathonfletcher 0:54f5be781526 89
jonathonfletcher 0:54f5be781526 90 /* build fixed huffman tables if first call (may not be thread safe) */
jonathonfletcher 0:54f5be781526 91 if (virgin) {
jonathonfletcher 0:54f5be781526 92 unsigned sym, bits;
jonathonfletcher 0:54f5be781526 93 static code *next;
jonathonfletcher 0:54f5be781526 94
jonathonfletcher 0:54f5be781526 95 /* literal/length table */
jonathonfletcher 0:54f5be781526 96 sym = 0;
jonathonfletcher 0:54f5be781526 97 while (sym < 144) state->lens[sym++] = 8;
jonathonfletcher 0:54f5be781526 98 while (sym < 256) state->lens[sym++] = 9;
jonathonfletcher 0:54f5be781526 99 while (sym < 280) state->lens[sym++] = 7;
jonathonfletcher 0:54f5be781526 100 while (sym < 288) state->lens[sym++] = 8;
jonathonfletcher 0:54f5be781526 101 next = fixed;
jonathonfletcher 0:54f5be781526 102 lenfix = next;
jonathonfletcher 0:54f5be781526 103 bits = 9;
jonathonfletcher 0:54f5be781526 104 inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
jonathonfletcher 0:54f5be781526 105
jonathonfletcher 0:54f5be781526 106 /* distance table */
jonathonfletcher 0:54f5be781526 107 sym = 0;
jonathonfletcher 0:54f5be781526 108 while (sym < 32) state->lens[sym++] = 5;
jonathonfletcher 0:54f5be781526 109 distfix = next;
jonathonfletcher 0:54f5be781526 110 bits = 5;
jonathonfletcher 0:54f5be781526 111 inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
jonathonfletcher 0:54f5be781526 112
jonathonfletcher 0:54f5be781526 113 /* do this just once */
jonathonfletcher 0:54f5be781526 114 virgin = 0;
jonathonfletcher 0:54f5be781526 115 }
jonathonfletcher 0:54f5be781526 116 #else /* !BUILDFIXED */
jonathonfletcher 0:54f5be781526 117 # include "inffixed.h"
jonathonfletcher 0:54f5be781526 118 #endif /* BUILDFIXED */
jonathonfletcher 0:54f5be781526 119 state->lencode = lenfix;
jonathonfletcher 0:54f5be781526 120 state->lenbits = 9;
jonathonfletcher 0:54f5be781526 121 state->distcode = distfix;
jonathonfletcher 0:54f5be781526 122 state->distbits = 5;
jonathonfletcher 0:54f5be781526 123 }
jonathonfletcher 0:54f5be781526 124
jonathonfletcher 0:54f5be781526 125 /* Macros for inflateBack(): */
jonathonfletcher 0:54f5be781526 126
jonathonfletcher 0:54f5be781526 127 /* Load returned state from inflate_fast() */
jonathonfletcher 0:54f5be781526 128 #define LOAD() \
jonathonfletcher 0:54f5be781526 129 do { \
jonathonfletcher 0:54f5be781526 130 put = strm->next_out; \
jonathonfletcher 0:54f5be781526 131 left = strm->avail_out; \
jonathonfletcher 0:54f5be781526 132 next = strm->next_in; \
jonathonfletcher 0:54f5be781526 133 have = strm->avail_in; \
jonathonfletcher 0:54f5be781526 134 hold = state->hold; \
jonathonfletcher 0:54f5be781526 135 bits = state->bits; \
jonathonfletcher 0:54f5be781526 136 } while (0)
jonathonfletcher 0:54f5be781526 137
jonathonfletcher 0:54f5be781526 138 /* Set state from registers for inflate_fast() */
jonathonfletcher 0:54f5be781526 139 #define RESTORE() \
jonathonfletcher 0:54f5be781526 140 do { \
jonathonfletcher 0:54f5be781526 141 strm->next_out = put; \
jonathonfletcher 0:54f5be781526 142 strm->avail_out = left; \
jonathonfletcher 0:54f5be781526 143 strm->next_in = next; \
jonathonfletcher 0:54f5be781526 144 strm->avail_in = have; \
jonathonfletcher 0:54f5be781526 145 state->hold = hold; \
jonathonfletcher 0:54f5be781526 146 state->bits = bits; \
jonathonfletcher 0:54f5be781526 147 } while (0)
jonathonfletcher 0:54f5be781526 148
jonathonfletcher 0:54f5be781526 149 /* Clear the input bit accumulator */
jonathonfletcher 0:54f5be781526 150 #define INITBITS() \
jonathonfletcher 0:54f5be781526 151 do { \
jonathonfletcher 0:54f5be781526 152 hold = 0; \
jonathonfletcher 0:54f5be781526 153 bits = 0; \
jonathonfletcher 0:54f5be781526 154 } while (0)
jonathonfletcher 0:54f5be781526 155
jonathonfletcher 0:54f5be781526 156 /* Assure that some input is available. If input is requested, but denied,
jonathonfletcher 0:54f5be781526 157 then return a Z_BUF_ERROR from inflateBack(). */
jonathonfletcher 0:54f5be781526 158 #define PULL() \
jonathonfletcher 0:54f5be781526 159 do { \
jonathonfletcher 0:54f5be781526 160 if (have == 0) { \
jonathonfletcher 0:54f5be781526 161 have = in(in_desc, &next); \
jonathonfletcher 0:54f5be781526 162 if (have == 0) { \
jonathonfletcher 0:54f5be781526 163 next = Z_NULL; \
jonathonfletcher 0:54f5be781526 164 ret = Z_BUF_ERROR; \
jonathonfletcher 0:54f5be781526 165 goto inf_leave; \
jonathonfletcher 0:54f5be781526 166 } \
jonathonfletcher 0:54f5be781526 167 } \
jonathonfletcher 0:54f5be781526 168 } while (0)
jonathonfletcher 0:54f5be781526 169
jonathonfletcher 0:54f5be781526 170 /* Get a byte of input into the bit accumulator, or return from inflateBack()
jonathonfletcher 0:54f5be781526 171 with an error if there is no input available. */
jonathonfletcher 0:54f5be781526 172 #define PULLBYTE() \
jonathonfletcher 0:54f5be781526 173 do { \
jonathonfletcher 0:54f5be781526 174 PULL(); \
jonathonfletcher 0:54f5be781526 175 have--; \
jonathonfletcher 0:54f5be781526 176 hold += (unsigned long)(*next++) << bits; \
jonathonfletcher 0:54f5be781526 177 bits += 8; \
jonathonfletcher 0:54f5be781526 178 } while (0)
jonathonfletcher 0:54f5be781526 179
jonathonfletcher 0:54f5be781526 180 /* Assure that there are at least n bits in the bit accumulator. If there is
jonathonfletcher 0:54f5be781526 181 not enough available input to do that, then return from inflateBack() with
jonathonfletcher 0:54f5be781526 182 an error. */
jonathonfletcher 0:54f5be781526 183 #define NEEDBITS(n) \
jonathonfletcher 0:54f5be781526 184 do { \
jonathonfletcher 0:54f5be781526 185 while (bits < (unsigned)(n)) \
jonathonfletcher 0:54f5be781526 186 PULLBYTE(); \
jonathonfletcher 0:54f5be781526 187 } while (0)
jonathonfletcher 0:54f5be781526 188
jonathonfletcher 0:54f5be781526 189 /* Return the low n bits of the bit accumulator (n < 16) */
jonathonfletcher 0:54f5be781526 190 #define BITS(n) \
jonathonfletcher 0:54f5be781526 191 ((unsigned)hold & ((1U << (n)) - 1))
jonathonfletcher 0:54f5be781526 192
jonathonfletcher 0:54f5be781526 193 /* Remove n bits from the bit accumulator */
jonathonfletcher 0:54f5be781526 194 #define DROPBITS(n) \
jonathonfletcher 0:54f5be781526 195 do { \
jonathonfletcher 0:54f5be781526 196 hold >>= (n); \
jonathonfletcher 0:54f5be781526 197 bits -= (unsigned)(n); \
jonathonfletcher 0:54f5be781526 198 } while (0)
jonathonfletcher 0:54f5be781526 199
jonathonfletcher 0:54f5be781526 200 /* Remove zero to seven bits as needed to go to a byte boundary */
jonathonfletcher 0:54f5be781526 201 #define BYTEBITS() \
jonathonfletcher 0:54f5be781526 202 do { \
jonathonfletcher 0:54f5be781526 203 hold >>= bits & 7; \
jonathonfletcher 0:54f5be781526 204 bits -= bits & 7; \
jonathonfletcher 0:54f5be781526 205 } while (0)
jonathonfletcher 0:54f5be781526 206
jonathonfletcher 0:54f5be781526 207 /* Assure that some output space is available, by writing out the window
jonathonfletcher 0:54f5be781526 208 if it's full. If the write fails, return from inflateBack() with a
jonathonfletcher 0:54f5be781526 209 Z_BUF_ERROR. */
jonathonfletcher 0:54f5be781526 210 #define ROOM() \
jonathonfletcher 0:54f5be781526 211 do { \
jonathonfletcher 0:54f5be781526 212 if (left == 0) { \
jonathonfletcher 0:54f5be781526 213 put = state->window; \
jonathonfletcher 0:54f5be781526 214 left = state->wsize; \
jonathonfletcher 0:54f5be781526 215 state->whave = left; \
jonathonfletcher 0:54f5be781526 216 if (out(out_desc, put, left)) { \
jonathonfletcher 0:54f5be781526 217 ret = Z_BUF_ERROR; \
jonathonfletcher 0:54f5be781526 218 goto inf_leave; \
jonathonfletcher 0:54f5be781526 219 } \
jonathonfletcher 0:54f5be781526 220 } \
jonathonfletcher 0:54f5be781526 221 } while (0)
jonathonfletcher 0:54f5be781526 222
jonathonfletcher 0:54f5be781526 223 /*
jonathonfletcher 0:54f5be781526 224 strm provides the memory allocation functions and window buffer on input,
jonathonfletcher 0:54f5be781526 225 and provides information on the unused input on return. For Z_DATA_ERROR
jonathonfletcher 0:54f5be781526 226 returns, strm will also provide an error message.
jonathonfletcher 0:54f5be781526 227
jonathonfletcher 0:54f5be781526 228 in() and out() are the call-back input and output functions. When
jonathonfletcher 0:54f5be781526 229 inflateBack() needs more input, it calls in(). When inflateBack() has
jonathonfletcher 0:54f5be781526 230 filled the window with output, or when it completes with data in the
jonathonfletcher 0:54f5be781526 231 window, it calls out() to write out the data. The application must not
jonathonfletcher 0:54f5be781526 232 change the provided input until in() is called again or inflateBack()
jonathonfletcher 0:54f5be781526 233 returns. The application must not change the window/output buffer until
jonathonfletcher 0:54f5be781526 234 inflateBack() returns.
jonathonfletcher 0:54f5be781526 235
jonathonfletcher 0:54f5be781526 236 in() and out() are called with a descriptor parameter provided in the
jonathonfletcher 0:54f5be781526 237 inflateBack() call. This parameter can be a structure that provides the
jonathonfletcher 0:54f5be781526 238 information required to do the read or write, as well as accumulated
jonathonfletcher 0:54f5be781526 239 information on the input and output such as totals and check values.
jonathonfletcher 0:54f5be781526 240
jonathonfletcher 0:54f5be781526 241 in() should return zero on failure. out() should return non-zero on
jonathonfletcher 0:54f5be781526 242 failure. If either in() or out() fails, than inflateBack() returns a
jonathonfletcher 0:54f5be781526 243 Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
jonathonfletcher 0:54f5be781526 244 was in() or out() that caused in the error. Otherwise, inflateBack()
jonathonfletcher 0:54f5be781526 245 returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
jonathonfletcher 0:54f5be781526 246 error, or Z_MEM_ERROR if it could not allocate memory for the state.
jonathonfletcher 0:54f5be781526 247 inflateBack() can also return Z_STREAM_ERROR if the input parameters
jonathonfletcher 0:54f5be781526 248 are not correct, i.e. strm is Z_NULL or the state was not initialized.
jonathonfletcher 0:54f5be781526 249 */
jonathonfletcher 0:54f5be781526 250 int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
jonathonfletcher 0:54f5be781526 251 z_streamp strm;
jonathonfletcher 0:54f5be781526 252 in_func in;
jonathonfletcher 0:54f5be781526 253 void FAR *in_desc;
jonathonfletcher 0:54f5be781526 254 out_func out;
jonathonfletcher 0:54f5be781526 255 void FAR *out_desc;
jonathonfletcher 0:54f5be781526 256 {
jonathonfletcher 0:54f5be781526 257 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 258 unsigned char FAR *next; /* next input */
jonathonfletcher 0:54f5be781526 259 unsigned char FAR *put; /* next output */
jonathonfletcher 0:54f5be781526 260 unsigned have, left; /* available input and output */
jonathonfletcher 0:54f5be781526 261 unsigned long hold; /* bit buffer */
jonathonfletcher 0:54f5be781526 262 unsigned bits; /* bits in bit buffer */
jonathonfletcher 0:54f5be781526 263 unsigned copy; /* number of stored or match bytes to copy */
jonathonfletcher 0:54f5be781526 264 unsigned char FAR *from; /* where to copy match bytes from */
jonathonfletcher 0:54f5be781526 265 code here; /* current decoding table entry */
jonathonfletcher 0:54f5be781526 266 code last; /* parent table entry */
jonathonfletcher 0:54f5be781526 267 unsigned len; /* length to copy for repeats, bits to drop */
jonathonfletcher 0:54f5be781526 268 int ret; /* return code */
jonathonfletcher 0:54f5be781526 269 static const unsigned short order[19] = /* permutation of code lengths */
jonathonfletcher 0:54f5be781526 270 {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
jonathonfletcher 0:54f5be781526 271
jonathonfletcher 0:54f5be781526 272 /* Check that the strm exists and that the state was initialized */
jonathonfletcher 0:54f5be781526 273 if (strm == Z_NULL || strm->state == Z_NULL)
jonathonfletcher 0:54f5be781526 274 return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 275 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 276
jonathonfletcher 0:54f5be781526 277 /* Reset the state */
jonathonfletcher 0:54f5be781526 278 strm->msg = Z_NULL;
jonathonfletcher 0:54f5be781526 279 state->mode = TYPE;
jonathonfletcher 0:54f5be781526 280 state->last = 0;
jonathonfletcher 0:54f5be781526 281 state->whave = 0;
jonathonfletcher 0:54f5be781526 282 next = strm->next_in;
jonathonfletcher 0:54f5be781526 283 have = next != Z_NULL ? strm->avail_in : 0;
jonathonfletcher 0:54f5be781526 284 hold = 0;
jonathonfletcher 0:54f5be781526 285 bits = 0;
jonathonfletcher 0:54f5be781526 286 put = state->window;
jonathonfletcher 0:54f5be781526 287 left = state->wsize;
jonathonfletcher 0:54f5be781526 288
jonathonfletcher 0:54f5be781526 289 /* Inflate until end of block marked as last */
jonathonfletcher 0:54f5be781526 290 for (;;)
jonathonfletcher 0:54f5be781526 291 switch (state->mode) {
jonathonfletcher 0:54f5be781526 292 case TYPE:
jonathonfletcher 0:54f5be781526 293 /* determine and dispatch block type */
jonathonfletcher 0:54f5be781526 294 if (state->last) {
jonathonfletcher 0:54f5be781526 295 BYTEBITS();
jonathonfletcher 0:54f5be781526 296 state->mode = DONE;
jonathonfletcher 0:54f5be781526 297 break;
jonathonfletcher 0:54f5be781526 298 }
jonathonfletcher 0:54f5be781526 299 NEEDBITS(3);
jonathonfletcher 0:54f5be781526 300 state->last = BITS(1);
jonathonfletcher 0:54f5be781526 301 DROPBITS(1);
jonathonfletcher 0:54f5be781526 302 switch (BITS(2)) {
jonathonfletcher 0:54f5be781526 303 case 0: /* stored block */
jonathonfletcher 0:54f5be781526 304 Tracev((stderr, "inflate: stored block%s\n",
jonathonfletcher 0:54f5be781526 305 state->last ? " (last)" : ""));
jonathonfletcher 0:54f5be781526 306 state->mode = STORED;
jonathonfletcher 0:54f5be781526 307 break;
jonathonfletcher 0:54f5be781526 308 case 1: /* fixed block */
jonathonfletcher 0:54f5be781526 309 fixedtables(state);
jonathonfletcher 0:54f5be781526 310 Tracev((stderr, "inflate: fixed codes block%s\n",
jonathonfletcher 0:54f5be781526 311 state->last ? " (last)" : ""));
jonathonfletcher 0:54f5be781526 312 state->mode = LEN; /* decode codes */
jonathonfletcher 0:54f5be781526 313 break;
jonathonfletcher 0:54f5be781526 314 case 2: /* dynamic block */
jonathonfletcher 0:54f5be781526 315 Tracev((stderr, "inflate: dynamic codes block%s\n",
jonathonfletcher 0:54f5be781526 316 state->last ? " (last)" : ""));
jonathonfletcher 0:54f5be781526 317 state->mode = TABLE;
jonathonfletcher 0:54f5be781526 318 break;
jonathonfletcher 0:54f5be781526 319 case 3:
jonathonfletcher 0:54f5be781526 320 strm->msg = (char *)"invalid block type";
jonathonfletcher 0:54f5be781526 321 state->mode = BAD;
jonathonfletcher 0:54f5be781526 322 }
jonathonfletcher 0:54f5be781526 323 DROPBITS(2);
jonathonfletcher 0:54f5be781526 324 break;
jonathonfletcher 0:54f5be781526 325
jonathonfletcher 0:54f5be781526 326 case STORED:
jonathonfletcher 0:54f5be781526 327 /* get and verify stored block length */
jonathonfletcher 0:54f5be781526 328 BYTEBITS(); /* go to byte boundary */
jonathonfletcher 0:54f5be781526 329 NEEDBITS(32);
jonathonfletcher 0:54f5be781526 330 if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
jonathonfletcher 0:54f5be781526 331 strm->msg = (char *)"invalid stored block lengths";
jonathonfletcher 0:54f5be781526 332 state->mode = BAD;
jonathonfletcher 0:54f5be781526 333 break;
jonathonfletcher 0:54f5be781526 334 }
jonathonfletcher 0:54f5be781526 335 state->length = (unsigned)hold & 0xffff;
jonathonfletcher 0:54f5be781526 336 Tracev((stderr, "inflate: stored length %u\n",
jonathonfletcher 0:54f5be781526 337 state->length));
jonathonfletcher 0:54f5be781526 338 INITBITS();
jonathonfletcher 0:54f5be781526 339
jonathonfletcher 0:54f5be781526 340 /* copy stored block from input to output */
jonathonfletcher 0:54f5be781526 341 while (state->length != 0) {
jonathonfletcher 0:54f5be781526 342 copy = state->length;
jonathonfletcher 0:54f5be781526 343 PULL();
jonathonfletcher 0:54f5be781526 344 ROOM();
jonathonfletcher 0:54f5be781526 345 if (copy > have) copy = have;
jonathonfletcher 0:54f5be781526 346 if (copy > left) copy = left;
jonathonfletcher 0:54f5be781526 347 zmemcpy(put, next, copy);
jonathonfletcher 0:54f5be781526 348 have -= copy;
jonathonfletcher 0:54f5be781526 349 next += copy;
jonathonfletcher 0:54f5be781526 350 left -= copy;
jonathonfletcher 0:54f5be781526 351 put += copy;
jonathonfletcher 0:54f5be781526 352 state->length -= copy;
jonathonfletcher 0:54f5be781526 353 }
jonathonfletcher 0:54f5be781526 354 Tracev((stderr, "inflate: stored end\n"));
jonathonfletcher 0:54f5be781526 355 state->mode = TYPE;
jonathonfletcher 0:54f5be781526 356 break;
jonathonfletcher 0:54f5be781526 357
jonathonfletcher 0:54f5be781526 358 case TABLE:
jonathonfletcher 0:54f5be781526 359 /* get dynamic table entries descriptor */
jonathonfletcher 0:54f5be781526 360 NEEDBITS(14);
jonathonfletcher 0:54f5be781526 361 state->nlen = BITS(5) + 257;
jonathonfletcher 0:54f5be781526 362 DROPBITS(5);
jonathonfletcher 0:54f5be781526 363 state->ndist = BITS(5) + 1;
jonathonfletcher 0:54f5be781526 364 DROPBITS(5);
jonathonfletcher 0:54f5be781526 365 state->ncode = BITS(4) + 4;
jonathonfletcher 0:54f5be781526 366 DROPBITS(4);
jonathonfletcher 0:54f5be781526 367 #ifndef PKZIP_BUG_WORKAROUND
jonathonfletcher 0:54f5be781526 368 if (state->nlen > 286 || state->ndist > 30) {
jonathonfletcher 0:54f5be781526 369 strm->msg = (char *)"too many length or distance symbols";
jonathonfletcher 0:54f5be781526 370 state->mode = BAD;
jonathonfletcher 0:54f5be781526 371 break;
jonathonfletcher 0:54f5be781526 372 }
jonathonfletcher 0:54f5be781526 373 #endif
jonathonfletcher 0:54f5be781526 374 Tracev((stderr, "inflate: table sizes ok\n"));
jonathonfletcher 0:54f5be781526 375
jonathonfletcher 0:54f5be781526 376 /* get code length code lengths (not a typo) */
jonathonfletcher 0:54f5be781526 377 state->have = 0;
jonathonfletcher 0:54f5be781526 378 while (state->have < state->ncode) {
jonathonfletcher 0:54f5be781526 379 NEEDBITS(3);
jonathonfletcher 0:54f5be781526 380 state->lens[order[state->have++]] = (unsigned short)BITS(3);
jonathonfletcher 0:54f5be781526 381 DROPBITS(3);
jonathonfletcher 0:54f5be781526 382 }
jonathonfletcher 0:54f5be781526 383 while (state->have < 19)
jonathonfletcher 0:54f5be781526 384 state->lens[order[state->have++]] = 0;
jonathonfletcher 0:54f5be781526 385 state->next = state->codes;
jonathonfletcher 0:54f5be781526 386 state->lencode = (code const FAR *)(state->next);
jonathonfletcher 0:54f5be781526 387 state->lenbits = 7;
jonathonfletcher 0:54f5be781526 388 ret = inflate_table(CODES, state->lens, 19, &(state->next),
jonathonfletcher 0:54f5be781526 389 &(state->lenbits), state->work);
jonathonfletcher 0:54f5be781526 390 if (ret) {
jonathonfletcher 0:54f5be781526 391 strm->msg = (char *)"invalid code lengths set";
jonathonfletcher 0:54f5be781526 392 state->mode = BAD;
jonathonfletcher 0:54f5be781526 393 break;
jonathonfletcher 0:54f5be781526 394 }
jonathonfletcher 0:54f5be781526 395 Tracev((stderr, "inflate: code lengths ok\n"));
jonathonfletcher 0:54f5be781526 396
jonathonfletcher 0:54f5be781526 397 /* get length and distance code code lengths */
jonathonfletcher 0:54f5be781526 398 state->have = 0;
jonathonfletcher 0:54f5be781526 399 while (state->have < state->nlen + state->ndist) {
jonathonfletcher 0:54f5be781526 400 for (;;) {
jonathonfletcher 0:54f5be781526 401 here = state->lencode[BITS(state->lenbits)];
jonathonfletcher 0:54f5be781526 402 if ((unsigned)(here.bits) <= bits) break;
jonathonfletcher 0:54f5be781526 403 PULLBYTE();
jonathonfletcher 0:54f5be781526 404 }
jonathonfletcher 0:54f5be781526 405 if (here.val < 16) {
jonathonfletcher 0:54f5be781526 406 DROPBITS(here.bits);
jonathonfletcher 0:54f5be781526 407 state->lens[state->have++] = here.val;
jonathonfletcher 0:54f5be781526 408 }
jonathonfletcher 0:54f5be781526 409 else {
jonathonfletcher 0:54f5be781526 410 if (here.val == 16) {
jonathonfletcher 0:54f5be781526 411 NEEDBITS(here.bits + 2);
jonathonfletcher 0:54f5be781526 412 DROPBITS(here.bits);
jonathonfletcher 0:54f5be781526 413 if (state->have == 0) {
jonathonfletcher 0:54f5be781526 414 strm->msg = (char *)"invalid bit length repeat";
jonathonfletcher 0:54f5be781526 415 state->mode = BAD;
jonathonfletcher 0:54f5be781526 416 break;
jonathonfletcher 0:54f5be781526 417 }
jonathonfletcher 0:54f5be781526 418 len = (unsigned)(state->lens[state->have - 1]);
jonathonfletcher 0:54f5be781526 419 copy = 3 + BITS(2);
jonathonfletcher 0:54f5be781526 420 DROPBITS(2);
jonathonfletcher 0:54f5be781526 421 }
jonathonfletcher 0:54f5be781526 422 else if (here.val == 17) {
jonathonfletcher 0:54f5be781526 423 NEEDBITS(here.bits + 3);
jonathonfletcher 0:54f5be781526 424 DROPBITS(here.bits);
jonathonfletcher 0:54f5be781526 425 len = 0;
jonathonfletcher 0:54f5be781526 426 copy = 3 + BITS(3);
jonathonfletcher 0:54f5be781526 427 DROPBITS(3);
jonathonfletcher 0:54f5be781526 428 }
jonathonfletcher 0:54f5be781526 429 else {
jonathonfletcher 0:54f5be781526 430 NEEDBITS(here.bits + 7);
jonathonfletcher 0:54f5be781526 431 DROPBITS(here.bits);
jonathonfletcher 0:54f5be781526 432 len = 0;
jonathonfletcher 0:54f5be781526 433 copy = 11 + BITS(7);
jonathonfletcher 0:54f5be781526 434 DROPBITS(7);
jonathonfletcher 0:54f5be781526 435 }
jonathonfletcher 0:54f5be781526 436 if (state->have + copy > state->nlen + state->ndist) {
jonathonfletcher 0:54f5be781526 437 strm->msg = (char *)"invalid bit length repeat";
jonathonfletcher 0:54f5be781526 438 state->mode = BAD;
jonathonfletcher 0:54f5be781526 439 break;
jonathonfletcher 0:54f5be781526 440 }
jonathonfletcher 0:54f5be781526 441 while (copy--)
jonathonfletcher 0:54f5be781526 442 state->lens[state->have++] = (unsigned short)len;
jonathonfletcher 0:54f5be781526 443 }
jonathonfletcher 0:54f5be781526 444 }
jonathonfletcher 0:54f5be781526 445
jonathonfletcher 0:54f5be781526 446 /* handle error breaks in while */
jonathonfletcher 0:54f5be781526 447 if (state->mode == BAD) break;
jonathonfletcher 0:54f5be781526 448
jonathonfletcher 0:54f5be781526 449 /* check for end-of-block code (better have one) */
jonathonfletcher 0:54f5be781526 450 if (state->lens[256] == 0) {
jonathonfletcher 0:54f5be781526 451 strm->msg = (char *)"invalid code -- missing end-of-block";
jonathonfletcher 0:54f5be781526 452 state->mode = BAD;
jonathonfletcher 0:54f5be781526 453 break;
jonathonfletcher 0:54f5be781526 454 }
jonathonfletcher 0:54f5be781526 455
jonathonfletcher 0:54f5be781526 456 /* build code tables -- note: do not change the lenbits or distbits
jonathonfletcher 0:54f5be781526 457 values here (9 and 6) without reading the comments in inftrees.h
jonathonfletcher 0:54f5be781526 458 concerning the ENOUGH constants, which depend on those values */
jonathonfletcher 0:54f5be781526 459 state->next = state->codes;
jonathonfletcher 0:54f5be781526 460 state->lencode = (code const FAR *)(state->next);
jonathonfletcher 0:54f5be781526 461 state->lenbits = 9;
jonathonfletcher 0:54f5be781526 462 ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
jonathonfletcher 0:54f5be781526 463 &(state->lenbits), state->work);
jonathonfletcher 0:54f5be781526 464 if (ret) {
jonathonfletcher 0:54f5be781526 465 strm->msg = (char *)"invalid literal/lengths set";
jonathonfletcher 0:54f5be781526 466 state->mode = BAD;
jonathonfletcher 0:54f5be781526 467 break;
jonathonfletcher 0:54f5be781526 468 }
jonathonfletcher 0:54f5be781526 469 state->distcode = (code const FAR *)(state->next);
jonathonfletcher 0:54f5be781526 470 state->distbits = 6;
jonathonfletcher 0:54f5be781526 471 ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
jonathonfletcher 0:54f5be781526 472 &(state->next), &(state->distbits), state->work);
jonathonfletcher 0:54f5be781526 473 if (ret) {
jonathonfletcher 0:54f5be781526 474 strm->msg = (char *)"invalid distances set";
jonathonfletcher 0:54f5be781526 475 state->mode = BAD;
jonathonfletcher 0:54f5be781526 476 break;
jonathonfletcher 0:54f5be781526 477 }
jonathonfletcher 0:54f5be781526 478 Tracev((stderr, "inflate: codes ok\n"));
jonathonfletcher 0:54f5be781526 479 state->mode = LEN;
jonathonfletcher 0:54f5be781526 480
jonathonfletcher 0:54f5be781526 481 case LEN:
jonathonfletcher 0:54f5be781526 482 /* use inflate_fast() if we have enough input and output */
jonathonfletcher 0:54f5be781526 483 if (have >= 6 && left >= 258) {
jonathonfletcher 0:54f5be781526 484 RESTORE();
jonathonfletcher 0:54f5be781526 485 if (state->whave < state->wsize)
jonathonfletcher 0:54f5be781526 486 state->whave = state->wsize - left;
jonathonfletcher 0:54f5be781526 487 inflate_fast(strm, state->wsize);
jonathonfletcher 0:54f5be781526 488 LOAD();
jonathonfletcher 0:54f5be781526 489 break;
jonathonfletcher 0:54f5be781526 490 }
jonathonfletcher 0:54f5be781526 491
jonathonfletcher 0:54f5be781526 492 /* get a literal, length, or end-of-block code */
jonathonfletcher 0:54f5be781526 493 for (;;) {
jonathonfletcher 0:54f5be781526 494 here = state->lencode[BITS(state->lenbits)];
jonathonfletcher 0:54f5be781526 495 if ((unsigned)(here.bits) <= bits) break;
jonathonfletcher 0:54f5be781526 496 PULLBYTE();
jonathonfletcher 0:54f5be781526 497 }
jonathonfletcher 0:54f5be781526 498 if (here.op && (here.op & 0xf0) == 0) {
jonathonfletcher 0:54f5be781526 499 last = here;
jonathonfletcher 0:54f5be781526 500 for (;;) {
jonathonfletcher 0:54f5be781526 501 here = state->lencode[last.val +
jonathonfletcher 0:54f5be781526 502 (BITS(last.bits + last.op) >> last.bits)];
jonathonfletcher 0:54f5be781526 503 if ((unsigned)(last.bits + here.bits) <= bits) break;
jonathonfletcher 0:54f5be781526 504 PULLBYTE();
jonathonfletcher 0:54f5be781526 505 }
jonathonfletcher 0:54f5be781526 506 DROPBITS(last.bits);
jonathonfletcher 0:54f5be781526 507 }
jonathonfletcher 0:54f5be781526 508 DROPBITS(here.bits);
jonathonfletcher 0:54f5be781526 509 state->length = (unsigned)here.val;
jonathonfletcher 0:54f5be781526 510
jonathonfletcher 0:54f5be781526 511 /* process literal */
jonathonfletcher 0:54f5be781526 512 if (here.op == 0) {
jonathonfletcher 0:54f5be781526 513 Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
jonathonfletcher 0:54f5be781526 514 "inflate: literal '%c'\n" :
jonathonfletcher 0:54f5be781526 515 "inflate: literal 0x%02x\n", here.val));
jonathonfletcher 0:54f5be781526 516 ROOM();
jonathonfletcher 0:54f5be781526 517 *put++ = (unsigned char)(state->length);
jonathonfletcher 0:54f5be781526 518 left--;
jonathonfletcher 0:54f5be781526 519 state->mode = LEN;
jonathonfletcher 0:54f5be781526 520 break;
jonathonfletcher 0:54f5be781526 521 }
jonathonfletcher 0:54f5be781526 522
jonathonfletcher 0:54f5be781526 523 /* process end of block */
jonathonfletcher 0:54f5be781526 524 if (here.op & 32) {
jonathonfletcher 0:54f5be781526 525 Tracevv((stderr, "inflate: end of block\n"));
jonathonfletcher 0:54f5be781526 526 state->mode = TYPE;
jonathonfletcher 0:54f5be781526 527 break;
jonathonfletcher 0:54f5be781526 528 }
jonathonfletcher 0:54f5be781526 529
jonathonfletcher 0:54f5be781526 530 /* invalid code */
jonathonfletcher 0:54f5be781526 531 if (here.op & 64) {
jonathonfletcher 0:54f5be781526 532 strm->msg = (char *)"invalid literal/length code";
jonathonfletcher 0:54f5be781526 533 state->mode = BAD;
jonathonfletcher 0:54f5be781526 534 break;
jonathonfletcher 0:54f5be781526 535 }
jonathonfletcher 0:54f5be781526 536
jonathonfletcher 0:54f5be781526 537 /* length code -- get extra bits, if any */
jonathonfletcher 0:54f5be781526 538 state->extra = (unsigned)(here.op) & 15;
jonathonfletcher 0:54f5be781526 539 if (state->extra != 0) {
jonathonfletcher 0:54f5be781526 540 NEEDBITS(state->extra);
jonathonfletcher 0:54f5be781526 541 state->length += BITS(state->extra);
jonathonfletcher 0:54f5be781526 542 DROPBITS(state->extra);
jonathonfletcher 0:54f5be781526 543 }
jonathonfletcher 0:54f5be781526 544 Tracevv((stderr, "inflate: length %u\n", state->length));
jonathonfletcher 0:54f5be781526 545
jonathonfletcher 0:54f5be781526 546 /* get distance code */
jonathonfletcher 0:54f5be781526 547 for (;;) {
jonathonfletcher 0:54f5be781526 548 here = state->distcode[BITS(state->distbits)];
jonathonfletcher 0:54f5be781526 549 if ((unsigned)(here.bits) <= bits) break;
jonathonfletcher 0:54f5be781526 550 PULLBYTE();
jonathonfletcher 0:54f5be781526 551 }
jonathonfletcher 0:54f5be781526 552 if ((here.op & 0xf0) == 0) {
jonathonfletcher 0:54f5be781526 553 last = here;
jonathonfletcher 0:54f5be781526 554 for (;;) {
jonathonfletcher 0:54f5be781526 555 here = state->distcode[last.val +
jonathonfletcher 0:54f5be781526 556 (BITS(last.bits + last.op) >> last.bits)];
jonathonfletcher 0:54f5be781526 557 if ((unsigned)(last.bits + here.bits) <= bits) break;
jonathonfletcher 0:54f5be781526 558 PULLBYTE();
jonathonfletcher 0:54f5be781526 559 }
jonathonfletcher 0:54f5be781526 560 DROPBITS(last.bits);
jonathonfletcher 0:54f5be781526 561 }
jonathonfletcher 0:54f5be781526 562 DROPBITS(here.bits);
jonathonfletcher 0:54f5be781526 563 if (here.op & 64) {
jonathonfletcher 0:54f5be781526 564 strm->msg = (char *)"invalid distance code";
jonathonfletcher 0:54f5be781526 565 state->mode = BAD;
jonathonfletcher 0:54f5be781526 566 break;
jonathonfletcher 0:54f5be781526 567 }
jonathonfletcher 0:54f5be781526 568 state->offset = (unsigned)here.val;
jonathonfletcher 0:54f5be781526 569
jonathonfletcher 0:54f5be781526 570 /* get distance extra bits, if any */
jonathonfletcher 0:54f5be781526 571 state->extra = (unsigned)(here.op) & 15;
jonathonfletcher 0:54f5be781526 572 if (state->extra != 0) {
jonathonfletcher 0:54f5be781526 573 NEEDBITS(state->extra);
jonathonfletcher 0:54f5be781526 574 state->offset += BITS(state->extra);
jonathonfletcher 0:54f5be781526 575 DROPBITS(state->extra);
jonathonfletcher 0:54f5be781526 576 }
jonathonfletcher 0:54f5be781526 577 if (state->offset > state->wsize - (state->whave < state->wsize ?
jonathonfletcher 0:54f5be781526 578 left : 0)) {
jonathonfletcher 0:54f5be781526 579 strm->msg = (char *)"invalid distance too far back";
jonathonfletcher 0:54f5be781526 580 state->mode = BAD;
jonathonfletcher 0:54f5be781526 581 break;
jonathonfletcher 0:54f5be781526 582 }
jonathonfletcher 0:54f5be781526 583 Tracevv((stderr, "inflate: distance %u\n", state->offset));
jonathonfletcher 0:54f5be781526 584
jonathonfletcher 0:54f5be781526 585 /* copy match from window to output */
jonathonfletcher 0:54f5be781526 586 do {
jonathonfletcher 0:54f5be781526 587 ROOM();
jonathonfletcher 0:54f5be781526 588 copy = state->wsize - state->offset;
jonathonfletcher 0:54f5be781526 589 if (copy < left) {
jonathonfletcher 0:54f5be781526 590 from = put + copy;
jonathonfletcher 0:54f5be781526 591 copy = left - copy;
jonathonfletcher 0:54f5be781526 592 }
jonathonfletcher 0:54f5be781526 593 else {
jonathonfletcher 0:54f5be781526 594 from = put - state->offset;
jonathonfletcher 0:54f5be781526 595 copy = left;
jonathonfletcher 0:54f5be781526 596 }
jonathonfletcher 0:54f5be781526 597 if (copy > state->length) copy = state->length;
jonathonfletcher 0:54f5be781526 598 state->length -= copy;
jonathonfletcher 0:54f5be781526 599 left -= copy;
jonathonfletcher 0:54f5be781526 600 do {
jonathonfletcher 0:54f5be781526 601 *put++ = *from++;
jonathonfletcher 0:54f5be781526 602 } while (--copy);
jonathonfletcher 0:54f5be781526 603 } while (state->length != 0);
jonathonfletcher 0:54f5be781526 604 break;
jonathonfletcher 0:54f5be781526 605
jonathonfletcher 0:54f5be781526 606 case DONE:
jonathonfletcher 0:54f5be781526 607 /* inflate stream terminated properly -- write leftover output */
jonathonfletcher 0:54f5be781526 608 ret = Z_STREAM_END;
jonathonfletcher 0:54f5be781526 609 if (left < state->wsize) {
jonathonfletcher 0:54f5be781526 610 if (out(out_desc, state->window, state->wsize - left))
jonathonfletcher 0:54f5be781526 611 ret = Z_BUF_ERROR;
jonathonfletcher 0:54f5be781526 612 }
jonathonfletcher 0:54f5be781526 613 goto inf_leave;
jonathonfletcher 0:54f5be781526 614
jonathonfletcher 0:54f5be781526 615 case BAD:
jonathonfletcher 0:54f5be781526 616 ret = Z_DATA_ERROR;
jonathonfletcher 0:54f5be781526 617 goto inf_leave;
jonathonfletcher 0:54f5be781526 618
jonathonfletcher 0:54f5be781526 619 default: /* can't happen, but makes compilers happy */
jonathonfletcher 0:54f5be781526 620 ret = Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 621 goto inf_leave;
jonathonfletcher 0:54f5be781526 622 }
jonathonfletcher 0:54f5be781526 623
jonathonfletcher 0:54f5be781526 624 /* Return unused input */
jonathonfletcher 0:54f5be781526 625 inf_leave:
jonathonfletcher 0:54f5be781526 626 strm->next_in = next;
jonathonfletcher 0:54f5be781526 627 strm->avail_in = have;
jonathonfletcher 0:54f5be781526 628 return ret;
jonathonfletcher 0:54f5be781526 629 }
jonathonfletcher 0:54f5be781526 630
jonathonfletcher 0:54f5be781526 631 int ZEXPORT inflateBackEnd(strm)
jonathonfletcher 0:54f5be781526 632 z_streamp strm;
jonathonfletcher 0:54f5be781526 633 {
jonathonfletcher 0:54f5be781526 634 if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
jonathonfletcher 0:54f5be781526 635 return Z_STREAM_ERROR;
jonathonfletcher 0:54f5be781526 636 ZFREE(strm, strm->state);
jonathonfletcher 0:54f5be781526 637 strm->state = Z_NULL;
jonathonfletcher 0:54f5be781526 638 Tracev((stderr, "inflate: end\n"));
jonathonfletcher 0:54f5be781526 639 return Z_OK;
jonathonfletcher 0:54f5be781526 640 }