2020-06-08 03:29:51 +03:00
|
|
|
package bitio
|
|
|
|
|
2022-01-24 23:21:48 +03:00
|
|
|
// TODO: NewBuffer with []byte arg to save on alloc
|
|
|
|
|
2020-06-08 03:29:51 +03:00
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
)
|
|
|
|
|
2022-02-09 03:22:51 +03:00
|
|
|
// Buffer is a bitio.Reader and bitio.Writer providing a bit buffer.
|
|
|
|
// Similar to bytes.Buffer.
|
2020-06-08 03:29:51 +03:00
|
|
|
type Buffer struct {
|
2022-01-24 23:21:48 +03:00
|
|
|
buf []byte
|
|
|
|
bufBits int64
|
|
|
|
bitsOff int64
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2022-01-24 23:21:48 +03:00
|
|
|
func (b *Buffer) Len() int64 { return b.bufBits - b.bitsOff }
|
2020-06-08 03:29:51 +03:00
|
|
|
|
2022-01-24 23:21:48 +03:00
|
|
|
func (b *Buffer) Reset() {
|
|
|
|
b.bufBits = 0
|
|
|
|
b.bitsOff = 0
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-05 18:52:22 +03:00
|
|
|
// Bits return unread bits in buffer
|
|
|
|
func (b *Buffer) Bits() ([]byte, int64) {
|
2022-01-24 23:21:48 +03:00
|
|
|
l := b.Len()
|
|
|
|
buf := make([]byte, BitsByteCount(l))
|
2022-02-05 18:52:22 +03:00
|
|
|
copyBufBits(buf, 0, b.buf, b.bitsOff, l, true)
|
2022-01-24 23:21:48 +03:00
|
|
|
return buf, b.bufBits
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2022-01-24 23:21:48 +03:00
|
|
|
func (b *Buffer) WriteBits(p []byte, nBits int64) (n int64, err error) {
|
|
|
|
tBytes := BitsByteCount(b.bufBits + nBits)
|
2020-06-08 03:29:51 +03:00
|
|
|
|
2022-01-24 23:21:48 +03:00
|
|
|
if tBytes > int64(len(b.buf)) {
|
|
|
|
if tBytes <= int64(cap(b.buf)) {
|
|
|
|
b.buf = b.buf[:tBytes]
|
|
|
|
} else {
|
|
|
|
buf := make([]byte, tBytes, tBytes*2)
|
|
|
|
copy(buf, b.buf)
|
|
|
|
b.buf = buf
|
|
|
|
}
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-05 18:52:22 +03:00
|
|
|
copyBufBits(b.buf, b.bufBits, p, 0, nBits, true)
|
2022-01-24 23:21:48 +03:00
|
|
|
b.bufBits += nBits
|
2020-06-08 03:29:51 +03:00
|
|
|
|
2022-01-24 23:21:48 +03:00
|
|
|
return nBits, nil
|
2021-11-23 00:08:36 +03:00
|
|
|
}
|
|
|
|
|
2022-01-24 23:21:48 +03:00
|
|
|
func (b *Buffer) empty() bool { return b.bufBits <= b.bitsOff }
|
2020-06-08 03:29:51 +03:00
|
|
|
|
2022-01-24 23:21:48 +03:00
|
|
|
func (b *Buffer) ReadBits(p []byte, nBits int64) (n int64, err error) {
|
|
|
|
if b.empty() {
|
|
|
|
b.Reset()
|
|
|
|
if nBits == 0 {
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
return 0, io.EOF
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2022-01-24 23:21:48 +03:00
|
|
|
c := nBits
|
2022-02-05 18:52:22 +03:00
|
|
|
left := b.Len()
|
2022-01-24 23:21:48 +03:00
|
|
|
if c > left {
|
|
|
|
c = left
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-05 18:52:22 +03:00
|
|
|
copyBufBits(p, 0, b.buf, b.bitsOff, c, true)
|
2022-01-24 23:21:48 +03:00
|
|
|
b.bitsOff += c
|
2020-06-08 03:29:51 +03:00
|
|
|
|
2022-01-24 23:21:48 +03:00
|
|
|
return c, nil
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|