96 lines
2.1 KiB
TypeScript
96 lines
2.1 KiB
TypeScript
import { LZMA } from "./lzma";
|
|
|
|
/**
|
|
* LZMA Decoder
|
|
* @author Nidin Vinayakan
|
|
*/
|
|
export class RangeDecoder {
|
|
static kTopValue: u32 = 1 << 24
|
|
|
|
public inStream: Uint8Array
|
|
public corrupted: boolean
|
|
|
|
public in_pos: i32
|
|
private range: u32 = 0
|
|
private code: u32 = 0
|
|
|
|
constructor() {
|
|
this.in_pos = 13
|
|
}
|
|
|
|
@inline
|
|
public isFinishedOK(): boolean {
|
|
return this.code == 0
|
|
}
|
|
|
|
@inline
|
|
public init(): void {
|
|
this.corrupted = false
|
|
|
|
if (this.inStream[this.in_pos++] != 0) {
|
|
this.corrupted = true
|
|
}
|
|
|
|
this.range = 0xffffffff
|
|
this.code = 0
|
|
|
|
for (var i: i32 = 0; i < 4; i++) {
|
|
this.code = (this.code << 8) | this.inStream[this.in_pos++]
|
|
}
|
|
|
|
if (this.code == this.range) {
|
|
this.corrupted = true
|
|
}
|
|
}
|
|
|
|
@inline
|
|
public normalize():void {
|
|
if (this.range < RangeDecoder.kTopValue) {
|
|
this.range <<= 8
|
|
this.code = (this.code << 8) | this.inStream[this.in_pos++]
|
|
}
|
|
}
|
|
|
|
@inline
|
|
public decodeDirectBits(numBits: i32): i32 {
|
|
var res:u32 = 0
|
|
do {
|
|
this.range >>>= 1
|
|
this.code -= this.range
|
|
let t:u32 = 0 - (this.code >>> 31)
|
|
this.code += this.range & t
|
|
|
|
if (this.code == this.range) {
|
|
this.corrupted = true
|
|
}
|
|
|
|
this.normalize()
|
|
res <<= 1
|
|
res += t + 1
|
|
} while (--numBits)
|
|
return res
|
|
}
|
|
|
|
@inline
|
|
decodeBit(prob: Uint16Array, index: i32):u16 {
|
|
var v:u16 = prob.__unchecked_get(index);
|
|
var bound:u32 = (this.range >> LZMA.kNumBitModelTotalBits) * v;
|
|
var symbol:u16 = 0;
|
|
if (this.code < bound)
|
|
{
|
|
v += ((1 << LZMA.kNumBitModelTotalBits) - v) >> LZMA.kNumMoveBits;
|
|
this.range = bound;
|
|
symbol = 0;
|
|
}
|
|
else
|
|
{
|
|
v -= v >> LZMA.kNumMoveBits;
|
|
this.code -= bound;
|
|
this.range -= bound;
|
|
symbol = 1;
|
|
}
|
|
prob.__unchecked_set(index, v)
|
|
this.normalize();
|
|
return symbol;
|
|
}
|
|
} |