mirror of
https://github.com/golang/go
synced 2024-11-13 18:20:32 -07:00
bufio: introduce Peek.
I'll leave whether or not this obsoletes UnreadByte for a future CL. R=r, rsc CC=golang-dev https://golang.org/cl/1912042
This commit is contained in:
parent
e45b58fe96
commit
27e249049e
@ -28,6 +28,7 @@ type Error struct {
|
|||||||
var (
|
var (
|
||||||
ErrInvalidUnreadByte os.Error = &Error{"bufio: invalid use of UnreadByte"}
|
ErrInvalidUnreadByte os.Error = &Error{"bufio: invalid use of UnreadByte"}
|
||||||
ErrBufferFull os.Error = &Error{"bufio: buffer full"}
|
ErrBufferFull os.Error = &Error{"bufio: buffer full"}
|
||||||
|
ErrNegativeCount os.Error = &Error{"bufio: negative count"}
|
||||||
errInternal os.Error = &Error{"bufio: internal error"}
|
errInternal os.Error = &Error{"bufio: internal error"}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -83,13 +84,11 @@ func NewReader(rd io.Reader) *Reader {
|
|||||||
// fill reads a new chunk into the buffer.
|
// fill reads a new chunk into the buffer.
|
||||||
func (b *Reader) fill() {
|
func (b *Reader) fill() {
|
||||||
// Slide existing data to beginning.
|
// Slide existing data to beginning.
|
||||||
if b.w > b.r {
|
if b.r > 0 {
|
||||||
copy(b.buf[0:b.w-b.r], b.buf[b.r:b.w])
|
copy(b.buf, b.buf[b.r:b.w])
|
||||||
b.w -= b.r
|
b.w -= b.r
|
||||||
} else {
|
|
||||||
b.w = 0
|
|
||||||
}
|
|
||||||
b.r = 0
|
b.r = 0
|
||||||
|
}
|
||||||
|
|
||||||
// Read new data.
|
// Read new data.
|
||||||
n, e := b.rd.Read(b.buf[b.w:])
|
n, e := b.rd.Read(b.buf[b.w:])
|
||||||
@ -99,6 +98,31 @@ func (b *Reader) fill() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Peek returns the next n bytes without advancing the reader. The bytes stop
|
||||||
|
// being valid at the next read call. If Peek returns fewer than n bytes, it
|
||||||
|
// also returns an error explaining why the read is short. The error is
|
||||||
|
// ErrBufferFull if n is larger than b's buffer size.
|
||||||
|
func (b *Reader) Peek(n int) ([]byte, os.Error) {
|
||||||
|
if n < 0 {
|
||||||
|
return nil, ErrNegativeCount
|
||||||
|
}
|
||||||
|
if n > len(b.buf) {
|
||||||
|
return nil, ErrBufferFull
|
||||||
|
}
|
||||||
|
for b.w-b.r < n && b.err == nil {
|
||||||
|
b.fill()
|
||||||
|
}
|
||||||
|
m := b.w - b.r
|
||||||
|
if m > n {
|
||||||
|
m = n
|
||||||
|
}
|
||||||
|
err := b.err
|
||||||
|
if m < n && err == nil {
|
||||||
|
err = ErrBufferFull
|
||||||
|
}
|
||||||
|
return b.buf[b.r : b.r+m], err
|
||||||
|
}
|
||||||
|
|
||||||
// Read reads data into p.
|
// Read reads data into p.
|
||||||
// It returns the number of bytes read into p.
|
// It returns the number of bytes read into p.
|
||||||
// If nn < len(p), also returns an error explaining
|
// If nn < len(p), also returns an error explaining
|
||||||
@ -129,7 +153,7 @@ func (b *Reader) Read(p []byte) (nn int, err os.Error) {
|
|||||||
if n > b.w-b.r {
|
if n > b.w-b.r {
|
||||||
n = b.w - b.r
|
n = b.w - b.r
|
||||||
}
|
}
|
||||||
copy(p[0:n], b.buf[b.r:b.r+n])
|
copy(p[0:n], b.buf[b.r:])
|
||||||
p = p[n:]
|
p = p[n:]
|
||||||
b.r += n
|
b.r += n
|
||||||
b.lastbyte = int(b.buf[b.r-1])
|
b.lastbyte = int(b.buf[b.r-1])
|
||||||
@ -291,10 +315,10 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err os.Error) {
|
|||||||
buf := make([]byte, n)
|
buf := make([]byte, n)
|
||||||
n = 0
|
n = 0
|
||||||
for i := 0; i < nfull; i++ {
|
for i := 0; i < nfull; i++ {
|
||||||
copy(buf[n:n+len(full[i])], full[i])
|
copy(buf[n:], full[i])
|
||||||
n += len(full[i])
|
n += len(full[i])
|
||||||
}
|
}
|
||||||
copy(buf[n:n+len(frag)], frag)
|
copy(buf[n:], frag)
|
||||||
return buf, err
|
return buf, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,3 +419,41 @@ func TestBufferFull(t *testing.T) {
|
|||||||
t.Errorf("second ReadSlice(,) = %q, %v", line, err)
|
t.Errorf("second ReadSlice(,) = %q, %v", line, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPeek(t *testing.T) {
|
||||||
|
p := make([]byte, 10)
|
||||||
|
buf, _ := NewReaderSize(strings.NewReader("abcdefghij"), 4)
|
||||||
|
if s, err := buf.Peek(1); string(s) != "a" || err != nil {
|
||||||
|
t.Fatalf("want %q got %q, err=%v", "a", string(s), err)
|
||||||
|
}
|
||||||
|
if s, err := buf.Peek(4); string(s) != "abcd" || err != nil {
|
||||||
|
t.Fatalf("want %q got %q, err=%v", "abcd", string(s), err)
|
||||||
|
}
|
||||||
|
if _, err := buf.Peek(5); err != ErrBufferFull {
|
||||||
|
t.Fatalf("want ErrBufFull got %v", err)
|
||||||
|
}
|
||||||
|
if _, err := buf.Read(p[0:3]); string(p[0:3]) != "abc" || err != nil {
|
||||||
|
t.Fatalf("want %q got %q, err=%v", "abc", string(p[0:3]), err)
|
||||||
|
}
|
||||||
|
if s, err := buf.Peek(1); string(s) != "d" || err != nil {
|
||||||
|
t.Fatalf("want %q got %q, err=%v", "d", string(s), err)
|
||||||
|
}
|
||||||
|
if s, err := buf.Peek(2); string(s) != "de" || err != nil {
|
||||||
|
t.Fatalf("want %q got %q, err=%v", "de", string(s), err)
|
||||||
|
}
|
||||||
|
if _, err := buf.Read(p[0:3]); string(p[0:3]) != "def" || err != nil {
|
||||||
|
t.Fatalf("want %q got %q, err=%v", "def", string(p[0:3]), err)
|
||||||
|
}
|
||||||
|
if s, err := buf.Peek(4); string(s) != "ghij" || err != nil {
|
||||||
|
t.Fatalf("want %q got %q, err=%v", "ghij", string(s), err)
|
||||||
|
}
|
||||||
|
if _, err := buf.Read(p[0:4]); string(p[0:4]) != "ghij" || err != nil {
|
||||||
|
t.Fatalf("want %q got %q, err=%v", "ghij", string(p[0:3]), err)
|
||||||
|
}
|
||||||
|
if s, err := buf.Peek(0); string(s) != "" || err != nil {
|
||||||
|
t.Fatalf("want %q got %q, err=%v", "", string(s), err)
|
||||||
|
}
|
||||||
|
if _, err := buf.Peek(1); err != os.EOF {
|
||||||
|
t.Fatalf("want EOF got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user