| // 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) | |
| } |