zworld-demo/library/zos/reader.go

128 lines
2.0 KiB
Go
Raw Normal View History

2023-12-22 22:04:27 +08:00
package zos
import (
"bytes"
"io"
"os"
)
func min(a int, b int) int {
if a < b {
return a
}
return b
}
type FReader struct {
io io.Reader
buf []byte
r, w int
err error
}
func NewReader(io io.Reader) *FReader {
return &FReader{
io: io,
buf: make([]byte, 4096),
r: 0,
w: 0,
}
}
func (b *FReader) Read(data []byte) (int, error) {
n, rn := len(data), 0
for rn < n {
d := min(b.w-b.r, n-rn)
if d > 0 {
copy(data[rn:rn+d], b.buf[b.r:b.r+d])
b.r += d
rn += d
if rn >= n {
break
}
}
err := b.fill()
if err != nil {
return rn, err
}
}
return rn, nil
}
func (b *FReader) ReadLine() ([]byte, error) {
line, err := b.ReadSlice('\n')
i := len(line) - 1
if i >= 0 && line[i] == '\r' {
return line[:i], err
}
return line, err
}
func (b *FReader) ReadLineFast() ([]byte, error) {
line, err := b.ReadSliceFast('\n')
i := len(line) - 1
if i >= 0 && line[i] == '\r' {
return line[:i], err
}
return line, err
}
func (b *FReader) ReadSlice(delim byte) ([]byte, error) {
var lines []byte
for {
line, err := b.ReadSliceFast(delim)
if err == nil || err != ErrBufferFull {
return line, err
}
lines = append(lines, line...)
}
return lines, nil
}
func (b *FReader) ReadSliceFast(delim byte) ([]byte, error) {
for {
// Search buffer.
if i := bytes.IndexByte(b.buf[b.r+0:b.w], delim); i >= 0 {
i += 1
b.r += i
return b.buf[b.r-i : b.r-1], nil
}
err := b.fill()
if err != nil {
return b.buf[b.r:], err
}
}
}
func (b *FReader) fill() error {
d := b.w - b.r
if d >= len(b.buf) {
b.r = 0
b.w = 0
return ErrBufferFull
}
// Slide existing data to beginning.
if b.r > 0 {
copy(b.buf, b.buf[b.r:b.w])
b.w -= b.r
b.r = 0
}
// Read new data: try a limited number of times.
n, err := b.io.Read(b.buf[b.w:])
b.w += n
return err
}
func (b *FReader) Clear() {
b.r = 0
b.w = 0
}
func (b *FReader) Seek(pos, offset int) {
r := b.r + offset
if r >= 0 && r <= b.w {
b.r = r
return
}
f, ok := b.io.(*os.File)
if ok {
f.Seek(int64(pos), 0)
b.r = 0
b.w = 0
}
}