128 lines
2.0 KiB
Go
128 lines
2.0 KiB
Go
|
|
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
|
||
|
|
}
|
||
|
|
}
|