diff options
| author | BiSaXa <1669855+BiSaXa@users.noreply.github.com> | 2022-09-05 11:51:18 +0300 |
|---|---|---|
| committer | BiSaXa <1669855+BiSaXa@users.noreply.github.com> | 2022-09-05 11:51:18 +0300 |
| commit | 42560481fa737e156c4b5e56561519b1be8468a9 (patch) | |
| tree | c62fe4b443a33d1700cd139c685d8cd2be4ed378 /bitreader.go | |
| parent | Merge branch 'main' of https://github.com/BiSaXa/BitReader (diff) | |
| download | bitreader-42560481fa737e156c4b5e56561519b1be8468a9.tar.gz bitreader-42560481fa737e156c4b5e56561519b1be8468a9.tar.bz2 bitreader-42560481fa737e156c4b5e56561519b1be8468a9.zip | |
v2 init
Diffstat (limited to '')
| -rw-r--r-- | bitreader.go | 221 |
1 files changed, 128 insertions, 93 deletions
diff --git a/bitreader.go b/bitreader.go index 06374b8..7e22ba6 100644 --- a/bitreader.go +++ b/bitreader.go | |||
| @@ -1,48 +1,96 @@ | |||
| 1 | package bitreader | 1 | // paksd |
| 2 | package main | ||
| 2 | 3 | ||
| 3 | import ( | 4 | import ( |
| 4 | "fmt" | 5 | "fmt" |
| 5 | "math/bits" | 6 | "io" |
| 6 | "strconv" | 7 | "math" |
| 7 | "strings" | ||
| 8 | ) | 8 | ) |
| 9 | 9 | ||
| 10 | type ReaderType struct { | 10 | type ReaderType struct { |
| 11 | data []byte // Reader data from a byte array | 11 | stream io.Reader // the underlying stream we're reading bytes from |
| 12 | base int // Current reader byte location | 12 | index uint8 // 0-7, the current index into the byte |
| 13 | index int // Current reader index | 13 | curByte byte // the byte we're currently reading from |
| 14 | le bool // Little endian or big endian? | 14 | le bool // whether to read in little-endian order |
| 15 | // Whenever index == 0, we need to read a new byte from stream into curByte | ||
| 15 | } | 16 | } |
| 16 | 17 | ||
| 17 | func Reader(data []byte, le bool) *ReaderType { | 18 | func Reader(stream io.Reader, le bool) *ReaderType { |
| 18 | dataClone := data | ||
| 19 | if le { | ||
| 20 | for index, byteValue := range data { | ||
| 21 | dataClone[index] = bits.Reverse8(byteValue) | ||
| 22 | } | ||
| 23 | } | ||
| 24 | return &ReaderType{ | 19 | return &ReaderType{ |
| 25 | data: dataClone, | 20 | stream: stream, |
| 26 | base: 0, | 21 | index: 0, |
| 27 | index: 0, | 22 | curByte: 0, // initial value doesn't matter, it'll be read as soon as we try to read any bits |
| 28 | le: le, | 23 | le: le, |
| 29 | } | 24 | } |
| 30 | } | 25 | } |
| 31 | 26 | ||
| 32 | func (reader *ReaderType) SkipBits(bits int) error { | 27 | func (reader *ReaderType) TryReadInt8() (uint8, error) { |
| 33 | if bits <= 0 { | 28 | value, err := reader.ReadBits(8) |
| 34 | return fmt.Errorf("SkipBits Error: Bits value %d lower or equals than 0.", bits) | 29 | if err != nil { |
| 30 | return 0, err | ||
| 31 | } | ||
| 32 | return uint8(value), nil | ||
| 33 | } | ||
| 34 | |||
| 35 | func (reader *ReaderType) TryReadInt16() (uint16, error) { | ||
| 36 | value, err := reader.ReadBits(16) | ||
| 37 | if err != nil { | ||
| 38 | return 0, err | ||
| 35 | } | 39 | } |
| 36 | err := reader.checkAvailableBits(bits) | 40 | return uint16(value), nil |
| 41 | } | ||
| 42 | |||
| 43 | func (reader *ReaderType) TryReadInt32() (uint32, error) { | ||
| 44 | value, err := reader.ReadBits(32) | ||
| 45 | if err != nil { | ||
| 46 | return 0, err | ||
| 47 | } | ||
| 48 | return uint32(value), nil | ||
| 49 | } | ||
| 50 | |||
| 51 | func (reader *ReaderType) TryReadInt64() (uint64, error) { | ||
| 52 | value, err := reader.ReadBits(64) | ||
| 53 | if err != nil { | ||
| 54 | return 0, err | ||
| 55 | } | ||
| 56 | return value, nil | ||
| 57 | } | ||
| 58 | |||
| 59 | func (reader *ReaderType) TryReadFloat32() (float32, error) { | ||
| 60 | value, err := reader.ReadBits(32) | ||
| 61 | if err != nil { | ||
| 62 | return 0, err | ||
| 63 | } | ||
| 64 | return math.Float32frombits(uint32(value)), nil | ||
| 65 | } | ||
| 66 | |||
| 67 | func (reader *ReaderType) TryReadFloat64() (float64, error) { | ||
| 68 | value, err := reader.ReadBits(64) | ||
| 69 | if err != nil { | ||
| 70 | return 0, err | ||
| 71 | } | ||
| 72 | return math.Float64frombits(value), nil | ||
| 73 | } | ||
| 74 | |||
| 75 | func (reader *ReaderType) SkipBits(bits int) error { | ||
| 76 | // read as many raw bytes as we can | ||
| 77 | bytes := bits / 8 | ||
| 78 | buf := make([]byte, bytes) | ||
| 79 | _, err := reader.stream.Read(buf) | ||
| 37 | if err != nil { | 80 | if err != nil { |
| 38 | return err | 81 | return err |
| 39 | } | 82 | } |
| 40 | for reader.index+bits > 7 { | 83 | // the final read byte should be the new current byte |
| 41 | reader.base++ | 84 | if bytes > 0 { |
| 42 | reader.index = 0 | 85 | reader.curByte = buf[bytes-1] |
| 43 | bits -= 8 | 86 | } |
| 87 | // read the extra bits | ||
| 88 | for i := bytes * 8; i < bits; i++ { | ||
| 89 | _, err := reader.readBit() | ||
| 90 | if err != nil { | ||
| 91 | return err | ||
| 92 | } | ||
| 44 | } | 93 | } |
| 45 | reader.index += bits | ||
| 46 | return nil | 94 | return nil |
| 47 | } | 95 | } |
| 48 | 96 | ||
| @@ -54,81 +102,68 @@ func (reader *ReaderType) SkipBytes(bytes int) error { | |||
| 54 | return nil | 102 | return nil |
| 55 | } | 103 | } |
| 56 | 104 | ||
| 57 | func (reader *ReaderType) ReadBits(bits int) (int, error) { | 105 | // Read up to 64 bits from the stream |
| 58 | if bits <= 0 { | 106 | func (reader *ReaderType) ReadBits(bits int) (uint64, error) { |
| 59 | return -1, fmt.Errorf("ReadBits Error: Bits value %d lower or equals than 0.", bits) | 107 | if bits < 1 || bits > 64 { |
| 60 | } | 108 | return 0, fmt.Errorf("ReadBits(bits) ERROR: Bits number should be between 1 and 64.") |
| 61 | if bits > 64 { | ||
| 62 | return -1, fmt.Errorf("ReadBits Error: Bits value %d higher than 64.", bits) | ||
| 63 | } | 109 | } |
| 64 | err := reader.checkAvailableBits(bits) | 110 | var val uint64 |
| 65 | if err != nil { | 111 | for i := 0; i < bits; i++ { |
| 66 | return -1, err | 112 | 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 { | 113 | if err != nil { |
| 96 | return -1, fmt.Errorf("%s", err) | 114 | return 0, err |
| 97 | } | 115 | } |
| 98 | return int(value), nil | 116 | |
| 99 | } else { | 117 | if reader.le { |
| 100 | var output string | 118 | val |= uint64(bit) << i |
| 101 | for i := 0; i < bits; i++ { | 119 | } else { |
| 102 | binary := fmt.Sprintf("%08b", reader.data[reader.base]) | 120 | val |= uint64(bit) << (bits - 1 - i) |
| 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 | } | ||
| 111 | // Conversion of string binary to int | ||
| 112 | value, err := strconv.ParseUint(output, 2, 64) | ||
| 113 | if err != nil { | ||
| 114 | return -1, fmt.Errorf("%s", err) | ||
| 115 | } | 121 | } |
| 116 | return int(value), nil | ||
| 117 | } | 122 | } |
| 123 | return val, nil | ||
| 118 | } | 124 | } |
| 119 | 125 | ||
| 120 | func (reader *ReaderType) ReadBit() (bool, error) { | 126 | func (reader *ReaderType) ReadBytes(bytes int) (uint64, error) { |
| 121 | value, err := reader.ReadBits(1) | 127 | if bytes < 1 || bytes > 8 { |
| 128 | return 0, fmt.Errorf("ReadBytes(bytes) ERROR: Bytes number should be between 1 and 8.") | ||
| 129 | } | ||
| 130 | value, err := reader.ReadBits(bytes * 8) | ||
| 122 | if err != nil { | 131 | if err != nil { |
| 123 | return false, fmt.Errorf("ReadBit Error: %s", err) | 132 | return 0, err |
| 124 | } | 133 | } |
| 125 | return value != 0, nil | 134 | return value, nil |
| 126 | } | 135 | } |
| 127 | 136 | ||
| 128 | func (reader *ReaderType) checkAvailableBits(bits int) error { | 137 | // Read a single bool from the stream |
| 129 | availableBits := (len(reader.data)-reader.base)*8 - reader.index | 138 | func (reader *ReaderType) ReadBool() (bool, error) { |
| 130 | if availableBits < bits { | 139 | val, err := reader.readBit() |
| 131 | return fmt.Errorf("BitReaderOutOfBounds: Wanted to read/skip %d bit(s) but only %d bit(s) is/are available.", bits, availableBits) | 140 | if err != nil { |
| 141 | return false, err | ||
| 142 | } | ||
| 143 | return val == 1, nil | ||
| 144 | } | ||
| 145 | |||
| 146 | // Read a single bit from the stream | ||
| 147 | func (reader *ReaderType) readBit() (uint8, error) { | ||
| 148 | if reader.index == 0 { | ||
| 149 | // read a byte from stream into curByte | ||
| 150 | buf := make([]byte, 1) | ||
| 151 | _, err := reader.stream.Read(buf) | ||
| 152 | if err != nil { | ||
| 153 | return 0, err | ||
| 154 | } | ||
| 155 | reader.curByte = buf[0] | ||
| 156 | } | ||
| 157 | var val bool | ||
| 158 | if reader.le { | ||
| 159 | val = (reader.curByte & (1 << reader.index)) != 0 | ||
| 160 | } else { | ||
| 161 | val = (reader.curByte & (1 << (7 - reader.index))) != 0 | ||
| 162 | } | ||
| 163 | reader.index = (reader.index + 1) % 8 | ||
| 164 | if val { | ||
| 165 | return 1, nil | ||
| 166 | } else { | ||
| 167 | return 0, nil | ||
| 132 | } | 168 | } |
| 133 | return nil | ||
| 134 | } | 169 | } |