lzma1 0.1.2 → 0.2.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/lib/index.d.ts CHANGED
@@ -3,8 +3,9 @@
3
3
  * Copyright Filip Seman
4
4
  * SPDX-License-Identifier: MIT
5
5
  */
6
- import { LZMA } from "./lzma.js";
6
+ import { type CompressionMode } from "./lzma.js";
7
7
  export { LZMA } from "./lzma.js";
8
+ export { CRC32_TABLE } from "./utils.js";
8
9
  /**
9
10
  * Compresses data using LZMA algorithm
10
11
  *
@@ -12,7 +13,7 @@ export { LZMA } from "./lzma.js";
12
13
  * @param mode Compression mode (1-9), defaults to 5
13
14
  * @returns Compressed data as a byte array
14
15
  */
15
- export declare function compress(data: Uint8Array | ArrayBuffer, mode?: keyof LZMA["CompressionModes"]): Uint8Array;
16
+ export declare function compress(data: Uint8Array | ArrayBuffer, mode?: CompressionMode): Uint8Array;
16
17
  /**
17
18
  * Compresses data using LZMA algorithm
18
19
  *
@@ -20,7 +21,7 @@ export declare function compress(data: Uint8Array | ArrayBuffer, mode?: keyof LZ
20
21
  * @param mode Compression mode (1-9), defaults to 5
21
22
  * @returns Compressed data as byte array
22
23
  */
23
- export declare function compressString(data: string, mode?: keyof LZMA["CompressionModes"]): Uint8Array;
24
+ export declare function compressString(data: string, mode?: CompressionMode): Uint8Array;
24
25
  /**
25
26
  * Decompresses LZMA compressed data
26
27
  *
package/lib/index.js CHANGED
@@ -3,8 +3,9 @@
3
3
  * Copyright Filip Seman
4
4
  * SPDX-License-Identifier: MIT
5
5
  */
6
- import { LZMA } from "./lzma.js";
6
+ import { LZMA, } from "./lzma.js";
7
7
  export { LZMA } from "./lzma.js";
8
+ export { CRC32_TABLE } from "./utils.js";
8
9
  /**
9
10
  * Compresses data using LZMA algorithm
10
11
  *
@@ -13,8 +14,12 @@ export { LZMA } from "./lzma.js";
13
14
  * @returns Compressed data as a byte array
14
15
  */
15
16
  export function compress(data, mode = 5) {
16
- const lzma = new LZMA();
17
- return new Uint8Array(lzma.compress(data, mode));
17
+ // Convert ArrayBuffer to Uint8Array if needed
18
+ const input = data instanceof ArrayBuffer
19
+ ? new Uint8Array(data)
20
+ : data;
21
+ const result = new LZMA().compress(input, mode);
22
+ return new Uint8Array(result);
18
23
  }
19
24
  /**
20
25
  * Compresses data using LZMA algorithm
@@ -24,8 +29,8 @@ export function compress(data, mode = 5) {
24
29
  * @returns Compressed data as byte array
25
30
  */
26
31
  export function compressString(data, mode = 5) {
27
- const lzma = new LZMA();
28
- return new Uint8Array(lzma.compressString(data, mode));
32
+ const compressedData = new LZMA().compressString(data, mode);
33
+ return new Uint8Array(compressedData);
29
34
  }
30
35
  /**
31
36
  * Decompresses LZMA compressed data
@@ -34,8 +39,11 @@ export function compressString(data, mode = 5) {
34
39
  * @returns Decompressed data
35
40
  */
36
41
  export function decompress(data) {
37
- const lzma = new LZMA();
38
- return new Uint8Array(lzma.decompress(data));
42
+ const input = data instanceof ArrayBuffer
43
+ ? new Uint8Array(data)
44
+ : data;
45
+ const decompressedData = new LZMA().decompress(input);
46
+ return new Uint8Array(decompressedData);
39
47
  }
40
48
  /**
41
49
  * Decompresses LZMA compressed data
@@ -44,6 +52,5 @@ export function decompress(data) {
44
52
  * @returns Decompressed data as string
45
53
  */
46
54
  export function decompressString(data) {
47
- const lzma = new LZMA();
48
- return lzma.decompressString(data);
55
+ return new LZMA().decompressString(data);
49
56
  }
