-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathbitreader.go
More file actions
336 lines (283 loc) · 6.25 KB
/
bitreader.go
File metadata and controls
336 lines (283 loc) · 6.25 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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
// Package bitreader provides basic interfaces to read and traverse
// an io.Reader as a stream of bits, rather than a stream of bytes.
package bitreader
import (
"errors"
"io"
)
// Reader1 is the interface that wraps the basic Read1 method
//
// Read1() will return true or false depending on whether or not
// the next bit in the bit stream is set, then advance one bit
// forward in the bit-stream.
//
// Read1() is the equivalent to Peek1() followed by Skip(1)
type Reader interface {
Read1() (bool, error)
}
type Reader8 interface {
Reader
Read8(n uint) (uint8, error)
}
type Reader16 interface {
Reader8
Read16(n uint) (uint16, error)
}
// Reader32 is the interface that wraps the basic Read32 method.
//
// Read32 allows for reading multiple bits, where (1 <= n <= 32) as a uint32
// from the bit stream. Then advancing the bit stream by n bits.
//
// Read32(n) is equivalent to Peek32(n) followed by Skip(n)
type Reader32 interface {
Reader16
Read32(n uint) (uint32, error)
}
type Reader64 interface {
Reader32
Read64(n uint) (uint64, error)
}
// Peeker is the interface that wraps the basic Peek1 method
//
// Peek1 will return true or false depending on whether or not
// the next bit in the bit stream is set; it does not advance
// the stream any bits.
type Peeker interface {
Peek1() (bool, error)
}
type Peeker8 interface {
Peeker
Peek8(n uint) (uint8, error)
}
type Peeker16 interface {
Peeker8
Peek16(n uint) (uint16, error)
}
// Peeker32 is the interface that wraps the basic Peek32 method.
//
// Peek32 allows for reading multiple bits, where (1 <= n <= 32) as a uint32
// from the bit stream; it does not advance
// the bit stream any bits.
type Peeker32 interface {
Peeker16
Peek32(n uint) (uint32, error)
}
type Peeker64 interface {
Peeker32
Peek64(n uint) (uint64, error)
}
// Skipper is the interface that wraps the basic Skip method.
//
// Skip will advance the bit stream by n bits. Note, n is not
// constrained, like PeekX and ReadX methods. You can skip
// any number of bits up to max uint; the reader will continue
// to fill and drain the buffer until complete.
type Skipper interface {
Skip(n uint) error
}
// Aligner is the interface that allows for byte realignment.
//
// IsAligned() returns true if the bit stream is currently
// aligned to a byte boundary.
//
// Align() will skip the necessary bit to realign the bit
// stream to a byte boundary. It returns the number of bits skipped
// (0 <= n < 8) during realignment.
type Aligner interface {
IsAligned() bool
Align() (n uint, err error)
}
type BitReader1 interface {
io.Reader
Reader
Peeker
Skipper
Aligner
}
type BitReader8 interface {
io.Reader
Reader8
Peeker8
Skipper
Aligner
}
type BitReader16 interface {
io.Reader
Reader16
Peeker16
Skipper
Aligner
}
type BitReader32 interface {
io.Reader
Reader32
Peeker32
Skipper
Aligner
}
type BitReader interface {
io.Reader
Reader64
Peeker64
Skipper
Aligner
}
// NewBitReader returns the default implementation of a BitReader
func NewReader(r io.Reader) BitReader {
return &bitreader{r: r}
}
type bitreader struct {
r io.Reader
buffer uint64
remaining uint
raw [8]uint8
}
func (br *bitreader) Read(p []byte) (int, error) {
br.Align()
count := int((br.remaining + 7) >> 3)
if count > len(p) {
count = len(p)
}
for i := 0; i < count; i++ {
val, err := br.Read8(8)
if err != nil {
return i, err
}
p[i] = val
}
n, err := br.r.Read(p[count:])
return count + n, err
}
func (br *bitreader) Skip(n uint) error {
return br.skip(n)
}
func (br *bitreader) IsAligned() bool {
return br.remaining&0x7 == 0
}
func (br *bitreader) Align() (n uint, err error) {
n = br.remaining & 0x7
return n, br.skip(n)
}
func (br *bitreader) Read1() (bool, error) {
val, err := br.Peek1()
if err != nil {
return false, checkEOF(err)
}
return val, br.skip(1)
}
func (br *bitreader) Read8(n uint) (uint8, error) {
if n > 8 {
return 0, errors.New("overflow")
}
val, err := br.read(n)
return uint8(val), checkEOF(err)
}
func (br *bitreader) Read16(n uint) (uint16, error) {
if n > 16 {
return 0, errors.New("overflow")
}
val, err := br.read(n)
return uint16(val), err
}
func (br *bitreader) Read32(n uint) (uint32, error) {
if n > 32 {
return 0, errors.New("overflow")
}
val, err := br.read(n)
return uint32(val), err
}
func (br *bitreader) Read64(n uint) (uint64, error) {
if n > 64 {
return 0, errors.New("overflow")
}
return br.read(n)
}
func (br *bitreader) Peek1() (bool, error) {
val, err := br.peek(1)
return err == nil && val == 1, err
}
func (br *bitreader) Peek8(n uint) (uint8, error) {
if n > 8 {
return 0, errors.New("overflow")
}
val, err := br.peek(n)
return uint8(val), err
}
func (br *bitreader) Peek16(n uint) (uint16, error) {
if n > 16 {
return 0, errors.New("overflow")
}
val, err := br.peek(n)
return uint16(val), err
}
func (br *bitreader) Peek32(n uint) (uint32, error) {
if n > 32 {
return 0, errors.New("overflow")
}
val, err := br.peek(n)
return uint32(val), err
}
func (br *bitreader) Peek64(n uint) (uint64, error) {
if n > 64 {
return 0, errors.New("overflow")
}
return br.peek(n)
}
func (br *bitreader) fill() error {
total := (64 - br.remaining) >> 3
n, err := br.r.Read(br.raw[:total])
if err != nil {
return err
}
ir := br.remaining
for i := 0; i < n; i++ {
pos := 64 - 8 - (uint(i) << 3) - ir
br.buffer |= uint64(br.raw[i]) << pos
br.remaining += 8
}
return nil
}
func (br *bitreader) read(n uint) (uint64, error) {
val, err := br.peek(n)
if err != nil {
return 0, checkEOF(err)
}
return val, br.skip(n)
}
func (br *bitreader) peek(n uint) (uint64, error) {
if n > 56 && br.remaining&0x7 != 0 {
return 0, errors.New("offset mismatch, can't fill the buffer with leftover-bytes")
}
for br.remaining < n {
if err := br.fill(); err != nil {
return 0, err
}
}
dist := 64 - n
mask := ^uint64(0) << dist
result := (br.buffer & mask) >> dist
return result, nil
}
func (br *bitreader) skip(n uint) error {
for n > 0 {
len := n
if len > br.remaining {
len = br.remaining
}
br.buffer <<= len
br.remaining -= len
n -= len
if n > 0 {
if err := br.fill(); err != nil {
return checkEOF(err)
}
}
}
return nil
}
func checkEOF(err error) error {
if err == io.EOF {
return io.ErrUnexpectedEOF
}
return err
}