diff options
Diffstat (limited to 'src/lib/io/io.go')
-rw-r--r-- | src/lib/io/io.go | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/src/lib/io/io.go b/src/lib/io/io.go new file mode 100644 index 000000000..9ae926441 --- /dev/null +++ b/src/lib/io/io.go @@ -0,0 +1,146 @@ +// 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. + +package io + +import ( + "os"; + "syscall"; +) + +export var ErrEOF = os.NewError("EOF") + +export type Read interface { + Read(p *[]byte) (n int, err *os.Error); +} + +export type Write interface { + Write(p *[]byte) (n int, err *os.Error); +} + +export type ReadWrite interface { + Read(p *[]byte) (n int, err *os.Error); + Write(p *[]byte) (n int, err *os.Error); +} + +export type ReadWriteClose interface { + Read(p *[]byte) (n int, err *os.Error); + Write(p *[]byte) (n int, err *os.Error); + Close() *os.Error; +} + +export func WriteString(w Write, s string) (n int, err *os.Error) { + b := new([]byte, len(s)+1); + if !syscall.StringToBytes(b, s) { + return -1, os.EINVAL + } + // BUG return w.Write(b[0:len(s)]) + r, e := w.Write(b[0:len(s)]); + return r, e +} + +// Read until buffer is full, EOF, or error +export func Readn(fd Read, buf *[]byte) (n int, err *os.Error) { + n = 0; + for n < len(buf) { + nn, e := fd.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 +} + +// Convert something that implements Read into something +// whose Reads are always Readn +type FullRead struct { + fd Read; +} + +func (fd *FullRead) Read(p *[]byte) (n int, err *os.Error) { + n, err = Readn(fd.fd, p); + return n, err +} + +export func MakeFullReader(fd Read) Read { + if fr, ok := fd.(*FullRead); ok { + // already a FullRead + return fd + } + return &FullRead{fd} +} + +// Copies n bytes (or until EOF is reached) from src to dst. +// Returns the number of bytes copied and the error, if any. +export func Copyn(src Read, dst Write, n int64) (written int64, err *os.Error) { + buf := new([]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 +} + +// Copies from src to dst until EOF is reached. +// Returns the number of bytes copied and the error, if any. +export func Copy(src Read, dst Write) (written int64, err *os.Error) { + buf := new([]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 +} + |