diff --git a/src/pkg/encoding/line/line.go b/src/pkg/encoding/line/line.go index f1c1061419c..779b5758add 100644 --- a/src/pkg/encoding/line/line.go +++ b/src/pkg/encoding/line/line.go @@ -28,6 +28,26 @@ func NewReader(input io.Reader, maxLineLength int) *Reader { } } +// Read reads from any buffered data past the last line read, or from the underlying +// io.Reader if the buffer is empty. +func (l *Reader) Read(p []byte) (n int, err os.Error) { + l.removeConsumedFromBuffer() + if len(l.buf) > 0 { + n = copy(p, l.buf) + l.consumed += n + return + } + return l.in.Read(p) +} + +func (l *Reader) removeConsumedFromBuffer() { + if l.consumed > 0 { + n := copy(l.buf, l.buf[l.consumed:]) + l.buf = l.buf[:n] + l.consumed = 0 + } +} + // ReadLine tries to return a single line, not including the end-of-line bytes. // If the line was found to be longer than the maximum length then isPrefix is // set and the beginning of the line is returned. The rest of the line will be @@ -36,11 +56,7 @@ func NewReader(input io.Reader, maxLineLength int) *Reader { // the Reader and is only valid until the next call to ReadLine. ReadLine // either returns a non-nil line or it returns an error, never both. func (l *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) { - if l.consumed > 0 { - n := copy(l.buf, l.buf[l.consumed:]) - l.buf = l.buf[:n] - l.consumed = 0 - } + l.removeConsumedFromBuffer() if len(l.buf) == 0 && l.err != nil { err = l.err diff --git a/src/pkg/encoding/line/line_test.go b/src/pkg/encoding/line/line_test.go index 68d13b58616..ff16d10c709 100644 --- a/src/pkg/encoding/line/line_test.go +++ b/src/pkg/encoding/line/line_test.go @@ -6,6 +6,7 @@ package line import ( "bytes" + "io" "os" "testing" ) @@ -87,3 +88,23 @@ func TestLineTooLong(t *testing.T) { t.Errorf("bad result for third line: %x", line) } } + +func TestReadAfterLines(t *testing.T) { + line1 := "line1" + restData := "line2\nline 3\n" + inbuf := bytes.NewBuffer([]byte(line1 + "\n" + restData)) + outbuf := new(bytes.Buffer) + maxLineLength := len(line1) + len(restData)/2 + l := NewReader(inbuf, maxLineLength) + line, isPrefix, err := l.ReadLine() + if isPrefix || err != nil || string(line) != line1 { + t.Errorf("bad result for first line: isPrefix=%v err=%v line=%q", isPrefix, err, string(line)) + } + n, err := io.Copy(outbuf, l) + if int(n) != len(restData) || err != nil { + t.Errorf("bad result for Read: n=%d err=%v", n, err) + } + if outbuf.String() != restData { + t.Errorf("bad result for Read: got %q; expected %q", outbuf.String(), restData) + } +}