Skip to content

Commit

Permalink
feat: 支持seek操作
Browse files Browse the repository at this point in the history
  • Loading branch information
CC11001100 committed Oct 24, 2023
1 parent ebefa1b commit 5570a3e
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 43 deletions.
114 changes: 88 additions & 26 deletions bit_buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,71 +6,133 @@ import (

const BitBeginOffset = 7

// BitBuffer 提供bit级别的缓存
// BitBuffer 在bit级别提供一些便于操作的API
type BitBuffer struct {

// 当前写到哪个下标了
nextWriteIndex int
// 下一个要操作的byte的下标
nextIndex int

// 当前写到的offset
nextWriteBitOffset int
// 下一个要操作的byte的offset
nextBitOffset int

// 当前的写缓存
buffer []byte
// buff当前对应的字节数组
bytes []byte
}

// New 创建一个可以用来写数据的位缓存空间
func New() *BitBuffer {
return &BitBuffer{
nextWriteIndex: 0,
nextWriteBitOffset: BitBeginOffset,
buffer: make([]byte, 0),
nextIndex: 0,
nextBitOffset: BitBeginOffset,
bytes: make([]byte, 1),
}
}

// Append 往缓存空间追加一个bit,会获取 bitValue 的最低位的bit值,1或者0
func (x *BitBuffer) Append(bitValue int) *BitBuffer {
// SetBytes 设置buff底层的字节数组
func (x *BitBuffer) SetBytes(bytes []byte) *BitBuffer {
x.bytes = bytes
return x
}

// SeekFirst 移动操作指针
func (x *BitBuffer) SeekFirst() *BitBuffer {
return x.Seek(0)
}

// SeekLast 移动指针到最后一个位置
func (x *BitBuffer) SeekLast() *BitBuffer {
return x.Seek(len(x.bytes) * 8)
}

// Seek 移动指针
func (x *BitBuffer) Seek(offset int) *BitBuffer {

// 保证空间是足够的
x.nextIndex = offset / 8
for len(x.bytes) <= x.nextIndex {
x.bytes = append(x.bytes, byte(0))
}

// 把便宜设置正确
x.nextBitOffset = BitBeginOffset - (offset % 8)

return x
}

// GetSeek 获取当前写指针
func (x *BitBuffer) GetSeek() int {
return x.nextIndex*8 + (BitBeginOffset - x.nextBitOffset)
}

// Capacity 获取当前的容量
func (x *BitBuffer) Capacity() int {
return len(x.bytes) * 8
}

// WriteBit 往缓存空间追加一个bit,会获取 bitValue 的最低位的bit值,1或者0
func (x *BitBuffer) WriteBit(bitValue int) *BitBuffer {

// 字节数组在需要的时候扩容
if x.nextWriteIndex >= len(x.buffer) {
x.buffer = append(x.buffer, byte(0x0))
if x.nextIndex >= len(x.bytes) {
x.bytes = append(x.bytes, byte(0x0))
}

// 写入下标
x.buffer[x.nextWriteIndex] ^= byte((bitValue & 0x01) << x.nextWriteBitOffset)
// 写入对应偏移的bit值,其他的bit位保持原值
x.bytes[x.nextIndex] = byte((bitValue&0x01)<<x.nextBitOffset) | (x.bytes[x.nextIndex] & ((0x1 << x.nextBitOffset) ^ 0xFF))

// 移动指针
x.nextWriteBitOffset--
if x.nextWriteBitOffset < 0 {
x.nextWriteBitOffset = BitBeginOffset
x.nextWriteIndex++
x.nextBitOffset--
if x.nextBitOffset < 0 {
x.nextBitOffset = BitBeginOffset
x.nextIndex++
}

return x
}

// AppendByte 往缓存空间一次追加一个byte
func (x *BitBuffer) AppendByte(b byte) *BitBuffer {
// WriteByte 往缓存空间一次追加一个byte
func (x *BitBuffer) WriteByte(b byte) *BitBuffer {
for offset := BitBeginOffset; offset >= 0; offset-- {
x.Append((int(b) >> offset) & 0x1)
x.WriteBit((int(b) >> offset) & 0x1)
}
return x
}

// ReadBit 从seek读取一个bit
func (x *BitBuffer) ReadBit() int {

// 读取对应offset的bit值
value := (x.bytes[x.nextIndex] & (0x1 << x.nextBitOffset)) >> x.nextBitOffset

// offset往后移动
x.nextBitOffset--
if x.nextBitOffset < 0 {
x.nextBitOffset = BitBeginOffset
x.nextIndex++
}

return int(value)
}

// IsAtLast 是否已经存在最后一个位置了
func (x *BitBuffer) IsAtLast() bool {
return x.GetSeek() == x.Capacity()
}

// Bytes 返回当前缓存空间所对应的字节数组
func (x *BitBuffer) Bytes() []byte {
return x.buffer
return x.bytes
}

// ToBinaryString 把当前的缓存空间转换为二进制字符串
func (x *BitBuffer) ToBinaryString() string {
buff := strings.Builder{}
loop:
for index, b := range x.buffer {
for index, b := range x.bytes {
for offset := BitBeginOffset; offset >= 0; offset-- {

// 没有写内容的部分就不转换到字符串中了
if index == x.nextWriteIndex && offset <= x.nextWriteBitOffset {
if index == x.nextIndex && offset <= x.nextBitOffset {
break loop
}

Expand Down
107 changes: 91 additions & 16 deletions bit_buffer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,103 @@ import (
"testing"
)

func TestBitBuffer_Append(t *testing.T) {
func TestBitBuffer_WriteBit(t *testing.T) {

buffer := New()
assert.Equal(t, "1", buffer.Append(1).ToBinaryString())
assert.Equal(t, "10", buffer.Append(0).ToBinaryString())
assert.Equal(t, "101", buffer.Append(1).ToBinaryString())
assert.Equal(t, "1010", buffer.Append(0).ToBinaryString())
assert.Equal(t, "10101", buffer.Append(1).ToBinaryString())
assert.Equal(t, "101010", buffer.Append(0).ToBinaryString())
assert.Equal(t, "1010101", buffer.Append(1).ToBinaryString())
assert.Equal(t, "10101011", buffer.Append(1).ToBinaryString())
assert.Equal(t, "101010111", buffer.Append(1).ToBinaryString())
assert.Equal(t, "1010101111", buffer.Append(1).ToBinaryString())
assert.Equal(t, "1", buffer.WriteBit(1).ToBinaryString())
assert.Equal(t, "10", buffer.WriteBit(0).ToBinaryString())
assert.Equal(t, "101", buffer.WriteBit(1).ToBinaryString())
assert.Equal(t, "1010", buffer.WriteBit(0).ToBinaryString())
assert.Equal(t, "10101", buffer.WriteBit(1).ToBinaryString())
assert.Equal(t, "101010", buffer.WriteBit(0).ToBinaryString())
assert.Equal(t, "1010101", buffer.WriteBit(1).ToBinaryString())
assert.Equal(t, "10101011", buffer.WriteBit(1).ToBinaryString())
assert.Equal(t, "101010111", buffer.WriteBit(1).ToBinaryString())
assert.Equal(t, "1010101111", buffer.WriteBit(1).ToBinaryString())

}

func TestBitBuffer_AppendByte(t *testing.T) {
func TestBitBuffer_WriteByte(t *testing.T) {

buffer := New()
assert.Equal(t, "11111111", buffer.AppendByte(0xFF).ToBinaryString())
assert.Equal(t, "111111110", buffer.Append(0).ToBinaryString())
assert.Equal(t, "1111111101", buffer.Append(1).ToBinaryString())
assert.Equal(t, "111111110111111111", buffer.AppendByte(0xFF).ToBinaryString())
assert.Equal(t, "11111111", buffer.WriteByte(0xFF).ToBinaryString())
assert.Equal(t, "111111110", buffer.WriteBit(0).ToBinaryString())
assert.Equal(t, "1111111101", buffer.WriteBit(1).ToBinaryString())
assert.Equal(t, "111111110111111111", buffer.WriteByte(0xFF).ToBinaryString())

}

func TestBitBuffer_SetBytes(t *testing.T) {
buffer := New().SetBytes([]byte{0x1, 0x2})
assert.Equal(t, []byte{0x1, 0x2}, buffer.Bytes())
}

func TestBitBuffer_Capacity(t *testing.T) {
buffer := New()
assert.Equal(t, 8, buffer.Capacity())
assert.Equal(t, 8, buffer.WriteBit(0x1).Capacity())
assert.Equal(t, 16, buffer.WriteByte(0xFF).Capacity())
}

func TestBitBuffer_GetSeek(t *testing.T) {
buffer := New()
assert.Equal(t, 0, buffer.GetSeek())
assert.Equal(t, 1, buffer.WriteBit(0x1).GetSeek())
}

func TestBitBuffer_Seek(t *testing.T) {
buffer := New().WriteByte(0xFF)
assert.Equal(t, "11111111", buffer.ToBinaryString())
assert.Equal(t, "", buffer.Seek(0).ToBinaryString())
assert.Equal(t, "1", buffer.Seek(1).ToBinaryString())
assert.Equal(t, "11", buffer.Seek(2).ToBinaryString())
assert.Equal(t, "111", buffer.Seek(3).ToBinaryString())
assert.Equal(t, "1111111", buffer.Seek(7).ToBinaryString())
assert.Equal(t, "11111111", buffer.Seek(8).ToBinaryString())
assert.Equal(t, "111111110", buffer.Seek(9).ToBinaryString())
assert.Equal(t, "111111110000000", buffer.Seek(15).ToBinaryString())
assert.Equal(t, "1111111100000000", buffer.Seek(16).ToBinaryString())
assert.Equal(t, "101111110000000000000000", buffer.Seek(1).WriteBit(0).SeekLast().ToBinaryString())
}

func TestBitBuffer_SeekFirst(t *testing.T) {
buffer := New().WriteByte(0xFF)
assert.Equal(t, "11111111", buffer.ToBinaryString())
assert.Equal(t, "", buffer.SeekFirst().ToBinaryString())
assert.Equal(t, "1", buffer.WriteBit(0x1).ToBinaryString())
}

func TestBitBuffer_SeekLast(t *testing.T) {
buffer := New().WriteByte(0xFF)
assert.Equal(t, "11111111", buffer.ToBinaryString())
assert.Equal(t, "11111111", buffer.SeekLast().ToBinaryString())
assert.Equal(t, "111111111", buffer.WriteBit(0x1).ToBinaryString())
}

func TestBitBuffer_ReadBit(t *testing.T) {
buffer := New().WriteByte(0xF0).SeekFirst()

assert.Equal(t, 1, buffer.ReadBit())
assert.False(t, buffer.IsAtLast())

assert.Equal(t, 1, buffer.ReadBit())
assert.False(t, buffer.IsAtLast())

assert.Equal(t, 1, buffer.ReadBit())
assert.False(t, buffer.IsAtLast())

assert.Equal(t, 1, buffer.ReadBit())
assert.False(t, buffer.IsAtLast())

assert.Equal(t, 0, buffer.ReadBit())
assert.False(t, buffer.IsAtLast())

assert.Equal(t, 0, buffer.ReadBit())
assert.False(t, buffer.IsAtLast())

assert.Equal(t, 0, buffer.ReadBit())
assert.False(t, buffer.IsAtLast())

assert.Equal(t, 0, buffer.ReadBit())
assert.True(t, buffer.IsAtLast())
}
2 changes: 1 addition & 1 deletion examples/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
func main() {

// 创建一块缓存空间,可以一个bit一个bit的往里面写
buffer := bit_buffer.New().Append(1).Append(0)
buffer := bit_buffer.New().WriteBit(1).WriteBit(0)

// 转为二进制字符串
binaryString := buffer.ToBinaryString()
Expand Down

0 comments on commit 5570a3e

Please sign in to comment.