forked from makiuchi-d/gozxing
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bit_source.go
74 lines (62 loc) · 1.58 KB
/
bit_source.go
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
package common
import (
errors "golang.org/x/xerrors"
)
type BitSource struct {
bytes []byte
byteOffset int
bitOffset int
}
func NewBitSource(bytes []byte) *BitSource {
return &BitSource{
bytes: bytes,
}
}
func (this *BitSource) GetBitOffset() int {
return this.bitOffset
}
func (this *BitSource) GetByteOffset() int {
return this.byteOffset
}
func (this *BitSource) ReadBits(numBits int) (int, error) {
if numBits < 1 || numBits > 32 || numBits > this.Available() {
return 0, errors.Errorf("IllegalArgumentException: %v", numBits)
}
result := 0
// First, read remainder from current byte
if this.bitOffset > 0 {
bitsLeft := 8 - this.bitOffset
toRead := bitsLeft
if numBits < bitsLeft {
toRead = numBits
}
bitsToNotRead := uint(bitsLeft - toRead)
mask := byte((0xFF >> uint(8-toRead)) << bitsToNotRead)
result = int(this.bytes[this.byteOffset]&mask) >> bitsToNotRead
numBits -= toRead
this.bitOffset += toRead
if this.bitOffset == 8 {
this.bitOffset = 0
this.byteOffset++
}
}
// Next read whole bytes
if numBits > 0 {
for numBits >= 8 {
result = (result << 8) | int(this.bytes[this.byteOffset]&0xFF)
this.byteOffset++
numBits -= 8
}
// Finally read a partial byte
if numBits > 0 {
bitsToNotRead := uint(8 - numBits)
mask := byte((0xFF >> bitsToNotRead) << bitsToNotRead)
result = (result << uint(numBits)) | int((this.bytes[this.byteOffset]&mask)>>bitsToNotRead)
this.bitOffset += numBits
}
}
return result, nil
}
func (this *BitSource) Available() int {
return 8*(len(this.bytes)-this.byteOffset) - this.bitOffset
}