diff options
Diffstat (limited to 'bitreader.go')
| -rw-r--r-- | bitreader.go | 281 |
1 files changed, 189 insertions, 92 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! | ||
| 1 | package bitreader | 8 | package bitreader |
| 2 | 9 | ||
| 3 | import ( | 10 | import ( |
| 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 | ||
| 10 | type ReaderType struct { | 18 | type 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 | ||
| 17 | func 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 { | 27 | func 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 | ||
| 32 | func (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) | 38 | func (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. | ||
| 48 | func (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. | ||
| 58 | func (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. | ||
| 68 | func (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. | ||
| 78 | func (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. | ||
| 88 | func (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. | ||
| 98 | func (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. | ||
| 108 | func (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. | ||
| 119 | func (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. | ||
| 49 | func (reader *ReaderType) SkipBytes(bytes int) error { | 144 | func (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 | ||
| 57 | func (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. |
| 158 | func (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 | ||
| 120 | func (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. | ||
| 184 | func (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 | ||
| 128 | func (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. |
| 199 | func (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. | ||
| 209 | func (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 | } |