sing/common/buf/buffer.go
2022-02-04 00:11:43 +08:00

322 lines
5.3 KiB
Go

package buf
import (
"crypto/rand"
"fmt"
"io"
"sing/common/list"
"sing/common"
)
type Buffer struct {
data []byte
start int
end int
managed bool
}
func New() *Buffer {
return &Buffer{
data: GetBytes(),
start: ReversedHeader,
end: ReversedHeader,
managed: true,
}
}
func StackNew() Buffer {
return Buffer{
data: GetBytes(),
managed: true,
}
}
func From(data []byte) *Buffer {
buffer := New()
buffer.Write(data)
return buffer
}
func As(data []byte) *Buffer {
size := len(data)
max := cap(data)
if size != max {
data = data[:max]
}
return &Buffer{
data: data,
end: size,
}
}
func With(data []byte) *Buffer {
return &Buffer{
data: data,
}
}
func (b *Buffer) Byte(index int) byte {
return b.data[b.start+index]
}
func (b *Buffer) SetByte(index int, value byte) {
b.data[b.start+index] = value
}
func (b *Buffer) Extend(n int) []byte {
if b.start == b.end {
b.start = 0
b.end = n
return b.data[:n]
}
end := b.end + n
ext := b.data[b.end:end]
b.end = end
return ext
}
func (b *Buffer) Advance(from int) {
b.start += from
}
func (b *Buffer) Truncate(to int) {
b.end = b.start + to
}
func (b *Buffer) Write(data []byte) (n int, err error) {
if b.IsFull() {
return 0, io.ErrShortBuffer
}
n = copy(b.data[b.end:], data)
b.end += n
return
}
func (b *Buffer) WriteAtFirst(data []byte) (n int, err error) {
size := len(data)
if b.start >= size {
n = copy(b.data[b.start-size:b.start], data)
b.start -= n
return
}
offset := size - b.start
copy(b.data[offset:], b.data[b.start:b.end])
n = copy(b.data[:offset], data)
b.end += offset
return
}
func (b *Buffer) WriteRandom(size int) {
common.Must1(io.ReadFull(rand.Reader, b.Extend(size)))
}
func (b *Buffer) WriteByte(byte byte) error {
if b.IsFull() {
return io.ErrShortBuffer
}
b.data[b.end] = byte
b.end++
return nil
}
func (b *Buffer) ReadFrom(r io.Reader) (int64, error) {
if b.IsFull() {
return 0, io.ErrShortBuffer
}
n, err := r.Read(b.FreeBytes())
if err != nil {
return 0, err
}
b.end += n
return int64(n), nil
}
func (b *Buffer) ReadFullFrom(r io.Reader, size int) (n int, err error) {
if b.IsFull() {
return 0, io.ErrShortBuffer
}
end := b.end + size
n, err = io.ReadFull(r, b.data[b.start:end])
if err != nil {
return 0, err
}
b.end += n
return
}
func (b *Buffer) WriteRune(s rune) (int, error) {
return b.Write([]byte{byte(s)})
}
func (b *Buffer) WriteString(s string) (int, error) {
return b.Write([]byte(s))
}
func (b *Buffer) WriteSprint(s ...any) (int, error) {
return b.WriteString(fmt.Sprint(s...))
}
func (b *Buffer) WriteZero() error {
if b.IsFull() {
return io.ErrShortBuffer
}
b.end++
b.data[b.end] = 0
return nil
}
func (b *Buffer) WriteZeroN(n int) error {
if b.end+n > b.Cap() {
return io.ErrShortBuffer
}
for i := b.end; i <= b.end+n; i++ {
b.data[i] = 0
}
b.end += n
return nil
}
func (b *Buffer) ReadByte() (byte, error) {
if b.IsEmpty() {
return 0, io.EOF
}
nb := b.data[b.start]
b.start++
return nb, nil
}
func (b *Buffer) ReadBytes(n int) ([]byte, error) {
if b.end-b.start < n {
return nil, io.EOF
}
nb := b.data[b.start : b.start+n]
b.start += n
return nb, nil
}
func (b *Buffer) Read(data []byte) (n int, err error) {
if b.Len() == 0 {
return 0, io.EOF
}
n = copy(data, b.data[b.start:b.end])
if n == b.Len() {
b.Reset()
} else {
b.start += n
}
return n, nil
}
func (b *Buffer) WriteTo(w io.Writer) (int64, error) {
n, err := w.Write(b.Bytes())
return int64(n), err
}
func (b *Buffer) Resize(start, end int) {
b.start = start
b.end = b.start + end
}
func (b *Buffer) Reset() {
b.start = ReversedHeader
b.end = ReversedHeader
}
func (b *Buffer) Release() {
if b == nil || b.data == nil || !b.managed {
return
}
PutBytes(b.data)
*b = Buffer{}
}
func (b Buffer) Len() int {
return b.end - b.start
}
func (b Buffer) Cap() int {
return cap(b.data)
}
func (b Buffer) Bytes() []byte {
return b.data[b.start:b.end]
}
func (b Buffer) Slice() []byte {
return b.data
}
func (b Buffer) From(n int) []byte {
return b.data[b.start+n : b.end]
}
func (b Buffer) To(n int) []byte {
return b.data[b.start : b.start+n]
}
func (b Buffer) Index(start int) []byte {
return b.data[b.start+start : b.start+start]
}
func (b Buffer) FreeLen() int {
return b.Cap() - b.end
}
func (b Buffer) FreeBytes() []byte {
return b.data[b.end:b.Cap()]
}
func (b Buffer) IsEmpty() bool {
return b.end-b.start == 0
}
func (b Buffer) IsFull() bool {
return b.end == b.Cap()
}
func (b Buffer) ToOwned() *Buffer {
var buffer *Buffer
if b.Len() > BufferSize {
buffer = As(make([]byte, b.Len()))
copy(buffer.data, b.Bytes())
} else {
buffer = New()
buffer.Write(b.Bytes())
}
return buffer
}
func (b Buffer) Copy() []byte {
buffer := make([]byte, b.Len())
copy(buffer, b.Bytes())
return buffer
}
func ReleaseMulti(mb *list.List[*Buffer]) {
for entry := mb.Front(); entry != nil; entry = entry.Next() {
// TODO: remove cast
var buffer *Buffer = entry.Value
buffer.Release()
}
}
func ForeachN(b []byte, size int) [][]byte {
total := len(b)
var index int
var retArr [][]byte
for {
nextIndex := index + size
if nextIndex < total {
retArr = append(retArr, b[index:nextIndex])
index = nextIndex
} else {
retArr = append(retArr, b[index:])
break
}
}
return retArr
}