Last active
October 9, 2017 22:06
-
-
Save StandoffVenus/f858c4f52a9cbc3c0c722c985cf2b993 to your computer and use it in GitHub Desktop.
Add comment about error catching.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"io" | |
"bytes" | |
"fmt" | |
) | |
type PlainBitReader struct { | |
reader io.ByteReader | |
byte byte | |
offset uint8 | |
} | |
// Simple new method to return new instance | |
func NewPlainBitReader(reader io.ByteReader) *PlainBitReader { | |
return &PlainBitReader{reader, 0, 0} | |
} | |
// We may encounter a read error from our reader. | |
// If so, we'll return that and the returned bit is considered invalid. | |
func (bitReader *PlainBitReader) ReadBit() (bool, error) { | |
if (bitReader.offset == 8) { bitReader.offset = 0 } | |
// Get next byte | |
if (bitReader.offset == 0) { | |
var err error | |
bitReader.byte, err = bitReader.reader.ReadByte() | |
if (err != nil) { | |
return false, err | |
} | |
} | |
// Compare current byte to 10000000 shifted right bitReader.offset times | |
bit := bitReader.byte & (0x80 >> bitReader.offset) | |
// Increment our offset | |
bitReader.offset++ | |
// Comparison will turn byte to boolean, and no error is returned | |
return bit != 0, nil | |
} | |
// We may encounter errors again, so we'll perform the same behavior as last time. | |
func (bitReader *PlainBitReader) ReadBits(bits int64) (uint64, error) { | |
var bitRange uint64 | |
// Read from bits - 1 to 0 | |
for i := bits - 1; i >= 0; i-- { | |
bit, err := bitReader.ReadBit() | |
if (err != nil) { return uint64(0), err } | |
if (bit) { | |
// xxxxxxxxx | |
// 1 << bits - 1 - amount of iterations | |
// Compared via OR. | |
// We're altering each individual bit of our uint64 each iteration, essentially. | |
bitRange |= (1 << uint64(i)) | |
} | |
} | |
return bitRange, nil | |
} | |
func main() { | |
// Bytes: | |
// 11111111 == 256 | |
// 00000000 == 0 | |
// 00001111 == 15 | |
bits := []byte { 0xFF, 0x00, 0x0F } | |
bitReader := NewPlainBitReader(bytes.NewBuffer(bits)) | |
// Read first 6 bits of our byte buffer. | |
// Bits: 111111 (== 63) | |
uintValue, err := bitReader.ReadBits(6) | |
// Error catching | |
// For brevity, I omitted the rest of these | |
if (err != nil) { panic(err) } | |
fmt.Println(uintValue) | |
// Read next 10 bits. | |
// Bits: 1100000000 (== 768) | |
uintValue, _ = bitReader.ReadBits(10) | |
fmt.Println(uintValue) | |
// Read next 4 bits. | |
// Bits: 0000 (== 0, obviously) | |
uintValue, _ = bitReader.ReadBits(4) | |
fmt.Println(uintValue) | |
// Read last 4 bits. | |
// Bits: 1111 (== 15) | |
uintValue, _ = bitReader.ReadBits(4) | |
fmt.Println(uintValue) | |
// Output: | |
// 63 | |
// 768 | |
// 0 | |
// 15 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment