diff options
Diffstat (limited to 'src/pkg/io/io.go')
| -rw-r--r-- | src/pkg/io/io.go | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/src/pkg/io/io.go b/src/pkg/io/io.go new file mode 100644 index 000000000..ba0449ac1 --- /dev/null +++ b/src/pkg/io/io.go @@ -0,0 +1,223 @@ +// 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"; +) + +// Error represents an unexpected I/O behavior. +type Error struct { + os.ErrorString +} + +// ErrEOF means that data was expected, but a read got EOF instead. +var ErrEOF os.Error = &Error{"EOF"} + +// ErrShortWrite means that a write accepted fewer bytes than requested +// but failed to return an explicit error. +var ErrShortWrite os.Error = &Error{"short write"} + + +// Reader is the interface that wraps the basic Read method. +// An implementation of Read is allowed to use all of p for +// scratch space during the call, even if it eventually returns +// n < len(p). +type Reader interface { + Read(p []byte) (n int, err os.Error); +} + +// Writer is the interface that wraps the basic Write method. +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; +} + +// Convert a string to an array of bytes for easy marshaling. +func StringBytes(s string) []byte { + b := make([]byte, len(s)); + for i := 0; i < len(s); i++ { + b[i] = s[i]; + } + return b; +} + +// 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(StringBytes(s)) +} + +// ReadAtLeast reads r into buf until at least min bytes have been read, +// or until EOF or error. +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 { + return n, e + } + if nn <= 0 { + return n, ErrEOF // no error but insufficient data + } + } + return n, nil +} + +// FullRead reads r until the buffer buf is full, or until EOF or error. +func FullRead(r Reader, buf []byte) (n int, err os.Error) { + // TODO(rsc): 6g bug prevents obvious return + n, err = ReadAtLeast(r, buf, len(buf)); + return; +} + +// Convert something that implements Read into something +// whose Reads are always FullReads +type fullRead struct { + r Reader; +} + +func (fr *fullRead) Read(p []byte) (n int, err os.Error) { + n, err = FullRead(fr.r, p); + return n, err +} + +// MakeFullReader takes r, an implementation of Read, and returns an object +// that still implements Read but always calls FullRead underneath. +func MakeFullReader(r Reader) Reader { + if fr, ok := r.(*fullRead); ok { + // already a fullRead + return r + } + return &fullRead{r} +} + +// Copy n copies n bytes (or until EOF is reached) 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 = os.EIO; + break; + } + } + if er != nil { + err = er; + break; + } + if nr == 0 { + err = ErrEOF; + break; + } + } + return written, err +} + +// Copy copies from src to dst until EOF is reached. +// 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 = os.EIO; + break; + } + } + if er != nil { + err = er; + break; + } + if nr == 0 { + 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 n > len(b) { + n = len(b); + } + bytes.Copy(p, b[0:n]); + *b = b[n:len(b)]; + return n, nil; +} + +// NewByteReader returns a new ByteReader reading from data. +func NewByteReader(data []byte) ByteReader { + return ByteReader{ &data }; +} + |
