@patrickdk77/archive-defuse 0.1.2 → 0.1.3
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/README.md +1 -1
- package/dist/lzma1/NOTICE +32 -18
- package/dist/lzma1/crc32.d.ts +2 -1
- package/dist/lzma1/crc32.js +3 -2
- package/dist/lzma1/hash234.d.ts +3 -1
- package/dist/lzma1/hash234.js +9 -4
- package/dist/lzma1/hc4.d.ts +3 -2
- package/dist/lzma1/hc4.js +6 -4
- package/dist/lzma1/header.js +1 -1
- package/dist/lzma1/lz-decoder.d.ts +14 -14
- package/dist/lzma1/lz-decoder.js +15 -33
- package/dist/lzma1/lz-encoder.d.ts +3 -2
- package/dist/lzma1/lz-encoder.js +6 -4
- package/dist/lzma1/lzma-coder.d.ts +51 -27
- package/dist/lzma1/lzma-coder.js +114 -48
- package/dist/lzma1/lzma-decoder.d.ts +41 -19
- package/dist/lzma1/lzma-decoder.js +159 -437
- package/dist/lzma1/lzma-encoder-fast.d.ts +2 -1
- package/dist/lzma1/lzma-encoder-fast.js +3 -2
- package/dist/lzma1/lzma-encoder.d.ts +68 -40
- package/dist/lzma1/lzma-encoder.js +289 -232
- package/dist/lzma1/lzma2-decoder.d.ts +17 -2
- package/dist/lzma1/lzma2-decoder.js +71 -15
- package/dist/lzma1/range-coder.d.ts +4 -0
- package/dist/lzma1/range-coder.js +5 -1
- package/dist/lzma1/range-decoder.d.ts +22 -22
- package/dist/lzma1/range-decoder.js +74 -32
- package/dist/lzma1/range-encoder.d.ts +26 -28
- package/dist/lzma1/range-encoder.js +98 -150
- package/package.json +1 -1
|
@@ -32,8 +32,11 @@
|
|
|
32
32
|
* they arrive and decodes an LZMA chunk once its compressed data, at most
|
|
33
33
|
* 64 KiB, is complete.
|
|
34
34
|
*
|
|
35
|
-
* Ported from XZ for Java (0BSD)
|
|
35
|
+
* Ported from XZ for Java (0BSD), `src/org/tukaani/xz/LZMA2InputStream.java`,
|
|
36
|
+
* with `rangecoder/RangeDecoderFromBuffer.java` and the LZMA2-only methods of
|
|
37
|
+
* `lz/LZDecoder.java` as functions, by Lasse Collin and Igor Pavlov.
|
|
36
38
|
*/
|
|
39
|
+
import { LzDecoder } from './lz-decoder';
|
|
37
40
|
export declare class Lzma2Decoder {
|
|
38
41
|
private readonly lz;
|
|
39
42
|
private readonly rc;
|
|
@@ -70,7 +73,7 @@ export declare class Lzma2Decoder {
|
|
|
70
73
|
* Approximate memory needed to decode, in KiB, as XZ for Java's
|
|
71
74
|
* `LZMA2InputStream.getMemoryUsage` computes it.
|
|
72
75
|
*/
|
|
73
|
-
static
|
|
76
|
+
static getMemoryUsageKb(dictSize: number): number;
|
|
74
77
|
/** Decodes as much of `input` as possible. */
|
|
75
78
|
write(input: Uint8Array): void;
|
|
76
79
|
/** Throws if the data ended before its end marker. */
|
|
@@ -83,3 +86,15 @@ export declare class Lzma2Decoder {
|
|
|
83
86
|
private currentLzma;
|
|
84
87
|
private decodeLzmaChunk;
|
|
85
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Copies `len` bytes of uncompressed data from `input` at `inPos` into the
|
|
91
|
+
* dictionary: `LZDecoder.copyUncompressed`. XZ for Java copies up to the end
|
|
92
|
+
* of the buffer and leaves the rest to its caller; this copy continues past
|
|
93
|
+
* the end like `repeat`.
|
|
94
|
+
*/
|
|
95
|
+
export declare function copyUncompressed(lz: LzDecoder, input: Uint8Array, inPosIn: number, lenIn: number): void;
|
|
96
|
+
/**
|
|
97
|
+
* Empties the dictionary, so matches can't reach back before this point:
|
|
98
|
+
* `LZDecoder.reset`.
|
|
99
|
+
*/
|
|
100
|
+
export declare function resetDictionary(lz: LzDecoder): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// Copied from lzma1 (Apache-2.0, Copyright Filip Seman) and changed for
|
|
2
|
+
// Copied from lzma1 0.6.1 (Apache-2.0, Copyright Filip Seman) and changed for archive-defuse. NOTICE in this folder lists the changes.
|
|
3
3
|
/**
|
|
4
4
|
* Decoder for raw LZMA2 data, the chunked format inside `.xz` blocks and
|
|
5
5
|
* 7z LZMA2 entries. LZMA2 has no header of its own. The container stores
|
|
@@ -34,24 +34,28 @@
|
|
|
34
34
|
* they arrive and decodes an LZMA chunk once its compressed data, at most
|
|
35
35
|
* 64 KiB, is complete.
|
|
36
36
|
*
|
|
37
|
-
* Ported from XZ for Java (0BSD)
|
|
37
|
+
* Ported from XZ for Java (0BSD), `src/org/tukaani/xz/LZMA2InputStream.java`,
|
|
38
|
+
* with `rangecoder/RangeDecoderFromBuffer.java` and the LZMA2-only methods of
|
|
39
|
+
* `lz/LZDecoder.java` as functions, by Lasse Collin and Igor Pavlov.
|
|
38
40
|
*/
|
|
39
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
42
|
exports.Lzma2Decoder = void 0;
|
|
43
|
+
exports.copyUncompressed = copyUncompressed;
|
|
44
|
+
exports.resetDictionary = resetDictionary;
|
|
41
45
|
const lz_decoder_1 = require("./lz-decoder");
|
|
42
46
|
const lzma_decoder_1 = require("./lzma-decoder");
|
|
43
47
|
const range_decoder_1 = require("./range-decoder");
|
|
44
|
-
const COMPRESSED_SIZE_MAX = 1 << 16;
|
|
45
48
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
49
|
+
* Input kept back while a chunk is decoded, as `INPUT_MARGIN` in lzma1's alone-decoder.ts, which archive-defuse does
|
|
50
|
+
* not carry. The value is lzma1's.
|
|
48
51
|
*/
|
|
49
52
|
const INPUT_MARGIN = 64;
|
|
53
|
+
const COMPRESSED_SIZE_MAX = 1 << 16;
|
|
50
54
|
/** Largest chunk header: control byte, two sizes and the properties. */
|
|
51
55
|
const CHUNK_HEADER_SIZE_MAX = 6;
|
|
52
56
|
class Lzma2Decoder {
|
|
53
57
|
lz;
|
|
54
|
-
rc = new range_decoder_1.
|
|
58
|
+
rc = new range_decoder_1.RangeDecoder();
|
|
55
59
|
lzma = null;
|
|
56
60
|
uncompressedSize = 0;
|
|
57
61
|
compressedSize = 0;
|
|
@@ -87,7 +91,7 @@ class Lzma2Decoder {
|
|
|
87
91
|
* Approximate memory needed to decode, in KiB, as XZ for Java's
|
|
88
92
|
* `LZMA2InputStream.getMemoryUsage` computes it.
|
|
89
93
|
*/
|
|
90
|
-
static
|
|
94
|
+
static getMemoryUsageKb(dictSize) {
|
|
91
95
|
// The base state is around 30-40 KiB (probabilities etc.), the range
|
|
92
96
|
// decoder needs COMPRESSED_SIZE_MAX bytes for buffering, and the LZ
|
|
93
97
|
// decoder needs a dictionary buffer.
|
|
@@ -103,7 +107,7 @@ class Lzma2Decoder {
|
|
|
103
107
|
}
|
|
104
108
|
if (!this.isLzmaChunk) {
|
|
105
109
|
const copySize = Math.min(this.uncompressedSize, input.length - pos);
|
|
106
|
-
this.lz
|
|
110
|
+
copyUncompressed(this.lz, input, pos, copySize);
|
|
107
111
|
pos += copySize;
|
|
108
112
|
this.outPos += copySize;
|
|
109
113
|
this.uncompressedSize -= copySize;
|
|
@@ -127,9 +131,9 @@ class Lzma2Decoder {
|
|
|
127
131
|
}
|
|
128
132
|
}
|
|
129
133
|
/** Collects the chunk header and decodes it once it is complete. */
|
|
130
|
-
readChunkHeader(input,
|
|
134
|
+
readChunkHeader(input, posIn) {
|
|
135
|
+
let pos = posIn;
|
|
131
136
|
const header = this.header;
|
|
132
|
-
let pos = start;
|
|
133
137
|
header[this.headerPos++] = input[pos++];
|
|
134
138
|
const size = chunkHeaderSize(header[0]);
|
|
135
139
|
const copySize = Math.min(size - this.headerPos, input.length - pos);
|
|
@@ -151,7 +155,7 @@ class Lzma2Decoder {
|
|
|
151
155
|
if (control >= 0xe0 || control === 0x01) {
|
|
152
156
|
this.needProps = true;
|
|
153
157
|
this.needDictReset = false;
|
|
154
|
-
this.lz
|
|
158
|
+
resetDictionary(this.lz);
|
|
155
159
|
this.outPos = 0;
|
|
156
160
|
}
|
|
157
161
|
else if (this.needDictReset) {
|
|
@@ -184,8 +188,8 @@ class Lzma2Decoder {
|
|
|
184
188
|
this.uncompressedSize = readUnsignedShort(header, 1) + 1;
|
|
185
189
|
}
|
|
186
190
|
}
|
|
187
|
-
decodeProps(
|
|
188
|
-
let props =
|
|
191
|
+
decodeProps(propsIn) {
|
|
192
|
+
let props = propsIn;
|
|
189
193
|
if (props > (4 * 5 + 4) * 9 + 8) {
|
|
190
194
|
throw new Error('Corrupted input: invalid LZMA2 properties');
|
|
191
195
|
}
|
|
@@ -207,14 +211,14 @@ class Lzma2Decoder {
|
|
|
207
211
|
decodeLzmaChunk() {
|
|
208
212
|
const lzma = this.currentLzma();
|
|
209
213
|
const outLimit = this.outPos + this.uncompressedSize;
|
|
210
|
-
this.rc
|
|
214
|
+
prepareInputBuffer(this.rc, this.inBuf, this.compressedSize);
|
|
211
215
|
lzma.outPos = this.outPos;
|
|
212
216
|
lzma.decode(outLimit, this.compressedSize);
|
|
213
217
|
// Decoding stops before the chunk's size when it reads past the
|
|
214
218
|
// chunk's data or decodes an end marker. XZ for Java throws in both
|
|
215
219
|
// cases. A match that would cross the chunk's end throws in
|
|
216
220
|
// `decode`, which XZ for Java detects with `lz.hasPending()`.
|
|
217
|
-
if (lzma.outPos !== outLimit || !this.rc.
|
|
221
|
+
if (lzma.outPos !== outLimit || !isChunkFinished(this.rc, this.compressedSize)) {
|
|
218
222
|
throw new Error("Corrupted input: LZMA2 chunk doesn't match its sizes");
|
|
219
223
|
}
|
|
220
224
|
this.outPos = outLimit;
|
|
@@ -222,6 +226,58 @@ class Lzma2Decoder {
|
|
|
222
226
|
}
|
|
223
227
|
}
|
|
224
228
|
exports.Lzma2Decoder = Lzma2Decoder;
|
|
229
|
+
/**
|
|
230
|
+
* Copies `len` bytes of uncompressed data from `input` at `inPos` into the
|
|
231
|
+
* dictionary: `LZDecoder.copyUncompressed`. XZ for Java copies up to the end
|
|
232
|
+
* of the buffer and leaves the rest to its caller; this copy continues past
|
|
233
|
+
* the end like `repeat`.
|
|
234
|
+
*/
|
|
235
|
+
function copyUncompressed(lz, input, inPosIn, lenIn) {
|
|
236
|
+
let inPos = inPosIn;
|
|
237
|
+
let len = lenIn;
|
|
238
|
+
while (len > 0) {
|
|
239
|
+
const copySize = Math.min(lz.buf.length - lz.pos, len);
|
|
240
|
+
lz.buf.set(input.subarray(inPos, inPos + copySize), lz.pos);
|
|
241
|
+
lz.pos += copySize;
|
|
242
|
+
inPos += copySize;
|
|
243
|
+
len -= copySize;
|
|
244
|
+
if (lz.pos === lz.buf.length) {
|
|
245
|
+
lz.onBufferEnd();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Empties the dictionary, so matches can't reach back before this point:
|
|
251
|
+
* `LZDecoder.reset`.
|
|
252
|
+
*/
|
|
253
|
+
function resetDictionary(lz) {
|
|
254
|
+
// In XZ for Java the caller flushes first. Here the sink has to get the
|
|
255
|
+
// pending bytes before the positions restart, or they are lost.
|
|
256
|
+
lz.flush();
|
|
257
|
+
lz.start = 0;
|
|
258
|
+
lz.pos = 0;
|
|
259
|
+
lz.wrapped = false;
|
|
260
|
+
// getByte(0) has to return 0x00 when nothing has been decoded.
|
|
261
|
+
lz.buf[lz.buf.length - 1] = 0x00;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Starts decoding the `len` bytes of chunk data at the start of `input`:
|
|
265
|
+
* `RangeDecoderFromBuffer.prepareInputBuffer`. Every LZMA chunk starts a new
|
|
266
|
+
* range coder.
|
|
267
|
+
*/
|
|
268
|
+
function prepareInputBuffer(rc, input, len) {
|
|
269
|
+
if (len < range_decoder_1.RANGE_DECODER_INIT_SIZE) {
|
|
270
|
+
throw new Error('Corrupted input: LZMA2 chunk is too short');
|
|
271
|
+
}
|
|
272
|
+
rc.init(input, 0);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* True when the chunk's `len` bytes have been consumed exactly and the range
|
|
276
|
+
* coder is finished: `RangeDecoderFromBuffer.isFinished`.
|
|
277
|
+
*/
|
|
278
|
+
function isChunkFinished(rc, len) {
|
|
279
|
+
return rc.pos === len && rc.code === 0;
|
|
280
|
+
}
|
|
225
281
|
/** Size of the chunk header that starts with `control`. */
|
|
226
282
|
function chunkHeaderSize(control) {
|
|
227
283
|
if (control >= 0xc0) {
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Constants shared by the range encoder and decoder.
|
|
3
3
|
*
|
|
4
|
+
* Ported from XZ for Java (0BSD), `src/org/tukaani/xz/rangecoder/RangeCoder.java`,
|
|
5
|
+
* by Lasse Collin and Igor Pavlov. The Java code's `(range & TOP_MASK) == 0`
|
|
6
|
+
* test appears here as the unsigned comparison `range < TOP_VALUE`.
|
|
7
|
+
*
|
|
4
8
|
* LZMA's entropy coder is a binary range coder: every coded bit has an
|
|
5
9
|
* adaptive probability (an 11-bit integer, the chance that the bit is 0)
|
|
6
10
|
* that is updated after each use.
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// Copied from lzma1 (Apache-2.0, Copyright Filip Seman) and changed for
|
|
2
|
+
// Copied from lzma1 0.6.1 (Apache-2.0, Copyright Filip Seman) and changed for archive-defuse. NOTICE in this folder lists the changes.
|
|
3
3
|
/**
|
|
4
4
|
* Constants shared by the range encoder and decoder.
|
|
5
5
|
*
|
|
6
|
+
* Ported from XZ for Java (0BSD), `src/org/tukaani/xz/rangecoder/RangeCoder.java`,
|
|
7
|
+
* by Lasse Collin and Igor Pavlov. The Java code's `(range & TOP_MASK) == 0`
|
|
8
|
+
* test appears here as the unsigned comparison `range < TOP_VALUE`.
|
|
9
|
+
*
|
|
6
10
|
* LZMA's entropy coder is a binary range coder: every coded bit has an
|
|
7
11
|
* adaptive probability (an 11-bit integer, the chance that the bit is 0)
|
|
8
12
|
* that is updated after each use.
|
|
@@ -1,15 +1,25 @@
|
|
|
1
|
-
/** Number of bytes the range decoder reads on initialization. */
|
|
2
|
-
export declare const RANGE_DECODER_INIT_SIZE = 5;
|
|
3
1
|
/**
|
|
4
2
|
* Range decoder reading from an in-memory byte array.
|
|
5
3
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Ported from XZ for Java (0BSD), `src/org/tukaani/xz/rangecoder/RangeDecoder.java`
|
|
5
|
+
* and `RangeDecoderFromStream.java`, by Lasse Collin and Igor Pavlov.
|
|
6
|
+
*
|
|
7
|
+
* Integer adaptations: `range` and `code` are unsigned 32-bit values in
|
|
8
|
+
* regular numbers (`<<` followed by `>>> 0`), so `Integer.compareUnsigned`
|
|
9
|
+
* becomes a plain `<`, and `(range & TOP_MASK) == 0` becomes `range <
|
|
10
|
+
* TOP_VALUE`. In `decodeDirectBits`, `(code - range) >>> 31` wraps to the
|
|
11
|
+
* same 32-bit pattern as Java's int subtraction.
|
|
8
12
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
13
|
+
* Contract adaptations: instead of an input stream, the input arrives in
|
|
14
|
+
* chunks (`setInput`) and running out of it throws, so a truncated stream
|
|
15
|
+
* is detected like the Java code's read past the end of the stream. An
|
|
16
|
+
* LZMA2 chunk is a buffer with spare bytes after its data, and a read into
|
|
17
|
+
* them makes the chunk fail, at the latest at its end check in
|
|
18
|
+
* `lzma2-decoder.ts`.
|
|
12
19
|
*/
|
|
20
|
+
import { type Probs } from './range-coder';
|
|
21
|
+
/** Number of bytes the range decoder reads on initialization. */
|
|
22
|
+
export declare const RANGE_DECODER_INIT_SIZE = 5;
|
|
13
23
|
export declare class RangeDecoder {
|
|
14
24
|
range: number;
|
|
15
25
|
code: number;
|
|
@@ -23,19 +33,9 @@ export declare class RangeDecoder {
|
|
|
23
33
|
/** True when the encoder's flush bytes have been consumed exactly. */
|
|
24
34
|
isFinished(): boolean;
|
|
25
35
|
private readByte;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
*
|
|
32
|
-
* Ported from XZ for Java (0BSD) by Lasse Collin and Igor Pavlov.
|
|
33
|
-
*/
|
|
34
|
-
export declare class RangeDecoderFromBuffer extends RangeDecoder {
|
|
35
|
-
/** Position after the chunk's compressed data. */
|
|
36
|
-
private end;
|
|
37
|
-
/** Starts decoding the `len` bytes of chunk data at the start of `input`. */
|
|
38
|
-
prepareInputBuffer(input: Uint8Array, len: number): void;
|
|
39
|
-
/** True when the chunk's data has been consumed exactly. */
|
|
40
|
-
isFinished(): boolean;
|
|
36
|
+
normalize(): void;
|
|
37
|
+
decodeBit(probs: Probs, index: number): number;
|
|
38
|
+
decodeBitTree(probs: Probs, offset: number, bits: number): number;
|
|
39
|
+
decodeReverseBitTree(probs: Probs, offset: number, bits: number): number;
|
|
40
|
+
decodeDirectBits(countIn: number): number;
|
|
41
41
|
}
|
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
exports.RangeDecoderFromBuffer = exports.RangeDecoder = exports.RANGE_DECODER_INIT_SIZE = void 0;
|
|
4
|
-
// Copied from lzma1 (Apache-2.0, Copyright Filip Seman) and changed for lzma-defuse. NOTICE in this folder lists the changes.
|
|
5
|
-
/** Number of bytes the range decoder reads on initialization. */
|
|
6
|
-
exports.RANGE_DECODER_INIT_SIZE = 5;
|
|
2
|
+
// Copied from lzma1 0.6.1 (Apache-2.0, Copyright Filip Seman) and changed for archive-defuse. NOTICE in this folder lists the changes.
|
|
7
3
|
/**
|
|
8
4
|
* Range decoder reading from an in-memory byte array.
|
|
9
5
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* Ported from XZ for Java (0BSD), `src/org/tukaani/xz/rangecoder/RangeDecoder.java`
|
|
7
|
+
* and `RangeDecoderFromStream.java`, by Lasse Collin and Igor Pavlov.
|
|
12
8
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
9
|
+
* Integer adaptations: `range` and `code` are unsigned 32-bit values in
|
|
10
|
+
* regular numbers (`<<` followed by `>>> 0`), so `Integer.compareUnsigned`
|
|
11
|
+
* becomes a plain `<`, and `(range & TOP_MASK) == 0` becomes `range <
|
|
12
|
+
* TOP_VALUE`. In `decodeDirectBits`, `(code - range) >>> 31` wraps to the
|
|
13
|
+
* same 32-bit pattern as Java's int subtraction.
|
|
14
|
+
*
|
|
15
|
+
* Contract adaptations: instead of an input stream, the input arrives in
|
|
16
|
+
* chunks (`setInput`) and running out of it throws, so a truncated stream
|
|
17
|
+
* is detected like the Java code's read past the end of the stream. An
|
|
18
|
+
* LZMA2 chunk is a buffer with spare bytes after its data, and a read into
|
|
19
|
+
* them makes the chunk fail, at the latest at its end check in
|
|
20
|
+
* `lzma2-decoder.ts`.
|
|
16
21
|
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.RangeDecoder = exports.RANGE_DECODER_INIT_SIZE = void 0;
|
|
24
|
+
const range_coder_1 = require("./range-coder");
|
|
25
|
+
/** Number of bytes the range decoder reads on initialization. */
|
|
26
|
+
exports.RANGE_DECODER_INIT_SIZE = 5;
|
|
17
27
|
class RangeDecoder {
|
|
18
28
|
range = 0;
|
|
19
29
|
code = 0;
|
|
@@ -50,29 +60,61 @@ class RangeDecoder {
|
|
|
50
60
|
}
|
|
51
61
|
return this.input[this.pos++];
|
|
52
62
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
* coder, and its compressed data is complete in the buffer before decoding
|
|
58
|
-
* starts, so the data ends at a known position.
|
|
59
|
-
*
|
|
60
|
-
* Ported from XZ for Java (0BSD) by Lasse Collin and Igor Pavlov.
|
|
61
|
-
*/
|
|
62
|
-
class RangeDecoderFromBuffer extends RangeDecoder {
|
|
63
|
-
/** Position after the chunk's compressed data. */
|
|
64
|
-
end = 0;
|
|
65
|
-
/** Starts decoding the `len` bytes of chunk data at the start of `input`. */
|
|
66
|
-
prepareInputBuffer(input, len) {
|
|
67
|
-
if (len < exports.RANGE_DECODER_INIT_SIZE) {
|
|
68
|
-
throw new Error('Corrupted input: LZMA2 chunk is too short');
|
|
63
|
+
normalize() {
|
|
64
|
+
if (this.range < range_coder_1.TOP_VALUE) {
|
|
65
|
+
this.code = ((this.code << 8) | this.readByte()) >>> 0;
|
|
66
|
+
this.range = (this.range << 8) >>> 0;
|
|
69
67
|
}
|
|
70
|
-
this.init(input, 0);
|
|
71
|
-
this.end = len;
|
|
72
68
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
69
|
+
decodeBit(probs, index) {
|
|
70
|
+
this.normalize();
|
|
71
|
+
const prob = probs[index];
|
|
72
|
+
const bound = (this.range >>> range_coder_1.BIT_MODEL_TOTAL_BITS) * prob;
|
|
73
|
+
let bit;
|
|
74
|
+
if (this.code < bound) {
|
|
75
|
+
this.range = bound;
|
|
76
|
+
probs[index] = prob + ((range_coder_1.BIT_MODEL_TOTAL - prob) >>> range_coder_1.MOVE_BITS);
|
|
77
|
+
bit = 0;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
this.range -= bound;
|
|
81
|
+
this.code -= bound;
|
|
82
|
+
probs[index] = prob - (prob >>> range_coder_1.MOVE_BITS);
|
|
83
|
+
bit = 1;
|
|
84
|
+
}
|
|
85
|
+
return bit;
|
|
86
|
+
}
|
|
87
|
+
decodeBitTree(probs, offset, bits) {
|
|
88
|
+
let symbol = 1;
|
|
89
|
+
do {
|
|
90
|
+
symbol = (symbol << 1) | this.decodeBit(probs, offset + symbol);
|
|
91
|
+
} while (symbol < 1 << bits);
|
|
92
|
+
return symbol - (1 << bits);
|
|
93
|
+
}
|
|
94
|
+
decodeReverseBitTree(probs, offset, bits) {
|
|
95
|
+
let symbol = 1;
|
|
96
|
+
let i = 0;
|
|
97
|
+
let result = 0;
|
|
98
|
+
do {
|
|
99
|
+
const bit = this.decodeBit(probs, offset + symbol);
|
|
100
|
+
symbol = (symbol << 1) | bit;
|
|
101
|
+
result |= bit << i++;
|
|
102
|
+
} while (symbol < 1 << bits);
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
decodeDirectBits(countIn) {
|
|
106
|
+
let count = countIn;
|
|
107
|
+
let result = 0;
|
|
108
|
+
do {
|
|
109
|
+
this.normalize();
|
|
110
|
+
this.range >>>= 1;
|
|
111
|
+
// 1 when code < range as 32-bit values (the subtraction wraps
|
|
112
|
+
// to the same bit pattern as Java's int arithmetic).
|
|
113
|
+
const t = (this.code - this.range) >>> 31;
|
|
114
|
+
this.code = (this.code - (this.range & (t - 1))) >>> 0;
|
|
115
|
+
result = (result << 1) | (1 - t);
|
|
116
|
+
} while (--count !== 0);
|
|
117
|
+
return result;
|
|
76
118
|
}
|
|
77
119
|
}
|
|
78
|
-
exports.
|
|
120
|
+
exports.RangeDecoder = RangeDecoder;
|
|
@@ -1,53 +1,51 @@
|
|
|
1
|
-
import { type Probs } from './range-coder';
|
|
2
|
-
export declare function getBitPrice(prob: number, bit: number): number;
|
|
3
|
-
/** Price of a `bits`-bit symbol coded MSB-first with the bit tree at `offset`. */
|
|
4
|
-
export declare function getBitTreePrice(probs: Probs, offset: number, bits: number, symbolIn: number): number;
|
|
5
|
-
/** Price of a `bits`-bit symbol coded LSB-first with the bit tree at `offset`. */
|
|
6
|
-
export declare function getReverseBitTreePrice(probs: Probs, offset: number, bits: number, symbolIn: number): number;
|
|
7
|
-
/** Price of bits coded with a fixed 50% probability. */
|
|
8
|
-
export declare function getDirectBitsPrice(count: number): number;
|
|
9
1
|
/**
|
|
10
2
|
* Range encoder writing to its own growable buffer.
|
|
11
3
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
4
|
+
* Ported from XZ for Java (0BSD), `src/org/tukaani/xz/rangecoder/RangeEncoder.java`
|
|
5
|
+
* and `RangeEncoderToBuffer.java`, by Lasse Collin and Igor Pavlov.
|
|
14
6
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
7
|
+
* Integer adaptations (see the hazard checklist in `docs/verification.md`):
|
|
8
|
+
* - `low` needs 33 bits (32 bits plus a carry), so it is a regular number;
|
|
9
|
+
* doubles represent integers up to 2^53 exactly. The carry test uses
|
|
10
|
+
* division instead of `low >>> 32`.
|
|
11
|
+
* - `range` is an unsigned 32-bit value in a regular number: `<<` is
|
|
12
|
+
* followed by `>>> 0`, and `(range & TOP_MASK) == 0` becomes an
|
|
13
|
+
* unsigned `range < TOP_VALUE`.
|
|
14
|
+
* - Bitwise ops on values that may exceed 2^31 are kept off the signed
|
|
15
|
+
* int32 path (`low`'s 24-bit wrap multiplies by 256 instead of
|
|
16
|
+
* shifting).
|
|
17
17
|
*/
|
|
18
|
+
import { type Probs } from './range-coder';
|
|
19
|
+
export declare function createPriceTable(): Uint32Array;
|
|
20
|
+
export declare function getBitPrice(prob: number, bit: number): number;
|
|
21
|
+
export declare function getBitTreePrice(probs: Probs, offset: number, bits: number, symbolIn: number): number;
|
|
22
|
+
export declare function getReverseBitTreePrice(probs: Probs, offset: number, bits: number, symbolIn: number): number;
|
|
23
|
+
export declare function getDirectBitsPrice(count: number): number;
|
|
18
24
|
export declare class RangeEncoder {
|
|
19
25
|
private low;
|
|
20
26
|
private range;
|
|
21
27
|
private cache;
|
|
28
|
+
/**
|
|
29
|
+
* NOTE: int is OK for LZMA2 because a compressed chunk is not more
|
|
30
|
+
* than 64 KiB, but with LZMA1 there is no chunking so in theory
|
|
31
|
+
* cacheSize can grow very big. A JS number counts well past 2^32.
|
|
32
|
+
*/
|
|
22
33
|
private cacheSize;
|
|
23
34
|
private buf;
|
|
24
35
|
private size;
|
|
25
36
|
constructor(initialCapacity: number);
|
|
37
|
+
reset(): void;
|
|
26
38
|
/** Appends bytes that are not range coded, e.g. a header. */
|
|
27
39
|
writeBytes(bytes: Uint8Array): void;
|
|
28
40
|
/** Returns a copy of the output written so far and empties the buffer. */
|
|
29
41
|
take(): Uint8Array;
|
|
30
42
|
/** Flushes all pending bytes and returns the rest of the output. */
|
|
31
43
|
finish(): Uint8Array;
|
|
44
|
+
private writeByte;
|
|
45
|
+
private shiftLow;
|
|
32
46
|
encodeBit(probs: Probs, index: number, bit: number): void;
|
|
33
|
-
/** Encodes a `bits`-bit symbol MSB-first with the bit tree at `offset`. */
|
|
34
47
|
encodeBitTree(probs: Probs, offset: number, bits: number, symbol: number): void;
|
|
35
|
-
/** Encodes a `bits`-bit symbol LSB-first with the bit tree at `offset`. */
|
|
36
48
|
encodeReverseBitTree(probs: Probs, offset: number, bits: number, symbolIn: number): void;
|
|
37
|
-
/** Encodes a literal byte with the 0x100-leaf bit tree at `offset`. */
|
|
38
|
-
encodeLiteral(probs: Probs, offset: number, symbol: number): void;
|
|
39
|
-
/**
|
|
40
|
-
* Encodes a literal after a match. The bits of `matchByte` (the byte at
|
|
41
|
-
* rep0) select separate probabilities until the first bit that differs.
|
|
42
|
-
*/
|
|
43
|
-
encodeMatchedLiteral(probs: Probs, offset: number, symbolIn: number, matchByteIn: number): void;
|
|
44
|
-
/** Encodes the `count` low bits of `value` with a fixed 50% probability. */
|
|
45
49
|
encodeDirectBits(value: number, countIn: number): void;
|
|
46
|
-
/**
|
|
47
|
-
* Moves the top byte of `low` to the output and returns the new `low`.
|
|
48
|
-
* A run of 0xFF bytes is held back (`cache` + `cacheSize`) until it is
|
|
49
|
-
* known whether a carry will propagate into it.
|
|
50
|
-
*/
|
|
51
|
-
private shiftLow;
|
|
52
50
|
private ensureCapacity;
|
|
53
51
|
}
|