diff options
Diffstat (limited to 'src/pkg/bufio/bufio.go')
-rw-r--r-- | src/pkg/bufio/bufio.go | 100 |
1 files changed, 89 insertions, 11 deletions
diff --git a/src/pkg/bufio/bufio.go b/src/pkg/bufio/bufio.go index b44d0e7d1..ee69c2d31 100644 --- a/src/pkg/bufio/bufio.go +++ b/src/pkg/bufio/bufio.go @@ -64,6 +64,8 @@ func NewReader(rd io.Reader) *Reader { return NewReaderSize(rd, defaultBufSize) } +var errNegativeRead = errors.New("bufio: reader returned negative count from Read") + // fill reads a new chunk into the buffer. func (b *Reader) fill() { // Slide existing data to beginning. @@ -74,10 +76,13 @@ func (b *Reader) fill() { } // Read new data. - n, e := b.rd.Read(b.buf[b.w:]) + n, err := b.rd.Read(b.buf[b.w:]) + if n < 0 { + panic(errNegativeRead) + } b.w += n - if e != nil { - b.err = e + if err != nil { + b.err = err } } @@ -272,6 +277,9 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) { panic("not reached") } +// ReadLine is a low-level line-reading primitive. Most callers should use +// ReadBytes('\n') or ReadString('\n') instead or use a Scanner. +// // 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 @@ -279,6 +287,9 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) { // 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. +// +// The text returned from ReadLine does not include the line end ("\r\n" or "\n"). +// No indication or error is given if the input ends without a final line end. func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) { line, err = b.ReadSlice('\n') if err == ErrBufferFull { @@ -320,6 +331,7 @@ func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) { // it returns the data read before the error and the error itself (often io.EOF). // ReadBytes returns err != nil if and only if the returned data does not end in // delim. +// For simple uses, a Scanner may be more convenient. func (b *Reader) ReadBytes(delim byte) (line []byte, err error) { // Use ReadSlice to look for array, // accumulating full buffers. @@ -367,9 +379,45 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err error) { // it returns the data read before the error and the error itself (often io.EOF). // ReadString returns err != nil if and only if the returned data does not end in // delim. +// For simple uses, a Scanner may be more convenient. func (b *Reader) ReadString(delim byte) (line string, err error) { - bytes, e := b.ReadBytes(delim) - return string(bytes), e + bytes, err := b.ReadBytes(delim) + return string(bytes), err +} + +// WriteTo implements io.WriterTo. +func (b *Reader) WriteTo(w io.Writer) (n int64, err error) { + n, err = b.writeBuf(w) + if err != nil { + return + } + + if r, ok := b.rd.(io.WriterTo); ok { + m, err := r.WriteTo(w) + n += m + return n, err + } + + for b.fill(); b.r < b.w; b.fill() { + m, err := b.writeBuf(w) + n += m + if err != nil { + return n, err + } + } + + if b.err == io.EOF { + b.err = nil + } + + return n, b.readErr() +} + +// writeBuf writes the Reader's buffer to the writer. +func (b *Reader) writeBuf(w io.Writer) (int64, error) { + n, err := w.Write(b.buf[b.r:b.w]) + b.r += n + return int64(n), err } // buffered output @@ -415,17 +463,17 @@ func (b *Writer) Flush() error { if b.n == 0 { return nil } - n, e := b.wr.Write(b.buf[0:b.n]) - if n < b.n && e == nil { - e = io.ErrShortWrite + n, err := b.wr.Write(b.buf[0:b.n]) + if n < b.n && err == nil { + err = io.ErrShortWrite } - if e != nil { + if err != nil { if n > 0 && n < b.n { copy(b.buf[0:b.n-n], b.buf[n:b.n]) } b.n -= n - b.err = e - return e + b.err = err + return err } b.n = 0 return nil @@ -529,6 +577,36 @@ func (b *Writer) WriteString(s string) (int, error) { return nn, nil } +// ReadFrom implements io.ReaderFrom. +func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) { + if b.Buffered() == 0 { + if w, ok := b.wr.(io.ReaderFrom); ok { + return w.ReadFrom(r) + } + } + var m int + for { + m, err = r.Read(b.buf[b.n:]) + if m == 0 { + break + } + b.n += m + n += int64(m) + if b.Available() == 0 { + if err1 := b.Flush(); err1 != nil { + return n, err1 + } + } + if err != nil { + break + } + } + if err == io.EOF { + err = nil + } + return n, err +} + // buffered input and output // ReadWriter stores pointers to a Reader and a Writer. |