From: Brad Fitzpatrick Date: Wed, 26 Jan 2011 14:59:53 +0000 (-0500) Subject: encoding/line: make it an io.Reader too X-Git-Tag: weekly.2011-02-01~76 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=3aee82b66003b4cbf9d938382273c8bce390fc35;p=gostls13.git encoding/line: make it an io.Reader too R=agl1, bradfitzwork, rsc CC=golang-dev https://golang.org/cl/4066043 --- diff --git a/src/pkg/encoding/line/line.go b/src/pkg/encoding/line/line.go index f1c1061419..779b5758ad 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 68d13b5861..ff16d10c70 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) + } +}