-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbit_reader.go
More file actions
75 lines (66 loc) · 1.76 KB
/
bit_reader.go
File metadata and controls
75 lines (66 loc) · 1.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package gzip
// BitReader is a struct for reading bits from a byte slice.
//
// (8i+j)-th bit is stored in i-th byte at j-th bit.
// Specifically, the least significant bit is stored in the first bit of the byte.
// It can be retrieved with (slice[i] >> j) & 1.
type BitReader struct {
// The byte slice to read from.
bytes []byte
// The number of bits read from the current byte.
numBitsRead int
// The current index in the byte slice.
index int
}
// NewBitReader creates a new BitReader.
func NewBitReader(bytes []byte) *BitReader {
return &BitReader{bytes: bytes}
}
// Bit reads a bit.
func (b *BitReader) Bit() byte {
result := (b.bytes[b.index] >> b.numBitsRead) & 1
b.numBitsRead++
if b.numBitsRead == 8 {
b.numBitsRead = 0
b.index++
}
return result
}
// Bytes reads the given number of bytes.
func (b *BitReader) Bytes(length int) []byte {
result := make([]byte, length)
for i := 0; i < length; i++ {
result[i] = byte(b.Int(8))
}
return result
}
// Int reads an integer of the given length.
func (b *BitReader) Int(length int) uint64 {
var result uint64
for i := 0; i < length; i++ {
result |= uint64(b.Bit()) << i
}
return result
}
// IntBE reads an integer of the given length, regarded as big endian.
func (b *BitReader) IntBE(length int) uint64 {
var result uint64
for i := length - 1; i >= 0; i-- {
result |= uint64(b.Bit()) << i
}
return result
}
func (b *BitReader) SkipToByteBoundary() {
if b.numBitsRead > 0 {
b.numBitsRead = 0
b.index++
}
}
// Remaining returns the number of bits remaining to be read.
func (b *BitReader) Remaining() int {
return (len(b.bytes)-b.index)*8 - b.numBitsRead
}
// Position returns the current position in bits.
func (b *BitReader) Position() uint64 {
return uint64(b.index)*8 + uint64(b.numBitsRead)
}