]> Cypherpunks repositories - gostls13.git/commitdiff
fix bufio bugs involving readers that return os.EOF with
authorRuss Cox <rsc@golang.org>
Wed, 26 Aug 2009 23:23:34 +0000 (16:23 -0700)
committerRuss Cox <rsc@golang.org>
Wed, 26 Aug 2009 23:23:34 +0000 (16:23 -0700)
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

src/pkg/bufio/bufio.go
src/pkg/bufio/bufio_test.go
src/pkg/testing/iotest/reader.go

index 295647d5a08d28294efaa6e71793205beb7ed30c..4f97871035b300f52e256e27c6cc51a204e2562b 100644 (file)
@@ -90,12 +90,8 @@ func NewReader(rd io.Reader) *Reader {
        return b;
 }
 
-//.fill reads a new chunk into the buffer.
-func (b *Reader) fill() os.Error {
-       if b.err != nil {
-               return b.err
-       }
-
+// fill reads a new chunk into the buffer.
+func (b *Reader) fill() {
        // Slide existing data to beginning.
        if b.w > b.r {
                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;
        if e != nil {
                b.err = e;
-               return e
        }
-       return nil
 }
 
 // Read reads data into p.
@@ -125,6 +119,9 @@ func (b *Reader) Read(p []byte) (nn int, err os.Error) {
        for len(p) > 0 {
                n := len(p);
                if b.w == b.r {
+                       if b.err != nil {
+                               return nn, b.err
+                       }
                        if len(p) >= len(b.buf) {
                                // Large read, empty buffer.
                                // 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)];
                                nn += n;
-                               if b.err != nil {
-                                       return nn, b.err
-                               }
                                continue;
                        }
                        b.fill();
-                       if b.err != nil {
-                               return nn, b.err
-                       }
+                       continue;
                }
                if 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.
 // If no byte is available, returns an error.
 func (b *Reader) ReadByte() (c byte, err os.Error) {
-       if b.w == b.r {
-               b.fill();
+       for b.w == b.r {
                if b.err != nil {
                        return 0, b.err
                }
+               b.fill();
        }
        c = b.buf[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.
 func (b *Reader) UnreadByte() os.Error {
-       if b.err != nil {
-               return b.err
-       }
        if b.r == b.w && b.lastbyte >= 0 {
                b.w = 1;
                b.r = 0;
@@ -194,14 +183,11 @@ func (b *Reader) UnreadByte() os.Error {
 // ReadRune reads a single UTF-8 encoded Unicode character and returns the
 // rune and its size in bytes.
 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();
-               if b.err != nil {
-                       if b.r == b.w {
-                               return 0, 0, b.err;
-                       }
-                       break;
-               }
+       }
+       if b.r == b.w {
+               return 0, 0, b.err;
        }
        rune, size = int(b.buf[b.r]), 1;
        if rune >= 0x80 {
@@ -235,10 +221,6 @@ func (b *Reader) Buffered() int {
 // For internal or advanced use only; most uses should
 // call ReadLineString or ReadLineBytes instead.
 func (b *Reader) ReadLineSlice(delim byte) (line []byte, err os.Error) {
-       if b.err != nil {
-               return nil, b.err
-       }
-
        // Look in buffer.
        if i := findByte(b.buf[b.r:b.w], delim); i >= 0 {
                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.
        for {
-               n := b.Buffered();
-               b.fill();
                if b.err != nil {
                        line := b.buf[b.r:b.w];
                        b.r = b.w;
                        return line, b.err
                }
 
+               n := b.Buffered();
+               b.fill();
+
                // Search new part of buffer
                if i := findByte(b.buf[n:b.w], delim); i >= 0 {
                        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
 // it might have read more than the buffer size.)
 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,
        // accumulating full buffers.
        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.
 func (b *Reader) ReadLineString(delim byte, savedelim bool) (line string, err os.Error) {
        bytes, e := b.ReadLineBytes(delim);
-       if e != nil {
-               return string(bytes), e
-       }
-       if !savedelim {
-               bytes = bytes[0:len(bytes)-1]
+       if n := len(bytes); !savedelim && n > 0 && bytes[n-1] == delim {
+               bytes = bytes[0:n-1]
        }
-       return string(bytes), nil
+       return string(bytes), e;
 }
 
 
index c04ebf214e334920e5c55106549e77b23437f46d..389b4097de285e4aa81f99eeaf4b2bcd83398593 100644 (file)
@@ -81,6 +81,7 @@ var readMakers = []readMaker {
        readMaker{ "full", func(r io.Reader) io.Reader { return r } },
        readMaker{ "byte", iotest.OneByteReader },
        readMaker{ "half", iotest.HalfReader },
+       readMaker{ "data+err", iotest.DataErrReader },
 }
 
 // Call ReadLineString (which ends up calling everything else)
index 0bb8633388a3a4c79c6e73cfb95f992809a3c056..c7ab6dc971d9d9a8577521e51a6f774c24bdc267 100644 (file)
@@ -9,8 +9,15 @@ package iotest
 import (
        "io";
        "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 {
        r io.Reader;
 }
@@ -22,10 +29,10 @@ func (r *oneByteReader) Read(p []byte) (int, os.Error) {
        return r.r.Read(p[0:1]);
 }
 
-// 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};
+// HalfReader returns a Reader that implements Read
+// by reading half as many requested bytes from r.
+func HalfReader(r io.Reader) io.Reader {
+       return &halfReader{r};
 }
 
 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]);
 }
 
-// HalfReader returns a Reader that implements Read
-// by reading half as many requested bytes from r.
-func HalfReader(r io.Reader) io.Reader {
-       return &halfReader{r};
+
+// DataErrReader returns a Reader that returns the final
+// error with the last data read, instead of by itself with
+// 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;
 }