v0.0.37
This commit is contained in:
parent
3552acd38b
commit
bdb181cb3a
@ -1,56 +1,157 @@
|
|||||||
package dataext
|
package dataext
|
||||||
|
|
||||||
import "io"
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type brcMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
modeSourceReading = 0
|
||||||
|
modeSourceFinished = 1
|
||||||
|
modeBufferReading = 2
|
||||||
|
modeBufferFinished = 3
|
||||||
|
)
|
||||||
|
|
||||||
type BufferedReadCloser interface {
|
type BufferedReadCloser interface {
|
||||||
io.ReadCloser
|
io.ReadCloser
|
||||||
BufferedAll() ([]byte, error)
|
BufferedAll() ([]byte, error)
|
||||||
|
Reset() error
|
||||||
}
|
}
|
||||||
|
|
||||||
type bufferedReadCloser struct {
|
type bufferedReadCloser struct {
|
||||||
buffer []byte
|
buffer []byte
|
||||||
inner io.ReadCloser
|
inner io.ReadCloser
|
||||||
finished bool
|
mode brcMode
|
||||||
}
|
off int
|
||||||
|
|
||||||
func (b *bufferedReadCloser) Read(p []byte) (int, error) {
|
|
||||||
|
|
||||||
n, err := b.inner.Read(p)
|
|
||||||
if n > 0 {
|
|
||||||
b.buffer = append(b.buffer, p[0:n]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err == io.EOF {
|
|
||||||
b.finished = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return n, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBufferedReadCloser(sub io.ReadCloser) BufferedReadCloser {
|
func NewBufferedReadCloser(sub io.ReadCloser) BufferedReadCloser {
|
||||||
return &bufferedReadCloser{
|
return &bufferedReadCloser{
|
||||||
buffer: make([]byte, 0, 1024),
|
buffer: make([]byte, 0, 1024),
|
||||||
inner: sub,
|
inner: sub,
|
||||||
finished: false,
|
mode: modeSourceReading,
|
||||||
|
off: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *bufferedReadCloser) Read(p []byte) (int, error) {
|
||||||
|
switch b.mode {
|
||||||
|
case modeSourceReading:
|
||||||
|
n, err := b.inner.Read(p)
|
||||||
|
if n > 0 {
|
||||||
|
b.buffer = append(b.buffer, p[0:n]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == io.EOF {
|
||||||
|
b.mode = modeSourceFinished
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, err
|
||||||
|
|
||||||
|
case modeSourceFinished:
|
||||||
|
return 0, io.EOF
|
||||||
|
|
||||||
|
case modeBufferReading:
|
||||||
|
|
||||||
|
if len(b.buffer) <= b.off {
|
||||||
|
b.mode = modeBufferFinished
|
||||||
|
if len(p) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
n := copy(p, b.buffer[b.off:])
|
||||||
|
b.off += n
|
||||||
|
return n, nil
|
||||||
|
|
||||||
|
case modeBufferFinished:
|
||||||
|
return 0, io.EOF
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0, errors.New("object in undefined status")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bufferedReadCloser) Close() error {
|
func (b *bufferedReadCloser) Close() error {
|
||||||
err := b.inner.Close()
|
switch b.mode {
|
||||||
if err != nil {
|
case modeSourceReading:
|
||||||
b.finished = true
|
_, err := b.BufferedAll()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = b.inner.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.mode = modeSourceFinished
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case modeSourceFinished:
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case modeBufferReading:
|
||||||
|
b.mode = modeBufferFinished
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case modeBufferFinished:
|
||||||
|
return nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return errors.New("object in undefined status")
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bufferedReadCloser) BufferedAll() ([]byte, error) {
|
func (b *bufferedReadCloser) BufferedAll() ([]byte, error) {
|
||||||
arr := make([]byte, 1024)
|
switch b.mode {
|
||||||
for !b.finished {
|
case modeSourceReading:
|
||||||
_, err := b.Read(arr)
|
arr := make([]byte, 1024)
|
||||||
if err != nil && err != io.EOF {
|
for b.mode == modeSourceReading {
|
||||||
return nil, err
|
_, err := b.Read(arr)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return b.buffer, nil
|
||||||
|
|
||||||
return b.buffer, nil
|
case modeSourceFinished:
|
||||||
|
return b.buffer, nil
|
||||||
|
|
||||||
|
case modeBufferReading:
|
||||||
|
return b.buffer, nil
|
||||||
|
|
||||||
|
case modeBufferFinished:
|
||||||
|
return b.buffer, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, errors.New("object in undefined status")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *bufferedReadCloser) Reset() error {
|
||||||
|
switch b.mode {
|
||||||
|
case modeSourceReading:
|
||||||
|
fallthrough
|
||||||
|
case modeSourceFinished:
|
||||||
|
err := b.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.mode = modeBufferReading
|
||||||
|
b.off = 0
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case modeBufferReading:
|
||||||
|
fallthrough
|
||||||
|
case modeBufferFinished:
|
||||||
|
b.mode = modeBufferReading
|
||||||
|
b.off = 0
|
||||||
|
return nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return errors.New("object in undefined status")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user