From 6ee7fe58087ec5a15bf9ae7717d3fc13bdd407e7 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Tue, 11 Nov 2008 17:28:36 -0800 Subject: [PATCH] Implement a "full reader" wrapper for io.Read, guaranteeing that either the buffer is full, zero bytes were read, or an error is returned. R=rsc DELTA=44 (42 added, 0 deleted, 2 changed) OCL=19027 CL=19047 --- src/lib/io.go | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/src/lib/io.go b/src/lib/io.go index 20b7b902922..44d072caa9b 100644 --- a/src/lib/io.go +++ b/src/lib/io.go @@ -3,8 +3,13 @@ // license that can be found in the LICENSE file. package io -import os "os" -import syscall "syscall" + +import ( + "os"; + "syscall"; +) + +export var ErrEOF = os.NewError("EOF") export type Read interface { Read(p *[]byte) (n int, err *os.Error); @@ -34,3 +39,40 @@ export func WriteString(w Write, s string) (n int, err *os.Error) { 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, p); + return n, err +} + +export func MakeFullReader(fd Read) Read { + if fr, ok := fd.(*FullRead); ok { + // already a FullRead + return fd + } + return &FullRead{fd} +}