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 | |
| download | bitreader-4a09f5844cb1649ecbdfec260628285cfcd640ec.tar.gz bitreader-4a09f5844cb1649ecbdfec260628285cfcd640ec.tar.bz2 bitreader-4a09f5844cb1649ecbdfec260628285cfcd640ec.zip | |
init - first full version
| -rw-r--r-- | LICENSE | 21 | ||||
| -rw-r--r-- | README.md | 1 | ||||
| -rw-r--r-- | bitreader.go | 129 | ||||
| -rw-r--r-- | bitreader_test.go | 103 | ||||
| -rw-r--r-- | go.mod | 3 |
5 files changed, 257 insertions, 0 deletions
| @@ -0,0 +1,21 @@ | |||
| 1 | MIT License | ||
| 2 | |||
| 3 | Copyright (c) 2022 Arda Serdar Pektezol | ||
| 4 | |||
| 5 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | of this software and associated documentation files (the "Software"), to deal | ||
| 7 | in the Software without restriction, including without limitation the rights | ||
| 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | copies of the Software, and to permit persons to whom the Software is | ||
| 10 | furnished to do so, subject to the following conditions: | ||
| 11 | |||
| 12 | The above copyright notice and this permission notice shall be included in all | ||
| 13 | copies or substantial portions of the Software. | ||
| 14 | |||
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | SOFTWARE. \ No newline at end of file | ||
diff --git a/README.md b/README.md new file mode 100644 index 0000000..a493a1f --- /dev/null +++ b/README.md | |||
| @@ -0,0 +1 @@ | |||
| # BitReader | |||
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 | } | ||
diff --git a/bitreader_test.go b/bitreader_test.go new file mode 100644 index 0000000..c29a3bd --- /dev/null +++ b/bitreader_test.go | |||
| @@ -0,0 +1,103 @@ | |||
| 1 | package main | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "testing" | ||
| 5 | ) | ||
| 6 | |||
| 7 | // 01110001, 00001101, 00000000, 00000000, 10100010, 00011011, 00000000, 00000000, 11001100 | ||
| 8 | var TestArray = [...]byte{113, 13, 0, 0, 162, 27, 0, 0, 204} | ||
| 9 | |||
| 10 | func TestReadBit(t *testing.T) { | ||
| 11 | bitreader := Reader(TestArray[:]) | ||
| 12 | expected := []bool{false, true, true, true} | ||
| 13 | for i := range expected { | ||
| 14 | value, err := bitreader.ReadBit() | ||
| 15 | if err != nil { | ||
| 16 | t.Fatal(err) | ||
| 17 | } | ||
| 18 | if value != expected[i] { | ||
| 19 | t.Fatalf("ReadBit FAIL for index %d: Expected %t, Got %t", i, expected[i], value) | ||
| 20 | } | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | func TestReadBitLSB(t *testing.T) { | ||
| 25 | bitreader := ReaderLSB(TestArray[:]) | ||
| 26 | expected := []bool{true, false, false, false} | ||
| 27 | for i := range expected { | ||
| 28 | value, err := bitreader.ReadBit() | ||
| 29 | if err != nil { | ||
| 30 | t.Fatal(err) | ||
| 31 | } | ||
| 32 | if value != expected[i] { | ||
| 33 | t.Fatalf("ReadBitLSB FAIL for index %d: Expected %t, Got %t", i, expected[i], value) | ||
| 34 | } | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 38 | func TestReadBits32(t *testing.T) { | ||
| 39 | bitreader := Reader(TestArray[:]) | ||
| 40 | expected := []int{3793354753, 2288779267} // 11100010000110100000000000000001, 10001000011011000000000000000011 | ||
| 41 | expectedBool := []bool{false, false} | ||
| 42 | for i := range expected { | ||
| 43 | bool, err := bitreader.ReadBit() | ||
| 44 | if bool != expectedBool[i] { | ||
| 45 | t.Fatalf("ReadBits32 ReadBit FAIL for index %d: Expected %t, Got %t", i, expectedBool[i], bool) | ||
| 46 | } | ||
| 47 | if err != nil { | ||
| 48 | t.Fatal(err) | ||
| 49 | } | ||
| 50 | value, err := bitreader.ReadBits32(32) | ||
| 51 | if err != nil { | ||
| 52 | t.Fatal(err) | ||
| 53 | } | ||
| 54 | if value != expected[i] { | ||
| 55 | t.Fatalf("ReadBits32 FAIL for index %d: Expected %d, Got %d", i, expected[i], value) | ||
| 56 | } | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | func TestReadBits32LSB(t *testing.T) { | ||
| 61 | bitreader := ReaderLSB(TestArray[:]) | ||
| 62 | expected := []int{1720, 1768} // 11010111000, 11011101000 | ||
| 63 | for i := range expected { | ||
| 64 | bitreader.ReadBit() | ||
| 65 | value, err := bitreader.ReadBits32(32) | ||
| 66 | if err != nil { | ||
| 67 | t.Fatal(err) | ||
| 68 | } | ||
| 69 | if value != expected[i] { | ||
| 70 | t.Fatalf("ReadBits32LSB FAIL for index %d: Expected %d, Got %d", i, expected[i], value) | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | func TestSkipBits(t *testing.T) { | ||
| 76 | bitreader := Reader(TestArray[:]) | ||
| 77 | expected := []bool{true, true, false, true} //00001101 | ||
| 78 | bitreader.SkipBits(12) | ||
| 79 | for i := range expected { | ||
| 80 | value, err := bitreader.ReadBit() | ||
| 81 | if err != nil { | ||
| 82 | t.Fatal(err) | ||
| 83 | } | ||
| 84 | if value != expected[i] { | ||
| 85 | t.Fatalf("SkipBits ReadBit FAIL for index %d: Expected %t, Got %t", i, expected[i], value) | ||
| 86 | } | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | func TestSkipBitsLSB(t *testing.T) { | ||
| 91 | bitreader := ReaderLSB(TestArray[:]) | ||
| 92 | expected := []bool{false, false, false, false} //10110000 | ||
| 93 | bitreader.SkipBits(12) | ||
| 94 | for i := range expected { | ||
| 95 | value, err := bitreader.ReadBit() | ||
| 96 | if err != nil { | ||
| 97 | t.Fatal(err) | ||
| 98 | } | ||
| 99 | if value != expected[i] { | ||
| 100 | t.Fatalf("SkipBits ReadBit FAIL for index %d: Expected %t, Got %t", i, expected[i], value) | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| @@ -0,0 +1,3 @@ | |||
| 1 | module github.com/bisaxa/bitreader | ||
| 2 | |||
| 3 | go 1.19 | ||