diff options
Diffstat (limited to 'src/pkg/bufio/bufio.go')
-rw-r--r-- | src/pkg/bufio/bufio.go | 95 |
1 files changed, 54 insertions, 41 deletions
diff --git a/src/pkg/bufio/bufio.go b/src/pkg/bufio/bufio.go index eae5c5ce9..32a25afae 100644 --- a/src/pkg/bufio/bufio.go +++ b/src/pkg/bufio/bufio.go @@ -282,6 +282,33 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err os.Error) { panic("not reached") } +// ReadLine tries to return a single line, not including the end-of-line bytes. +// If the line was too long for the buffer then isPrefix is set and the +// beginning of the line is returned. The rest of the line will be returned +// from future calls. isPrefix will be false when returning the last fragment +// of the line. The returned buffer is only valid until the next call to +// ReadLine. ReadLine either returns a non-nil line or it returns an error, +// never both. +func (b *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) { + line, err = b.ReadSlice('\n') + if err == ErrBufferFull { + return line, true, nil + } + + if len(line) == 0 { + return + } + err = nil + + if line[len(line)-1] == '\n' { + line = line[:len(line)-1] + } + if len(line) > 0 && line[len(line)-1] == '\r' { + line = line[:len(line)-1] + } + return +} + // ReadBytes reads until the first occurrence of delim in the input, // returning a slice containing the data up to and including the delimiter. // If ReadBytes encounters an error before finding a delimiter, @@ -415,38 +442,27 @@ func (b *Writer) Buffered() int { return b.n } // If nn < len(p), it also returns an error explaining // why the write is short. func (b *Writer) Write(p []byte) (nn int, err os.Error) { - if b.err != nil { - return 0, b.err - } - nn = 0 - for len(p) > 0 { - n := b.Available() - if n <= 0 { - if b.Flush(); b.err != nil { - break - } - n = b.Available() - } - if b.Buffered() == 0 && len(p) >= len(b.buf) { + for len(p) > b.Available() && b.err == nil { + var n int + if b.Buffered() == 0 { // Large write, empty buffer. // Write directly from p to avoid copy. n, b.err = b.wr.Write(p) - nn += n - p = p[n:] - if b.err != nil { - break - } - continue + } else { + n = copy(b.buf[b.n:], p) + b.n += n + b.Flush() } - if n > len(p) { - n = len(p) - } - copy(b.buf[b.n:b.n+n], p[0:n]) - b.n += n nn += n p = p[n:] } - return nn, b.err + if b.err != nil { + return nn, b.err + } + n := copy(b.buf[b.n:], p) + b.n += n + nn += n + return nn, nil } // WriteByte writes a single byte. @@ -496,24 +512,21 @@ func (b *Writer) WriteRune(rune int) (size int, err os.Error) { // If the count is less than len(s), it also returns an error explaining // why the write is short. func (b *Writer) WriteString(s string) (int, os.Error) { - if b.err != nil { - return 0, b.err - } - // Common case, worth making fast. - if b.Available() >= len(s) || len(b.buf) >= len(s) && b.Flush() == nil { - for i := 0; i < len(s); i++ { // loop over bytes, not runes. - b.buf[b.n] = s[i] - b.n++ - } - return len(s), nil + nn := 0 + for len(s) > b.Available() && b.err == nil { + n := copy(b.buf[b.n:], s) + b.n += n + nn += n + s = s[n:] + b.Flush() } - for i := 0; i < len(s); i++ { // loop over bytes, not runes. - b.WriteByte(s[i]) - if b.err != nil { - return i, b.err - } + if b.err != nil { + return nn, b.err } - return len(s), nil + n := copy(b.buf[b.n:], s) + b.n += n + nn += n + return nn, nil } // buffered input and output |