1
1
mirror of https://github.com/wader/fq.git synced 2024-11-29 23:27:12 +03:00
fq/pkg/bitio/buffer.go

73 lines
1.3 KiB
Go
Raw Normal View History

2020-06-08 03:29:51 +03:00
package bitio
// 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 {
buf []byte
bufBits int64
bitsOff int64
2020-06-08 03:29:51 +03:00
}
func (b *Buffer) Len() int64 { return b.bufBits - b.bitsOff }
2020-06-08 03:29:51 +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) {
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)
return buf, b.bufBits
2020-06-08 03:29:51 +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
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)
b.bufBits += nBits
2020-06-08 03:29:51 +03:00
return nBits, nil
}
func (b *Buffer) empty() bool { return b.bufBits <= b.bitsOff }
2020-06-08 03:29:51 +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
}
c := nBits
2022-02-05 18:52:22 +03:00
left := b.Len()
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)
b.bitsOff += c
2020-06-08 03:29:51 +03:00
return c, nil
2020-06-08 03:29:51 +03:00
}