Skip to content

Instantly share code, notes, and snippets.

@shaunlee
Created August 12, 2016 13:14
Show Gist options
  • Save shaunlee/3f8f6a08913124d806babbe36e633b1d to your computer and use it in GitHub Desktop.
Save shaunlee/3f8f6a08913124d806babbe36e633b1d to your computer and use it in GitHub Desktop.
Circle byte buffer
package main
import (
"io"
"errors"
)
var ErrBufferIsNotEnough = errors.New("buffer is not enough")
type ByteBuffer struct {
data []byte
size uint64
head uint64 // write cursor
tail uint64 // read cursor
}
func NewByteBuffer(size uint64) *ByteBuffer {
return &ByteBuffer{
data: make([]byte, size),
size: size,
}
}
func (p *ByteBuffer) Write(v []byte) (int, error) {
length := uint64(len(v))
if length > p.size - (p.head - p.tail) {
return 0, ErrBufferIsNotEnough
}
offset_head := p.head % p.size
offset_tail := p.tail % p.size
if offset_head < offset_tail {
// #_#
copy(p.data[offset_head:], v)
} else {
right := p.size - p.head
if right >= length {
// #__
copy(p.data[offset_head:], v)
} else {
// _#_
copy(p.data[offset_head:], v[:right])
copy(p.data[:length - right], v[right:])
}
}
p.head += length
return int(length), nil
}
func (p *ByteBuffer) Read(v []byte) (int, error) {
if p.head - p.tail == 0 {
return 0, io.EOF
}
length := uint64(len(v))
if length > p.head - p.tail {
length = p.head - p.tail
}
offset_head := p.head % p.size
offset_tail := p.tail % p.size
if offset_head > offset_tail {
copy(v, p.data[offset_tail:offset_tail + length])
} else {
right := p.size - p.tail
if right >= length {
copy(v, p.data[offset_tail:])
} else {
copy(v[:right], p.data[offset_tail:])
copy(v[right:], p.data[:length - right])
}
}
p.tail += length
return int(length), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment