Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80549 views
1
'use strict';
2
3
// See state defs from inflate.js
4
var BAD = 30; /* got a data error -- remain here until reset */
5
var TYPE = 12; /* i: waiting for type bits, including last-flag bit */
6
7
/*
8
Decode literal, length, and distance codes and write out the resulting
9
literal and match bytes until either not enough input or output is
10
available, an end-of-block is encountered, or a data error is encountered.
11
When large enough input and output buffers are supplied to inflate(), for
12
example, a 16K input buffer and a 64K output buffer, more than 95% of the
13
inflate execution time is spent in this routine.
14
15
Entry assumptions:
16
17
state.mode === LEN
18
strm.avail_in >= 6
19
strm.avail_out >= 258
20
start >= strm.avail_out
21
state.bits < 8
22
23
On return, state.mode is one of:
24
25
LEN -- ran out of enough output space or enough available input
26
TYPE -- reached end of block code, inflate() to interpret next block
27
BAD -- error in block data
28
29
Notes:
30
31
- The maximum input bits used by a length/distance pair is 15 bits for the
32
length code, 5 bits for the length extra, 15 bits for the distance code,
33
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
34
Therefore if strm.avail_in >= 6, then there is enough input to avoid
35
checking for available input while decoding.
36
37
- The maximum bytes that a single length/distance pair can output is 258
38
bytes, which is the maximum length that can be coded. inflate_fast()
39
requires strm.avail_out >= 258 for each loop to avoid checking for
40
output space.
41
*/
42
module.exports = function inflate_fast(strm, start) {
43
var state;
44
var _in; /* local strm.input */
45
var last; /* have enough input while in < last */
46
var _out; /* local strm.output */
47
var beg; /* inflate()'s initial strm.output */
48
var end; /* while out < end, enough space available */
49
//#ifdef INFLATE_STRICT
50
var dmax; /* maximum distance from zlib header */
51
//#endif
52
var wsize; /* window size or zero if not using window */
53
var whave; /* valid bytes in the window */
54
var wnext; /* window write index */
55
var window; /* allocated sliding window, if wsize != 0 */
56
var hold; /* local strm.hold */
57
var bits; /* local strm.bits */
58
var lcode; /* local strm.lencode */
59
var dcode; /* local strm.distcode */
60
var lmask; /* mask for first level of length codes */
61
var dmask; /* mask for first level of distance codes */
62
var here; /* retrieved table entry */
63
var op; /* code bits, operation, extra bits, or */
64
/* window position, window bytes to copy */
65
var len; /* match length, unused bytes */
66
var dist; /* match distance */
67
var from; /* where to copy match from */
68
var from_source;
69
70
71
var input, output; // JS specific, because we have no pointers
72
73
/* copy state to local variables */
74
state = strm.state;
75
//here = state.here;
76
_in = strm.next_in;
77
input = strm.input;
78
last = _in + (strm.avail_in - 5);
79
_out = strm.next_out;
80
output = strm.output;
81
beg = _out - (start - strm.avail_out);
82
end = _out + (strm.avail_out - 257);
83
//#ifdef INFLATE_STRICT
84
dmax = state.dmax;
85
//#endif
86
wsize = state.wsize;
87
whave = state.whave;
88
wnext = state.wnext;
89
window = state.window;
90
hold = state.hold;
91
bits = state.bits;
92
lcode = state.lencode;
93
dcode = state.distcode;
94
lmask = (1 << state.lenbits) - 1;
95
dmask = (1 << state.distbits) - 1;
96
97
98
/* decode literals and length/distances until end-of-block or not enough
99
input data or output space */
100
101
top:
102
do {
103
if (bits < 15) {
104
hold += input[_in++] << bits;
105
bits += 8;
106
hold += input[_in++] << bits;
107
bits += 8;
108
}
109
110
here = lcode[hold & lmask];
111
112
dolen:
113
for (;;) { // Goto emulation
114
op = here >>> 24/*here.bits*/;
115
hold >>>= op;
116
bits -= op;
117
op = (here >>> 16) & 0xff/*here.op*/;
118
if (op === 0) { /* literal */
119
//Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
120
// "inflate: literal '%c'\n" :
121
// "inflate: literal 0x%02x\n", here.val));
122
output[_out++] = here & 0xffff/*here.val*/;
123
}
124
else if (op & 16) { /* length base */
125
len = here & 0xffff/*here.val*/;
126
op &= 15; /* number of extra bits */
127
if (op) {
128
if (bits < op) {
129
hold += input[_in++] << bits;
130
bits += 8;
131
}
132
len += hold & ((1 << op) - 1);
133
hold >>>= op;
134
bits -= op;
135
}
136
//Tracevv((stderr, "inflate: length %u\n", len));
137
if (bits < 15) {
138
hold += input[_in++] << bits;
139
bits += 8;
140
hold += input[_in++] << bits;
141
bits += 8;
142
}
143
here = dcode[hold & dmask];
144
145
dodist:
146
for (;;) { // goto emulation
147
op = here >>> 24/*here.bits*/;
148
hold >>>= op;
149
bits -= op;
150
op = (here >>> 16) & 0xff/*here.op*/;
151
152
if (op & 16) { /* distance base */
153
dist = here & 0xffff/*here.val*/;
154
op &= 15; /* number of extra bits */
155
if (bits < op) {
156
hold += input[_in++] << bits;
157
bits += 8;
158
if (bits < op) {
159
hold += input[_in++] << bits;
160
bits += 8;
161
}
162
}
163
dist += hold & ((1 << op) - 1);
164
//#ifdef INFLATE_STRICT
165
if (dist > dmax) {
166
strm.msg = 'invalid distance too far back';
167
state.mode = BAD;
168
break top;
169
}
170
//#endif
171
hold >>>= op;
172
bits -= op;
173
//Tracevv((stderr, "inflate: distance %u\n", dist));
174
op = _out - beg; /* max distance in output */
175
if (dist > op) { /* see if copy from window */
176
op = dist - op; /* distance back in window */
177
if (op > whave) {
178
if (state.sane) {
179
strm.msg = 'invalid distance too far back';
180
state.mode = BAD;
181
break top;
182
}
183
184
// (!) This block is disabled in zlib defailts,
185
// don't enable it for binary compatibility
186
//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
187
// if (len <= op - whave) {
188
// do {
189
// output[_out++] = 0;
190
// } while (--len);
191
// continue top;
192
// }
193
// len -= op - whave;
194
// do {
195
// output[_out++] = 0;
196
// } while (--op > whave);
197
// if (op === 0) {
198
// from = _out - dist;
199
// do {
200
// output[_out++] = output[from++];
201
// } while (--len);
202
// continue top;
203
// }
204
//#endif
205
}
206
from = 0; // window index
207
from_source = window;
208
if (wnext === 0) { /* very common case */
209
from += wsize - op;
210
if (op < len) { /* some from window */
211
len -= op;
212
do {
213
output[_out++] = window[from++];
214
} while (--op);
215
from = _out - dist; /* rest from output */
216
from_source = output;
217
}
218
}
219
else if (wnext < op) { /* wrap around window */
220
from += wsize + wnext - op;
221
op -= wnext;
222
if (op < len) { /* some from end of window */
223
len -= op;
224
do {
225
output[_out++] = window[from++];
226
} while (--op);
227
from = 0;
228
if (wnext < len) { /* some from start of window */
229
op = wnext;
230
len -= op;
231
do {
232
output[_out++] = window[from++];
233
} while (--op);
234
from = _out - dist; /* rest from output */
235
from_source = output;
236
}
237
}
238
}
239
else { /* contiguous in window */
240
from += wnext - op;
241
if (op < len) { /* some from window */
242
len -= op;
243
do {
244
output[_out++] = window[from++];
245
} while (--op);
246
from = _out - dist; /* rest from output */
247
from_source = output;
248
}
249
}
250
while (len > 2) {
251
output[_out++] = from_source[from++];
252
output[_out++] = from_source[from++];
253
output[_out++] = from_source[from++];
254
len -= 3;
255
}
256
if (len) {
257
output[_out++] = from_source[from++];
258
if (len > 1) {
259
output[_out++] = from_source[from++];
260
}
261
}
262
}
263
else {
264
from = _out - dist; /* copy direct from output */
265
do { /* minimum length is three */
266
output[_out++] = output[from++];
267
output[_out++] = output[from++];
268
output[_out++] = output[from++];
269
len -= 3;
270
} while (len > 2);
271
if (len) {
272
output[_out++] = output[from++];
273
if (len > 1) {
274
output[_out++] = output[from++];
275
}
276
}
277
}
278
}
279
else if ((op & 64) === 0) { /* 2nd level distance code */
280
here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
281
continue dodist;
282
}
283
else {
284
strm.msg = 'invalid distance code';
285
state.mode = BAD;
286
break top;
287
}
288
289
break; // need to emulate goto via "continue"
290
}
291
}
292
else if ((op & 64) === 0) { /* 2nd level length code */
293
here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
294
continue dolen;
295
}
296
else if (op & 32) { /* end-of-block */
297
//Tracevv((stderr, "inflate: end of block\n"));
298
state.mode = TYPE;
299
break top;
300
}
301
else {
302
strm.msg = 'invalid literal/length code';
303
state.mode = BAD;
304
break top;
305
}
306
307
break; // need to emulate goto via "continue"
308
}
309
} while (_in < last && _out < end);
310
311
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
312
len = bits >> 3;
313
_in -= len;
314
bits -= len << 3;
315
hold &= (1 << bits) - 1;
316
317
/* update state and return */
318
strm.next_in = _in;
319
strm.next_out = _out;
320
strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));
321
strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));
322
state.hold = hold;
323
state.bits = bits;
324
return;
325
};
326
327