dbf-halloween2015
diff libs/zlib/inffast.c @ 1:c3f5c32cb210
barfed all the libraries in the source tree to make porting easier
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 01 Nov 2015 00:36:56 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/zlib/inffast.c Sun Nov 01 00:36:56 2015 +0200 1.3 @@ -0,0 +1,318 @@ 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 */