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