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 /* inffast.c -- fast decoding
jonathonfletcher 0:54f5be781526 2 * Copyright (C) 1995-2008, 2010 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 #include "zutil.h"
jonathonfletcher 0:54f5be781526 7 #include "inftrees.h"
jonathonfletcher 0:54f5be781526 8 #include "inflate.h"
jonathonfletcher 0:54f5be781526 9 #include "inffast.h"
jonathonfletcher 0:54f5be781526 10
jonathonfletcher 0:54f5be781526 11 #ifndef ASMINF
jonathonfletcher 0:54f5be781526 12
jonathonfletcher 0:54f5be781526 13 /* Allow machine dependent optimization for post-increment or pre-increment.
jonathonfletcher 0:54f5be781526 14 Based on testing to date,
jonathonfletcher 0:54f5be781526 15 Pre-increment preferred for:
jonathonfletcher 0:54f5be781526 16 - PowerPC G3 (Adler)
jonathonfletcher 0:54f5be781526 17 - MIPS R5000 (Randers-Pehrson)
jonathonfletcher 0:54f5be781526 18 Post-increment preferred for:
jonathonfletcher 0:54f5be781526 19 - none
jonathonfletcher 0:54f5be781526 20 No measurable difference:
jonathonfletcher 0:54f5be781526 21 - Pentium III (Anderson)
jonathonfletcher 0:54f5be781526 22 - M68060 (Nikl)
jonathonfletcher 0:54f5be781526 23 */
jonathonfletcher 0:54f5be781526 24 #ifdef POSTINC
jonathonfletcher 0:54f5be781526 25 # define OFF 0
jonathonfletcher 0:54f5be781526 26 # define PUP(a) *(a)++
jonathonfletcher 0:54f5be781526 27 #else
jonathonfletcher 0:54f5be781526 28 # define OFF 1
jonathonfletcher 0:54f5be781526 29 # define PUP(a) *++(a)
jonathonfletcher 0:54f5be781526 30 #endif
jonathonfletcher 0:54f5be781526 31
jonathonfletcher 0:54f5be781526 32 /*
jonathonfletcher 0:54f5be781526 33 Decode literal, length, and distance codes and write out the resulting
jonathonfletcher 0:54f5be781526 34 literal and match bytes until either not enough input or output is
jonathonfletcher 0:54f5be781526 35 available, an end-of-block is encountered, or a data error is encountered.
jonathonfletcher 0:54f5be781526 36 When large enough input and output buffers are supplied to inflate(), for
jonathonfletcher 0:54f5be781526 37 example, a 16K input buffer and a 64K output buffer, more than 95% of the
jonathonfletcher 0:54f5be781526 38 inflate execution time is spent in this routine.
jonathonfletcher 0:54f5be781526 39
jonathonfletcher 0:54f5be781526 40 Entry assumptions:
jonathonfletcher 0:54f5be781526 41
jonathonfletcher 0:54f5be781526 42 state->mode == LEN
jonathonfletcher 0:54f5be781526 43 strm->avail_in >= 6
jonathonfletcher 0:54f5be781526 44 strm->avail_out >= 258
jonathonfletcher 0:54f5be781526 45 start >= strm->avail_out
jonathonfletcher 0:54f5be781526 46 state->bits < 8
jonathonfletcher 0:54f5be781526 47
jonathonfletcher 0:54f5be781526 48 On return, state->mode is one of:
jonathonfletcher 0:54f5be781526 49
jonathonfletcher 0:54f5be781526 50 LEN -- ran out of enough output space or enough available input
jonathonfletcher 0:54f5be781526 51 TYPE -- reached end of block code, inflate() to interpret next block
jonathonfletcher 0:54f5be781526 52 BAD -- error in block data
jonathonfletcher 0:54f5be781526 53
jonathonfletcher 0:54f5be781526 54 Notes:
jonathonfletcher 0:54f5be781526 55
jonathonfletcher 0:54f5be781526 56 - The maximum input bits used by a length/distance pair is 15 bits for the
jonathonfletcher 0:54f5be781526 57 length code, 5 bits for the length extra, 15 bits for the distance code,
jonathonfletcher 0:54f5be781526 58 and 13 bits for the distance extra. This totals 48 bits, or six bytes.
jonathonfletcher 0:54f5be781526 59 Therefore if strm->avail_in >= 6, then there is enough input to avoid
jonathonfletcher 0:54f5be781526 60 checking for available input while decoding.
jonathonfletcher 0:54f5be781526 61
jonathonfletcher 0:54f5be781526 62 - The maximum bytes that a single length/distance pair can output is 258
jonathonfletcher 0:54f5be781526 63 bytes, which is the maximum length that can be coded. inflate_fast()
jonathonfletcher 0:54f5be781526 64 requires strm->avail_out >= 258 for each loop to avoid checking for
jonathonfletcher 0:54f5be781526 65 output space.
jonathonfletcher 0:54f5be781526 66 */
jonathonfletcher 0:54f5be781526 67 void ZLIB_INTERNAL inflate_fast(strm, start)
jonathonfletcher 0:54f5be781526 68 z_streamp strm;
jonathonfletcher 0:54f5be781526 69 unsigned start; /* inflate()'s starting value for strm->avail_out */
jonathonfletcher 0:54f5be781526 70 {
jonathonfletcher 0:54f5be781526 71 struct inflate_state FAR *state;
jonathonfletcher 0:54f5be781526 72 unsigned char FAR *in; /* local strm->next_in */
jonathonfletcher 0:54f5be781526 73 unsigned char FAR *last; /* while in < last, enough input available */
jonathonfletcher 0:54f5be781526 74 unsigned char FAR *out; /* local strm->next_out */
jonathonfletcher 0:54f5be781526 75 unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
jonathonfletcher 0:54f5be781526 76 unsigned char FAR *end; /* while out < end, enough space available */
jonathonfletcher 0:54f5be781526 77 #ifdef INFLATE_STRICT
jonathonfletcher 0:54f5be781526 78 unsigned dmax; /* maximum distance from zlib header */
jonathonfletcher 0:54f5be781526 79 #endif
jonathonfletcher 0:54f5be781526 80 unsigned wsize; /* window size or zero if not using window */
jonathonfletcher 0:54f5be781526 81 unsigned whave; /* valid bytes in the window */
jonathonfletcher 0:54f5be781526 82 unsigned wnext; /* window write index */
jonathonfletcher 0:54f5be781526 83 unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
jonathonfletcher 0:54f5be781526 84 unsigned long hold; /* local strm->hold */
jonathonfletcher 0:54f5be781526 85 unsigned bits; /* local strm->bits */
jonathonfletcher 0:54f5be781526 86 code const FAR *lcode; /* local strm->lencode */
jonathonfletcher 0:54f5be781526 87 code const FAR *dcode; /* local strm->distcode */
jonathonfletcher 0:54f5be781526 88 unsigned lmask; /* mask for first level of length codes */
jonathonfletcher 0:54f5be781526 89 unsigned dmask; /* mask for first level of distance codes */
jonathonfletcher 0:54f5be781526 90 code here; /* retrieved table entry */
jonathonfletcher 0:54f5be781526 91 unsigned op; /* code bits, operation, extra bits, or */
jonathonfletcher 0:54f5be781526 92 /* window position, window bytes to copy */
jonathonfletcher 0:54f5be781526 93 unsigned len; /* match length, unused bytes */
jonathonfletcher 0:54f5be781526 94 unsigned dist; /* match distance */
jonathonfletcher 0:54f5be781526 95 unsigned char FAR *from; /* where to copy match from */
jonathonfletcher 0:54f5be781526 96
jonathonfletcher 0:54f5be781526 97 /* copy state to local variables */
jonathonfletcher 0:54f5be781526 98 state = (struct inflate_state FAR *)strm->state;
jonathonfletcher 0:54f5be781526 99 in = strm->next_in - OFF;
jonathonfletcher 0:54f5be781526 100 last = in + (strm->avail_in - 5);
jonathonfletcher 0:54f5be781526 101 out = strm->next_out - OFF;
jonathonfletcher 0:54f5be781526 102 beg = out - (start - strm->avail_out);
jonathonfletcher 0:54f5be781526 103 end = out + (strm->avail_out - 257);
jonathonfletcher 0:54f5be781526 104 #ifdef INFLATE_STRICT
jonathonfletcher 0:54f5be781526 105 dmax = state->dmax;
jonathonfletcher 0:54f5be781526 106 #endif
jonathonfletcher 0:54f5be781526 107 wsize = state->wsize;
jonathonfletcher 0:54f5be781526 108 whave = state->whave;
jonathonfletcher 0:54f5be781526 109 wnext = state->wnext;
jonathonfletcher 0:54f5be781526 110 window = state->window;
jonathonfletcher 0:54f5be781526 111 hold = state->hold;
jonathonfletcher 0:54f5be781526 112 bits = state->bits;
jonathonfletcher 0:54f5be781526 113 lcode = state->lencode;
jonathonfletcher 0:54f5be781526 114 dcode = state->distcode;
jonathonfletcher 0:54f5be781526 115 lmask = (1U << state->lenbits) - 1;
jonathonfletcher 0:54f5be781526 116 dmask = (1U << state->distbits) - 1;
jonathonfletcher 0:54f5be781526 117
jonathonfletcher 0:54f5be781526 118 /* decode literals and length/distances until end-of-block or not enough
jonathonfletcher 0:54f5be781526 119 input data or output space */
jonathonfletcher 0:54f5be781526 120 do {
jonathonfletcher 0:54f5be781526 121 if (bits < 15) {
jonathonfletcher 0:54f5be781526 122 hold += (unsigned long)(PUP(in)) << bits;
jonathonfletcher 0:54f5be781526 123 bits += 8;
jonathonfletcher 0:54f5be781526 124 hold += (unsigned long)(PUP(in)) << bits;
jonathonfletcher 0:54f5be781526 125 bits += 8;
jonathonfletcher 0:54f5be781526 126 }
jonathonfletcher 0:54f5be781526 127 here = lcode[hold & lmask];
jonathonfletcher 0:54f5be781526 128 dolen:
jonathonfletcher 0:54f5be781526 129 op = (unsigned)(here.bits);
jonathonfletcher 0:54f5be781526 130 hold >>= op;
jonathonfletcher 0:54f5be781526 131 bits -= op;
jonathonfletcher 0:54f5be781526 132 op = (unsigned)(here.op);
jonathonfletcher 0:54f5be781526 133 if (op == 0) { /* literal */
jonathonfletcher 0:54f5be781526 134 Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
jonathonfletcher 0:54f5be781526 135 "inflate: literal '%c'\n" :
jonathonfletcher 0:54f5be781526 136 "inflate: literal 0x%02x\n", here.val));
jonathonfletcher 0:54f5be781526 137 PUP(out) = (unsigned char)(here.val);
jonathonfletcher 0:54f5be781526 138 }
jonathonfletcher 0:54f5be781526 139 else if (op & 16) { /* length base */
jonathonfletcher 0:54f5be781526 140 len = (unsigned)(here.val);
jonathonfletcher 0:54f5be781526 141 op &= 15; /* number of extra bits */
jonathonfletcher 0:54f5be781526 142 if (op) {
jonathonfletcher 0:54f5be781526 143 if (bits < op) {
jonathonfletcher 0:54f5be781526 144 hold += (unsigned long)(PUP(in)) << bits;
jonathonfletcher 0:54f5be781526 145 bits += 8;
jonathonfletcher 0:54f5be781526 146 }
jonathonfletcher 0:54f5be781526 147 len += (unsigned)hold & ((1U << op) - 1);
jonathonfletcher 0:54f5be781526 148 hold >>= op;
jonathonfletcher 0:54f5be781526 149 bits -= op;
jonathonfletcher 0:54f5be781526 150 }
jonathonfletcher 0:54f5be781526 151 Tracevv((stderr, "inflate: length %u\n", len));
jonathonfletcher 0:54f5be781526 152 if (bits < 15) {
jonathonfletcher 0:54f5be781526 153 hold += (unsigned long)(PUP(in)) << bits;
jonathonfletcher 0:54f5be781526 154 bits += 8;
jonathonfletcher 0:54f5be781526 155 hold += (unsigned long)(PUP(in)) << bits;
jonathonfletcher 0:54f5be781526 156 bits += 8;
jonathonfletcher 0:54f5be781526 157 }
jonathonfletcher 0:54f5be781526 158 here = dcode[hold & dmask];
jonathonfletcher 0:54f5be781526 159 dodist:
jonathonfletcher 0:54f5be781526 160 op = (unsigned)(here.bits);
jonathonfletcher 0:54f5be781526 161 hold >>= op;
jonathonfletcher 0:54f5be781526 162 bits -= op;
jonathonfletcher 0:54f5be781526 163 op = (unsigned)(here.op);
jonathonfletcher 0:54f5be781526 164 if (op & 16) { /* distance base */
jonathonfletcher 0:54f5be781526 165 dist = (unsigned)(here.val);
jonathonfletcher 0:54f5be781526 166 op &= 15; /* number of extra bits */
jonathonfletcher 0:54f5be781526 167 if (bits < op) {
jonathonfletcher 0:54f5be781526 168 hold += (unsigned long)(PUP(in)) << bits;
jonathonfletcher 0:54f5be781526 169 bits += 8;
jonathonfletcher 0:54f5be781526 170 if (bits < op) {
jonathonfletcher 0:54f5be781526 171 hold += (unsigned long)(PUP(in)) << bits;
jonathonfletcher 0:54f5be781526 172 bits += 8;
jonathonfletcher 0:54f5be781526 173 }
jonathonfletcher 0:54f5be781526 174 }
jonathonfletcher 0:54f5be781526 175 dist += (unsigned)hold & ((1U << op) - 1);
jonathonfletcher 0:54f5be781526 176 #ifdef INFLATE_STRICT
jonathonfletcher 0:54f5be781526 177 if (dist > dmax) {
jonathonfletcher 0:54f5be781526 178 strm->msg = (char *)"invalid distance too far back";
jonathonfletcher 0:54f5be781526 179 state->mode = BAD;
jonathonfletcher 0:54f5be781526 180 break;
jonathonfletcher 0:54f5be781526 181 }
jonathonfletcher 0:54f5be781526 182 #endif
jonathonfletcher 0:54f5be781526 183 hold >>= op;
jonathonfletcher 0:54f5be781526 184 bits -= op;
jonathonfletcher 0:54f5be781526 185 Tracevv((stderr, "inflate: distance %u\n", dist));
jonathonfletcher 0:54f5be781526 186 op = (unsigned)(out - beg); /* max distance in output */
jonathonfletcher 0:54f5be781526 187 if (dist > op) { /* see if copy from window */
jonathonfletcher 0:54f5be781526 188 op = dist - op; /* distance back in window */
jonathonfletcher 0:54f5be781526 189 if (op > whave) {
jonathonfletcher 0:54f5be781526 190 if (state->sane) {
jonathonfletcher 0:54f5be781526 191 strm->msg =
jonathonfletcher 0:54f5be781526 192 (char *)"invalid distance too far back";
jonathonfletcher 0:54f5be781526 193 state->mode = BAD;
jonathonfletcher 0:54f5be781526 194 break;
jonathonfletcher 0:54f5be781526 195 }
jonathonfletcher 0:54f5be781526 196 #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
jonathonfletcher 0:54f5be781526 197 if (len <= op - whave) {
jonathonfletcher 0:54f5be781526 198 do {
jonathonfletcher 0:54f5be781526 199 PUP(out) = 0;
jonathonfletcher 0:54f5be781526 200 } while (--len);
jonathonfletcher 0:54f5be781526 201 continue;
jonathonfletcher 0:54f5be781526 202 }
jonathonfletcher 0:54f5be781526 203 len -= op - whave;
jonathonfletcher 0:54f5be781526 204 do {
jonathonfletcher 0:54f5be781526 205 PUP(out) = 0;
jonathonfletcher 0:54f5be781526 206 } while (--op > whave);
jonathonfletcher 0:54f5be781526 207 if (op == 0) {
jonathonfletcher 0:54f5be781526 208 from = out - dist;
jonathonfletcher 0:54f5be781526 209 do {
jonathonfletcher 0:54f5be781526 210 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 211 } while (--len);
jonathonfletcher 0:54f5be781526 212 continue;
jonathonfletcher 0:54f5be781526 213 }
jonathonfletcher 0:54f5be781526 214 #endif
jonathonfletcher 0:54f5be781526 215 }
jonathonfletcher 0:54f5be781526 216 from = window - OFF;
jonathonfletcher 0:54f5be781526 217 if (wnext == 0) { /* very common case */
jonathonfletcher 0:54f5be781526 218 from += wsize - op;
jonathonfletcher 0:54f5be781526 219 if (op < len) { /* some from window */
jonathonfletcher 0:54f5be781526 220 len -= op;
jonathonfletcher 0:54f5be781526 221 do {
jonathonfletcher 0:54f5be781526 222 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 223 } while (--op);
jonathonfletcher 0:54f5be781526 224 from = out - dist; /* rest from output */
jonathonfletcher 0:54f5be781526 225 }
jonathonfletcher 0:54f5be781526 226 }
jonathonfletcher 0:54f5be781526 227 else if (wnext < op) { /* wrap around window */
jonathonfletcher 0:54f5be781526 228 from += wsize + wnext - op;
jonathonfletcher 0:54f5be781526 229 op -= wnext;
jonathonfletcher 0:54f5be781526 230 if (op < len) { /* some from end of window */
jonathonfletcher 0:54f5be781526 231 len -= op;
jonathonfletcher 0:54f5be781526 232 do {
jonathonfletcher 0:54f5be781526 233 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 234 } while (--op);
jonathonfletcher 0:54f5be781526 235 from = window - OFF;
jonathonfletcher 0:54f5be781526 236 if (wnext < len) { /* some from start of window */
jonathonfletcher 0:54f5be781526 237 op = wnext;
jonathonfletcher 0:54f5be781526 238 len -= op;
jonathonfletcher 0:54f5be781526 239 do {
jonathonfletcher 0:54f5be781526 240 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 241 } while (--op);
jonathonfletcher 0:54f5be781526 242 from = out - dist; /* rest from output */
jonathonfletcher 0:54f5be781526 243 }
jonathonfletcher 0:54f5be781526 244 }
jonathonfletcher 0:54f5be781526 245 }
jonathonfletcher 0:54f5be781526 246 else { /* contiguous in window */
jonathonfletcher 0:54f5be781526 247 from += wnext - op;
jonathonfletcher 0:54f5be781526 248 if (op < len) { /* some from window */
jonathonfletcher 0:54f5be781526 249 len -= op;
jonathonfletcher 0:54f5be781526 250 do {
jonathonfletcher 0:54f5be781526 251 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 252 } while (--op);
jonathonfletcher 0:54f5be781526 253 from = out - dist; /* rest from output */
jonathonfletcher 0:54f5be781526 254 }
jonathonfletcher 0:54f5be781526 255 }
jonathonfletcher 0:54f5be781526 256 while (len > 2) {
jonathonfletcher 0:54f5be781526 257 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 258 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 259 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 260 len -= 3;
jonathonfletcher 0:54f5be781526 261 }
jonathonfletcher 0:54f5be781526 262 if (len) {
jonathonfletcher 0:54f5be781526 263 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 264 if (len > 1)
jonathonfletcher 0:54f5be781526 265 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 266 }
jonathonfletcher 0:54f5be781526 267 }
jonathonfletcher 0:54f5be781526 268 else {
jonathonfletcher 0:54f5be781526 269 from = out - dist; /* copy direct from output */
jonathonfletcher 0:54f5be781526 270 do { /* minimum length is three */
jonathonfletcher 0:54f5be781526 271 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 272 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 273 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 274 len -= 3;
jonathonfletcher 0:54f5be781526 275 } while (len > 2);
jonathonfletcher 0:54f5be781526 276 if (len) {
jonathonfletcher 0:54f5be781526 277 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 278 if (len > 1)
jonathonfletcher 0:54f5be781526 279 PUP(out) = PUP(from);
jonathonfletcher 0:54f5be781526 280 }
jonathonfletcher 0:54f5be781526 281 }
jonathonfletcher 0:54f5be781526 282 }
jonathonfletcher 0:54f5be781526 283 else if ((op & 64) == 0) { /* 2nd level distance code */
jonathonfletcher 0:54f5be781526 284 here = dcode[here.val + (hold & ((1U << op) - 1))];
jonathonfletcher 0:54f5be781526 285 goto dodist;
jonathonfletcher 0:54f5be781526 286 }
jonathonfletcher 0:54f5be781526 287 else {
jonathonfletcher 0:54f5be781526 288 strm->msg = (char *)"invalid distance code";
jonathonfletcher 0:54f5be781526 289 state->mode = BAD;
jonathonfletcher 0:54f5be781526 290 break;
jonathonfletcher 0:54f5be781526 291 }
jonathonfletcher 0:54f5be781526 292 }
jonathonfletcher 0:54f5be781526 293 else if ((op & 64) == 0) { /* 2nd level length code */
jonathonfletcher 0:54f5be781526 294 here = lcode[here.val + (hold & ((1U << op) - 1))];
jonathonfletcher 0:54f5be781526 295 goto dolen;
jonathonfletcher 0:54f5be781526 296 }
jonathonfletcher 0:54f5be781526 297 else if (op & 32) { /* end-of-block */
jonathonfletcher 0:54f5be781526 298 Tracevv((stderr, "inflate: end of block\n"));
jonathonfletcher 0:54f5be781526 299 state->mode = TYPE;
jonathonfletcher 0:54f5be781526 300 break;
jonathonfletcher 0:54f5be781526 301 }
jonathonfletcher 0:54f5be781526 302 else {
jonathonfletcher 0:54f5be781526 303 strm->msg = (char *)"invalid literal/length code";
jonathonfletcher 0:54f5be781526 304 state->mode = BAD;
jonathonfletcher 0:54f5be781526 305 break;
jonathonfletcher 0:54f5be781526 306 }
jonathonfletcher 0:54f5be781526 307 } while (in < last && out < end);
jonathonfletcher 0:54f5be781526 308
jonathonfletcher 0:54f5be781526 309 /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
jonathonfletcher 0:54f5be781526 310 len = bits >> 3;
jonathonfletcher 0:54f5be781526 311 in -= len;
jonathonfletcher 0:54f5be781526 312 bits -= len << 3;
jonathonfletcher 0:54f5be781526 313 hold &= (1U << bits) - 1;
jonathonfletcher 0:54f5be781526 314
jonathonfletcher 0:54f5be781526 315 /* update state and return */
jonathonfletcher 0:54f5be781526 316 strm->next_in = in + OFF;
jonathonfletcher 0:54f5be781526 317 strm->next_out = out + OFF;
jonathonfletcher 0:54f5be781526 318 strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
jonathonfletcher 0:54f5be781526 319 strm->avail_out = (unsigned)(out < end ?
jonathonfletcher 0:54f5be781526 320 257 + (end - out) : 257 - (out - end));
jonathonfletcher 0:54f5be781526 321 state->hold = hold;
jonathonfletcher 0:54f5be781526 322 state->bits = bits;
jonathonfletcher 0:54f5be781526 323 return;
jonathonfletcher 0:54f5be781526 324 }
jonathonfletcher 0:54f5be781526 325
jonathonfletcher 0:54f5be781526 326 /*
jonathonfletcher 0:54f5be781526 327 inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
jonathonfletcher 0:54f5be781526 328 - Using bit fields for code structure
jonathonfletcher 0:54f5be781526 329 - Different op definition to avoid & for extra bits (do & for table bits)
jonathonfletcher 0:54f5be781526 330 - Three separate decoding do-loops for direct, window, and wnext == 0
jonathonfletcher 0:54f5be781526 331 - Special case for distance > 1 copies to do overlapped load and store copy
jonathonfletcher 0:54f5be781526 332 - Explicit branch predictions (based on measured branch probabilities)
jonathonfletcher 0:54f5be781526 333 - Deferring match copy and interspersed it with decoding subsequent codes
jonathonfletcher 0:54f5be781526 334 - Swapping literal/length else
jonathonfletcher 0:54f5be781526 335 - Swapping window/direct else
jonathonfletcher 0:54f5be781526 336 - Larger unrolled copy loops (three is about right)
jonathonfletcher 0:54f5be781526 337 - Moving len -= 3 statement into middle of loop
jonathonfletcher 0:54f5be781526 338 */
jonathonfletcher 0:54f5be781526 339
jonathonfletcher 0:54f5be781526 340 #endif /* !ASMINF */