1
0
mirror of https://github.com/golang/go synced 2024-11-20 10:54:49 -07:00

fix bufio bugs involving readers that return os.EOF with

the last bit of data.

add a new iotest.DataErrReader for tests

R=r
DELTA=93  (41 added, 31 deleted, 21 changed)
OCL=33897
CL=33915
This commit is contained in:
Russ Cox 2009-08-26 16:23:34 -07:00
parent 26a2642fc3
commit 29415d0557
3 changed files with 60 additions and 50 deletions

View File

@ -90,12 +90,8 @@ func NewReader(rd io.Reader) *Reader {
return b; return b;
} }
//.fill reads a new chunk into the buffer. // fill reads a new chunk into the buffer.
func (b *Reader) fill() os.Error { func (b *Reader) fill() {
if b.err != nil {
return b.err
}
// Slide existing data to beginning. // Slide existing data to beginning.
if b.w > b.r { if b.w > b.r {
copySlice(b.buf[0:b.w-b.r], b.buf[b.r:b.w]); copySlice(b.buf[0:b.w-b.r], b.buf[b.r:b.w]);
@ -110,9 +106,7 @@ func (b *Reader) fill() os.Error {
b.w += n; b.w += n;
if e != nil { if e != nil {
b.err = e; b.err = e;
return e
} }
return nil
} }
// Read reads data into p. // Read reads data into p.
@ -125,6 +119,9 @@ func (b *Reader) Read(p []byte) (nn int, err os.Error) {
for len(p) > 0 { for len(p) > 0 {
n := len(p); n := len(p);
if b.w == b.r { if b.w == b.r {
if b.err != nil {
return nn, b.err
}
if len(p) >= len(b.buf) { if len(p) >= len(b.buf) {
// Large read, empty buffer. // Large read, empty buffer.
// Read directly into p to avoid copy. // Read directly into p to avoid copy.
@ -134,15 +131,10 @@ func (b *Reader) Read(p []byte) (nn int, err os.Error) {
} }
p = p[n:len(p)]; p = p[n:len(p)];
nn += n; nn += n;
if b.err != nil {
return nn, b.err
}
continue; continue;
} }
b.fill(); b.fill();
if b.err != nil { continue;
return nn, b.err
}
} }
if n > b.w - b.r { if n > b.w - b.r {
n = b.w - b.r n = b.w - b.r
@ -159,11 +151,11 @@ func (b *Reader) Read(p []byte) (nn int, err os.Error) {
// ReadByte reads and returns a single byte. // ReadByte reads and returns a single byte.
// If no byte is available, returns an error. // If no byte is available, returns an error.
func (b *Reader) ReadByte() (c byte, err os.Error) { func (b *Reader) ReadByte() (c byte, err os.Error) {
if b.w == b.r { for b.w == b.r {
b.fill();
if b.err != nil { if b.err != nil {
return 0, b.err return 0, b.err
} }
b.fill();
} }
c = b.buf[b.r]; c = b.buf[b.r];
b.r++; b.r++;
@ -173,9 +165,6 @@ func (b *Reader) ReadByte() (c byte, err os.Error) {
// UnreadByte unreads the last byte. Only the most recently read byte can be unread. // UnreadByte unreads the last byte. Only the most recently read byte can be unread.
func (b *Reader) UnreadByte() os.Error { func (b *Reader) UnreadByte() os.Error {
if b.err != nil {
return b.err
}
if b.r == b.w && b.lastbyte >= 0 { if b.r == b.w && b.lastbyte >= 0 {
b.w = 1; b.w = 1;
b.r = 0; b.r = 0;
@ -194,15 +183,12 @@ func (b *Reader) UnreadByte() os.Error {
// ReadRune reads a single UTF-8 encoded Unicode character and returns the // ReadRune reads a single UTF-8 encoded Unicode character and returns the
// rune and its size in bytes. // rune and its size in bytes.
func (b *Reader) ReadRune() (rune int, size int, err os.Error) { func (b *Reader) ReadRune() (rune int, size int, err os.Error) {
for b.r + utf8.UTFMax > b.w && !utf8.FullRune(b.buf[b.r:b.w]) { for b.r + utf8.UTFMax > b.w && !utf8.FullRune(b.buf[b.r:b.w]) && b.err == nil {
b.fill(); b.fill();
if b.err != nil { }
if b.r == b.w { if b.r == b.w {
return 0, 0, b.err; return 0, 0, b.err;
} }
break;
}
}
rune, size = int(b.buf[b.r]), 1; rune, size = int(b.buf[b.r]), 1;
if rune >= 0x80 { if rune >= 0x80 {
rune, size = utf8.DecodeRune(b.buf[b.r:b.w]); rune, size = utf8.DecodeRune(b.buf[b.r:b.w]);
@ -235,10 +221,6 @@ func (b *Reader) Buffered() int {
// For internal or advanced use only; most uses should // For internal or advanced use only; most uses should
// call ReadLineString or ReadLineBytes instead. // call ReadLineString or ReadLineBytes instead.
func (b *Reader) ReadLineSlice(delim byte) (line []byte, err os.Error) { func (b *Reader) ReadLineSlice(delim byte) (line []byte, err os.Error) {
if b.err != nil {
return nil, b.err
}
// Look in buffer. // Look in buffer.
if i := findByte(b.buf[b.r:b.w], delim); i >= 0 { if i := findByte(b.buf[b.r:b.w], delim); i >= 0 {
line1 := b.buf[b.r:b.r+i+1]; line1 := b.buf[b.r:b.r+i+1];
@ -248,14 +230,15 @@ func (b *Reader) ReadLineSlice(delim byte) (line []byte, err os.Error) {
// Read more into buffer, until buffer fills or we find delim. // Read more into buffer, until buffer fills or we find delim.
for { for {
n := b.Buffered();
b.fill();
if b.err != nil { if b.err != nil {
line := b.buf[b.r:b.w]; line := b.buf[b.r:b.w];
b.r = b.w; b.r = b.w;
return line, b.err return line, b.err
} }
n := b.Buffered();
b.fill();
// Search new part of buffer // Search new part of buffer
if i := findByte(b.buf[n:b.w], delim); i >= 0 { if i := findByte(b.buf[n:b.w], delim); i >= 0 {
line := b.buf[0:n+i+1]; line := b.buf[0:n+i+1];
@ -277,10 +260,6 @@ func (b *Reader) ReadLineSlice(delim byte) (line []byte, err os.Error) {
// and the error. (It can't leave the data in the buffer because // and the error. (It can't leave the data in the buffer because
// it might have read more than the buffer size.) // it might have read more than the buffer size.)
func (b *Reader) ReadLineBytes(delim byte) (line []byte, err os.Error) { func (b *Reader) ReadLineBytes(delim byte) (line []byte, err os.Error) {
if b.err != nil {
return nil, b.err
}
// Use ReadLineSlice to look for array, // Use ReadLineSlice to look for array,
// accumulating full buffers. // accumulating full buffers.
var frag []byte; var frag []byte;
@ -353,13 +332,10 @@ func (b *Reader) ReadLineBytes(delim byte) (line []byte, err os.Error) {
// If savedelim, keep delim in the result; otherwise drop it. // If savedelim, keep delim in the result; otherwise drop it.
func (b *Reader) ReadLineString(delim byte, savedelim bool) (line string, err os.Error) { func (b *Reader) ReadLineString(delim byte, savedelim bool) (line string, err os.Error) {
bytes, e := b.ReadLineBytes(delim); bytes, e := b.ReadLineBytes(delim);
if e != nil { if n := len(bytes); !savedelim && n > 0 && bytes[n-1] == delim {
return string(bytes), e bytes = bytes[0:n-1]
} }
if !savedelim { return string(bytes), e;
bytes = bytes[0:len(bytes)-1]
}
return string(bytes), nil
} }

View File

@ -81,6 +81,7 @@ var readMakers = []readMaker {
readMaker{ "full", func(r io.Reader) io.Reader { return r } }, readMaker{ "full", func(r io.Reader) io.Reader { return r } },
readMaker{ "byte", iotest.OneByteReader }, readMaker{ "byte", iotest.OneByteReader },
readMaker{ "half", iotest.HalfReader }, readMaker{ "half", iotest.HalfReader },
readMaker{ "data+err", iotest.DataErrReader },
} }
// Call ReadLineString (which ends up calling everything else) // Call ReadLineString (which ends up calling everything else)

View File

@ -9,8 +9,15 @@ package iotest
import ( import (
"io"; "io";
"os"; "os";
"bytes";
) )
// OneByteReader returns a Reader that implements
// each non-empty Read by reading one byte from r.
func OneByteReader(r io.Reader) io.Reader {
return &oneByteReader{r};
}
type oneByteReader struct { type oneByteReader struct {
r io.Reader; r io.Reader;
} }
@ -22,10 +29,10 @@ func (r *oneByteReader) Read(p []byte) (int, os.Error) {
return r.r.Read(p[0:1]); return r.r.Read(p[0:1]);
} }
// OneByteReader returns a Reader that implements // HalfReader returns a Reader that implements Read
// each non-empty Read by reading one byte from r. // by reading half as many requested bytes from r.
func OneByteReader(r io.Reader) io.Reader { func HalfReader(r io.Reader) io.Reader {
return &oneByteReader{r}; return &halfReader{r};
} }
type halfReader struct { type halfReader struct {
@ -36,9 +43,35 @@ func (r *halfReader) Read(p []byte) (int, os.Error) {
return r.r.Read(p[0:(len(p)+1)/2]); return r.r.Read(p[0:(len(p)+1)/2]);
} }
// HalfReader returns a Reader that implements Read
// by reading half as many requested bytes from r. // DataErrReader returns a Reader that returns the final
func HalfReader(r io.Reader) io.Reader { // error with the last data read, instead of by itself with
return &halfReader{r}; // zero bytes of data.
func DataErrReader(r io.Reader) io.Reader {
return &dataErrReader{r, nil, make([]byte, 1024)};
}
type dataErrReader struct {
r io.Reader;
unread []byte;
data []byte;
}
func (r *dataErrReader) Read(p []byte) (n int, err os.Error) {
// loop because first call needs two reads:
// one to get data and a second to look for an error.
for {
if len(r.unread) == 0 {
n1, err1 := r.r.Read(r.data);
r.unread = r.data[0:n1];
err = err1;
}
if n > 0 {
break;
}
n = bytes.Copy(p, r.unread);
r.unread = r.unread[n:len(r.unread)];
}
return;
} }