blob: a5edc040d6614f90c4fb63389477f97dbc6ba4ca (
plain)
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
76
77
78
79
80
81
82
83
84
|
// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package binary
// BitStream provides methods for reading and writing bits to a slice of bytes.
// Bits are packed in a least-significant-bit to most-significant-bit order.
type BitStream struct {
Data []byte // The byte slice containing the bits
ReadPos uint32 // The current read offset from the start of the Data slice (in bits)
WritePos uint32 // The current write offset from the start of the Data slice (in bits)
}
// ReadBit reads a single bit from the BitStream, incrementing ReadPos by one.
func (s *BitStream) ReadBit() uint32 {
ReadPos := s.ReadPos
s.ReadPos = ReadPos + 1
return (uint32(s.Data[ReadPos/8]) >> (ReadPos % 8)) & 1
}
// WriteBit writes a single bit to the BitStream, incrementing WritePos by one.
func (s *BitStream) WriteBit(bit uint32) {
WritePos := s.WritePos
b := WritePos / 8
if b == uint32(len(s.Data)) {
s.Data = append(s.Data, byte(0))
}
s.Data[b] |= byte((bit & 1) << (WritePos % 8))
s.WritePos = WritePos + 1
}
// Read reads the specified number of bits from the BitStream, increamenting the ReadPos by the
// specified number of bits and returning the bits packed into a uint32. The bits are packed into
// the uint32 from LSB to MSB.
func (s *BitStream) Read(count uint32) uint32 {
byteIdx := s.ReadPos / 8
bitIdx := s.ReadPos & 7
// Start
val := uint32(s.Data[byteIdx]) >> bitIdx
readCount := 8 - bitIdx
if count <= readCount {
s.ReadPos += count
return val & ((1 << count) - 1)
}
s.ReadPos += readCount
byteIdx++
bitIdx = 0
// Whole bytes
for ; readCount+7 < count; readCount += 8 {
val |= uint32(s.Data[byteIdx]) << readCount
byteIdx++
s.ReadPos += 8
}
// Remainder
rem := count - readCount
if rem > 0 {
val |= (uint32(s.Data[byteIdx]) & ((1 << rem) - 1)) << readCount
s.ReadPos += rem
}
return val
}
// Write writes the specified number of bits from the packed uint32, increamenting the WritePos by
// the specified number of bits. The bits are read from the uint32 from LSB to MSB.
func (s *BitStream) Write(bits, count uint32) {
// TODO: Slowest implementation ever? Quite possibly. Optimise
for i := uint32(0); i < count; i++ {
s.WriteBit(bits >> i)
}
}
|