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