1
2
3
4
5
6
7
8
9
10
11
12
13#ifndef ASMINF
14
15
16
17
18
19
20
21
22
23
24
25
26#ifdef POSTINC
27# define OFF 0
28# define PUP(a) *(a)++
29#else
30# define OFF 1
31# define PUP(a) *++(a)
32#endif
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69void inflate_fast(z_streamp strm, unsigned start)
70
71{
72 struct inflate_state FAR *state;
73 unsigned char FAR *in;
74 unsigned char FAR *last;
75 unsigned char FAR *out;
76 unsigned char FAR *beg;
77 unsigned char FAR *end;
78#ifdef INFLATE_STRICT
79 unsigned dmax;
80#endif
81 unsigned wsize;
82 unsigned whave;
83 unsigned write;
84 unsigned char FAR *window;
85 unsigned long hold;
86 unsigned bits;
87 code const FAR *lcode;
88 code const FAR *dcode;
89 unsigned lmask;
90 unsigned dmask;
91 code this;
92 unsigned op;
93
94 unsigned len;
95 unsigned dist;
96 unsigned char FAR *from;
97
98
99 state = (struct inflate_state FAR *)strm->state;
100 in = strm->next_in - OFF;
101 last = in + (strm->avail_in - 5);
102 if (in > last && strm->avail_in > 5) {
103
104
105
106
107 strm->avail_in = 0xffffffff - (uintptr_t)in;
108 last = in + (strm->avail_in - 5);
109 }
110 out = strm->next_out - OFF;
111 beg = out - (start - strm->avail_out);
112 end = out + (strm->avail_out - 257);
113#ifdef INFLATE_STRICT
114 dmax = state->dmax;
115#endif
116 wsize = state->wsize;
117 whave = state->whave;
118 write = state->write;
119 window = state->window;
120 hold = state->hold;
121 bits = state->bits;
122 lcode = state->lencode;
123 dcode = state->distcode;
124 lmask = (1U << state->lenbits) - 1;
125 dmask = (1U << state->distbits) - 1;
126
127
128
129 do {
130 if (bits < 15) {
131 hold += (unsigned long)(PUP(in)) << bits;
132 bits += 8;
133 hold += (unsigned long)(PUP(in)) << bits;
134 bits += 8;
135 }
136 this = lcode[hold & lmask];
137 dolen:
138 op = (unsigned)(this.bits);
139 hold >>= op;
140 bits -= op;
141 op = (unsigned)(this.op);
142 if (op == 0) {
143 Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
144 "inflate: literal '%c'\n" :
145 "inflate: literal 0x%02x\n", this.val));
146 PUP(out) = (unsigned char)(this.val);
147 }
148 else if (op & 16) {
149 len = (unsigned)(this.val);
150 op &= 15;
151 if (op) {
152 if (bits < op) {
153 hold += (unsigned long)(PUP(in)) << bits;
154 bits += 8;
155 }
156 len += (unsigned)hold & ((1U << op) - 1);
157 hold >>= op;
158 bits -= op;
159 }
160 Tracevv((stderr, "inflate: length %u\n", len));
161 if (bits < 15) {
162 hold += (unsigned long)(PUP(in)) << bits;
163 bits += 8;
164 hold += (unsigned long)(PUP(in)) << bits;
165 bits += 8;
166 }
167 this = dcode[hold & dmask];
168 dodist:
169 op = (unsigned)(this.bits);
170 hold >>= op;
171 bits -= op;
172 op = (unsigned)(this.op);
173 if (op & 16) {
174 dist = (unsigned)(this.val);
175 op &= 15;
176 if (bits < op) {
177 hold += (unsigned long)(PUP(in)) << bits;
178 bits += 8;
179 if (bits < op) {
180 hold += (unsigned long)(PUP(in)) << bits;
181 bits += 8;
182 }
183 }
184 dist += (unsigned)hold & ((1U << op) - 1);
185#ifdef INFLATE_STRICT
186 if (dist > dmax) {
187 strm->msg = (char *)"invalid distance too far back";
188 state->mode = BAD;
189 break;
190 }
191#endif
192 hold >>= op;
193 bits -= op;
194 Tracevv((stderr, "inflate: distance %u\n", dist));
195 op = (unsigned)(out - beg);
196 if (dist > op) {
197 op = dist - op;
198 if (op > whave) {
199 strm->msg = (char *)"invalid distance too far back";
200 state->mode = BAD;
201 break;
202 }
203 from = window - OFF;
204 if (write == 0) {
205 from += wsize - op;
206 if (op < len) {
207 len -= op;
208 do {
209 PUP(out) = PUP(from);
210 } while (--op);
211 from = out - dist;
212 }
213 }
214 else if (write < op) {
215 from += wsize + write - op;
216 op -= write;
217 if (op < len) {
218 len -= op;
219 do {
220 PUP(out) = PUP(from);
221 } while (--op);
222 from = window - OFF;
223 if (write < len) {
224 op = write;
225 len -= op;
226 do {
227 PUP(out) = PUP(from);
228 } while (--op);
229 from = out - dist;
230 }
231 }
232 }
233 else {
234 from += write - op;
235 if (op < len) {
236 len -= op;
237 do {
238 PUP(out) = PUP(from);
239 } while (--op);
240 from = out - dist;
241 }
242 }
243 while (len > 2) {
244 PUP(out) = PUP(from);
245 PUP(out) = PUP(from);
246 PUP(out) = PUP(from);
247 len -= 3;
248 }
249 if (len) {
250 PUP(out) = PUP(from);
251 if (len > 1)
252 PUP(out) = PUP(from);
253 }
254 }
255 else {
256 unsigned short *sout;
257 unsigned long loops;
258
259 from = out - dist;
260
261
262 if (!((long)(out - 1 + OFF) & 1)) {
263 PUP(out) = PUP(from);
264 len--;
265 }
266 sout = (unsigned short *)(out - OFF);
267 if (dist > 2 ) {
268 unsigned short *sfrom;
269
270 sfrom = (unsigned short *)(from - OFF);
271 loops = len >> 1;
272 do
273 PUP(sout) = get_unaligned(++sfrom);
274 while (--loops);
275 out = (unsigned char *)sout + OFF;
276 from = (unsigned char *)sfrom + OFF;
277 } else {
278 unsigned short pat16;
279
280 pat16 = *(sout-2+2*OFF);
281 if (dist == 1)
282#if defined(__BIG_ENDIAN)
283 pat16 = (pat16 & 0xff) | ((pat16 & 0xff ) << 8);
284#elif defined(__LITTLE_ENDIAN)
285 pat16 = (pat16 & 0xff00) | ((pat16 & 0xff00 ) >> 8);
286#else
287#error __BIG_ENDIAN nor __LITTLE_ENDIAN is defined
288#endif
289 loops = len >> 1;
290 do
291 PUP(sout) = pat16;
292 while (--loops);
293 out = (unsigned char *)sout + OFF;
294 }
295 if (len & 1)
296 PUP(out) = PUP(from);
297 }
298 }
299 else if ((op & 64) == 0) {
300 this = dcode[this.val + (hold & ((1U << op) - 1))];
301 goto dodist;
302 }
303 else {
304 strm->msg = (char *)"invalid distance code";
305 state->mode = BAD;
306 break;
307 }
308 }
309 else if ((op & 64) == 0) {
310 this = lcode[this.val + (hold & ((1U << op) - 1))];
311 goto dolen;
312 }
313 else if (op & 32) {
314 Tracevv((stderr, "inflate: end of block\n"));
315 state->mode = TYPE;
316 break;
317 }
318 else {
319 strm->msg = (char *)"invalid literal/length code";
320 state->mode = BAD;
321 break;
322 }
323 } while (in < last && out < end);
324
325
326 len = bits >> 3;
327 in -= len;
328 bits -= len << 3;
329 hold &= (1U << bits) - 1;
330
331
332 strm->next_in = in + OFF;
333 strm->next_out = out + OFF;
334 strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
335 strm->avail_out = (unsigned)(out < end ?
336 257 + (end - out) : 257 - (out - end));
337 state->hold = hold;
338 state->bits = bits;
339 return;
340}
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356#endif
357