plevinjs 0.2.1 → 0.2.2

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.
Files changed (63) hide show
  1. package/README.md +78 -13
  2. package/dist/cli.d.ts +4 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +16 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/compress.d.ts +5 -0
  7. package/dist/compress.d.ts.map +1 -0
  8. package/dist/compress.js +954 -0
  9. package/dist/compress.js.map +1 -0
  10. package/dist/countries.d.ts +1 -1
  11. package/dist/countries.d.ts.map +1 -1
  12. package/dist/countries.js +251 -250
  13. package/dist/countries.js.map +1 -1
  14. package/dist/derive.d.ts +1 -0
  15. package/dist/derive.d.ts.map +1 -1
  16. package/dist/derive.js +12 -6
  17. package/dist/derive.js.map +1 -1
  18. package/dist/estimate.d.ts +38 -0
  19. package/dist/estimate.d.ts.map +1 -0
  20. package/dist/estimate.js +263 -0
  21. package/dist/estimate.js.map +1 -0
  22. package/dist/extra.d.ts.map +1 -1
  23. package/dist/extra.js +12 -12
  24. package/dist/extra.js.map +1 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +51 -6
  27. package/dist/index.js.map +1 -1
  28. package/dist/leaves.d.ts +30 -0
  29. package/dist/leaves.d.ts.map +1 -0
  30. package/dist/leaves.js +183 -0
  31. package/dist/leaves.js.map +1 -0
  32. package/dist/lzma.d.ts +18 -0
  33. package/dist/lzma.d.ts.map +1 -1
  34. package/dist/lzma.js +18 -18
  35. package/dist/lzma.js.map +1 -1
  36. package/dist/matcher.d.ts +25 -0
  37. package/dist/matcher.d.ts.map +1 -0
  38. package/dist/matcher.js +198 -0
  39. package/dist/matcher.js.map +1 -0
  40. package/dist/models.d.ts +7 -0
  41. package/dist/models.d.ts.map +1 -1
  42. package/dist/plevin.min.js +258 -257
  43. package/dist/reader.d.ts.map +1 -1
  44. package/dist/reader.js +12 -1
  45. package/dist/reader.js.map +1 -1
  46. package/dist/selection.d.ts +34 -0
  47. package/dist/selection.d.ts.map +1 -0
  48. package/dist/selection.js +338 -0
  49. package/dist/selection.js.map +1 -0
  50. package/dist/slim.d.ts +21 -0
  51. package/dist/slim.d.ts.map +1 -0
  52. package/dist/slim.js +639 -0
  53. package/dist/slim.js.map +1 -0
  54. package/dist/slim.min.js +1 -0
  55. package/dist/stats.d.ts +61 -0
  56. package/dist/stats.d.ts.map +1 -0
  57. package/dist/stats.js +368 -0
  58. package/dist/stats.js.map +1 -0
  59. package/dist/writer.d.ts +32 -0
  60. package/dist/writer.d.ts.map +1 -0
  61. package/dist/writer.js +325 -0
  62. package/dist/writer.js.map +1 -0
  63. package/package.json +7 -2
