Commit 0b2da60f authored by Egon Elbre's avatar Egon Elbre Committed by Robert Griesemer

bufio: fix UnreadSlice followed by UnreadRune

Also, fix a write check in writeBuf and make some bounds checks simpler.

LGTM=gri
R=golang-codereviews, adg, gri, r, minux
CC=golang-codereviews
https://golang.org/cl/113060043
parent 964b98e8
...@@ -30,8 +30,8 @@ var ( ...@@ -30,8 +30,8 @@ var (
// Reader implements buffering for an io.Reader object. // Reader implements buffering for an io.Reader object.
type Reader struct { type Reader struct {
buf []byte buf []byte
rd io.Reader rd io.Reader // reader provided by the client
r, w int r, w int // buf read and write positions
err error err error
lastByte int lastByte int
lastRuneSize int lastRuneSize int
...@@ -131,18 +131,17 @@ func (b *Reader) Peek(n int) ([]byte, error) { ...@@ -131,18 +131,17 @@ func (b *Reader) Peek(n int) ([]byte, error) {
for b.w-b.r < n && b.err == nil { for b.w-b.r < n && b.err == nil {
b.fill() // b.w-b.r < len(b.buf) => buffer is not full b.fill() // b.w-b.r < len(b.buf) => buffer is not full
} }
m := b.w - b.r
if m > n {
m = n
}
var err error var err error
if m < n { if avail := b.w - b.r; avail < n {
// not enough data in buffer
n = avail
err = b.readErr() err = b.readErr()
if err == nil { if err == nil {
err = ErrBufferFull err = ErrBufferFull
} }
} }
return b.buf[b.r : b.r+m], err return b.buf[b.r : b.r+n], err
} }
// Read reads data into p. // Read reads data into p.
...@@ -173,15 +172,13 @@ func (b *Reader) Read(p []byte) (n int, err error) { ...@@ -173,15 +172,13 @@ func (b *Reader) Read(p []byte) (n int, err error) {
return n, b.readErr() return n, b.readErr()
} }
b.fill() // buffer is empty b.fill() // buffer is empty
if b.w == b.r { if b.r == b.w {
return 0, b.readErr() return 0, b.readErr()
} }
} }
if n > b.w-b.r { // copy as much as we can
n = b.w - b.r n = copy(p, b.buf[b.r:b.w])
}
copy(p[0:n], b.buf[b.r:])
b.r += n b.r += n
b.lastByte = int(b.buf[b.r-1]) b.lastByte = int(b.buf[b.r-1])
b.lastRuneSize = -1 b.lastRuneSize = -1
...@@ -288,7 +285,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) { ...@@ -288,7 +285,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
} }
// Buffer full? // Buffer full?
if n := b.Buffered(); n >= len(b.buf) { if b.Buffered() >= len(b.buf) {
b.r = b.w b.r = b.w
line = b.buf line = b.buf
err = ErrBufferFull err = ErrBufferFull
...@@ -301,6 +298,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) { ...@@ -301,6 +298,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
// Handle last byte, if any. // Handle last byte, if any.
if i := len(line) - 1; i >= 0 { if i := len(line) - 1; i >= 0 {
b.lastByte = int(line[i]) b.lastByte = int(line[i])
b.lastRuneSize = -1
} }
return return
...@@ -458,11 +456,13 @@ func (b *Reader) WriteTo(w io.Writer) (n int64, err error) { ...@@ -458,11 +456,13 @@ func (b *Reader) WriteTo(w io.Writer) (n int64, err error) {
return n, b.readErr() return n, b.readErr()
} }
var errNegativeWrite = errors.New("bufio: writer returned negative count from Write")
// writeBuf writes the Reader's buffer to the writer. // writeBuf writes the Reader's buffer to the writer.
func (b *Reader) writeBuf(w io.Writer) (int64, error) { func (b *Reader) writeBuf(w io.Writer) (int64, error) {
n, err := w.Write(b.buf[b.r:b.w]) n, err := w.Write(b.buf[b.r:b.w])
if n < b.r-b.w { if n < 0 {
panic(errors.New("bufio: writer did not write all data")) panic(errNegativeWrite)
} }
b.r += n b.r += n
return int64(n), err return int64(n), err
......
...@@ -463,6 +463,18 @@ func TestUnreadRuneError(t *testing.T) { ...@@ -463,6 +463,18 @@ func TestUnreadRuneError(t *testing.T) {
if r.UnreadRune() == nil { if r.UnreadRune() == nil {
t.Error("expected error after UnreadByte (3)") t.Error("expected error after UnreadByte (3)")
} }
// Test error after ReadSlice.
_, _, err = r.ReadRune() // reset state
if err != nil {
t.Error("unexpected error on ReadRune (4):", err)
}
_, err = r.ReadSlice(0)
if err != io.EOF {
t.Error("unexpected error on ReadSlice (4):", err)
}
if r.UnreadRune() == nil {
t.Error("expected error after ReadSlice (4)")
}
} }
func TestUnreadRuneAtEOF(t *testing.T) { func TestUnreadRuneAtEOF(t *testing.T) {
......
...@@ -64,8 +64,9 @@ var ( ...@@ -64,8 +64,9 @@ var (
) )
const ( const (
// Maximum size used to buffer a token. The actual maximum token size // MaxScanTokenSize is the maximum size used to buffer a token.
// may be smaller as the buffer may need to include, for instance, a newline. // The actual maximum token size may be smaller as the buffer
// may need to include, for instance, a newline.
MaxScanTokenSize = 64 * 1024 MaxScanTokenSize = 64 * 1024
) )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment