| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // This package provides basic interfaces to I/O primitives. |
| // Its primary job is to wrap existing implementations of such primitives, |
| // such as those in package os, into shared public interfaces that |
| // abstract the functionality. |
| // It also provides buffering primitives and some other basic operations. |
| package io |
| |
| import ( |
| "bytes"; |
| "os"; |
| "strings"; |
| ) |
| |
| // Error represents an unexpected I/O behavior. |
| type Error struct { |
| os.ErrorString |
| } |
| |
| // ErrShortWrite means that a write accepted fewer bytes than requested |
| // but failed to return an explicit error. |
| var ErrShortWrite os.Error = &Error{"short write"} |
| |
| // ErrUnexpectedEOF means that os.EOF was encountered in the |
| // middle of reading a fixed-size block or data structure. |
| var ErrUnexpectedEOF os.Error = &Error{"unexpected EOF"} |
| |
| // Reader is the interface that wraps the basic Read method. |
| // |
| // Read reads up to len(p) bytes into p. It returns the number of bytes |
| // read (0 <= n <= len(p)) and any error encountered. |
| // Even if Read returns n < len(p), |
| // it may use all of p as scratch space during the call. |
| // If some data is available but not len(p) bytes, Read conventionally |
| // returns what is available rather than block waiting for more. |
| // |
| // At the end of the input stream, Read returns 0, os.EOF. |
| // Read may return a non-zero number of bytes with a non-nil err. |
| // In particular, a Read that exhausts the input may return n > 0, os.EOF. |
| type Reader interface { |
| Read(p []byte) (n int, err os.Error); |
| } |
| |
| // Writer is the interface that wraps the basic Write method. |
| // |
| // Write writes len(p) bytes from p to the underlying data stream. |
| // It returns the number of bytes written from p (0 <= n <= len(p)) |
| // and any error encountered that caused the write to stop early. |
| // Write must return a non-nil error if it returns n < len(p). |
| type Writer interface { |
| Write(p []byte) (n int, err os.Error); |
| } |
| |
| // Closer is the interface that wraps the basic Close method. |
| type Closer interface { |
| Close() os.Error; |
| } |
| |
| // ReadWrite is the interface that groups the basic Read and Write methods. |
| type ReadWriter interface { |
| Reader; |
| Writer; |
| } |
| |
| // ReadCloser is the interface that groups the basic Read and Close methods. |
| type ReadCloser interface { |
| Reader; |
| Closer; |
| } |
| |
| // WriteCloser is the interface that groups the basic Write and Close methods. |
| type WriteCloser interface { |
| Writer; |
| Closer; |
| } |
| |
| // ReadWriteCloser is the interface that groups the basic Read, Write and Close methods. |
| type ReadWriteCloser interface { |
| Reader; |
| Writer; |
| Closer; |
| } |
| |
| // WriteString writes the contents of the string s to w, which accepts an array of bytes. |
| func WriteString(w Writer, s string) (n int, err os.Error) { |
| return w.Write(strings.Bytes(s)) |
| } |
| |
| // ReadAtLeast reads from r into buf until it has read at least min bytes. |
| // It returns the number of bytes copied and an error if fewer bytes were read. |
| // The error is os.EOF only if no bytes were read. |
| // If an EOF happens after reading fewer than min bytes, |
| // ReadAtLeast returns ErrUnexpectedEOF. |
| func ReadAtLeast(r Reader, buf []byte, min int) (n int, err os.Error) { |
| n = 0; |
| for n < min { |
| nn, e := r.Read(buf[n:len(buf)]); |
| if nn > 0 { |
| n += nn |
| } |
| if e != nil { |
| if e == os.EOF && n > 0 { |
| e = ErrUnexpectedEOF; |
| } |
| return n, e |
| } |
| } |
| return n, nil |
| } |
| |
| // ReadFull reads exactly len(buf) bytes from r into buf. |
| // It returns the number of bytes copied and an error if fewer bytes were read. |
| // The error is os.EOF only if no bytes were read. |
| // If an EOF happens after reading some but not all the bytes, |
| // ReadFull returns ErrUnexpectedEOF. |
| func ReadFull(r Reader, buf []byte) (n int, err os.Error) { |
| // TODO(rsc): 6g bug keeps us from writing the obvious 1-liner |
| n, err = ReadAtLeast(r, buf, len(buf)); |
| return; |
| } |
| |
| // Copyn copies n bytes (or until an error) from src to dst. |
| // It returns the number of bytes copied and the error, if any. |
| func Copyn(src Reader, dst Writer, n int64) (written int64, err os.Error) { |
| 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; |
| } |
| } |
| return written, err |
| } |
| |
| // Copy copies from src to dst until either EOF is reached |
| // on src or an error occurs. It returns the number of bytes |
| // copied and the error, if any. |
| func Copy(src Reader, dst Writer) (written int64, err os.Error) { |
| buf := make([]byte, 32*1024); |
| for { |
| nr, er := src.Read(buf); |
| 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 == os.EOF { |
| break; |
| } |
| if er != nil { |
| err = er; |
| break; |
| } |
| } |
| return written, err |
| } |
| |
| // A ByteReader satisfies Reads by consuming data from a slice of bytes. |
| // Clients can call NewByteReader to create one or wrap pointers |
| // to their own slices: r := ByteReader{&data}. |
| type ByteReader struct { |
| Data *[]byte |
| } |
| |
| func (r ByteReader) Read(p []byte) (int, os.Error) { |
| n := len(p); |
| b := *r.Data; |
| if len(b) == 0 { |
| return 0, os.EOF; |
| } |
| if n > len(b) { |
| n = len(b); |
| } |
| bytes.Copy(p, b[0:n]); |
| *r.Data = b[n:len(b)]; |
| return n, nil; |
| } |
| |
| // NewByteReader returns a new ByteReader reading from data. |
| func NewByteReader(data []byte) ByteReader { |
| return ByteReader{ &data }; |
| } |
| |