mirror of https://github.com/golang/go.git
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
This commit is contained in:
parent
964b98e8c3
commit
0b2da60fb8
|
|
@ -30,8 +30,8 @@ var (
|
|||
// Reader implements buffering for an io.Reader object.
|
||||
type Reader struct {
|
||||
buf []byte
|
||||
rd io.Reader
|
||||
r, w int
|
||||
rd io.Reader // reader provided by the client
|
||||
r, w int // buf read and write positions
|
||||
err error
|
||||
lastByte int
|
||||
lastRuneSize int
|
||||
|
|
@ -131,18 +131,17 @@ func (b *Reader) Peek(n int) ([]byte, error) {
|
|||
for b.w-b.r < n && b.err == nil {
|
||||
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
|
||||
if m < n {
|
||||
if avail := b.w - b.r; avail < n {
|
||||
// not enough data in buffer
|
||||
n = avail
|
||||
err = b.readErr()
|
||||
if err == nil {
|
||||
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.
|
||||
|
|
@ -173,15 +172,13 @@ func (b *Reader) Read(p []byte) (n int, err error) {
|
|||
return n, b.readErr()
|
||||
}
|
||||
b.fill() // buffer is empty
|
||||
if b.w == b.r {
|
||||
if b.r == b.w {
|
||||
return 0, b.readErr()
|
||||
}
|
||||
}
|
||||
|
||||
if n > b.w-b.r {
|
||||
n = b.w - b.r
|
||||
}
|
||||
copy(p[0:n], b.buf[b.r:])
|
||||
// copy as much as we can
|
||||
n = copy(p, b.buf[b.r:b.w])
|
||||
b.r += n
|
||||
b.lastByte = int(b.buf[b.r-1])
|
||||
b.lastRuneSize = -1
|
||||
|
|
@ -288,7 +285,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
|
|||
}
|
||||
|
||||
// Buffer full?
|
||||
if n := b.Buffered(); n >= len(b.buf) {
|
||||
if b.Buffered() >= len(b.buf) {
|
||||
b.r = b.w
|
||||
line = b.buf
|
||||
err = ErrBufferFull
|
||||
|
|
@ -301,6 +298,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
|
|||
// Handle last byte, if any.
|
||||
if i := len(line) - 1; i >= 0 {
|
||||
b.lastByte = int(line[i])
|
||||
b.lastRuneSize = -1
|
||||
}
|
||||
|
||||
return
|
||||
|
|
@ -458,11 +456,13 @@ func (b *Reader) WriteTo(w io.Writer) (n int64, err error) {
|
|||
return n, b.readErr()
|
||||
}
|
||||
|
||||
var errNegativeWrite = errors.New("bufio: writer returned negative count from Write")
|
||||
|
||||
// writeBuf writes the Reader's buffer to the writer.
|
||||
func (b *Reader) writeBuf(w io.Writer) (int64, error) {
|
||||
n, err := w.Write(b.buf[b.r:b.w])
|
||||
if n < b.r-b.w {
|
||||
panic(errors.New("bufio: writer did not write all data"))
|
||||
if n < 0 {
|
||||
panic(errNegativeWrite)
|
||||
}
|
||||
b.r += n
|
||||
return int64(n), err
|
||||
|
|
|
|||
|
|
@ -463,6 +463,18 @@ func TestUnreadRuneError(t *testing.T) {
|
|||
if r.UnreadRune() == nil {
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -64,8 +64,9 @@ var (
|
|||
)
|
||||
|
||||
const (
|
||||
// Maximum size used to buffer a token. The actual maximum token size
|
||||
// may be smaller as the buffer may need to include, for instance, a newline.
|
||||
// MaxScanTokenSize is the maximum size used to buffer a token.
|
||||
// The actual maximum token size may be smaller as the buffer
|
||||
// may need to include, for instance, a newline.
|
||||
MaxScanTokenSize = 64 * 1024
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue