diff options
Diffstat (limited to 'src/pkg/io/io.go')
-rw-r--r-- | src/pkg/io/io.go | 81 |
1 files changed, 37 insertions, 44 deletions
diff --git a/src/pkg/io/io.go b/src/pkg/io/io.go index 54bf159eb..23d05e575 100644 --- a/src/pkg/io/io.go +++ b/src/pkg/io/io.go @@ -130,11 +130,23 @@ type ReadWriteSeeker interface { } // ReaderFrom is the interface that wraps the ReadFrom method. +// +// ReadFrom reads data from r until EOF or error. +// The return value n is the number of bytes read. +// Any error except io.EOF encountered during the read is also returned. +// +// The Copy function uses ReaderFrom if available. type ReaderFrom interface { ReadFrom(r Reader) (n int64, err error) } // WriterTo is the interface that wraps the WriteTo method. +// +// WriteTo writes data to w until there's no more data to write or +// when an error occurs. The return value n is the number of bytes +// written. Any error encountered during the write is also returned. +// +// The Copy function uses WriterTo if available. type WriterTo interface { WriteTo(w Writer) (n int64, err error) } @@ -204,6 +216,11 @@ type ByteScanner interface { UnreadByte() error } +// ByteWriter is the interface that wraps the WriteByte method. +type ByteWriter interface { + WriteByte(c byte) error +} + // RuneReader is the interface that wraps the ReadRune method. // // ReadRune reads a single UTF-8 encoded Unicode character @@ -245,6 +262,7 @@ func WriteString(w Writer, s string) (n int, err error) { // If an EOF happens after reading fewer than min bytes, // ReadAtLeast returns ErrUnexpectedEOF. // If min is greater than the length of buf, ReadAtLeast returns ErrShortBuffer. +// On return, n >= min if and only if err == nil. func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) { if len(buf) < min { return 0, ErrShortBuffer @@ -254,12 +272,10 @@ func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) { nn, err = r.Read(buf[n:]) n += nn } - if err == EOF { - if n >= min { - err = nil - } else if n > 0 { - err = ErrUnexpectedEOF - } + if n >= min { + err = nil + } else if n > 0 && err == EOF { + err = ErrUnexpectedEOF } return } @@ -269,56 +285,28 @@ func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) { // The error is EOF only if no bytes were read. // If an EOF happens after reading some but not all the bytes, // ReadFull returns ErrUnexpectedEOF. +// On return, n == len(buf) if and only if err == nil. func ReadFull(r Reader, buf []byte) (n int, err error) { return ReadAtLeast(r, buf, len(buf)) } // CopyN copies n bytes (or until an error) from src to dst. // It returns the number of bytes copied and the earliest -// error encountered while copying. Because Read can -// return the full amount requested as well as an error -// (including EOF), so can CopyN. +// error encountered while copying. +// On return, written == n if and only if err == nil. // // If dst implements the ReaderFrom interface, // the copy is implemented using it. func CopyN(dst Writer, src Reader, n int64) (written int64, err error) { - // If the writer has a ReadFrom method, use it to do the copy. - // Avoids a buffer allocation and a copy. - if rt, ok := dst.(ReaderFrom); ok { - written, err = rt.ReadFrom(LimitReader(src, n)) - if written < n && err == nil { - // rt stopped early; must have been EOF. - err = EOF - } - return + written, err = Copy(dst, LimitReader(src, n)) + if written == n { + return n, nil } - buf := make([]byte, 32*1024) - for written < n { - l := len(buf) - if d := n - written; d < int64(l) { - l = int(d) - } - nr, er := src.Read(buf[0:l]) - if nr > 0 { - nw, ew := dst.Write(buf[0:nr]) - if nw > 0 { - written += int64(nw) - } - if ew != nil { - err = ew - break - } - if nr != nw { - err = ErrShortWrite - break - } - } - if er != nil { - err = er - break - } + if written < n && err == nil { + // src stopped early; must have been EOF. + err = EOF } - return written, err + return } // Copy copies from src to dst until either EOF is reached @@ -451,6 +439,11 @@ func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err error) { off += s.base if max := s.limit - off; int64(len(p)) > max { p = p[0:max] + n, err = s.r.ReadAt(p, off) + if err == nil { + err = EOF + } + return n, err } return s.r.ReadAt(p, off) } |