sourcepawn/compiler/zlib/inffast.c
branchsourcemod-1.1.0
changeset 2283 03a67e41afbc
parent 1951 c7b4237fff50
child 2287 017a725c9d17
     1.1 --- a/sourcepawn/compiler/zlib/inffast.c	Fri Mar 28 06:21:34 2008 +0000
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,318 +0,0 @@
     1.4 -/* inffast.c -- fast decoding
     1.5 - * Copyright (C) 1995-2004 Mark Adler
     1.6 - * For conditions of distribution and use, see copyright notice in zlib.h
     1.7 - */
     1.8 -
     1.9 -#include "zutil.h"
    1.10 -#include "inftrees.h"
    1.11 -#include "inflate.h"
    1.12 -#include "inffast.h"
    1.13 -
    1.14 -#ifndef ASMINF
    1.15 -
    1.16 -/* Allow machine dependent optimization for post-increment or pre-increment.
    1.17 -   Based on testing to date,
    1.18 -   Pre-increment preferred for:
    1.19 -   - PowerPC G3 (Adler)
    1.20 -   - MIPS R5000 (Randers-Pehrson)
    1.21 -   Post-increment preferred for:
    1.22 -   - none
    1.23 -   No measurable difference:
    1.24 -   - Pentium III (Anderson)
    1.25 -   - M68060 (Nikl)
    1.26 - */
    1.27 -#ifdef POSTINC
    1.28 -#  define OFF 0
    1.29 -#  define PUP(a) *(a)++
    1.30 -#else
    1.31 -#  define OFF 1
    1.32 -#  define PUP(a) *++(a)
    1.33 -#endif
    1.34 -
    1.35 -/*
    1.36 -   Decode literal, length, and distance codes and write out the resulting
    1.37 -   literal and match bytes until either not enough input or output is
    1.38 -   available, an end-of-block is encountered, or a data error is encountered.
    1.39 -   When large enough input and output buffers are supplied to inflate(), for
    1.40 -   example, a 16K input buffer and a 64K output buffer, more than 95% of the
    1.41 -   inflate execution time is spent in this routine.
    1.42 -
    1.43 -   Entry assumptions:
    1.44 -
    1.45 -        state->mode == LEN
    1.46 -        strm->avail_in >= 6
    1.47 -        strm->avail_out >= 258
    1.48 -        start >= strm->avail_out
    1.49 -        state->bits < 8
    1.50 -
    1.51 -   On return, state->mode is one of:
    1.52 -
    1.53 -        LEN -- ran out of enough output space or enough available input
    1.54 -        TYPE -- reached end of block code, inflate() to interpret next block
    1.55 -        BAD -- error in block data
    1.56 -
    1.57 -   Notes:
    1.58 -
    1.59 -    - The maximum input bits used by a length/distance pair is 15 bits for the
    1.60 -      length code, 5 bits for the length extra, 15 bits for the distance code,
    1.61 -      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
    1.62 -      Therefore if strm->avail_in >= 6, then there is enough input to avoid
    1.63 -      checking for available input while decoding.
    1.64 -
    1.65 -    - The maximum bytes that a single length/distance pair can output is 258
    1.66 -      bytes, which is the maximum length that can be coded.  inflate_fast()
    1.67 -      requires strm->avail_out >= 258 for each loop to avoid checking for
    1.68 -      output space.
    1.69 - */
    1.70 -void inflate_fast(strm, start)
    1.71 -z_streamp strm;
    1.72 -unsigned start;         /* inflate()'s starting value for strm->avail_out */
    1.73 -{
    1.74 -    struct inflate_state FAR *state;
    1.75 -    unsigned char FAR *in;      /* local strm->next_in */
    1.76 -    unsigned char FAR *last;    /* while in < last, enough input available */
    1.77 -    unsigned char FAR *out;     /* local strm->next_out */
    1.78 -    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
    1.79 -    unsigned char FAR *end;     /* while out < end, enough space available */
    1.80 -#ifdef INFLATE_STRICT
    1.81 -    unsigned dmax;              /* maximum distance from zlib header */
    1.82 -#endif
    1.83 -    unsigned wsize;             /* window size or zero if not using window */
    1.84 -    unsigned whave;             /* valid bytes in the window */
    1.85 -    unsigned write;             /* window write index */
    1.86 -    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
    1.87 -    unsigned long hold;         /* local strm->hold */
    1.88 -    unsigned bits;              /* local strm->bits */
    1.89 -    code const FAR *lcode;      /* local strm->lencode */
    1.90 -    code const FAR *dcode;      /* local strm->distcode */
    1.91 -    unsigned lmask;             /* mask for first level of length codes */
    1.92 -    unsigned dmask;             /* mask for first level of distance codes */
    1.93 -    code this;                  /* retrieved table entry */
    1.94 -    unsigned op;                /* code bits, operation, extra bits, or */
    1.95 -                                /*  window position, window bytes to copy */
    1.96 -    unsigned len;               /* match length, unused bytes */
    1.97 -    unsigned dist;              /* match distance */
    1.98 -    unsigned char FAR *from;    /* where to copy match from */
    1.99 -
   1.100 -    /* copy state to local variables */
   1.101 -    state = (struct inflate_state FAR *)strm->state;
   1.102 -    in = strm->next_in - OFF;
   1.103 -    last = in + (strm->avail_in - 5);
   1.104 -    out = strm->next_out - OFF;
   1.105 -    beg = out - (start - strm->avail_out);
   1.106 -    end = out + (strm->avail_out - 257);
   1.107 -#ifdef INFLATE_STRICT
   1.108 -    dmax = state->dmax;
   1.109 -#endif
   1.110 -    wsize = state->wsize;
   1.111 -    whave = state->whave;
   1.112 -    write = state->write;
   1.113 -    window = state->window;
   1.114 -    hold = state->hold;
   1.115 -    bits = state->bits;
   1.116 -    lcode = state->lencode;
   1.117 -    dcode = state->distcode;
   1.118 -    lmask = (1U << state->lenbits) - 1;
   1.119 -    dmask = (1U << state->distbits) - 1;
   1.120 -
   1.121 -    /* decode literals and length/distances until end-of-block or not enough
   1.122 -       input data or output space */
   1.123 -    do {
   1.124 -        if (bits < 15) {
   1.125 -            hold += (unsigned long)(PUP(in)) << bits;
   1.126 -            bits += 8;
   1.127 -            hold += (unsigned long)(PUP(in)) << bits;
   1.128 -            bits += 8;
   1.129 -        }
   1.130 -        this = lcode[hold & lmask];
   1.131 -      dolen:
   1.132 -        op = (unsigned)(this.bits);
   1.133 -        hold >>= op;
   1.134 -        bits -= op;
   1.135 -        op = (unsigned)(this.op);
   1.136 -        if (op == 0) {                          /* literal */
   1.137 -            Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
   1.138 -                    "inflate:         literal '%c'\n" :
   1.139 -                    "inflate:         literal 0x%02x\n", this.val));
   1.140 -            PUP(out) = (unsigned char)(this.val);
   1.141 -        }
   1.142 -        else if (op & 16) {                     /* length base */
   1.143 -            len = (unsigned)(this.val);
   1.144 -            op &= 15;                           /* number of extra bits */
   1.145 -            if (op) {
   1.146 -                if (bits < op) {
   1.147 -                    hold += (unsigned long)(PUP(in)) << bits;
   1.148 -                    bits += 8;
   1.149 -                }
   1.150 -                len += (unsigned)hold & ((1U << op) - 1);
   1.151 -                hold >>= op;
   1.152 -                bits -= op;
   1.153 -            }
   1.154 -            Tracevv((stderr, "inflate:         length %u\n", len));
   1.155 -            if (bits < 15) {
   1.156 -                hold += (unsigned long)(PUP(in)) << bits;
   1.157 -                bits += 8;
   1.158 -                hold += (unsigned long)(PUP(in)) << bits;
   1.159 -                bits += 8;
   1.160 -            }
   1.161 -            this = dcode[hold & dmask];
   1.162 -          dodist:
   1.163 -            op = (unsigned)(this.bits);
   1.164 -            hold >>= op;
   1.165 -            bits -= op;
   1.166 -            op = (unsigned)(this.op);
   1.167 -            if (op & 16) {                      /* distance base */
   1.168 -                dist = (unsigned)(this.val);
   1.169 -                op &= 15;                       /* number of extra bits */
   1.170 -                if (bits < op) {
   1.171 -                    hold += (unsigned long)(PUP(in)) << bits;
   1.172 -                    bits += 8;
   1.173 -                    if (bits < op) {
   1.174 -                        hold += (unsigned long)(PUP(in)) << bits;
   1.175 -                        bits += 8;
   1.176 -                    }
   1.177 -                }
   1.178 -                dist += (unsigned)hold & ((1U << op) - 1);
   1.179 -#ifdef INFLATE_STRICT
   1.180 -                if (dist > dmax) {
   1.181 -                    strm->msg = (char *)"invalid distance too far back";
   1.182 -                    state->mode = BAD;
   1.183 -                    break;
   1.184 -                }
   1.185 -#endif
   1.186 -                hold >>= op;
   1.187 -                bits -= op;
   1.188 -                Tracevv((stderr, "inflate:         distance %u\n", dist));
   1.189 -                op = (unsigned)(out - beg);     /* max distance in output */
   1.190 -                if (dist > op) {                /* see if copy from window */
   1.191 -                    op = dist - op;             /* distance back in window */
   1.192 -                    if (op > whave) {
   1.193 -                        strm->msg = (char *)"invalid distance too far back";
   1.194 -                        state->mode = BAD;
   1.195 -                        break;
   1.196 -                    }
   1.197 -                    from = window - OFF;
   1.198 -                    if (write == 0) {           /* very common case */
   1.199 -                        from += wsize - op;
   1.200 -                        if (op < len) {         /* some from window */
   1.201 -                            len -= op;
   1.202 -                            do {
   1.203 -                                PUP(out) = PUP(from);
   1.204 -                            } while (--op);
   1.205 -                            from = out - dist;  /* rest from output */
   1.206 -                        }
   1.207 -                    }
   1.208 -                    else if (write < op) {      /* wrap around window */
   1.209 -                        from += wsize + write - op;
   1.210 -                        op -= write;
   1.211 -                        if (op < len) {         /* some from end of window */
   1.212 -                            len -= op;
   1.213 -                            do {
   1.214 -                                PUP(out) = PUP(from);
   1.215 -                            } while (--op);
   1.216 -                            from = window - OFF;
   1.217 -                            if (write < len) {  /* some from start of window */
   1.218 -                                op = write;
   1.219 -                                len -= op;
   1.220 -                                do {
   1.221 -                                    PUP(out) = PUP(from);
   1.222 -                                } while (--op);
   1.223 -                                from = out - dist;      /* rest from output */
   1.224 -                            }
   1.225 -                        }
   1.226 -                    }
   1.227 -                    else {                      /* contiguous in window */
   1.228 -                        from += write - op;
   1.229 -                        if (op < len) {         /* some from window */
   1.230 -                            len -= op;
   1.231 -                            do {
   1.232 -                                PUP(out) = PUP(from);
   1.233 -                            } while (--op);
   1.234 -                            from = out - dist;  /* rest from output */
   1.235 -                        }
   1.236 -                    }
   1.237 -                    while (len > 2) {
   1.238 -                        PUP(out) = PUP(from);
   1.239 -                        PUP(out) = PUP(from);
   1.240 -                        PUP(out) = PUP(from);
   1.241 -                        len -= 3;
   1.242 -                    }
   1.243 -                    if (len) {
   1.244 -                        PUP(out) = PUP(from);
   1.245 -                        if (len > 1)
   1.246 -                            PUP(out) = PUP(from);
   1.247 -                    }
   1.248 -                }
   1.249 -                else {
   1.250 -                    from = out - dist;          /* copy direct from output */
   1.251 -                    do {                        /* minimum length is three */
   1.252 -                        PUP(out) = PUP(from);
   1.253 -                        PUP(out) = PUP(from);
   1.254 -                        PUP(out) = PUP(from);
   1.255 -                        len -= 3;
   1.256 -                    } while (len > 2);
   1.257 -                    if (len) {
   1.258 -                        PUP(out) = PUP(from);
   1.259 -                        if (len > 1)
   1.260 -                            PUP(out) = PUP(from);
   1.261 -                    }
   1.262 -                }
   1.263 -            }
   1.264 -            else if ((op & 64) == 0) {          /* 2nd level distance code */
   1.265 -                this = dcode[this.val + (hold & ((1U << op) - 1))];
   1.266 -                goto dodist;
   1.267 -            }
   1.268 -            else {
   1.269 -                strm->msg = (char *)"invalid distance code";
   1.270 -                state->mode = BAD;
   1.271 -                break;
   1.272 -            }
   1.273 -        }
   1.274 -        else if ((op & 64) == 0) {              /* 2nd level length code */
   1.275 -            this = lcode[this.val + (hold & ((1U << op) - 1))];
   1.276 -            goto dolen;
   1.277 -        }
   1.278 -        else if (op & 32) {                     /* end-of-block */
   1.279 -            Tracevv((stderr, "inflate:         end of block\n"));
   1.280 -            state->mode = TYPE;
   1.281 -            break;
   1.282 -        }
   1.283 -        else {
   1.284 -            strm->msg = (char *)"invalid literal/length code";
   1.285 -            state->mode = BAD;
   1.286 -            break;
   1.287 -        }
   1.288 -    } while (in < last && out < end);
   1.289 -
   1.290 -    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
   1.291 -    len = bits >> 3;
   1.292 -    in -= len;
   1.293 -    bits -= len << 3;
   1.294 -    hold &= (1U << bits) - 1;
   1.295 -
   1.296 -    /* update state and return */
   1.297 -    strm->next_in = in + OFF;
   1.298 -    strm->next_out = out + OFF;
   1.299 -    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
   1.300 -    strm->avail_out = (unsigned)(out < end ?
   1.301 -                                 257 + (end - out) : 257 - (out - end));
   1.302 -    state->hold = hold;
   1.303 -    state->bits = bits;
   1.304 -    return;
   1.305 -}
   1.306 -
   1.307 -/*
   1.308 -   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
   1.309 -   - Using bit fields for code structure
   1.310 -   - Different op definition to avoid & for extra bits (do & for table bits)
   1.311 -   - Three separate decoding do-loops for direct, window, and write == 0
   1.312 -   - Special case for distance > 1 copies to do overlapped load and store copy
   1.313 -   - Explicit branch predictions (based on measured branch probabilities)
   1.314 -   - Deferring match copy and interspersed it with decoding subsequent codes
   1.315 -   - Swapping literal/length else
   1.316 -   - Swapping window/direct else
   1.317 -   - Larger unrolled copy loops (three is about right)
   1.318 -   - Moving len -= 3 statement into middle of loop
   1.319 - */
   1.320 -
   1.321 -#endif /* !ASMINF */