@@ -0,0 +1,70 @@
1
+ import { type BitTree } from "./utils.js";
2
+ /**
3
+ * Range encoder interface for LenEncoder to communicate with
4
+ */
5
+ export interface RangeEncoder {
6
+ encodeBit(probs: number[], index: number, symbol: number): void;
7
+ encodeBitTree(encoder: BitTree, symbol: number): void;
8
+ }
9
+ /**
10
+ * Length encoder class for LZMA compression
11
+ * Handles encoding of match lengths with price optimization
12
+ */
13
+ export declare class LenEncoder {
14
+ private choice;
15
+ private lowCoder;
16
+ private midCoder;
17
+ private highCoder;
18
+ private tableSize;
19
+ private prices;
20
+ private counters;
21
+ constructor();
22
+ /**
23
+ * Initialize the encoder with specified number of position states
24
+ */
25
+ init(numPosStates: number): void;
26
+ /**
27
+ * Encode a length value using the provided range encoder
28
+ */
29
+ encode(symbol: number, posState: number, rangeEncoder: RangeEncoder): void;
30
+ /**
31
+ * Encode with price table update
32
+ */
33
+ encodeWithUpdate(symbol: number, posState: number, rangeEncoder: RangeEncoder): void;
34
+ /**
35
+ * Get price for encoding a symbol at the given position state
36
+ */
37
+ getPrice(symbol: number, posState: number): number;
38
+ /**
39
+ * Initialize as a price table encoder
40
+ */
41
+ initPriceTable(): void;
42
+ /**
43
+ * Set table size for price optimization
44
+ */
45
+ setTableSize(size: number): void;
46
+ /**
47
+ * Set table size and update internal counters
48
+ */
49
+ setTableSizeAndInitCounters(size: number, numPosStates: number): void;
50
+ /**
51
+ * Get table size
52
+ */
53
+ getTableSize(): number;
54
+ /**
55
+ * Update price tables for all position states
56
+ */
57
+ updateTables(numPosStates: number): void;
58
+ /**
59
+ * Calculate price for bit tree encoder
60
+ */
61
+ private getBitTreePrice;
62
+ /**
63
+ * Get price for a single bit
64
+ */
65
+ private getBitPrice;
66
+ /**
67
+ * Set prices for all symbols in a position state range
68
+ */
69
+ private setPrices;
70
+ }
@@ -0,0 +1,171 @@
1
+ import { createBitTree, getBitPrice, initArray, initBitModels, } from "./utils.js";
2
+ /**
3
+ * Length encoder class for LZMA compression
4
+ * Handles encoding of match lengths with price optimization
5
+ */
6
+ export class LenEncoder {
7
+ // Choice probability arrays for length range selection
8
+ choice = initArray(2);
9
+ // Low range coders (for lengths 2-9)
10
+ lowCoder = [];
11
+ // Mid range coders (for lengths 10-17)
12
+ midCoder = [];
13
+ // High range coder (for lengths 18+)
14
+ highCoder = createBitTree(8);
15
+ // Price optimization properties
16
+ tableSize = 0;
17
+ prices = [];
18
+ counters = [];
19
+ constructor() {
20
+ // Initialize low and mid coders for all position states (up to 16)
21
+ for (let posState = 0; posState < 16; ++posState) {
22
+ this.lowCoder[posState] = createBitTree(3);
23
+ this.midCoder[posState] = createBitTree(3);
24
+ }
25
+ }
26
+ /**
27
+ * Initialize the encoder with specified number of position states
28
+ */
29
+ init(numPosStates) {
30
+ // Initialize choice probability models
31
+ initBitModels(this.choice);
32
+ // Initialize low and mid coders for each position state
33
+ for (let posState = 0; posState < numPosStates; ++posState) {
34
+ initBitModels(this.lowCoder[posState].models);
35
+ initBitModels(this.midCoder[posState].models);
36
+ }
37
+ // Initialize high coder
38
+ initBitModels(this.highCoder.models);
39
+ }
40
+ /**
41
+ * Encode a length value using the provided range encoder
42
+ */
43
+ encode(symbol, posState, rangeEncoder) {
44
+ if (symbol < 8) {
45
+ // Length 2-9: use low coder
46
+ rangeEncoder.encodeBit(this.choice, 0, 0);
47
+ rangeEncoder.encodeBitTree(this.lowCoder[posState], symbol);
48
+ }
49
+ else {
50
+ symbol -= 8;
51
+ rangeEncoder.encodeBit(this.choice, 0, 1);
52
+ if (symbol < 8) {
53
+ // Length 10-17: use mid coder
54
+ rangeEncoder.encodeBit(this.choice, 1, 0);
55
+ rangeEncoder.encodeBitTree(this.midCoder[posState], symbol);
56
+ }
57
+ else {
58
+ // Length 18+: use high coder
59
+ rangeEncoder.encodeBit(this.choice, 1, 1);
60
+ rangeEncoder.encodeBitTree(this.highCoder, symbol - 8);
61
+ }
62
+ }
63
+ }
64
+ /**
65
+ * Encode with price table update
66
+ */
67
+ encodeWithUpdate(symbol, posState, rangeEncoder) {
68
+ this.encode(symbol, posState, rangeEncoder);
69
+ if (this.counters && (this.counters[posState] -= 1) == 0) {
70
+ // Reset counter and update prices if needed
71
+ this.counters[posState] = this.tableSize;
72
+ }
73
+ }
74
+ /**
75
+ * Get price for encoding a symbol at the given position state
76
+ */
77
+ getPrice(symbol, posState) {
78
+ return this.prices[posState * 0x110 + symbol];
79
+ }
80
+ /**
81
+ * Initialize as a price table encoder
82
+ */
83
+ initPriceTable() {
84
+ this.prices = [];
85
+ this.counters = [];
86
+ }
87
+ /**
88
+ * Set table size for price optimization
89
+ */
90
+ setTableSize(size) {
91
+ this.tableSize = size;
92
+ }
93
+ /**
94
+ * Set table size and update internal counters
95
+ */
96
+ setTableSizeAndInitCounters(size, numPosStates) {
97
+ this.tableSize = size;
98
+ if (this.counters) {
99
+ for (let posState = 0; posState < numPosStates; ++posState) {
100
+ this.counters[posState] = size;
101
+ }
102
+ }
103
+ }
104
+ /**
105
+ * Get table size
106
+ */
107
+ getTableSize() {
108
+ return this.tableSize;
109
+ }
110
+ /**
111
+ * Update price tables for all position states
112
+ */
113
+ updateTables(numPosStates) {
114
+ if (!this.prices || !this.counters) {
115
+ this.initPriceTable();
116
+ }
117
+ for (let posState = 0; posState < numPosStates; ++posState) {
118
+ this.setPrices(posState, this.tableSize, this.prices, 0);
119
+ if (this.counters) {
120
+ this.counters[posState] = this.tableSize;
121
+ }
122
+ }
123
+ }
124
+ // Private methods for internal state management
125
+ /**
126
+ * Calculate price for bit tree encoder
127
+ */
128
+ getBitTreePrice(encoder, symbol) {
129
+ let bit, bitIndex, m = 1, price = 0;
130
+ for (bitIndex = encoder.numBitLevels; bitIndex != 0;) {
131
+ bitIndex -= 1;
132
+ bit = symbol >>> bitIndex & 1;
133
+ price += this.getBitPrice(encoder.models[m], bit);
134
+ m = (m << 1) + bit;
135
+ }
136
+ return price;
137
+ }
138
+ /**
139
+ * Get price for a single bit
140
+ */
141
+ getBitPrice(prob, symbol) {
142
+ return getBitPrice(prob, symbol);
143
+ }
144
+ /**
145
+ * Set prices for all symbols in a position state range
146
+ */
147
+ setPrices(posState, numSymbols, prices, priceIndex) {
148
+ const a0 = this.getBitPrice(this.choice[0], 0);
149
+ const a1 = this.getBitPrice(this.choice[0], 1);
150
+ const b0 = a1 + this.getBitPrice(this.choice[1], 0);
151
+ const b1 = a1 + this.getBitPrice(this.choice[1], 1);
152
+ let i = 0;
153
+ const st = priceIndex + posState * 0x110;
154
+ // Set prices for low range (lengths 2-9)
155
+ for (i = 0; i < 8; ++i) {
156
+ if (i >= numSymbols)
157
+ return;
158
+ prices[st + i] = a0 + this.getBitTreePrice(this.lowCoder[posState], i);
159
+ }
160
+ // Set prices for mid range (lengths 10-17)
161
+ for (; i < 16; ++i) {
162
+ if (i >= numSymbols)
163
+ return;
164
+ prices[st + i] = b0 + this.getBitTreePrice(this.midCoder[posState], i - 8);
165
+ }
166
+ // Set prices for high range (lengths 18+)
167
+ for (; i < numSymbols; ++i) {
168
+ prices[st + i] = b1 + this.getBitTreePrice(this.highCoder, i - 8 - 8);
169
+ }
170
+ }
171
+ }
@@ -0,0 +1,63 @@
1
+ import { type BasicRangeDecoder, type BasicRangeEncoder } from "./utils.js";
2
+ export declare class LitSubCoder {
3
+ private coders;
4
+ constructor();
5
+ /**
6
+ * Decode normal literal symbol
7
+ */
8
+ decodeNormal(rd: BasicRangeDecoder): number;
9
+ /**
10
+ * Decode literal symbol with match byte context
11
+ */
12
+ decodeWithMatchByte(rd: BasicRangeDecoder, matchByte: number): number;
13
+ /**
14
+ * Encode literal symbol
15
+ */
16
+ encode(re: BasicRangeEncoder, symbol: number): void;
17
+ /**
18
+ * Encode literal symbol with match byte context
19
+ */
20
+ encodeMatched(re: BasicRangeEncoder, matchByte: number, symbol: number): void;
21
+ /**
22
+ * Get price for encoding literal symbol
23
+ */
24
+ getPrice(matchMode: boolean, matchByte: number, symbol: number): number;
25
+ /**
26
+ * Reset coder to initial state
27
+ */
28
+ reset(): void;
29
+ /**
30
+ * Get decoders array (for compatibility with LiteralDecoderEncoder2)
31
+ */
32
+ get decoders(): number[];
33
+ }
34
+ export declare class LitCoder {
35
+ private _coders;
36
+ private _numPrevBits;
37
+ private _posMask;
38
+ constructor(numPosBits: number, numPrevBits: number);
39
+ /**
40
+ * Get sub-coder for position and previous byte
41
+ */
42
+ getSubCoder(pos: number, prevByte: number): LitSubCoder;
43
+ /**
44
+ * Reset all sub-coders
45
+ */
46
+ reset(): void;
47
+ /**
48
+ * Get number of previous bits (for compatibility)
49
+ */
50
+ get numPrevBits(): number;
51
+ /**
52
+ * Get number of position bits (for compatibility)
53
+ */
54
+ get numPosBits(): number;
55
+ /**
56
+ * Get position mask (for compatibility)
57
+ */
58
+ get posMask(): number;
59
+ /**
60
+ * Get coders array (for compatibility)
61
+ */
62
+ get coders(): LitSubCoder[];
63
+ }
@@ -0,0 +1,162 @@
1
+ import { getBitPrice, initArray, } from "./utils.js";
2
+ export class LitSubCoder {
3
+ coders;
4
+ constructor() {
5
+ this.coders = initArray(0x300, 0x400);
6
+ }
7
+ /**
8
+ * Decode normal literal symbol
9
+ */
10
+ decodeNormal(rd) {
11
+ let symbol = 1;
12
+ while (symbol < 0x100) {
13
+ const i = rd.decodeBit(this.coders, symbol);
14
+ symbol = (symbol << 1) | i;
15
+ }
16
+ return symbol & 0xFF;
17
+ }
18
+ /**
19
+ * Decode literal symbol with match byte context
20
+ */
21
+ decodeWithMatchByte(rd, matchByte) {
22
+ let uMatchByte = matchByte;
23
+ let symbol = 1;
24
+ while (symbol < 0x100) {
25
+ const matchBit = (uMatchByte >> 7) & 1;
26
+ uMatchByte <<= 1;
27
+ const bit = rd.decodeBit(this.coders, ((1 + matchBit) << 8) + symbol);
28
+ symbol = (symbol << 1) | bit;
29
+ if (matchBit !== bit) {
30
+ while (symbol < 0x100) {
31
+ const i = rd.decodeBit(this.coders, symbol);
32
+ symbol = (symbol << 1) | i;
33
+ }
34
+ break;
35
+ }
36
+ }
37
+ return symbol & 0xFF;
38
+ }
39
+ /**
40
+ * Encode literal symbol
41
+ */
42
+ encode(re, symbol) {
43
+ let context = 1;
44
+ for (let i = 7; i >= 0; i--) {
45
+ const bit = (symbol >> i) & 1;
46
+ re.encodeBit(this.coders, context, bit);
47
+ context = (context << 1) | bit;
48
+ }
49
+ }
50
+ /**
51
+ * Encode literal symbol with match byte context
52
+ */
53
+ encodeMatched(re, matchByte, symbol) {
54
+ let uMatchByte = matchByte;
55
+ let context = 1;
56
+ let same = true;
57
+ for (let i = 7; i >= 0; i--) {
58
+ const bit = (symbol >> i) & 1;
59
+ let state = context;
60
+ if (same) {
61
+ const matchBit = (uMatchByte >> i) & 1;
62
+ state += (1 + matchBit) << 8;
63
+ same = matchBit === bit;
64
+ }
65
+ re.encodeBit(this.coders, state, bit);
66
+ context = (context << 1) | bit;
67
+ }
68
+ }
69
+ /**
70
+ * Get price for encoding literal symbol
71
+ */
72
+ getPrice(matchMode, matchByte, symbol) {
73
+ let uMatchByte = matchByte;
74
+ let price = 0;
75
+ let context = 1;
76
+ let i = 7;
77
+ if (matchMode) {
78
+ while (i >= 0) {
79
+ const matchBit = (uMatchByte >> i) & 1;
80
+ const bit = (symbol >> i) & 1;
81
+ price += getBitPrice(this.coders[(1 + matchBit) << 8 + context], bit);
82
+ context = (context << 1) | bit;
83
+ if (matchBit !== bit) {
84
+ i--;
85
+ break;
86
+ }
87
+ i--;
88
+ }
89
+ }
90
+ while (i >= 0) {
91
+ const bit = (symbol >> i) & 1;
92
+ price += getBitPrice(this.coders[context], bit);
93
+ context = (context << 1) | bit;
94
+ i--;
95
+ }
96
+ return price;
97
+ }
98
+ /**
99
+ * Reset coder to initial state
100
+ */
101
+ reset() {
102
+ this.coders.fill(1024);
103
+ }
104
+ /**
105
+ * Get decoders array (for compatibility with LiteralDecoderEncoder2)
106
+ */
107
+ get decoders() {
108
+ return this.coders;
109
+ }
110
+ }
111
+ export class LitCoder {
112
+ _coders;
113
+ _numPrevBits;
114
+ _posMask;
115
+ constructor(numPosBits, numPrevBits) {
116
+ const numStates = 1 << (numPrevBits + numPosBits);
117
+ this._coders = [];
118
+ this._numPrevBits = numPrevBits;
119
+ this._posMask = (1 << numPosBits) - 1;
120
+ for (let i = 0; i < numStates; i++) {
121
+ this._coders[i] = new LitSubCoder();
122
+ }
123
+ }
124
+ /**
125
+ * Get sub-coder for position and previous byte
126
+ */
127
+ getSubCoder(pos, prevByte) {
128
+ return this._coders[((pos & this._posMask) << this._numPrevBits)
129
+ + (prevByte >> (8 - this._numPrevBits))];
130
+ }
131
+ /**
132
+ * Reset all sub-coders
133
+ */
134
+ reset() {
135
+ this._coders.forEach((coder) => coder.reset());
136
+ }
137
+ /**
138
+ * Get number of previous bits (for compatibility)
139
+ */
140
+ get numPrevBits() {
141
+ return this._numPrevBits;
142
+ }
143
+ /**
144
+ * Get number of position bits (for compatibility)
145
+ */
146
+ get numPosBits() {
147
+ // Calculate from posMask
148
+ return Math.log2(this._posMask + 1);
149
+ }
150
+ /**
151
+ * Get position mask (for compatibility)
152
+ */
153
+ get posMask() {
154
+ return this._posMask;
155
+ }
156
+ /**
157
+ * Get coders array (for compatibility)
158
+ */
159
+ get coders() {
160
+ return this._coders;
161
+ }
162
+ }
@@ -0,0 +1,43 @@
1
+ import { MatchFinder } from "./encoder.js";
2
+ /**
3
+ * LzInWindow - Input Window helper for LZMA encoding
4
+ *
5
+ * This class manages the input window operations for LZMA encoding,
6
+ * including buffer management, position tracking, and input stream reading.
7
+ */
8
+ export declare class LzInWindow {
9
+ private matchFinder;
10
+ constructor(matchFinder: MatchFinder);
11
+ /**
12
+ * Get a byte at the specified index relative to current position
13
+ */
14
+ getIndexByte(index: number): number;
15
+ /**
16
+ * Calculate match length between current position and a previous position
17
+ */
18
+ getMatchLen(index: number, distance: number, limit: number): number;
19
+ /**
20
+ * Get number of available bytes in the input window
21
+ */
22
+ getNumAvailableBytes(): number;
23
+ /**
24
+ * Move buffer block when reaching buffer boundaries
25
+ */
26
+ moveBlock(): void;
27
+ /**
28
+ * Move position by one and handle buffer management
29
+ */
30
+ movePos(): void;
31
+ /**
32
+ * Read a block of data from the input stream
33
+ */
34
+ readBlock(): void;
35
+ /**
36
+ * Reduce all position offsets by the specified value
37
+ */
38
+ reduceOffsets(subValue: number): void;
39
+ /**
40
+ * Read data from the input stream into the buffer
41
+ */
42
+ private readFromStream;
43
+ }