summaryrefslogtreecommitdiff
path: root/src/lib/io/io.go
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2008-11-25 09:41:58 -0800
committerRob Pike <r@golang.org>2008-11-25 09:41:58 -0800
commit1eaa3fc56b95b7c1acd348795bdf87368eca3ce7 (patch)
treeb423f8c2acc0c5054e93ed17fa0c41a4763b25b8 /src/lib/io/io.go
parent22fb1175911f2631207aee68d9a0f8ddf73bc5bd (diff)
downloadgolang-1eaa3fc56b95b7c1acd348795bdf87368eca3ce7.tar.gz
make a (rudimentary) ByteBuffer and put it in package "io".
fix up protocol buffers to use it. R=rsc DELTA=1232 (612 added, 572 deleted, 48 changed) OCL=19964 CL=19981
Diffstat (limited to 'src/lib/io/io.go')
-rw-r--r--src/lib/io/io.go146
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
+}
+