///|
let brotli_read_size : Int = 4096
///|
let brotli_ibuf_size : Int = 2 * 4096 + 32
///|
let brotli_ibuf_mask : Int = 2 * 4096 - 1
///|
priv struct BitReader {
buf : FixedArray[Int]
data : Bytes
data_len : Int
mut data_pos : Int
mut buf_ptr : Int
mut val : Int
mut pos : Int
mut bit_pos : Int
mut bit_end_pos : Int
mut eos : Bool
}
///|
fn BitReader::new(data : Bytes) -> BitReader raise BrotliError {
let br : BitReader = {
buf: FixedArray::make(brotli_ibuf_size, 0),
data,
data_len: data.length(),
data_pos: 0,
buf_ptr: 0,
val: 0,
pos: 0,
bit_pos: 0,
bit_end_pos: 0,
eos: false,
}
br.read_more_input()
for i in 0..<4 {
br.val = br.val | (br.buf[br.pos] << (8 * i))
br.pos += 1
}
br
}
///|
fn BitReader::read_input(self : BitReader, dst : Int, count : Int) -> Int {
let available = self.data_len - self.data_pos
let to_read = if count > available { available } else { count }
for i in 0.. Unit raise BrotliError {
if self.bit_end_pos > 256 {
return
}
if self.eos {
if self.bit_pos > self.bit_end_pos {
raise BrotliError::InvalidData("Unexpected end of input")
}
return
}
let dst = self.buf_ptr
let bytes_read = self.read_input(dst, brotli_read_size)
if bytes_read < brotli_read_size {
self.eos = true
for p in 0..<32 {
self.buf[dst + bytes_read + p] = 0
}
}
if dst == 0 {
for p in 0..<32 {
self.buf[(brotli_read_size << 1) + p] = self.buf[p]
}
self.buf_ptr = brotli_read_size
} else {
self.buf_ptr = 0
}
self.bit_end_pos += bytes_read << 3
}
///|
fn BitReader::fill_bit_window(self : BitReader) -> Unit {
while self.bit_pos >= 8 {
self.val = ushr(self.val, 8)
self.val = self.val | (self.buf[self.pos & brotli_ibuf_mask] << 24)
self.pos += 1
self.bit_pos = self.bit_pos - 8
self.bit_end_pos = self.bit_end_pos - 8
}
}
///|
fn BitReader::read_bits(self : BitReader, n_bits : Int) -> Int {
if 32 - self.bit_pos < n_bits {
self.fill_bit_window()
}
let val = ushr(self.val, self.bit_pos) & kBitMask[n_bits]
self.bit_pos += n_bits
val
}
///|
fn BitReader::reset(self : BitReader) -> Unit raise BrotliError {
self.buf_ptr = 0
self.val = 0
self.pos = 0
self.bit_pos = 0
self.bit_end_pos = 0
self.eos = false
self.read_more_input()
for i in 0..<4 {
self.val = self.val | (self.buf[self.pos] << (8 * i))
self.pos += 1
}
}