diff options
Diffstat (limited to 'libgo/go/bufio')
-rw-r--r-- | libgo/go/bufio/bufio.go | 3 | ||||
-rw-r--r-- | libgo/go/bufio/bufio_test.go | 54 | ||||
-rw-r--r-- | libgo/go/bufio/example_test.go | 16 | ||||
-rw-r--r-- | libgo/go/bufio/scan.go | 2 |
4 files changed, 74 insertions, 1 deletions
diff --git a/libgo/go/bufio/bufio.go b/libgo/go/bufio/bufio.go index 0125d72..0f05d3b 100644 --- a/libgo/go/bufio/bufio.go +++ b/libgo/go/bufio/bufio.go @@ -197,6 +197,9 @@ func (b *Reader) Discard(n int) (discarded int, err error) { func (b *Reader) Read(p []byte) (n int, err error) { n = len(p) if n == 0 { + if b.Buffered() > 0 { + return 0, nil + } return 0, b.readErr() } if b.r == b.w { diff --git a/libgo/go/bufio/bufio_test.go b/libgo/go/bufio/bufio_test.go index f7a0682..782ca21 100644 --- a/libgo/go/bufio/bufio_test.go +++ b/libgo/go/bufio/bufio_test.go @@ -1481,6 +1481,60 @@ func newScriptedReader(steps ...func(p []byte) (n int, err error)) io.Reader { return &sr } +// eofReader returns the number of bytes read and io.EOF for the read that consumes the last of the content. +type eofReader struct { + buf []byte +} + +func (r *eofReader) Read(p []byte) (int, error) { + read := copy(p, r.buf) + r.buf = r.buf[read:] + + switch read { + case 0, len(r.buf): + // As allowed in the documentation, this will return io.EOF + // in the same call that consumes the last of the data. + // https://godoc.org/io#Reader + return read, io.EOF + } + + return read, nil +} + +func TestPartialReadEOF(t *testing.T) { + src := make([]byte, 10) + eofR := &eofReader{buf: src} + r := NewReader(eofR) + + // Start by reading 5 of the 10 available bytes. + dest := make([]byte, 5) + read, err := r.Read(dest) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if n := len(dest); read != n { + t.Fatalf("read %d bytes; wanted %d bytes", read, n) + } + + // The Reader should have buffered all the content from the io.Reader. + if n := len(eofR.buf); n != 0 { + t.Fatalf("got %d bytes left in bufio.Reader source; want 0 bytes", n) + } + // To prove the point, check that there are still 5 bytes available to read. + if n := r.Buffered(); n != 5 { + t.Fatalf("got %d bytes buffered in bufio.Reader; want 5 bytes", n) + } + + // This is the second read of 0 bytes. + read, err = r.Read([]byte{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if read != 0 { + t.Fatalf("read %d bytes; want 0 bytes", read) + } +} + func BenchmarkReaderCopyOptimal(b *testing.B) { // Optimal case is where the underlying reader implements io.WriterTo srcBuf := bytes.NewBuffer(make([]byte, 8192)) diff --git a/libgo/go/bufio/example_test.go b/libgo/go/bufio/example_test.go index 4666e6d..8885d40 100644 --- a/libgo/go/bufio/example_test.go +++ b/libgo/go/bufio/example_test.go @@ -31,6 +31,19 @@ func ExampleScanner_lines() { } } +// Return the most recent call to Scan as a []byte. +func ExampleScanner_Bytes() { + scanner := bufio.NewScanner(strings.NewReader("gopher")) + for scanner.Scan() { + fmt.Println(len(scanner.Bytes()) == 6) + } + if err := scanner.Err(); err != nil { + fmt.Fprintln(os.Stderr, "shouldn't see an error scanning a string") + } + // Output: + // true +} + // Use a Scanner to implement a simple word-count utility by scanning the // input as a sequence of space-delimited tokens. func ExampleScanner_words() { @@ -94,6 +107,9 @@ func ExampleScanner_emptyFinalToken() { return i + 1, data[:i], nil } } + if !atEOF { + return 0, nil, nil + } // There is one final token to be delivered, which may be the empty string. // Returning bufio.ErrFinalToken here tells Scan there are no more tokens after this // but does not trigger an error to be returned from Scan itself. diff --git a/libgo/go/bufio/scan.go b/libgo/go/bufio/scan.go index cefd261..4e787c4 100644 --- a/libgo/go/bufio/scan.go +++ b/libgo/go/bufio/scan.go @@ -73,7 +73,7 @@ var ( const ( // MaxScanTokenSize is the maximum size used to buffer a token - // unless the user provides an explicit buffer with Scan.Buffer. + // unless the user provides an explicit buffer with Scanner.Buffer. // The actual maximum token size may be smaller as the buffer // may need to include, for instance, a newline. MaxScanTokenSize = 64 * 1024 |