From 42560481fa737e156c4b5e56561519b1be8468a9 Mon Sep 17 00:00:00 2001 From: BiSaXa <1669855+BiSaXa@users.noreply.github.com> Date: Mon, 5 Sep 2022 11:51:18 +0300 Subject: v2 init --- bitreader.go | 221 ++++++++++++++++++++++++++++++++++------------------------- 1 file 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 @@ -package bitreader +// paksd +package main import ( "fmt" - "math/bits" - "strconv" - "strings" + "io" + "math" ) type ReaderType struct { - data []byte // Reader data from a byte array - base int // Current reader byte location - index int // Current reader index - le bool // Little endian or big endian? + stream io.Reader // the underlying stream we're reading bytes from + index uint8 // 0-7, the current index into the byte + curByte byte // the byte we're currently reading from + le bool // whether to read in little-endian order + // Whenever index == 0, we need to read a new byte from stream into curByte } -func Reader(data []byte, le bool) *ReaderType { - dataClone := data - if le { - for index, byteValue := range data { - dataClone[index] = bits.Reverse8(byteValue) - } - } +func Reader(stream io.Reader, le bool) *ReaderType { return &ReaderType{ - data: dataClone, - base: 0, - index: 0, - le: le, + stream: stream, + index: 0, + curByte: 0, // initial value doesn't matter, it'll be read as soon as we try to read any bits + le: le, } } -func (reader *ReaderType) SkipBits(bits int) error { - if bits <= 0 { - return fmt.Errorf("SkipBits Error: Bits value %d lower or equals than 0.", bits) +func (reader *ReaderType) TryReadInt8() (uint8, error) { + value, err := reader.ReadBits(8) + if err != nil { + return 0, err + } + return uint8(value), nil +} + +func (reader *ReaderType) TryReadInt16() (uint16, error) { + value, err := reader.ReadBits(16) + if err != nil { + return 0, err } - err := reader.checkAvailableBits(bits) + return uint16(value), nil +} + +func (reader *ReaderType) TryReadInt32() (uint32, error) { + value, err := reader.ReadBits(32) + if err != nil { + return 0, err + } + return uint32(value), nil +} + +func (reader *ReaderType) TryReadInt64() (uint64, error) { + value, err := reader.ReadBits(64) + if err != nil { + return 0, err + } + return value, nil +} + +func (reader *ReaderType) TryReadFloat32() (float32, error) { + value, err := reader.ReadBits(32) + if err != nil { + return 0, err + } + return math.Float32frombits(uint32(value)), nil +} + +func (reader *ReaderType) TryReadFloat64() (float64, error) { + value, err := reader.ReadBits(64) + if err != nil { + return 0, err + } + return math.Float64frombits(value), nil +} + +func (reader *ReaderType) SkipBits(bits int) error { + // read as many raw bytes as we can + bytes := bits / 8 + buf := make([]byte, bytes) + _, err := reader.stream.Read(buf) if err != nil { return err } - for reader.index+bits > 7 { - reader.base++ - reader.index = 0 - bits -= 8 + // the final read byte should be the new current byte + if bytes > 0 { + reader.curByte = buf[bytes-1] + } + // read the extra bits + for i := bytes * 8; i < bits; i++ { + _, err := reader.readBit() + if err != nil { + return err + } } - reader.index += bits return nil } @@ -54,81 +102,68 @@ func (reader *ReaderType) SkipBytes(bytes int) error { return nil } -func (reader *ReaderType) ReadBits(bits int) (int, error) { - if bits <= 0 { - return -1, fmt.Errorf("ReadBits Error: Bits value %d lower or equals than 0.", bits) - } - if bits > 64 { - return -1, fmt.Errorf("ReadBits Error: Bits value %d higher than 64.", bits) +// Read up to 64 bits from the stream +func (reader *ReaderType) ReadBits(bits int) (uint64, error) { + if bits < 1 || bits > 64 { + return 0, fmt.Errorf("ReadBits(bits) ERROR: Bits number should be between 1 and 64.") } - err := reader.checkAvailableBits(bits) - if err != nil { - return -1, err - } - if reader.le { - var output string - // Go to last bit and read backwards from there - reader.base += bits / 8 - reader.index += bits % 8 - if reader.index > 7 { - reader.index -= 8 - reader.base++ - } - for i := 0; i < bits; i++ { - reader.index-- - if reader.index < 0 { - reader.base-- - reader.index = 7 - } - binary := fmt.Sprintf("%08b", reader.data[reader.base]) - binaryArr := strings.Split(binary, "") - output += binaryArr[reader.index] - } - // Return to last bit after reading - reader.base += bits / 8 - reader.index += bits % 8 - if reader.index > 7 { - reader.index -= 8 - } - // Conversion of string binary to int - value, err := strconv.ParseUint(output, 2, 64) + var val uint64 + for i := 0; i < bits; i++ { + bit, err := reader.readBit() if err != nil { - return -1, fmt.Errorf("%s", err) + return 0, err } - return int(value), nil - } else { - var output string - for i := 0; i < bits; i++ { - binary := fmt.Sprintf("%08b", reader.data[reader.base]) - binaryArr := strings.Split(binary, "") - output += binaryArr[reader.index] - reader.index++ - if reader.index > 7 { - reader.base++ - reader.index = 0 - } - } - // Conversion of string binary to int - value, err := strconv.ParseUint(output, 2, 64) - if err != nil { - return -1, fmt.Errorf("%s", err) + + if reader.le { + val |= uint64(bit) << i + } else { + val |= uint64(bit) << (bits - 1 - i) } - return int(value), nil } + return val, nil } -func (reader *ReaderType) ReadBit() (bool, error) { - value, err := reader.ReadBits(1) +func (reader *ReaderType) ReadBytes(bytes int) (uint64, error) { + if bytes < 1 || bytes > 8 { + return 0, fmt.Errorf("ReadBytes(bytes) ERROR: Bytes number should be between 1 and 8.") + } + value, err := reader.ReadBits(bytes * 8) if err != nil { - return false, fmt.Errorf("ReadBit Error: %s", err) + return 0, err } - return value != 0, nil + return value, nil } -func (reader *ReaderType) checkAvailableBits(bits int) error { - availableBits := (len(reader.data)-reader.base)*8 - reader.index - if availableBits < bits { - return fmt.Errorf("BitReaderOutOfBounds: Wanted to read/skip %d bit(s) but only %d bit(s) is/are available.", bits, availableBits) +// Read a single bool from the stream +func (reader *ReaderType) ReadBool() (bool, error) { + val, err := reader.readBit() + if err != nil { + return false, err + } + return val == 1, nil +} + +// Read a single bit from the stream +func (reader *ReaderType) readBit() (uint8, error) { + if reader.index == 0 { + // read a byte from stream into curByte + buf := make([]byte, 1) + _, err := reader.stream.Read(buf) + if err != nil { + return 0, err + } + reader.curByte = buf[0] + } + var val bool + if reader.le { + val = (reader.curByte & (1 << reader.index)) != 0 + } else { + val = (reader.curByte & (1 << (7 - reader.index))) != 0 + } + reader.index = (reader.index + 1) % 8 + if val { + return 1, nil + } else { + return 0, nil } - return nil } -- cgit v1.2.3 From 9aa30fe369ce48a3c69cc6fa886ceb52316b3d82 Mon Sep 17 00:00:00 2001 From: BiSaXa <1669855+BiSaXa@users.noreply.github.com> Date: Mon, 5 Sep 2022 11:51:51 +0300 Subject: v2 init - 69% test coverage, nice --- bitreader_test.go | 164 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 143 insertions(+), 21 deletions(-) diff --git a/bitreader_test.go b/bitreader_test.go index 5d344d2..ef13dfe 100644 --- a/bitreader_test.go +++ b/bitreader_test.go @@ -1,17 +1,102 @@ -package bitreader +package main import ( + "bytes" "testing" ) // 01110001, 00001101, 00000000, 00000000, 10100010, 00011011, 00000000, 00000000, 11001100 var TestArray = [...]byte{113, 13, 0, 0, 162, 27, 0, 0, 204} +func TestTryReadFloat32(t *testing.T) { + bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + expected := []float32{6.98198182157e+29, -2.10064170919e-18} + for i := range expected { + value, err := bitreader.TryReadFloat32() + if err != nil { + t.Fatal(err) + } + if value != expected[i] { + t.Fatalf("TryReadFloat32 FAIL for index %d: Expected %f, Got %f", i, expected[i], value) + } + } +} + +func TestTryReadFloat64(t *testing.T) { + bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + expected := []float64{3.68828741038253948851462939603e+236} + for i := range expected { + value, err := bitreader.TryReadFloat64() + if err != nil { + t.Fatal(err) + } + if value != expected[i] { + t.Fatalf("TryReadFloat64 FAIL for index %d: Expected %f, Got %f", i, expected[i], value) + } + } +} + +func TestTryReadInt8(t *testing.T) { + bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + expected := []int{113, 13, 0} + for i := range expected { + value, err := bitreader.TryReadInt8() + if err != nil { + t.Fatal(err) + } + if int(value) != expected[i] { + t.Fatalf("TryReadInt8 FAIL for index %d: Expected %d, Got %d", i, expected[i], value) + } + } +} + +func TestTryReadInt16(t *testing.T) { + bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + expected := []int{28941, 0, 41499, 0} + for i := range expected { + value, err := bitreader.TryReadInt16() + if err != nil { + t.Fatal(err) + } + if int(value) != expected[i] { + t.Fatalf("TryReadInt16 FAIL for index %d: Expected %d, Got %d", i, expected[i], value) + } + } +} + +func TestTryReadInt32(t *testing.T) { + bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + expected := []int{1896677376, 2719678464} + for i := range expected { + value, err := bitreader.TryReadInt32() + if err != nil { + t.Fatal(err) + } + if int(value) != expected[i] { + t.Fatalf("TryReadInt32 FAIL for index %d: Expected %d, Got %d", i, expected[i], value) + } + } +} + +func TestTryReadInt64(t *testing.T) { + bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + expected := []int{8146167303702773760} + for i := range expected { + value, err := bitreader.TryReadInt64() + if err != nil { + t.Fatal(err) + } + if int(value) != expected[i] { + t.Fatalf("TryReadInt64 FAIL for index %d: Expected %d, Got %d", i, expected[i], value) + } + } +} + func TestReadBit(t *testing.T) { - bitreader := Reader(TestArray[:], false) + bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) expected := []bool{false, true, true, true} for i := range expected { - value, err := bitreader.ReadBit() + value, err := bitreader.ReadBool() if err != nil { t.Fatal(err) } @@ -22,27 +107,27 @@ func TestReadBit(t *testing.T) { } func TestReadBitLE(t *testing.T) { - bitreader := Reader(TestArray[:], true) + bitreader := Reader(bytes.NewBuffer(TestArray[:]), true) expected := []bool{true, false, false, false} for i := range expected { - value, err := bitreader.ReadBit() + value, err := bitreader.ReadBool() if err != nil { t.Fatal(err) } if value != expected[i] { - t.Fatalf("ReadBitLSB FAIL for index %d: Expected %t, Got %t", i, expected[i], value) + t.Fatalf("ReadBitLE FAIL for index %d: Expected %t, Got %t", i, expected[i], value) } } } -func TestReadBits32(t *testing.T) { - bitreader := Reader(TestArray[:], false) +func TestReadBits(t *testing.T) { + bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) expected := []int{3793354753, 2288779267} // 11100010000110100000000000000001, 10001000011011000000000000000011 expectedBool := []bool{false, false} for i := range expected { - bool, err := bitreader.ReadBit() + bool, err := bitreader.ReadBool() if bool != expectedBool[i] { - t.Fatalf("ReadBits32 ReadBit FAIL for index %d: Expected %t, Got %t", i, expectedBool[i], bool) + t.Fatalf("ReadBits ReadBit FAIL for index %d: Expected %t, Got %t", i, expectedBool[i], bool) } if err != nil { t.Fatal(err) @@ -51,36 +136,73 @@ func TestReadBits32(t *testing.T) { if err != nil { t.Fatal(err) } - if value != expected[i] { - t.Fatalf("ReadBits32 FAIL for index %d: Expected %d, Got %d", i, expected[i], value) + if int(value) != expected[i] { + t.Fatalf("ReadBits FAIL for index %d: Expected %d, Got %d", i, expected[i], value) } } } func TestReadBitsLE(t *testing.T) { - bitreader := Reader(TestArray[:], true) + bitreader := Reader(bytes.NewBuffer(TestArray[:]), true) expected := []int{1720, 1768} // 11010111000, 11011101000 for i := range expected { - bitreader.ReadBit() + bitreader.ReadBool() value, err := bitreader.ReadBits(32) if err != nil { t.Fatal(err) } - if value != expected[i] { - t.Fatalf("ReadBits32LSB FAIL for index %d: Expected %d, Got %d", i, expected[i], value) + if int(value) != expected[i] { + t.Fatalf("ReadBitsLE FAIL for index %d: Expected %d, Got %d", i, expected[i], value) + } + } +} + +func TestReadBytes(t *testing.T) { + bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + expected := []int{3793354753, 2288779267} // 11100010000110100000000000000001, 10001000011011000000000000000011 + expectedBool := []bool{false, false} + for i := range expected { + bool, err := bitreader.ReadBool() + if bool != expectedBool[i] { + t.Fatalf("ReadBytes ReadBit FAIL for index %d: Expected %t, Got %t", i, expectedBool[i], bool) + } + if err != nil { + t.Fatal(err) + } + value, err := bitreader.ReadBytes(4) + if err != nil { + t.Fatal(err) + } + if int(value) != expected[i] { + t.Fatalf("ReadBytes FAIL for index %d: Expected %d, Got %d", i, expected[i], value) + } + } +} + +func TestReadBytesLE(t *testing.T) { + bitreader := Reader(bytes.NewBuffer(TestArray[:]), true) + expected := []int{1720, 1768} // 11010111000, 11011101000 + for i := range expected { + bitreader.ReadBool() + value, err := bitreader.ReadBytes(4) + if err != nil { + t.Fatal(err) + } + if int(value) != expected[i] { + t.Fatalf("ReadBytesLE FAIL for index %d: Expected %d, Got %d", i, expected[i], value) } } } func TestSkipBits(t *testing.T) { - bitreader := Reader(TestArray[:], false) + bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) expected := []bool{true, true, false, true} //00001101 err := bitreader.SkipBits(12) if err != nil { t.Fatal(err) } for i := range expected { - value, err := bitreader.ReadBit() + value, err := bitreader.ReadBool() if err != nil { t.Fatal(err) } @@ -91,16 +213,16 @@ func TestSkipBits(t *testing.T) { } func TestSkipBitsLE(t *testing.T) { - bitreader := Reader(TestArray[:], true) + bitreader := Reader(bytes.NewBuffer(TestArray[:]), true) expected := []bool{false, false, false, false} //10110000 bitreader.SkipBits(12) for i := range expected { - value, err := bitreader.ReadBit() + value, err := bitreader.ReadBool() if err != nil { t.Fatal(err) } if value != expected[i] { - t.Fatalf("SkipBits ReadBit FAIL for index %d: Expected %t, Got %t", i, expected[i], value) + t.Fatalf("SkipBitsLE ReadBit FAIL for index %d: Expected %t, Got %t", i, expected[i], value) } } } -- cgit v1.2.3 From 05d7eb4e0f7b0865fa9a0f4f9bdcdbc37d80631c Mon Sep 17 00:00:00 2001 From: BiSaXa <1669855+BiSaXa@users.noreply.github.com> Date: Wed, 7 Sep 2022 17:24:02 +0300 Subject: change package name to bitreader --- bitreader.go | 2 +- bitreader_test.go | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/bitreader.go b/bitreader.go index 7e22ba6..aeade92 100644 --- a/bitreader.go +++ b/bitreader.go @@ -1,5 +1,5 @@ // paksd -package main +package bitreader import ( "fmt" diff --git a/bitreader_test.go b/bitreader_test.go index ef13dfe..d0460c7 100644 --- a/bitreader_test.go +++ b/bitreader_test.go @@ -1,4 +1,4 @@ -package main +package bitreader import ( "bytes" @@ -9,7 +9,7 @@ import ( var TestArray = [...]byte{113, 13, 0, 0, 162, 27, 0, 0, 204} func TestTryReadFloat32(t *testing.T) { - bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []float32{6.98198182157e+29, -2.10064170919e-18} for i := range expected { value, err := bitreader.TryReadFloat32() @@ -23,7 +23,7 @@ func TestTryReadFloat32(t *testing.T) { } func TestTryReadFloat64(t *testing.T) { - bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []float64{3.68828741038253948851462939603e+236} for i := range expected { value, err := bitreader.TryReadFloat64() @@ -37,7 +37,7 @@ func TestTryReadFloat64(t *testing.T) { } func TestTryReadInt8(t *testing.T) { - bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []int{113, 13, 0} for i := range expected { value, err := bitreader.TryReadInt8() @@ -51,7 +51,7 @@ func TestTryReadInt8(t *testing.T) { } func TestTryReadInt16(t *testing.T) { - bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []int{28941, 0, 41499, 0} for i := range expected { value, err := bitreader.TryReadInt16() @@ -65,7 +65,7 @@ func TestTryReadInt16(t *testing.T) { } func TestTryReadInt32(t *testing.T) { - bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []int{1896677376, 2719678464} for i := range expected { value, err := bitreader.TryReadInt32() @@ -79,7 +79,7 @@ func TestTryReadInt32(t *testing.T) { } func TestTryReadInt64(t *testing.T) { - bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []int{8146167303702773760} for i := range expected { value, err := bitreader.TryReadInt64() @@ -93,7 +93,7 @@ func TestTryReadInt64(t *testing.T) { } func TestReadBit(t *testing.T) { - bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []bool{false, true, true, true} for i := range expected { value, err := bitreader.ReadBool() @@ -107,7 +107,7 @@ func TestReadBit(t *testing.T) { } func TestReadBitLE(t *testing.T) { - bitreader := Reader(bytes.NewBuffer(TestArray[:]), true) + bitreader := Reader(bytes.NewReader(TestArray[:]), true) expected := []bool{true, false, false, false} for i := range expected { value, err := bitreader.ReadBool() @@ -121,7 +121,7 @@ func TestReadBitLE(t *testing.T) { } func TestReadBits(t *testing.T) { - bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []int{3793354753, 2288779267} // 11100010000110100000000000000001, 10001000011011000000000000000011 expectedBool := []bool{false, false} for i := range expected { @@ -143,7 +143,7 @@ func TestReadBits(t *testing.T) { } func TestReadBitsLE(t *testing.T) { - bitreader := Reader(bytes.NewBuffer(TestArray[:]), true) + bitreader := Reader(bytes.NewReader(TestArray[:]), true) expected := []int{1720, 1768} // 11010111000, 11011101000 for i := range expected { bitreader.ReadBool() @@ -158,7 +158,7 @@ func TestReadBitsLE(t *testing.T) { } func TestReadBytes(t *testing.T) { - bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []int{3793354753, 2288779267} // 11100010000110100000000000000001, 10001000011011000000000000000011 expectedBool := []bool{false, false} for i := range expected { @@ -180,7 +180,7 @@ func TestReadBytes(t *testing.T) { } func TestReadBytesLE(t *testing.T) { - bitreader := Reader(bytes.NewBuffer(TestArray[:]), true) + bitreader := Reader(bytes.NewReader(TestArray[:]), true) expected := []int{1720, 1768} // 11010111000, 11011101000 for i := range expected { bitreader.ReadBool() @@ -195,7 +195,7 @@ func TestReadBytesLE(t *testing.T) { } func TestSkipBits(t *testing.T) { - bitreader := Reader(bytes.NewBuffer(TestArray[:]), false) + bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []bool{true, true, false, true} //00001101 err := bitreader.SkipBits(12) if err != nil { @@ -213,7 +213,7 @@ func TestSkipBits(t *testing.T) { } func TestSkipBitsLE(t *testing.T) { - bitreader := Reader(bytes.NewBuffer(TestArray[:]), true) + bitreader := Reader(bytes.NewReader(TestArray[:]), true) expected := []bool{false, false, false, false} //10110000 bitreader.SkipBits(12) for i := range expected { -- cgit v1.2.3 From 64e0e23b8a0f1a14a54f855d9c585d62549cf036 Mon Sep 17 00:00:00 2001 From: BiSaXa <1669855+BiSaXa@users.noreply.github.com> Date: Wed, 7 Sep 2022 18:15:25 +0300 Subject: no err output on try wrapper funcs --- bitreader.go | 36 ++++++++++++++++++------------------ bitreader_test.go | 30 ++++++------------------------ 2 files changed, 24 insertions(+), 42 deletions(-) diff --git a/bitreader.go b/bitreader.go index aeade92..b84dd1b 100644 --- a/bitreader.go +++ b/bitreader.go @@ -24,52 +24,52 @@ func Reader(stream io.Reader, le bool) *ReaderType { } } -func (reader *ReaderType) TryReadInt8() (uint8, error) { +func (reader *ReaderType) TryReadInt8() uint8 { value, err := reader.ReadBits(8) if err != nil { - return 0, err + panic(err) } - return uint8(value), nil + return uint8(value) } -func (reader *ReaderType) TryReadInt16() (uint16, error) { +func (reader *ReaderType) TryReadInt16() uint16 { value, err := reader.ReadBits(16) if err != nil { - return 0, err + panic(err) } - return uint16(value), nil + return uint16(value) } -func (reader *ReaderType) TryReadInt32() (uint32, error) { +func (reader *ReaderType) TryReadInt32() uint32 { value, err := reader.ReadBits(32) if err != nil { - return 0, err + panic(err) } - return uint32(value), nil + return uint32(value) } -func (reader *ReaderType) TryReadInt64() (uint64, error) { +func (reader *ReaderType) TryReadInt64() uint64 { value, err := reader.ReadBits(64) if err != nil { - return 0, err + panic(err) } - return value, nil + return value } -func (reader *ReaderType) TryReadFloat32() (float32, error) { +func (reader *ReaderType) TryReadFloat32() float32 { value, err := reader.ReadBits(32) if err != nil { - return 0, err + panic(err) } - return math.Float32frombits(uint32(value)), nil + return math.Float32frombits(uint32(value)) } -func (reader *ReaderType) TryReadFloat64() (float64, error) { +func (reader *ReaderType) TryReadFloat64() float64 { value, err := reader.ReadBits(64) if err != nil { - return 0, err + panic(err) } - return math.Float64frombits(value), nil + return math.Float64frombits(value) } func (reader *ReaderType) SkipBits(bits int) error { diff --git a/bitreader_test.go b/bitreader_test.go index d0460c7..85b0c98 100644 --- a/bitreader_test.go +++ b/bitreader_test.go @@ -12,10 +12,7 @@ func TestTryReadFloat32(t *testing.T) { bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []float32{6.98198182157e+29, -2.10064170919e-18} for i := range expected { - value, err := bitreader.TryReadFloat32() - if err != nil { - t.Fatal(err) - } + value := bitreader.TryReadFloat32() if value != expected[i] { t.Fatalf("TryReadFloat32 FAIL for index %d: Expected %f, Got %f", i, expected[i], value) } @@ -26,10 +23,7 @@ func TestTryReadFloat64(t *testing.T) { bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []float64{3.68828741038253948851462939603e+236} for i := range expected { - value, err := bitreader.TryReadFloat64() - if err != nil { - t.Fatal(err) - } + value := bitreader.TryReadFloat64() if value != expected[i] { t.Fatalf("TryReadFloat64 FAIL for index %d: Expected %f, Got %f", i, expected[i], value) } @@ -40,10 +34,7 @@ func TestTryReadInt8(t *testing.T) { bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []int{113, 13, 0} for i := range expected { - value, err := bitreader.TryReadInt8() - if err != nil { - t.Fatal(err) - } + value := bitreader.TryReadInt8() if int(value) != expected[i] { t.Fatalf("TryReadInt8 FAIL for index %d: Expected %d, Got %d", i, expected[i], value) } @@ -54,10 +45,7 @@ func TestTryReadInt16(t *testing.T) { bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []int{28941, 0, 41499, 0} for i := range expected { - value, err := bitreader.TryReadInt16() - if err != nil { - t.Fatal(err) - } + value := bitreader.TryReadInt16() if int(value) != expected[i] { t.Fatalf("TryReadInt16 FAIL for index %d: Expected %d, Got %d", i, expected[i], value) } @@ -68,10 +56,7 @@ func TestTryReadInt32(t *testing.T) { bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []int{1896677376, 2719678464} for i := range expected { - value, err := bitreader.TryReadInt32() - if err != nil { - t.Fatal(err) - } + value := bitreader.TryReadInt32() if int(value) != expected[i] { t.Fatalf("TryReadInt32 FAIL for index %d: Expected %d, Got %d", i, expected[i], value) } @@ -82,10 +67,7 @@ func TestTryReadInt64(t *testing.T) { bitreader := Reader(bytes.NewReader(TestArray[:]), false) expected := []int{8146167303702773760} for i := range expected { - value, err := bitreader.TryReadInt64() - if err != nil { - t.Fatal(err) - } + value := bitreader.TryReadInt64() if int(value) != expected[i] { t.Fatalf("TryReadInt64 FAIL for index %d: Expected %d, Got %d", i, expected[i], value) } -- cgit v1.2.3 From ea36a3a27a7420ca8f64e5193ae0dde9ac0ca05d Mon Sep 17 00:00:00 2001 From: BiSaXa <1669855+BiSaXa@users.noreply.github.com> Date: Thu, 8 Sep 2022 09:52:25 +0300 Subject: added tryreadbool and tryreadint1 --- bitreader.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/bitreader.go b/bitreader.go index b84dd1b..568f4f7 100644 --- a/bitreader.go +++ b/bitreader.go @@ -24,6 +24,22 @@ func Reader(stream io.Reader, le bool) *ReaderType { } } +func (reader *ReaderType) TryReadBool() bool { + flag, err := reader.ReadBool() + if err != nil { + panic(err) + } + return flag +} + +func (reader *ReaderType) TryReadInt1() uint8 { + value, err := reader.ReadBits(1) + if err != nil { + panic(err) + } + return uint8(value) +} + func (reader *ReaderType) TryReadInt8() uint8 { value, err := reader.ReadBits(8) if err != nil { -- cgit v1.2.3 From d05afc7acbec130e313587225bebe26c3a023449 Mon Sep 17 00:00:00 2001 From: BiSaXa <1669855+BiSaXa@users.noreply.github.com> Date: Sun, 11 Sep 2022 10:06:12 +0300 Subject: added go doc --- bitreader.go | 74 ++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 14 deletions(-) diff --git a/bitreader.go b/bitreader.go index 568f4f7..3fbc221 100644 --- a/bitreader.go +++ b/bitreader.go @@ -1,4 +1,10 @@ -// paksd +// BitReader is a simple bit reader with big/little-endian support for golang. +// It can read stream data from an io.Reader; can read from os.File and a byte array with bytes.NewReader(array). +// Uses bitwise operations for v2. +// Supports reading up to 64 bits at one time. +// Includes wrapper functions for most used data types. +// Error checking on all but wrapper functions. +// Thanks to github.com/mlugg for the big help! package bitreader import ( @@ -7,23 +13,28 @@ import ( "math" ) +// ReaderType is the main structure of our Reader. +// Whenever index == 0, we need to read a new byte from stream into curByte type ReaderType struct { - stream io.Reader // the underlying stream we're reading bytes from - index uint8 // 0-7, the current index into the byte - curByte byte // the byte we're currently reading from - le bool // whether to read in little-endian order - // Whenever index == 0, we need to read a new byte from stream into curByte + stream io.Reader // The underlying stream we're reading bytes from + index uint8 // The current index into the byte [0-7] + curByte byte // The byte we're currently reading from + le bool // Whether to read in little-endian order } +// Reader is the main constructor that creates the ReaderType object +// with stream data and little-endian state. func Reader(stream io.Reader, le bool) *ReaderType { return &ReaderType{ stream: stream, index: 0, - curByte: 0, // initial value doesn't matter, it'll be read as soon as we try to read any bits + curByte: 0, // Initial value doesn't matter, it'll be read as soon as we try to read any bits le: le, } } +// TryReadBool is a wrapper function that gets the state of 1-bit, +// returns true if 1, false if 0. Panics on error. func (reader *ReaderType) TryReadBool() bool { flag, err := reader.ReadBool() if err != nil { @@ -32,6 +43,8 @@ func (reader *ReaderType) TryReadBool() bool { return flag } +// TryReadInt1 is a wrapper function that returns the value of 1-bit. +// Returns type uint8. Panics on error. func (reader *ReaderType) TryReadInt1() uint8 { value, err := reader.ReadBits(1) if err != nil { @@ -40,6 +53,8 @@ func (reader *ReaderType) TryReadInt1() uint8 { return uint8(value) } +// TryReadInt8 is a wrapper function that returns the value of 8-bits. +// Returns uint8. Panics on error. func (reader *ReaderType) TryReadInt8() uint8 { value, err := reader.ReadBits(8) if err != nil { @@ -48,6 +63,8 @@ func (reader *ReaderType) TryReadInt8() uint8 { return uint8(value) } +// TryReadInt16 is a wrapper function that returns the value of 16-bits. +// Returns uint16. Panics on error. func (reader *ReaderType) TryReadInt16() uint16 { value, err := reader.ReadBits(16) if err != nil { @@ -56,6 +73,8 @@ func (reader *ReaderType) TryReadInt16() uint16 { return uint16(value) } +// TryReadInt32 is a wrapper function that returns the value of 32-bits. +// Returns uint32. Panics on error. func (reader *ReaderType) TryReadInt32() uint32 { value, err := reader.ReadBits(32) if err != nil { @@ -64,6 +83,8 @@ func (reader *ReaderType) TryReadInt32() uint32 { return uint32(value) } +// TryReadInt64 is a wrapper function that returns the value of 64-bits. +// Returns uint64. Panics on error. func (reader *ReaderType) TryReadInt64() uint64 { value, err := reader.ReadBits(64) if err != nil { @@ -72,6 +93,8 @@ func (reader *ReaderType) TryReadInt64() uint64 { return value } +// TryReadFloat32 is a wrapper function that returns the value of 32-bits. +// Returns float32. Panics on error. func (reader *ReaderType) TryReadFloat32() float32 { value, err := reader.ReadBits(32) if err != nil { @@ -80,6 +103,8 @@ func (reader *ReaderType) TryReadFloat32() float32 { return math.Float32frombits(uint32(value)) } +// TryReadFloat64 is a wrapper function that returns the value of 64-bits. +// Returns float64. Panics on error. func (reader *ReaderType) TryReadFloat64() float64 { value, err := reader.ReadBits(64) if err != nil { @@ -88,19 +113,22 @@ func (reader *ReaderType) TryReadFloat64() float64 { return math.Float64frombits(value) } +// SkipBits is a function that increases Reader index +// based on given input bits number. Returns an error +// if there are no remaining bits. func (reader *ReaderType) SkipBits(bits int) error { - // read as many raw bytes as we can + // Read as many raw bytes as we can bytes := bits / 8 buf := make([]byte, bytes) _, err := reader.stream.Read(buf) if err != nil { return err } - // the final read byte should be the new current byte + // The final read byte should be the new current byte if bytes > 0 { reader.curByte = buf[bytes-1] } - // read the extra bits + // Read the extra bits for i := bytes * 8; i < bits; i++ { _, err := reader.readBit() if err != nil { @@ -110,6 +138,9 @@ func (reader *ReaderType) SkipBits(bits int) error { return nil } +// SkipBytes is a function that increases Reader index +// based on given input bytes number. Returns an error +// if there are no remaining bits. func (reader *ReaderType) SkipBytes(bytes int) error { err := reader.SkipBits(bytes * 8) if err != nil { @@ -118,7 +149,12 @@ func (reader *ReaderType) SkipBytes(bytes int) error { return nil } -// Read up to 64 bits from the stream +// ReadBits is a function that reads the specified amount of bits +// specified in the parameter and returns the value, error +// based on the output. It can read up to 64 bits. Returns the read +// value in type uint64. +// +// Returns an error if there are no remaining bits. func (reader *ReaderType) ReadBits(bits int) (uint64, error) { if bits < 1 || bits > 64 { return 0, fmt.Errorf("ReadBits(bits) ERROR: Bits number should be between 1 and 64.") @@ -139,6 +175,12 @@ func (reader *ReaderType) ReadBits(bits int) (uint64, error) { return val, nil } +// ReadBytes is a function that reads the specified amount of bytes +// specified in the parameter and returns the value, error +// based on the output. It can read up to 8 bytes. Returns the read +// value in type uint64. +// +// Returns an error if there are no remaining bits. func (reader *ReaderType) ReadBytes(bytes int) (uint64, error) { if bytes < 1 || bytes > 8 { return 0, fmt.Errorf("ReadBytes(bytes) ERROR: Bytes number should be between 1 and 8.") @@ -150,7 +192,10 @@ func (reader *ReaderType) ReadBytes(bytes int) (uint64, error) { return value, nil } -// Read a single bool from the stream +// ReadBool is a function that reads one bit and returns the state, error +// based on the output. Returns the read value in a bool format. +// +// Returns an error if there are no remaining bits. func (reader *ReaderType) ReadBool() (bool, error) { val, err := reader.readBit() if err != nil { @@ -159,10 +204,11 @@ func (reader *ReaderType) ReadBool() (bool, error) { return val == 1, nil } -// Read a single bit from the stream +// readBit is a private function that reads a single bit from the stream. +// This is the main function that makes us read stream data. func (reader *ReaderType) readBit() (uint8, error) { if reader.index == 0 { - // read a byte from stream into curByte + // Read a byte from stream into curByte buf := make([]byte, 1) _, err := reader.stream.Read(buf) if err != nil { -- cgit v1.2.3