brotli-lib 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/LICENSE_THIRD_PARTY +88 -0
- package/README.md +112 -0
- package/dist/decode/bit-reader.d.ts +31 -0
- package/dist/decode/bit-reader.d.ts.map +1 -0
- package/dist/decode/decode.d.ts +7 -0
- package/dist/decode/decode.d.ts.map +1 -0
- package/dist/decode/dictionary-bin.d.ts +2 -0
- package/dist/decode/dictionary-bin.d.ts.map +1 -0
- package/dist/decode/dictionary.d.ts +8 -0
- package/dist/decode/dictionary.d.ts.map +1 -0
- package/dist/decode/engine.d.ts +93 -0
- package/dist/decode/engine.d.ts.map +1 -0
- package/dist/decode/index.d.ts +3 -0
- package/dist/decode/index.d.ts.map +1 -0
- package/dist/decode/streams.d.ts +13 -0
- package/dist/decode/streams.d.ts.map +1 -0
- package/dist/decode.cjs +2138 -0
- package/dist/decode.d.ts +3 -0
- package/dist/decode.d.ts.map +1 -0
- package/dist/decode.js +2135 -0
- package/dist/encode/backward-references-hq.d.ts +13 -0
- package/dist/encode/backward-references-hq.d.ts.map +1 -0
- package/dist/encode/backward-references.d.ts +14 -0
- package/dist/encode/backward-references.d.ts.map +1 -0
- package/dist/encode/bit-cost.d.ts +11 -0
- package/dist/encode/bit-cost.d.ts.map +1 -0
- package/dist/encode/bit-writer.d.ts +25 -0
- package/dist/encode/bit-writer.d.ts.map +1 -0
- package/dist/encode/block-splitter.d.ts +12 -0
- package/dist/encode/block-splitter.d.ts.map +1 -0
- package/dist/encode/cluster.d.ts +25 -0
- package/dist/encode/cluster.d.ts.map +1 -0
- package/dist/encode/command.d.ts +28 -0
- package/dist/encode/command.d.ts.map +1 -0
- package/dist/encode/context-map.d.ts +13 -0
- package/dist/encode/context-map.d.ts.map +1 -0
- package/dist/encode/context.d.ts +14 -0
- package/dist/encode/context.d.ts.map +1 -0
- package/dist/encode/enc-constants.d.ts +92 -0
- package/dist/encode/enc-constants.d.ts.map +1 -0
- package/dist/encode/encode.d.ts +39 -0
- package/dist/encode/encode.d.ts.map +1 -0
- package/dist/encode/entropy-encode.d.ts +20 -0
- package/dist/encode/entropy-encode.d.ts.map +1 -0
- package/dist/encode/fast-log.d.ts +7 -0
- package/dist/encode/fast-log.d.ts.map +1 -0
- package/dist/encode/hash-binary-tree.d.ts +23 -0
- package/dist/encode/hash-binary-tree.d.ts.map +1 -0
- package/dist/encode/hash-chains.d.ts +20 -0
- package/dist/encode/hash-chains.d.ts.map +1 -0
- package/dist/encode/hash-simple.d.ts +19 -0
- package/dist/encode/hash-simple.d.ts.map +1 -0
- package/dist/encode/histogram.d.ts +61 -0
- package/dist/encode/histogram.d.ts.map +1 -0
- package/dist/encode/index.d.ts +4 -0
- package/dist/encode/index.d.ts.map +1 -0
- package/dist/encode/match.d.ts +31 -0
- package/dist/encode/match.d.ts.map +1 -0
- package/dist/encode/metablock.d.ts +48 -0
- package/dist/encode/metablock.d.ts.map +1 -0
- package/dist/encode/static-dict.d.ts +26 -0
- package/dist/encode/static-dict.d.ts.map +1 -0
- package/dist/encode/zopfli-cost-model.d.ts +21 -0
- package/dist/encode/zopfli-cost-model.d.ts.map +1 -0
- package/dist/encode.cjs +2426 -0
- package/dist/encode.d.ts +4 -0
- package/dist/encode.d.ts.map +1 -0
- package/dist/encode.js +2422 -0
- package/dist/index.cjs +4562 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4556 -0
- package/package.json +66 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,4556 @@
|
|
|
1
|
+
//#region src/decode/streams.ts
|
|
2
|
+
var BrotliInput = class {
|
|
3
|
+
constructor(buffer) {
|
|
4
|
+
this.buffer = buffer;
|
|
5
|
+
this.pos = 0;
|
|
6
|
+
}
|
|
7
|
+
read(buf, i, count) {
|
|
8
|
+
const available = this.buffer.length - this.pos;
|
|
9
|
+
if (count > available) count = available;
|
|
10
|
+
buf.set(this.buffer.subarray(this.pos, this.pos + count), i);
|
|
11
|
+
this.pos += count;
|
|
12
|
+
return count;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/decode/bit-reader.ts
|
|
18
|
+
const BROTLI_READ_SIZE = 4096;
|
|
19
|
+
const BROTLI_BYTE_BUFFER_SIZE = BROTLI_READ_SIZE + 64;
|
|
20
|
+
const BROTLI_SHORT_BUFFER_SIZE = BROTLI_BYTE_BUFFER_SIZE >> 1;
|
|
21
|
+
const BROTLI_IBUF_MASK = 2 * BROTLI_READ_SIZE - 1;
|
|
22
|
+
const kBitMask = new Uint32Array([
|
|
23
|
+
0,
|
|
24
|
+
1,
|
|
25
|
+
3,
|
|
26
|
+
7,
|
|
27
|
+
15,
|
|
28
|
+
31,
|
|
29
|
+
63,
|
|
30
|
+
127,
|
|
31
|
+
255,
|
|
32
|
+
511,
|
|
33
|
+
1023,
|
|
34
|
+
2047,
|
|
35
|
+
4095,
|
|
36
|
+
8191,
|
|
37
|
+
16383,
|
|
38
|
+
32767,
|
|
39
|
+
65535,
|
|
40
|
+
131071,
|
|
41
|
+
262143,
|
|
42
|
+
524287,
|
|
43
|
+
1048575,
|
|
44
|
+
2097151,
|
|
45
|
+
4194303,
|
|
46
|
+
8388607,
|
|
47
|
+
16777215
|
|
48
|
+
]);
|
|
49
|
+
var BrotliBitReader = class {
|
|
50
|
+
static {
|
|
51
|
+
this.READ_SIZE = BROTLI_READ_SIZE;
|
|
52
|
+
}
|
|
53
|
+
static {
|
|
54
|
+
this.IBUF_MASK = BROTLI_IBUF_MASK;
|
|
55
|
+
}
|
|
56
|
+
constructor(input) {
|
|
57
|
+
this.accumulator32_ = 0;
|
|
58
|
+
this.bit_offset_ = 0;
|
|
59
|
+
this.half_offset_ = 0;
|
|
60
|
+
this.tail_bytes_ = 0;
|
|
61
|
+
this.end_of_stream_reached_ = 0;
|
|
62
|
+
this.input_ = input;
|
|
63
|
+
this.byte_buffer_ = new Uint8Array(BROTLI_BYTE_BUFFER_SIZE);
|
|
64
|
+
this.short_buffer_ = new Int16Array(BROTLI_SHORT_BUFFER_SIZE);
|
|
65
|
+
this.reset();
|
|
66
|
+
}
|
|
67
|
+
reset() {
|
|
68
|
+
this.accumulator32_ = 0;
|
|
69
|
+
this.bit_offset_ = 32;
|
|
70
|
+
this.half_offset_ = 2048;
|
|
71
|
+
this.tail_bytes_ = 0;
|
|
72
|
+
this.end_of_stream_reached_ = 0;
|
|
73
|
+
this.prepare();
|
|
74
|
+
return this.bit_offset_ < 32;
|
|
75
|
+
}
|
|
76
|
+
readMoreInput() {
|
|
77
|
+
if (this.end_of_stream_reached_ !== 0) {
|
|
78
|
+
if (this.halfAvailable() >= -2) return;
|
|
79
|
+
throw new Error("Unexpected end of input");
|
|
80
|
+
}
|
|
81
|
+
const read_offset = this.half_offset_ << 1;
|
|
82
|
+
let bytes_in_buffer = BROTLI_READ_SIZE - read_offset;
|
|
83
|
+
this.byte_buffer_.copyWithin(0, read_offset, BROTLI_READ_SIZE);
|
|
84
|
+
this.half_offset_ = 0;
|
|
85
|
+
while (bytes_in_buffer < BROTLI_READ_SIZE) {
|
|
86
|
+
const space_left = BROTLI_READ_SIZE - bytes_in_buffer;
|
|
87
|
+
const len = this.input_.read(this.byte_buffer_, bytes_in_buffer, space_left);
|
|
88
|
+
if (len < 0) throw new Error("Unexpected end of input");
|
|
89
|
+
if (len <= 0) {
|
|
90
|
+
this.end_of_stream_reached_ = 1;
|
|
91
|
+
this.tail_bytes_ = bytes_in_buffer;
|
|
92
|
+
bytes_in_buffer += 1;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
bytes_in_buffer += len;
|
|
96
|
+
}
|
|
97
|
+
this.bytesToNibbles(bytes_in_buffer);
|
|
98
|
+
}
|
|
99
|
+
bytesToNibbles(bytes_in_buffer) {
|
|
100
|
+
const short_buffer = this.short_buffer_;
|
|
101
|
+
const byte_buffer = this.byte_buffer_;
|
|
102
|
+
const len = bytes_in_buffer + 1 >> 1;
|
|
103
|
+
for (let i = 0; i < len; ++i) short_buffer[i] = byte_buffer[i * 2] & 255 | (byte_buffer[i * 2 + 1] & 255) << 8;
|
|
104
|
+
}
|
|
105
|
+
readInput(buf, offset, length) {
|
|
106
|
+
return this.input_.read(buf, offset, length);
|
|
107
|
+
}
|
|
108
|
+
checkHealth(end_of_stream) {
|
|
109
|
+
if (this.end_of_stream_reached_ === 0) return;
|
|
110
|
+
const byte_offset = (this.half_offset_ << 1) + (this.bit_offset_ + 7 >> 3) - 4;
|
|
111
|
+
if (byte_offset > this.tail_bytes_) throw new Error("Unexpected end of input");
|
|
112
|
+
if (end_of_stream !== 0 && byte_offset !== this.tail_bytes_) throw new Error("Unexpected end of input");
|
|
113
|
+
}
|
|
114
|
+
prepare() {
|
|
115
|
+
if (this.half_offset_ > 2030) this.readMoreInput();
|
|
116
|
+
this.checkHealth(0);
|
|
117
|
+
this.accumulator32_ = this.short_buffer_[this.half_offset_++] << 16 | this.accumulator32_ >>> 16;
|
|
118
|
+
this.bit_offset_ -= 16;
|
|
119
|
+
this.accumulator32_ = this.short_buffer_[this.half_offset_++] << 16 | this.accumulator32_ >>> 16;
|
|
120
|
+
this.bit_offset_ -= 16;
|
|
121
|
+
}
|
|
122
|
+
reload16() {
|
|
123
|
+
if (this.half_offset_ > 2030) this.readMoreInput();
|
|
124
|
+
this.checkHealth(0);
|
|
125
|
+
this.accumulator32_ = this.short_buffer_[this.half_offset_++] << 16 | this.accumulator32_ >>> 16;
|
|
126
|
+
this.bit_offset_ -= 16;
|
|
127
|
+
}
|
|
128
|
+
readFewBits(n_bits) {
|
|
129
|
+
const val = this.accumulator32_ >>> this.bit_offset_ & kBitMask[n_bits];
|
|
130
|
+
this.bit_offset_ += n_bits;
|
|
131
|
+
return val;
|
|
132
|
+
}
|
|
133
|
+
readManyBits(n_bits) {
|
|
134
|
+
const low = this.readFewBits(16);
|
|
135
|
+
this.reload16();
|
|
136
|
+
return low | this.readFewBits(n_bits - 16) << 16;
|
|
137
|
+
}
|
|
138
|
+
peekBits(n_bits) {
|
|
139
|
+
if (this.bit_offset_ >= 16) this.reload16();
|
|
140
|
+
return this.accumulator32_ >>> this.bit_offset_ & kBitMask[n_bits];
|
|
141
|
+
}
|
|
142
|
+
skipBits(n_bits) {
|
|
143
|
+
this.bit_offset_ += n_bits;
|
|
144
|
+
}
|
|
145
|
+
alignToByte() {
|
|
146
|
+
const padding = 32 - this.bit_offset_ & 7;
|
|
147
|
+
if (padding === 0) return 0;
|
|
148
|
+
return this.readBits(padding);
|
|
149
|
+
}
|
|
150
|
+
copyRawBytes(dst, offset, length) {
|
|
151
|
+
let pos = offset;
|
|
152
|
+
let len = length;
|
|
153
|
+
if ((this.bit_offset_ & 7) !== 0) throw new Error("Invalid alignment for raw copy");
|
|
154
|
+
while (this.bit_offset_ !== 32 && len !== 0) {
|
|
155
|
+
dst[pos++] = this.accumulator32_ >>> this.bit_offset_;
|
|
156
|
+
this.bit_offset_ += 8;
|
|
157
|
+
len--;
|
|
158
|
+
}
|
|
159
|
+
if (len === 0) return;
|
|
160
|
+
const copy_nibbles = Math.min(this.halfAvailable(), len >> 1);
|
|
161
|
+
if (copy_nibbles > 0) {
|
|
162
|
+
const read_offset = this.half_offset_ << 1;
|
|
163
|
+
const delta = copy_nibbles << 1;
|
|
164
|
+
dst.set(this.byte_buffer_.subarray(read_offset, read_offset + delta), pos);
|
|
165
|
+
pos += delta;
|
|
166
|
+
len -= delta;
|
|
167
|
+
this.half_offset_ += copy_nibbles;
|
|
168
|
+
}
|
|
169
|
+
if (len === 0) return;
|
|
170
|
+
if (this.halfAvailable() > 0) {
|
|
171
|
+
if (this.bit_offset_ >= 16) {
|
|
172
|
+
this.accumulator32_ = this.short_buffer_[this.half_offset_++] << 16 | this.accumulator32_ >>> 16;
|
|
173
|
+
this.bit_offset_ -= 16;
|
|
174
|
+
}
|
|
175
|
+
while (len !== 0) {
|
|
176
|
+
dst[pos++] = this.accumulator32_ >>> this.bit_offset_;
|
|
177
|
+
this.bit_offset_ += 8;
|
|
178
|
+
len--;
|
|
179
|
+
}
|
|
180
|
+
this.checkHealth(0);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
while (len > 0) {
|
|
184
|
+
const chunk_len = this.readInput(dst, pos, len);
|
|
185
|
+
if (chunk_len <= 0) throw new Error("Unexpected end of input");
|
|
186
|
+
pos += chunk_len;
|
|
187
|
+
len -= chunk_len;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
halfAvailable() {
|
|
191
|
+
let limit = 2048;
|
|
192
|
+
if (this.end_of_stream_reached_ !== 0) limit = this.tail_bytes_ + 1 >> 1;
|
|
193
|
+
return limit - this.half_offset_;
|
|
194
|
+
}
|
|
195
|
+
readBits(n_bits) {
|
|
196
|
+
if (this.bit_offset_ >= 16) this.reload16();
|
|
197
|
+
if (n_bits <= 16) return this.readFewBits(n_bits);
|
|
198
|
+
return this.readManyBits(n_bits);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
//#endregion
|
|
203
|
+
//#region src/decode/dictionary-bin.ts
|
|
204
|
+
const compressedDictionary = "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";
|
|
205
|
+
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region src/decode/dictionary.ts
|
|
208
|
+
let _decoder = null;
|
|
209
|
+
function setDecoder(decoder) {
|
|
210
|
+
_decoder = decoder;
|
|
211
|
+
}
|
|
212
|
+
const offsetsByLength = new Uint32Array([
|
|
213
|
+
0,
|
|
214
|
+
0,
|
|
215
|
+
0,
|
|
216
|
+
0,
|
|
217
|
+
0,
|
|
218
|
+
4096,
|
|
219
|
+
9216,
|
|
220
|
+
21504,
|
|
221
|
+
35840,
|
|
222
|
+
44032,
|
|
223
|
+
53248,
|
|
224
|
+
63488,
|
|
225
|
+
74752,
|
|
226
|
+
87040,
|
|
227
|
+
93696,
|
|
228
|
+
100864,
|
|
229
|
+
104704,
|
|
230
|
+
106752,
|
|
231
|
+
108928,
|
|
232
|
+
113536,
|
|
233
|
+
115968,
|
|
234
|
+
118528,
|
|
235
|
+
119872,
|
|
236
|
+
121280,
|
|
237
|
+
122016
|
|
238
|
+
]);
|
|
239
|
+
const sizeBitsByLength = new Uint8Array([
|
|
240
|
+
0,
|
|
241
|
+
0,
|
|
242
|
+
0,
|
|
243
|
+
0,
|
|
244
|
+
10,
|
|
245
|
+
10,
|
|
246
|
+
11,
|
|
247
|
+
11,
|
|
248
|
+
10,
|
|
249
|
+
10,
|
|
250
|
+
10,
|
|
251
|
+
10,
|
|
252
|
+
10,
|
|
253
|
+
9,
|
|
254
|
+
9,
|
|
255
|
+
8,
|
|
256
|
+
7,
|
|
257
|
+
7,
|
|
258
|
+
8,
|
|
259
|
+
7,
|
|
260
|
+
7,
|
|
261
|
+
6,
|
|
262
|
+
6,
|
|
263
|
+
5,
|
|
264
|
+
5
|
|
265
|
+
]);
|
|
266
|
+
|
|
267
|
+
//#endregion
|
|
268
|
+
//#region src/decode/engine.ts
|
|
269
|
+
const MAX_HUFFMAN_TABLE_SIZE = Int32Array.from([
|
|
270
|
+
256,
|
|
271
|
+
402,
|
|
272
|
+
436,
|
|
273
|
+
468,
|
|
274
|
+
500,
|
|
275
|
+
534,
|
|
276
|
+
566,
|
|
277
|
+
598,
|
|
278
|
+
630,
|
|
279
|
+
662,
|
|
280
|
+
694,
|
|
281
|
+
726,
|
|
282
|
+
758,
|
|
283
|
+
790,
|
|
284
|
+
822,
|
|
285
|
+
854,
|
|
286
|
+
886,
|
|
287
|
+
920,
|
|
288
|
+
952,
|
|
289
|
+
984,
|
|
290
|
+
1016,
|
|
291
|
+
1048,
|
|
292
|
+
1080
|
|
293
|
+
]);
|
|
294
|
+
const CODE_LENGTH_CODE_ORDER = Int32Array.from([
|
|
295
|
+
1,
|
|
296
|
+
2,
|
|
297
|
+
3,
|
|
298
|
+
4,
|
|
299
|
+
0,
|
|
300
|
+
5,
|
|
301
|
+
17,
|
|
302
|
+
6,
|
|
303
|
+
16,
|
|
304
|
+
7,
|
|
305
|
+
8,
|
|
306
|
+
9,
|
|
307
|
+
10,
|
|
308
|
+
11,
|
|
309
|
+
12,
|
|
310
|
+
13,
|
|
311
|
+
14,
|
|
312
|
+
15
|
|
313
|
+
]);
|
|
314
|
+
const DISTANCE_SHORT_CODE_INDEX_OFFSET = Int32Array.from([
|
|
315
|
+
0,
|
|
316
|
+
3,
|
|
317
|
+
2,
|
|
318
|
+
1,
|
|
319
|
+
0,
|
|
320
|
+
0,
|
|
321
|
+
0,
|
|
322
|
+
0,
|
|
323
|
+
0,
|
|
324
|
+
0,
|
|
325
|
+
3,
|
|
326
|
+
3,
|
|
327
|
+
3,
|
|
328
|
+
3,
|
|
329
|
+
3,
|
|
330
|
+
3
|
|
331
|
+
]);
|
|
332
|
+
const DISTANCE_SHORT_CODE_VALUE_OFFSET = Int32Array.from([
|
|
333
|
+
0,
|
|
334
|
+
0,
|
|
335
|
+
0,
|
|
336
|
+
0,
|
|
337
|
+
-1,
|
|
338
|
+
1,
|
|
339
|
+
-2,
|
|
340
|
+
2,
|
|
341
|
+
-3,
|
|
342
|
+
3,
|
|
343
|
+
-1,
|
|
344
|
+
1,
|
|
345
|
+
-2,
|
|
346
|
+
2,
|
|
347
|
+
-3,
|
|
348
|
+
3
|
|
349
|
+
]);
|
|
350
|
+
const FIXED_TABLE = Int32Array.from([
|
|
351
|
+
131072,
|
|
352
|
+
131076,
|
|
353
|
+
131075,
|
|
354
|
+
196610,
|
|
355
|
+
131072,
|
|
356
|
+
131076,
|
|
357
|
+
131075,
|
|
358
|
+
262145,
|
|
359
|
+
131072,
|
|
360
|
+
131076,
|
|
361
|
+
131075,
|
|
362
|
+
196610,
|
|
363
|
+
131072,
|
|
364
|
+
131076,
|
|
365
|
+
131075,
|
|
366
|
+
262149
|
|
367
|
+
]);
|
|
368
|
+
const BLOCK_LENGTH_OFFSET = Int32Array.from([
|
|
369
|
+
1,
|
|
370
|
+
5,
|
|
371
|
+
9,
|
|
372
|
+
13,
|
|
373
|
+
17,
|
|
374
|
+
25,
|
|
375
|
+
33,
|
|
376
|
+
41,
|
|
377
|
+
49,
|
|
378
|
+
65,
|
|
379
|
+
81,
|
|
380
|
+
97,
|
|
381
|
+
113,
|
|
382
|
+
145,
|
|
383
|
+
177,
|
|
384
|
+
209,
|
|
385
|
+
241,
|
|
386
|
+
305,
|
|
387
|
+
369,
|
|
388
|
+
497,
|
|
389
|
+
753,
|
|
390
|
+
1265,
|
|
391
|
+
2289,
|
|
392
|
+
4337,
|
|
393
|
+
8433,
|
|
394
|
+
16625
|
|
395
|
+
]);
|
|
396
|
+
const BLOCK_LENGTH_N_BITS = Int32Array.from([
|
|
397
|
+
2,
|
|
398
|
+
2,
|
|
399
|
+
2,
|
|
400
|
+
2,
|
|
401
|
+
3,
|
|
402
|
+
3,
|
|
403
|
+
3,
|
|
404
|
+
3,
|
|
405
|
+
4,
|
|
406
|
+
4,
|
|
407
|
+
4,
|
|
408
|
+
4,
|
|
409
|
+
5,
|
|
410
|
+
5,
|
|
411
|
+
5,
|
|
412
|
+
5,
|
|
413
|
+
6,
|
|
414
|
+
6,
|
|
415
|
+
7,
|
|
416
|
+
8,
|
|
417
|
+
9,
|
|
418
|
+
10,
|
|
419
|
+
11,
|
|
420
|
+
12,
|
|
421
|
+
13,
|
|
422
|
+
24
|
|
423
|
+
]);
|
|
424
|
+
const INSERT_LENGTH_N_BITS = Int16Array.from([
|
|
425
|
+
0,
|
|
426
|
+
0,
|
|
427
|
+
0,
|
|
428
|
+
0,
|
|
429
|
+
0,
|
|
430
|
+
0,
|
|
431
|
+
1,
|
|
432
|
+
1,
|
|
433
|
+
2,
|
|
434
|
+
2,
|
|
435
|
+
3,
|
|
436
|
+
3,
|
|
437
|
+
4,
|
|
438
|
+
4,
|
|
439
|
+
5,
|
|
440
|
+
5,
|
|
441
|
+
6,
|
|
442
|
+
7,
|
|
443
|
+
8,
|
|
444
|
+
9,
|
|
445
|
+
10,
|
|
446
|
+
12,
|
|
447
|
+
14,
|
|
448
|
+
24
|
|
449
|
+
]);
|
|
450
|
+
const COPY_LENGTH_N_BITS = Int16Array.from([
|
|
451
|
+
0,
|
|
452
|
+
0,
|
|
453
|
+
0,
|
|
454
|
+
0,
|
|
455
|
+
0,
|
|
456
|
+
0,
|
|
457
|
+
0,
|
|
458
|
+
0,
|
|
459
|
+
1,
|
|
460
|
+
1,
|
|
461
|
+
2,
|
|
462
|
+
2,
|
|
463
|
+
3,
|
|
464
|
+
3,
|
|
465
|
+
4,
|
|
466
|
+
4,
|
|
467
|
+
5,
|
|
468
|
+
5,
|
|
469
|
+
6,
|
|
470
|
+
7,
|
|
471
|
+
8,
|
|
472
|
+
9,
|
|
473
|
+
10,
|
|
474
|
+
24
|
|
475
|
+
]);
|
|
476
|
+
const CMD_LOOKUP = new Int16Array(2816);
|
|
477
|
+
unpackCommandLookupTable(CMD_LOOKUP);
|
|
478
|
+
const IS_LITTLE_ENDIAN = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1;
|
|
479
|
+
function log2floor(i) {
|
|
480
|
+
let result = -1;
|
|
481
|
+
let step = 16;
|
|
482
|
+
let v = i;
|
|
483
|
+
while (step > 0) {
|
|
484
|
+
let next = v >> step;
|
|
485
|
+
if (next !== 0) {
|
|
486
|
+
result += step;
|
|
487
|
+
v = next;
|
|
488
|
+
}
|
|
489
|
+
step = step >> 1;
|
|
490
|
+
}
|
|
491
|
+
return result + v;
|
|
492
|
+
}
|
|
493
|
+
function calculateDistanceAlphabetSize$1(npostfix, ndirect, maxndistbits) {
|
|
494
|
+
return 16 + ndirect + 2 * (maxndistbits << npostfix);
|
|
495
|
+
}
|
|
496
|
+
function calculateDistanceAlphabetLimit(s, maxDistance, npostfix, ndirect) {
|
|
497
|
+
if (maxDistance < ndirect + (2 << npostfix)) return makeError(s, -23);
|
|
498
|
+
const offset = (maxDistance - ndirect >> npostfix) + 4;
|
|
499
|
+
const ndistbits = log2floor(offset) - 1;
|
|
500
|
+
return ((ndistbits - 1 << 1 | offset >> ndistbits & 1) - 1 << npostfix) + (1 << npostfix) + ndirect + 16;
|
|
501
|
+
}
|
|
502
|
+
function unpackCommandLookupTable(cmdLookup) {
|
|
503
|
+
const insertLengthOffsets = new Int32Array(24);
|
|
504
|
+
const copyLengthOffsets = new Int32Array(24);
|
|
505
|
+
copyLengthOffsets[0] = 2;
|
|
506
|
+
for (let i = 0; i < 23; ++i) {
|
|
507
|
+
insertLengthOffsets[i + 1] = insertLengthOffsets[i] + (1 << INSERT_LENGTH_N_BITS[i]);
|
|
508
|
+
copyLengthOffsets[i + 1] = copyLengthOffsets[i] + (1 << COPY_LENGTH_N_BITS[i]);
|
|
509
|
+
}
|
|
510
|
+
for (let cmdCode = 0; cmdCode < 704; ++cmdCode) {
|
|
511
|
+
let rangeIdx = cmdCode >> 6;
|
|
512
|
+
let distanceContextOffset = -4;
|
|
513
|
+
if (rangeIdx >= 2) {
|
|
514
|
+
rangeIdx -= 2;
|
|
515
|
+
distanceContextOffset = 0;
|
|
516
|
+
}
|
|
517
|
+
const insertCode = (170064 >> rangeIdx * 2 & 3) << 3 | cmdCode >> 3 & 7;
|
|
518
|
+
const copyCode = (156228 >> rangeIdx * 2 & 3) << 3 | cmdCode & 7;
|
|
519
|
+
const copyLengthOffset = copyLengthOffsets[copyCode];
|
|
520
|
+
const distanceContext = distanceContextOffset + Math.min(copyLengthOffset, 5) - 2;
|
|
521
|
+
const index = cmdCode * 4;
|
|
522
|
+
cmdLookup[index] = INSERT_LENGTH_N_BITS[insertCode] | COPY_LENGTH_N_BITS[copyCode] << 8;
|
|
523
|
+
cmdLookup[index + 1] = insertLengthOffsets[insertCode];
|
|
524
|
+
cmdLookup[index + 2] = copyLengthOffsets[copyCode];
|
|
525
|
+
cmdLookup[index + 3] = distanceContext;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
function decodeWindowBits$1(s) {
|
|
529
|
+
const largeWindowEnabled = s.isLargeWindow;
|
|
530
|
+
s.isLargeWindow = 0;
|
|
531
|
+
if (s.bitOffset >= 16) {
|
|
532
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
533
|
+
s.bitOffset -= 16;
|
|
534
|
+
}
|
|
535
|
+
if (readFewBits(s, 1) === 0) return 16;
|
|
536
|
+
let n = readFewBits(s, 3);
|
|
537
|
+
if (n !== 0) return 17 + n;
|
|
538
|
+
n = readFewBits(s, 3);
|
|
539
|
+
if (n !== 0) {
|
|
540
|
+
if (n === 1) {
|
|
541
|
+
if (largeWindowEnabled === 0) return -1;
|
|
542
|
+
s.isLargeWindow = 1;
|
|
543
|
+
if (readFewBits(s, 1) === 1) return -1;
|
|
544
|
+
n = readFewBits(s, 6);
|
|
545
|
+
if (n < 10 || n > 30) return -1;
|
|
546
|
+
return n;
|
|
547
|
+
}
|
|
548
|
+
return 8 + n;
|
|
549
|
+
}
|
|
550
|
+
return 17;
|
|
551
|
+
}
|
|
552
|
+
function attachDictionaryChunk(s, data) {
|
|
553
|
+
if (s.runningState !== 1) return makeError(s, -24);
|
|
554
|
+
if (s.cdNumChunks === 0) {
|
|
555
|
+
s.cdChunks = new Array(16);
|
|
556
|
+
s.cdChunkOffsets = new Int32Array(16);
|
|
557
|
+
s.cdBlockBits = -1;
|
|
558
|
+
}
|
|
559
|
+
if (s.cdNumChunks === 15) return makeError(s, -27);
|
|
560
|
+
s.cdChunks[s.cdNumChunks] = data;
|
|
561
|
+
s.cdNumChunks++;
|
|
562
|
+
s.cdTotalSize += data.length;
|
|
563
|
+
s.cdChunkOffsets[s.cdNumChunks] = s.cdTotalSize;
|
|
564
|
+
return 0;
|
|
565
|
+
}
|
|
566
|
+
function initState(s) {
|
|
567
|
+
if (s.runningState !== 0) return makeError(s, -26);
|
|
568
|
+
s.blockTrees = new Int32Array(3091);
|
|
569
|
+
s.blockTrees[0] = 7;
|
|
570
|
+
s.distRbIdx = 3;
|
|
571
|
+
let result = calculateDistanceAlphabetLimit(s, 2147483644, 3, 120);
|
|
572
|
+
if (result < 0) return result;
|
|
573
|
+
const maxDistanceAlphabetLimit = result;
|
|
574
|
+
s.distExtraBits = new Int8Array(maxDistanceAlphabetLimit);
|
|
575
|
+
s.distOffset = new Int32Array(maxDistanceAlphabetLimit);
|
|
576
|
+
result = initBitReader(s);
|
|
577
|
+
if (result < 0) return result;
|
|
578
|
+
s.runningState = 1;
|
|
579
|
+
return 0;
|
|
580
|
+
}
|
|
581
|
+
function close(s) {
|
|
582
|
+
if (s.runningState === 0) return makeError(s, -25);
|
|
583
|
+
if (s.runningState > 0) s.runningState = 11;
|
|
584
|
+
return 0;
|
|
585
|
+
}
|
|
586
|
+
function decodeVarLenUnsignedByte(s) {
|
|
587
|
+
if (s.bitOffset >= 16) {
|
|
588
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
589
|
+
s.bitOffset -= 16;
|
|
590
|
+
}
|
|
591
|
+
if (readFewBits(s, 1) !== 0) {
|
|
592
|
+
const n = readFewBits(s, 3);
|
|
593
|
+
if (n === 0) return 1;
|
|
594
|
+
return readFewBits(s, n) + (1 << n);
|
|
595
|
+
}
|
|
596
|
+
return 0;
|
|
597
|
+
}
|
|
598
|
+
function decodeMetaBlockLength$1(s) {
|
|
599
|
+
if (s.bitOffset >= 16) {
|
|
600
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
601
|
+
s.bitOffset -= 16;
|
|
602
|
+
}
|
|
603
|
+
s.inputEnd = readFewBits(s, 1);
|
|
604
|
+
s.metaBlockLength = 0;
|
|
605
|
+
s.isUncompressed = 0;
|
|
606
|
+
s.isMetadata = 0;
|
|
607
|
+
if (s.inputEnd !== 0 && readFewBits(s, 1) !== 0) return 0;
|
|
608
|
+
const sizeNibbles = readFewBits(s, 2) + 4;
|
|
609
|
+
if (sizeNibbles === 7) {
|
|
610
|
+
s.isMetadata = 1;
|
|
611
|
+
if (readFewBits(s, 1) !== 0) return makeError(s, -6);
|
|
612
|
+
const sizeBytes = readFewBits(s, 2);
|
|
613
|
+
if (sizeBytes === 0) return 0;
|
|
614
|
+
for (let i = 0; i < sizeBytes; ++i) {
|
|
615
|
+
if (s.bitOffset >= 16) {
|
|
616
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
617
|
+
s.bitOffset -= 16;
|
|
618
|
+
}
|
|
619
|
+
const bits = readFewBits(s, 8);
|
|
620
|
+
if (bits === 0 && i + 1 === sizeBytes && sizeBytes > 1) return makeError(s, -8);
|
|
621
|
+
s.metaBlockLength += bits << i * 8;
|
|
622
|
+
}
|
|
623
|
+
} else for (let i = 0; i < sizeNibbles; ++i) {
|
|
624
|
+
if (s.bitOffset >= 16) {
|
|
625
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
626
|
+
s.bitOffset -= 16;
|
|
627
|
+
}
|
|
628
|
+
const bits = readFewBits(s, 4);
|
|
629
|
+
if (bits === 0 && i + 1 === sizeNibbles && sizeNibbles > 4) return makeError(s, -8);
|
|
630
|
+
s.metaBlockLength += bits << i * 4;
|
|
631
|
+
}
|
|
632
|
+
s.metaBlockLength++;
|
|
633
|
+
if (s.inputEnd === 0) s.isUncompressed = readFewBits(s, 1);
|
|
634
|
+
return 0;
|
|
635
|
+
}
|
|
636
|
+
function readSymbol(tableGroup, tableIdx, s) {
|
|
637
|
+
let offset = tableGroup[tableIdx];
|
|
638
|
+
const v = s.accumulator32 >>> s.bitOffset;
|
|
639
|
+
offset += v & 255;
|
|
640
|
+
const e0 = tableGroup[offset];
|
|
641
|
+
const bits = e0 >> 16;
|
|
642
|
+
const sym = e0 & 65535;
|
|
643
|
+
if (bits <= 8) {
|
|
644
|
+
s.bitOffset += bits;
|
|
645
|
+
return sym;
|
|
646
|
+
}
|
|
647
|
+
offset += sym;
|
|
648
|
+
const mask = (1 << bits) - 1;
|
|
649
|
+
offset += (v & mask) >>> 8;
|
|
650
|
+
const e1 = tableGroup[offset];
|
|
651
|
+
s.bitOffset += (e1 >> 16) + 8;
|
|
652
|
+
return e1 & 65535;
|
|
653
|
+
}
|
|
654
|
+
function readBlockLength(tableGroup, tableIdx, s) {
|
|
655
|
+
if (s.bitOffset >= 16) {
|
|
656
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
657
|
+
s.bitOffset -= 16;
|
|
658
|
+
}
|
|
659
|
+
const code = readSymbol(tableGroup, tableIdx, s);
|
|
660
|
+
const n = BLOCK_LENGTH_N_BITS[code];
|
|
661
|
+
if (s.bitOffset >= 16) {
|
|
662
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
663
|
+
s.bitOffset -= 16;
|
|
664
|
+
}
|
|
665
|
+
return BLOCK_LENGTH_OFFSET[code] + (n <= 16 ? readFewBits(s, n) : readManyBits(s, n));
|
|
666
|
+
}
|
|
667
|
+
function moveToFront(v, index) {
|
|
668
|
+
let i = index;
|
|
669
|
+
const value = v[i];
|
|
670
|
+
while (i > 0) {
|
|
671
|
+
v[i] = v[i - 1];
|
|
672
|
+
i--;
|
|
673
|
+
}
|
|
674
|
+
v[0] = value;
|
|
675
|
+
}
|
|
676
|
+
function inverseMoveToFrontTransform(v, vLen) {
|
|
677
|
+
const mtf = new Int32Array(256);
|
|
678
|
+
for (let i = 0; i < 256; ++i) mtf[i] = i;
|
|
679
|
+
for (let i = 0; i < vLen; ++i) {
|
|
680
|
+
const index = v[i] & 255;
|
|
681
|
+
v[i] = mtf[index];
|
|
682
|
+
if (index !== 0) moveToFront(mtf, index);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
function readHuffmanCodeLengths(codeLengthCodeLengths, numSymbols, codeLengths, s) {
|
|
686
|
+
let symbol = 0;
|
|
687
|
+
let prevCodeLen = 8;
|
|
688
|
+
let repeat = 0;
|
|
689
|
+
let repeatCodeLen = 0;
|
|
690
|
+
let space = 32768;
|
|
691
|
+
const table = new Int32Array(33);
|
|
692
|
+
buildHuffmanTable(table, table.length - 1, 5, codeLengthCodeLengths, 18);
|
|
693
|
+
while (symbol < numSymbols && space > 0) {
|
|
694
|
+
if (s.halfOffset > 2030) {
|
|
695
|
+
const result = readMoreInput(s);
|
|
696
|
+
if (result < 0) return result;
|
|
697
|
+
}
|
|
698
|
+
if (s.bitOffset >= 16) {
|
|
699
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
700
|
+
s.bitOffset -= 16;
|
|
701
|
+
}
|
|
702
|
+
const p = s.accumulator32 >>> s.bitOffset & 31;
|
|
703
|
+
s.bitOffset += table[p] >> 16;
|
|
704
|
+
const codeLen = table[p] & 65535;
|
|
705
|
+
if (codeLen < 16) {
|
|
706
|
+
repeat = 0;
|
|
707
|
+
codeLengths[symbol++] = codeLen;
|
|
708
|
+
if (codeLen !== 0) {
|
|
709
|
+
prevCodeLen = codeLen;
|
|
710
|
+
space -= 32768 >> codeLen;
|
|
711
|
+
}
|
|
712
|
+
} else {
|
|
713
|
+
const extraBits = codeLen - 14;
|
|
714
|
+
let newLen = 0;
|
|
715
|
+
if (codeLen === 16) newLen = prevCodeLen;
|
|
716
|
+
if (repeatCodeLen !== newLen) {
|
|
717
|
+
repeat = 0;
|
|
718
|
+
repeatCodeLen = newLen;
|
|
719
|
+
}
|
|
720
|
+
const oldRepeat = repeat;
|
|
721
|
+
if (repeat > 0) {
|
|
722
|
+
repeat -= 2;
|
|
723
|
+
repeat = repeat << extraBits;
|
|
724
|
+
}
|
|
725
|
+
if (s.bitOffset >= 16) {
|
|
726
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
727
|
+
s.bitOffset -= 16;
|
|
728
|
+
}
|
|
729
|
+
repeat += readFewBits(s, extraBits) + 3;
|
|
730
|
+
const repeatDelta = repeat - oldRepeat;
|
|
731
|
+
if (symbol + repeatDelta > numSymbols) return makeError(s, -2);
|
|
732
|
+
for (let i = 0; i < repeatDelta; ++i) codeLengths[symbol++] = repeatCodeLen;
|
|
733
|
+
if (repeatCodeLen !== 0) space -= repeatDelta << 15 - repeatCodeLen;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
if (space !== 0) return makeError(s, -18);
|
|
737
|
+
codeLengths.fill(0, symbol, numSymbols);
|
|
738
|
+
return 0;
|
|
739
|
+
}
|
|
740
|
+
function checkDupes(s, symbols, length) {
|
|
741
|
+
for (let i = 0; i < length - 1; ++i) for (let j = i + 1; j < length; ++j) if (symbols[i] === symbols[j]) return makeError(s, -7);
|
|
742
|
+
return 0;
|
|
743
|
+
}
|
|
744
|
+
function readSimpleHuffmanCode(alphabetSizeMax, alphabetSizeLimit, tableGroup, tableIdx, s) {
|
|
745
|
+
const codeLengths = new Int32Array(alphabetSizeLimit);
|
|
746
|
+
const symbols = new Int32Array(4);
|
|
747
|
+
const maxBits = 1 + log2floor(alphabetSizeMax - 1);
|
|
748
|
+
const numSymbols = readFewBits(s, 2) + 1;
|
|
749
|
+
for (let i = 0; i < numSymbols; ++i) {
|
|
750
|
+
if (s.bitOffset >= 16) {
|
|
751
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
752
|
+
s.bitOffset -= 16;
|
|
753
|
+
}
|
|
754
|
+
const symbol = readFewBits(s, maxBits);
|
|
755
|
+
if (symbol >= alphabetSizeLimit) return makeError(s, -15);
|
|
756
|
+
symbols[i] = symbol;
|
|
757
|
+
}
|
|
758
|
+
const result = checkDupes(s, symbols, numSymbols);
|
|
759
|
+
if (result < 0) return result;
|
|
760
|
+
let histogramId = numSymbols;
|
|
761
|
+
if (numSymbols === 4) histogramId += readFewBits(s, 1);
|
|
762
|
+
switch (histogramId) {
|
|
763
|
+
case 1:
|
|
764
|
+
codeLengths[symbols[0]] = 1;
|
|
765
|
+
break;
|
|
766
|
+
case 2:
|
|
767
|
+
codeLengths[symbols[0]] = 1;
|
|
768
|
+
codeLengths[symbols[1]] = 1;
|
|
769
|
+
break;
|
|
770
|
+
case 3:
|
|
771
|
+
codeLengths[symbols[0]] = 1;
|
|
772
|
+
codeLengths[symbols[1]] = 2;
|
|
773
|
+
codeLengths[symbols[2]] = 2;
|
|
774
|
+
break;
|
|
775
|
+
case 4:
|
|
776
|
+
codeLengths[symbols[0]] = 2;
|
|
777
|
+
codeLengths[symbols[1]] = 2;
|
|
778
|
+
codeLengths[symbols[2]] = 2;
|
|
779
|
+
codeLengths[symbols[3]] = 2;
|
|
780
|
+
break;
|
|
781
|
+
case 5:
|
|
782
|
+
codeLengths[symbols[0]] = 1;
|
|
783
|
+
codeLengths[symbols[1]] = 2;
|
|
784
|
+
codeLengths[symbols[2]] = 3;
|
|
785
|
+
codeLengths[symbols[3]] = 3;
|
|
786
|
+
break;
|
|
787
|
+
default: break;
|
|
788
|
+
}
|
|
789
|
+
return buildHuffmanTable(tableGroup, tableIdx, 8, codeLengths, alphabetSizeLimit);
|
|
790
|
+
}
|
|
791
|
+
function readComplexHuffmanCode(alphabetSizeLimit, skip, tableGroup, tableIdx, s) {
|
|
792
|
+
const codeLengths = new Int32Array(alphabetSizeLimit);
|
|
793
|
+
const codeLengthCodeLengths = new Int32Array(18);
|
|
794
|
+
let space = 32;
|
|
795
|
+
let numCodes = 0;
|
|
796
|
+
for (let i = skip; i < 18; ++i) {
|
|
797
|
+
const codeLenIdx = CODE_LENGTH_CODE_ORDER[i];
|
|
798
|
+
if (s.bitOffset >= 16) {
|
|
799
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
800
|
+
s.bitOffset -= 16;
|
|
801
|
+
}
|
|
802
|
+
const p = s.accumulator32 >>> s.bitOffset & 15;
|
|
803
|
+
s.bitOffset += FIXED_TABLE[p] >> 16;
|
|
804
|
+
const v = FIXED_TABLE[p] & 65535;
|
|
805
|
+
codeLengthCodeLengths[codeLenIdx] = v;
|
|
806
|
+
if (v !== 0) {
|
|
807
|
+
space -= 32 >> v;
|
|
808
|
+
numCodes++;
|
|
809
|
+
if (space <= 0) break;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
if (space !== 0 && numCodes !== 1) return makeError(s, -4);
|
|
813
|
+
const result = readHuffmanCodeLengths(codeLengthCodeLengths, alphabetSizeLimit, codeLengths, s);
|
|
814
|
+
if (result < 0) return result;
|
|
815
|
+
return buildHuffmanTable(tableGroup, tableIdx, 8, codeLengths, alphabetSizeLimit);
|
|
816
|
+
}
|
|
817
|
+
function readHuffmanCode(alphabetSizeMax, alphabetSizeLimit, tableGroup, tableIdx, s) {
|
|
818
|
+
if (s.halfOffset > 2030) {
|
|
819
|
+
const result = readMoreInput(s);
|
|
820
|
+
if (result < 0) return result;
|
|
821
|
+
}
|
|
822
|
+
if (s.bitOffset >= 16) {
|
|
823
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
824
|
+
s.bitOffset -= 16;
|
|
825
|
+
}
|
|
826
|
+
const simpleCodeOrSkip = readFewBits(s, 2);
|
|
827
|
+
if (simpleCodeOrSkip === 1) return readSimpleHuffmanCode(alphabetSizeMax, alphabetSizeLimit, tableGroup, tableIdx, s);
|
|
828
|
+
return readComplexHuffmanCode(alphabetSizeLimit, simpleCodeOrSkip, tableGroup, tableIdx, s);
|
|
829
|
+
}
|
|
830
|
+
function decodeContextMap(contextMapSize, contextMap, s) {
|
|
831
|
+
let result;
|
|
832
|
+
if (s.halfOffset > 2030) {
|
|
833
|
+
result = readMoreInput(s);
|
|
834
|
+
if (result < 0) return result;
|
|
835
|
+
}
|
|
836
|
+
const numTrees = decodeVarLenUnsignedByte(s) + 1;
|
|
837
|
+
if (numTrees === 1) {
|
|
838
|
+
contextMap.fill(0, 0, contextMapSize);
|
|
839
|
+
return numTrees;
|
|
840
|
+
}
|
|
841
|
+
if (s.bitOffset >= 16) {
|
|
842
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
843
|
+
s.bitOffset -= 16;
|
|
844
|
+
}
|
|
845
|
+
const useRleForZeros = readFewBits(s, 1);
|
|
846
|
+
let maxRunLengthPrefix = 0;
|
|
847
|
+
if (useRleForZeros !== 0) maxRunLengthPrefix = readFewBits(s, 4) + 1;
|
|
848
|
+
const alphabetSize = numTrees + maxRunLengthPrefix;
|
|
849
|
+
const tableSize = MAX_HUFFMAN_TABLE_SIZE[alphabetSize + 31 >> 5];
|
|
850
|
+
const table = new Int32Array(tableSize + 1);
|
|
851
|
+
const tableIdx = table.length - 1;
|
|
852
|
+
result = readHuffmanCode(alphabetSize, alphabetSize, table, tableIdx, s);
|
|
853
|
+
if (result < 0) return result;
|
|
854
|
+
let i = 0;
|
|
855
|
+
while (i < contextMapSize) {
|
|
856
|
+
if (s.halfOffset > 2030) {
|
|
857
|
+
result = readMoreInput(s);
|
|
858
|
+
if (result < 0) return result;
|
|
859
|
+
}
|
|
860
|
+
if (s.bitOffset >= 16) {
|
|
861
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
862
|
+
s.bitOffset -= 16;
|
|
863
|
+
}
|
|
864
|
+
const code = readSymbol(table, tableIdx, s);
|
|
865
|
+
if (code === 0) {
|
|
866
|
+
contextMap[i] = 0;
|
|
867
|
+
i++;
|
|
868
|
+
} else if (code <= maxRunLengthPrefix) {
|
|
869
|
+
if (s.bitOffset >= 16) {
|
|
870
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
871
|
+
s.bitOffset -= 16;
|
|
872
|
+
}
|
|
873
|
+
let reps = (1 << code) + readFewBits(s, code);
|
|
874
|
+
while (reps !== 0) {
|
|
875
|
+
if (i >= contextMapSize) return makeError(s, -3);
|
|
876
|
+
contextMap[i] = 0;
|
|
877
|
+
i++;
|
|
878
|
+
reps--;
|
|
879
|
+
}
|
|
880
|
+
} else {
|
|
881
|
+
contextMap[i] = code - maxRunLengthPrefix;
|
|
882
|
+
i++;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
if (s.bitOffset >= 16) {
|
|
886
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
887
|
+
s.bitOffset -= 16;
|
|
888
|
+
}
|
|
889
|
+
if (readFewBits(s, 1) === 1) inverseMoveToFrontTransform(contextMap, contextMapSize);
|
|
890
|
+
return numTrees;
|
|
891
|
+
}
|
|
892
|
+
function decodeBlockTypeAndLength(s, treeType, numBlockTypes) {
|
|
893
|
+
const ringBuffers = s.rings;
|
|
894
|
+
const offset = 4 + treeType * 2;
|
|
895
|
+
if (s.bitOffset >= 16) {
|
|
896
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
897
|
+
s.bitOffset -= 16;
|
|
898
|
+
}
|
|
899
|
+
let blockType = readSymbol(s.blockTrees, 2 * treeType, s);
|
|
900
|
+
const result = readBlockLength(s.blockTrees, 2 * treeType + 1, s);
|
|
901
|
+
if (blockType === 1) blockType = ringBuffers[offset + 1] + 1;
|
|
902
|
+
else if (blockType === 0) blockType = ringBuffers[offset];
|
|
903
|
+
else blockType -= 2;
|
|
904
|
+
if (blockType >= numBlockTypes) blockType -= numBlockTypes;
|
|
905
|
+
ringBuffers[offset] = ringBuffers[offset + 1];
|
|
906
|
+
ringBuffers[offset + 1] = blockType;
|
|
907
|
+
return result;
|
|
908
|
+
}
|
|
909
|
+
function decodeLiteralBlockSwitch(s) {
|
|
910
|
+
s.literalBlockLength = decodeBlockTypeAndLength(s, 0, s.numLiteralBlockTypes);
|
|
911
|
+
const literalBlockType = s.rings[5];
|
|
912
|
+
s.contextMapSlice = literalBlockType << 6;
|
|
913
|
+
s.literalTreeIdx = s.contextMap[s.contextMapSlice] & 255;
|
|
914
|
+
s.contextLookupOffset1 = s.contextModes[literalBlockType] << 9;
|
|
915
|
+
s.contextLookupOffset2 = s.contextLookupOffset1 + 256;
|
|
916
|
+
}
|
|
917
|
+
function decodeCommandBlockSwitch(s) {
|
|
918
|
+
s.commandBlockLength = decodeBlockTypeAndLength(s, 1, s.numCommandBlockTypes);
|
|
919
|
+
s.commandTreeIdx = s.rings[7];
|
|
920
|
+
}
|
|
921
|
+
function decodeDistanceBlockSwitch(s) {
|
|
922
|
+
s.distanceBlockLength = decodeBlockTypeAndLength(s, 2, s.numDistanceBlockTypes);
|
|
923
|
+
s.distContextMapSlice = s.rings[9] << 2;
|
|
924
|
+
}
|
|
925
|
+
function maybeReallocateRingBuffer(s) {
|
|
926
|
+
let newSize = s.maxRingBufferSize;
|
|
927
|
+
if (newSize > s.expectedTotalSize) {
|
|
928
|
+
const minimalNewSize = s.expectedTotalSize;
|
|
929
|
+
while (newSize >> 1 > minimalNewSize) newSize = newSize >> 1;
|
|
930
|
+
if (s.inputEnd === 0 && newSize < 16384 && s.maxRingBufferSize >= 16384) newSize = 16384;
|
|
931
|
+
}
|
|
932
|
+
if (newSize <= s.ringBufferSize) return;
|
|
933
|
+
const ringBufferSizeWithSlack = newSize + 37;
|
|
934
|
+
const newBuffer = new Uint8Array(ringBufferSizeWithSlack);
|
|
935
|
+
const oldBuffer = s.ringBuffer;
|
|
936
|
+
if (oldBuffer.length !== 0) newBuffer.set(oldBuffer.subarray(0, s.ringBufferSize), 0);
|
|
937
|
+
s.ringBuffer = newBuffer;
|
|
938
|
+
s.ringBufferSize = newSize;
|
|
939
|
+
}
|
|
940
|
+
function readNextMetablockHeader(s) {
|
|
941
|
+
if (s.inputEnd !== 0) {
|
|
942
|
+
s.nextRunningState = 10;
|
|
943
|
+
s.runningState = 12;
|
|
944
|
+
return 0;
|
|
945
|
+
}
|
|
946
|
+
s.literalTreeGroup = new Int32Array(0);
|
|
947
|
+
s.commandTreeGroup = new Int32Array(0);
|
|
948
|
+
s.distanceTreeGroup = new Int32Array(0);
|
|
949
|
+
let result;
|
|
950
|
+
if (s.halfOffset > 2030) {
|
|
951
|
+
result = readMoreInput(s);
|
|
952
|
+
if (result < 0) return result;
|
|
953
|
+
}
|
|
954
|
+
result = decodeMetaBlockLength$1(s);
|
|
955
|
+
if (result < 0) return result;
|
|
956
|
+
if (s.metaBlockLength === 0 && s.isMetadata === 0) return 0;
|
|
957
|
+
if (s.isUncompressed !== 0 || s.isMetadata !== 0) {
|
|
958
|
+
result = jumpToByteBoundary(s);
|
|
959
|
+
if (result < 0) return result;
|
|
960
|
+
if (s.isMetadata === 0) s.runningState = 6;
|
|
961
|
+
else s.runningState = 5;
|
|
962
|
+
} else s.runningState = 3;
|
|
963
|
+
if (s.isMetadata !== 0) return 0;
|
|
964
|
+
s.expectedTotalSize += s.metaBlockLength;
|
|
965
|
+
if (s.expectedTotalSize > 1 << 30) s.expectedTotalSize = 1 << 30;
|
|
966
|
+
if (s.ringBufferSize < s.maxRingBufferSize) maybeReallocateRingBuffer(s);
|
|
967
|
+
return 0;
|
|
968
|
+
}
|
|
969
|
+
function readMetablockPartition(s, treeType, numBlockTypes) {
|
|
970
|
+
let offset = s.blockTrees[2 * treeType];
|
|
971
|
+
if (numBlockTypes <= 1) {
|
|
972
|
+
s.blockTrees[2 * treeType + 1] = offset;
|
|
973
|
+
s.blockTrees[2 * treeType + 2] = offset;
|
|
974
|
+
return 1 << 28;
|
|
975
|
+
}
|
|
976
|
+
const blockTypeAlphabetSize = numBlockTypes + 2;
|
|
977
|
+
let result = readHuffmanCode(blockTypeAlphabetSize, blockTypeAlphabetSize, s.blockTrees, 2 * treeType, s);
|
|
978
|
+
if (result < 0) return result;
|
|
979
|
+
offset += result;
|
|
980
|
+
s.blockTrees[2 * treeType + 1] = offset;
|
|
981
|
+
const blockLengthAlphabetSize = 26;
|
|
982
|
+
result = readHuffmanCode(blockLengthAlphabetSize, blockLengthAlphabetSize, s.blockTrees, 2 * treeType + 1, s);
|
|
983
|
+
if (result < 0) return result;
|
|
984
|
+
offset += result;
|
|
985
|
+
s.blockTrees[2 * treeType + 2] = offset;
|
|
986
|
+
return readBlockLength(s.blockTrees, 2 * treeType + 1, s);
|
|
987
|
+
}
|
|
988
|
+
function calculateDistanceLut(s, alphabetSizeLimit) {
|
|
989
|
+
const distExtraBits = s.distExtraBits;
|
|
990
|
+
const distOffset = s.distOffset;
|
|
991
|
+
const npostfix = s.distancePostfixBits;
|
|
992
|
+
const ndirect = s.numDirectDistanceCodes;
|
|
993
|
+
const postfix = 1 << npostfix;
|
|
994
|
+
let bits = 1;
|
|
995
|
+
let half = 0;
|
|
996
|
+
let i = 16;
|
|
997
|
+
for (let j = 0; j < ndirect; ++j) {
|
|
998
|
+
distExtraBits[i] = 0;
|
|
999
|
+
distOffset[i] = j + 1;
|
|
1000
|
+
++i;
|
|
1001
|
+
}
|
|
1002
|
+
while (i < alphabetSizeLimit) {
|
|
1003
|
+
const base = ndirect + ((2 + half << bits) - 4 << npostfix) + 1;
|
|
1004
|
+
for (let j = 0; j < postfix; ++j) {
|
|
1005
|
+
distExtraBits[i] = bits;
|
|
1006
|
+
distOffset[i] = base + j;
|
|
1007
|
+
++i;
|
|
1008
|
+
}
|
|
1009
|
+
bits = bits + half;
|
|
1010
|
+
half = half ^ 1;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
function readMetablockHuffmanCodesAndContextMaps(s) {
|
|
1014
|
+
s.numLiteralBlockTypes = decodeVarLenUnsignedByte(s) + 1;
|
|
1015
|
+
let result = readMetablockPartition(s, 0, s.numLiteralBlockTypes);
|
|
1016
|
+
if (result < 0) return result;
|
|
1017
|
+
s.literalBlockLength = result;
|
|
1018
|
+
s.numCommandBlockTypes = decodeVarLenUnsignedByte(s) + 1;
|
|
1019
|
+
result = readMetablockPartition(s, 1, s.numCommandBlockTypes);
|
|
1020
|
+
if (result < 0) return result;
|
|
1021
|
+
s.commandBlockLength = result;
|
|
1022
|
+
s.numDistanceBlockTypes = decodeVarLenUnsignedByte(s) + 1;
|
|
1023
|
+
result = readMetablockPartition(s, 2, s.numDistanceBlockTypes);
|
|
1024
|
+
if (result < 0) return result;
|
|
1025
|
+
s.distanceBlockLength = result;
|
|
1026
|
+
if (s.halfOffset > 2030) {
|
|
1027
|
+
result = readMoreInput(s);
|
|
1028
|
+
if (result < 0) return result;
|
|
1029
|
+
}
|
|
1030
|
+
if (s.bitOffset >= 16) {
|
|
1031
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
1032
|
+
s.bitOffset -= 16;
|
|
1033
|
+
}
|
|
1034
|
+
s.distancePostfixBits = readFewBits(s, 2);
|
|
1035
|
+
s.numDirectDistanceCodes = readFewBits(s, 4) << s.distancePostfixBits;
|
|
1036
|
+
s.contextModes = new Int8Array(s.numLiteralBlockTypes);
|
|
1037
|
+
let i = 0;
|
|
1038
|
+
while (i < s.numLiteralBlockTypes) {
|
|
1039
|
+
const limit = Math.min(i + 96, s.numLiteralBlockTypes);
|
|
1040
|
+
while (i < limit) {
|
|
1041
|
+
if (s.bitOffset >= 16) {
|
|
1042
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
1043
|
+
s.bitOffset -= 16;
|
|
1044
|
+
}
|
|
1045
|
+
s.contextModes[i] = readFewBits(s, 2);
|
|
1046
|
+
i++;
|
|
1047
|
+
}
|
|
1048
|
+
if (s.halfOffset > 2030) {
|
|
1049
|
+
result = readMoreInput(s);
|
|
1050
|
+
if (result < 0) return result;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
const contextMapLength = s.numLiteralBlockTypes << 6;
|
|
1054
|
+
s.contextMap = new Int8Array(contextMapLength);
|
|
1055
|
+
result = decodeContextMap(contextMapLength, s.contextMap, s);
|
|
1056
|
+
if (result < 0) return result;
|
|
1057
|
+
const numLiteralTrees = result;
|
|
1058
|
+
s.trivialLiteralContext = 1;
|
|
1059
|
+
for (let j = 0; j < contextMapLength; ++j) if (s.contextMap[j] !== j >> 6) {
|
|
1060
|
+
s.trivialLiteralContext = 0;
|
|
1061
|
+
break;
|
|
1062
|
+
}
|
|
1063
|
+
s.distContextMap = new Int8Array(s.numDistanceBlockTypes << 2);
|
|
1064
|
+
result = decodeContextMap(s.numDistanceBlockTypes << 2, s.distContextMap, s);
|
|
1065
|
+
if (result < 0) return result;
|
|
1066
|
+
const numDistTrees = result;
|
|
1067
|
+
s.literalTreeGroup = new Int32Array(huffmanTreeGroupAllocSize(256, numLiteralTrees));
|
|
1068
|
+
result = decodeHuffmanTreeGroup(256, 256, numLiteralTrees, s, s.literalTreeGroup);
|
|
1069
|
+
if (result < 0) return result;
|
|
1070
|
+
s.commandTreeGroup = new Int32Array(huffmanTreeGroupAllocSize(704, s.numCommandBlockTypes));
|
|
1071
|
+
result = decodeHuffmanTreeGroup(704, 704, s.numCommandBlockTypes, s, s.commandTreeGroup);
|
|
1072
|
+
if (result < 0) return result;
|
|
1073
|
+
let distanceAlphabetSizeMax = calculateDistanceAlphabetSize$1(s.distancePostfixBits, s.numDirectDistanceCodes, 24);
|
|
1074
|
+
let distanceAlphabetSizeLimit = distanceAlphabetSizeMax;
|
|
1075
|
+
if (s.isLargeWindow === 1) {
|
|
1076
|
+
distanceAlphabetSizeMax = calculateDistanceAlphabetSize$1(s.distancePostfixBits, s.numDirectDistanceCodes, 62);
|
|
1077
|
+
result = calculateDistanceAlphabetLimit(s, 2147483644, s.distancePostfixBits, s.numDirectDistanceCodes);
|
|
1078
|
+
if (result < 0) return result;
|
|
1079
|
+
distanceAlphabetSizeLimit = result;
|
|
1080
|
+
}
|
|
1081
|
+
s.distanceTreeGroup = new Int32Array(huffmanTreeGroupAllocSize(distanceAlphabetSizeLimit, numDistTrees));
|
|
1082
|
+
result = decodeHuffmanTreeGroup(distanceAlphabetSizeMax, distanceAlphabetSizeLimit, numDistTrees, s, s.distanceTreeGroup);
|
|
1083
|
+
if (result < 0) return result;
|
|
1084
|
+
calculateDistanceLut(s, distanceAlphabetSizeLimit);
|
|
1085
|
+
s.contextMapSlice = 0;
|
|
1086
|
+
s.distContextMapSlice = 0;
|
|
1087
|
+
s.contextLookupOffset1 = s.contextModes[0] * 512;
|
|
1088
|
+
s.contextLookupOffset2 = s.contextLookupOffset1 + 256;
|
|
1089
|
+
s.literalTreeIdx = 0;
|
|
1090
|
+
s.commandTreeIdx = 0;
|
|
1091
|
+
s.rings[4] = 1;
|
|
1092
|
+
s.rings[5] = 0;
|
|
1093
|
+
s.rings[6] = 1;
|
|
1094
|
+
s.rings[7] = 0;
|
|
1095
|
+
s.rings[8] = 1;
|
|
1096
|
+
s.rings[9] = 0;
|
|
1097
|
+
return 0;
|
|
1098
|
+
}
|
|
1099
|
+
function copyUncompressedData(s) {
|
|
1100
|
+
const ringBuffer = s.ringBuffer;
|
|
1101
|
+
let result;
|
|
1102
|
+
if (s.metaBlockLength <= 0) {
|
|
1103
|
+
result = reload(s);
|
|
1104
|
+
if (result < 0) return result;
|
|
1105
|
+
s.runningState = 2;
|
|
1106
|
+
return 0;
|
|
1107
|
+
}
|
|
1108
|
+
const chunkLength = Math.min(s.ringBufferSize - s.pos, s.metaBlockLength);
|
|
1109
|
+
result = copyRawBytes(s, ringBuffer, s.pos, chunkLength);
|
|
1110
|
+
if (result < 0) return result;
|
|
1111
|
+
s.metaBlockLength -= chunkLength;
|
|
1112
|
+
s.pos += chunkLength;
|
|
1113
|
+
if (s.pos === s.ringBufferSize) {
|
|
1114
|
+
s.nextRunningState = 6;
|
|
1115
|
+
s.runningState = 12;
|
|
1116
|
+
return 0;
|
|
1117
|
+
}
|
|
1118
|
+
result = reload(s);
|
|
1119
|
+
if (result < 0) return result;
|
|
1120
|
+
s.runningState = 2;
|
|
1121
|
+
return 0;
|
|
1122
|
+
}
|
|
1123
|
+
function writeRingBuffer(s) {
|
|
1124
|
+
const toWrite = Math.min(s.outputLength - s.outputUsed, s.ringBufferBytesReady - s.ringBufferBytesWritten);
|
|
1125
|
+
if (toWrite !== 0) {
|
|
1126
|
+
s.output.set(s.ringBuffer.subarray(s.ringBufferBytesWritten, s.ringBufferBytesWritten + toWrite), s.outputOffset + s.outputUsed);
|
|
1127
|
+
s.outputUsed += toWrite;
|
|
1128
|
+
s.ringBufferBytesWritten += toWrite;
|
|
1129
|
+
}
|
|
1130
|
+
if (s.outputUsed < s.outputLength) return 0;
|
|
1131
|
+
return 2;
|
|
1132
|
+
}
|
|
1133
|
+
function huffmanTreeGroupAllocSize(alphabetSizeLimit, n) {
|
|
1134
|
+
return n + n * MAX_HUFFMAN_TABLE_SIZE[alphabetSizeLimit + 31 >> 5];
|
|
1135
|
+
}
|
|
1136
|
+
function decodeHuffmanTreeGroup(alphabetSizeMax, alphabetSizeLimit, n, s, group) {
|
|
1137
|
+
let next = n;
|
|
1138
|
+
for (let i = 0; i < n; ++i) {
|
|
1139
|
+
group[i] = next;
|
|
1140
|
+
const result = readHuffmanCode(alphabetSizeMax, alphabetSizeLimit, group, i, s);
|
|
1141
|
+
if (result < 0) return result;
|
|
1142
|
+
next += result;
|
|
1143
|
+
}
|
|
1144
|
+
return 0;
|
|
1145
|
+
}
|
|
1146
|
+
function calculateFence(s) {
|
|
1147
|
+
let result = s.ringBufferSize;
|
|
1148
|
+
if (s.isEager !== 0) result = Math.min(result, s.ringBufferBytesWritten + s.outputLength - s.outputUsed);
|
|
1149
|
+
return result;
|
|
1150
|
+
}
|
|
1151
|
+
function doUseDictionary(s, fence) {
|
|
1152
|
+
if (s.distance > 2147483644) return makeError(s, -9);
|
|
1153
|
+
const address = s.distance - s.maxDistance - 1 - s.cdTotalSize;
|
|
1154
|
+
if (address < 0) {
|
|
1155
|
+
const result = initializeCompoundDictionaryCopy(s, -address - 1, s.copyLength);
|
|
1156
|
+
if (result < 0) return result;
|
|
1157
|
+
s.runningState = 14;
|
|
1158
|
+
} else {
|
|
1159
|
+
ensureDictionary();
|
|
1160
|
+
const dictionaryData = data;
|
|
1161
|
+
const wordLength = s.copyLength;
|
|
1162
|
+
if (wordLength > 31) return makeError(s, -9);
|
|
1163
|
+
const shift = sizeBits[wordLength];
|
|
1164
|
+
if (shift === 0) return makeError(s, -9);
|
|
1165
|
+
let offset = offsets[wordLength];
|
|
1166
|
+
const wordIdx = address & (1 << shift) - 1;
|
|
1167
|
+
const transformIdx = address >> shift;
|
|
1168
|
+
offset += wordIdx * wordLength;
|
|
1169
|
+
const transforms = RFC_TRANSFORMS;
|
|
1170
|
+
if (transformIdx >= transforms.numTransforms) return makeError(s, -9);
|
|
1171
|
+
const len = transformDictionaryWord(s.ringBuffer, s.pos, dictionaryData, offset, wordLength, transforms, transformIdx);
|
|
1172
|
+
s.pos += len;
|
|
1173
|
+
s.metaBlockLength -= len;
|
|
1174
|
+
if (s.pos >= fence) {
|
|
1175
|
+
s.nextRunningState = 4;
|
|
1176
|
+
s.runningState = 12;
|
|
1177
|
+
return 0;
|
|
1178
|
+
}
|
|
1179
|
+
s.runningState = 4;
|
|
1180
|
+
}
|
|
1181
|
+
return 0;
|
|
1182
|
+
}
|
|
1183
|
+
function initializeCompoundDictionary(s) {
|
|
1184
|
+
s.cdBlockMap = new Int8Array(256);
|
|
1185
|
+
let blockBits = 8;
|
|
1186
|
+
while (s.cdTotalSize - 1 >> blockBits !== 0) blockBits++;
|
|
1187
|
+
blockBits -= 8;
|
|
1188
|
+
s.cdBlockBits = blockBits;
|
|
1189
|
+
let cursor = 0;
|
|
1190
|
+
let index = 0;
|
|
1191
|
+
while (cursor < s.cdTotalSize) {
|
|
1192
|
+
while (s.cdChunkOffsets[index + 1] < cursor) index++;
|
|
1193
|
+
s.cdBlockMap[cursor >> blockBits] = index;
|
|
1194
|
+
cursor += 1 << blockBits;
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
function initializeCompoundDictionaryCopy(s, address, length) {
|
|
1198
|
+
if (s.cdBlockBits === -1) initializeCompoundDictionary(s);
|
|
1199
|
+
let index = s.cdBlockMap[address >> s.cdBlockBits];
|
|
1200
|
+
while (address >= s.cdChunkOffsets[index + 1]) index++;
|
|
1201
|
+
if (s.cdTotalSize > address + length) return makeError(s, -9);
|
|
1202
|
+
s.distRbIdx = s.distRbIdx + 1 & 3;
|
|
1203
|
+
s.rings[s.distRbIdx] = s.distance;
|
|
1204
|
+
s.metaBlockLength -= length;
|
|
1205
|
+
s.cdBrIndex = index;
|
|
1206
|
+
s.cdBrOffset = address - s.cdChunkOffsets[index];
|
|
1207
|
+
s.cdBrLength = length;
|
|
1208
|
+
s.cdBrCopied = 0;
|
|
1209
|
+
return 0;
|
|
1210
|
+
}
|
|
1211
|
+
function copyFromCompoundDictionary(s, fence) {
|
|
1212
|
+
let pos = s.pos;
|
|
1213
|
+
const origPos = pos;
|
|
1214
|
+
while (s.cdBrLength !== s.cdBrCopied) {
|
|
1215
|
+
const space = fence - pos;
|
|
1216
|
+
const remChunkLength = s.cdChunkOffsets[s.cdBrIndex + 1] - s.cdChunkOffsets[s.cdBrIndex] - s.cdBrOffset;
|
|
1217
|
+
let length = s.cdBrLength - s.cdBrCopied;
|
|
1218
|
+
if (length > remChunkLength) length = remChunkLength;
|
|
1219
|
+
if (length > space) length = space;
|
|
1220
|
+
s.ringBuffer.set(s.cdChunks[s.cdBrIndex].subarray(s.cdBrOffset, s.cdBrOffset + length), pos);
|
|
1221
|
+
pos += length;
|
|
1222
|
+
s.cdBrOffset += length;
|
|
1223
|
+
s.cdBrCopied += length;
|
|
1224
|
+
if (length === remChunkLength) {
|
|
1225
|
+
s.cdBrIndex++;
|
|
1226
|
+
s.cdBrOffset = 0;
|
|
1227
|
+
}
|
|
1228
|
+
if (pos >= fence) break;
|
|
1229
|
+
}
|
|
1230
|
+
return pos - origPos;
|
|
1231
|
+
}
|
|
1232
|
+
function decompress(s) {
|
|
1233
|
+
let result;
|
|
1234
|
+
if (s.runningState === 0) return makeError(s, -25);
|
|
1235
|
+
if (s.runningState < 0) return makeError(s, -28);
|
|
1236
|
+
if (s.runningState === 11) return makeError(s, -22);
|
|
1237
|
+
if (s.runningState === 1) {
|
|
1238
|
+
const windowBits = decodeWindowBits$1(s);
|
|
1239
|
+
if (windowBits === -1) return makeError(s, -11);
|
|
1240
|
+
s.maxRingBufferSize = 1 << windowBits;
|
|
1241
|
+
s.maxBackwardDistance = s.maxRingBufferSize - 16;
|
|
1242
|
+
s.runningState = 2;
|
|
1243
|
+
}
|
|
1244
|
+
let fence = calculateFence(s);
|
|
1245
|
+
let ringBufferMask = s.ringBufferSize - 1;
|
|
1246
|
+
let ringBuffer = s.ringBuffer;
|
|
1247
|
+
while (s.runningState !== 10) switch (s.runningState) {
|
|
1248
|
+
case 2:
|
|
1249
|
+
if (s.metaBlockLength < 0) return makeError(s, -10);
|
|
1250
|
+
result = readNextMetablockHeader(s);
|
|
1251
|
+
if (result < 0) return result;
|
|
1252
|
+
fence = calculateFence(s);
|
|
1253
|
+
ringBufferMask = s.ringBufferSize - 1;
|
|
1254
|
+
ringBuffer = s.ringBuffer;
|
|
1255
|
+
continue;
|
|
1256
|
+
case 3:
|
|
1257
|
+
result = readMetablockHuffmanCodesAndContextMaps(s);
|
|
1258
|
+
if (result < 0) return result;
|
|
1259
|
+
s.runningState = 4;
|
|
1260
|
+
continue;
|
|
1261
|
+
case 4:
|
|
1262
|
+
if (s.metaBlockLength <= 0) {
|
|
1263
|
+
s.runningState = 2;
|
|
1264
|
+
continue;
|
|
1265
|
+
}
|
|
1266
|
+
if (s.halfOffset > 2030) {
|
|
1267
|
+
result = readMoreInput(s);
|
|
1268
|
+
if (result < 0) return result;
|
|
1269
|
+
}
|
|
1270
|
+
if (s.commandBlockLength === 0) decodeCommandBlockSwitch(s);
|
|
1271
|
+
s.commandBlockLength--;
|
|
1272
|
+
if (s.bitOffset >= 16) {
|
|
1273
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
1274
|
+
s.bitOffset -= 16;
|
|
1275
|
+
}
|
|
1276
|
+
const cmdCode = readSymbol(s.commandTreeGroup, s.commandTreeIdx, s) << 2;
|
|
1277
|
+
const insertAndCopyExtraBits = CMD_LOOKUP[cmdCode];
|
|
1278
|
+
const insertLengthOffset = CMD_LOOKUP[cmdCode + 1];
|
|
1279
|
+
const copyLengthOffset = CMD_LOOKUP[cmdCode + 2];
|
|
1280
|
+
s.distanceCode = CMD_LOOKUP[cmdCode + 3];
|
|
1281
|
+
if (s.bitOffset >= 16) {
|
|
1282
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
1283
|
+
s.bitOffset -= 16;
|
|
1284
|
+
}
|
|
1285
|
+
const insertLengthExtraBits = insertAndCopyExtraBits & 255;
|
|
1286
|
+
s.insertLength = insertLengthOffset + (insertLengthExtraBits <= 16 ? readFewBits(s, insertLengthExtraBits) : readManyBits(s, insertLengthExtraBits));
|
|
1287
|
+
if (s.bitOffset >= 16) {
|
|
1288
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
1289
|
+
s.bitOffset -= 16;
|
|
1290
|
+
}
|
|
1291
|
+
const copyLengthExtraBits = insertAndCopyExtraBits >> 8;
|
|
1292
|
+
s.copyLength = copyLengthOffset + (copyLengthExtraBits <= 16 ? readFewBits(s, copyLengthExtraBits) : readManyBits(s, copyLengthExtraBits));
|
|
1293
|
+
s.j = 0;
|
|
1294
|
+
s.runningState = 7;
|
|
1295
|
+
continue;
|
|
1296
|
+
case 7:
|
|
1297
|
+
if (s.trivialLiteralContext !== 0) while (s.j < s.insertLength) {
|
|
1298
|
+
if (s.halfOffset > 2030) {
|
|
1299
|
+
result = readMoreInput(s);
|
|
1300
|
+
if (result < 0) return result;
|
|
1301
|
+
}
|
|
1302
|
+
if (s.literalBlockLength === 0) decodeLiteralBlockSwitch(s);
|
|
1303
|
+
s.literalBlockLength--;
|
|
1304
|
+
if (s.bitOffset >= 16) {
|
|
1305
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
1306
|
+
s.bitOffset -= 16;
|
|
1307
|
+
}
|
|
1308
|
+
ringBuffer[s.pos] = readSymbol(s.literalTreeGroup, s.literalTreeIdx, s);
|
|
1309
|
+
s.pos++;
|
|
1310
|
+
s.j++;
|
|
1311
|
+
if (s.pos >= fence) {
|
|
1312
|
+
s.nextRunningState = 7;
|
|
1313
|
+
s.runningState = 12;
|
|
1314
|
+
break;
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
else {
|
|
1318
|
+
let prevByte1 = ringBuffer[s.pos - 1 & ringBufferMask];
|
|
1319
|
+
let prevByte2 = ringBuffer[s.pos - 2 & ringBufferMask];
|
|
1320
|
+
while (s.j < s.insertLength) {
|
|
1321
|
+
if (s.halfOffset > 2030) {
|
|
1322
|
+
result = readMoreInput(s);
|
|
1323
|
+
if (result < 0) return result;
|
|
1324
|
+
}
|
|
1325
|
+
if (s.literalBlockLength === 0) decodeLiteralBlockSwitch(s);
|
|
1326
|
+
const literalContext = LOOKUP[s.contextLookupOffset1 + prevByte1] | LOOKUP[s.contextLookupOffset2 + prevByte2];
|
|
1327
|
+
const literalTreeIdx = s.contextMap[s.contextMapSlice + literalContext] & 255;
|
|
1328
|
+
s.literalBlockLength--;
|
|
1329
|
+
prevByte2 = prevByte1;
|
|
1330
|
+
if (s.bitOffset >= 16) {
|
|
1331
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
1332
|
+
s.bitOffset -= 16;
|
|
1333
|
+
}
|
|
1334
|
+
prevByte1 = readSymbol(s.literalTreeGroup, literalTreeIdx, s);
|
|
1335
|
+
ringBuffer[s.pos] = prevByte1;
|
|
1336
|
+
s.pos++;
|
|
1337
|
+
s.j++;
|
|
1338
|
+
if (s.pos >= fence) {
|
|
1339
|
+
s.nextRunningState = 7;
|
|
1340
|
+
s.runningState = 12;
|
|
1341
|
+
break;
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
if (s.runningState !== 7) continue;
|
|
1346
|
+
s.metaBlockLength -= s.insertLength;
|
|
1347
|
+
if (s.metaBlockLength <= 0) {
|
|
1348
|
+
s.runningState = 4;
|
|
1349
|
+
continue;
|
|
1350
|
+
}
|
|
1351
|
+
let distanceCode = s.distanceCode;
|
|
1352
|
+
if (distanceCode < 0) s.distance = s.rings[s.distRbIdx];
|
|
1353
|
+
else {
|
|
1354
|
+
if (s.halfOffset > 2030) {
|
|
1355
|
+
result = readMoreInput(s);
|
|
1356
|
+
if (result < 0) return result;
|
|
1357
|
+
}
|
|
1358
|
+
if (s.distanceBlockLength === 0) decodeDistanceBlockSwitch(s);
|
|
1359
|
+
s.distanceBlockLength--;
|
|
1360
|
+
if (s.bitOffset >= 16) {
|
|
1361
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
1362
|
+
s.bitOffset -= 16;
|
|
1363
|
+
}
|
|
1364
|
+
const distTreeIdx = s.distContextMap[s.distContextMapSlice + distanceCode] & 255;
|
|
1365
|
+
distanceCode = readSymbol(s.distanceTreeGroup, distTreeIdx, s);
|
|
1366
|
+
if (distanceCode < 16) {
|
|
1367
|
+
const index = s.distRbIdx + DISTANCE_SHORT_CODE_INDEX_OFFSET[distanceCode] & 3;
|
|
1368
|
+
s.distance = s.rings[index] + DISTANCE_SHORT_CODE_VALUE_OFFSET[distanceCode];
|
|
1369
|
+
if (s.distance < 0) return makeError(s, -12);
|
|
1370
|
+
} else {
|
|
1371
|
+
const extraBits = s.distExtraBits[distanceCode];
|
|
1372
|
+
let bits;
|
|
1373
|
+
if (s.bitOffset + extraBits <= 32) bits = readFewBits(s, extraBits);
|
|
1374
|
+
else {
|
|
1375
|
+
if (s.bitOffset >= 16) {
|
|
1376
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
1377
|
+
s.bitOffset -= 16;
|
|
1378
|
+
}
|
|
1379
|
+
bits = extraBits <= 16 ? readFewBits(s, extraBits) : readManyBits(s, extraBits);
|
|
1380
|
+
}
|
|
1381
|
+
s.distance = s.distOffset[distanceCode] + (bits << s.distancePostfixBits);
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
if (s.maxDistance !== s.maxBackwardDistance && s.pos < s.maxBackwardDistance) s.maxDistance = s.pos;
|
|
1385
|
+
else s.maxDistance = s.maxBackwardDistance;
|
|
1386
|
+
if (s.distance > s.maxDistance) {
|
|
1387
|
+
s.runningState = 9;
|
|
1388
|
+
continue;
|
|
1389
|
+
}
|
|
1390
|
+
if (distanceCode > 0) {
|
|
1391
|
+
s.distRbIdx = s.distRbIdx + 1 & 3;
|
|
1392
|
+
s.rings[s.distRbIdx] = s.distance;
|
|
1393
|
+
}
|
|
1394
|
+
if (s.copyLength > s.metaBlockLength) return makeError(s, -9);
|
|
1395
|
+
s.j = 0;
|
|
1396
|
+
s.runningState = 8;
|
|
1397
|
+
continue;
|
|
1398
|
+
case 8:
|
|
1399
|
+
let src = s.pos - s.distance & ringBufferMask;
|
|
1400
|
+
let dst = s.pos;
|
|
1401
|
+
const copyLength = s.copyLength - s.j;
|
|
1402
|
+
const srcEnd = src + copyLength;
|
|
1403
|
+
const dstEnd = dst + copyLength;
|
|
1404
|
+
if (srcEnd < ringBufferMask && dstEnd < ringBufferMask) {
|
|
1405
|
+
if (s.distance === 4 && copyLength >= 8) {
|
|
1406
|
+
ringBuffer[dst] = ringBuffer[src];
|
|
1407
|
+
ringBuffer[dst + 1] = ringBuffer[src + 1];
|
|
1408
|
+
ringBuffer[dst + 2] = ringBuffer[src + 2];
|
|
1409
|
+
ringBuffer[dst + 3] = ringBuffer[src + 3];
|
|
1410
|
+
let written = 4;
|
|
1411
|
+
while (written < copyLength) {
|
|
1412
|
+
const chunk = Math.min(written, copyLength - written);
|
|
1413
|
+
ringBuffer.copyWithin(dst + written, dst, dst + chunk);
|
|
1414
|
+
written += chunk;
|
|
1415
|
+
}
|
|
1416
|
+
} else if (copyLength < 12 || srcEnd > dst && dstEnd > src) {
|
|
1417
|
+
const numQuads = copyLength + 3 >> 2;
|
|
1418
|
+
for (let k = 0; k < numQuads; ++k) {
|
|
1419
|
+
ringBuffer[dst++] = ringBuffer[src++];
|
|
1420
|
+
ringBuffer[dst++] = ringBuffer[src++];
|
|
1421
|
+
ringBuffer[dst++] = ringBuffer[src++];
|
|
1422
|
+
ringBuffer[dst++] = ringBuffer[src++];
|
|
1423
|
+
}
|
|
1424
|
+
} else ringBuffer.copyWithin(dst, src, srcEnd);
|
|
1425
|
+
s.j += copyLength;
|
|
1426
|
+
s.metaBlockLength -= copyLength;
|
|
1427
|
+
s.pos += copyLength;
|
|
1428
|
+
} else while (s.j < s.copyLength) {
|
|
1429
|
+
ringBuffer[s.pos] = ringBuffer[s.pos - s.distance & ringBufferMask];
|
|
1430
|
+
s.metaBlockLength--;
|
|
1431
|
+
s.pos++;
|
|
1432
|
+
s.j++;
|
|
1433
|
+
if (s.pos >= fence) {
|
|
1434
|
+
s.nextRunningState = 8;
|
|
1435
|
+
s.runningState = 12;
|
|
1436
|
+
break;
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
if (s.runningState === 8) s.runningState = 4;
|
|
1440
|
+
continue;
|
|
1441
|
+
case 9:
|
|
1442
|
+
result = doUseDictionary(s, fence);
|
|
1443
|
+
if (result < 0) return result;
|
|
1444
|
+
continue;
|
|
1445
|
+
case 14:
|
|
1446
|
+
s.pos += copyFromCompoundDictionary(s, fence);
|
|
1447
|
+
if (s.pos >= fence) {
|
|
1448
|
+
s.nextRunningState = 14;
|
|
1449
|
+
s.runningState = 12;
|
|
1450
|
+
return 2;
|
|
1451
|
+
}
|
|
1452
|
+
s.runningState = 4;
|
|
1453
|
+
continue;
|
|
1454
|
+
case 5:
|
|
1455
|
+
while (s.metaBlockLength > 0) {
|
|
1456
|
+
if (s.halfOffset > 2030) {
|
|
1457
|
+
result = readMoreInput(s);
|
|
1458
|
+
if (result < 0) return result;
|
|
1459
|
+
}
|
|
1460
|
+
if (s.bitOffset >= 16) {
|
|
1461
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
1462
|
+
s.bitOffset -= 16;
|
|
1463
|
+
}
|
|
1464
|
+
readFewBits(s, 8);
|
|
1465
|
+
s.metaBlockLength--;
|
|
1466
|
+
}
|
|
1467
|
+
s.runningState = 2;
|
|
1468
|
+
continue;
|
|
1469
|
+
case 6:
|
|
1470
|
+
result = copyUncompressedData(s);
|
|
1471
|
+
if (result < 0) return result;
|
|
1472
|
+
continue;
|
|
1473
|
+
case 12:
|
|
1474
|
+
s.ringBufferBytesReady = Math.min(s.pos, s.ringBufferSize);
|
|
1475
|
+
s.runningState = 13;
|
|
1476
|
+
continue;
|
|
1477
|
+
case 13:
|
|
1478
|
+
result = writeRingBuffer(s);
|
|
1479
|
+
if (result !== 0) return result;
|
|
1480
|
+
if (s.pos >= s.maxBackwardDistance) s.maxDistance = s.maxBackwardDistance;
|
|
1481
|
+
if (s.pos >= s.ringBufferSize) {
|
|
1482
|
+
if (s.pos > s.ringBufferSize) ringBuffer.copyWithin(0, s.ringBufferSize, s.pos);
|
|
1483
|
+
s.pos = s.pos & ringBufferMask;
|
|
1484
|
+
s.ringBufferBytesWritten = 0;
|
|
1485
|
+
}
|
|
1486
|
+
s.runningState = s.nextRunningState;
|
|
1487
|
+
continue;
|
|
1488
|
+
default: return makeError(s, -28);
|
|
1489
|
+
}
|
|
1490
|
+
if (s.runningState !== 10) return makeError(s, -29);
|
|
1491
|
+
if (s.metaBlockLength < 0) return makeError(s, -10);
|
|
1492
|
+
result = jumpToByteBoundary(s);
|
|
1493
|
+
if (result !== 0) return result;
|
|
1494
|
+
result = checkHealth(s, 1);
|
|
1495
|
+
if (result !== 0) return result;
|
|
1496
|
+
return 1;
|
|
1497
|
+
}
|
|
1498
|
+
var Transforms = class {
|
|
1499
|
+
constructor(numTransforms, prefixSuffixLen, prefixSuffixCount) {
|
|
1500
|
+
this.numTransforms = 0;
|
|
1501
|
+
this.triplets = new Int32Array(0);
|
|
1502
|
+
this.prefixSuffixStorage = new Int8Array(0);
|
|
1503
|
+
this.prefixSuffixHeads = new Int32Array(0);
|
|
1504
|
+
this.params = new Int16Array(0);
|
|
1505
|
+
this.numTransforms = numTransforms;
|
|
1506
|
+
this.triplets = new Int32Array(numTransforms * 3);
|
|
1507
|
+
this.params = new Int16Array(numTransforms);
|
|
1508
|
+
this.prefixSuffixStorage = new Int8Array(prefixSuffixLen);
|
|
1509
|
+
this.prefixSuffixHeads = new Int32Array(prefixSuffixCount + 1);
|
|
1510
|
+
}
|
|
1511
|
+
};
|
|
1512
|
+
const RFC_TRANSFORMS = new Transforms(121, 167, 50);
|
|
1513
|
+
function unpackTransforms(prefixSuffix, prefixSuffixHeads, transforms, prefixSuffixSrc, transformsSrc) {
|
|
1514
|
+
const prefixSuffixBytes = toUtf8Runes(prefixSuffixSrc);
|
|
1515
|
+
const n = prefixSuffixBytes.length;
|
|
1516
|
+
let index = 1;
|
|
1517
|
+
let j = 0;
|
|
1518
|
+
for (let i = 0; i < n; ++i) {
|
|
1519
|
+
const c = prefixSuffixBytes[i];
|
|
1520
|
+
if (c === 35) prefixSuffixHeads[index++] = j;
|
|
1521
|
+
else prefixSuffix[j++] = c;
|
|
1522
|
+
}
|
|
1523
|
+
for (let i = 0; i < 363; ++i) transforms[i] = transformsSrc.charCodeAt(i) - 32;
|
|
1524
|
+
}
|
|
1525
|
+
unpackTransforms(RFC_TRANSFORMS.prefixSuffixStorage, RFC_TRANSFORMS.prefixSuffixHeads, RFC_TRANSFORMS.triplets, "# #s #, #e #.# the #.com/#Â\xA0# of # and # in # to #\"#\">#\n#]# for # a # that #. # with #'# from # by #. The # on # as # is #ing #\n #:#ed #(# at #ly #=\"# of the #. This #,# not #er #al #='#ful #ive #less #est #ize #ous #", " !! ! , *! &! \" ! ) * * - ! # ! #!*! + ,$ ! - % . / # 0 1 . \" 2 3!* 4% ! # / 5 6 7 8 0 1 & $ 9 + : ; < ' != > ?! 4 @ 4 2 & A *# ( B C& ) % ) !*# *-% A +! *. D! %' & E *6 F G% ! *A *% H! D I!+! J!+ K +- *4! A L!*4 M N +6 O!*% +.! K *G P +%( ! G *D +D Q +# *K!*G!+D!+# +G +A +4!+% +K!+4!*D!+K!*K");
|
|
1526
|
+
function transformDictionaryWord(dst, dstOffset, src, srcOffset, wordLen, transforms, transformIndex) {
|
|
1527
|
+
let offset = dstOffset;
|
|
1528
|
+
const triplets = transforms.triplets;
|
|
1529
|
+
const prefixSuffixStorage = transforms.prefixSuffixStorage;
|
|
1530
|
+
const prefixSuffixHeads = transforms.prefixSuffixHeads;
|
|
1531
|
+
const transformOffset = 3 * transformIndex;
|
|
1532
|
+
const prefixIdx = triplets[transformOffset];
|
|
1533
|
+
const transformType = triplets[transformOffset + 1];
|
|
1534
|
+
const suffixIdx = triplets[transformOffset + 2];
|
|
1535
|
+
let prefix = prefixSuffixHeads[prefixIdx];
|
|
1536
|
+
const prefixEnd = prefixSuffixHeads[prefixIdx + 1];
|
|
1537
|
+
let suffix = prefixSuffixHeads[suffixIdx];
|
|
1538
|
+
const suffixEnd = prefixSuffixHeads[suffixIdx + 1];
|
|
1539
|
+
let omitFirst = transformType - 11;
|
|
1540
|
+
let omitLast = transformType;
|
|
1541
|
+
if (omitFirst < 1 || omitFirst > 9) omitFirst = 0;
|
|
1542
|
+
if (omitLast < 1 || omitLast > 9) omitLast = 0;
|
|
1543
|
+
while (prefix !== prefixEnd) dst[offset++] = prefixSuffixStorage[prefix++];
|
|
1544
|
+
let len = wordLen;
|
|
1545
|
+
if (omitFirst > len) omitFirst = len;
|
|
1546
|
+
let dictOffset = srcOffset + omitFirst;
|
|
1547
|
+
len -= omitFirst;
|
|
1548
|
+
len -= omitLast;
|
|
1549
|
+
let i = len;
|
|
1550
|
+
while (i > 0) {
|
|
1551
|
+
dst[offset++] = src[dictOffset++];
|
|
1552
|
+
i--;
|
|
1553
|
+
}
|
|
1554
|
+
if (transformType === 10 || transformType === 11) {
|
|
1555
|
+
let uppercaseOffset = offset - len;
|
|
1556
|
+
if (transformType === 10) len = 1;
|
|
1557
|
+
while (len > 0) {
|
|
1558
|
+
const c0 = dst[uppercaseOffset] & 255;
|
|
1559
|
+
if (c0 < 192) {
|
|
1560
|
+
if (c0 >= 97 && c0 <= 122) dst[uppercaseOffset] = dst[uppercaseOffset] ^ 32;
|
|
1561
|
+
uppercaseOffset += 1;
|
|
1562
|
+
len -= 1;
|
|
1563
|
+
} else if (c0 < 224) {
|
|
1564
|
+
dst[uppercaseOffset + 1] = dst[uppercaseOffset + 1] ^ 32;
|
|
1565
|
+
uppercaseOffset += 2;
|
|
1566
|
+
len -= 2;
|
|
1567
|
+
} else {
|
|
1568
|
+
dst[uppercaseOffset + 2] = dst[uppercaseOffset + 2] ^ 5;
|
|
1569
|
+
uppercaseOffset += 3;
|
|
1570
|
+
len -= 3;
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
} else if (transformType === 21 || transformType === 22) {
|
|
1574
|
+
let shiftOffset = offset - len;
|
|
1575
|
+
const param = transforms.params[transformIndex];
|
|
1576
|
+
let scalar = (param & 32767) + (16777216 - (param & 32768));
|
|
1577
|
+
while (len > 0) {
|
|
1578
|
+
let step = 1;
|
|
1579
|
+
const c0 = dst[shiftOffset] & 255;
|
|
1580
|
+
if (c0 < 128) {
|
|
1581
|
+
scalar += c0;
|
|
1582
|
+
dst[shiftOffset] = scalar & 127;
|
|
1583
|
+
} else if (c0 < 192) {} else if (c0 < 224) if (len >= 2) {
|
|
1584
|
+
const c1 = dst[shiftOffset + 1];
|
|
1585
|
+
scalar += c1 & 63 | (c0 & 31) << 6;
|
|
1586
|
+
dst[shiftOffset] = 192 | scalar >> 6 & 31;
|
|
1587
|
+
dst[shiftOffset + 1] = c1 & 192 | scalar & 63;
|
|
1588
|
+
step = 2;
|
|
1589
|
+
} else step = len;
|
|
1590
|
+
else if (c0 < 240) if (len >= 3) {
|
|
1591
|
+
const c1 = dst[shiftOffset + 1];
|
|
1592
|
+
const c2 = dst[shiftOffset + 2];
|
|
1593
|
+
scalar += c2 & 63 | (c1 & 63) << 6 | (c0 & 15) << 12;
|
|
1594
|
+
dst[shiftOffset] = 224 | scalar >> 12 & 15;
|
|
1595
|
+
dst[shiftOffset + 1] = c1 & 192 | scalar >> 6 & 63;
|
|
1596
|
+
dst[shiftOffset + 2] = c2 & 192 | scalar & 63;
|
|
1597
|
+
step = 3;
|
|
1598
|
+
} else step = len;
|
|
1599
|
+
else if (c0 < 248) if (len >= 4) {
|
|
1600
|
+
const c1 = dst[shiftOffset + 1];
|
|
1601
|
+
const c2 = dst[shiftOffset + 2];
|
|
1602
|
+
const c3 = dst[shiftOffset + 3];
|
|
1603
|
+
scalar += c3 & 63 | (c2 & 63) << 6 | (c1 & 63) << 12 | (c0 & 7) << 18;
|
|
1604
|
+
dst[shiftOffset] = 240 | scalar >> 18 & 7;
|
|
1605
|
+
dst[shiftOffset + 1] = c1 & 192 | scalar >> 12 & 63;
|
|
1606
|
+
dst[shiftOffset + 2] = c2 & 192 | scalar >> 6 & 63;
|
|
1607
|
+
dst[shiftOffset + 3] = c3 & 192 | scalar & 63;
|
|
1608
|
+
step = 4;
|
|
1609
|
+
} else step = len;
|
|
1610
|
+
shiftOffset += step;
|
|
1611
|
+
len -= step;
|
|
1612
|
+
if (transformType === 21) len = 0;
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
while (suffix !== suffixEnd) dst[offset++] = prefixSuffixStorage[suffix++];
|
|
1616
|
+
return offset - dstOffset;
|
|
1617
|
+
}
|
|
1618
|
+
function getNextKey(key, len) {
|
|
1619
|
+
let step = 1 << len - 1;
|
|
1620
|
+
while ((key & step) !== 0) step = step >> 1;
|
|
1621
|
+
return (key & step - 1) + step;
|
|
1622
|
+
}
|
|
1623
|
+
function replicateValue(table, offset, step, end, item) {
|
|
1624
|
+
let pos = end;
|
|
1625
|
+
while (pos > 0) {
|
|
1626
|
+
pos -= step;
|
|
1627
|
+
table[offset + pos] = item;
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
function nextTableBitSize(count, len, rootBits) {
|
|
1631
|
+
let bits = len;
|
|
1632
|
+
let left = 1 << bits - rootBits;
|
|
1633
|
+
while (bits < 15) {
|
|
1634
|
+
left -= count[bits];
|
|
1635
|
+
if (left <= 0) break;
|
|
1636
|
+
bits++;
|
|
1637
|
+
left = left << 1;
|
|
1638
|
+
}
|
|
1639
|
+
return bits - rootBits;
|
|
1640
|
+
}
|
|
1641
|
+
function buildHuffmanTable(tableGroup, tableIdx, rootBits, codeLengths, codeLengthsSize) {
|
|
1642
|
+
const tableOffset = tableGroup[tableIdx];
|
|
1643
|
+
const sorted = new Int32Array(codeLengthsSize);
|
|
1644
|
+
const count = new Int32Array(16);
|
|
1645
|
+
const offset = new Int32Array(16);
|
|
1646
|
+
for (let sym = 0; sym < codeLengthsSize; ++sym) count[codeLengths[sym]]++;
|
|
1647
|
+
offset[1] = 0;
|
|
1648
|
+
for (let len = 1; len < 15; ++len) offset[len + 1] = offset[len] + count[len];
|
|
1649
|
+
for (let sym = 0; sym < codeLengthsSize; ++sym) if (codeLengths[sym] !== 0) sorted[offset[codeLengths[sym]]++] = sym;
|
|
1650
|
+
let tableBits = rootBits;
|
|
1651
|
+
let tableSize = 1 << tableBits;
|
|
1652
|
+
let totalSize = tableSize;
|
|
1653
|
+
if (offset[15] === 1) {
|
|
1654
|
+
for (let k = 0; k < totalSize; ++k) tableGroup[tableOffset + k] = sorted[0];
|
|
1655
|
+
return totalSize;
|
|
1656
|
+
}
|
|
1657
|
+
let key = 0;
|
|
1658
|
+
let symbol = 0;
|
|
1659
|
+
let step = 1;
|
|
1660
|
+
for (let len = 1; len <= rootBits; ++len) {
|
|
1661
|
+
step = step << 1;
|
|
1662
|
+
while (count[len] > 0) {
|
|
1663
|
+
replicateValue(tableGroup, tableOffset + key, step, tableSize, len << 16 | sorted[symbol++]);
|
|
1664
|
+
key = getNextKey(key, len);
|
|
1665
|
+
count[len]--;
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
const mask = totalSize - 1;
|
|
1669
|
+
let low = -1;
|
|
1670
|
+
let currentOffset = tableOffset;
|
|
1671
|
+
step = 1;
|
|
1672
|
+
for (let len = rootBits + 1; len <= 15; ++len) {
|
|
1673
|
+
step = step << 1;
|
|
1674
|
+
while (count[len] > 0) {
|
|
1675
|
+
if ((key & mask) !== low) {
|
|
1676
|
+
currentOffset += tableSize;
|
|
1677
|
+
tableBits = nextTableBitSize(count, len, rootBits);
|
|
1678
|
+
tableSize = 1 << tableBits;
|
|
1679
|
+
totalSize += tableSize;
|
|
1680
|
+
low = key & mask;
|
|
1681
|
+
tableGroup[tableOffset + low] = tableBits + rootBits << 16 | currentOffset - tableOffset - low;
|
|
1682
|
+
}
|
|
1683
|
+
replicateValue(tableGroup, currentOffset + (key >> rootBits), step, tableSize, len - rootBits << 16 | sorted[symbol++]);
|
|
1684
|
+
key = getNextKey(key, len);
|
|
1685
|
+
count[len]--;
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
return totalSize;
|
|
1689
|
+
}
|
|
1690
|
+
function readMoreInput(s) {
|
|
1691
|
+
if (s.endOfStreamReached !== 0) {
|
|
1692
|
+
if (halfAvailable(s) >= -2) return 0;
|
|
1693
|
+
return makeError(s, -16);
|
|
1694
|
+
}
|
|
1695
|
+
const readOffset = s.halfOffset << 1;
|
|
1696
|
+
let bytesInBuffer = 4096 - readOffset;
|
|
1697
|
+
s.byteBuffer.copyWithin(0, readOffset, 4096);
|
|
1698
|
+
s.halfOffset = 0;
|
|
1699
|
+
while (bytesInBuffer < 4096) {
|
|
1700
|
+
const spaceLeft = 4096 - bytesInBuffer;
|
|
1701
|
+
const len = readInput(s, s.byteBuffer, bytesInBuffer, spaceLeft);
|
|
1702
|
+
if (len < -1) return len;
|
|
1703
|
+
if (len <= 0) {
|
|
1704
|
+
s.endOfStreamReached = 1;
|
|
1705
|
+
s.tailBytes = bytesInBuffer;
|
|
1706
|
+
bytesInBuffer += 1;
|
|
1707
|
+
break;
|
|
1708
|
+
}
|
|
1709
|
+
bytesInBuffer += len;
|
|
1710
|
+
}
|
|
1711
|
+
bytesToNibbles(s, bytesInBuffer);
|
|
1712
|
+
return 0;
|
|
1713
|
+
}
|
|
1714
|
+
function checkHealth(s, endOfStream) {
|
|
1715
|
+
if (s.endOfStreamReached === 0) return 0;
|
|
1716
|
+
const byteOffset = (s.halfOffset << 1) + (s.bitOffset + 7 >> 3) - 4;
|
|
1717
|
+
if (byteOffset > s.tailBytes) return makeError(s, -13);
|
|
1718
|
+
if (endOfStream !== 0 && byteOffset !== s.tailBytes) return makeError(s, -17);
|
|
1719
|
+
return 0;
|
|
1720
|
+
}
|
|
1721
|
+
function readFewBits(s, n) {
|
|
1722
|
+
const v = s.accumulator32 >>> s.bitOffset & (1 << n) - 1;
|
|
1723
|
+
s.bitOffset += n;
|
|
1724
|
+
return v;
|
|
1725
|
+
}
|
|
1726
|
+
function readManyBits(s, n) {
|
|
1727
|
+
const low = readFewBits(s, 16);
|
|
1728
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
1729
|
+
s.bitOffset -= 16;
|
|
1730
|
+
return low | readFewBits(s, n - 16) << 16;
|
|
1731
|
+
}
|
|
1732
|
+
function initBitReader(s) {
|
|
1733
|
+
s.byteBuffer = new Int8Array(4160);
|
|
1734
|
+
s.byteBuffer16 = new Uint16Array(s.byteBuffer.buffer, s.byteBuffer.byteOffset, 2080);
|
|
1735
|
+
s.accumulator32 = 0;
|
|
1736
|
+
s.shortBuffer = new Int16Array(2080);
|
|
1737
|
+
s.bitOffset = 32;
|
|
1738
|
+
s.halfOffset = 2048;
|
|
1739
|
+
s.endOfStreamReached = 0;
|
|
1740
|
+
return prepare(s);
|
|
1741
|
+
}
|
|
1742
|
+
function prepare(s) {
|
|
1743
|
+
if (s.halfOffset > 2030) {
|
|
1744
|
+
const result = readMoreInput(s);
|
|
1745
|
+
if (result !== 0) return result;
|
|
1746
|
+
}
|
|
1747
|
+
let health = checkHealth(s, 0);
|
|
1748
|
+
if (health !== 0) return health;
|
|
1749
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
1750
|
+
s.bitOffset -= 16;
|
|
1751
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
1752
|
+
s.bitOffset -= 16;
|
|
1753
|
+
return 0;
|
|
1754
|
+
}
|
|
1755
|
+
function reload(s) {
|
|
1756
|
+
if (s.bitOffset === 32) return prepare(s);
|
|
1757
|
+
return 0;
|
|
1758
|
+
}
|
|
1759
|
+
function jumpToByteBoundary(s) {
|
|
1760
|
+
const padding = 32 - s.bitOffset & 7;
|
|
1761
|
+
if (padding !== 0) {
|
|
1762
|
+
if (readFewBits(s, padding) !== 0) return makeError(s, -5);
|
|
1763
|
+
}
|
|
1764
|
+
return 0;
|
|
1765
|
+
}
|
|
1766
|
+
function halfAvailable(s) {
|
|
1767
|
+
let limit = 2048;
|
|
1768
|
+
if (s.endOfStreamReached !== 0) limit = s.tailBytes + 1 >> 1;
|
|
1769
|
+
return limit - s.halfOffset;
|
|
1770
|
+
}
|
|
1771
|
+
function copyRawBytes(s, data, offset, length) {
|
|
1772
|
+
let pos = offset;
|
|
1773
|
+
let len = length;
|
|
1774
|
+
if ((s.bitOffset & 7) !== 0) return makeError(s, -30);
|
|
1775
|
+
while (s.bitOffset !== 32 && len !== 0) {
|
|
1776
|
+
data[pos++] = s.accumulator32 >>> s.bitOffset;
|
|
1777
|
+
s.bitOffset += 8;
|
|
1778
|
+
len--;
|
|
1779
|
+
}
|
|
1780
|
+
if (len === 0) return 0;
|
|
1781
|
+
const copyNibbles = Math.min(halfAvailable(s), len >> 1);
|
|
1782
|
+
if (copyNibbles > 0) {
|
|
1783
|
+
const readOffset = s.halfOffset << 1;
|
|
1784
|
+
const delta = copyNibbles << 1;
|
|
1785
|
+
data.set(s.byteBuffer.subarray(readOffset, readOffset + delta), pos);
|
|
1786
|
+
pos += delta;
|
|
1787
|
+
len -= delta;
|
|
1788
|
+
s.halfOffset += copyNibbles;
|
|
1789
|
+
}
|
|
1790
|
+
if (len === 0) return 0;
|
|
1791
|
+
if (halfAvailable(s) > 0) {
|
|
1792
|
+
if (s.bitOffset >= 16) {
|
|
1793
|
+
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
|
|
1794
|
+
s.bitOffset -= 16;
|
|
1795
|
+
}
|
|
1796
|
+
while (len !== 0) {
|
|
1797
|
+
data[pos++] = s.accumulator32 >>> s.bitOffset;
|
|
1798
|
+
s.bitOffset += 8;
|
|
1799
|
+
len--;
|
|
1800
|
+
}
|
|
1801
|
+
return checkHealth(s, 0);
|
|
1802
|
+
}
|
|
1803
|
+
while (len > 0) {
|
|
1804
|
+
const chunkLen = readInput(s, data, pos, len);
|
|
1805
|
+
if (chunkLen < -1) return chunkLen;
|
|
1806
|
+
if (chunkLen <= 0) return makeError(s, -16);
|
|
1807
|
+
pos += chunkLen;
|
|
1808
|
+
len -= chunkLen;
|
|
1809
|
+
}
|
|
1810
|
+
return 0;
|
|
1811
|
+
}
|
|
1812
|
+
function bytesToNibbles(s, byteLen) {
|
|
1813
|
+
const halfLen = byteLen >> 1;
|
|
1814
|
+
const shortBuffer = s.shortBuffer;
|
|
1815
|
+
if (IS_LITTLE_ENDIAN) {
|
|
1816
|
+
shortBuffer.set(s.byteBuffer16.subarray(0, halfLen));
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
const byteBuffer = s.byteBuffer;
|
|
1820
|
+
for (let i = 0; i < halfLen; ++i) shortBuffer[i] = byteBuffer[i * 2] & 255 | (byteBuffer[i * 2 + 1] & 255) << 8;
|
|
1821
|
+
}
|
|
1822
|
+
const LOOKUP = new Int32Array(2048);
|
|
1823
|
+
function unpackLookupTable(lookup, utfMap, utfRle) {
|
|
1824
|
+
for (let i = 0; i < 256; ++i) {
|
|
1825
|
+
lookup[i] = i & 63;
|
|
1826
|
+
lookup[512 + i] = i >> 2;
|
|
1827
|
+
lookup[1792 + i] = 2 + (i >> 6);
|
|
1828
|
+
}
|
|
1829
|
+
for (let i = 0; i < 128; ++i) lookup[1024 + i] = 4 * (utfMap.charCodeAt(i) - 32);
|
|
1830
|
+
for (let i = 0; i < 64; ++i) {
|
|
1831
|
+
lookup[1152 + i] = i & 1;
|
|
1832
|
+
lookup[1216 + i] = 2 + (i & 1);
|
|
1833
|
+
}
|
|
1834
|
+
let offset = 1280;
|
|
1835
|
+
for (let k = 0; k < 19; ++k) {
|
|
1836
|
+
const value = k & 3;
|
|
1837
|
+
const rep = utfRle.charCodeAt(k) - 32;
|
|
1838
|
+
for (let i = 0; i < rep; ++i) lookup[offset++] = value;
|
|
1839
|
+
}
|
|
1840
|
+
for (let i = 0; i < 16; ++i) {
|
|
1841
|
+
lookup[1792 + i] = 1;
|
|
1842
|
+
lookup[2032 + i] = 6;
|
|
1843
|
+
}
|
|
1844
|
+
lookup[1792] = 0;
|
|
1845
|
+
lookup[2047] = 7;
|
|
1846
|
+
for (let i = 0; i < 256; ++i) lookup[1536 + i] = lookup[1792 + i] << 3;
|
|
1847
|
+
}
|
|
1848
|
+
unpackLookupTable(LOOKUP, " !! ! \"#$##%#$&'##(#)#++++++++++((&*'##,---,---,-----,-----,-----&#'###.///.///./////./////./////&#'# ", "A/* ': & : $ @");
|
|
1849
|
+
var State = class {
|
|
1850
|
+
constructor() {
|
|
1851
|
+
this.ringBuffer = new Uint8Array(0);
|
|
1852
|
+
this.contextModes = new Int8Array(0);
|
|
1853
|
+
this.contextMap = new Int8Array(0);
|
|
1854
|
+
this.distContextMap = new Int8Array(0);
|
|
1855
|
+
this.distExtraBits = new Int8Array(0);
|
|
1856
|
+
this.output = new Uint8Array(0);
|
|
1857
|
+
this.byteBuffer = new Int8Array(0);
|
|
1858
|
+
this.byteBuffer16 = new Uint16Array(0);
|
|
1859
|
+
this.shortBuffer = new Int16Array(0);
|
|
1860
|
+
this.intBuffer = new Int32Array(0);
|
|
1861
|
+
this.rings = new Int32Array(0);
|
|
1862
|
+
this.blockTrees = new Int32Array(0);
|
|
1863
|
+
this.literalTreeGroup = new Int32Array(0);
|
|
1864
|
+
this.commandTreeGroup = new Int32Array(0);
|
|
1865
|
+
this.distanceTreeGroup = new Int32Array(0);
|
|
1866
|
+
this.distOffset = new Int32Array(0);
|
|
1867
|
+
this.accumulator64 = 0;
|
|
1868
|
+
this.runningState = 0;
|
|
1869
|
+
this.nextRunningState = 0;
|
|
1870
|
+
this.accumulator32 = 0;
|
|
1871
|
+
this.bitOffset = 0;
|
|
1872
|
+
this.halfOffset = 0;
|
|
1873
|
+
this.tailBytes = 0;
|
|
1874
|
+
this.endOfStreamReached = 0;
|
|
1875
|
+
this.metaBlockLength = 0;
|
|
1876
|
+
this.inputEnd = 0;
|
|
1877
|
+
this.isUncompressed = 0;
|
|
1878
|
+
this.isMetadata = 0;
|
|
1879
|
+
this.literalBlockLength = 0;
|
|
1880
|
+
this.numLiteralBlockTypes = 0;
|
|
1881
|
+
this.commandBlockLength = 0;
|
|
1882
|
+
this.numCommandBlockTypes = 0;
|
|
1883
|
+
this.distanceBlockLength = 0;
|
|
1884
|
+
this.numDistanceBlockTypes = 0;
|
|
1885
|
+
this.pos = 0;
|
|
1886
|
+
this.maxDistance = 0;
|
|
1887
|
+
this.distRbIdx = 0;
|
|
1888
|
+
this.trivialLiteralContext = 0;
|
|
1889
|
+
this.literalTreeIdx = 0;
|
|
1890
|
+
this.commandTreeIdx = 0;
|
|
1891
|
+
this.j = 0;
|
|
1892
|
+
this.insertLength = 0;
|
|
1893
|
+
this.contextMapSlice = 0;
|
|
1894
|
+
this.distContextMapSlice = 0;
|
|
1895
|
+
this.contextLookupOffset1 = 0;
|
|
1896
|
+
this.contextLookupOffset2 = 0;
|
|
1897
|
+
this.distanceCode = 0;
|
|
1898
|
+
this.numDirectDistanceCodes = 0;
|
|
1899
|
+
this.distancePostfixBits = 0;
|
|
1900
|
+
this.distance = 0;
|
|
1901
|
+
this.copyLength = 0;
|
|
1902
|
+
this.maxBackwardDistance = 0;
|
|
1903
|
+
this.maxRingBufferSize = 0;
|
|
1904
|
+
this.ringBufferSize = 0;
|
|
1905
|
+
this.expectedTotalSize = 0;
|
|
1906
|
+
this.outputOffset = 0;
|
|
1907
|
+
this.outputLength = 0;
|
|
1908
|
+
this.outputUsed = 0;
|
|
1909
|
+
this.ringBufferBytesWritten = 0;
|
|
1910
|
+
this.ringBufferBytesReady = 0;
|
|
1911
|
+
this.isEager = 0;
|
|
1912
|
+
this.isLargeWindow = 0;
|
|
1913
|
+
this.cdNumChunks = 0;
|
|
1914
|
+
this.cdTotalSize = 0;
|
|
1915
|
+
this.cdBrIndex = 0;
|
|
1916
|
+
this.cdBrOffset = 0;
|
|
1917
|
+
this.cdBrLength = 0;
|
|
1918
|
+
this.cdBrCopied = 0;
|
|
1919
|
+
this.cdChunks = new Array(0);
|
|
1920
|
+
this.cdChunkOffsets = new Int32Array(0);
|
|
1921
|
+
this.cdBlockBits = 0;
|
|
1922
|
+
this.cdBlockMap = new Int8Array(0);
|
|
1923
|
+
this.input = new InputStream(new Int8Array(0));
|
|
1924
|
+
this.ringBuffer = new Uint8Array(0);
|
|
1925
|
+
this.rings = new Int32Array(10);
|
|
1926
|
+
this.rings[0] = 16;
|
|
1927
|
+
this.rings[1] = 15;
|
|
1928
|
+
this.rings[2] = 11;
|
|
1929
|
+
this.rings[3] = 4;
|
|
1930
|
+
}
|
|
1931
|
+
};
|
|
1932
|
+
let data = new Int8Array(0);
|
|
1933
|
+
const offsets = new Int32Array(32);
|
|
1934
|
+
const sizeBits = new Int32Array(32);
|
|
1935
|
+
let dictionaryInitialized = false;
|
|
1936
|
+
function ensureDictionary() {
|
|
1937
|
+
if (dictionaryInitialized) return;
|
|
1938
|
+
dictionaryInitialized = true;
|
|
1939
|
+
const binary = atob(compressedDictionary);
|
|
1940
|
+
const compressed = new Uint8Array(binary.length);
|
|
1941
|
+
for (let i = 0; i < binary.length; i++) compressed[i] = binary.charCodeAt(i);
|
|
1942
|
+
const dict = brotliDecode$1(compressed);
|
|
1943
|
+
setData(new Int8Array(dict.buffer, dict.byteOffset, dict.byteLength), new Int32Array([
|
|
1944
|
+
0,
|
|
1945
|
+
0,
|
|
1946
|
+
0,
|
|
1947
|
+
0,
|
|
1948
|
+
10,
|
|
1949
|
+
10,
|
|
1950
|
+
11,
|
|
1951
|
+
11,
|
|
1952
|
+
10,
|
|
1953
|
+
10,
|
|
1954
|
+
10,
|
|
1955
|
+
10,
|
|
1956
|
+
10,
|
|
1957
|
+
9,
|
|
1958
|
+
9,
|
|
1959
|
+
8,
|
|
1960
|
+
7,
|
|
1961
|
+
7,
|
|
1962
|
+
8,
|
|
1963
|
+
7,
|
|
1964
|
+
7,
|
|
1965
|
+
6,
|
|
1966
|
+
6,
|
|
1967
|
+
5,
|
|
1968
|
+
5
|
|
1969
|
+
]));
|
|
1970
|
+
}
|
|
1971
|
+
function setData(newData, newSizeBits) {
|
|
1972
|
+
const dictionaryOffsets = offsets;
|
|
1973
|
+
const dictionarySizeBits = sizeBits;
|
|
1974
|
+
for (let i = 0; i < newSizeBits.length; ++i) dictionarySizeBits[i] = newSizeBits[i];
|
|
1975
|
+
let pos = 0;
|
|
1976
|
+
for (let i = 0; i < newSizeBits.length; ++i) {
|
|
1977
|
+
dictionaryOffsets[i] = pos;
|
|
1978
|
+
const bits = dictionarySizeBits[i];
|
|
1979
|
+
if (bits !== 0) pos += i << (bits & 31);
|
|
1980
|
+
}
|
|
1981
|
+
for (let i = newSizeBits.length; i < 32; ++i) dictionaryOffsets[i] = pos;
|
|
1982
|
+
data = newData;
|
|
1983
|
+
}
|
|
1984
|
+
var InputStream = class {
|
|
1985
|
+
constructor(data) {
|
|
1986
|
+
this.data = new Uint8Array(0);
|
|
1987
|
+
this.offset = 0;
|
|
1988
|
+
this.data = data;
|
|
1989
|
+
}
|
|
1990
|
+
};
|
|
1991
|
+
function readInput(s, dst, offset, length) {
|
|
1992
|
+
if (s.input === null) return -1;
|
|
1993
|
+
const src = s.input;
|
|
1994
|
+
const end = Math.min(src.offset + length, src.data.length);
|
|
1995
|
+
const bytesRead = end - src.offset;
|
|
1996
|
+
dst.set(src.data.subarray(src.offset, end), offset);
|
|
1997
|
+
src.offset += bytesRead;
|
|
1998
|
+
return bytesRead;
|
|
1999
|
+
}
|
|
2000
|
+
function closeInput(s) {
|
|
2001
|
+
s.input = new InputStream(new Int8Array(0));
|
|
2002
|
+
}
|
|
2003
|
+
function toUtf8Runes(src) {
|
|
2004
|
+
const n = src.length;
|
|
2005
|
+
const result = new Int32Array(n);
|
|
2006
|
+
for (let i = 0; i < n; ++i) result[i] = src.charCodeAt(i);
|
|
2007
|
+
return result;
|
|
2008
|
+
}
|
|
2009
|
+
function makeError(s, code) {
|
|
2010
|
+
if (code >= 0) return code;
|
|
2011
|
+
if (s.runningState >= 0) s.runningState = code;
|
|
2012
|
+
throw new Error("Brotli error code: " + code);
|
|
2013
|
+
}
|
|
2014
|
+
/**
|
|
2015
|
+
* Decodes brotli stream.
|
|
2016
|
+
*/
|
|
2017
|
+
function brotliDecode$1(bytes, options) {
|
|
2018
|
+
const s = new State();
|
|
2019
|
+
s.input = new InputStream(bytes);
|
|
2020
|
+
initState(s);
|
|
2021
|
+
if (options) {
|
|
2022
|
+
const customDictionary = options.customDictionary;
|
|
2023
|
+
if (customDictionary) attachDictionaryChunk(s, customDictionary);
|
|
2024
|
+
}
|
|
2025
|
+
const outputSize = options?.outputSize;
|
|
2026
|
+
if (outputSize !== void 0 && outputSize > 0) {
|
|
2027
|
+
const result = new Uint8Array(outputSize);
|
|
2028
|
+
s.output = result;
|
|
2029
|
+
s.outputOffset = 0;
|
|
2030
|
+
s.outputLength = outputSize;
|
|
2031
|
+
s.outputUsed = 0;
|
|
2032
|
+
decompress(s);
|
|
2033
|
+
close(s);
|
|
2034
|
+
closeInput(s);
|
|
2035
|
+
return result;
|
|
2036
|
+
}
|
|
2037
|
+
let totalOutput = 0;
|
|
2038
|
+
const chunks = [];
|
|
2039
|
+
while (true) {
|
|
2040
|
+
const chunk = new Uint8Array(16384);
|
|
2041
|
+
chunks.push(chunk);
|
|
2042
|
+
s.output = chunk;
|
|
2043
|
+
s.outputOffset = 0;
|
|
2044
|
+
s.outputLength = 16384;
|
|
2045
|
+
s.outputUsed = 0;
|
|
2046
|
+
decompress(s);
|
|
2047
|
+
totalOutput += s.outputUsed;
|
|
2048
|
+
if (s.outputUsed < 16384) break;
|
|
2049
|
+
}
|
|
2050
|
+
close(s);
|
|
2051
|
+
closeInput(s);
|
|
2052
|
+
const result = new Uint8Array(totalOutput);
|
|
2053
|
+
let offset = 0;
|
|
2054
|
+
for (let i = 0; i < chunks.length; ++i) {
|
|
2055
|
+
const chunk = chunks[i];
|
|
2056
|
+
const len = Math.min(totalOutput, offset + 16384) - offset;
|
|
2057
|
+
if (len < 16384) result.set(chunk.subarray(0, len), offset);
|
|
2058
|
+
else result.set(chunk, offset);
|
|
2059
|
+
offset += len;
|
|
2060
|
+
}
|
|
2061
|
+
return result;
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
//#endregion
|
|
2065
|
+
//#region src/decode/decode.ts
|
|
2066
|
+
function decodeWindowBits(br) {
|
|
2067
|
+
if (br.readBits(1) === 0) return 16;
|
|
2068
|
+
let n = br.readBits(3);
|
|
2069
|
+
if (n > 0) return 17 + n;
|
|
2070
|
+
n = br.readBits(3);
|
|
2071
|
+
if (n > 0) return 8 + n;
|
|
2072
|
+
return 17;
|
|
2073
|
+
}
|
|
2074
|
+
function decodeMetaBlockLength(br) {
|
|
2075
|
+
const out = {
|
|
2076
|
+
meta_block_length: 0,
|
|
2077
|
+
input_end: 0,
|
|
2078
|
+
is_uncompressed: 0,
|
|
2079
|
+
is_metadata: false
|
|
2080
|
+
};
|
|
2081
|
+
out.input_end = br.readBits(1);
|
|
2082
|
+
if (out.input_end && br.readBits(1)) return out;
|
|
2083
|
+
const size_nibbles = br.readBits(2) + 4;
|
|
2084
|
+
if (size_nibbles === 7) {
|
|
2085
|
+
out.is_metadata = true;
|
|
2086
|
+
if (br.readBits(1) !== 0) throw new Error("Invalid reserved bit");
|
|
2087
|
+
const size_bytes = br.readBits(2);
|
|
2088
|
+
if (size_bytes === 0) return out;
|
|
2089
|
+
for (let i = 0; i < size_bytes; i++) {
|
|
2090
|
+
const next_byte = br.readBits(8);
|
|
2091
|
+
if (i + 1 === size_bytes && size_bytes > 1 && next_byte === 0) throw new Error("Invalid size byte");
|
|
2092
|
+
out.meta_block_length |= next_byte << i * 8;
|
|
2093
|
+
}
|
|
2094
|
+
} else for (let i = 0; i < size_nibbles; ++i) {
|
|
2095
|
+
const next_nibble = br.readBits(4);
|
|
2096
|
+
if (i + 1 === size_nibbles && size_nibbles > 4 && next_nibble === 0) throw new Error("Invalid size nibble");
|
|
2097
|
+
out.meta_block_length |= next_nibble << i * 4;
|
|
2098
|
+
}
|
|
2099
|
+
++out.meta_block_length;
|
|
2100
|
+
if (!out.input_end && !out.is_metadata) out.is_uncompressed = br.readBits(1);
|
|
2101
|
+
return out;
|
|
2102
|
+
}
|
|
2103
|
+
function brotliDecodedSize(buffer) {
|
|
2104
|
+
const br = new BrotliBitReader(new BrotliInput(buffer));
|
|
2105
|
+
decodeWindowBits(br);
|
|
2106
|
+
const out = decodeMetaBlockLength(br);
|
|
2107
|
+
if (out.input_end) return out.meta_block_length;
|
|
2108
|
+
return -1;
|
|
2109
|
+
}
|
|
2110
|
+
function brotliDecode(buffer, options) {
|
|
2111
|
+
let output_size;
|
|
2112
|
+
let maxOutputSize;
|
|
2113
|
+
let customDictionary;
|
|
2114
|
+
if (typeof options === "number") output_size = options;
|
|
2115
|
+
else {
|
|
2116
|
+
maxOutputSize = options?.maxOutputSize;
|
|
2117
|
+
const dict = options?.customDictionary;
|
|
2118
|
+
if (dict) customDictionary = dict instanceof Uint8Array ? dict : new Uint8Array(dict.buffer, dict.byteOffset, dict.byteLength);
|
|
2119
|
+
}
|
|
2120
|
+
if (output_size === void 0) {
|
|
2121
|
+
const estimatedSize = brotliDecodedSize(buffer);
|
|
2122
|
+
if (estimatedSize > 0) output_size = estimatedSize;
|
|
2123
|
+
}
|
|
2124
|
+
if (maxOutputSize !== void 0 && output_size !== void 0 && output_size > maxOutputSize) throw new Error(`Decompressed size ${output_size} exceeds limit ${maxOutputSize}`);
|
|
2125
|
+
const decoded = brotliDecode$1(buffer, {
|
|
2126
|
+
customDictionary,
|
|
2127
|
+
outputSize: output_size
|
|
2128
|
+
});
|
|
2129
|
+
if (maxOutputSize !== void 0 && decoded.length > maxOutputSize) throw new Error(`Decompressed size ${decoded.length} exceeds limit ${maxOutputSize}`);
|
|
2130
|
+
return decoded;
|
|
2131
|
+
}
|
|
2132
|
+
setDecoder(brotliDecode);
|
|
2133
|
+
|
|
2134
|
+
//#endregion
|
|
2135
|
+
//#region src/encode/bit-writer.ts
|
|
2136
|
+
var BitWriter = class {
|
|
2137
|
+
constructor(initialSize = 4096) {
|
|
2138
|
+
this.buffer = new Uint8Array(initialSize);
|
|
2139
|
+
this.pos = 0;
|
|
2140
|
+
this.flushedBytePos = 0;
|
|
2141
|
+
}
|
|
2142
|
+
ensureCapacity(bits) {
|
|
2143
|
+
const bytesNeeded = (this.pos + bits + 7 >>> 3) + 1;
|
|
2144
|
+
if (bytesNeeded > this.buffer.length) {
|
|
2145
|
+
const newSize = Math.max(this.buffer.length * 2, bytesNeeded);
|
|
2146
|
+
const newBuffer = new Uint8Array(newSize);
|
|
2147
|
+
newBuffer.set(this.buffer);
|
|
2148
|
+
this.buffer = newBuffer;
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
writeBits(nBits, value) {
|
|
2152
|
+
this.ensureCapacity(nBits);
|
|
2153
|
+
const bytePos = this.pos >>> 3;
|
|
2154
|
+
const bitOffset = this.pos & 7;
|
|
2155
|
+
let v = this.buffer[bytePos] | 0;
|
|
2156
|
+
v |= value << bitOffset;
|
|
2157
|
+
this.buffer[bytePos] = v & 255;
|
|
2158
|
+
let bitsWritten = 8 - bitOffset;
|
|
2159
|
+
let remaining = value >>> bitsWritten;
|
|
2160
|
+
let pos = bytePos + 1;
|
|
2161
|
+
while (bitsWritten < nBits) {
|
|
2162
|
+
this.buffer[pos++] = remaining & 255;
|
|
2163
|
+
remaining >>>= 8;
|
|
2164
|
+
bitsWritten += 8;
|
|
2165
|
+
}
|
|
2166
|
+
this.pos += nBits;
|
|
2167
|
+
}
|
|
2168
|
+
writeBitsLong(nBits, value) {
|
|
2169
|
+
if (nBits <= 25) {
|
|
2170
|
+
this.writeBits(nBits, Number(value));
|
|
2171
|
+
return;
|
|
2172
|
+
}
|
|
2173
|
+
this.ensureCapacity(nBits);
|
|
2174
|
+
const bytePos = this.pos >>> 3;
|
|
2175
|
+
const bitOffset = this.pos & 7;
|
|
2176
|
+
let v = value << BigInt(bitOffset);
|
|
2177
|
+
const bytesToWrite = nBits + bitOffset + 7 >>> 3;
|
|
2178
|
+
this.buffer[bytePos] |= Number(v & 255n);
|
|
2179
|
+
v >>= 8n;
|
|
2180
|
+
for (let i = 1; i < bytesToWrite; i++) {
|
|
2181
|
+
this.buffer[bytePos + i] = Number(v & 255n);
|
|
2182
|
+
v >>= 8n;
|
|
2183
|
+
}
|
|
2184
|
+
this.pos += nBits;
|
|
2185
|
+
}
|
|
2186
|
+
writeBit(bit) {
|
|
2187
|
+
this.writeBits(1, bit & 1);
|
|
2188
|
+
}
|
|
2189
|
+
writeByte(byte) {
|
|
2190
|
+
if ((this.pos & 7) !== 0) throw new Error("BitWriter not byte-aligned");
|
|
2191
|
+
this.ensureCapacity(8);
|
|
2192
|
+
this.buffer[this.pos >>> 3] = byte & 255;
|
|
2193
|
+
this.pos += 8;
|
|
2194
|
+
}
|
|
2195
|
+
writeBytes(bytes) {
|
|
2196
|
+
if ((this.pos & 7) !== 0) throw new Error("BitWriter not byte-aligned");
|
|
2197
|
+
this.ensureCapacity(bytes.length * 8);
|
|
2198
|
+
this.buffer.set(bytes, this.pos >>> 3);
|
|
2199
|
+
this.pos += bytes.length * 8;
|
|
2200
|
+
}
|
|
2201
|
+
alignToByte() {
|
|
2202
|
+
const padding = 8 - (this.pos & 7) & 7;
|
|
2203
|
+
if (padding > 0) this.writeBits(padding, 0);
|
|
2204
|
+
return padding;
|
|
2205
|
+
}
|
|
2206
|
+
get bytePos() {
|
|
2207
|
+
return this.pos >>> 3;
|
|
2208
|
+
}
|
|
2209
|
+
get bitOffset() {
|
|
2210
|
+
return this.pos & 7;
|
|
2211
|
+
}
|
|
2212
|
+
reset() {
|
|
2213
|
+
this.pos = 0;
|
|
2214
|
+
this.flushedBytePos = 0;
|
|
2215
|
+
this.buffer.fill(0);
|
|
2216
|
+
}
|
|
2217
|
+
takeBytes() {
|
|
2218
|
+
const end = this.pos >>> 3;
|
|
2219
|
+
if (end <= this.flushedBytePos) return new Uint8Array(0);
|
|
2220
|
+
const out = this.buffer.slice(this.flushedBytePos, end);
|
|
2221
|
+
this.flushedBytePos = end;
|
|
2222
|
+
return out;
|
|
2223
|
+
}
|
|
2224
|
+
finish() {
|
|
2225
|
+
const byteLength = this.pos + 7 >>> 3;
|
|
2226
|
+
return this.buffer.slice(0, byteLength);
|
|
2227
|
+
}
|
|
2228
|
+
prepareStorage() {
|
|
2229
|
+
if ((this.pos & 7) !== 0) throw new Error("prepareStorage requires byte alignment");
|
|
2230
|
+
this.ensureCapacity(8);
|
|
2231
|
+
this.buffer[this.pos >>> 3] = 0;
|
|
2232
|
+
}
|
|
2233
|
+
};
|
|
2234
|
+
function encodeWindowBits(lgwin, largeWindow) {
|
|
2235
|
+
if (largeWindow) return {
|
|
2236
|
+
value: (lgwin & 63) << 8 | 17,
|
|
2237
|
+
bits: 14
|
|
2238
|
+
};
|
|
2239
|
+
if (lgwin === 16) return {
|
|
2240
|
+
value: 0,
|
|
2241
|
+
bits: 1
|
|
2242
|
+
};
|
|
2243
|
+
else if (lgwin === 17) return {
|
|
2244
|
+
value: 1,
|
|
2245
|
+
bits: 7
|
|
2246
|
+
};
|
|
2247
|
+
else if (lgwin > 17 && lgwin <= 24) return {
|
|
2248
|
+
value: lgwin - 17 << 1 | 1,
|
|
2249
|
+
bits: 4
|
|
2250
|
+
};
|
|
2251
|
+
else return {
|
|
2252
|
+
value: lgwin - 8 << 4 | 1,
|
|
2253
|
+
bits: 7
|
|
2254
|
+
};
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
//#endregion
|
|
2258
|
+
//#region src/encode/enc-constants.ts
|
|
2259
|
+
const FAST_ONE_PASS_COMPRESSION_QUALITY = 0;
|
|
2260
|
+
const FAST_TWO_PASS_COMPRESSION_QUALITY = 1;
|
|
2261
|
+
const ZOPFLIFICATION_QUALITY = 10;
|
|
2262
|
+
const HQ_ZOPFLIFICATION_QUALITY = 11;
|
|
2263
|
+
const MIN_QUALITY = 0;
|
|
2264
|
+
const MAX_QUALITY = 11;
|
|
2265
|
+
const DEFAULT_QUALITY = 11;
|
|
2266
|
+
const MAX_QUALITY_FOR_STATIC_ENTROPY_CODES = 2;
|
|
2267
|
+
const MIN_QUALITY_FOR_BLOCK_SPLIT = 4;
|
|
2268
|
+
const MIN_WINDOW_BITS = 10;
|
|
2269
|
+
const MAX_WINDOW_BITS = 24;
|
|
2270
|
+
const LARGE_MAX_WINDOW_BITS = 30;
|
|
2271
|
+
const DEFAULT_WINDOW_BITS = 22;
|
|
2272
|
+
const MIN_INPUT_BLOCK_BITS = 16;
|
|
2273
|
+
const MAX_INPUT_BLOCK_BITS = 24;
|
|
2274
|
+
const MAX_ZOPFLI_LEN_QUALITY_10 = 150;
|
|
2275
|
+
const MAX_ZOPFLI_LEN_QUALITY_11 = 325;
|
|
2276
|
+
let HasherType = /* @__PURE__ */ function(HasherType) {
|
|
2277
|
+
HasherType[HasherType["NONE"] = 0] = "NONE";
|
|
2278
|
+
HasherType[HasherType["H01"] = 1] = "H01";
|
|
2279
|
+
HasherType[HasherType["H02"] = 2] = "H02";
|
|
2280
|
+
HasherType[HasherType["H03"] = 3] = "H03";
|
|
2281
|
+
HasherType[HasherType["H04"] = 4] = "H04";
|
|
2282
|
+
HasherType[HasherType["H05"] = 5] = "H05";
|
|
2283
|
+
HasherType[HasherType["H06"] = 6] = "H06";
|
|
2284
|
+
HasherType[HasherType["H10"] = 10] = "H10";
|
|
2285
|
+
HasherType[HasherType["H35"] = 35] = "H35";
|
|
2286
|
+
HasherType[HasherType["H40"] = 40] = "H40";
|
|
2287
|
+
HasherType[HasherType["H41"] = 41] = "H41";
|
|
2288
|
+
HasherType[HasherType["H42"] = 42] = "H42";
|
|
2289
|
+
HasherType[HasherType["H54"] = 54] = "H54";
|
|
2290
|
+
HasherType[HasherType["H55"] = 55] = "H55";
|
|
2291
|
+
HasherType[HasherType["H58"] = 58] = "H58";
|
|
2292
|
+
HasherType[HasherType["H65"] = 65] = "H65";
|
|
2293
|
+
HasherType[HasherType["H68"] = 68] = "H68";
|
|
2294
|
+
return HasherType;
|
|
2295
|
+
}({});
|
|
2296
|
+
let EncoderMode = /* @__PURE__ */ function(EncoderMode) {
|
|
2297
|
+
EncoderMode[EncoderMode["GENERIC"] = 0] = "GENERIC";
|
|
2298
|
+
EncoderMode[EncoderMode["TEXT"] = 1] = "TEXT";
|
|
2299
|
+
EncoderMode[EncoderMode["FONT"] = 2] = "FONT";
|
|
2300
|
+
return EncoderMode;
|
|
2301
|
+
}({});
|
|
2302
|
+
const NUM_COMMAND_CODES = 704;
|
|
2303
|
+
const NUM_LITERAL_CODES = 256;
|
|
2304
|
+
const NUM_DISTANCE_SHORT_CODES = 16;
|
|
2305
|
+
function maxZopfliLen(quality) {
|
|
2306
|
+
return quality <= 10 ? MAX_ZOPFLI_LEN_QUALITY_10 : MAX_ZOPFLI_LEN_QUALITY_11;
|
|
2307
|
+
}
|
|
2308
|
+
function maxZopfliCandidates(quality) {
|
|
2309
|
+
return quality <= 10 ? 1 : 5;
|
|
2310
|
+
}
|
|
2311
|
+
function sanitizeParams(params) {
|
|
2312
|
+
params.quality = Math.max(MIN_QUALITY, Math.min(MAX_QUALITY, params.quality));
|
|
2313
|
+
if (params.quality <= MAX_QUALITY_FOR_STATIC_ENTROPY_CODES) params.largeWindow = false;
|
|
2314
|
+
const maxLgwin = params.largeWindow ? LARGE_MAX_WINDOW_BITS : MAX_WINDOW_BITS;
|
|
2315
|
+
params.lgwin = Math.max(MIN_WINDOW_BITS, Math.min(maxLgwin, params.lgwin));
|
|
2316
|
+
}
|
|
2317
|
+
function computeLgBlock(params) {
|
|
2318
|
+
let lgblock = params.lgblock;
|
|
2319
|
+
if (params.quality === FAST_ONE_PASS_COMPRESSION_QUALITY || params.quality === FAST_TWO_PASS_COMPRESSION_QUALITY) lgblock = params.lgwin;
|
|
2320
|
+
else if (params.quality < MIN_QUALITY_FOR_BLOCK_SPLIT) lgblock = 14;
|
|
2321
|
+
else if (lgblock === 0) {
|
|
2322
|
+
lgblock = 16;
|
|
2323
|
+
if (params.quality >= 9 && params.lgwin > lgblock) lgblock = Math.min(18, params.lgwin);
|
|
2324
|
+
} else lgblock = Math.max(MIN_INPUT_BLOCK_BITS, Math.min(MAX_INPUT_BLOCK_BITS, lgblock));
|
|
2325
|
+
return lgblock;
|
|
2326
|
+
}
|
|
2327
|
+
function createDefaultParams() {
|
|
2328
|
+
return {
|
|
2329
|
+
mode: EncoderMode.GENERIC,
|
|
2330
|
+
quality: DEFAULT_QUALITY,
|
|
2331
|
+
lgwin: DEFAULT_WINDOW_BITS,
|
|
2332
|
+
lgblock: 0,
|
|
2333
|
+
streamOffset: 0,
|
|
2334
|
+
sizeHint: 0,
|
|
2335
|
+
disableLiteralContextModeling: false,
|
|
2336
|
+
largeWindow: false,
|
|
2337
|
+
hasher: {
|
|
2338
|
+
type: HasherType.H10,
|
|
2339
|
+
bucketBits: 17,
|
|
2340
|
+
blockBits: 0,
|
|
2341
|
+
numLastDistancesToCheck: 16
|
|
2342
|
+
},
|
|
2343
|
+
dist: {
|
|
2344
|
+
distancePostfixBits: 0,
|
|
2345
|
+
numDirectDistanceCodes: 0,
|
|
2346
|
+
alphabetSizeMax: 0,
|
|
2347
|
+
alphabetSizeLimit: 0,
|
|
2348
|
+
maxDistance: 0
|
|
2349
|
+
}
|
|
2350
|
+
};
|
|
2351
|
+
}
|
|
2352
|
+
|
|
2353
|
+
//#endregion
|
|
2354
|
+
//#region src/encode/fast-log.ts
|
|
2355
|
+
const kLog2Table = new Float64Array([
|
|
2356
|
+
0,
|
|
2357
|
+
0,
|
|
2358
|
+
1,
|
|
2359
|
+
1.5849625007211563,
|
|
2360
|
+
2,
|
|
2361
|
+
2.321928094887362,
|
|
2362
|
+
2.584962500721156,
|
|
2363
|
+
2.807354922057604,
|
|
2364
|
+
3,
|
|
2365
|
+
3.1699250014423126,
|
|
2366
|
+
3.3219280948873626,
|
|
2367
|
+
3.4594316186372978,
|
|
2368
|
+
3.5849625007211565,
|
|
2369
|
+
3.700439718141092,
|
|
2370
|
+
3.8073549220576037,
|
|
2371
|
+
3.9068905956085187,
|
|
2372
|
+
4,
|
|
2373
|
+
4.08746284125034,
|
|
2374
|
+
4.169925001442312,
|
|
2375
|
+
4.247927513443585,
|
|
2376
|
+
4.321928094887363,
|
|
2377
|
+
4.392317422778761,
|
|
2378
|
+
4.459431618637297,
|
|
2379
|
+
4.523561956057013,
|
|
2380
|
+
4.584962500721157,
|
|
2381
|
+
4.643856189774724,
|
|
2382
|
+
4.700439718141093,
|
|
2383
|
+
4.754887502163469,
|
|
2384
|
+
4.807354922057604,
|
|
2385
|
+
4.857980995127573,
|
|
2386
|
+
4.906890595608519,
|
|
2387
|
+
4.954196310386876,
|
|
2388
|
+
5,
|
|
2389
|
+
5.044394119358453,
|
|
2390
|
+
5.08746284125034,
|
|
2391
|
+
5.129283016944966,
|
|
2392
|
+
5.169925001442312,
|
|
2393
|
+
5.20945336562895,
|
|
2394
|
+
5.247927513443585,
|
|
2395
|
+
5.285402218862249,
|
|
2396
|
+
5.321928094887363,
|
|
2397
|
+
5.357552004618084,
|
|
2398
|
+
5.392317422778761,
|
|
2399
|
+
5.426264754702098,
|
|
2400
|
+
5.459431618637297,
|
|
2401
|
+
5.491853096329675,
|
|
2402
|
+
5.523561956057013,
|
|
2403
|
+
5.554588851677638,
|
|
2404
|
+
5.584962500721157,
|
|
2405
|
+
5.614709844115208,
|
|
2406
|
+
5.643856189774724,
|
|
2407
|
+
5.672425341971496,
|
|
2408
|
+
5.700439718141093,
|
|
2409
|
+
5.7279204545632,
|
|
2410
|
+
5.754887502163469,
|
|
2411
|
+
5.78135971352466,
|
|
2412
|
+
5.807354922057605,
|
|
2413
|
+
5.832890014164742,
|
|
2414
|
+
5.857980995127572,
|
|
2415
|
+
5.882643049361842,
|
|
2416
|
+
5.906890595608519,
|
|
2417
|
+
5.930737337562887,
|
|
2418
|
+
5.954196310386876,
|
|
2419
|
+
5.977279923499917,
|
|
2420
|
+
6,
|
|
2421
|
+
6.022367813028454,
|
|
2422
|
+
6.044394119358453,
|
|
2423
|
+
6.066089190457772,
|
|
2424
|
+
6.08746284125034,
|
|
2425
|
+
6.10852445677817,
|
|
2426
|
+
6.129283016944967,
|
|
2427
|
+
6.149747119504682,
|
|
2428
|
+
6.169925001442312,
|
|
2429
|
+
6.189824558880018,
|
|
2430
|
+
6.209453365628951,
|
|
2431
|
+
6.22881869049588,
|
|
2432
|
+
6.247927513443586,
|
|
2433
|
+
6.266786540694902,
|
|
2434
|
+
6.285402218862249,
|
|
2435
|
+
6.303780748177103,
|
|
2436
|
+
6.321928094887362,
|
|
2437
|
+
6.339850002884625,
|
|
2438
|
+
6.357552004618085,
|
|
2439
|
+
6.375039431346925,
|
|
2440
|
+
6.39231742277876,
|
|
2441
|
+
6.409390936137703,
|
|
2442
|
+
6.426264754702098,
|
|
2443
|
+
6.442943495848729,
|
|
2444
|
+
6.459431618637298,
|
|
2445
|
+
6.475733430966398,
|
|
2446
|
+
6.491853096329675,
|
|
2447
|
+
6.507794640198696,
|
|
2448
|
+
6.523561956057013,
|
|
2449
|
+
6.539158811108032,
|
|
2450
|
+
6.554588851677638,
|
|
2451
|
+
6.569855608330948,
|
|
2452
|
+
6.584962500721156,
|
|
2453
|
+
6.599912842187128,
|
|
2454
|
+
6.614709844115209,
|
|
2455
|
+
6.6293566200796095,
|
|
2456
|
+
6.643856189774725,
|
|
2457
|
+
6.6582114827517955,
|
|
2458
|
+
6.672425341971495,
|
|
2459
|
+
6.6865005271832185,
|
|
2460
|
+
6.700439718141092,
|
|
2461
|
+
6.714245517666122,
|
|
2462
|
+
6.727920454563199,
|
|
2463
|
+
6.7414669864011465,
|
|
2464
|
+
6.754887502163469,
|
|
2465
|
+
6.768184324776926,
|
|
2466
|
+
6.78135971352466,
|
|
2467
|
+
6.794415866350106,
|
|
2468
|
+
6.807354922057604,
|
|
2469
|
+
6.820178962415189,
|
|
2470
|
+
6.832890014164742,
|
|
2471
|
+
6.845490050944376,
|
|
2472
|
+
6.857980995127572,
|
|
2473
|
+
6.870364719583405,
|
|
2474
|
+
6.882643049361842,
|
|
2475
|
+
6.894817763307944,
|
|
2476
|
+
6.906890595608519,
|
|
2477
|
+
6.9188632372745955,
|
|
2478
|
+
6.930737337562887,
|
|
2479
|
+
6.94251450533924,
|
|
2480
|
+
6.954196310386876,
|
|
2481
|
+
6.965784284662088,
|
|
2482
|
+
6.977279923499917,
|
|
2483
|
+
6.988684686772166,
|
|
2484
|
+
7,
|
|
2485
|
+
7.011227255423254,
|
|
2486
|
+
7.022367813028454,
|
|
2487
|
+
7.03342300153745,
|
|
2488
|
+
7.044394119358453,
|
|
2489
|
+
7.05528243550119,
|
|
2490
|
+
7.066089190457772,
|
|
2491
|
+
7.076815597050832,
|
|
2492
|
+
7.08746284125034,
|
|
2493
|
+
7.098032082960527,
|
|
2494
|
+
7.10852445677817,
|
|
2495
|
+
7.118941072723508,
|
|
2496
|
+
7.129283016944966,
|
|
2497
|
+
7.139551352398794,
|
|
2498
|
+
7.149747119504682,
|
|
2499
|
+
7.159871336778389,
|
|
2500
|
+
7.169925001442313,
|
|
2501
|
+
7.1799090900149345,
|
|
2502
|
+
7.189824558880018,
|
|
2503
|
+
7.199672344836364,
|
|
2504
|
+
7.209453365628949,
|
|
2505
|
+
7.219168520462162,
|
|
2506
|
+
7.22881869049588,
|
|
2507
|
+
7.238404739325079,
|
|
2508
|
+
7.247927513443586,
|
|
2509
|
+
7.257387842692652,
|
|
2510
|
+
7.266786540694902,
|
|
2511
|
+
7.276124405274238,
|
|
2512
|
+
7.285402218862249,
|
|
2513
|
+
7.294620748891627,
|
|
2514
|
+
7.303780748177103,
|
|
2515
|
+
7.312882955284356,
|
|
2516
|
+
7.321928094887362,
|
|
2517
|
+
7.330916878114618,
|
|
2518
|
+
7.339850002884624,
|
|
2519
|
+
7.348728154231078,
|
|
2520
|
+
7.357552004618085,
|
|
2521
|
+
7.366322214245815,
|
|
2522
|
+
7.375039431346925,
|
|
2523
|
+
7.383704292474053,
|
|
2524
|
+
7.392317422778761,
|
|
2525
|
+
7.400879436282184,
|
|
2526
|
+
7.409390936137703,
|
|
2527
|
+
7.417852514885899,
|
|
2528
|
+
7.426264754702098,
|
|
2529
|
+
7.4346282276367255,
|
|
2530
|
+
7.442943495848729,
|
|
2531
|
+
7.45121111183233,
|
|
2532
|
+
7.459431618637297,
|
|
2533
|
+
7.467605550082998,
|
|
2534
|
+
7.475733430966398,
|
|
2535
|
+
7.483815777264256,
|
|
2536
|
+
7.491853096329675,
|
|
2537
|
+
7.499845887083206,
|
|
2538
|
+
7.507794640198696,
|
|
2539
|
+
7.515699838284044,
|
|
2540
|
+
7.523561956057013,
|
|
2541
|
+
7.531381460516312,
|
|
2542
|
+
7.539158811108032,
|
|
2543
|
+
7.546894459887637,
|
|
2544
|
+
7.554588851677638,
|
|
2545
|
+
7.562242424221073,
|
|
2546
|
+
7.569855608330948,
|
|
2547
|
+
7.577428828035749,
|
|
2548
|
+
7.584962500721156,
|
|
2549
|
+
7.592457037268081,
|
|
2550
|
+
7.599912842187128,
|
|
2551
|
+
7.607330313749611,
|
|
2552
|
+
7.6147098441152075,
|
|
2553
|
+
7.622051819456376,
|
|
2554
|
+
7.6293566200796095,
|
|
2555
|
+
7.636624620543649,
|
|
2556
|
+
7.643856189774724,
|
|
2557
|
+
7.651051691178929,
|
|
2558
|
+
7.6582114827517955,
|
|
2559
|
+
7.6653359171851765,
|
|
2560
|
+
7.672425341971495,
|
|
2561
|
+
7.679480099505446,
|
|
2562
|
+
7.6865005271832185,
|
|
2563
|
+
7.693486957499325,
|
|
2564
|
+
7.700439718141093,
|
|
2565
|
+
7.7073591320808825,
|
|
2566
|
+
7.714245517666122,
|
|
2567
|
+
7.721099188707186,
|
|
2568
|
+
7.7279204545632,
|
|
2569
|
+
7.734709620225839,
|
|
2570
|
+
7.7414669864011465,
|
|
2571
|
+
7.74819284958946,
|
|
2572
|
+
7.754887502163469,
|
|
2573
|
+
7.7615512324444795,
|
|
2574
|
+
7.768184324776926,
|
|
2575
|
+
7.774787059601174,
|
|
2576
|
+
7.781359713524661,
|
|
2577
|
+
7.787902559391432,
|
|
2578
|
+
7.794415866350106,
|
|
2579
|
+
7.800899899920305,
|
|
2580
|
+
7.807354922057604,
|
|
2581
|
+
7.813781191217037,
|
|
2582
|
+
7.820178962415189,
|
|
2583
|
+
7.826548487290916,
|
|
2584
|
+
7.832890014164742,
|
|
2585
|
+
7.8392037880969445,
|
|
2586
|
+
7.845490050944376,
|
|
2587
|
+
7.851749041416057,
|
|
2588
|
+
7.857980995127572,
|
|
2589
|
+
7.86418614465428,
|
|
2590
|
+
7.870364719583405,
|
|
2591
|
+
7.876516946565,
|
|
2592
|
+
7.8826430493618425,
|
|
2593
|
+
7.88874324889826,
|
|
2594
|
+
7.894817763307945,
|
|
2595
|
+
7.90086680798075,
|
|
2596
|
+
7.906890595608519,
|
|
2597
|
+
7.912889336229962,
|
|
2598
|
+
7.9188632372745955,
|
|
2599
|
+
7.924812503605781,
|
|
2600
|
+
7.930737337562887,
|
|
2601
|
+
7.936637939002572,
|
|
2602
|
+
7.94251450533924,
|
|
2603
|
+
7.948367231584678,
|
|
2604
|
+
7.954196310386876,
|
|
2605
|
+
7.960001932068081,
|
|
2606
|
+
7.965784284662087,
|
|
2607
|
+
7.971543553950772,
|
|
2608
|
+
7.977279923499917,
|
|
2609
|
+
7.98299357469431,
|
|
2610
|
+
7.988684686772166,
|
|
2611
|
+
7.994353436858858
|
|
2612
|
+
]);
|
|
2613
|
+
const LOG2_TABLE_SIZE = 256;
|
|
2614
|
+
const LOG_2_INV = 1.4426950408889634;
|
|
2615
|
+
function log2FloorNonZero(n) {
|
|
2616
|
+
return 31 - Math.clz32(n | 0);
|
|
2617
|
+
}
|
|
2618
|
+
function fastLog2(v) {
|
|
2619
|
+
if (v < LOG2_TABLE_SIZE) return kLog2Table[v];
|
|
2620
|
+
return Math.log(v) * LOG_2_INV;
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2623
|
+
//#endregion
|
|
2624
|
+
//#region src/encode/match.ts
|
|
2625
|
+
const LITERAL_BYTE_SCORE = 135;
|
|
2626
|
+
const DISTANCE_BIT_PENALTY = 30;
|
|
2627
|
+
const SCORE_BASE = DISTANCE_BIT_PENALTY * 8 * 4;
|
|
2628
|
+
function backwardReferenceScore(copyLength, backwardDistance) {
|
|
2629
|
+
return SCORE_BASE + LITERAL_BYTE_SCORE * copyLength - DISTANCE_BIT_PENALTY * log2FloorNonZero(backwardDistance);
|
|
2630
|
+
}
|
|
2631
|
+
function backwardReferenceScoreUsingLastDistance(copyLength) {
|
|
2632
|
+
return LITERAL_BYTE_SCORE * copyLength + SCORE_BASE + 15;
|
|
2633
|
+
}
|
|
2634
|
+
function findMatchLength(data, s1, s2, limit) {
|
|
2635
|
+
let matched = 0;
|
|
2636
|
+
while (matched + 4 <= limit) {
|
|
2637
|
+
if (data[s1 + matched] !== data[s2 + matched] || data[s1 + matched + 1] !== data[s2 + matched + 1] || data[s1 + matched + 2] !== data[s2 + matched + 2] || data[s1 + matched + 3] !== data[s2 + matched + 3]) break;
|
|
2638
|
+
matched += 4;
|
|
2639
|
+
}
|
|
2640
|
+
while (matched < limit && data[s1 + matched] === data[s2 + matched]) matched++;
|
|
2641
|
+
return matched;
|
|
2642
|
+
}
|
|
2643
|
+
function createBackwardMatch(distance, length) {
|
|
2644
|
+
return {
|
|
2645
|
+
distance,
|
|
2646
|
+
length,
|
|
2647
|
+
score: backwardReferenceScore(length, distance),
|
|
2648
|
+
lenCodeDelta: 0
|
|
2649
|
+
};
|
|
2650
|
+
}
|
|
2651
|
+
function createSearchResult() {
|
|
2652
|
+
return {
|
|
2653
|
+
len: 0,
|
|
2654
|
+
distance: 0,
|
|
2655
|
+
score: 0,
|
|
2656
|
+
lenCodeDelta: 0
|
|
2657
|
+
};
|
|
2658
|
+
}
|
|
2659
|
+
function prepareDistanceCache(distanceCache, numDistances) {
|
|
2660
|
+
if (numDistances > 4) {
|
|
2661
|
+
const lastDistance = distanceCache[0];
|
|
2662
|
+
distanceCache[4] = lastDistance - 1;
|
|
2663
|
+
distanceCache[5] = lastDistance + 1;
|
|
2664
|
+
distanceCache[6] = lastDistance - 2;
|
|
2665
|
+
distanceCache[7] = lastDistance + 2;
|
|
2666
|
+
distanceCache[8] = lastDistance - 3;
|
|
2667
|
+
distanceCache[9] = lastDistance + 3;
|
|
2668
|
+
if (numDistances > 10) {
|
|
2669
|
+
const nextLastDistance = distanceCache[1];
|
|
2670
|
+
distanceCache[10] = nextLastDistance - 1;
|
|
2671
|
+
distanceCache[11] = nextLastDistance + 1;
|
|
2672
|
+
distanceCache[12] = nextLastDistance - 2;
|
|
2673
|
+
distanceCache[13] = nextLastDistance + 2;
|
|
2674
|
+
distanceCache[14] = nextLastDistance - 3;
|
|
2675
|
+
distanceCache[15] = nextLastDistance + 3;
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
}
|
|
2679
|
+
const HASH_MUL_32 = 506832829;
|
|
2680
|
+
const HASH_MUL_64 = 506832829n;
|
|
2681
|
+
function hashBytes4(data, pos, bucketBits) {
|
|
2682
|
+
const b0 = pos < data.length ? data[pos] : 0;
|
|
2683
|
+
const b1 = pos + 1 < data.length ? data[pos + 1] : 0;
|
|
2684
|
+
const b2 = pos + 2 < data.length ? data[pos + 2] : 0;
|
|
2685
|
+
const b3 = pos + 3 < data.length ? data[pos + 3] : 0;
|
|
2686
|
+
const h32 = (b0 | b1 << 8 | b2 << 16 | b3 << 24) >>> 0;
|
|
2687
|
+
return Math.imul(h32, HASH_MUL_32) >>> 0 >>> 32 - bucketBits;
|
|
2688
|
+
}
|
|
2689
|
+
function hashBytes8(data, pos, hashLen, bucketBits) {
|
|
2690
|
+
let h64 = 0n;
|
|
2691
|
+
for (let i = 0; i < 8; i++) {
|
|
2692
|
+
const byte = pos + i < data.length ? data[pos + i] : 0;
|
|
2693
|
+
h64 |= BigInt(byte) << BigInt(i * 8);
|
|
2694
|
+
}
|
|
2695
|
+
const shift = BigInt(64 - 8 * hashLen);
|
|
2696
|
+
h64 = (h64 << shift) * HASH_MUL_64;
|
|
2697
|
+
return Number(h64 >> BigInt(64 - bucketBits));
|
|
2698
|
+
}
|
|
2699
|
+
|
|
2700
|
+
//#endregion
|
|
2701
|
+
//#region src/encode/hash-simple.ts
|
|
2702
|
+
const Q2_BUCKET_BITS = 16;
|
|
2703
|
+
const Q3_BUCKET_BITS = 17;
|
|
2704
|
+
const HASH_LEN = 5;
|
|
2705
|
+
const MIN_MATCH_LEN$1 = 4;
|
|
2706
|
+
var SimpleHasher = class {
|
|
2707
|
+
constructor(bucketBits, _lgwin) {
|
|
2708
|
+
this.bucketBits = bucketBits;
|
|
2709
|
+
const bucketSize = 1 << bucketBits;
|
|
2710
|
+
this.buckets = new Uint32Array(bucketSize);
|
|
2711
|
+
}
|
|
2712
|
+
reset() {
|
|
2713
|
+
this.buckets.fill(0);
|
|
2714
|
+
}
|
|
2715
|
+
prepare(data, inputSize) {
|
|
2716
|
+
if (inputSize <= this.buckets.length >> 5) for (let i = 0; i < inputSize; i++) {
|
|
2717
|
+
const key = this.hashBytes(data, i);
|
|
2718
|
+
this.buckets[key] = 0;
|
|
2719
|
+
}
|
|
2720
|
+
else this.buckets.fill(0);
|
|
2721
|
+
}
|
|
2722
|
+
hashBytes(data, pos) {
|
|
2723
|
+
return hashBytes8(data, pos, HASH_LEN, this.bucketBits);
|
|
2724
|
+
}
|
|
2725
|
+
store(data, mask, ix) {
|
|
2726
|
+
const key = this.hashBytes(data, ix & mask);
|
|
2727
|
+
this.buckets[key] = ix;
|
|
2728
|
+
}
|
|
2729
|
+
storeRange(data, mask, ixStart, ixEnd) {
|
|
2730
|
+
for (let i = ixStart; i < ixEnd; i++) this.store(data, mask, i);
|
|
2731
|
+
}
|
|
2732
|
+
findLongestMatch(data, ringBufferMask, distanceCache, curIx, maxLength, maxBackward, out) {
|
|
2733
|
+
const curIxMasked = curIx & ringBufferMask;
|
|
2734
|
+
let bestLen = out.len;
|
|
2735
|
+
const key = this.hashBytes(data, curIxMasked);
|
|
2736
|
+
let bestScore = out.score;
|
|
2737
|
+
out.lenCodeDelta = 0;
|
|
2738
|
+
const cachedBackward = distanceCache[0];
|
|
2739
|
+
if (cachedBackward > 0 && cachedBackward <= maxBackward) {
|
|
2740
|
+
let prevIx = curIx - cachedBackward;
|
|
2741
|
+
prevIx &= ringBufferMask;
|
|
2742
|
+
if (data[prevIx + bestLen] === data[curIxMasked + bestLen]) {
|
|
2743
|
+
const len = findMatchLength(data, prevIx, curIxMasked, maxLength);
|
|
2744
|
+
if (len >= MIN_MATCH_LEN$1) {
|
|
2745
|
+
const score = backwardReferenceScoreUsingLastDistance(len);
|
|
2746
|
+
if (score > bestScore) {
|
|
2747
|
+
bestLen = len;
|
|
2748
|
+
out.len = len;
|
|
2749
|
+
out.distance = cachedBackward;
|
|
2750
|
+
out.score = score;
|
|
2751
|
+
bestScore = score;
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
let prevIx = this.buckets[key];
|
|
2757
|
+
this.buckets[key] = curIx;
|
|
2758
|
+
const backward = curIx - prevIx;
|
|
2759
|
+
if (backward === 0 || backward > maxBackward) return;
|
|
2760
|
+
prevIx &= ringBufferMask;
|
|
2761
|
+
if (data[prevIx + bestLen] !== data[curIxMasked + bestLen]) return;
|
|
2762
|
+
const len = findMatchLength(data, prevIx, curIxMasked, maxLength);
|
|
2763
|
+
if (len >= MIN_MATCH_LEN$1) {
|
|
2764
|
+
const score = backwardReferenceScore(len, backward);
|
|
2765
|
+
if (score > bestScore) {
|
|
2766
|
+
out.len = len;
|
|
2767
|
+
out.distance = backward;
|
|
2768
|
+
out.score = score;
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
};
|
|
2773
|
+
function createSimpleHasher(quality, lgwin) {
|
|
2774
|
+
return new SimpleHasher(quality === 2 ? Q2_BUCKET_BITS : Q3_BUCKET_BITS, lgwin);
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2777
|
+
//#endregion
|
|
2778
|
+
//#region src/encode/hash-chains.ts
|
|
2779
|
+
const MIN_MATCH_LEN = 4;
|
|
2780
|
+
var HashChainHasher = class {
|
|
2781
|
+
constructor(bucketBits, blockBits, lgwin, numLastDistancesToCheck = 4) {
|
|
2782
|
+
this.bucketBits = bucketBits;
|
|
2783
|
+
this.blockBits = blockBits;
|
|
2784
|
+
this.windowMask = (1 << lgwin) - 1;
|
|
2785
|
+
this.numLastDistancesToCheck = numLastDistancesToCheck;
|
|
2786
|
+
this.buckets = new Uint32Array(1 << bucketBits);
|
|
2787
|
+
this.chains = new Uint32Array(1 << lgwin);
|
|
2788
|
+
}
|
|
2789
|
+
reset() {
|
|
2790
|
+
this.buckets.fill(0);
|
|
2791
|
+
}
|
|
2792
|
+
hashBytes(data, pos) {
|
|
2793
|
+
return hashBytes4(data, pos, this.bucketBits);
|
|
2794
|
+
}
|
|
2795
|
+
store(data, mask, ix) {
|
|
2796
|
+
const maskedIx = ix & mask;
|
|
2797
|
+
const key = this.hashBytes(data, maskedIx);
|
|
2798
|
+
const minorKey = ix & this.windowMask;
|
|
2799
|
+
this.chains[minorKey] = this.buckets[key];
|
|
2800
|
+
this.buckets[key] = ix;
|
|
2801
|
+
}
|
|
2802
|
+
storeRange(data, mask, ixStart, ixEnd) {
|
|
2803
|
+
for (let i = ixStart; i < ixEnd; i++) this.store(data, mask, i);
|
|
2804
|
+
}
|
|
2805
|
+
findLongestMatch(data, ringBufferMask, distanceCache, curIx, maxLength, maxBackward, out) {
|
|
2806
|
+
const curIxMasked = curIx & ringBufferMask;
|
|
2807
|
+
let bestLen = out.len;
|
|
2808
|
+
let bestScore = out.score;
|
|
2809
|
+
const key = this.hashBytes(data, curIxMasked);
|
|
2810
|
+
const minorKey = curIx & this.windowMask;
|
|
2811
|
+
out.lenCodeDelta = 0;
|
|
2812
|
+
prepareDistanceCache(distanceCache, this.numLastDistancesToCheck);
|
|
2813
|
+
for (let i = 0; i < this.numLastDistancesToCheck; i++) {
|
|
2814
|
+
const cachedBackward = distanceCache[i];
|
|
2815
|
+
if (cachedBackward <= 0 || cachedBackward > maxBackward) continue;
|
|
2816
|
+
let prevIx = curIx - cachedBackward;
|
|
2817
|
+
prevIx &= ringBufferMask;
|
|
2818
|
+
if (data[prevIx + bestLen] !== data[curIxMasked + bestLen]) continue;
|
|
2819
|
+
const len = findMatchLength(data, prevIx, curIxMasked, maxLength);
|
|
2820
|
+
if (len >= MIN_MATCH_LEN) {
|
|
2821
|
+
const score = backwardReferenceScoreUsingLastDistance(len);
|
|
2822
|
+
if (score > bestScore) {
|
|
2823
|
+
bestLen = len;
|
|
2824
|
+
out.len = len;
|
|
2825
|
+
out.distance = cachedBackward;
|
|
2826
|
+
out.score = score;
|
|
2827
|
+
bestScore = score;
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
this.chains[minorKey] = this.buckets[key];
|
|
2832
|
+
this.buckets[key] = curIx;
|
|
2833
|
+
const maxChainLength = 1 << this.blockBits;
|
|
2834
|
+
let prevIx = this.chains[minorKey];
|
|
2835
|
+
for (let chainLen = 0; chainLen < maxChainLength; chainLen++) {
|
|
2836
|
+
const backward = curIx - prevIx;
|
|
2837
|
+
if (backward === 0 || backward > maxBackward) break;
|
|
2838
|
+
const prevIxMasked = prevIx & ringBufferMask;
|
|
2839
|
+
if (data[prevIxMasked + bestLen] !== data[curIxMasked + bestLen]) {
|
|
2840
|
+
prevIx = this.chains[prevIx & this.windowMask];
|
|
2841
|
+
continue;
|
|
2842
|
+
}
|
|
2843
|
+
const len = findMatchLength(data, prevIxMasked, curIxMasked, maxLength);
|
|
2844
|
+
if (len >= MIN_MATCH_LEN) {
|
|
2845
|
+
const score = backwardReferenceScore(len, backward);
|
|
2846
|
+
if (score > bestScore) {
|
|
2847
|
+
bestLen = len;
|
|
2848
|
+
out.len = len;
|
|
2849
|
+
out.distance = backward;
|
|
2850
|
+
out.score = score;
|
|
2851
|
+
bestScore = score;
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2854
|
+
prevIx = this.chains[prevIx & this.windowMask];
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
findAllMatches(data, ringBufferMask, distanceCache, curIx, maxLength, maxBackward) {
|
|
2858
|
+
const curIxMasked = curIx & ringBufferMask;
|
|
2859
|
+
const matches = [];
|
|
2860
|
+
const key = this.hashBytes(data, curIxMasked);
|
|
2861
|
+
const minorKey = curIx & this.windowMask;
|
|
2862
|
+
let bestLen = 0;
|
|
2863
|
+
prepareDistanceCache(distanceCache, this.numLastDistancesToCheck);
|
|
2864
|
+
for (let i = 0; i < this.numLastDistancesToCheck; i++) {
|
|
2865
|
+
const cachedBackward = distanceCache[i];
|
|
2866
|
+
if (cachedBackward <= 0 || cachedBackward > maxBackward) continue;
|
|
2867
|
+
let prevIx = curIx - cachedBackward;
|
|
2868
|
+
prevIx &= ringBufferMask;
|
|
2869
|
+
const len = findMatchLength(data, prevIx, curIxMasked, maxLength);
|
|
2870
|
+
if (len >= MIN_MATCH_LEN && len > bestLen) {
|
|
2871
|
+
bestLen = len;
|
|
2872
|
+
matches.push({
|
|
2873
|
+
distance: cachedBackward,
|
|
2874
|
+
length: len,
|
|
2875
|
+
score: backwardReferenceScoreUsingLastDistance(len),
|
|
2876
|
+
lenCodeDelta: 0
|
|
2877
|
+
});
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
this.chains[minorKey] = this.buckets[key];
|
|
2881
|
+
this.buckets[key] = curIx;
|
|
2882
|
+
const maxChainLength = 1 << this.blockBits;
|
|
2883
|
+
let prevIx = this.chains[minorKey];
|
|
2884
|
+
for (let chainLen = 0; chainLen < maxChainLength; chainLen++) {
|
|
2885
|
+
const backward = curIx - prevIx;
|
|
2886
|
+
if (backward === 0 || backward > maxBackward) break;
|
|
2887
|
+
const len = findMatchLength(data, prevIx & ringBufferMask, curIxMasked, maxLength);
|
|
2888
|
+
if (len >= MIN_MATCH_LEN && len > bestLen) {
|
|
2889
|
+
bestLen = len;
|
|
2890
|
+
matches.push({
|
|
2891
|
+
distance: backward,
|
|
2892
|
+
length: len,
|
|
2893
|
+
score: backwardReferenceScore(len, backward),
|
|
2894
|
+
lenCodeDelta: 0
|
|
2895
|
+
});
|
|
2896
|
+
}
|
|
2897
|
+
prevIx = this.chains[prevIx & this.windowMask];
|
|
2898
|
+
}
|
|
2899
|
+
matches.sort((a, b) => a.length - b.length);
|
|
2900
|
+
return matches;
|
|
2901
|
+
}
|
|
2902
|
+
};
|
|
2903
|
+
function createHashChainHasher(quality, lgwin) {
|
|
2904
|
+
let bucketBits;
|
|
2905
|
+
let blockBits;
|
|
2906
|
+
let numLastDistancesToCheck;
|
|
2907
|
+
if (quality < 7) {
|
|
2908
|
+
bucketBits = 14;
|
|
2909
|
+
blockBits = quality - 1;
|
|
2910
|
+
numLastDistancesToCheck = 4;
|
|
2911
|
+
} else if (quality < 9) {
|
|
2912
|
+
bucketBits = 15;
|
|
2913
|
+
blockBits = quality - 1;
|
|
2914
|
+
numLastDistancesToCheck = 10;
|
|
2915
|
+
} else {
|
|
2916
|
+
bucketBits = 15;
|
|
2917
|
+
blockBits = quality - 1;
|
|
2918
|
+
numLastDistancesToCheck = 16;
|
|
2919
|
+
}
|
|
2920
|
+
return new HashChainHasher(bucketBits, blockBits, lgwin, numLastDistancesToCheck);
|
|
2921
|
+
}
|
|
2922
|
+
|
|
2923
|
+
//#endregion
|
|
2924
|
+
//#region src/encode/hash-binary-tree.ts
|
|
2925
|
+
const BUCKET_BITS = 17;
|
|
2926
|
+
const MAX_TREE_COMP_LENGTH = 128;
|
|
2927
|
+
const MAX_TREE_SEARCH_DEPTH = 64;
|
|
2928
|
+
const WINDOW_GAP = 16;
|
|
2929
|
+
var BinaryTreeHasher = class {
|
|
2930
|
+
constructor(lgwin, inputSize) {
|
|
2931
|
+
this.windowMask = (1 << lgwin) - 1;
|
|
2932
|
+
this.invalidPos = 0 - this.windowMask >>> 0;
|
|
2933
|
+
this.bucketSize = 1 << BUCKET_BITS;
|
|
2934
|
+
this.buckets = new Uint32Array(this.bucketSize);
|
|
2935
|
+
const numNodes = inputSize !== void 0 ? Math.min(inputSize, 1 << lgwin) : 1 << lgwin;
|
|
2936
|
+
this.forest = new Uint32Array(2 * numNodes);
|
|
2937
|
+
this.forest.fill(this.invalidPos);
|
|
2938
|
+
}
|
|
2939
|
+
reset() {
|
|
2940
|
+
this.buckets.fill(this.invalidPos);
|
|
2941
|
+
this.forest.fill(this.invalidPos);
|
|
2942
|
+
}
|
|
2943
|
+
leftChildIndex(pos) {
|
|
2944
|
+
return 2 * (pos & this.windowMask);
|
|
2945
|
+
}
|
|
2946
|
+
rightChildIndex(pos) {
|
|
2947
|
+
return 2 * (pos & this.windowMask) + 1;
|
|
2948
|
+
}
|
|
2949
|
+
storeAndFindMatches(data, curIx, ringBufferMask, maxLength, maxBackward, matches) {
|
|
2950
|
+
const curIxMasked = curIx & ringBufferMask;
|
|
2951
|
+
const maxCompLen = Math.min(maxLength, MAX_TREE_COMP_LENGTH);
|
|
2952
|
+
const shouldRerootTree = maxLength >= MAX_TREE_COMP_LENGTH;
|
|
2953
|
+
const key = hashBytes4(data, curIxMasked, BUCKET_BITS);
|
|
2954
|
+
let prevIx = this.buckets[key];
|
|
2955
|
+
let nodeLeft = this.leftChildIndex(curIx);
|
|
2956
|
+
let nodeRight = this.rightChildIndex(curIx);
|
|
2957
|
+
let bestLenLeft = 0;
|
|
2958
|
+
let bestLenRight = 0;
|
|
2959
|
+
let bestLen = matches ? 1 : 0;
|
|
2960
|
+
const result = matches || [];
|
|
2961
|
+
if (shouldRerootTree) this.buckets[key] = curIx;
|
|
2962
|
+
for (let depthRemaining = MAX_TREE_SEARCH_DEPTH; depthRemaining > 0; depthRemaining--) {
|
|
2963
|
+
if (prevIx === this.invalidPos) {
|
|
2964
|
+
if (shouldRerootTree) {
|
|
2965
|
+
this.forest[nodeLeft] = this.invalidPos;
|
|
2966
|
+
this.forest[nodeRight] = this.invalidPos;
|
|
2967
|
+
}
|
|
2968
|
+
break;
|
|
2969
|
+
}
|
|
2970
|
+
const backward = curIx - prevIx;
|
|
2971
|
+
const prevIxMasked = prevIx & ringBufferMask;
|
|
2972
|
+
if (backward <= 0 || backward > maxBackward) {
|
|
2973
|
+
if (shouldRerootTree) {
|
|
2974
|
+
this.forest[nodeLeft] = this.invalidPos;
|
|
2975
|
+
this.forest[nodeRight] = this.invalidPos;
|
|
2976
|
+
}
|
|
2977
|
+
break;
|
|
2978
|
+
}
|
|
2979
|
+
const curLen = Math.min(bestLenLeft, bestLenRight);
|
|
2980
|
+
const len = curLen + findMatchLength(data, curIxMasked + curLen, prevIxMasked + curLen, maxLength - curLen);
|
|
2981
|
+
if (matches && len > bestLen) {
|
|
2982
|
+
bestLen = len;
|
|
2983
|
+
result.push(createBackwardMatch(backward, len));
|
|
2984
|
+
}
|
|
2985
|
+
if (len >= maxCompLen) {
|
|
2986
|
+
if (shouldRerootTree) {
|
|
2987
|
+
this.forest[nodeLeft] = this.forest[this.leftChildIndex(prevIx)];
|
|
2988
|
+
this.forest[nodeRight] = this.forest[this.rightChildIndex(prevIx)];
|
|
2989
|
+
}
|
|
2990
|
+
break;
|
|
2991
|
+
}
|
|
2992
|
+
if (data[curIxMasked + len] > data[prevIxMasked + len]) {
|
|
2993
|
+
bestLenLeft = len;
|
|
2994
|
+
if (shouldRerootTree) this.forest[nodeLeft] = prevIx;
|
|
2995
|
+
nodeLeft = this.rightChildIndex(prevIx);
|
|
2996
|
+
prevIx = this.forest[nodeLeft];
|
|
2997
|
+
} else {
|
|
2998
|
+
bestLenRight = len;
|
|
2999
|
+
if (shouldRerootTree) this.forest[nodeRight] = prevIx;
|
|
3000
|
+
nodeRight = this.leftChildIndex(prevIx);
|
|
3001
|
+
prevIx = this.forest[nodeRight];
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
return result;
|
|
3005
|
+
}
|
|
3006
|
+
findAllMatches(data, ringBufferMask, curIx, maxLength, maxBackward) {
|
|
3007
|
+
const curIxMasked = curIx & ringBufferMask;
|
|
3008
|
+
const matches = [];
|
|
3009
|
+
let bestLen = 1;
|
|
3010
|
+
const shortMatchMaxBackward = 64;
|
|
3011
|
+
const stop = curIx > shortMatchMaxBackward ? curIx - shortMatchMaxBackward : 0;
|
|
3012
|
+
for (let i = curIx - 1; i > stop && bestLen <= 2; i--) {
|
|
3013
|
+
const backward = curIx - i;
|
|
3014
|
+
if (backward > maxBackward) break;
|
|
3015
|
+
const prevIxMasked = i & ringBufferMask;
|
|
3016
|
+
if (data[curIxMasked] !== data[prevIxMasked] || data[curIxMasked + 1] !== data[prevIxMasked + 1]) continue;
|
|
3017
|
+
const len = findMatchLength(data, prevIxMasked, curIxMasked, maxLength);
|
|
3018
|
+
if (len > bestLen) {
|
|
3019
|
+
bestLen = len;
|
|
3020
|
+
matches.push(createBackwardMatch(backward, len));
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
3023
|
+
if (bestLen < maxLength) {
|
|
3024
|
+
const treeMatches = this.storeAndFindMatches(data, curIx, ringBufferMask, maxLength, maxBackward, []);
|
|
3025
|
+
for (const m of treeMatches) if (m.length > bestLen) {
|
|
3026
|
+
bestLen = m.length;
|
|
3027
|
+
matches.push(m);
|
|
3028
|
+
}
|
|
3029
|
+
} else this.storeAndFindMatches(data, curIx, ringBufferMask, maxLength, maxBackward, null);
|
|
3030
|
+
matches.sort((a, b) => a.length - b.length);
|
|
3031
|
+
return matches;
|
|
3032
|
+
}
|
|
3033
|
+
store(data, mask, ix) {
|
|
3034
|
+
const maxBackward = this.windowMask - WINDOW_GAP + 1;
|
|
3035
|
+
this.storeAndFindMatches(data, ix, mask, MAX_TREE_COMP_LENGTH, maxBackward, null);
|
|
3036
|
+
}
|
|
3037
|
+
storeRange(data, mask, ixStart, ixEnd) {
|
|
3038
|
+
let i = ixStart;
|
|
3039
|
+
let j = ixStart;
|
|
3040
|
+
if (ixStart + 63 <= ixEnd) i = ixEnd - 63;
|
|
3041
|
+
if (ixStart + 512 <= i) for (; j < i; j += 8) this.store(data, mask, j);
|
|
3042
|
+
for (; i < ixEnd; i++) this.store(data, mask, i);
|
|
3043
|
+
}
|
|
3044
|
+
stitchToPreviousBlock(numBytes, position, ringBuffer, ringBufferMask) {
|
|
3045
|
+
if (numBytes >= 3 && position >= MAX_TREE_COMP_LENGTH) {
|
|
3046
|
+
const iStart = position - MAX_TREE_COMP_LENGTH + 1;
|
|
3047
|
+
const iEnd = Math.min(position, iStart + numBytes);
|
|
3048
|
+
for (let i = iStart; i < iEnd; i++) {
|
|
3049
|
+
const maxBackward = this.windowMask - Math.max(WINDOW_GAP - 1, position - i);
|
|
3050
|
+
this.storeAndFindMatches(ringBuffer, i, ringBufferMask, MAX_TREE_COMP_LENGTH, maxBackward, null);
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
};
|
|
3055
|
+
function createBinaryTreeHasher(lgwin, inputSize) {
|
|
3056
|
+
return new BinaryTreeHasher(lgwin, inputSize);
|
|
3057
|
+
}
|
|
3058
|
+
|
|
3059
|
+
//#endregion
|
|
3060
|
+
//#region src/encode/command.ts
|
|
3061
|
+
const INSERT_LENGTH_BASE = new Uint32Array([
|
|
3062
|
+
0,
|
|
3063
|
+
1,
|
|
3064
|
+
2,
|
|
3065
|
+
3,
|
|
3066
|
+
4,
|
|
3067
|
+
5,
|
|
3068
|
+
6,
|
|
3069
|
+
8,
|
|
3070
|
+
10,
|
|
3071
|
+
14,
|
|
3072
|
+
18,
|
|
3073
|
+
26,
|
|
3074
|
+
34,
|
|
3075
|
+
50,
|
|
3076
|
+
66,
|
|
3077
|
+
98,
|
|
3078
|
+
130,
|
|
3079
|
+
194,
|
|
3080
|
+
322,
|
|
3081
|
+
578,
|
|
3082
|
+
1090,
|
|
3083
|
+
2114,
|
|
3084
|
+
6210,
|
|
3085
|
+
22594
|
|
3086
|
+
]);
|
|
3087
|
+
const INSERT_LENGTH_EXTRA = new Uint32Array([
|
|
3088
|
+
0,
|
|
3089
|
+
0,
|
|
3090
|
+
0,
|
|
3091
|
+
0,
|
|
3092
|
+
0,
|
|
3093
|
+
0,
|
|
3094
|
+
1,
|
|
3095
|
+
1,
|
|
3096
|
+
2,
|
|
3097
|
+
2,
|
|
3098
|
+
3,
|
|
3099
|
+
3,
|
|
3100
|
+
4,
|
|
3101
|
+
4,
|
|
3102
|
+
5,
|
|
3103
|
+
5,
|
|
3104
|
+
6,
|
|
3105
|
+
7,
|
|
3106
|
+
8,
|
|
3107
|
+
9,
|
|
3108
|
+
10,
|
|
3109
|
+
12,
|
|
3110
|
+
14,
|
|
3111
|
+
24
|
|
3112
|
+
]);
|
|
3113
|
+
const COPY_LENGTH_BASE = new Uint32Array([
|
|
3114
|
+
2,
|
|
3115
|
+
3,
|
|
3116
|
+
4,
|
|
3117
|
+
5,
|
|
3118
|
+
6,
|
|
3119
|
+
7,
|
|
3120
|
+
8,
|
|
3121
|
+
9,
|
|
3122
|
+
10,
|
|
3123
|
+
12,
|
|
3124
|
+
14,
|
|
3125
|
+
18,
|
|
3126
|
+
22,
|
|
3127
|
+
30,
|
|
3128
|
+
38,
|
|
3129
|
+
54,
|
|
3130
|
+
70,
|
|
3131
|
+
102,
|
|
3132
|
+
134,
|
|
3133
|
+
198,
|
|
3134
|
+
326,
|
|
3135
|
+
582,
|
|
3136
|
+
1094,
|
|
3137
|
+
2118
|
|
3138
|
+
]);
|
|
3139
|
+
const COPY_LENGTH_EXTRA = new Uint32Array([
|
|
3140
|
+
0,
|
|
3141
|
+
0,
|
|
3142
|
+
0,
|
|
3143
|
+
0,
|
|
3144
|
+
0,
|
|
3145
|
+
0,
|
|
3146
|
+
0,
|
|
3147
|
+
0,
|
|
3148
|
+
1,
|
|
3149
|
+
1,
|
|
3150
|
+
2,
|
|
3151
|
+
2,
|
|
3152
|
+
3,
|
|
3153
|
+
3,
|
|
3154
|
+
4,
|
|
3155
|
+
4,
|
|
3156
|
+
5,
|
|
3157
|
+
5,
|
|
3158
|
+
6,
|
|
3159
|
+
7,
|
|
3160
|
+
8,
|
|
3161
|
+
9,
|
|
3162
|
+
10,
|
|
3163
|
+
24
|
|
3164
|
+
]);
|
|
3165
|
+
function getInsertLengthCode(insertLen) {
|
|
3166
|
+
if (insertLen < 6) return insertLen;
|
|
3167
|
+
else if (insertLen < 130) {
|
|
3168
|
+
const nbits = log2FloorNonZero(insertLen - 2) - 1;
|
|
3169
|
+
return (nbits << 1) + (insertLen - 2 >>> nbits) + 2;
|
|
3170
|
+
} else if (insertLen < 2114) return log2FloorNonZero(insertLen - 66) + 10;
|
|
3171
|
+
else if (insertLen < 6210) return 21;
|
|
3172
|
+
else if (insertLen < 22594) return 22;
|
|
3173
|
+
else return 23;
|
|
3174
|
+
}
|
|
3175
|
+
function getCopyLengthCode(copyLen) {
|
|
3176
|
+
if (copyLen < 10) return copyLen - 2;
|
|
3177
|
+
else if (copyLen < 134) {
|
|
3178
|
+
const nbits = log2FloorNonZero(copyLen - 6) - 1;
|
|
3179
|
+
return (nbits << 1) + (copyLen - 6 >>> nbits) + 4;
|
|
3180
|
+
} else if (copyLen < 2118) return log2FloorNonZero(copyLen - 70) + 12;
|
|
3181
|
+
else return 23;
|
|
3182
|
+
}
|
|
3183
|
+
function combineLengthCodes(insCode, copyCode, useLastDistance) {
|
|
3184
|
+
const bits64 = copyCode & 7 | (insCode & 7) << 3;
|
|
3185
|
+
if (useLastDistance && insCode < 8 && copyCode < 16) return copyCode < 8 ? bits64 : bits64 | 64;
|
|
3186
|
+
else {
|
|
3187
|
+
let offset = 2 * ((copyCode >>> 3) + 3 * (insCode >>> 3));
|
|
3188
|
+
offset = (offset << 5) + 64 + (5377344 >>> offset & 192);
|
|
3189
|
+
return offset | bits64;
|
|
3190
|
+
}
|
|
3191
|
+
}
|
|
3192
|
+
function getLengthCode(insertLen, copyLen, useLastDistance) {
|
|
3193
|
+
return combineLengthCodes(getInsertLengthCode(insertLen), getCopyLengthCode(copyLen), useLastDistance);
|
|
3194
|
+
}
|
|
3195
|
+
function getInsertBase(insCode) {
|
|
3196
|
+
return INSERT_LENGTH_BASE[insCode];
|
|
3197
|
+
}
|
|
3198
|
+
function getInsertExtra(insCode) {
|
|
3199
|
+
return INSERT_LENGTH_EXTRA[insCode];
|
|
3200
|
+
}
|
|
3201
|
+
function getCopyBase(copyCode) {
|
|
3202
|
+
return COPY_LENGTH_BASE[copyCode];
|
|
3203
|
+
}
|
|
3204
|
+
function getCopyExtra(copyCode) {
|
|
3205
|
+
return COPY_LENGTH_EXTRA[copyCode];
|
|
3206
|
+
}
|
|
3207
|
+
function prefixEncodeCopyDistance(distanceCode, numDirectCodes, postfixBits) {
|
|
3208
|
+
if (distanceCode < NUM_DISTANCE_SHORT_CODES + numDirectCodes) return [
|
|
3209
|
+
distanceCode,
|
|
3210
|
+
0,
|
|
3211
|
+
0
|
|
3212
|
+
];
|
|
3213
|
+
else {
|
|
3214
|
+
const dist = (1 << postfixBits + 2) + (distanceCode - NUM_DISTANCE_SHORT_CODES - numDirectCodes);
|
|
3215
|
+
const bucket = log2FloorNonZero(dist) - 1;
|
|
3216
|
+
const postfix = dist & (1 << postfixBits) - 1;
|
|
3217
|
+
const prefix = dist >>> bucket & 1;
|
|
3218
|
+
const offset = 2 + prefix << bucket;
|
|
3219
|
+
const nbits = bucket - postfixBits;
|
|
3220
|
+
return [
|
|
3221
|
+
nbits << 10 | NUM_DISTANCE_SHORT_CODES + numDirectCodes + (2 * (nbits - 1) + prefix << postfixBits) + postfix,
|
|
3222
|
+
dist - offset >>> postfixBits,
|
|
3223
|
+
nbits
|
|
3224
|
+
];
|
|
3225
|
+
}
|
|
3226
|
+
}
|
|
3227
|
+
function createCommand(insertLen, copyLen, copyLenCodeDelta, distanceCode, numDirectCodes = 0, postfixBits = 0) {
|
|
3228
|
+
const copyLenEncoded = copyLen | (copyLenCodeDelta & 127) << 25;
|
|
3229
|
+
const [distCode, distExtra, distNbits] = prefixEncodeCopyDistance(distanceCode, numDirectCodes, postfixBits);
|
|
3230
|
+
const distPrefix = distCode | distNbits << 10;
|
|
3231
|
+
const useLastDistance = (distCode & 1023) === 0;
|
|
3232
|
+
return {
|
|
3233
|
+
insertLen,
|
|
3234
|
+
copyLen: copyLenEncoded,
|
|
3235
|
+
distExtra,
|
|
3236
|
+
cmdPrefix: getLengthCode(insertLen, copyLen + copyLenCodeDelta, useLastDistance),
|
|
3237
|
+
distPrefix
|
|
3238
|
+
};
|
|
3239
|
+
}
|
|
3240
|
+
function createInsertCommand(insertLen) {
|
|
3241
|
+
const copyLenCode = 2;
|
|
3242
|
+
const insCode = getInsertLengthCode(insertLen);
|
|
3243
|
+
let cmdPrefix;
|
|
3244
|
+
if (insCode < 8) cmdPrefix = getLengthCode(insertLen, copyLenCode, true);
|
|
3245
|
+
else cmdPrefix = getLengthCode(insertLen, copyLenCode, false);
|
|
3246
|
+
return {
|
|
3247
|
+
insertLen,
|
|
3248
|
+
copyLen: 67108864,
|
|
3249
|
+
distExtra: 0,
|
|
3250
|
+
cmdPrefix,
|
|
3251
|
+
distPrefix: 0
|
|
3252
|
+
};
|
|
3253
|
+
}
|
|
3254
|
+
function commandCopyLen(cmd) {
|
|
3255
|
+
return cmd.copyLen & 33554431;
|
|
3256
|
+
}
|
|
3257
|
+
function commandCopyLenCode(cmd) {
|
|
3258
|
+
const modifier = cmd.copyLen >>> 25;
|
|
3259
|
+
const delta = modifier & 64 ? modifier | 4294967168 : modifier;
|
|
3260
|
+
return (cmd.copyLen & 33554431) + delta;
|
|
3261
|
+
}
|
|
3262
|
+
|
|
3263
|
+
//#endregion
|
|
3264
|
+
//#region src/encode/backward-references.ts
|
|
3265
|
+
function createBackwardReferences(numBytes, position, ringbuffer, ringbufferMask, hasher, distCache, lastInsertLen, _quality) {
|
|
3266
|
+
const commands = [];
|
|
3267
|
+
let numLiterals = 0;
|
|
3268
|
+
let insertLen = lastInsertLen;
|
|
3269
|
+
let pos = position;
|
|
3270
|
+
const posEnd = position + numBytes;
|
|
3271
|
+
const maxWindowBackward = (1 << 22) - 16;
|
|
3272
|
+
while (pos < posEnd) {
|
|
3273
|
+
const maxLen = posEnd - pos;
|
|
3274
|
+
if (maxLen < 4) {
|
|
3275
|
+
insertLen += maxLen;
|
|
3276
|
+
pos += maxLen;
|
|
3277
|
+
break;
|
|
3278
|
+
}
|
|
3279
|
+
const maxBackward = Math.min(pos, maxWindowBackward);
|
|
3280
|
+
const result = createSearchResult();
|
|
3281
|
+
hasher.findLongestMatch(ringbuffer, ringbufferMask, distCache, pos, Math.min(maxLen, 128), maxBackward, result);
|
|
3282
|
+
if (result.len >= 4 && result.score > 0 && result.distance > 0) {
|
|
3283
|
+
const distance = result.distance;
|
|
3284
|
+
const matchLen = result.len;
|
|
3285
|
+
if (distance > pos) {
|
|
3286
|
+
hasher.store(ringbuffer, ringbufferMask, pos);
|
|
3287
|
+
insertLen++;
|
|
3288
|
+
pos++;
|
|
3289
|
+
continue;
|
|
3290
|
+
}
|
|
3291
|
+
const distCode = distanceToCode(distance, distCache);
|
|
3292
|
+
const cmd = createCommand(insertLen, matchLen, result.lenCodeDelta, distCode);
|
|
3293
|
+
commands.push(cmd);
|
|
3294
|
+
numLiterals += insertLen;
|
|
3295
|
+
if (distCode > 0) {
|
|
3296
|
+
distCache[3] = distCache[2];
|
|
3297
|
+
distCache[2] = distCache[1];
|
|
3298
|
+
distCache[1] = distCache[0];
|
|
3299
|
+
distCache[0] = distance;
|
|
3300
|
+
}
|
|
3301
|
+
const storeEnd = Math.min(pos + matchLen, posEnd - 4);
|
|
3302
|
+
for (let i = pos + 1; i < storeEnd; i++) hasher.store(ringbuffer, ringbufferMask, i);
|
|
3303
|
+
pos += matchLen;
|
|
3304
|
+
insertLen = 0;
|
|
3305
|
+
} else {
|
|
3306
|
+
hasher.store(ringbuffer, ringbufferMask, pos);
|
|
3307
|
+
insertLen++;
|
|
3308
|
+
pos++;
|
|
3309
|
+
}
|
|
3310
|
+
}
|
|
3311
|
+
if (insertLen > 0) {
|
|
3312
|
+
const cmd = createInsertCommand(insertLen);
|
|
3313
|
+
commands.push(cmd);
|
|
3314
|
+
numLiterals += insertLen;
|
|
3315
|
+
insertLen = 0;
|
|
3316
|
+
}
|
|
3317
|
+
return [
|
|
3318
|
+
commands,
|
|
3319
|
+
numLiterals,
|
|
3320
|
+
insertLen
|
|
3321
|
+
];
|
|
3322
|
+
}
|
|
3323
|
+
const DISTANCE_CACHE_INDEX$1 = new Uint8Array([
|
|
3324
|
+
0,
|
|
3325
|
+
1,
|
|
3326
|
+
2,
|
|
3327
|
+
3,
|
|
3328
|
+
0,
|
|
3329
|
+
0,
|
|
3330
|
+
0,
|
|
3331
|
+
0,
|
|
3332
|
+
0,
|
|
3333
|
+
0,
|
|
3334
|
+
1,
|
|
3335
|
+
1,
|
|
3336
|
+
1,
|
|
3337
|
+
1,
|
|
3338
|
+
1,
|
|
3339
|
+
1
|
|
3340
|
+
]);
|
|
3341
|
+
const DISTANCE_CACHE_OFFSET$1 = new Int8Array([
|
|
3342
|
+
0,
|
|
3343
|
+
0,
|
|
3344
|
+
0,
|
|
3345
|
+
0,
|
|
3346
|
+
-1,
|
|
3347
|
+
1,
|
|
3348
|
+
-2,
|
|
3349
|
+
2,
|
|
3350
|
+
-3,
|
|
3351
|
+
3,
|
|
3352
|
+
-1,
|
|
3353
|
+
1,
|
|
3354
|
+
-2,
|
|
3355
|
+
2,
|
|
3356
|
+
-3,
|
|
3357
|
+
3
|
|
3358
|
+
]);
|
|
3359
|
+
function distanceToCode(distance, distCache) {
|
|
3360
|
+
for (let i = 0; i < NUM_DISTANCE_SHORT_CODES; i++) {
|
|
3361
|
+
const cached = distCache[DISTANCE_CACHE_INDEX$1[i]] + DISTANCE_CACHE_OFFSET$1[i];
|
|
3362
|
+
if (distance === cached && cached > 0) return i;
|
|
3363
|
+
}
|
|
3364
|
+
return distance + NUM_DISTANCE_SHORT_CODES - 1;
|
|
3365
|
+
}
|
|
3366
|
+
function backwardMatchLength(match) {
|
|
3367
|
+
return match.length;
|
|
3368
|
+
}
|
|
3369
|
+
|
|
3370
|
+
//#endregion
|
|
3371
|
+
//#region src/encode/zopfli-cost-model.ts
|
|
3372
|
+
const INFINITY_COST = 17e37;
|
|
3373
|
+
var ZopfliCostModel = class {
|
|
3374
|
+
constructor(numBytes, distanceAlphabetSize) {
|
|
3375
|
+
this.minCostCmd = INFINITY_COST;
|
|
3376
|
+
this.numBytes = numBytes;
|
|
3377
|
+
this.distanceHistogramSize = distanceAlphabetSize;
|
|
3378
|
+
this.costCmd = new Float32Array(NUM_COMMAND_CODES);
|
|
3379
|
+
this.costDist = new Float32Array(distanceAlphabetSize);
|
|
3380
|
+
this.literalCosts = new Float32Array(numBytes + 2);
|
|
3381
|
+
}
|
|
3382
|
+
setFromLiteralCosts(position, ringbuffer, ringbufferMask) {
|
|
3383
|
+
const literalHistograms = new Float64Array(3 * 256);
|
|
3384
|
+
this.estimateBitCostsForLiterals(position, this.numBytes, ringbufferMask, ringbuffer, literalHistograms);
|
|
3385
|
+
this.literalCosts[0] = 0;
|
|
3386
|
+
let literalCarry = 0;
|
|
3387
|
+
for (let i = 0; i < this.numBytes; i++) {
|
|
3388
|
+
const byte = ringbuffer[position + i & ringbufferMask];
|
|
3389
|
+
literalCarry += literalHistograms[byte];
|
|
3390
|
+
this.literalCosts[i + 1] = this.literalCosts[i] + literalCarry;
|
|
3391
|
+
literalCarry -= this.literalCosts[i + 1] - this.literalCosts[i];
|
|
3392
|
+
}
|
|
3393
|
+
for (let i = 0; i < NUM_COMMAND_CODES; i++) this.costCmd[i] = fastLog2(11 + i);
|
|
3394
|
+
for (let i = 0; i < this.distanceHistogramSize; i++) this.costDist[i] = fastLog2(20 + i);
|
|
3395
|
+
this.minCostCmd = fastLog2(11);
|
|
3396
|
+
}
|
|
3397
|
+
setFromCommands(position, ringbuffer, ringbufferMask, commands, lastInsertLen) {
|
|
3398
|
+
const histogramLiteral = new Uint32Array(NUM_LITERAL_CODES);
|
|
3399
|
+
const histogramCmd = new Uint32Array(NUM_COMMAND_CODES);
|
|
3400
|
+
const histogramDist = new Uint32Array(this.distanceHistogramSize);
|
|
3401
|
+
const costLiteral = new Float32Array(NUM_LITERAL_CODES);
|
|
3402
|
+
let pos = position - lastInsertLen;
|
|
3403
|
+
for (const cmd of commands) {
|
|
3404
|
+
const insLen = cmd.insertLen;
|
|
3405
|
+
const copyLen = commandCopyLen(cmd);
|
|
3406
|
+
const distCode = cmd.distPrefix & 1023;
|
|
3407
|
+
const cmdCode = cmd.cmdPrefix;
|
|
3408
|
+
histogramCmd[cmdCode]++;
|
|
3409
|
+
if (cmdCode >= 128) histogramDist[distCode]++;
|
|
3410
|
+
for (let j = 0; j < insLen; j++) histogramLiteral[ringbuffer[pos + j & ringbufferMask]]++;
|
|
3411
|
+
pos += insLen + copyLen;
|
|
3412
|
+
}
|
|
3413
|
+
this.setCostFromHistogram(histogramLiteral, true, costLiteral);
|
|
3414
|
+
this.setCostFromHistogram(histogramCmd, false, this.costCmd);
|
|
3415
|
+
this.setCostFromHistogram(histogramDist, false, this.costDist);
|
|
3416
|
+
this.minCostCmd = INFINITY_COST;
|
|
3417
|
+
for (let i = 0; i < NUM_COMMAND_CODES; i++) if (this.costCmd[i] < this.minCostCmd) this.minCostCmd = this.costCmd[i];
|
|
3418
|
+
this.literalCosts[0] = 0;
|
|
3419
|
+
let literalCarry = 0;
|
|
3420
|
+
for (let i = 0; i < this.numBytes; i++) {
|
|
3421
|
+
const byte = ringbuffer[position + i & ringbufferMask];
|
|
3422
|
+
literalCarry += costLiteral[byte];
|
|
3423
|
+
this.literalCosts[i + 1] = this.literalCosts[i] + literalCarry;
|
|
3424
|
+
literalCarry -= this.literalCosts[i + 1] - this.literalCosts[i];
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
3427
|
+
setCostFromHistogram(histogram, isLiteralHistogram, cost) {
|
|
3428
|
+
let sum = 0;
|
|
3429
|
+
for (let i = 0; i < histogram.length; i++) sum += histogram[i];
|
|
3430
|
+
const log2sum = fastLog2(sum);
|
|
3431
|
+
let missingSymbolSum = sum;
|
|
3432
|
+
if (!isLiteralHistogram) {
|
|
3433
|
+
for (let i = 0; i < histogram.length; i++) if (histogram[i] === 0) missingSymbolSum++;
|
|
3434
|
+
}
|
|
3435
|
+
const missingSymbolCost = fastLog2(missingSymbolSum) + 2;
|
|
3436
|
+
for (let i = 0; i < histogram.length; i++) if (histogram[i] === 0) cost[i] = missingSymbolCost;
|
|
3437
|
+
else {
|
|
3438
|
+
cost[i] = log2sum - fastLog2(histogram[i]);
|
|
3439
|
+
if (cost[i] < 1) cost[i] = 1;
|
|
3440
|
+
}
|
|
3441
|
+
}
|
|
3442
|
+
estimateBitCostsForLiterals(position, numBytes, ringbufferMask, ringbuffer, costs) {
|
|
3443
|
+
const histogram = new Uint32Array(256);
|
|
3444
|
+
for (let i = 0; i < numBytes; i++) histogram[ringbuffer[position + i & ringbufferMask]]++;
|
|
3445
|
+
const log2total = fastLog2(numBytes);
|
|
3446
|
+
for (let i = 0; i < 256; i++) if (histogram[i] === 0) costs[i] = log2total + 2;
|
|
3447
|
+
else {
|
|
3448
|
+
costs[i] = log2total - fastLog2(histogram[i]);
|
|
3449
|
+
if (costs[i] < 1) costs[i] = 1;
|
|
3450
|
+
}
|
|
3451
|
+
}
|
|
3452
|
+
getCommandCost(cmdCode) {
|
|
3453
|
+
return this.costCmd[cmdCode];
|
|
3454
|
+
}
|
|
3455
|
+
getDistanceCost(distCode) {
|
|
3456
|
+
return this.costDist[distCode];
|
|
3457
|
+
}
|
|
3458
|
+
getLiteralCosts(from, to) {
|
|
3459
|
+
return this.literalCosts[to] - this.literalCosts[from];
|
|
3460
|
+
}
|
|
3461
|
+
getMinCostCmd() {
|
|
3462
|
+
return this.minCostCmd;
|
|
3463
|
+
}
|
|
3464
|
+
};
|
|
3465
|
+
|
|
3466
|
+
//#endregion
|
|
3467
|
+
//#region src/encode/backward-references-hq.ts
|
|
3468
|
+
const DISTANCE_CACHE_INDEX = new Uint8Array([
|
|
3469
|
+
0,
|
|
3470
|
+
1,
|
|
3471
|
+
2,
|
|
3472
|
+
3,
|
|
3473
|
+
0,
|
|
3474
|
+
0,
|
|
3475
|
+
0,
|
|
3476
|
+
0,
|
|
3477
|
+
0,
|
|
3478
|
+
0,
|
|
3479
|
+
1,
|
|
3480
|
+
1,
|
|
3481
|
+
1,
|
|
3482
|
+
1,
|
|
3483
|
+
1,
|
|
3484
|
+
1
|
|
3485
|
+
]);
|
|
3486
|
+
const DISTANCE_CACHE_OFFSET = new Int8Array([
|
|
3487
|
+
0,
|
|
3488
|
+
0,
|
|
3489
|
+
0,
|
|
3490
|
+
0,
|
|
3491
|
+
-1,
|
|
3492
|
+
1,
|
|
3493
|
+
-2,
|
|
3494
|
+
2,
|
|
3495
|
+
-3,
|
|
3496
|
+
3,
|
|
3497
|
+
-1,
|
|
3498
|
+
1,
|
|
3499
|
+
-2,
|
|
3500
|
+
2,
|
|
3501
|
+
-3,
|
|
3502
|
+
3
|
|
3503
|
+
]);
|
|
3504
|
+
const LONG_COPY_QUICK_STEP = 16384;
|
|
3505
|
+
function createZopfliNodes(length) {
|
|
3506
|
+
const nodes = new Array(length);
|
|
3507
|
+
for (let i = 0; i < length; i++) nodes[i] = {
|
|
3508
|
+
length: 1,
|
|
3509
|
+
distance: 0,
|
|
3510
|
+
dcodeInsertLength: 0,
|
|
3511
|
+
cost: INFINITY_COST,
|
|
3512
|
+
shortcut: 0
|
|
3513
|
+
};
|
|
3514
|
+
return nodes;
|
|
3515
|
+
}
|
|
3516
|
+
function zopfliNodeCopyLength(node) {
|
|
3517
|
+
return node.length & 33554431;
|
|
3518
|
+
}
|
|
3519
|
+
function zopfliNodeLengthCode(node) {
|
|
3520
|
+
const modifier = node.length >>> 25;
|
|
3521
|
+
return zopfliNodeCopyLength(node) + 9 - modifier;
|
|
3522
|
+
}
|
|
3523
|
+
function zopfliNodeCopyDistance(node) {
|
|
3524
|
+
return node.distance;
|
|
3525
|
+
}
|
|
3526
|
+
function zopfliNodeDistanceCode(node) {
|
|
3527
|
+
const shortCode = node.dcodeInsertLength >>> 27;
|
|
3528
|
+
return shortCode === 0 ? zopfliNodeCopyDistance(node) + NUM_DISTANCE_SHORT_CODES - 1 : shortCode - 1;
|
|
3529
|
+
}
|
|
3530
|
+
function zopfliNodeCommandLength(node) {
|
|
3531
|
+
return zopfliNodeCopyLength(node) + (node.dcodeInsertLength & 134217727);
|
|
3532
|
+
}
|
|
3533
|
+
function zopfliNodeInsertLength(node) {
|
|
3534
|
+
return node.dcodeInsertLength & 134217727;
|
|
3535
|
+
}
|
|
3536
|
+
var StartPosQueue = class {
|
|
3537
|
+
constructor() {
|
|
3538
|
+
this.q = [];
|
|
3539
|
+
this.idx = 0;
|
|
3540
|
+
}
|
|
3541
|
+
push(posdata) {
|
|
3542
|
+
const offset = ~this.idx++ & 7;
|
|
3543
|
+
while (this.q.length < 8) this.q.push({
|
|
3544
|
+
pos: 0,
|
|
3545
|
+
distanceCache: new Int32Array(4),
|
|
3546
|
+
costdiff: INFINITY_COST,
|
|
3547
|
+
cost: INFINITY_COST
|
|
3548
|
+
});
|
|
3549
|
+
this.q[offset] = {
|
|
3550
|
+
pos: posdata.pos,
|
|
3551
|
+
distanceCache: posdata.distanceCache.slice(),
|
|
3552
|
+
costdiff: posdata.costdiff,
|
|
3553
|
+
cost: posdata.cost
|
|
3554
|
+
};
|
|
3555
|
+
const len = this.size();
|
|
3556
|
+
for (let i = 1; i < len; i++) {
|
|
3557
|
+
const a = offset + i - 1 & 7;
|
|
3558
|
+
const b = offset + i & 7;
|
|
3559
|
+
if (this.q[a].costdiff > this.q[b].costdiff) {
|
|
3560
|
+
const tmp = this.q[a];
|
|
3561
|
+
this.q[a] = this.q[b];
|
|
3562
|
+
this.q[b] = tmp;
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
}
|
|
3566
|
+
size() {
|
|
3567
|
+
return Math.min(this.idx, 8);
|
|
3568
|
+
}
|
|
3569
|
+
at(k) {
|
|
3570
|
+
return this.q[k - this.idx & 7];
|
|
3571
|
+
}
|
|
3572
|
+
reset() {
|
|
3573
|
+
this.idx = 0;
|
|
3574
|
+
}
|
|
3575
|
+
};
|
|
3576
|
+
function updateZopfliNode(nodes, pos, startPos, len, lenCode, dist, shortCode, cost) {
|
|
3577
|
+
const next = nodes[pos + len];
|
|
3578
|
+
next.length = len | len + 9 - lenCode << 25;
|
|
3579
|
+
next.distance = dist;
|
|
3580
|
+
next.dcodeInsertLength = shortCode << 27 | pos - startPos;
|
|
3581
|
+
next.cost = cost;
|
|
3582
|
+
}
|
|
3583
|
+
function computeMinimumCopyLength(startCost, nodes, numBytes, pos) {
|
|
3584
|
+
let minCost = startCost;
|
|
3585
|
+
let len = 2;
|
|
3586
|
+
let nextLenBucket = 4;
|
|
3587
|
+
let nextLenOffset = 10;
|
|
3588
|
+
while (pos + len <= numBytes && nodes[pos + len].cost <= minCost) {
|
|
3589
|
+
len++;
|
|
3590
|
+
if (len === nextLenOffset) {
|
|
3591
|
+
minCost += 1;
|
|
3592
|
+
nextLenOffset += nextLenBucket;
|
|
3593
|
+
nextLenBucket *= 2;
|
|
3594
|
+
}
|
|
3595
|
+
}
|
|
3596
|
+
return len;
|
|
3597
|
+
}
|
|
3598
|
+
function computeDistanceShortcut(blockStart, pos, maxBackwardLimit, gap, nodes) {
|
|
3599
|
+
if (pos === 0) return 0;
|
|
3600
|
+
const cLen = zopfliNodeCopyLength(nodes[pos]);
|
|
3601
|
+
const iLen = zopfliNodeInsertLength(nodes[pos]);
|
|
3602
|
+
const dist = zopfliNodeCopyDistance(nodes[pos]);
|
|
3603
|
+
if (dist + cLen <= blockStart + pos + gap && dist <= maxBackwardLimit + gap && zopfliNodeDistanceCode(nodes[pos]) > 0) return pos;
|
|
3604
|
+
else return nodes[pos - cLen - iLen].shortcut;
|
|
3605
|
+
}
|
|
3606
|
+
function computeDistanceCache(pos, startingDistCache, nodes, distCache) {
|
|
3607
|
+
let idx = 0;
|
|
3608
|
+
let p = nodes[pos].shortcut;
|
|
3609
|
+
while (idx < 4 && p > 0) {
|
|
3610
|
+
const iLen = zopfliNodeInsertLength(nodes[p]);
|
|
3611
|
+
const cLen = zopfliNodeCopyLength(nodes[p]);
|
|
3612
|
+
const dist = zopfliNodeCopyDistance(nodes[p]);
|
|
3613
|
+
distCache[idx++] = dist;
|
|
3614
|
+
p = nodes[p - cLen - iLen].shortcut;
|
|
3615
|
+
}
|
|
3616
|
+
for (; idx < 4; idx++) distCache[idx] = startingDistCache[idx - (4 - idx)];
|
|
3617
|
+
}
|
|
3618
|
+
function evaluateNode(blockStart, pos, maxBackwardLimit, gap, startingDistCache, model, queue, nodes) {
|
|
3619
|
+
const nodeCost = nodes[pos].cost;
|
|
3620
|
+
nodes[pos].shortcut = computeDistanceShortcut(blockStart, pos, maxBackwardLimit, gap, nodes);
|
|
3621
|
+
if (nodeCost <= model.getLiteralCosts(0, pos)) {
|
|
3622
|
+
const distanceCache = new Int32Array(4);
|
|
3623
|
+
computeDistanceCache(pos, startingDistCache, nodes, distanceCache);
|
|
3624
|
+
queue.push({
|
|
3625
|
+
pos,
|
|
3626
|
+
cost: nodeCost,
|
|
3627
|
+
costdiff: nodeCost - model.getLiteralCosts(0, pos),
|
|
3628
|
+
distanceCache
|
|
3629
|
+
});
|
|
3630
|
+
}
|
|
3631
|
+
}
|
|
3632
|
+
function updateNodes(numBytes, blockStart, pos, ringbuffer, ringbufferMask, quality, maxBackwardLimit, startingDistCache, numMatches, matches, model, queue, nodes) {
|
|
3633
|
+
const curIx = blockStart + pos;
|
|
3634
|
+
const curIxMasked = curIx & ringbufferMask;
|
|
3635
|
+
const maxDistance = Math.min(curIx, maxBackwardLimit);
|
|
3636
|
+
const maxLen = numBytes - pos;
|
|
3637
|
+
const maxZopfliLenVal = maxZopfliLen(quality);
|
|
3638
|
+
const maxIters = maxZopfliCandidates(quality);
|
|
3639
|
+
evaluateNode(blockStart, pos, maxBackwardLimit, 0, startingDistCache, model, queue, nodes);
|
|
3640
|
+
const posdata0 = queue.at(0);
|
|
3641
|
+
let minLen = computeMinimumCopyLength(posdata0.cost + model.getMinCostCmd() + model.getLiteralCosts(posdata0.pos, pos), nodes, numBytes, pos);
|
|
3642
|
+
let result = 0;
|
|
3643
|
+
for (let k = 0; k < maxIters && k < queue.size(); k++) {
|
|
3644
|
+
const posdata = queue.at(k);
|
|
3645
|
+
const start = posdata.pos;
|
|
3646
|
+
const insCode = getInsertLengthCode(pos - start);
|
|
3647
|
+
const baseCost = posdata.costdiff + getInsertExtra(insCode) + model.getLiteralCosts(0, pos);
|
|
3648
|
+
let bestLen = minLen - 1;
|
|
3649
|
+
for (let j = 0; j < NUM_DISTANCE_SHORT_CODES && bestLen < maxLen; j++) {
|
|
3650
|
+
const idx = DISTANCE_CACHE_INDEX[j];
|
|
3651
|
+
const backward = posdata.distanceCache[idx] + DISTANCE_CACHE_OFFSET[j];
|
|
3652
|
+
if (backward <= 0 || backward > maxDistance) continue;
|
|
3653
|
+
let prevIx = curIx - backward;
|
|
3654
|
+
prevIx &= ringbufferMask;
|
|
3655
|
+
if (curIxMasked + bestLen > ringbufferMask) break;
|
|
3656
|
+
if (ringbuffer[prevIx + bestLen] !== ringbuffer[curIxMasked + bestLen]) continue;
|
|
3657
|
+
const len = findMatchLength(ringbuffer, prevIx, curIxMasked, maxLen);
|
|
3658
|
+
if (len >= 4) {
|
|
3659
|
+
const distCost = baseCost + model.getDistanceCost(j);
|
|
3660
|
+
for (let l = bestLen + 1; l <= len; l++) {
|
|
3661
|
+
const copyCode = getCopyLengthCode(l);
|
|
3662
|
+
const cmdCode = combineLengthCodes(insCode, copyCode, j === 0);
|
|
3663
|
+
const cost = (cmdCode < 128 ? baseCost : distCost) + getCopyExtra(copyCode) + model.getCommandCost(cmdCode);
|
|
3664
|
+
if (cost < nodes[pos + l].cost) {
|
|
3665
|
+
updateZopfliNode(nodes, pos, start, l, l, backward, j + 1, cost);
|
|
3666
|
+
result = Math.max(result, l);
|
|
3667
|
+
}
|
|
3668
|
+
bestLen = l;
|
|
3669
|
+
}
|
|
3670
|
+
}
|
|
3671
|
+
}
|
|
3672
|
+
if (k >= 2) continue;
|
|
3673
|
+
let matchLen = minLen;
|
|
3674
|
+
for (let j = 0; j < numMatches; j++) {
|
|
3675
|
+
const match = matches[j];
|
|
3676
|
+
const dist = match.distance;
|
|
3677
|
+
const isDictionaryMatch = dist > maxDistance;
|
|
3678
|
+
const distCode = dist + NUM_DISTANCE_SHORT_CODES - 1;
|
|
3679
|
+
const distCost = baseCost + (distCode < NUM_DISTANCE_SHORT_CODES ? 0 : log2FloorNonZero(dist) - 1) + model.getDistanceCost(distCode & 1023);
|
|
3680
|
+
let maxMatchLen = backwardMatchLength(match);
|
|
3681
|
+
if (matchLen < maxMatchLen && (isDictionaryMatch || maxMatchLen > maxZopfliLenVal)) matchLen = maxMatchLen;
|
|
3682
|
+
for (; matchLen <= maxMatchLen; matchLen++) {
|
|
3683
|
+
const lenCode = isDictionaryMatch ? match.length + match.lenCodeDelta : matchLen;
|
|
3684
|
+
const copyCode = getCopyLengthCode(lenCode);
|
|
3685
|
+
const cmdCode = combineLengthCodes(insCode, copyCode, false);
|
|
3686
|
+
const cost = distCost + getCopyExtra(copyCode) + model.getCommandCost(cmdCode);
|
|
3687
|
+
if (cost < nodes[pos + matchLen].cost) {
|
|
3688
|
+
updateZopfliNode(nodes, pos, start, matchLen, lenCode, dist, 0, cost);
|
|
3689
|
+
result = Math.max(result, matchLen);
|
|
3690
|
+
}
|
|
3691
|
+
}
|
|
3692
|
+
}
|
|
3693
|
+
}
|
|
3694
|
+
return result;
|
|
3695
|
+
}
|
|
3696
|
+
function computeShortestPathFromNodes(numBytes, nodes) {
|
|
3697
|
+
let index = numBytes;
|
|
3698
|
+
let numCommands = 0;
|
|
3699
|
+
while ((nodes[index].dcodeInsertLength & 134217727) === 0 && nodes[index].length === 1) index--;
|
|
3700
|
+
nodes[index].cost = 4294967295;
|
|
3701
|
+
while (index !== 0) {
|
|
3702
|
+
const len = zopfliNodeCommandLength(nodes[index]);
|
|
3703
|
+
index -= len;
|
|
3704
|
+
nodes[index].cost = len;
|
|
3705
|
+
numCommands++;
|
|
3706
|
+
}
|
|
3707
|
+
return numCommands;
|
|
3708
|
+
}
|
|
3709
|
+
function createZopfliBackwardReferences(numBytes, position, ringbuffer, ringbufferMask, quality, hasher, distCache, lastInsertLen) {
|
|
3710
|
+
const maxBackwardLimit = (1 << 22) - 16;
|
|
3711
|
+
const maxZopfliLenVal = maxZopfliLen(quality);
|
|
3712
|
+
const nodes = createZopfliNodes(numBytes + 1);
|
|
3713
|
+
nodes[0].length = 0;
|
|
3714
|
+
nodes[0].cost = 0;
|
|
3715
|
+
const model = new ZopfliCostModel(numBytes, 544);
|
|
3716
|
+
model.setFromLiteralCosts(position, ringbuffer, ringbufferMask);
|
|
3717
|
+
const queue = new StartPosQueue();
|
|
3718
|
+
for (let i = 0; i + 3 < numBytes; i++) {
|
|
3719
|
+
const pos = position + i;
|
|
3720
|
+
const maxDistance = Math.min(pos, maxBackwardLimit);
|
|
3721
|
+
const matches = hasher.findAllMatches(ringbuffer, ringbufferMask, pos, numBytes - i, maxDistance);
|
|
3722
|
+
if (matches.length > 0) {
|
|
3723
|
+
const longestMatch = matches[matches.length - 1];
|
|
3724
|
+
if (backwardMatchLength(longestMatch) > maxZopfliLenVal) {
|
|
3725
|
+
matches.length = 0;
|
|
3726
|
+
matches.push(longestMatch);
|
|
3727
|
+
}
|
|
3728
|
+
}
|
|
3729
|
+
const skip = updateNodes(numBytes, position, i, ringbuffer, ringbufferMask, quality, maxBackwardLimit, distCache, matches.length, matches, model, queue, nodes);
|
|
3730
|
+
if (skip >= LONG_COPY_QUICK_STEP) i += skip - 1;
|
|
3731
|
+
else if (matches.length === 1 && backwardMatchLength(matches[0]) > maxZopfliLenVal) i += backwardMatchLength(matches[0]) - 1;
|
|
3732
|
+
}
|
|
3733
|
+
computeShortestPathFromNodes(numBytes, nodes);
|
|
3734
|
+
return createCommandsFromPath(numBytes, position, nodes, distCache, lastInsertLen);
|
|
3735
|
+
}
|
|
3736
|
+
function createHqZopfliBackwardReferences(numBytes, position, ringbuffer, ringbufferMask, hasher, distCache, lastInsertLen) {
|
|
3737
|
+
const quality = 11;
|
|
3738
|
+
const maxBackwardLimit = (1 << 22) - 16;
|
|
3739
|
+
const maxZopfliLenVal = maxZopfliLen(quality);
|
|
3740
|
+
const allMatches = [];
|
|
3741
|
+
const numMatchesPerPos = [];
|
|
3742
|
+
for (let i = 0; i + 3 < numBytes; i++) {
|
|
3743
|
+
const pos = position + i;
|
|
3744
|
+
const maxDistance = Math.min(pos, maxBackwardLimit);
|
|
3745
|
+
const matches = hasher.findAllMatches(ringbuffer, ringbufferMask, pos, numBytes - i, maxDistance);
|
|
3746
|
+
if (matches.length > 0) {
|
|
3747
|
+
const longestMatch = matches[matches.length - 1];
|
|
3748
|
+
if (backwardMatchLength(longestMatch) > maxZopfliLenVal) {
|
|
3749
|
+
const skip = backwardMatchLength(longestMatch) - 1;
|
|
3750
|
+
allMatches.push([longestMatch]);
|
|
3751
|
+
numMatchesPerPos.push(1);
|
|
3752
|
+
for (let j = 0; j < skip && i + j + 1 < numBytes; j++) {
|
|
3753
|
+
allMatches.push([]);
|
|
3754
|
+
numMatchesPerPos.push(0);
|
|
3755
|
+
}
|
|
3756
|
+
i += skip;
|
|
3757
|
+
continue;
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
allMatches.push(matches);
|
|
3761
|
+
numMatchesPerPos.push(matches.length);
|
|
3762
|
+
}
|
|
3763
|
+
while (allMatches.length < numBytes) {
|
|
3764
|
+
allMatches.push([]);
|
|
3765
|
+
numMatchesPerPos.push(0);
|
|
3766
|
+
}
|
|
3767
|
+
const origDistCache = distCache.slice();
|
|
3768
|
+
const origLastInsertLen = lastInsertLen;
|
|
3769
|
+
const model = new ZopfliCostModel(numBytes, 544);
|
|
3770
|
+
let commands = [];
|
|
3771
|
+
let numLiterals = 0;
|
|
3772
|
+
let finalLastInsertLen = lastInsertLen;
|
|
3773
|
+
for (let iteration = 0; iteration < 2; iteration++) {
|
|
3774
|
+
const nodes = createZopfliNodes(numBytes + 1);
|
|
3775
|
+
nodes[0].length = 0;
|
|
3776
|
+
nodes[0].cost = 0;
|
|
3777
|
+
distCache.set(origDistCache);
|
|
3778
|
+
lastInsertLen = origLastInsertLen;
|
|
3779
|
+
if (iteration === 0) model.setFromLiteralCosts(position, ringbuffer, ringbufferMask);
|
|
3780
|
+
else model.setFromCommands(position, ringbuffer, ringbufferMask, commands, origLastInsertLen);
|
|
3781
|
+
const queue = new StartPosQueue();
|
|
3782
|
+
for (let i = 0; i + 3 < numBytes; i++) {
|
|
3783
|
+
const numMatches = numMatchesPerPos[i];
|
|
3784
|
+
const matches = allMatches[i];
|
|
3785
|
+
const skip = updateNodes(numBytes, position, i, ringbuffer, ringbufferMask, quality, maxBackwardLimit, distCache, numMatches, matches, model, queue, nodes);
|
|
3786
|
+
if (skip >= LONG_COPY_QUICK_STEP) i += skip - 1;
|
|
3787
|
+
else if (numMatches === 1 && backwardMatchLength(matches[0]) > maxZopfliLenVal) i += backwardMatchLength(matches[0]) - 1;
|
|
3788
|
+
}
|
|
3789
|
+
computeShortestPathFromNodes(numBytes, nodes);
|
|
3790
|
+
[commands, numLiterals, finalLastInsertLen] = createCommandsFromPath(numBytes, position, nodes, distCache, lastInsertLen);
|
|
3791
|
+
}
|
|
3792
|
+
return [
|
|
3793
|
+
commands,
|
|
3794
|
+
numLiterals,
|
|
3795
|
+
finalLastInsertLen
|
|
3796
|
+
];
|
|
3797
|
+
}
|
|
3798
|
+
function createCommandsFromPath(numBytes, blockStart, nodes, distCache, lastInsertLen) {
|
|
3799
|
+
const maxBackwardLimit = (1 << 22) - 16;
|
|
3800
|
+
const commands = [];
|
|
3801
|
+
let numLiterals = 0;
|
|
3802
|
+
let pos = 0;
|
|
3803
|
+
let offset = nodes[0].cost;
|
|
3804
|
+
let isFirst = true;
|
|
3805
|
+
while (offset !== 4294967295 && offset !== 0) {
|
|
3806
|
+
const next = nodes[pos + offset];
|
|
3807
|
+
const copyLen = zopfliNodeCopyLength(next);
|
|
3808
|
+
let insertLen = zopfliNodeInsertLength(next);
|
|
3809
|
+
pos += insertLen;
|
|
3810
|
+
if (isFirst) {
|
|
3811
|
+
insertLen += lastInsertLen;
|
|
3812
|
+
isFirst = false;
|
|
3813
|
+
}
|
|
3814
|
+
const distance = zopfliNodeCopyDistance(next);
|
|
3815
|
+
const lenCode = zopfliNodeLengthCode(next);
|
|
3816
|
+
const distCode = zopfliNodeDistanceCode(next);
|
|
3817
|
+
const cmd = createCommand(insertLen, copyLen, lenCode - copyLen, distCode);
|
|
3818
|
+
commands.push(cmd);
|
|
3819
|
+
if (!(distance > Math.min(blockStart + pos, maxBackwardLimit)) && distCode > 0) {
|
|
3820
|
+
distCache[3] = distCache[2];
|
|
3821
|
+
distCache[2] = distCache[1];
|
|
3822
|
+
distCache[1] = distCache[0];
|
|
3823
|
+
distCache[0] = distance;
|
|
3824
|
+
}
|
|
3825
|
+
numLiterals += insertLen;
|
|
3826
|
+
pos += copyLen;
|
|
3827
|
+
offset = next.cost;
|
|
3828
|
+
}
|
|
3829
|
+
const finalInsertLen = numBytes - pos;
|
|
3830
|
+
return [
|
|
3831
|
+
commands,
|
|
3832
|
+
numLiterals,
|
|
3833
|
+
finalInsertLen
|
|
3834
|
+
];
|
|
3835
|
+
}
|
|
3836
|
+
|
|
3837
|
+
//#endregion
|
|
3838
|
+
//#region src/encode/histogram.ts
|
|
3839
|
+
const NUM_DISTANCE_HISTOGRAM_SYMBOLS = 544;
|
|
3840
|
+
function createHistogramLiteral() {
|
|
3841
|
+
return {
|
|
3842
|
+
data: new Uint32Array(NUM_LITERAL_CODES),
|
|
3843
|
+
totalCount: 0,
|
|
3844
|
+
bitCost: Infinity
|
|
3845
|
+
};
|
|
3846
|
+
}
|
|
3847
|
+
function createHistogramCommand() {
|
|
3848
|
+
return {
|
|
3849
|
+
data: new Uint32Array(NUM_COMMAND_CODES),
|
|
3850
|
+
totalCount: 0,
|
|
3851
|
+
bitCost: Infinity
|
|
3852
|
+
};
|
|
3853
|
+
}
|
|
3854
|
+
function createHistogramDistance() {
|
|
3855
|
+
return {
|
|
3856
|
+
data: new Uint32Array(NUM_DISTANCE_HISTOGRAM_SYMBOLS),
|
|
3857
|
+
totalCount: 0,
|
|
3858
|
+
bitCost: Infinity
|
|
3859
|
+
};
|
|
3860
|
+
}
|
|
3861
|
+
function histogramAdd(histogram, symbol) {
|
|
3862
|
+
histogram.data[symbol]++;
|
|
3863
|
+
histogram.totalCount++;
|
|
3864
|
+
}
|
|
3865
|
+
|
|
3866
|
+
//#endregion
|
|
3867
|
+
//#region src/encode/entropy-encode.ts
|
|
3868
|
+
const MAX_HUFFMAN_BITS = 15;
|
|
3869
|
+
const SHELL_GAPS = [
|
|
3870
|
+
132,
|
|
3871
|
+
57,
|
|
3872
|
+
23,
|
|
3873
|
+
10,
|
|
3874
|
+
4,
|
|
3875
|
+
1
|
|
3876
|
+
];
|
|
3877
|
+
function createHuffmanTree(histogram, treeLimit = MAX_HUFFMAN_BITS) {
|
|
3878
|
+
const length = histogram.length;
|
|
3879
|
+
const depths = new Uint8Array(length);
|
|
3880
|
+
const bits = new Uint16Array(length);
|
|
3881
|
+
let nonZeroCount = 0;
|
|
3882
|
+
let lastNonZero = 0;
|
|
3883
|
+
for (let i = 0; i < length; i++) if (histogram[i] > 0) {
|
|
3884
|
+
nonZeroCount++;
|
|
3885
|
+
lastNonZero = i;
|
|
3886
|
+
}
|
|
3887
|
+
if (nonZeroCount === 0) return {
|
|
3888
|
+
depths,
|
|
3889
|
+
bits
|
|
3890
|
+
};
|
|
3891
|
+
if (nonZeroCount === 1) {
|
|
3892
|
+
depths[lastNonZero] = 1;
|
|
3893
|
+
bits[lastNonZero] = 0;
|
|
3894
|
+
return {
|
|
3895
|
+
depths,
|
|
3896
|
+
bits
|
|
3897
|
+
};
|
|
3898
|
+
}
|
|
3899
|
+
const tree = new Array(2 * length + 2);
|
|
3900
|
+
for (let countLimit = 1;; countLimit *= 2) {
|
|
3901
|
+
let n = 0;
|
|
3902
|
+
for (let i = length - 1; i >= 0; i--) if (histogram[i] > 0) {
|
|
3903
|
+
const count = Math.max(histogram[i], countLimit);
|
|
3904
|
+
tree[n++] = {
|
|
3905
|
+
totalCount: count,
|
|
3906
|
+
indexLeft: -1,
|
|
3907
|
+
indexRightOrValue: i
|
|
3908
|
+
};
|
|
3909
|
+
}
|
|
3910
|
+
sortHuffmanNodes(tree, n);
|
|
3911
|
+
const sentinel = {
|
|
3912
|
+
totalCount: 4294967295,
|
|
3913
|
+
indexLeft: -1,
|
|
3914
|
+
indexRightOrValue: -1
|
|
3915
|
+
};
|
|
3916
|
+
tree[n] = sentinel;
|
|
3917
|
+
tree[n + 1] = sentinel;
|
|
3918
|
+
let i = 0;
|
|
3919
|
+
let j = n + 1;
|
|
3920
|
+
for (let k = n - 1; k > 0; k--) {
|
|
3921
|
+
let left;
|
|
3922
|
+
if (tree[i].totalCount <= tree[j].totalCount) left = i++;
|
|
3923
|
+
else left = j++;
|
|
3924
|
+
let right;
|
|
3925
|
+
if (tree[i].totalCount <= tree[j].totalCount) right = i++;
|
|
3926
|
+
else right = j++;
|
|
3927
|
+
const jEnd = 2 * n - k;
|
|
3928
|
+
tree[jEnd] = {
|
|
3929
|
+
totalCount: tree[left].totalCount + tree[right].totalCount,
|
|
3930
|
+
indexLeft: left,
|
|
3931
|
+
indexRightOrValue: right
|
|
3932
|
+
};
|
|
3933
|
+
tree[jEnd + 1] = sentinel;
|
|
3934
|
+
}
|
|
3935
|
+
if (setDepth(2 * n - 1, tree, depths, treeLimit)) break;
|
|
3936
|
+
depths.fill(0);
|
|
3937
|
+
}
|
|
3938
|
+
convertBitDepthsToSymbols(depths, bits);
|
|
3939
|
+
return {
|
|
3940
|
+
depths,
|
|
3941
|
+
bits
|
|
3942
|
+
};
|
|
3943
|
+
}
|
|
3944
|
+
function setDepth(root, tree, depths, maxDepth) {
|
|
3945
|
+
const stack = new Int32Array(16);
|
|
3946
|
+
let level = 0;
|
|
3947
|
+
let p = root;
|
|
3948
|
+
stack[0] = -1;
|
|
3949
|
+
while (true) {
|
|
3950
|
+
if (tree[p].indexLeft >= 0) {
|
|
3951
|
+
level++;
|
|
3952
|
+
if (level > maxDepth) return false;
|
|
3953
|
+
stack[level] = tree[p].indexRightOrValue;
|
|
3954
|
+
p = tree[p].indexLeft;
|
|
3955
|
+
continue;
|
|
3956
|
+
} else depths[tree[p].indexRightOrValue] = level;
|
|
3957
|
+
while (level >= 0 && stack[level] === -1) level--;
|
|
3958
|
+
if (level < 0) return true;
|
|
3959
|
+
p = stack[level];
|
|
3960
|
+
stack[level] = -1;
|
|
3961
|
+
}
|
|
3962
|
+
}
|
|
3963
|
+
function sortHuffmanNodes(nodes, n) {
|
|
3964
|
+
if (n < 13) for (let i = 1; i < n; i++) {
|
|
3965
|
+
const tmp = nodes[i];
|
|
3966
|
+
let k = i;
|
|
3967
|
+
let j = i - 1;
|
|
3968
|
+
while (j >= 0 && compareNodes(tmp, nodes[j])) {
|
|
3969
|
+
nodes[k] = nodes[j];
|
|
3970
|
+
k = j;
|
|
3971
|
+
j--;
|
|
3972
|
+
}
|
|
3973
|
+
nodes[k] = tmp;
|
|
3974
|
+
}
|
|
3975
|
+
else {
|
|
3976
|
+
const startGap = n < 57 ? 2 : 0;
|
|
3977
|
+
for (let g = startGap; g < 6; g++) {
|
|
3978
|
+
const gap = SHELL_GAPS[g];
|
|
3979
|
+
for (let i = gap; i < n; i++) {
|
|
3980
|
+
let j = i;
|
|
3981
|
+
const tmp = nodes[i];
|
|
3982
|
+
while (j >= gap && compareNodes(tmp, nodes[j - gap])) {
|
|
3983
|
+
nodes[j] = nodes[j - gap];
|
|
3984
|
+
j -= gap;
|
|
3985
|
+
}
|
|
3986
|
+
nodes[j] = tmp;
|
|
3987
|
+
}
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
}
|
|
3991
|
+
function compareNodes(a, b) {
|
|
3992
|
+
if (a.totalCount !== b.totalCount) return a.totalCount < b.totalCount;
|
|
3993
|
+
return a.indexRightOrValue > b.indexRightOrValue;
|
|
3994
|
+
}
|
|
3995
|
+
function reverseBits(numBits, bits) {
|
|
3996
|
+
const LUT = [
|
|
3997
|
+
0,
|
|
3998
|
+
8,
|
|
3999
|
+
4,
|
|
4000
|
+
12,
|
|
4001
|
+
2,
|
|
4002
|
+
10,
|
|
4003
|
+
6,
|
|
4004
|
+
14,
|
|
4005
|
+
1,
|
|
4006
|
+
9,
|
|
4007
|
+
5,
|
|
4008
|
+
13,
|
|
4009
|
+
3,
|
|
4010
|
+
11,
|
|
4011
|
+
7,
|
|
4012
|
+
15
|
|
4013
|
+
];
|
|
4014
|
+
let retval = LUT[bits & 15];
|
|
4015
|
+
for (let i = 4; i < numBits; i += 4) {
|
|
4016
|
+
retval <<= 4;
|
|
4017
|
+
bits >>>= 4;
|
|
4018
|
+
retval |= LUT[bits & 15];
|
|
4019
|
+
}
|
|
4020
|
+
retval >>>= -numBits & 3;
|
|
4021
|
+
return retval;
|
|
4022
|
+
}
|
|
4023
|
+
function convertBitDepthsToSymbols(depths, bits) {
|
|
4024
|
+
const len = depths.length;
|
|
4025
|
+
const blCount = new Uint16Array(MAX_HUFFMAN_BITS + 1);
|
|
4026
|
+
const nextCode = new Uint16Array(MAX_HUFFMAN_BITS + 1);
|
|
4027
|
+
for (let i = 0; i < len; i++) blCount[depths[i]]++;
|
|
4028
|
+
blCount[0] = 0;
|
|
4029
|
+
let code = 0;
|
|
4030
|
+
for (let i = 1; i <= MAX_HUFFMAN_BITS; i++) {
|
|
4031
|
+
code = code + blCount[i - 1] << 1;
|
|
4032
|
+
nextCode[i] = code;
|
|
4033
|
+
}
|
|
4034
|
+
for (let i = 0; i < len; i++) if (depths[i] > 0) bits[i] = reverseBits(depths[i], nextCode[depths[i]]++);
|
|
4035
|
+
}
|
|
4036
|
+
|
|
4037
|
+
//#endregion
|
|
4038
|
+
//#region src/encode/context-map.ts
|
|
4039
|
+
function buildAndStoreHuffmanTree(writer, histogram, alphabetSize, depths, bits) {
|
|
4040
|
+
let count = 0;
|
|
4041
|
+
const s4 = [
|
|
4042
|
+
0,
|
|
4043
|
+
0,
|
|
4044
|
+
0,
|
|
4045
|
+
0
|
|
4046
|
+
];
|
|
4047
|
+
for (let i = 0; i < alphabetSize; i++) if (histogram[i]) {
|
|
4048
|
+
if (count < 4) s4[count] = i;
|
|
4049
|
+
count++;
|
|
4050
|
+
}
|
|
4051
|
+
let maxBits = 0;
|
|
4052
|
+
let maxBitsCounter = alphabetSize - 1;
|
|
4053
|
+
while (maxBitsCounter) {
|
|
4054
|
+
maxBitsCounter >>>= 1;
|
|
4055
|
+
maxBits++;
|
|
4056
|
+
}
|
|
4057
|
+
if (count <= 1) {
|
|
4058
|
+
writer.writeBits(4, 1);
|
|
4059
|
+
writer.writeBits(maxBits, s4[0]);
|
|
4060
|
+
depths[s4[0]] = 0;
|
|
4061
|
+
bits[s4[0]] = 0;
|
|
4062
|
+
return;
|
|
4063
|
+
}
|
|
4064
|
+
depths.fill(0);
|
|
4065
|
+
const tree = createHuffmanTree(histogram.subarray(0, alphabetSize), 15);
|
|
4066
|
+
depths.set(tree.depths.subarray(0, alphabetSize));
|
|
4067
|
+
convertBitDepthsToSymbols(depths, bits);
|
|
4068
|
+
if (count <= 4) storeSimpleHuffmanTree(writer, depths, s4, count, maxBits);
|
|
4069
|
+
else storeComplexHuffmanTree(writer, depths, alphabetSize);
|
|
4070
|
+
}
|
|
4071
|
+
function storeSimpleHuffmanTree(writer, depths, symbols, numSymbols, maxBits) {
|
|
4072
|
+
const sorted = symbols.slice(0, numSymbols);
|
|
4073
|
+
sorted.sort((a, b) => depths[a] - depths[b]);
|
|
4074
|
+
writer.writeBits(2, 1);
|
|
4075
|
+
writer.writeBits(2, numSymbols - 1);
|
|
4076
|
+
for (let i = 0; i < numSymbols; i++) writer.writeBits(maxBits, sorted[i]);
|
|
4077
|
+
if (numSymbols === 4) writer.writeBits(1, depths[sorted[0]] === 1 ? 1 : 0);
|
|
4078
|
+
}
|
|
4079
|
+
function storeComplexHuffmanTree(writer, depths, length) {
|
|
4080
|
+
const huffmanTree = [];
|
|
4081
|
+
const huffmanTreeExtraBits = [];
|
|
4082
|
+
writeHuffmanTreeRepresentation(depths, length, huffmanTree, huffmanTreeExtraBits);
|
|
4083
|
+
const codeLengthHistogram = new Uint32Array(18);
|
|
4084
|
+
for (const code of huffmanTree) codeLengthHistogram[code]++;
|
|
4085
|
+
let numCodes = 0;
|
|
4086
|
+
let firstCode = 0;
|
|
4087
|
+
for (let i = 0; i < 18; i++) if (codeLengthHistogram[i]) {
|
|
4088
|
+
if (numCodes === 0) firstCode = i;
|
|
4089
|
+
numCodes++;
|
|
4090
|
+
}
|
|
4091
|
+
const codeLengthDepths = new Uint8Array(18);
|
|
4092
|
+
const codeLengthBits = new Uint16Array(18);
|
|
4093
|
+
const tree = createHuffmanTree(codeLengthHistogram, 5);
|
|
4094
|
+
codeLengthDepths.set(tree.depths.subarray(0, 18));
|
|
4095
|
+
convertBitDepthsToSymbols(codeLengthDepths, codeLengthBits);
|
|
4096
|
+
storeHuffmanTreeOfHuffmanTree(writer, numCodes, codeLengthDepths);
|
|
4097
|
+
if (numCodes === 1) codeLengthDepths[firstCode] = 0;
|
|
4098
|
+
for (let i = 0; i < huffmanTree.length; i++) {
|
|
4099
|
+
const code = huffmanTree[i];
|
|
4100
|
+
writer.writeBits(codeLengthDepths[code], codeLengthBits[code]);
|
|
4101
|
+
if (code === 16) writer.writeBits(2, huffmanTreeExtraBits[i]);
|
|
4102
|
+
else if (code === 17) writer.writeBits(3, huffmanTreeExtraBits[i]);
|
|
4103
|
+
}
|
|
4104
|
+
}
|
|
4105
|
+
function writeHuffmanTreeRepresentation(depths, length, tree, extraBits) {
|
|
4106
|
+
const INITIAL_PREV = 8;
|
|
4107
|
+
let newLength = length;
|
|
4108
|
+
while (newLength > 0 && depths[newLength - 1] === 0) newLength--;
|
|
4109
|
+
let prevValue = INITIAL_PREV;
|
|
4110
|
+
let i = 0;
|
|
4111
|
+
while (i < newLength) {
|
|
4112
|
+
const value = depths[i];
|
|
4113
|
+
let reps = 1;
|
|
4114
|
+
while (i + reps < newLength && depths[i + reps] === value) reps++;
|
|
4115
|
+
i += reps;
|
|
4116
|
+
if (value === 0) writeHuffmanTreeRepetitionsZeros(reps, tree, extraBits);
|
|
4117
|
+
else {
|
|
4118
|
+
writeHuffmanTreeRepetitions(prevValue, value, reps, tree, extraBits);
|
|
4119
|
+
prevValue = value;
|
|
4120
|
+
}
|
|
4121
|
+
}
|
|
4122
|
+
}
|
|
4123
|
+
function writeHuffmanTreeRepetitions(prevValue, value, reps, tree, extraBits) {
|
|
4124
|
+
const REPEAT_PREVIOUS = 16;
|
|
4125
|
+
if (prevValue !== value) {
|
|
4126
|
+
tree.push(value);
|
|
4127
|
+
extraBits.push(0);
|
|
4128
|
+
reps--;
|
|
4129
|
+
}
|
|
4130
|
+
if (reps === 7) {
|
|
4131
|
+
tree.push(value);
|
|
4132
|
+
extraBits.push(0);
|
|
4133
|
+
reps--;
|
|
4134
|
+
}
|
|
4135
|
+
if (reps < 3) for (let j = 0; j < reps; j++) {
|
|
4136
|
+
tree.push(value);
|
|
4137
|
+
extraBits.push(0);
|
|
4138
|
+
}
|
|
4139
|
+
else {
|
|
4140
|
+
const startIdx = tree.length;
|
|
4141
|
+
reps -= 3;
|
|
4142
|
+
while (true) {
|
|
4143
|
+
tree.push(REPEAT_PREVIOUS);
|
|
4144
|
+
extraBits.push(reps & 3);
|
|
4145
|
+
reps >>>= 2;
|
|
4146
|
+
if (reps === 0) break;
|
|
4147
|
+
reps--;
|
|
4148
|
+
}
|
|
4149
|
+
reverseArraySlice(tree, startIdx, tree.length);
|
|
4150
|
+
reverseArraySlice(extraBits, startIdx, extraBits.length);
|
|
4151
|
+
}
|
|
4152
|
+
}
|
|
4153
|
+
function writeHuffmanTreeRepetitionsZeros(reps, tree, extraBits) {
|
|
4154
|
+
const REPEAT_ZERO = 17;
|
|
4155
|
+
if (reps === 11) {
|
|
4156
|
+
tree.push(0);
|
|
4157
|
+
extraBits.push(0);
|
|
4158
|
+
reps--;
|
|
4159
|
+
}
|
|
4160
|
+
if (reps < 3) for (let j = 0; j < reps; j++) {
|
|
4161
|
+
tree.push(0);
|
|
4162
|
+
extraBits.push(0);
|
|
4163
|
+
}
|
|
4164
|
+
else {
|
|
4165
|
+
const startIdx = tree.length;
|
|
4166
|
+
reps -= 3;
|
|
4167
|
+
while (true) {
|
|
4168
|
+
tree.push(REPEAT_ZERO);
|
|
4169
|
+
extraBits.push(reps & 7);
|
|
4170
|
+
reps >>>= 3;
|
|
4171
|
+
if (reps === 0) break;
|
|
4172
|
+
reps--;
|
|
4173
|
+
}
|
|
4174
|
+
reverseArraySlice(tree, startIdx, tree.length);
|
|
4175
|
+
reverseArraySlice(extraBits, startIdx, extraBits.length);
|
|
4176
|
+
}
|
|
4177
|
+
}
|
|
4178
|
+
function reverseArraySlice(arr, start, end) {
|
|
4179
|
+
while (start < end - 1) {
|
|
4180
|
+
const tmp = arr[start];
|
|
4181
|
+
arr[start] = arr[end - 1];
|
|
4182
|
+
arr[end - 1] = tmp;
|
|
4183
|
+
start++;
|
|
4184
|
+
end--;
|
|
4185
|
+
}
|
|
4186
|
+
}
|
|
4187
|
+
function storeHuffmanTreeOfHuffmanTree(writer, numCodes, depths) {
|
|
4188
|
+
const storageOrder = [
|
|
4189
|
+
1,
|
|
4190
|
+
2,
|
|
4191
|
+
3,
|
|
4192
|
+
4,
|
|
4193
|
+
0,
|
|
4194
|
+
5,
|
|
4195
|
+
17,
|
|
4196
|
+
6,
|
|
4197
|
+
16,
|
|
4198
|
+
7,
|
|
4199
|
+
8,
|
|
4200
|
+
9,
|
|
4201
|
+
10,
|
|
4202
|
+
11,
|
|
4203
|
+
12,
|
|
4204
|
+
13,
|
|
4205
|
+
14,
|
|
4206
|
+
15
|
|
4207
|
+
];
|
|
4208
|
+
const symbols = [
|
|
4209
|
+
0,
|
|
4210
|
+
7,
|
|
4211
|
+
3,
|
|
4212
|
+
2,
|
|
4213
|
+
1,
|
|
4214
|
+
15
|
|
4215
|
+
];
|
|
4216
|
+
const bitLengths = [
|
|
4217
|
+
2,
|
|
4218
|
+
4,
|
|
4219
|
+
3,
|
|
4220
|
+
2,
|
|
4221
|
+
2,
|
|
4222
|
+
4
|
|
4223
|
+
];
|
|
4224
|
+
let codesToStore = 18;
|
|
4225
|
+
if (numCodes > 1) while (codesToStore > 0 && depths[storageOrder[codesToStore - 1]] === 0) codesToStore--;
|
|
4226
|
+
let skipSome = 0;
|
|
4227
|
+
if (depths[storageOrder[0]] === 0 && depths[storageOrder[1]] === 0) {
|
|
4228
|
+
skipSome = 2;
|
|
4229
|
+
if (depths[storageOrder[2]] === 0) skipSome = 3;
|
|
4230
|
+
}
|
|
4231
|
+
writer.writeBits(2, skipSome);
|
|
4232
|
+
for (let i = skipSome; i < codesToStore; i++) {
|
|
4233
|
+
const len = depths[storageOrder[i]];
|
|
4234
|
+
writer.writeBits(bitLengths[len], symbols[len]);
|
|
4235
|
+
}
|
|
4236
|
+
}
|
|
4237
|
+
|
|
4238
|
+
//#endregion
|
|
4239
|
+
//#region src/encode/metablock.ts
|
|
4240
|
+
function encodeMlen(length) {
|
|
4241
|
+
const lg = length === 1 ? 1 : log2FloorNonZero(length - 1) + 1;
|
|
4242
|
+
const mnibbles = Math.floor((lg < 16 ? 16 : lg + 3) / 4);
|
|
4243
|
+
return {
|
|
4244
|
+
bits: BigInt(length - 1),
|
|
4245
|
+
numBits: mnibbles * 4,
|
|
4246
|
+
nibblesBits: mnibbles - 4
|
|
4247
|
+
};
|
|
4248
|
+
}
|
|
4249
|
+
function storeCompressedMetaBlockHeader(writer, isLast, length) {
|
|
4250
|
+
writer.writeBits(1, isLast ? 1 : 0);
|
|
4251
|
+
if (isLast) writer.writeBits(1, 0);
|
|
4252
|
+
const { bits, numBits, nibblesBits } = encodeMlen(length);
|
|
4253
|
+
writer.writeBits(2, nibblesBits);
|
|
4254
|
+
writer.writeBitsLong(numBits, bits);
|
|
4255
|
+
if (!isLast) writer.writeBits(1, 0);
|
|
4256
|
+
}
|
|
4257
|
+
function storeUncompressedMetaBlockHeader(writer, length) {
|
|
4258
|
+
writer.writeBits(1, 0);
|
|
4259
|
+
const { bits, numBits, nibblesBits } = encodeMlen(length);
|
|
4260
|
+
writer.writeBits(2, nibblesBits);
|
|
4261
|
+
writer.writeBitsLong(numBits, bits);
|
|
4262
|
+
writer.writeBits(1, 1);
|
|
4263
|
+
}
|
|
4264
|
+
function storeCommandExtra(writer, cmd) {
|
|
4265
|
+
const copyLenCode = commandCopyLenCode(cmd);
|
|
4266
|
+
const insCode = getInsertLengthCode(cmd.insertLen);
|
|
4267
|
+
const copyCode = getCopyLengthCode(copyLenCode);
|
|
4268
|
+
const insNumExtra = getInsertExtra(insCode);
|
|
4269
|
+
const insExtraVal = cmd.insertLen - getInsertBase(insCode);
|
|
4270
|
+
const copyExtraVal = copyLenCode - getCopyBase(copyCode);
|
|
4271
|
+
const totalBits = insNumExtra + getCopyExtra(copyCode);
|
|
4272
|
+
const combinedBits = copyExtraVal << insNumExtra | insExtraVal;
|
|
4273
|
+
writer.writeBits(totalBits, combinedBits);
|
|
4274
|
+
}
|
|
4275
|
+
function storeMetaBlockTrivial(writer, input, startPos, length, mask, isLast, commands, distanceAlphabetSize) {
|
|
4276
|
+
storeCompressedMetaBlockHeader(writer, isLast, length);
|
|
4277
|
+
const litHisto = createHistogramLiteral();
|
|
4278
|
+
const cmdHisto = createHistogramCommand();
|
|
4279
|
+
const distHisto = createHistogramDistance();
|
|
4280
|
+
let pos = startPos;
|
|
4281
|
+
for (const cmd of commands) {
|
|
4282
|
+
histogramAdd(cmdHisto, cmd.cmdPrefix);
|
|
4283
|
+
for (let j = 0; j < cmd.insertLen; j++) histogramAdd(litHisto, input[pos + j & mask]);
|
|
4284
|
+
pos += cmd.insertLen;
|
|
4285
|
+
const copyLen = commandCopyLen(cmd);
|
|
4286
|
+
pos += copyLen;
|
|
4287
|
+
if (copyLen && cmd.cmdPrefix >= 128) histogramAdd(distHisto, cmd.distPrefix & 1023);
|
|
4288
|
+
}
|
|
4289
|
+
writer.writeBits(13, 0);
|
|
4290
|
+
const litDepths = new Uint8Array(NUM_LITERAL_CODES);
|
|
4291
|
+
const litBits = new Uint16Array(NUM_LITERAL_CODES);
|
|
4292
|
+
const cmdDepths = new Uint8Array(NUM_COMMAND_CODES);
|
|
4293
|
+
const cmdBits = new Uint16Array(NUM_COMMAND_CODES);
|
|
4294
|
+
const distDepths = new Uint8Array(distanceAlphabetSize);
|
|
4295
|
+
const distBits = new Uint16Array(distanceAlphabetSize);
|
|
4296
|
+
buildAndStoreHuffmanTree(writer, litHisto.data, NUM_LITERAL_CODES, litDepths, litBits);
|
|
4297
|
+
buildAndStoreHuffmanTree(writer, cmdHisto.data, NUM_COMMAND_CODES, cmdDepths, cmdBits);
|
|
4298
|
+
buildAndStoreHuffmanTree(writer, distHisto.data, distanceAlphabetSize, distDepths, distBits);
|
|
4299
|
+
pos = startPos;
|
|
4300
|
+
for (const cmd of commands) {
|
|
4301
|
+
writer.writeBits(cmdDepths[cmd.cmdPrefix], cmdBits[cmd.cmdPrefix]);
|
|
4302
|
+
storeCommandExtra(writer, cmd);
|
|
4303
|
+
for (let j = 0; j < cmd.insertLen; j++) {
|
|
4304
|
+
const literal = input[pos + j & mask];
|
|
4305
|
+
writer.writeBits(litDepths[literal], litBits[literal]);
|
|
4306
|
+
}
|
|
4307
|
+
pos += cmd.insertLen;
|
|
4308
|
+
const copyLen = commandCopyLen(cmd);
|
|
4309
|
+
pos += copyLen;
|
|
4310
|
+
if (copyLen && cmd.cmdPrefix >= 128) {
|
|
4311
|
+
const distCode = cmd.distPrefix & 1023;
|
|
4312
|
+
const distNumExtra = cmd.distPrefix >>> 10;
|
|
4313
|
+
const distExtra = cmd.distExtra;
|
|
4314
|
+
writer.writeBits(distDepths[distCode], distBits[distCode]);
|
|
4315
|
+
writer.writeBits(distNumExtra, distExtra);
|
|
4316
|
+
}
|
|
4317
|
+
}
|
|
4318
|
+
if (isLast) writer.alignToByte();
|
|
4319
|
+
}
|
|
4320
|
+
function storeUncompressedMetaBlock(writer, input, position, mask, length, isFinal) {
|
|
4321
|
+
storeUncompressedMetaBlockHeader(writer, length);
|
|
4322
|
+
writer.alignToByte();
|
|
4323
|
+
let maskedPos = position & mask;
|
|
4324
|
+
if (maskedPos + length > mask + 1) {
|
|
4325
|
+
const len1 = mask + 1 - maskedPos;
|
|
4326
|
+
writer.writeBytes(input.subarray(maskedPos, maskedPos + len1));
|
|
4327
|
+
length -= len1;
|
|
4328
|
+
maskedPos = 0;
|
|
4329
|
+
}
|
|
4330
|
+
writer.writeBytes(input.subarray(maskedPos, maskedPos + length));
|
|
4331
|
+
writer.prepareStorage();
|
|
4332
|
+
if (isFinal) {
|
|
4333
|
+
writer.writeBits(1, 1);
|
|
4334
|
+
writer.writeBits(1, 1);
|
|
4335
|
+
writer.alignToByte();
|
|
4336
|
+
}
|
|
4337
|
+
}
|
|
4338
|
+
|
|
4339
|
+
//#endregion
|
|
4340
|
+
//#region src/encode/encode.ts
|
|
4341
|
+
function brotliEncode(input, options = {}) {
|
|
4342
|
+
const params = createDefaultParams();
|
|
4343
|
+
if (options.quality !== void 0) params.quality = Math.max(0, Math.min(11, options.quality));
|
|
4344
|
+
if (options.lgwin !== void 0) params.lgwin = Math.max(10, Math.min(24, options.lgwin));
|
|
4345
|
+
if (options.mode !== void 0) params.mode = options.mode;
|
|
4346
|
+
if (options.sizeHint !== void 0) params.sizeHint = options.sizeHint;
|
|
4347
|
+
sanitizeParams(params);
|
|
4348
|
+
params.lgblock = computeLgBlock(params);
|
|
4349
|
+
if (input.length === 0) return encodeEmptyInput();
|
|
4350
|
+
if (params.quality === 0 || input.length < 64) return encodeUncompressed(input);
|
|
4351
|
+
if (params.quality === 1) return encodeFast(input, params);
|
|
4352
|
+
return encodeStandard(input, params);
|
|
4353
|
+
}
|
|
4354
|
+
function encodeEmptyInput() {
|
|
4355
|
+
const writer = new BitWriter(16);
|
|
4356
|
+
const windowBits = encodeWindowBits(10, false);
|
|
4357
|
+
writer.writeBits(windowBits.bits, windowBits.value);
|
|
4358
|
+
writer.writeBits(1, 1);
|
|
4359
|
+
writer.writeBits(1, 1);
|
|
4360
|
+
writer.alignToByte();
|
|
4361
|
+
return writer.finish();
|
|
4362
|
+
}
|
|
4363
|
+
function encodeUncompressed(input) {
|
|
4364
|
+
const writer = new BitWriter(input.length + 32);
|
|
4365
|
+
const windowBits = encodeWindowBits(Math.max(10, Math.min(24, input.length <= 1 ? 10 : Math.ceil(Math.log2(input.length)) + 1)), false);
|
|
4366
|
+
writer.writeBits(windowBits.bits, windowBits.value);
|
|
4367
|
+
const maxBlockSize = (1 << 24) - 1;
|
|
4368
|
+
let pos = 0;
|
|
4369
|
+
while (pos < input.length) {
|
|
4370
|
+
const blockSize = Math.min(input.length - pos, maxBlockSize);
|
|
4371
|
+
if (pos + blockSize >= input.length) storeUncompressedMetaBlock(writer, input, pos, input.length - 1, blockSize, true);
|
|
4372
|
+
else storeUncompressedMetaBlock(writer, input, pos, input.length - 1, blockSize, false);
|
|
4373
|
+
pos += blockSize;
|
|
4374
|
+
}
|
|
4375
|
+
return writer.finish();
|
|
4376
|
+
}
|
|
4377
|
+
function encodeFast(input, params) {
|
|
4378
|
+
const writer = new BitWriter(input.length);
|
|
4379
|
+
const windowBits = encodeWindowBits(params.lgwin, false);
|
|
4380
|
+
writer.writeBits(windowBits.bits, windowBits.value);
|
|
4381
|
+
const hasher = createSimpleHasher(params.quality, params.lgwin);
|
|
4382
|
+
const distCache = new Int32Array([
|
|
4383
|
+
4,
|
|
4384
|
+
11,
|
|
4385
|
+
15,
|
|
4386
|
+
16
|
|
4387
|
+
]);
|
|
4388
|
+
const ringBufferMask = (1 << params.lgwin) - 1;
|
|
4389
|
+
const blockSize = 1 << params.lgblock;
|
|
4390
|
+
let pos = 0;
|
|
4391
|
+
while (pos < input.length) {
|
|
4392
|
+
const blockLen = Math.min(input.length - pos, blockSize);
|
|
4393
|
+
const isLast = pos + blockLen >= input.length;
|
|
4394
|
+
const [commands] = createBackwardReferences(blockLen, pos, input, ringBufferMask, hasher, distCache, 0, params.quality);
|
|
4395
|
+
const distAlphabetSize = 16 + (48 << params.dist.distancePostfixBits);
|
|
4396
|
+
storeMetaBlockTrivial(writer, input, pos, blockLen, ringBufferMask, isLast, commands, distAlphabetSize);
|
|
4397
|
+
pos += blockLen;
|
|
4398
|
+
}
|
|
4399
|
+
return writer.finish();
|
|
4400
|
+
}
|
|
4401
|
+
function encodeStandard(input, params) {
|
|
4402
|
+
const writer = new BitWriter(Math.max(1024, Math.floor(input.length * 1.2)));
|
|
4403
|
+
const windowBits = encodeWindowBits(params.lgwin, params.largeWindow);
|
|
4404
|
+
writer.writeBits(windowBits.bits, windowBits.value);
|
|
4405
|
+
let hasher;
|
|
4406
|
+
if (params.quality <= 4) hasher = createSimpleHasher(params.quality, params.lgwin);
|
|
4407
|
+
else if (params.quality <= 9) hasher = createHashChainHasher(params.quality, params.lgwin);
|
|
4408
|
+
else hasher = createBinaryTreeHasher(params.lgwin, input.length);
|
|
4409
|
+
const distCache = new Int32Array([
|
|
4410
|
+
4,
|
|
4411
|
+
11,
|
|
4412
|
+
15,
|
|
4413
|
+
16
|
|
4414
|
+
]);
|
|
4415
|
+
const ringBufferMask = (1 << params.lgwin) - 1;
|
|
4416
|
+
const maxMetablockSize = 1 << 24;
|
|
4417
|
+
let pos = 0;
|
|
4418
|
+
while (pos < input.length) {
|
|
4419
|
+
const metablockLen = Math.min(input.length - pos, maxMetablockSize);
|
|
4420
|
+
const isLast = pos + metablockLen >= input.length;
|
|
4421
|
+
let commands;
|
|
4422
|
+
let lastInsertLen = 0;
|
|
4423
|
+
if (params.quality >= HQ_ZOPFLIFICATION_QUALITY && hasher instanceof BinaryTreeHasher) [commands, , lastInsertLen] = createHqZopfliBackwardReferences(metablockLen, pos, input, ringBufferMask, hasher, distCache, 0);
|
|
4424
|
+
else if (params.quality >= ZOPFLIFICATION_QUALITY && hasher instanceof BinaryTreeHasher) [commands, , lastInsertLen] = createZopfliBackwardReferences(metablockLen, pos, input, ringBufferMask, params.quality, hasher, distCache, 0);
|
|
4425
|
+
else if (hasher instanceof HashChainHasher) [commands, , lastInsertLen] = createBackwardReferences(metablockLen, pos, input, ringBufferMask, hasher, distCache, 0, params.quality);
|
|
4426
|
+
else if (hasher instanceof SimpleHasher) [commands, , lastInsertLen] = createBackwardReferences(metablockLen, pos, input, ringBufferMask, hasher, distCache, 0, params.quality);
|
|
4427
|
+
else commands = [createInsertCommand(metablockLen)];
|
|
4428
|
+
if (lastInsertLen > 0) if (commands.length === 0) commands = [createInsertCommand(metablockLen)];
|
|
4429
|
+
else {
|
|
4430
|
+
const lastCmd = commands[commands.length - 1];
|
|
4431
|
+
if (commandCopyLen(lastCmd) === 0) lastCmd.insertLen += lastInsertLen;
|
|
4432
|
+
else commands.push(createInsertCommand(lastInsertLen));
|
|
4433
|
+
}
|
|
4434
|
+
else if (commands.length === 0) commands = [createInsertCommand(metablockLen)];
|
|
4435
|
+
const distAlphabetSize = calculateDistanceAlphabetSize(params);
|
|
4436
|
+
storeMetaBlockTrivial(writer, input, pos, metablockLen, ringBufferMask, isLast, commands, distAlphabetSize);
|
|
4437
|
+
pos += metablockLen;
|
|
4438
|
+
}
|
|
4439
|
+
return writer.finish();
|
|
4440
|
+
}
|
|
4441
|
+
function calculateDistanceAlphabetSize(params) {
|
|
4442
|
+
const npostfix = params.dist.distancePostfixBits;
|
|
4443
|
+
return 16 + params.dist.numDirectDistanceCodes + (48 << npostfix);
|
|
4444
|
+
}
|
|
4445
|
+
var BrotliEncoder = class {
|
|
4446
|
+
constructor(options = {}) {
|
|
4447
|
+
const params = createDefaultParams();
|
|
4448
|
+
if (options.quality !== void 0) params.quality = Math.max(0, Math.min(11, options.quality));
|
|
4449
|
+
if (options.lgwin !== void 0) params.lgwin = Math.max(10, Math.min(24, options.lgwin));
|
|
4450
|
+
if (options.mode !== void 0) params.mode = options.mode;
|
|
4451
|
+
if (options.sizeHint !== void 0) params.sizeHint = options.sizeHint;
|
|
4452
|
+
sanitizeParams(params);
|
|
4453
|
+
params.lgblock = computeLgBlock(params);
|
|
4454
|
+
const ringBufferSize = 1 << params.lgwin;
|
|
4455
|
+
this.state = {
|
|
4456
|
+
params,
|
|
4457
|
+
hasher: null,
|
|
4458
|
+
distCache: new Int32Array([
|
|
4459
|
+
4,
|
|
4460
|
+
11,
|
|
4461
|
+
15,
|
|
4462
|
+
16
|
|
4463
|
+
]),
|
|
4464
|
+
lastInsertLen: 0,
|
|
4465
|
+
commands: [],
|
|
4466
|
+
numLiterals: 0,
|
|
4467
|
+
inputPos: 0,
|
|
4468
|
+
lastProcessedPos: 0,
|
|
4469
|
+
ringBuffer: new Uint8Array(ringBufferSize),
|
|
4470
|
+
ringBufferMask: ringBufferSize - 1,
|
|
4471
|
+
prevByte: 0,
|
|
4472
|
+
prevByte2: 0,
|
|
4473
|
+
isInitialized: false,
|
|
4474
|
+
isLastBlockEmitted: false,
|
|
4475
|
+
writer: new BitWriter()
|
|
4476
|
+
};
|
|
4477
|
+
}
|
|
4478
|
+
initialize() {
|
|
4479
|
+
if (this.state.isInitialized) return;
|
|
4480
|
+
const { params, writer } = this.state;
|
|
4481
|
+
const windowBits = encodeWindowBits(params.lgwin, params.largeWindow);
|
|
4482
|
+
writer.writeBits(windowBits.bits, windowBits.value);
|
|
4483
|
+
if (params.quality <= 4) this.state.hasher = createSimpleHasher(params.quality, params.lgwin);
|
|
4484
|
+
else if (params.quality <= 9) this.state.hasher = createHashChainHasher(params.quality, params.lgwin);
|
|
4485
|
+
else this.state.hasher = createBinaryTreeHasher(params.lgwin);
|
|
4486
|
+
this.state.isInitialized = true;
|
|
4487
|
+
}
|
|
4488
|
+
update(input) {
|
|
4489
|
+
this.initialize();
|
|
4490
|
+
const { ringBuffer, ringBufferMask } = this.state;
|
|
4491
|
+
for (let i = 0; i < input.length; i++) ringBuffer[this.state.inputPos + i & ringBufferMask] = input[i];
|
|
4492
|
+
this.state.inputPos += input.length;
|
|
4493
|
+
const blockSize = 1 << this.state.params.lgblock;
|
|
4494
|
+
const output = [];
|
|
4495
|
+
while (this.state.inputPos - this.state.lastProcessedPos >= blockSize) {
|
|
4496
|
+
const chunk = this.processBlock(blockSize, false);
|
|
4497
|
+
if (chunk.length > 0) output.push(chunk);
|
|
4498
|
+
}
|
|
4499
|
+
if (output.length === 0) return new Uint8Array(0);
|
|
4500
|
+
if (output.length === 1) return output[0];
|
|
4501
|
+
const totalLen = output.reduce((sum, arr) => sum + arr.length, 0);
|
|
4502
|
+
const result = new Uint8Array(totalLen);
|
|
4503
|
+
let offset = 0;
|
|
4504
|
+
for (const chunk of output) {
|
|
4505
|
+
result.set(chunk, offset);
|
|
4506
|
+
offset += chunk.length;
|
|
4507
|
+
}
|
|
4508
|
+
return result;
|
|
4509
|
+
}
|
|
4510
|
+
finish() {
|
|
4511
|
+
this.initialize();
|
|
4512
|
+
const remaining = this.state.inputPos - this.state.lastProcessedPos;
|
|
4513
|
+
if (remaining > 0) return this.processBlock(remaining, true);
|
|
4514
|
+
if (!this.state.isLastBlockEmitted) {
|
|
4515
|
+
const { writer } = this.state;
|
|
4516
|
+
writer.writeBits(1, 1);
|
|
4517
|
+
writer.writeBits(1, 1);
|
|
4518
|
+
writer.alignToByte();
|
|
4519
|
+
this.state.isLastBlockEmitted = true;
|
|
4520
|
+
}
|
|
4521
|
+
return this.state.writer.takeBytes();
|
|
4522
|
+
}
|
|
4523
|
+
processBlock(blockLen, isLast) {
|
|
4524
|
+
const { params, ringBuffer, ringBufferMask, distCache, hasher, writer } = this.state;
|
|
4525
|
+
const pos = this.state.lastProcessedPos;
|
|
4526
|
+
if (!hasher) throw new Error("Encoder not initialized");
|
|
4527
|
+
let commands;
|
|
4528
|
+
let numLiterals;
|
|
4529
|
+
let lastInsertLen;
|
|
4530
|
+
if (hasher instanceof SimpleHasher || hasher instanceof HashChainHasher) [commands, numLiterals, lastInsertLen] = createBackwardReferences(blockLen, pos, ringBuffer, ringBufferMask, hasher, distCache, this.state.lastInsertLen, params.quality);
|
|
4531
|
+
else if (hasher instanceof BinaryTreeHasher) if (params.quality >= HQ_ZOPFLIFICATION_QUALITY) [commands, numLiterals, lastInsertLen] = createHqZopfliBackwardReferences(blockLen, pos, ringBuffer, ringBufferMask, hasher, distCache, this.state.lastInsertLen);
|
|
4532
|
+
else [commands, numLiterals, lastInsertLen] = createZopfliBackwardReferences(blockLen, pos, ringBuffer, ringBufferMask, params.quality, hasher, distCache, this.state.lastInsertLen);
|
|
4533
|
+
else {
|
|
4534
|
+
commands = [createInsertCommand(blockLen)];
|
|
4535
|
+
numLiterals = blockLen;
|
|
4536
|
+
lastInsertLen = 0;
|
|
4537
|
+
}
|
|
4538
|
+
if (lastInsertLen > 0) if (commands.length === 0) commands = [createInsertCommand(blockLen)];
|
|
4539
|
+
else {
|
|
4540
|
+
const lastCmd = commands[commands.length - 1];
|
|
4541
|
+
if (commandCopyLen(lastCmd) === 0) lastCmd.insertLen += lastInsertLen;
|
|
4542
|
+
else commands.push(createInsertCommand(lastInsertLen));
|
|
4543
|
+
}
|
|
4544
|
+
else if (commands.length === 0) commands = [createInsertCommand(blockLen)];
|
|
4545
|
+
const distAlphabetSize = calculateDistanceAlphabetSize(params);
|
|
4546
|
+
storeMetaBlockTrivial(writer, ringBuffer, pos, blockLen, ringBufferMask, isLast, commands, distAlphabetSize);
|
|
4547
|
+
this.state.lastProcessedPos += blockLen;
|
|
4548
|
+
this.state.lastInsertLen = 0;
|
|
4549
|
+
this.state.numLiterals += numLiterals;
|
|
4550
|
+
if (isLast) this.state.isLastBlockEmitted = true;
|
|
4551
|
+
return writer.takeBytes();
|
|
4552
|
+
}
|
|
4553
|
+
};
|
|
4554
|
+
|
|
4555
|
+
//#endregion
|
|
4556
|
+
export { BrotliEncoder, EncoderMode, brotliDecode, brotliDecodedSize, brotliEncode };
|