2024-07-08 22:31:15 +02:00
|
|
|
import type { ITokenizer } from 'strtok3';
|
2018-11-10 15:50:39 +01:00
|
|
|
import * as Token from 'token-types';
|
|
|
|
|
|
|
|
|
|
export class BitReader {
|
|
|
|
|
|
2024-08-08 10:19:14 +02:00
|
|
|
public pos = 0;
|
2024-08-09 09:57:18 +02:00
|
|
|
private dword: number | null = null;
|
2025-03-29 17:26:10 +02:00
|
|
|
private tokenizer: ITokenizer;
|
2018-11-10 15:50:39 +01:00
|
|
|
|
2025-03-29 17:26:10 +02:00
|
|
|
public constructor(tokenizer: ITokenizer) {
|
|
|
|
|
this.tokenizer = tokenizer;
|
2018-11-10 15:50:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param bits 1..30 bits
|
|
|
|
|
*/
|
2018-11-24 15:23:57 +01:00
|
|
|
public async read(bits: number): Promise<number> {
|
2018-11-10 15:50:39 +01:00
|
|
|
|
2024-08-09 09:57:18 +02:00
|
|
|
while (this.dword === null) {
|
2018-11-24 15:23:57 +01:00
|
|
|
this.dword = await this.tokenizer.readToken(Token.UINT32_LE);
|
2018-11-10 15:50:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let out = this.dword;
|
|
|
|
|
this.pos += bits;
|
|
|
|
|
|
|
|
|
|
if (this.pos < 32) {
|
|
|
|
|
out >>>= (32 - this.pos);
|
2018-11-24 15:23:57 +01:00
|
|
|
return out & ((1 << bits) - 1);
|
2024-08-08 10:19:14 +02:00
|
|
|
}
|
2018-11-10 15:50:39 +01:00
|
|
|
this.pos -= 32;
|
|
|
|
|
if (this.pos === 0) {
|
2024-08-09 09:57:18 +02:00
|
|
|
this.dword = null;
|
2018-11-24 15:23:57 +01:00
|
|
|
return out & ((1 << bits) - 1);
|
2024-08-08 10:19:14 +02:00
|
|
|
}
|
2018-11-24 15:23:57 +01:00
|
|
|
this.dword = await this.tokenizer.readToken(Token.UINT32_LE);
|
|
|
|
|
if (this.pos) {
|
|
|
|
|
out <<= this.pos;
|
|
|
|
|
out |= this.dword >>> (32 - this.pos);
|
|
|
|
|
}
|
|
|
|
|
return out & ((1 << bits) - 1);
|
2018-11-10 15:50:39 +01:00
|
|
|
}
|
|
|
|
|
|
2018-11-24 15:23:57 +01:00
|
|
|
public async ignore(bits: number): Promise<number> {
|
2018-11-10 15:50:39 +01:00
|
|
|
|
|
|
|
|
if (this.pos > 0) {
|
|
|
|
|
const remaining = 32 - this.pos;
|
2024-08-09 09:57:18 +02:00
|
|
|
this.dword = null;
|
2018-11-10 15:50:39 +01:00
|
|
|
bits -= remaining;
|
|
|
|
|
this.pos = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const remainder = bits % 32;
|
|
|
|
|
const numOfWords = (bits - remainder) / 32;
|
2018-11-24 15:23:57 +01:00
|
|
|
await this.tokenizer.ignore(numOfWords * 4);
|
|
|
|
|
return this.read(remainder);
|
2018-11-10 15:50:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|