lzma1 0.2.0 → 0.3.0
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 +10 -3
- package/lib/decoder.js +84 -85
- package/lib/encoder.js +794 -143
- package/lib/index.js +0 -1
- package/lib/lz-window.js +3 -4
- package/lib/lzma.js +50 -1383
- package/lib/match-finder.js +402 -0
- package/lib/range-decoder.js +3 -16
- package/lib/range-encoder.js +14 -24
- package/lib/streams.js +64 -1
- package/lib/utils.js +4 -102
- package/package.json +24 -13
- package/src/decoder.ts +604 -0
- package/src/encoder.ts +2108 -0
- package/src/index.ts +71 -0
- package/src/len-coder.ts +217 -0
- package/src/lit-coder.ts +196 -0
- package/src/lz-window.ts +99 -0
- package/src/lzma.ts +142 -0
- package/src/match-finder.ts +548 -0
- package/src/range-bit-tree-coder.ts +109 -0
- package/src/range-decoder.ts +98 -0
- package/src/range-encoder.ts +136 -0
- package/src/streams.ts +73 -0
- package/src/utils.ts +263 -0
- package/lib/chunker.d.ts +0 -46
- package/lib/chunker.js +0 -68
- package/lib/decoder.d.ts +0 -80
- package/lib/encoder.d.ts +0 -266
- package/lib/index.d.ts +0 -38
- package/lib/len-coder.d.ts +0 -70
- package/lib/lit-coder.d.ts +0 -63
- package/lib/lz-in-window.d.ts +0 -43
- package/lib/lz-in-window.js +0 -132
- package/lib/lz-window.d.ts +0 -35
- package/lib/lzma.d.ts +0 -107
- package/lib/match-finder-config.d.ts +0 -34
- package/lib/match-finder-config.js +0 -63
- package/lib/range-bit-tree-coder.d.ts +0 -34
- package/lib/range-decoder.d.ts +0 -34
- package/lib/range-encoder.d.ts +0 -46
- package/lib/streams.d.ts +0 -32
- package/lib/utils.d.ts +0 -127
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { InputBuffer } from "./streams.js";
|
|
2
|
+
|
|
3
|
+
export class RangeDecoder {
|
|
4
|
+
public stream: InputBuffer | null = null;
|
|
5
|
+
public code: number = 0;
|
|
6
|
+
public rrange: number = 0;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Set input stream for decoding
|
|
10
|
+
*/
|
|
11
|
+
setStream(stream: InputBuffer | null): void {
|
|
12
|
+
this.stream = stream;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Initialize range decoder
|
|
17
|
+
*/
|
|
18
|
+
init(): void {
|
|
19
|
+
this.code = 0;
|
|
20
|
+
this.rrange = -1;
|
|
21
|
+
|
|
22
|
+
for (let i = 0; i < 5; ++i) {
|
|
23
|
+
this.code = this.code << 8 | this.readFromStream();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Decode a single bit using probability model
|
|
29
|
+
*/
|
|
30
|
+
decodeBit(probs: number[], index: number): 0 | 1 {
|
|
31
|
+
let newBound, prob = probs[index];
|
|
32
|
+
newBound = (this.rrange >>> 11) * prob;
|
|
33
|
+
|
|
34
|
+
if ((this.code ^ -0x80000000) < (newBound ^ -0x80000000)) {
|
|
35
|
+
this.rrange = newBound;
|
|
36
|
+
probs[index] = prob + ((2048 - prob) >>> 5);
|
|
37
|
+
if (!(this.rrange & -0x1000000)) {
|
|
38
|
+
this.code = this.code << 8 | this.readFromStream();
|
|
39
|
+
this.rrange <<= 8;
|
|
40
|
+
}
|
|
41
|
+
return 0;
|
|
42
|
+
} else {
|
|
43
|
+
this.rrange -= newBound;
|
|
44
|
+
this.code -= newBound;
|
|
45
|
+
probs[index] = prob - (prob >>> 5);
|
|
46
|
+
if (!(this.rrange & -0x1000000)) {
|
|
47
|
+
this.code = this.code << 8 | this.readFromStream();
|
|
48
|
+
this.rrange <<= 8;
|
|
49
|
+
}
|
|
50
|
+
return 1;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Decode direct bits (without probability model)
|
|
56
|
+
*/
|
|
57
|
+
decodeDirectBits(numTotalBits: number): number {
|
|
58
|
+
let result = 0;
|
|
59
|
+
|
|
60
|
+
for (let i = numTotalBits; i != 0; i -= 1) {
|
|
61
|
+
this.rrange >>>= 1;
|
|
62
|
+
let t = (this.code - this.rrange) >>> 31;
|
|
63
|
+
this.code -= this.rrange & (t - 1);
|
|
64
|
+
result = result << 1 | 1 - t;
|
|
65
|
+
|
|
66
|
+
if (!(this.rrange & -0x1000000)) {
|
|
67
|
+
this.code = this.code << 8 | this.readFromStream();
|
|
68
|
+
this.rrange <<= 8;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get current code value (for compatibility)
|
|
77
|
+
*/
|
|
78
|
+
get currentCode(): number {
|
|
79
|
+
return this.code;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Get current range value (for compatibility)
|
|
84
|
+
*/
|
|
85
|
+
get currentRange(): number {
|
|
86
|
+
return this.rrange;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Read a single byte from the input stream
|
|
91
|
+
*/
|
|
92
|
+
private readFromStream(): number {
|
|
93
|
+
if (!this.stream) {
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
return this.stream.readByte();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { OutputBuffer } from "./streams.js";
|
|
2
|
+
|
|
3
|
+
export class RangeEncoder {
|
|
4
|
+
private stream: OutputBuffer | null = null;
|
|
5
|
+
private low: bigint = 0n;
|
|
6
|
+
private rrange: number = 0;
|
|
7
|
+
private cache: number = 0;
|
|
8
|
+
private cacheSize: number = 0;
|
|
9
|
+
private position: bigint = 0n;
|
|
10
|
+
|
|
11
|
+
constructor() {
|
|
12
|
+
// Initialize with default values
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Set output stream for encoding
|
|
17
|
+
*/
|
|
18
|
+
setStream(stream: OutputBuffer | null): void {
|
|
19
|
+
this.stream = stream;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Initialize range encoder
|
|
24
|
+
*/
|
|
25
|
+
init(): void {
|
|
26
|
+
this.position = 0n;
|
|
27
|
+
this.low = 0n;
|
|
28
|
+
this.rrange = -1;
|
|
29
|
+
this.cacheSize = 1;
|
|
30
|
+
this.cache = 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Encode a single bit using probability model
|
|
35
|
+
*/
|
|
36
|
+
encodeBit(probs: number[], index: number, bit: number): void {
|
|
37
|
+
const prob = probs[index];
|
|
38
|
+
const newBound = (this.rrange >>> 11) * prob;
|
|
39
|
+
|
|
40
|
+
if (bit === 0) {
|
|
41
|
+
this.rrange = newBound;
|
|
42
|
+
probs[index] = prob + ((2048 - prob) >>> 5);
|
|
43
|
+
} else {
|
|
44
|
+
this.low += BigInt(newBound);
|
|
45
|
+
this.rrange -= newBound;
|
|
46
|
+
probs[index] = prob - (prob >>> 5);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!(this.rrange & -0x1000000)) {
|
|
50
|
+
this.rrange <<= 8;
|
|
51
|
+
this.shiftLow();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Encode direct bits (without probability model)
|
|
57
|
+
*/
|
|
58
|
+
encodeDirectBits(value: number, numTotalBits: number): void {
|
|
59
|
+
for (let i = numTotalBits - 1; i >= 0; i--) {
|
|
60
|
+
this.rrange >>>= 1;
|
|
61
|
+
if (((value >>> i) & 1) === 1) {
|
|
62
|
+
this.low += BigInt(this.rrange);
|
|
63
|
+
}
|
|
64
|
+
if (!(this.rrange & -0x1000000)) {
|
|
65
|
+
this.rrange <<= 8;
|
|
66
|
+
this.shiftLow();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Encode bit tree symbol
|
|
73
|
+
*/
|
|
74
|
+
encodeBitTree(numBitLevels: number, models: number[], symbol: number, startIndex: number = 1): void {
|
|
75
|
+
let m = 1;
|
|
76
|
+
for (let bitIndex = numBitLevels; bitIndex !== 0; bitIndex--) {
|
|
77
|
+
const bit = (symbol >>> (bitIndex - 1)) & 1;
|
|
78
|
+
this.encodeBit(models, startIndex + m - 1, bit);
|
|
79
|
+
m = (m << 1) | bit;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Reverse encode bits
|
|
85
|
+
*/
|
|
86
|
+
reverseEncodeBits(numBitLevels: number, models: number[], symbol: number, startIndex: number): void {
|
|
87
|
+
let m = 1;
|
|
88
|
+
for (let i = 0; i < numBitLevels; i++) {
|
|
89
|
+
const bit = symbol & 1;
|
|
90
|
+
this.encodeBit(models, startIndex + m, bit);
|
|
91
|
+
m = (m << 1) | bit;
|
|
92
|
+
symbol >>>= 1;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Finish encoding and flush remaining data
|
|
98
|
+
*/
|
|
99
|
+
finish(): void {
|
|
100
|
+
for (let i = 0; i < 5; i++) {
|
|
101
|
+
this.shiftLow();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Shift low value and write to stream
|
|
107
|
+
*/
|
|
108
|
+
private shiftLow(): void {
|
|
109
|
+
const lowHi = Number((this.low >> 32n) & 0xFFFFFFFFn);
|
|
110
|
+
|
|
111
|
+
if (lowHi !== 0 || Number(this.low & 0xFFFFFFFFn) < 0xFF000000) {
|
|
112
|
+
this.position += BigInt(this.cacheSize);
|
|
113
|
+
|
|
114
|
+
let temp = this.cache;
|
|
115
|
+
do {
|
|
116
|
+
this.writeToStream(temp + lowHi);
|
|
117
|
+
temp = 255;
|
|
118
|
+
} while (--this.cacheSize !== 0);
|
|
119
|
+
|
|
120
|
+
this.cache = (Number(this.low & 0xFFFFFFFFn) >>> 24) & 0xFF;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
this.cacheSize++;
|
|
124
|
+
this.low = BigInt(Number(this.low & 0xFFFFFFFFn) & 0xFFFFFF) << 8n;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Write byte to output stream
|
|
129
|
+
*/
|
|
130
|
+
private writeToStream(value: number): void {
|
|
131
|
+
if (!this.stream) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
this.stream.writeByte(value & 0xFF);
|
|
135
|
+
}
|
|
136
|
+
}
|
package/src/streams.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only input buffer wrapping a Uint8Array.
|
|
3
|
+
*/
|
|
4
|
+
export class InputBuffer {
|
|
5
|
+
buf: Uint8Array;
|
|
6
|
+
pos: number = 0;
|
|
7
|
+
count: number;
|
|
8
|
+
|
|
9
|
+
constructor(data: Uint8Array) {
|
|
10
|
+
this.buf = data;
|
|
11
|
+
this.count = data.length;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
readByte(): number {
|
|
15
|
+
if (this.pos >= this.count) return -1;
|
|
16
|
+
return this.buf[this.pos++] & 0xFF;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
readBytes(dest: Uint8Array, off: number, len: number): number {
|
|
20
|
+
if (this.pos >= this.count) return -1;
|
|
21
|
+
len = Math.min(len, this.count - this.pos);
|
|
22
|
+
dest.set(this.buf.subarray(this.pos, this.pos + len), off);
|
|
23
|
+
this.pos += len;
|
|
24
|
+
return len;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get remaining(): number {
|
|
28
|
+
return this.count - this.pos;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Growable output buffer backed by a Uint8Array.
|
|
34
|
+
*/
|
|
35
|
+
export class OutputBuffer {
|
|
36
|
+
buf: Uint8Array;
|
|
37
|
+
count: number = 0;
|
|
38
|
+
|
|
39
|
+
constructor(capacity: number = 32) {
|
|
40
|
+
this.buf = new Uint8Array(capacity);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private grow(requiredSize: number): void {
|
|
44
|
+
const newSize = Math.max(this.buf.length * 2, requiredSize);
|
|
45
|
+
const newBuf = new Uint8Array(newSize);
|
|
46
|
+
newBuf.set(this.buf.subarray(0, this.count));
|
|
47
|
+
this.buf = newBuf;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
writeByte(b: number): void {
|
|
51
|
+
if (this.count >= this.buf.length) {
|
|
52
|
+
this.grow(this.count + 1);
|
|
53
|
+
}
|
|
54
|
+
this.buf[this.count++] = b;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
writeBytes(src: Uint8Array, off: number, len: number): void {
|
|
58
|
+
const requiredSize = this.count + len;
|
|
59
|
+
if (requiredSize > this.buf.length) {
|
|
60
|
+
this.grow(requiredSize);
|
|
61
|
+
}
|
|
62
|
+
this.buf.set(src.subarray(off, off + len), this.count);
|
|
63
|
+
this.count += len;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
write(buf: Uint8Array): void {
|
|
67
|
+
this.writeBytes(buf, 0, buf.length);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
toArray(): Uint8Array {
|
|
71
|
+
return this.buf.slice(0, this.count);
|
|
72
|
+
}
|
|
73
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
export interface BitTree {
|
|
2
|
+
numBitLevels: number;
|
|
3
|
+
models: number[];
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Literal decoder/encoder for optimization
|
|
8
|
+
*/
|
|
9
|
+
export interface LiteralDecoderEncoder2 {
|
|
10
|
+
decoders: number[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Basic range encoder interface for bit operations
|
|
15
|
+
*/
|
|
16
|
+
export interface BasicRangeEncoder {
|
|
17
|
+
encodeBit(probs: number[], index: number, bit: number): void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Basic range decoder interface for bit operations
|
|
22
|
+
*/
|
|
23
|
+
export interface BasicRangeDecoder {
|
|
24
|
+
decodeBit(probs: number[], index: number): number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Additional LZMA constants
|
|
28
|
+
export const INFINITY_PRICE = 0xFFFFFFF;
|
|
29
|
+
export const _MAX_UINT32 = 0xFFFFFFFF;
|
|
30
|
+
export const DICTIONARY_SIZE_THRESHOLD = 0x3FFFFFFF;
|
|
31
|
+
|
|
32
|
+
// Range coder constants
|
|
33
|
+
export const kTopValue = 1 << 24;
|
|
34
|
+
export const kNumBitModelTotalBits = 11;
|
|
35
|
+
export const kBitModelTotal = 1 << kNumBitModelTotalBits;
|
|
36
|
+
export const kNumMoveBits = 5;
|
|
37
|
+
export const kNumMoveReducingBits = 2;
|
|
38
|
+
export const kNumBitPriceShiftBits = 6;
|
|
39
|
+
|
|
40
|
+
// Common array sizes used throughout LZMA implementation
|
|
41
|
+
export const MATCH_DECODERS_SIZE = 0xC0; // 192
|
|
42
|
+
export const REP_DECODERS_SIZE = 12;
|
|
43
|
+
export const POS_DECODERS_SIZE = 114;
|
|
44
|
+
export const LITERAL_DECODER_SIZE = 0x300; // 768
|
|
45
|
+
export const DEFAULT_WINDOW_SIZE = 0x1000; // 4096
|
|
46
|
+
export const CHOICE_ARRAY_SIZE = 2;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* CRC32 lookup table for hash calculations
|
|
50
|
+
* dprint-ignore
|
|
51
|
+
*/
|
|
52
|
+
export const CRC32_TABLE = [
|
|
53
|
+
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
|
|
54
|
+
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
|
|
55
|
+
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
|
|
56
|
+
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
|
57
|
+
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
|
|
58
|
+
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
|
|
59
|
+
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
|
|
60
|
+
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
|
61
|
+
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
|
|
62
|
+
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
|
|
63
|
+
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
|
|
64
|
+
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
|
65
|
+
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
|
|
66
|
+
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
|
|
67
|
+
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
|
|
68
|
+
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
|
69
|
+
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
|
|
70
|
+
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
|
|
71
|
+
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
|
|
72
|
+
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
|
73
|
+
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
|
|
74
|
+
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
|
|
75
|
+
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
|
|
76
|
+
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
|
77
|
+
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
|
|
78
|
+
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
|
|
79
|
+
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
|
|
80
|
+
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
|
81
|
+
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
|
|
82
|
+
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
|
|
83
|
+
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
|
|
84
|
+
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
|
85
|
+
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
|
|
86
|
+
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
|
|
87
|
+
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
|
|
88
|
+
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
|
89
|
+
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
|
|
90
|
+
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
|
|
91
|
+
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
|
|
92
|
+
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
|
93
|
+
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
|
|
94
|
+
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
|
|
95
|
+
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Pre-computed static instances for common use
|
|
100
|
+
*/
|
|
101
|
+
export const PROB_PRICES: number[] = createProbPrices();
|
|
102
|
+
export const G_FAST_POS: number[] = createFastPos();
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Initialize array with specified length and default value
|
|
106
|
+
* This is MUCH faster than "new Array(len)" in newer versions of v8
|
|
107
|
+
* (starting with Node.js 0.11.15, which uses v8 3.28.73).
|
|
108
|
+
*/
|
|
109
|
+
export function initArray(len: number, value = 0): number[] {
|
|
110
|
+
const array = [];
|
|
111
|
+
|
|
112
|
+
// Pre-allocate array by setting the last index
|
|
113
|
+
array[len - 1] = undefined;
|
|
114
|
+
|
|
115
|
+
// Fill with specified value if needed
|
|
116
|
+
if (value !== 0) {
|
|
117
|
+
for (let i = 0; i < len; i++) {
|
|
118
|
+
array[i] = value;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return array as unknown as number[];
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Copy array data with bounds checking and overlap handling
|
|
127
|
+
*/
|
|
128
|
+
export function arraycopy(
|
|
129
|
+
src: number[],
|
|
130
|
+
srcOfs: number,
|
|
131
|
+
dest: number[],
|
|
132
|
+
destOfs: number,
|
|
133
|
+
len: number,
|
|
134
|
+
): void {
|
|
135
|
+
// Bounds checking
|
|
136
|
+
if (
|
|
137
|
+
srcOfs < 0
|
|
138
|
+
|| destOfs < 0
|
|
139
|
+
|| len < 0
|
|
140
|
+
|| srcOfs + len > src.length
|
|
141
|
+
|| destOfs + len > dest.length
|
|
142
|
+
) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (
|
|
147
|
+
src === dest
|
|
148
|
+
&& srcOfs < destOfs
|
|
149
|
+
&& destOfs < srcOfs + len
|
|
150
|
+
) {
|
|
151
|
+
// Overlapping regions - copy backwards
|
|
152
|
+
for (let i = len - 1; i >= 0; i--) {
|
|
153
|
+
dest[destOfs + i] = src[srcOfs + i];
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
// Non-overlapping or safe regions - copy forward
|
|
157
|
+
for (let i = 0; i < len; i++) {
|
|
158
|
+
dest[destOfs + i] = src[srcOfs + i];
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get bit price using pre-computed probability prices
|
|
165
|
+
*/
|
|
166
|
+
export function getBitPrice(probability: number, bit: number): number {
|
|
167
|
+
return PROB_PRICES[((probability - bit ^ -bit) & 2047) >>> 2];
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Bit model operations
|
|
172
|
+
*/
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Initialize bit models with default probability
|
|
176
|
+
*/
|
|
177
|
+
export function initBitModels(probs: number[]): void {
|
|
178
|
+
for (let i = probs.length - 1; i >= 0; --i) {
|
|
179
|
+
probs[i] = 1024;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Position and state operations
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Get length to position state mapping
|
|
189
|
+
*/
|
|
190
|
+
export function getLenToPosState(len: number): number {
|
|
191
|
+
len -= 2;
|
|
192
|
+
if (len < 4) {
|
|
193
|
+
return len;
|
|
194
|
+
}
|
|
195
|
+
return 3;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Update state after character encoding/decoding
|
|
200
|
+
*/
|
|
201
|
+
const STATE_UPDATE_CHAR_TABLE = [0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5];
|
|
202
|
+
|
|
203
|
+
export function stateUpdateChar(index: number): number {
|
|
204
|
+
if (index >= 0 && index < STATE_UPDATE_CHAR_TABLE.length) {
|
|
205
|
+
return STATE_UPDATE_CHAR_TABLE[index];
|
|
206
|
+
}
|
|
207
|
+
if (index < 4) {
|
|
208
|
+
return 0;
|
|
209
|
+
}
|
|
210
|
+
if (index < 10) {
|
|
211
|
+
return index - 3;
|
|
212
|
+
}
|
|
213
|
+
return index - 6;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Bit tree operations
|
|
218
|
+
*/
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Create a bit tree with specified number of bit levels
|
|
222
|
+
*/
|
|
223
|
+
export function createBitTree(numBitLevels: number): BitTree {
|
|
224
|
+
return {
|
|
225
|
+
numBitLevels: numBitLevels,
|
|
226
|
+
models: initArray(1 << numBitLevels),
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Create probability prices lookup table
|
|
232
|
+
*/
|
|
233
|
+
export function createProbPrices(): number[] {
|
|
234
|
+
const probPrices = [];
|
|
235
|
+
for (let i = 8; i >= 0; --i) {
|
|
236
|
+
let start = 1 << (9 - i - 1);
|
|
237
|
+
let end = 1 << (9 - i);
|
|
238
|
+
|
|
239
|
+
for (let j = start; j < end; ++j) {
|
|
240
|
+
probPrices[j] = (i << 6) + ((end - j) << 6 >>> (9 - i - 1));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return probPrices;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Create fast position lookup table
|
|
249
|
+
*/
|
|
250
|
+
export function createFastPos(): number[] {
|
|
251
|
+
const gFastPos = [0, 1];
|
|
252
|
+
let c = 2;
|
|
253
|
+
|
|
254
|
+
for (let slotFast = 2; slotFast < 22; ++slotFast) {
|
|
255
|
+
let k = 1 << ((slotFast >> 1) - 1);
|
|
256
|
+
|
|
257
|
+
for (let j = 0; j < k; ++j, ++c) {
|
|
258
|
+
gFastPos[c] = slotFast;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return gFastPos;
|
|
263
|
+
}
|
package/lib/chunker.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { Decoder } from "./decoder.js";
|
|
2
|
-
import { Encoder } from "./encoder.js";
|
|
3
|
-
/**
|
|
4
|
-
* Base chunker interface for both encoding and decoding operations
|
|
5
|
-
*/
|
|
6
|
-
interface BaseChunker {
|
|
7
|
-
alive: number;
|
|
8
|
-
inBytesProcessed: [number, number];
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Interface for LZMA instance needed by EncoderChunker
|
|
12
|
-
*/
|
|
13
|
-
interface LZMAInstance {
|
|
14
|
-
codeOneBlock(): void;
|
|
15
|
-
releaseStreams(): void;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Encoder chunker for handling compression chunk processing
|
|
19
|
-
*/
|
|
20
|
-
export declare class EncoderChunker implements BaseChunker {
|
|
21
|
-
encoder: Encoder | null;
|
|
22
|
-
decoder: null;
|
|
23
|
-
alive: number;
|
|
24
|
-
inBytesProcessed: [number, number];
|
|
25
|
-
private lzma;
|
|
26
|
-
constructor(lzma: LZMAInstance);
|
|
27
|
-
/**
|
|
28
|
-
* Process one chunk of encoding
|
|
29
|
-
*/
|
|
30
|
-
processChunk(): number;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Decoder chunker for handling decompression chunk processing
|
|
34
|
-
*/
|
|
35
|
-
export declare class DecoderChunker implements BaseChunker {
|
|
36
|
-
encoder: null;
|
|
37
|
-
decoder: Decoder;
|
|
38
|
-
alive: number;
|
|
39
|
-
inBytesProcessed: [number, number];
|
|
40
|
-
constructor(decoder: Decoder);
|
|
41
|
-
/**
|
|
42
|
-
* Process one chunk of decoding
|
|
43
|
-
*/
|
|
44
|
-
processChunk(): number;
|
|
45
|
-
}
|
|
46
|
-
export {};
|
package/lib/chunker.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { compare64, P0_LONG_LIT, } from "./utils.js";
|
|
2
|
-
/**
|
|
3
|
-
* Encoder chunker for handling compression chunk processing
|
|
4
|
-
*/
|
|
5
|
-
export class EncoderChunker {
|
|
6
|
-
encoder = null;
|
|
7
|
-
decoder = null;
|
|
8
|
-
alive = 0;
|
|
9
|
-
inBytesProcessed = [0, 0];
|
|
10
|
-
lzma;
|
|
11
|
-
constructor(lzma) {
|
|
12
|
-
this.lzma = lzma;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Process one chunk of encoding
|
|
16
|
-
*/
|
|
17
|
-
processChunk() {
|
|
18
|
-
if (!this.alive) {
|
|
19
|
-
throw new Error("bad state");
|
|
20
|
-
}
|
|
21
|
-
if (!this.encoder) {
|
|
22
|
-
throw new Error("No decoding");
|
|
23
|
-
}
|
|
24
|
-
this.lzma.codeOneBlock();
|
|
25
|
-
this.inBytesProcessed = this.encoder.processedInSize[0];
|
|
26
|
-
if (this.encoder.finished[0]) {
|
|
27
|
-
this.lzma.releaseStreams();
|
|
28
|
-
this.alive = 0;
|
|
29
|
-
}
|
|
30
|
-
return this.alive;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Decoder chunker for handling decompression chunk processing
|
|
35
|
-
*/
|
|
36
|
-
export class DecoderChunker {
|
|
37
|
-
encoder = null;
|
|
38
|
-
decoder;
|
|
39
|
-
alive = 0;
|
|
40
|
-
inBytesProcessed = [0, 0];
|
|
41
|
-
constructor(decoder) {
|
|
42
|
-
this.decoder = decoder;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Process one chunk of decoding
|
|
46
|
-
*/
|
|
47
|
-
processChunk() {
|
|
48
|
-
if (!this.alive) {
|
|
49
|
-
throw new Error("Bad state");
|
|
50
|
-
}
|
|
51
|
-
if (this.encoder) {
|
|
52
|
-
throw new Error("No encoding");
|
|
53
|
-
}
|
|
54
|
-
const result = this.decoder.codeOneChunk();
|
|
55
|
-
if (result === -1) {
|
|
56
|
-
throw new Error("Corrupted input");
|
|
57
|
-
}
|
|
58
|
-
this.inBytesProcessed = this.decoder.nowPos64;
|
|
59
|
-
const isOutputComplete = (compare64(this.decoder.outSize, P0_LONG_LIT) >= 0)
|
|
60
|
-
&& (compare64(this.decoder.nowPos64, this.decoder.outSize) >= 0);
|
|
61
|
-
if (result || isOutputComplete) {
|
|
62
|
-
this.decoder.flush();
|
|
63
|
-
this.decoder.cleanup();
|
|
64
|
-
this.alive = 0;
|
|
65
|
-
}
|
|
66
|
-
return this.alive;
|
|
67
|
-
}
|
|
68
|
-
}
|