| // Copyright 2023 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package zstd |
| |
| import ( |
| "math/bits" |
| ) |
| |
| // block is the data for a single compressed block. |
| // The data starts immediately after the 3 byte block header, |
| // and is Block_Size bytes long. |
| type block []byte |
| |
| // bitReader reads a bit stream going forward. |
| type bitReader struct { |
| r *Reader // for error reporting |
| data block // the bits to read |
| off uint32 // current offset into data |
| bits uint32 // bits ready to be returned |
| cnt uint32 // number of valid bits in the bits field |
| } |
| |
| // makeBitReader makes a bit reader starting at off. |
| func (r *Reader) makeBitReader(data block, off int) bitReader { |
| return bitReader{ |
| r: r, |
| data: data, |
| off: uint32(off), |
| } |
| } |
| |
| // moreBits is called to read more bits. |
| // This ensures that at least 16 bits are available. |
| func (br *bitReader) moreBits() error { |
| for br.cnt < 16 { |
| if br.off >= uint32(len(br.data)) { |
| return br.r.makeEOFError(int(br.off)) |
| } |
| c := br.data[br.off] |
| br.off++ |
| br.bits |= uint32(c) << br.cnt |
| br.cnt += 8 |
| } |
| return nil |
| } |
| |
| // val is called to fetch a value of b bits. |
| func (br *bitReader) val(b uint8) uint32 { |
| r := br.bits & ((1 << b) - 1) |
| br.bits >>= b |
| br.cnt -= uint32(b) |
| return r |
| } |
| |
| // backup steps back to the last byte we used. |
| func (br *bitReader) backup() { |
| for br.cnt >= 8 { |
| br.off-- |
| br.cnt -= 8 |
| } |
| } |
| |
| // makeError returns an error at the current offset wrapping a string. |
| func (br *bitReader) makeError(msg string) error { |
| return br.r.makeError(int(br.off), msg) |
| } |
| |
| // reverseBitReader reads a bit stream in reverse. |
| type reverseBitReader struct { |
| r *Reader // for error reporting |
| data block // the bits to read |
| off uint32 // current offset into data |
| start uint32 // start in data; we read backward to start |
| bits uint32 // bits ready to be returned |
| cnt uint32 // number of valid bits in bits field |
| } |
| |
| // makeReverseBitReader makes a reverseBitReader reading backward |
| // from off to start. The bitstream starts with a 1 bit in the last |
| // byte, at off. |
| func (r *Reader) makeReverseBitReader(data block, off, start int) (reverseBitReader, error) { |
| streamStart := data[off] |
| if streamStart == 0 { |
| return reverseBitReader{}, r.makeError(off, "zero byte at reverse bit stream start") |
| } |
| rbr := reverseBitReader{ |
| r: r, |
| data: data, |
| off: uint32(off), |
| start: uint32(start), |
| bits: uint32(streamStart), |
| cnt: uint32(7 - bits.LeadingZeros8(streamStart)), |
| } |
| return rbr, nil |
| } |
| |
| // val is called to fetch a value of b bits. |
| func (rbr *reverseBitReader) val(b uint8) (uint32, error) { |
| if !rbr.fetch(b) { |
| return 0, rbr.r.makeEOFError(int(rbr.off)) |
| } |
| |
| rbr.cnt -= uint32(b) |
| v := (rbr.bits >> rbr.cnt) & ((1 << b) - 1) |
| return v, nil |
| } |
| |
| // fetch is called to ensure that at least b bits are available. |
| // It reports false if this can't be done, |
| // in which case only rbr.cnt bits are available. |
| func (rbr *reverseBitReader) fetch(b uint8) bool { |
| for rbr.cnt < uint32(b) { |
| if rbr.off <= rbr.start { |
| return false |
| } |
| rbr.off-- |
| c := rbr.data[rbr.off] |
| rbr.bits <<= 8 |
| rbr.bits |= uint32(c) |
| rbr.cnt += 8 |
| } |
| return true |
| } |
| |
| // makeError returns an error at the current offset wrapping a string. |
| func (rbr *reverseBitReader) makeError(msg string) error { |
| return rbr.r.makeError(int(rbr.off), msg) |
| } |