226 lines
3.6 KiB
Go
Raw Normal View History

2021-12-04 16:42:11 +00:00
package bytes
import (
"errors"
)
var (
ErrInvalidLength = errors.New("invalid length")
ErrInvalidPosition = errors.New("invalid position")
ErrNotEnougth = errors.New("bytes not enougth")
)
// Buffer .
type Buffer struct {
total int
buffers [][]byte
onRelease func(b []byte)
}
// Len .
func (bb *Buffer) Len() int {
return bb.total
}
// Push .
func (bb *Buffer) Push(b []byte) {
if len(b) == 0 {
return
}
bb.buffers = append(bb.buffers, b)
bb.total += len(b)
}
// Pop .
func (bb *Buffer) Pop(n int) ([]byte, error) {
if n < 0 {
return nil, ErrInvalidLength
}
if bb.total < n {
return nil, ErrNotEnougth
}
bb.total -= n
var buf = bb.buffers[0]
if len(buf) >= n {
ret := buf[:n]
bb.buffers[0] = bb.buffers[0][n:]
if len(bb.buffers[0]) == 0 {
bb.releaseHead()
}
return ret, nil
}
var ret = make([]byte, n)[0:0]
for n > 0 {
if len(buf) >= n {
ret = append(ret, buf[:n]...)
bb.buffers[0] = bb.buffers[0][n:]
if len(bb.buffers[0]) == 0 {
bb.releaseHead()
}
return ret, nil
}
ret = append(ret, buf...)
bb.releaseHead()
n -= len(buf)
buf = bb.buffers[0]
}
return ret, nil
}
// Append .
func (bb *Buffer) Append(b []byte) {
if len(b) == 0 {
return
}
n := len(bb.buffers)
if n == 0 {
bb.buffers = append(bb.buffers, b)
return
}
bb.buffers[n-1] = append(bb.buffers[n-1], b...)
bb.total += len(b)
}
// Head .
func (bb *Buffer) Head(n int) ([]byte, error) {
if n < 0 {
return nil, ErrInvalidLength
}
if bb.total < n {
return nil, ErrNotEnougth
}
if len(bb.buffers[0]) >= n {
return bb.buffers[0][:n], nil
}
ret := make([]byte, n)
copied := 0
for i := 0; n > 0; i++ {
buf := bb.buffers[i]
if len(buf) >= n {
copy(ret[copied:], buf[:n])
return ret, nil
} else {
copy(ret[copied:], buf)
n -= len(buf)
copied += len(buf)
}
}
return ret, nil
}
// Sub .
func (bb *Buffer) Sub(from, to int) ([]byte, error) {
if from < 0 || to < 0 || to < from {
return nil, ErrInvalidPosition
}
if bb.total < to {
return nil, ErrNotEnougth
}
if len(bb.buffers[0]) >= to {
return bb.buffers[0][from:to], nil
}
n := to - from
ret := make([]byte, n)
copied := 0
for i := 0; n > 0; i++ {
buf := bb.buffers[i]
if len(buf) >= from+n {
copy(ret[copied:], buf[from:from+n])
return ret, nil
} else {
if len(buf) > from {
if from > 0 {
buf = buf[from:]
from = 0
}
copy(ret[copied:], buf)
copied += len(buf)
n -= len(buf)
} else {
from -= len(buf)
}
}
}
return ret, nil
}
// Write .
func (bb *Buffer) Write(b []byte) {
bb.Push(b)
}
// Read .
func (bb *Buffer) Read(n int) ([]byte, error) {
return bb.Pop(n)
}
// ReadAll .
func (bb *Buffer) ReadAll() ([]byte, error) {
if len(bb.buffers) == 0 {
return nil, nil
}
ret := append([]byte{}, bb.buffers[0]...)
if bb.onRelease != nil {
bb.onRelease(bb.buffers[0])
for i := 1; i < len(bb.buffers); i++ {
ret = append(ret, bb.buffers[i]...)
bb.onRelease(bb.buffers[i])
}
} else {
for i := 1; i < len(bb.buffers); i++ {
ret = append(ret, bb.buffers[i]...)
}
}
bb.buffers = nil
bb.total = 0
return ret, nil
}
// Reset .
func (bb *Buffer) Reset() {
if bb.onRelease != nil {
for i := 0; i < len(bb.buffers); i++ {
bb.onRelease(bb.buffers[i])
}
}
bb.buffers = nil
bb.total = 0
}
func (bb *Buffer) OnRelease(onRelease func(b []byte)) {
bb.onRelease = onRelease
}
func (bb *Buffer) releaseHead() {
if bb.onRelease != nil {
bb.onRelease(bb.buffers[0])
}
switch len(bb.buffers) {
case 1:
bb.buffers = nil
default:
bb.buffers = bb.buffers[1:]
}
}
// NewBuffer .
func NewBuffer() *Buffer {
return &Buffer{}
}