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:
parent
26a2642fc3
commit
29415d0557
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user