aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bitreader.go281
-rw-r--r--bitreader_test.go144
2 files changed, 313 insertions, 112 deletions
diff --git a/bitreader.go b/bitreader.go
index 06374b8..3fbc221 100644
--- a/bitreader.go
+++ b/bitreader.go
@@ -1,51 +1,146 @@
1// BitReader is a simple bit reader with big/little-endian support for golang.
2// It can read stream data from an io.Reader; can read from os.File and a byte array with bytes.NewReader(array).
3// Uses bitwise operations for v2.
4// Supports reading up to 64 bits at one time.
5// Includes wrapper functions for most used data types.
6// Error checking on all but wrapper functions.
7// Thanks to github.com/mlugg for the big help!
1package bitreader 8package bitreader
2 9
3import ( 10import (
4 "fmt" 11 "fmt"
5 "math/bits" 12 "io"
6 "strconv" 13 "math"
7 "strings"
8) 14)
9 15
16// ReaderType is the main structure of our Reader.
17// Whenever index == 0, we need to read a new byte from stream into curByte
10type ReaderType struct { 18type ReaderType struct {
11 data []byte // Reader data from a byte array 19 stream io.Reader // The underlying stream we're reading bytes from
12 base int // Current reader byte location 20 index uint8 // The current index into the byte [0-7]
13 index int // Current reader index 21 curByte byte // The byte we're currently reading from
14 le bool // Little endian or big endian? 22 le bool // Whether to read in little-endian order
15} 23}
16 24
17func Reader(data []byte, le bool) *ReaderType { 25// Reader is the main constructor that creates the ReaderType object
18 dataClone := data 26// with stream data and little-endian state.
19 if le { 27func Reader(stream io.Reader, le bool) *ReaderType {
20 for index, byteValue := range data {
21 dataClone[index] = bits.Reverse8(byteValue)
22 }
23 }
24 return &ReaderType{ 28 return &ReaderType{
25 data: dataClone, 29 stream: stream,
26 base: 0, 30 index: 0,
27 index: 0, 31 curByte: 0, // Initial value doesn't matter, it'll be read as soon as we try to read any bits
28 le: le, 32 le: le,
29 } 33 }
30} 34}
31 35
32func (reader *ReaderType) SkipBits(bits int) error { 36// TryReadBool is a wrapper function that gets the state of 1-bit,
33 if bits <= 0 { 37// returns true if 1, false if 0. Panics on error.
34 return fmt.Errorf("SkipBits Error: Bits value %d lower or equals than 0.", bits) 38func (reader *ReaderType) TryReadBool() bool {
39 flag, err := reader.ReadBool()
40 if err != nil {
41 panic(err)
42 }
43 return flag
44}
45
46// TryReadInt1 is a wrapper function that returns the value of 1-bit.
47// Returns type uint8. Panics on error.
48func (reader *ReaderType) TryReadInt1() uint8 {
49 value, err := reader.ReadBits(1)
50 if err != nil {
51 panic(err)
52 }
53 return uint8(value)
54}
55
56// TryReadInt8 is a wrapper function that returns the value of 8-bits.
57// Returns uint8. Panics on error.
58func (reader *ReaderType) TryReadInt8() uint8 {
59 value, err := reader.ReadBits(8)
60 if err != nil {
61 panic(err)
62 }
63 return uint8(value)
64}
65
66// TryReadInt16 is a wrapper function that returns the value of 16-bits.
67// Returns uint16. Panics on error.
68func (reader *ReaderType) TryReadInt16() uint16 {
69 value, err := reader.ReadBits(16)
70 if err != nil {
71 panic(err)
72 }
73 return uint16(value)
74}
75
76// TryReadInt32 is a wrapper function that returns the value of 32-bits.
77// Returns uint32. Panics on error.
78func (reader *ReaderType) TryReadInt32() uint32 {
79 value, err := reader.ReadBits(32)
80 if err != nil {
81 panic(err)
82 }
83 return uint32(value)
84}
85
86// TryReadInt64 is a wrapper function that returns the value of 64-bits.
87// Returns uint64. Panics on error.
88func (reader *ReaderType) TryReadInt64() uint64 {
89 value, err := reader.ReadBits(64)
90 if err != nil {
91 panic(err)
92 }
93 return value
94}
95
96// TryReadFloat32 is a wrapper function that returns the value of 32-bits.
97// Returns float32. Panics on error.
98func (reader *ReaderType) TryReadFloat32() float32 {
99 value, err := reader.ReadBits(32)
100 if err != nil {
101 panic(err)
102 }
103 return math.Float32frombits(uint32(value))
104}
105
106// TryReadFloat64 is a wrapper function that returns the value of 64-bits.
107// Returns float64. Panics on error.
108func (reader *ReaderType) TryReadFloat64() float64 {
109 value, err := reader.ReadBits(64)
110 if err != nil {
111 panic(err)
35 } 112 }
36 err := reader.checkAvailableBits(bits) 113 return math.Float64frombits(value)
114}
115
116// SkipBits is a function that increases Reader index
117// based on given input bits number. Returns an error
118// if there are no remaining bits.
119func (reader *ReaderType) SkipBits(bits int) error {
120 // Read as many raw bytes as we can
121 bytes := bits / 8
122 buf := make([]byte, bytes)
123 _, err := reader.stream.Read(buf)
37 if err != nil { 124 if err != nil {
38 return err 125 return err
39 } 126 }
40 for reader.index+bits > 7 { 127 // The final read byte should be the new current byte
41 reader.base++ 128 if bytes > 0 {
42 reader.index = 0 129 reader.curByte = buf[bytes-1]
43 bits -= 8 130 }
131 // Read the extra bits
132 for i := bytes * 8; i < bits; i++ {
133 _, err := reader.readBit()
134 if err != nil {
135 return err
136 }
44 } 137 }
45 reader.index += bits
46 return nil 138 return nil
47} 139}
48 140
141// SkipBytes is a function that increases Reader index
142// based on given input bytes number. Returns an error
143// if there are no remaining bits.
49func (reader *ReaderType) SkipBytes(bytes int) error { 144func (reader *ReaderType) SkipBytes(bytes int) error {
50 err := reader.SkipBits(bytes * 8) 145 err := reader.SkipBits(bytes * 8)
51 if err != nil { 146 if err != nil {
@@ -54,81 +149,83 @@ func (reader *ReaderType) SkipBytes(bytes int) error {
54 return nil 149 return nil
55} 150}
56 151
57func (reader *ReaderType) ReadBits(bits int) (int, error) { 152// ReadBits is a function that reads the specified amount of bits
58 if bits <= 0 { 153// specified in the parameter and returns the value, error
59 return -1, fmt.Errorf("ReadBits Error: Bits value %d lower or equals than 0.", bits) 154// based on the output. It can read up to 64 bits. Returns the read
60 } 155// value in type uint64.
61 if bits > 64 { 156//
62 return -1, fmt.Errorf("ReadBits Error: Bits value %d higher than 64.", bits) 157// Returns an error if there are no remaining bits.
158func (reader *ReaderType) ReadBits(bits int) (uint64, error) {
159 if bits < 1 || bits > 64 {
160 return 0, fmt.Errorf("ReadBits(bits) ERROR: Bits number should be between 1 and 64.")
63 } 161 }
64 err := reader.checkAvailableBits(bits) 162 var val uint64
65 if err != nil { 163 for i := 0; i < bits; i++ {
66 return -1, err 164 bit, err := reader.readBit()
67 }
68 if reader.le {
69 var output string
70 // Go to last bit and read backwards from there
71 reader.base += bits / 8
72 reader.index += bits % 8
73 if reader.index > 7 {
74 reader.index -= 8
75 reader.base++
76 }
77 for i := 0; i < bits; i++ {
78 reader.index--
79 if reader.index < 0 {
80 reader.base--
81 reader.index = 7
82 }
83 binary := fmt.Sprintf("%08b", reader.data[reader.base])
84 binaryArr := strings.Split(binary, "")
85 output += binaryArr[reader.index]
86 }
87 // Return to last bit after reading
88 reader.base += bits / 8
89 reader.index += bits % 8
90 if reader.index > 7 {
91 reader.index -= 8
92 }
93 // Conversion of string binary to int
94 value, err := strconv.ParseUint(output, 2, 64)
95 if err != nil { 165 if err != nil {
96 return -1, fmt.Errorf("%s", err) 166 return 0, err
97 }
98 return int(value), nil
99 } else {
100 var output string
101 for i := 0; i < bits; i++ {
102 binary := fmt.Sprintf("%08b", reader.data[reader.base])
103 binaryArr := strings.Split(binary, "")
104 output += binaryArr[reader.index]
105 reader.index++
106 if reader.index > 7 {
107 reader.base++
108 reader.index = 0
109 }
110 } 167 }
111 // Conversion of string binary to int 168
112 value, err := strconv.ParseUint(output, 2, 64) 169 if reader.le {
113 if err != nil { 170 val |= uint64(bit) << i
114 return -1, fmt.Errorf("%s", err) 171 } else {
172 val |= uint64(bit) << (bits - 1 - i)
115 } 173 }
116 return int(value), nil
117 } 174 }
175 return val, nil
118} 176}
119 177
120func (reader *ReaderType) ReadBit() (bool, error) { 178// ReadBytes is a function that reads the specified amount of bytes
121 value, err := reader.ReadBits(1) 179// specified in the parameter and returns the value, error
180// based on the output. It can read up to 8 bytes. Returns the read
181// value in type uint64.
182//
183// Returns an error if there are no remaining bits.
184func (reader *ReaderType) ReadBytes(bytes int) (uint64, error) {
185 if bytes < 1 || bytes > 8 {
186 return 0, fmt.Errorf("ReadBytes(bytes) ERROR: Bytes number should be between 1 and 8.")
187 }
188 value, err := reader.ReadBits(bytes * 8)
122 if err != nil { 189 if err != nil {
123 return false, fmt.Errorf("ReadBit Error: %s", err) 190 return 0, err
124 } 191 }
125 return value != 0, nil 192 return value, nil
126} 193}
127 194
128func (reader *ReaderType) checkAvailableBits(bits int) error { 195// ReadBool is a function that reads one bit and returns the state, error
129 availableBits := (len(reader.data)-reader.base)*8 - reader.index 196// based on the output. Returns the read value in a bool format.
130 if availableBits < bits { 197//
131 return fmt.Errorf("BitReaderOutOfBounds: Wanted to read/skip %d bit(s) but only %d bit(s) is/are available.", bits, availableBits) 198// Returns an error if there are no remaining bits.
199func (reader *ReaderType) ReadBool() (bool, error) {
200 val, err := reader.readBit()
201 if err != nil {
202 return false, err
203 }
204 return val == 1, nil
205}
206
207// readBit is a private function that reads a single bit from the stream.
208// This is the main function that makes us read stream data.
209func (reader *ReaderType) readBit() (uint8, error) {
210 if reader.index == 0 {
211 // Read a byte from stream into curByte
212 buf := make([]byte, 1)
213 _, err := reader.stream.Read(buf)
214 if err != nil {
215 return 0, err
216 }
217 reader.curByte = buf[0]
218 }
219 var val bool
220 if reader.le {
221 val = (reader.curByte & (1 << reader.index)) != 0
222 } else {
223 val = (reader.curByte & (1 << (7 - reader.index))) != 0
224 }
225 reader.index = (reader.index + 1) % 8
226 if val {
227 return 1, nil
228 } else {
229 return 0, nil
132 } 230 }
133 return nil
134} 231}
diff --git a/bitreader_test.go b/bitreader_test.go
index 5d344d2..85b0c98 100644
--- a/bitreader_test.go
+++ b/bitreader_test.go
@@ -1,17 +1,84 @@
1package bitreader 1package bitreader
2 2
3import ( 3import (
4 "bytes"
4 "testing" 5 "testing"
5) 6)
6 7
7// 01110001, 00001101, 00000000, 00000000, 10100010, 00011011, 00000000, 00000000, 11001100 8// 01110001, 00001101, 00000000, 00000000, 10100010, 00011011, 00000000, 00000000, 11001100
8var TestArray = [...]byte{113, 13, 0, 0, 162, 27, 0, 0, 204} 9var TestArray = [...]byte{113, 13, 0, 0, 162, 27, 0, 0, 204}
9 10
11func TestTryReadFloat32(t *testing.T) {
12 bitreader := Reader(bytes.NewReader(TestArray[:]), false)
13 expected := []float32{6.98198182157e+29, -2.10064170919e-18}
14 for i := range expected {
15 value := bitreader.TryReadFloat32()
16 if value != expected[i] {
17 t.Fatalf("TryReadFloat32 FAIL for index %d: Expected %f, Got %f", i, expected[i], value)
18 }
19 }
20}
21
22func TestTryReadFloat64(t *testing.T) {
23 bitreader := Reader(bytes.NewReader(TestArray[:]), false)
24 expected := []float64{3.68828741038253948851462939603e+236}
25 for i := range expected {
26 value := bitreader.TryReadFloat64()
27 if value != expected[i] {
28 t.Fatalf("TryReadFloat64 FAIL for index %d: Expected %f, Got %f", i, expected[i], value)
29 }
30 }
31}
32
33func TestTryReadInt8(t *testing.T) {
34 bitreader := Reader(bytes.NewReader(TestArray[:]), false)
35 expected := []int{113, 13, 0}
36 for i := range expected {
37 value := bitreader.TryReadInt8()
38 if int(value) != expected[i] {
39 t.Fatalf("TryReadInt8 FAIL for index %d: Expected %d, Got %d", i, expected[i], value)
40 }
41 }
42}
43
44func TestTryReadInt16(t *testing.T) {
45 bitreader := Reader(bytes.NewReader(TestArray[:]), false)
46 expected := []int{28941, 0, 41499, 0}
47 for i := range expected {
48 value := bitreader.TryReadInt16()
49 if int(value) != expected[i] {
50 t.Fatalf("TryReadInt16 FAIL for index %d: Expected %d, Got %d", i, expected[i], value)
51 }
52 }
53}
54
55func TestTryReadInt32(t *testing.T) {
56 bitreader := Reader(bytes.NewReader(TestArray[:]), false)
57 expected := []int{1896677376, 2719678464}
58 for i := range expected {
59 value := bitreader.TryReadInt32()
60 if int(value) != expected[i] {
61 t.Fatalf("TryReadInt32 FAIL for index %d: Expected %d, Got %d", i, expected[i], value)
62 }
63 }
64}
65
66func TestTryReadInt64(t *testing.T) {
67 bitreader := Reader(bytes.NewReader(TestArray[:]), false)
68 expected := []int{8146167303702773760}
69 for i := range expected {
70 value := bitreader.TryReadInt64()
71 if int(value) != expected[i] {
72 t.Fatalf("TryReadInt64 FAIL for index %d: Expected %d, Got %d", i, expected[i], value)
73 }
74 }
75}
76
10func TestReadBit(t *testing.T) { 77func TestReadBit(t *testing.T) {
11 bitreader := Reader(TestArray[:], false) 78 bitreader := Reader(bytes.NewReader(TestArray[:]), false)
12 expected := []bool{false, true, true, true} 79 expected := []bool{false, true, true, true}
13 for i := range expected { 80 for i := range expected {
14 value, err := bitreader.ReadBit() 81 value, err := bitreader.ReadBool()
15 if err != nil { 82 if err != nil {
16 t.Fatal(err) 83 t.Fatal(err)
17 } 84 }
@@ -22,27 +89,27 @@ func TestReadBit(t *testing.T) {
22} 89}
23 90
24func TestReadBitLE(t *testing.T) { 91func TestReadBitLE(t *testing.T) {
25 bitreader := Reader(TestArray[:], true) 92 bitreader := Reader(bytes.NewReader(TestArray[:]), true)
26 expected := []bool{true, false, false, false} 93 expected := []bool{true, false, false, false}
27 for i := range expected { 94 for i := range expected {
28 value, err := bitreader.ReadBit() 95 value, err := bitreader.ReadBool()
29 if err != nil { 96 if err != nil {
30 t.Fatal(err) 97 t.Fatal(err)
31 } 98 }
32 if value != expected[i] { 99 if value != expected[i] {
33 t.Fatalf("ReadBitLSB FAIL for index %d: Expected %t, Got %t", i, expected[i], value) 100 t.Fatalf("ReadBitLE FAIL for index %d: Expected %t, Got %t", i, expected[i], value)
34 } 101 }
35 } 102 }
36} 103}
37 104
38func TestReadBits32(t *testing.T) { 105func TestReadBits(t *testing.T) {
39 bitreader := Reader(TestArray[:], false) 106 bitreader := Reader(bytes.NewReader(TestArray[:]), false)
40 expected := []int{3793354753, 2288779267} // 11100010000110100000000000000001, 10001000011011000000000000000011 107 expected := []int{3793354753, 2288779267} // 11100010000110100000000000000001, 10001000011011000000000000000011
41 expectedBool := []bool{false, false} 108 expectedBool := []bool{false, false}
42 for i := range expected { 109 for i := range expected {
43 bool, err := bitreader.ReadBit() 110 bool, err := bitreader.ReadBool()
44 if bool != expectedBool[i] { 111 if bool != expectedBool[i] {
45 t.Fatalf("ReadBits32 ReadBit FAIL for index %d: Expected %t, Got %t", i, expectedBool[i], bool) 112 t.Fatalf("ReadBits ReadBit FAIL for index %d: Expected %t, Got %t", i, expectedBool[i], bool)
46 } 113 }
47 if err != nil { 114 if err != nil {
48 t.Fatal(err) 115 t.Fatal(err)
@@ -51,36 +118,73 @@ func TestReadBits32(t *testing.T) {
51 if err != nil { 118 if err != nil {
52 t.Fatal(err) 119 t.Fatal(err)
53 } 120 }
54 if value != expected[i] { 121 if int(value) != expected[i] {
55 t.Fatalf("ReadBits32 FAIL for index %d: Expected %d, Got %d", i, expected[i], value) 122 t.Fatalf("ReadBits FAIL for index %d: Expected %d, Got %d", i, expected[i], value)
56 } 123 }
57 } 124 }
58} 125}
59 126
60func TestReadBitsLE(t *testing.T) { 127func TestReadBitsLE(t *testing.T) {
61 bitreader := Reader(TestArray[:], true) 128 bitreader := Reader(bytes.NewReader(TestArray[:]), true)
62 expected := []int{1720, 1768} // 11010111000, 11011101000 129 expected := []int{1720, 1768} // 11010111000, 11011101000
63 for i := range expected { 130 for i := range expected {
64 bitreader.ReadBit() 131 bitreader.ReadBool()
65 value, err := bitreader.ReadBits(32) 132 value, err := bitreader.ReadBits(32)
66 if err != nil { 133 if err != nil {
67 t.Fatal(err) 134 t.Fatal(err)
68 } 135 }
69 if value != expected[i] { 136 if int(value) != expected[i] {
70 t.Fatalf("ReadBits32LSB FAIL for index %d: Expected %d, Got %d", i, expected[i], value) 137 t.Fatalf("ReadBitsLE FAIL for index %d: Expected %d, Got %d", i, expected[i], value)
138 }
139 }
140}
141
142func TestReadBytes(t *testing.T) {
143 bitreader := Reader(bytes.NewReader(TestArray[:]), false)
144 expected := []int{3793354753, 2288779267} // 11100010000110100000000000000001, 10001000011011000000000000000011
145 expectedBool := []bool{false, false}
146 for i := range expected {
147 bool, err := bitreader.ReadBool()
148 if bool != expectedBool[i] {
149 t.Fatalf("ReadBytes ReadBit FAIL for index %d: Expected %t, Got %t", i, expectedBool[i], bool)
150 }
151 if err != nil {
152 t.Fatal(err)
153 }
154 value, err := bitreader.ReadBytes(4)
155 if err != nil {
156 t.Fatal(err)
157 }
158 if int(value) != expected[i] {
159 t.Fatalf("ReadBytes FAIL for index %d: Expected %d, Got %d", i, expected[i], value)
160 }
161 }
162}
163
164func TestReadBytesLE(t *testing.T) {
165 bitreader := Reader(bytes.NewReader(TestArray[:]), true)
166 expected := []int{1720, 1768} // 11010111000, 11011101000
167 for i := range expected {
168 bitreader.ReadBool()
169 value, err := bitreader.ReadBytes(4)
170 if err != nil {
171 t.Fatal(err)
172 }
173 if int(value) != expected[i] {
174 t.Fatalf("ReadBytesLE FAIL for index %d: Expected %d, Got %d", i, expected[i], value)
71 } 175 }
72 } 176 }
73} 177}
74 178
75func TestSkipBits(t *testing.T) { 179func TestSkipBits(t *testing.T) {
76 bitreader := Reader(TestArray[:], false) 180 bitreader := Reader(bytes.NewReader(TestArray[:]), false)
77 expected := []bool{true, true, false, true} //00001101 181 expected := []bool{true, true, false, true} //00001101
78 err := bitreader.SkipBits(12) 182 err := bitreader.SkipBits(12)
79 if err != nil { 183 if err != nil {
80 t.Fatal(err) 184 t.Fatal(err)
81 } 185 }
82 for i := range expected { 186 for i := range expected {
83 value, err := bitreader.ReadBit() 187 value, err := bitreader.ReadBool()
84 if err != nil { 188 if err != nil {
85 t.Fatal(err) 189 t.Fatal(err)
86 } 190 }
@@ -91,16 +195,16 @@ func TestSkipBits(t *testing.T) {
91} 195}
92 196
93func TestSkipBitsLE(t *testing.T) { 197func TestSkipBitsLE(t *testing.T) {
94 bitreader := Reader(TestArray[:], true) 198 bitreader := Reader(bytes.NewReader(TestArray[:]), true)
95 expected := []bool{false, false, false, false} //10110000 199 expected := []bool{false, false, false, false} //10110000
96 bitreader.SkipBits(12) 200 bitreader.SkipBits(12)
97 for i := range expected { 201 for i := range expected {
98 value, err := bitreader.ReadBit() 202 value, err := bitreader.ReadBool()
99 if err != nil { 203 if err != nil {
100 t.Fatal(err) 204 t.Fatal(err)
101 } 205 }
102 if value != expected[i] { 206 if value != expected[i] {
103 t.Fatalf("SkipBits ReadBit FAIL for index %d: Expected %t, Got %t", i, expected[i], value) 207 t.Fatalf("SkipBitsLE ReadBit FAIL for index %d: Expected %t, Got %t", i, expected[i], value)
104 } 208 }
105 } 209 }
106} 210}