annotate src/zlib-1.2.8/inffast.c @ 83:ae30d91d2ffe

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