@@ -0,0 +1,954 @@
1
+ /** Raw LZMA1 to an end marker, step for step the encoder liblzma runs at preset 9. */
2
+ import { ALIGN, HALF, HIGH, IS_FIRST, IS_LONG, IS_MATCH, IS_REPEAT, IS_SECOND, IS_THIRD, LENGTHS, LITERALS, LOW, MIDDLE, REPEATS, SLOTS, SPECIAL, } from "./lzma.js";
3
+ import { LONGEST, Matcher, NICE } from "./matcher.js";
4
+ const PRICES = Uint8Array.of(128, 103, 91, 84, 78, 73, 69, 66, 63, 61, 58, 56, 54, 52, 51, 49, 48, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 34, 33, 32, 31, 31, 30, 29, 29, 28, 28, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 22, 21, 21, 20, 20, 19, 19, 19, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1);
5
+ const TOP = 1 << 24;
6
+ const TOTAL = 2048;
7
+ const SYMBOLS = 58;
8
+ const BIT_0 = 0;
9
+ const BIT_1 = 1;
10
+ const DIRECT_0 = 2;
11
+ const DIRECT_1 = 3;
12
+ const FLUSH = 4;
13
+ const REPS = 4;
14
+ const OPTS = 1 << 12;
15
+ const INFINITE = 1 << 30;
16
+ const NO_BACK = 0xffffffff;
17
+ const LITERAL_STATES = 7;
18
+ const FULL_DISTANCES = 128;
19
+ const DISTANCE_SLOTS = 40;
20
+ const ALIGN_SIZE = 16;
21
+ const LENGTH_TABLE = NICE - 1;
22
+ const STRIDE = 272;
23
+ const BYTES_LIMIT = 2_000_000;
24
+ const afterLiteral = (state) => state < 4 ? 0 : state < 10 ? state - 3 : state - 6;
25
+ const afterMatch = (state) => (state < LITERAL_STATES ? 7 : 10);
26
+ const afterLongRep = (state) => (state < LITERAL_STATES ? 8 : 11);
27
+ const afterShortRep = (state) => (state < LITERAL_STATES ? 9 : 11);
28
+ const slotOf = (distance) => {
29
+ if (distance < 4)
30
+ return distance;
31
+ const top = 31 - Math.clz32(distance);
32
+ return (top << 1) + ((distance >>> (top - 1)) & 1);
33
+ };
34
+ const distanceState = (length) => (length < 6 ? length - 2 : 3);
35
+ const price0 = (probs, slot) => PRICES[probs[slot] >> 4];
36
+ const price1 = (probs, slot) => PRICES[(probs[slot] ^ (TOTAL - 1)) >> 4];
37
+ const priceOf = (probs, slot, bit) => PRICES[(probs[slot] ^ (bit ? TOTAL - 1 : 0)) >> 4];
38
+ const treePrice = (probs, base, bits, symbol) => {
39
+ let price = 0;
40
+ let node = symbol + (1 << bits);
41
+ while (node !== 1) {
42
+ const bit = node & 1;
43
+ node >>= 1;
44
+ price += priceOf(probs, base + node, bit);
45
+ }
46
+ return price;
47
+ };
48
+ const reversePrice = (probs, base, bits, symbol) => {
49
+ let price = 0;
50
+ let index = 1;
51
+ let left = symbol;
52
+ for (let step = 0; step < bits; step += 1) {
53
+ const bit = left & 1;
54
+ left >>= 1;
55
+ price += priceOf(probs, base + index, bit);
56
+ index = (index << 1) + bit;
57
+ }
58
+ return price;
59
+ };
60
+ class RangeEncoder {
61
+ low = 0;
62
+ extra = 1;
63
+ range = 0xffffffff;
64
+ cache = 0;
65
+ count = 0;
66
+ at = 0;
67
+ kinds = new Uint8Array(SYMBOLS);
68
+ slots = new Int32Array(SYMBOLS);
69
+ out = new Uint8Array(1 << 12);
70
+ size = 0;
71
+ probs;
72
+ constructor(probs) {
73
+ this.probs = probs;
74
+ }
75
+ bit(slot, bit) {
76
+ this.kinds[this.count] = bit;
77
+ this.slots[this.count] = slot;
78
+ this.count += 1;
79
+ }
80
+ tree(base, bits, symbol) {
81
+ let index = 1;
82
+ for (let left = bits - 1; left >= 0; left -= 1) {
83
+ const bit = (symbol >>> left) & 1;
84
+ this.bit(base + index, bit);
85
+ index = (index << 1) + bit;
86
+ }
87
+ }
88
+ reverse(base, bits, symbol) {
89
+ let index = 1;
90
+ let left = symbol;
91
+ for (let step = 0; step < bits; step += 1) {
92
+ const bit = left & 1;
93
+ left >>>= 1;
94
+ this.bit(base + index, bit);
95
+ index = (index << 1) + bit;
96
+ }
97
+ }
98
+ direct(value, bits) {
99
+ for (let left = bits - 1; left >= 0; left -= 1) {
100
+ this.kinds[this.count] = DIRECT_0 + ((value >>> left) & 1);
101
+ this.count += 1;
102
+ }
103
+ }
104
+ flush() {
105
+ for (let step = 0; step < 5; step += 1) {
106
+ this.kinds[this.count] = FLUSH;
107
+ this.count += 1;
108
+ }
109
+ }
110
+ encode() {
111
+ const { probs, kinds, slots } = this;
112
+ while (this.at < this.count) {
113
+ if (this.range < TOP) {
114
+ this.shift();
115
+ this.range = (this.range << 8) >>> 0;
116
+ }
117
+ const kind = kinds[this.at];
118
+ if (kind === BIT_0) {
119
+ const prob = probs[slots[this.at]];
120
+ this.range = (this.range >>> 11) * prob;
121
+ probs[slots[this.at]] = prob + ((TOTAL - prob) >> 5);
122
+ }
123
+ else if (kind === BIT_1) {
124
+ const prob = probs[slots[this.at]];
125
+ const bound = prob * (this.range >>> 11);
126
+ this.low += bound;
127
+ this.range -= bound;
128
+ probs[slots[this.at]] = prob - (prob >> 5);
129
+ }
130
+ else if (kind === FLUSH) {
131
+ this.finish();
132
+ return;
133
+ }
134
+ else {
135
+ this.range >>>= 1;
136
+ if (kind === DIRECT_1)
137
+ this.low += this.range;
138
+ }
139
+ this.at += 1;
140
+ }
141
+ this.count = 0;
142
+ this.at = 0;
143
+ }
144
+ bytes() {
145
+ return this.out.slice(0, this.size);
146
+ }
147
+ finish() {
148
+ this.range = 0xffffffff;
149
+ do {
150
+ this.shift();
151
+ this.at += 1;
152
+ } while (this.at < this.count);
153
+ this.low = 0;
154
+ this.extra = 1;
155
+ this.cache = 0;
156
+ this.count = 0;
157
+ this.at = 0;
158
+ }
159
+ push(byte) {
160
+ if (this.size === this.out.length) {
161
+ const grown = new Uint8Array(this.size * 2);
162
+ grown.set(this.out);
163
+ this.out = grown;
164
+ }
165
+ this.out[this.size] = byte;
166
+ this.size += 1;
167
+ }
168
+ shift() {
169
+ const lower = this.low % 0x100000000;
170
+ if (lower < 0xff000000 || this.low >= 0x100000000) {
171
+ const carry = this.low >= 0x100000000 ? 1 : 0;
172
+ let byte = this.cache;
173
+ do {
174
+ this.push((byte + carry) & 0xff);
175
+ byte = 0xff;
176
+ this.extra -= 1;
177
+ } while (this.extra !== 0);
178
+ this.cache = (lower >>> 24) & 0xff;
179
+ }
180
+ this.extra += 1;
181
+ this.low = (lower & 0xffffff) * 256;
182
+ }
183
+ }
184
+ class Lengths {
185
+ prices = new Uint32Array(16 * STRIDE);
186
+ counters = new Int32Array(16);
187
+ base;
188
+ probs;
189
+ constructor(base, probs) {
190
+ this.base = base;
191
+ this.probs = probs;
192
+ }
193
+ low(state) {
194
+ return this.base + LOW + state * 8;
195
+ }
196
+ middle(state) {
197
+ return this.base + MIDDLE + state * 8;
198
+ }
199
+ price(length, state) {
200
+ return this.prices[state * STRIDE + length - 2];
201
+ }
202
+ update(state) {
203
+ const { probs, base, prices } = this;
204
+ this.counters[state] = LENGTH_TABLE;
205
+ const first = price0(probs, base);
206
+ const second = price1(probs, base);
207
+ const third = second + price0(probs, base + 1);
208
+ const fourth = second + price1(probs, base + 1);
209
+ const row = state * STRIDE;
210
+ for (let at = 0; at < LENGTH_TABLE; at += 1) {
211
+ if (at < 8) {
212
+ prices[row + at] = first + treePrice(probs, this.low(state), 3, at);
213
+ }
214
+ else if (at < 16) {
215
+ prices[row + at] = third + treePrice(probs, this.middle(state), 3, at - 8);
216
+ }
217
+ else {
218
+ prices[row + at] = fourth + treePrice(probs, base + HIGH, 8, at - 16);
219
+ }
220
+ }
221
+ }
222
+ }
223
+ class Path {
224
+ state = new Uint8Array(OPTS + LONGEST + 2);
225
+ previousLiteral = new Uint8Array(OPTS + LONGEST + 2);
226
+ twice = new Uint8Array(OPTS + LONGEST + 2);
227
+ positionTwice = new Uint32Array(OPTS + LONGEST + 2);
228
+ backTwice = new Uint32Array(OPTS + LONGEST + 2);
229
+ price = new Uint32Array(OPTS + LONGEST + 2);
230
+ position = new Uint32Array(OPTS + LONGEST + 2);
231
+ back = new Uint32Array(OPTS + LONGEST + 2);
232
+ backs = new Uint32Array((OPTS + LONGEST + 2) * REPS);
233
+ }
234
+ class Encoder {
235
+ probs;
236
+ ranges;
237
+ matcher;
238
+ matchLengths;
239
+ repLengths;
240
+ path = new Path();
241
+ reps = new Uint32Array(REPS);
242
+ repLens = new Uint32Array(REPS);
243
+ slotPrices = new Uint32Array(4 * 64);
244
+ distancePrices = new Uint32Array(4 * FULL_DISTANCES);
245
+ alignPrices = new Uint32Array(ALIGN_SIZE);
246
+ literalContext;
247
+ literalMask;
248
+ positionMask;
249
+ state = 0;
250
+ longest = 0;
251
+ found = 0;
252
+ matchPriceCount = 0x7fffffff;
253
+ alignPriceCount = 0x7fffffff;
254
+ endIndex = 0;
255
+ currentIndex = 0;
256
+ back = 0;
257
+ length = 0;
258
+ data;
259
+ constructor(data, [context, position, matches]) {
260
+ this.data = data;
261
+ this.probs = new Uint16Array(LITERALS + (0x300 << (context + position))).fill(HALF);
262
+ this.ranges = new RangeEncoder(this.probs);
263
+ this.matcher = new Matcher(data);
264
+ this.matchLengths = new Lengths(LENGTHS, this.probs);
265
+ this.repLengths = new Lengths(REPEATS, this.probs);
266
+ this.literalContext = context;
267
+ this.literalMask = (1 << position) - 1;
268
+ this.positionMask = (1 << matches) - 1;
269
+ for (let state = 0; state <= this.positionMask; state += 1) {
270
+ this.matchLengths.update(state);
271
+ this.repLengths.update(state);
272
+ }
273
+ }
274
+ run() {
275
+ const { matcher, ranges, data } = this;
276
+ if (data.length > 0) {
277
+ matcher.skip(1);
278
+ matcher.readAhead = 0;
279
+ ranges.bit(IS_MATCH, 0);
280
+ ranges.tree(LITERALS, 8, data[0]);
281
+ }
282
+ let position = matcher.readPos - matcher.readAhead;
283
+ for (;;) {
284
+ ranges.encode();
285
+ if (matcher.readPos >= matcher.end && matcher.readAhead === 0)
286
+ break;
287
+ this.optimum(position);
288
+ this.encode(this.back, this.length, position);
289
+ position += this.length;
290
+ }
291
+ this.endMarker(position);
292
+ ranges.flush();
293
+ ranges.encode();
294
+ return ranges.bytes();
295
+ }
296
+ endMarker(position) {
297
+ const { ranges } = this;
298
+ const spot = position & this.positionMask;
299
+ ranges.bit(IS_MATCH + this.state * 16 + spot, 1);
300
+ ranges.bit(IS_REPEAT + this.state, 0);
301
+ this.match(spot, 0xffffffff, 2);
302
+ }
303
+ literalBase(position, previous) {
304
+ const context = this.literalContext;
305
+ const spot = ((position & this.literalMask) << context) + (previous >> (8 - context));
306
+ return LITERALS + 0x300 * spot;
307
+ }
308
+ literal(position) {
309
+ const { matcher, data, ranges } = this;
310
+ const at = matcher.readPos - matcher.readAhead;
311
+ const base = this.literalBase(position, data[at - 1]);
312
+ if (this.state < LITERAL_STATES) {
313
+ ranges.tree(base, 8, data[at]);
314
+ }
315
+ else {
316
+ this.literalMatched(base, data[at - this.reps[0] - 1], data[at]);
317
+ }
318
+ this.state = afterLiteral(this.state);
319
+ }
320
+ literalMatched(base, matchByte, symbol) {
321
+ let offset = 0x100;
322
+ let left = symbol + 0x100;
323
+ let byte = matchByte;
324
+ do {
325
+ byte <<= 1;
326
+ const matchBit = byte & offset;
327
+ this.ranges.bit(base + offset + matchBit + (left >> 8), (left >> 7) & 1);
328
+ left <<= 1;
329
+ offset &= ~(byte ^ left);
330
+ } while (left < 0x10000);
331
+ }
332
+ writeLength(lengths, spot, length) {
333
+ const { ranges } = this;
334
+ const base = lengths.base;
335
+ const rest = length - 2;
336
+ if (rest < 8) {
337
+ ranges.bit(base, 0);
338
+ ranges.tree(lengths.low(spot), 3, rest);
339
+ }
340
+ else if (rest < 16) {
341
+ ranges.bit(base, 1);
342
+ ranges.bit(base + 1, 0);
343
+ ranges.tree(lengths.middle(spot), 3, rest - 8);
344
+ }
345
+ else {
346
+ ranges.bit(base, 1);
347
+ ranges.bit(base + 1, 1);
348
+ ranges.tree(base + HIGH, 8, rest - 16);
349
+ }
350
+ lengths.counters[spot] -= 1;
351
+ if (lengths.counters[spot] === 0)
352
+ lengths.update(spot);
353
+ }
354
+ match(spot, distance, length) {
355
+ const { ranges } = this;
356
+ this.state = afterMatch(this.state);
357
+ this.writeLength(this.matchLengths, spot, length);
358
+ const slot = slotOf(distance);
359
+ ranges.tree(SLOTS + distanceState(length) * 64, 6, slot);
360
+ if (slot >= 4)
361
+ this.writeDistance(distance, slot);
362
+ this.reps[3] = this.reps[2];
363
+ this.reps[2] = this.reps[1];
364
+ this.reps[1] = this.reps[0];
365
+ this.reps[0] = distance;
366
+ this.matchPriceCount += 1;
367
+ }
368
+ writeDistance(distance, slot) {
369
+ const { ranges } = this;
370
+ const footer = (slot >> 1) - 1;
371
+ const base = (2 | (slot & 1)) * 2 ** footer;
372
+ const reduced = distance - base;
373
+ if (slot < 14) {
374
+ ranges.reverse(SPECIAL + base - slot - 1, footer, reduced);
375
+ return;
376
+ }
377
+ ranges.direct(Math.floor(reduced / 16), footer - 4);
378
+ ranges.reverse(ALIGN, 4, reduced & 15);
379
+ this.alignPriceCount += 1;
380
+ }
381
+ repMatch(spot, rep, length) {
382
+ const { ranges, reps } = this;
383
+ const { state } = this;
384
+ if (rep === 0) {
385
+ ranges.bit(IS_FIRST + state, 0);
386
+ ranges.bit(IS_LONG + state * 16 + spot, length !== 1 ? 1 : 0);
387
+ }
388
+ else {
389
+ const distance = reps[rep];
390
+ ranges.bit(IS_FIRST + state, 1);
391
+ if (rep === 1) {
392
+ ranges.bit(IS_SECOND + state, 0);
393
+ }
394
+ else {
395
+ ranges.bit(IS_SECOND + state, 1);
396
+ ranges.bit(IS_THIRD + state, rep - 2);
397
+ if (rep === 3)
398
+ reps[3] = reps[2];
399
+ reps[2] = reps[1];
400
+ }
401
+ reps[1] = reps[0];
402
+ reps[0] = distance;
403
+ }
404
+ if (length === 1) {
405
+ this.state = afterShortRep(state);
406
+ return;
407
+ }
408
+ this.writeLength(this.repLengths, spot, length);
409
+ this.state = afterLongRep(state);
410
+ }
411
+ encode(back, length, position) {
412
+ const { ranges, matcher } = this;
413
+ const spot = position & this.positionMask;
414
+ if (back === NO_BACK) {
415
+ ranges.bit(IS_MATCH + this.state * 16 + spot, 0);
416
+ this.literal(position);
417
+ }
418
+ else if (back < REPS) {
419
+ ranges.bit(IS_MATCH + this.state * 16 + spot, 1);
420
+ ranges.bit(IS_REPEAT + this.state, 1);
421
+ this.repMatch(spot, back, length);
422
+ }
423
+ else {
424
+ ranges.bit(IS_MATCH + this.state * 16 + spot, 1);
425
+ ranges.bit(IS_REPEAT + this.state, 0);
426
+ this.match(spot, back - REPS, length);
427
+ }
428
+ matcher.readAhead -= length;
429
+ }
430
+ literalPrice(position, previous, matched, matchByte, symbol) {
431
+ const { probs } = this;
432
+ const base = this.literalBase(position, previous);
433
+ if (!matched)
434
+ return treePrice(probs, base, 8, symbol);
435
+ let price = 0;
436
+ let offset = 0x100;
437
+ let left = symbol + 0x100;
438
+ let byte = matchByte;
439
+ do {
440
+ byte <<= 1;
441
+ const matchBit = byte & offset;
442
+ price += priceOf(probs, base + offset + matchBit + (left >> 8), (left >> 7) & 1);
443
+ left <<= 1;
444
+ offset &= ~(byte ^ left);
445
+ } while (left < 0x10000);
446
+ return price;
447
+ }
448
+ shortRepPrice(state, spot) {
449
+ const { probs } = this;
450
+ return price0(probs, IS_FIRST + state) + price0(probs, IS_LONG + state * 16 + spot);
451
+ }
452
+ pureRepPrice(rep, state, spot) {
453
+ const { probs } = this;
454
+ if (rep === 0) {
455
+ return price0(probs, IS_FIRST + state) + price1(probs, IS_LONG + state * 16 + spot);
456
+ }
457
+ const first = price1(probs, IS_FIRST + state);
458
+ if (rep === 1)
459
+ return first + price0(probs, IS_SECOND + state);
460
+ return (first + price1(probs, IS_SECOND + state) + priceOf(probs, IS_THIRD + state, rep - 2));
461
+ }
462
+ repPrice(rep, length, state, spot) {
463
+ return this.repLengths.price(length, spot) + this.pureRepPrice(rep, state, spot);
464
+ }
465
+ distanceLengthPrice(distance, length, spot) {
466
+ const state = distanceState(length);
467
+ let price;
468
+ if (distance < FULL_DISTANCES) {
469
+ price = this.distancePrices[state * FULL_DISTANCES + distance];
470
+ }
471
+ else {
472
+ price =
473
+ this.slotPrices[state * 64 + slotOf(distance)] +
474
+ this.alignPrices[distance & (ALIGN_SIZE - 1)];
475
+ }
476
+ return price + this.matchLengths.price(length, spot);
477
+ }
478
+ fillDistancePrices() {
479
+ const { probs, slotPrices, distancePrices } = this;
480
+ for (let state = 0; state < 4; state += 1) {
481
+ const row = state * 64;
482
+ for (let slot = 0; slot < DISTANCE_SLOTS; slot += 1) {
483
+ slotPrices[row + slot] = treePrice(probs, SLOTS + row, 6, slot);
484
+ }
485
+ for (let slot = 14; slot < DISTANCE_SLOTS; slot += 1) {
486
+ slotPrices[row + slot] += ((slot >> 1) - 1 - 4) << 4;
487
+ }
488
+ for (let at = 0; at < 4; at += 1) {
489
+ distancePrices[state * FULL_DISTANCES + at] = slotPrices[row + at];
490
+ }
491
+ }
492
+ for (let at = 4; at < FULL_DISTANCES; at += 1) {
493
+ const slot = slotOf(at);
494
+ const footer = (slot >> 1) - 1;
495
+ const base = (2 | (slot & 1)) << footer;
496
+ const price = reversePrice(probs, SPECIAL + base - slot - 1, footer, at - base);
497
+ for (let state = 0; state < 4; state += 1) {
498
+ distancePrices[state * FULL_DISTANCES + at] =
499
+ price + slotPrices[state * 64 + slot];
500
+ }
501
+ }
502
+ this.matchPriceCount = 0;
503
+ }
504
+ fillAlignPrices() {
505
+ for (let at = 0; at < ALIGN_SIZE; at += 1) {
506
+ this.alignPrices[at] = reversePrice(this.probs, ALIGN, 4, at);
507
+ }
508
+ this.alignPriceCount = 0;
509
+ }
510
+ literalChoice(path, at) {
511
+ path.back[at] = NO_BACK;
512
+ path.previousLiteral[at] = 0;
513
+ }
514
+ shortRepChoice(path, at) {
515
+ path.back[at] = 0;
516
+ path.previousLiteral[at] = 0;
517
+ }
518
+ backward(cur) {
519
+ const { path } = this;
520
+ this.endIndex = cur;
521
+ let at = cur;
522
+ let positionMemory = path.position[at];
523
+ let backMemory = path.back[at];
524
+ do {
525
+ if (path.previousLiteral[at]) {
526
+ this.literalChoice(path, positionMemory);
527
+ path.position[positionMemory] = positionMemory - 1;
528
+ if (path.twice[at]) {
529
+ path.previousLiteral[positionMemory - 1] = 0;
530
+ path.position[positionMemory - 1] = path.positionTwice[at];
531
+ path.back[positionMemory - 1] = path.backTwice[at];
532
+ }
533
+ }
534
+ const previous = positionMemory;
535
+ const backNow = backMemory;
536
+ backMemory = path.back[previous];
537
+ positionMemory = path.position[previous];
538
+ path.back[previous] = backNow;
539
+ path.position[previous] = at;
540
+ at = previous;
541
+ } while (at !== 0);
542
+ this.currentIndex = path.position[0];
543
+ this.length = path.position[0];
544
+ this.back = path.back[0];
545
+ }
546
+ optimum(position) {
547
+ const { path, matcher } = this;
548
+ if (this.endIndex !== this.currentIndex) {
549
+ const next = path.position[this.currentIndex];
550
+ this.length = next - this.currentIndex;
551
+ this.back = path.back[this.currentIndex];
552
+ this.currentIndex = next;
553
+ return;
554
+ }
555
+ if (matcher.readAhead === 0) {
556
+ if (this.matchPriceCount >= 1 << 7)
557
+ this.fillDistancePrices();
558
+ if (this.alignPriceCount >= ALIGN_SIZE)
559
+ this.fillAlignPrices();
560
+ }
561
+ let end = this.first(position);
562
+ if (end < 0)
563
+ return;
564
+ const reps = Uint32Array.from(this.reps);
565
+ let cur = 1;
566
+ for (; cur < end; cur += 1) {
567
+ this.longest = matcher.find();
568
+ this.found = matcher.count;
569
+ if (this.longest >= NICE)
570
+ break;
571
+ const available = Math.min(matcher.available + 1, OPTS - 1 - cur);
572
+ end = this.extend(reps, matcher.readPos - 1, end, position + cur, cur, available);
573
+ }
574
+ this.backward(cur);
575
+ }
576
+ done(back, length) {
577
+ this.back = back;
578
+ this.length = length;
579
+ return -1;
580
+ }
581
+ first(position) {
582
+ const { matcher, data, path, reps, repLens, probs } = this;
583
+ const distances = matcher.distances;
584
+ let main;
585
+ let count;
586
+ if (matcher.readAhead === 0) {
587
+ main = matcher.find();
588
+ count = matcher.count;
589
+ }
590
+ else {
591
+ main = this.longest;
592
+ count = this.found;
593
+ }
594
+ const available = Math.min(matcher.available + 1, LONGEST);
595
+ if (available < 2)
596
+ return this.done(NO_BACK, 1);
597
+ const buf = matcher.readPos - 1;
598
+ let best = 0;
599
+ for (let rep = 0; rep < REPS; rep += 1) {
600
+ const back = buf - reps[rep] - 1;
601
+ if (data[buf] !== data[back] || data[buf + 1] !== data[back + 1]) {
602
+ repLens[rep] = 0;
603
+ continue;
604
+ }
605
+ repLens[rep] = matcher.same(buf, back, 2, available);
606
+ if (repLens[rep] > repLens[best])
607
+ best = rep;
608
+ }
609
+ if (repLens[best] >= NICE) {
610
+ matcher.skip(repLens[best] - 1);
611
+ return this.done(best, repLens[best]);
612
+ }
613
+ if (main >= NICE) {
614
+ matcher.skip(main - 1);
615
+ return this.done(distances[count - 1] + REPS, main);
616
+ }
617
+ const current = data[buf];
618
+ const matchByte = data[buf - reps[0] - 1];
619
+ if (main < 2 && current !== matchByte && repLens[best] < 2) {
620
+ return this.done(NO_BACK, 1);
621
+ }
622
+ path.state[0] = this.state;
623
+ const spot = position & this.positionMask;
624
+ path.price[1] =
625
+ price0(probs, IS_MATCH + this.state * 16 + spot) +
626
+ this.literalPrice(position, data[buf - 1], this.state >= LITERAL_STATES, matchByte, current);
627
+ this.literalChoice(path, 1);
628
+ const matchPrice = price1(probs, IS_MATCH + this.state * 16 + spot);
629
+ const repMatchPrice = matchPrice + price1(probs, IS_REPEAT + this.state);
630
+ if (matchByte === current) {
631
+ const shortPrice = repMatchPrice + this.shortRepPrice(this.state, spot);
632
+ if (shortPrice < path.price[1]) {
633
+ path.price[1] = shortPrice;
634
+ this.shortRepChoice(path, 1);
635
+ }
636
+ }
637
+ const end = Math.max(main, repLens[best]);
638
+ if (end < 2)
639
+ return this.done(path.back[1], 1);
640
+ path.position[1] = 0;
641
+ for (let rep = 0; rep < REPS; rep += 1)
642
+ path.backs[rep] = reps[rep];
643
+ for (let length = end; length >= 2; length -= 1)
644
+ path.price[length] = INFINITE;
645
+ this.firstReps(repMatchPrice, spot);
646
+ this.firstMatches(matchPrice, spot, main, count);
647
+ return end;
648
+ }
649
+ firstReps(repMatchPrice, spot) {
650
+ const { path, repLens } = this;
651
+ for (let rep = 0; rep < REPS; rep += 1) {
652
+ if (repLens[rep] < 2)
653
+ continue;
654
+ const price = repMatchPrice + this.pureRepPrice(rep, this.state, spot);
655
+ for (let length = repLens[rep]; length >= 2; length -= 1) {
656
+ const total = price + this.repLengths.price(length, spot);
657
+ if (total >= path.price[length])
658
+ continue;
659
+ path.price[length] = total;
660
+ path.position[length] = 0;
661
+ path.back[length] = rep;
662
+ path.previousLiteral[length] = 0;
663
+ }
664
+ }
665
+ }
666
+ firstMatches(matchPrice, spot, main, count) {
667
+ const { path, repLens, probs } = this;
668
+ const { lengths, distances } = this.matcher;
669
+ const normal = matchPrice + price0(probs, IS_REPEAT + this.state);
670
+ let length = repLens[0] >= 2 ? repLens[0] + 1 : 2;
671
+ if (length > main)
672
+ return;
673
+ let index = 0;
674
+ while (length > lengths[index])
675
+ index += 1;
676
+ for (;; length += 1) {
677
+ const distance = distances[index];
678
+ const total = normal + this.distanceLengthPrice(distance, length, spot);
679
+ if (total < path.price[length]) {
680
+ path.price[length] = total;
681
+ path.position[length] = 0;
682
+ path.back[length] = distance + REPS;
683
+ path.previousLiteral[length] = 0;
684
+ }
685
+ if (length === lengths[index]) {
686
+ index += 1;
687
+ if (index === count)
688
+ break;
689
+ }
690
+ }
691
+ }
692
+ extend(reps, buf, lengthEnd, position, cur, availableFull) {
693
+ const { path, data, probs } = this;
694
+ const state = this.stateAt(reps, cur);
695
+ const spot = position & this.positionMask;
696
+ const curPrice = path.price[cur];
697
+ const current = data[buf];
698
+ const matchByte = data[buf - reps[0] - 1];
699
+ const literalTotal = curPrice +
700
+ price0(probs, IS_MATCH + state * 16 + spot) +
701
+ this.literalPrice(position, data[buf - 1], state >= LITERAL_STATES, matchByte, current);
702
+ let end = lengthEnd;
703
+ let nextIsLiteral = false;
704
+ if (literalTotal < path.price[cur + 1]) {
705
+ path.price[cur + 1] = literalTotal;
706
+ path.position[cur + 1] = cur;
707
+ this.literalChoice(path, cur + 1);
708
+ nextIsLiteral = true;
709
+ }
710
+ const matchPrice = curPrice + price1(probs, IS_MATCH + state * 16 + spot);
711
+ const repMatchPrice = matchPrice + price1(probs, IS_REPEAT + state);
712
+ if (matchByte === current &&
713
+ !(path.position[cur + 1] < cur && path.back[cur + 1] === 0)) {
714
+ const shortPrice = repMatchPrice + this.shortRepPrice(state, spot);
715
+ if (shortPrice <= path.price[cur + 1]) {
716
+ path.price[cur + 1] = shortPrice;
717
+ path.position[cur + 1] = cur;
718
+ this.shortRepChoice(path, cur + 1);
719
+ nextIsLiteral = true;
720
+ }
721
+ }
722
+ if (availableFull < 2)
723
+ return end;
724
+ const available = Math.min(availableFull, NICE);
725
+ if (!nextIsLiteral && matchByte !== current) {
726
+ end = this.literalThenRep(reps, buf, end, cur, position, state, literalTotal, availableFull);
727
+ }
728
+ const from = {
729
+ reps,
730
+ buf,
731
+ cur,
732
+ position,
733
+ state,
734
+ spot,
735
+ matchPrice,
736
+ repMatchPrice,
737
+ available,
738
+ availableFull,
739
+ };
740
+ return this.extendMatches(from, this.extendReps(from, end));
741
+ }
742
+ stateAt(reps, cur) {
743
+ const { path } = this;
744
+ let positionBefore = path.position[cur];
745
+ let state;
746
+ if (path.previousLiteral[cur]) {
747
+ positionBefore -= 1;
748
+ if (path.twice[cur]) {
749
+ state = path.state[path.positionTwice[cur]];
750
+ state = path.backTwice[cur] < REPS ? afterLongRep(state) : afterMatch(state);
751
+ }
752
+ else {
753
+ state = path.state[positionBefore];
754
+ }
755
+ state = afterLiteral(state);
756
+ }
757
+ else {
758
+ state = path.state[positionBefore];
759
+ }
760
+ if (positionBefore === cur - 1) {
761
+ state = path.back[cur] === 0 ? afterShortRep(state) : afterLiteral(state);
762
+ }
763
+ else {
764
+ state = this.advance(reps, cur, positionBefore, state);
765
+ }
766
+ path.state[cur] = state;
767
+ for (let rep = 0; rep < REPS; rep += 1)
768
+ path.backs[cur * REPS + rep] = reps[rep];
769
+ return state;
770
+ }
771
+ advance(reps, cur, before, start) {
772
+ const { path } = this;
773
+ let positionBefore = before;
774
+ let state = start;
775
+ let distance;
776
+ if (path.previousLiteral[cur] && path.twice[cur]) {
777
+ positionBefore = path.positionTwice[cur];
778
+ distance = path.backTwice[cur];
779
+ state = afterLongRep(state);
780
+ }
781
+ else {
782
+ distance = path.back[cur];
783
+ state = distance < REPS ? afterLongRep(state) : afterMatch(state);
784
+ }
785
+ const backs = positionBefore * REPS;
786
+ if (distance < REPS) {
787
+ reps[0] = path.backs[backs + distance];
788
+ let at = 1;
789
+ for (; at <= distance; at += 1)
790
+ reps[at] = path.backs[backs + at - 1];
791
+ for (; at < REPS; at += 1)
792
+ reps[at] = path.backs[backs + at];
793
+ }
794
+ else {
795
+ reps[0] = distance - REPS;
796
+ for (let at = 1; at < REPS; at += 1)
797
+ reps[at] = path.backs[backs + at - 1];
798
+ }
799
+ return state;
800
+ }
801
+ raise(path, end, upTo) {
802
+ let last = end;
803
+ while (last < upTo) {
804
+ last += 1;
805
+ path.price[last] = INFINITE;
806
+ }
807
+ return last;
808
+ }
809
+ literalThenRep(reps, buf, lengthEnd, cur, position, state, literalTotal, availableFull) {
810
+ const { path, probs } = this;
811
+ const limit = Math.min(availableFull, NICE + 1);
812
+ const test = this.matcher.same(buf, buf - reps[0] - 1, 1, limit) - 1;
813
+ if (test < 2)
814
+ return lengthEnd;
815
+ const after = afterLiteral(state);
816
+ const next = (position + 1) & this.positionMask;
817
+ const nextRepPrice = literalTotal +
818
+ price1(probs, IS_MATCH + after * 16 + next) +
819
+ price1(probs, IS_REPEAT + after);
820
+ const offset = cur + 1 + test;
821
+ const end = this.raise(path, lengthEnd, offset);
822
+ const total = nextRepPrice + this.repPrice(0, test, after, next);
823
+ if (total >= path.price[offset])
824
+ return end;
825
+ path.price[offset] = total;
826
+ path.position[offset] = cur + 1;
827
+ path.back[offset] = 0;
828
+ path.previousLiteral[offset] = 1;
829
+ path.twice[offset] = 0;
830
+ return end;
831
+ }
832
+ extendReps(from, lengthEnd) {
833
+ const { path, data } = this;
834
+ const { reps, buf, cur, state, spot, repMatchPrice } = from;
835
+ let end = lengthEnd;
836
+ let start = 2;
837
+ for (let rep = 0; rep < REPS; rep += 1) {
838
+ const back = buf - reps[rep] - 1;
839
+ if (data[buf] !== data[back] || data[buf + 1] !== data[back + 1])
840
+ continue;
841
+ const test = this.matcher.same(buf, back, 2, from.available);
842
+ end = this.raise(path, end, cur + test);
843
+ const price = repMatchPrice + this.pureRepPrice(rep, state, spot);
844
+ for (let length = test; length >= 2; length -= 1) {
845
+ const total = price + this.repLengths.price(length, spot);
846
+ if (total >= path.price[cur + length])
847
+ continue;
848
+ path.price[cur + length] = total;
849
+ path.position[cur + length] = cur;
850
+ path.back[cur + length] = rep;
851
+ path.previousLiteral[cur + length] = 0;
852
+ }
853
+ if (rep === 0)
854
+ start = test + 1;
855
+ end = this.matchLiteralRep(from, end, {
856
+ back,
857
+ test,
858
+ price: price + this.repLengths.price(test, spot),
859
+ mode: afterLongRep(state),
860
+ previous: rep,
861
+ isRep: true,
862
+ });
863
+ }
864
+ return [end, start];
865
+ }
866
+ matchLiteralRep(from, lengthEnd, plan) {
867
+ const { path, data, probs } = this;
868
+ const { buf, cur, position } = from;
869
+ const limit = Math.min(from.availableFull, plan.test + 1 + NICE);
870
+ let again = plan.test + 1;
871
+ if (again < limit)
872
+ again = this.matcher.same(buf, plan.back, again, limit);
873
+ again -= plan.test + 1;
874
+ if (again < 2)
875
+ return lengthEnd;
876
+ let after = plan.mode;
877
+ let next = (position + plan.test) & this.positionMask;
878
+ const literalPrice = plan.price +
879
+ price0(probs, IS_MATCH + after * 16 + next) +
880
+ this.literalPrice(position + plan.test, data[buf + plan.test - 1], true, data[plan.back + plan.test], data[buf + plan.test]);
881
+ after = afterLiteral(after);
882
+ next = (next + 1) & this.positionMask;
883
+ const nextRepPrice = literalPrice +
884
+ price1(probs, IS_MATCH + after * 16 + next) +
885
+ price1(probs, IS_REPEAT + after);
886
+ const offset = cur + plan.test + 1 + again;
887
+ const end = this.raise(path, lengthEnd, offset);
888
+ const total = nextRepPrice + this.repPrice(0, again, after, next);
889
+ if (total >= path.price[offset])
890
+ return end;
891
+ path.price[offset] = total;
892
+ path.position[offset] = cur + plan.test + 1;
893
+ path.back[offset] = 0;
894
+ path.previousLiteral[offset] = 1;
895
+ path.twice[offset] = 1;
896
+ path.positionTwice[offset] = cur;
897
+ path.backTwice[offset] = plan.isRep ? plan.previous : plan.previous + REPS;
898
+ return end;
899
+ }
900
+ extendMatches(from, found) {
901
+ const { path, probs } = this;
902
+ const { lengths, distances } = this.matcher;
903
+ const { cur, spot, matchPrice, available, state } = from;
904
+ let [end, start] = found;
905
+ let longest = this.longest;
906
+ let count = this.found;
907
+ if (longest > available) {
908
+ longest = available;
909
+ count = 0;
910
+ while (longest > lengths[count])
911
+ count += 1;
912
+ lengths[count] = longest;
913
+ count += 1;
914
+ }
915
+ if (longest < start)
916
+ return end;
917
+ const normal = matchPrice + price0(probs, IS_REPEAT + state);
918
+ end = this.raise(path, end, cur + longest);
919
+ let index = 0;
920
+ while (start > lengths[index])
921
+ index += 1;
922
+ for (let test = start;; test += 1) {
923
+ const back = distances[index];
924
+ const total = normal + this.distanceLengthPrice(back, test, spot);
925
+ if (total < path.price[cur + test]) {
926
+ path.price[cur + test] = total;
927
+ path.position[cur + test] = cur;
928
+ path.back[cur + test] = back + REPS;
929
+ path.previousLiteral[cur + test] = 0;
930
+ }
931
+ if (test === lengths[index]) {
932
+ end = this.matchLiteralRep(from, end, {
933
+ back: from.buf - back - 1,
934
+ test,
935
+ price: total,
936
+ mode: afterMatch(state),
937
+ previous: back,
938
+ isRep: false,
939
+ });
940
+ index += 1;
941
+ if (index === count)
942
+ break;
943
+ }
944
+ }
945
+ return end;
946
+ }
947
+ }
948
+ /** One block as a raw stream, the way `lzma.ts` and liblzma read it. */
949
+ export const compress = (data, tuning) => {
950
+ if (data.length > BYTES_LIMIT)
951
+ throw new Error("lzma: a block over 2 MB");
952
+ return new Encoder(data, tuning).run();
953
+ };
954
+ //# sourceMappingURL=compress.js.map