diff options
| author | BiSaXa <1669855+BiSaXa@users.noreply.github.com> | 2022-09-04 01:07:28 +0300 |
|---|---|---|
| committer | BiSaXa <1669855+BiSaXa@users.noreply.github.com> | 2022-09-04 01:07:28 +0300 |
| commit | 4a09f5844cb1649ecbdfec260628285cfcd640ec (patch) | |
| tree | 7d1a4f31d0771467f0ae0db3444d3545fc3fbfe7 /bitreader.go | |
| download | bitreader-4a09f5844cb1649ecbdfec260628285cfcd640ec.tar.gz bitreader-4a09f5844cb1649ecbdfec260628285cfcd640ec.tar.bz2 bitreader-4a09f5844cb1649ecbdfec260628285cfcd640ec.zip | |
init - first full version
Diffstat (limited to 'bitreader.go')
| -rw-r--r-- | bitreader.go | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/bitreader.go b/bitreader.go new file mode 100644 index 0000000..9d9a273 --- /dev/null +++ b/bitreader.go | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | package main | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "fmt" | ||
| 5 | "math/bits" | ||
| 6 | "strconv" | ||
| 7 | "strings" | ||
| 8 | ) | ||
| 9 | |||
| 10 | type ReaderType struct { | ||
| 11 | data []byte | ||
| 12 | base int | ||
| 13 | index int | ||
| 14 | lsb bool | ||
| 15 | } | ||
| 16 | |||
| 17 | func Reader(data []byte) *ReaderType { | ||
| 18 | return &ReaderType{ | ||
| 19 | data: data, | ||
| 20 | base: 0, | ||
| 21 | index: 0, | ||
| 22 | lsb: false, | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | func ReaderLSB(data []byte) *ReaderType { | ||
| 27 | dataReversed := data | ||
| 28 | for index, byteValue := range data { | ||
| 29 | dataReversed[index] = bits.Reverse8(byteValue) | ||
| 30 | } | ||
| 31 | return &ReaderType{ | ||
| 32 | data: dataReversed, | ||
| 33 | base: 0, | ||
| 34 | index: 0, | ||
| 35 | lsb: true, | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | func (reader *ReaderType) SkipBits(bits int) error { | ||
| 40 | if bits <= 0 { | ||
| 41 | return fmt.Errorf("SkipBits Error: Bits value %d lower or equals than 0.", bits) | ||
| 42 | } | ||
| 43 | for reader.index+bits > 7 { | ||
| 44 | reader.base++ | ||
| 45 | reader.index = 0 | ||
| 46 | bits -= 8 | ||
| 47 | } | ||
| 48 | reader.index += bits | ||
| 49 | return nil | ||
| 50 | } | ||
| 51 | |||
| 52 | func (reader *ReaderType) ReadBits32(bits int) (int, error) { | ||
| 53 | if bits <= 0 { | ||
| 54 | return -1, fmt.Errorf("ReadBits Error: Bits value %d lower or equals than 0.", bits) | ||
| 55 | } | ||
| 56 | if bits > 32 { | ||
| 57 | return -1, fmt.Errorf("ReadBits Error: Bits value %d higher than 32.", bits) | ||
| 58 | } | ||
| 59 | err := reader.checkAvailableBits(bits) | ||
| 60 | if err != nil { | ||
| 61 | return -1, err | ||
| 62 | } | ||
| 63 | if reader.lsb { | ||
| 64 | var output string | ||
| 65 | // Go to last bit and read backwards from there | ||
| 66 | reader.base += bits / 8 | ||
| 67 | reader.index += bits % 8 | ||
| 68 | if reader.index > 7 { | ||
| 69 | reader.index -= 8 | ||
| 70 | reader.base++ | ||
| 71 | } | ||
| 72 | for i := 0; i < bits; i++ { | ||
| 73 | reader.index-- | ||
| 74 | if reader.index < 0 { | ||
| 75 | reader.base-- | ||
| 76 | reader.index = 7 | ||
| 77 | } | ||
| 78 | binary := fmt.Sprintf("%08b", reader.data[reader.base]) | ||
| 79 | binaryArr := strings.Split(binary, "") | ||
| 80 | output += binaryArr[reader.index] | ||
| 81 | } | ||
| 82 | // Return to last bit after reading | ||
| 83 | reader.base += bits / 8 | ||
| 84 | reader.index += bits % 8 | ||
| 85 | if reader.index > 7 { | ||
| 86 | reader.index -= 8 | ||
| 87 | } | ||
| 88 | // Conversion of string binary to int | ||
| 89 | value, err := strconv.ParseUint(output, 2, 32) | ||
| 90 | if err != nil { | ||
| 91 | return -1, fmt.Errorf("%s", err) | ||
| 92 | } | ||
| 93 | return int(value), nil | ||
| 94 | } else { | ||
| 95 | var output string | ||
| 96 | for i := 0; i < bits; i++ { | ||
| 97 | binary := fmt.Sprintf("%08b", reader.data[reader.base]) | ||
| 98 | binaryArr := strings.Split(binary, "") | ||
| 99 | output += binaryArr[reader.index] | ||
| 100 | reader.index++ | ||
| 101 | if reader.index > 7 { | ||
| 102 | reader.base++ | ||
| 103 | reader.index = 0 | ||
| 104 | } | ||
| 105 | } | ||
| 106 | // Conversion of string binary to int | ||
| 107 | value, err := strconv.ParseUint(output, 2, 32) | ||
| 108 | if err != nil { | ||
| 109 | return -1, fmt.Errorf("%s", err) | ||
| 110 | } | ||
| 111 | return int(value), nil | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | func (reader *ReaderType) ReadBit() (bool, error) { | ||
| 116 | value, err := reader.ReadBits32(1) | ||
| 117 | if err != nil { | ||
| 118 | return false, fmt.Errorf("ReadBit Error: %s", err) | ||
| 119 | } | ||
| 120 | return value != 0, nil | ||
| 121 | } | ||
| 122 | |||
| 123 | func (reader *ReaderType) checkAvailableBits(bits int) error { | ||
| 124 | availableBits := (len(reader.data)-reader.base)*8 - reader.index | ||
| 125 | if availableBits < bits { | ||
| 126 | return fmt.Errorf("BitReaderOutOfBounds: Wanted to read %d bit(s) but only %d bit(s) is/are available.", bits, availableBits) | ||
| 127 | } | ||
| 128 | return nil | ||
| 129 | } | ||