github.com/bir3/gocompiler@v0.9.2202/extra/compress/zstd/bitreader.go (about) 1 // Copyright 2019+ Klaus Post. All rights reserved. 2 // License information can be found in the LICENSE file. 3 // Based on work by Yann Collet, released under BSD License. 4 5 package zstd 6 7 import ( 8 "encoding/binary" 9 "errors" 10 "fmt" 11 "io" 12 "math/bits" 13 ) 14 15 // bitReader reads a bitstream in reverse. 16 // The last set bit indicates the start of the stream and is used 17 // for aligning the input. 18 type bitReader struct { 19 in []byte 20 off uint // next byte to read is at in[off - 1] 21 value uint64 // Maybe use [16]byte, but shifting is awkward. 22 bitsRead uint8 23 } 24 25 // init initializes and resets the bit reader. 26 func (b *bitReader) init(in []byte) error { 27 if len(in) < 1 { 28 return errors.New("corrupt stream: too short") 29 } 30 b.in = in 31 b.off = uint(len(in)) 32 // The highest bit of the last byte indicates where to start 33 v := in[len(in)-1] 34 if v == 0 { 35 return errors.New("corrupt stream, did not find end of stream") 36 } 37 b.bitsRead = 64 38 b.value = 0 39 if len(in) >= 8 { 40 b.fillFastStart() 41 } else { 42 b.fill() 43 b.fill() 44 } 45 b.bitsRead += 8 - uint8(highBits(uint32(v))) 46 return nil 47 } 48 49 // getBits will return n bits. n can be 0. 50 func (b *bitReader) getBits(n uint8) int { 51 if n == 0 /*|| b.bitsRead >= 64 */ { 52 return 0 53 } 54 return int(b.get32BitsFast(n)) 55 } 56 57 // get32BitsFast requires that at least one bit is requested every time. 58 // There are no checks if the buffer is filled. 59 func (b *bitReader) get32BitsFast(n uint8) uint32 { 60 const regMask = 64 - 1 61 v := uint32((b.value << (b.bitsRead & regMask)) >> ((regMask + 1 - n) & regMask)) 62 b.bitsRead += n 63 return v 64 } 65 66 // fillFast() will make sure at least 32 bits are available. 67 // There must be at least 4 bytes available. 68 func (b *bitReader) fillFast() { 69 if b.bitsRead < 32 { 70 return 71 } 72 // 2 bounds checks. 73 v := b.in[b.off-4:] 74 v = v[:4] 75 low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) 76 b.value = (b.value << 32) | uint64(low) 77 b.bitsRead -= 32 78 b.off -= 4 79 } 80 81 // fillFastStart() assumes the bitreader is empty and there is at least 8 bytes to read. 82 func (b *bitReader) fillFastStart() { 83 // Do single re-slice to avoid bounds checks. 84 b.value = binary.LittleEndian.Uint64(b.in[b.off-8:]) 85 b.bitsRead = 0 86 b.off -= 8 87 } 88 89 // fill() will make sure at least 32 bits are available. 90 func (b *bitReader) fill() { 91 if b.bitsRead < 32 { 92 return 93 } 94 if b.off >= 4 { 95 v := b.in[b.off-4:] 96 v = v[:4] 97 low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) 98 b.value = (b.value << 32) | uint64(low) 99 b.bitsRead -= 32 100 b.off -= 4 101 return 102 } 103 for b.off > 0 { 104 b.value = (b.value << 8) | uint64(b.in[b.off-1]) 105 b.bitsRead -= 8 106 b.off-- 107 } 108 } 109 110 // finished returns true if all bits have been read from the bit stream. 111 func (b *bitReader) finished() bool { 112 return b.off == 0 && b.bitsRead >= 64 113 } 114 115 // overread returns true if more bits have been requested than is on the stream. 116 func (b *bitReader) overread() bool { 117 return b.bitsRead > 64 118 } 119 120 // remain returns the number of bits remaining. 121 func (b *bitReader) remain() uint { 122 return b.off*8 + 64 - uint(b.bitsRead) 123 } 124 125 // close the bitstream and returns an error if out-of-buffer reads occurred. 126 func (b *bitReader) close() error { 127 // Release reference. 128 b.in = nil 129 if !b.finished() { 130 return fmt.Errorf("%d extra bits on block, should be 0", b.remain()) 131 } 132 if b.bitsRead > 64 { 133 return io.ErrUnexpectedEOF 134 } 135 return nil 136 } 137 138 func highBits(val uint32) (n uint32) { 139 return uint32(bits.Len32(val) - 1) 140 }