remove io.ErrEOF.
rename io.FullRead to io.ReadFull, to match
ReadAtLeast and ReadAll.
remove io.FullReader, because it is now unused.
R=r
DELTA=295 (88 added, 105 deleted, 102 changed)
OCL=30544
CL=30588
func (tr *Reader) readHeader() *Header {
header := make([]byte, blockSize);
var n int;
- if n, tr.err = io.FullRead(tr.r, header); tr.err != nil {
+ if n, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
return nil
}
// Two blocks of zero bytes marks the end of the archive.
if bytes.Equal(header, zeroBlock[0:blockSize]) {
- if n, tr.err = io.FullRead(tr.r, header); tr.err != nil {
+ if n, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
return nil
}
if !bytes.Equal(header, zeroBlock[0:blockSize]) {
t.Fatalf("Didn't get first file: %v", err);
}
buf := make([]byte, 4);
- if n, err := io.FullRead(tr, buf); err != nil {
+ if n, err := io.ReadFull(tr, buf); err != nil {
t.Fatalf("Unexpected error: %v", err);
}
if expected := io.StringBytes("Kilt"); !bytes.Equal(buf, expected) {
t.Fatalf("Didn't get second file: %v", err);
}
buf = make([]byte, 6);
- if n, err := io.FullRead(tr, buf); err != nil {
+ if n, err := io.ReadFull(tr, buf); err != nil {
t.Fatalf("Unexpected error: %v", err);
}
if expected := io.StringBytes("Google"); !bytes.Equal(buf, expected) {
// It returns the number of bytes read into p.
// If nn < len(p), also returns an error explaining
// why the read is short. At EOF, the count will be
-// zero and err will be io.ErrEOF.
+// zero and err will be os.EOF.
func (b *Reader) Read(p []byte) (nn int, err os.Error) {
nn = 0;
for len(p) > 0 {
if b.err != nil {
return nn, b.err
}
- if n == 0 {
- return nn, io.ErrEOF
- }
continue;
}
b.fill();
if b.err != nil {
return nn, b.err
}
- if b.w == b.r {
- return nn, io.ErrEOF
- }
}
if n > b.w - b.r {
n = b.w - b.r
if b.err != nil {
return 0, b.err
}
- if b.w == b.r {
- return 0, io.ErrEOF
- }
}
c = b.buf[b.r];
b.r++;
}
if b.w - b.r == n {
// no bytes read
- if b.r == b.w {
- return 0, 0, io.ErrEOF
- }
break;
}
}
n := b.Buffered();
b.fill();
if b.err != nil {
- return nil, b.err
- }
- if b.Buffered() == n { // no data added; end of file
line := b.buf[b.r:b.w];
b.r = b.w;
- return line, io.ErrEOF
+ return line, b.err
}
// Search new part of buffer
nb := 0;
for {
c, e := buf.ReadByte();
- if e == io.ErrEOF {
+ if e == os.EOF {
break
}
if e != nil {
s := "";
for {
s1, e := b.ReadLineString('\n', true);
- if e == io.ErrEOF {
+ if e == os.EOF {
break
}
if e != nil {
for {
n, e := buf.Read(b[nb:nb+m]);
nb += n;
- if e == io.ErrEOF {
+ if e == os.EOF {
break
}
}
f.b = 0;
// Length then ones-complement of length.
- nr, err := f.r.Read(f.buf[0:4]);
+ nr, err := io.ReadFull(f.r, f.buf[0:4]);
f.roffset += int64(nr);
- if nr < 4 && err == nil {
- err = io.ErrEOF;
- }
if err != nil {
return &ReadError{f.roffset, err};
}
if m > n {
m = n;
}
- m, err := f.r.Read(f.hist[f.hp:f.hp+m]);
+ m, err := io.ReadFull(f.r, f.hist[f.hp:f.hp+m]);
f.roffset += int64(m);
- if m == 0 && err == nil {
- err = io.ErrEOF;
- }
if err != nil {
return &ReadError{f.roffset, err};
}
}
func (z *GzipInflater) readHeader(save bool) os.Error {
- n, err := io.FullRead(z.r, z.buf[0:10]);
+ n, err := io.ReadFull(z.r, z.buf[0:10]);
if err != nil {
- if n != 0 && err == io.ErrEOF {
- return HeaderError;
- }
return err;
}
if z.buf[0] != gzipID1 || z.buf[1] != gzipID2 || z.buf[2] != gzipDeflate {
}
z.digest.Reset();
z.digest.Write(z.buf[0:10]);
-
+
if z.flg & flagExtra != 0{
n, err := z.read2();
if err != nil {
}
data := make([]byte, n);
var nn int;
- if nn, err = io.FullRead(z.r, data); err != nil {
+ if nn, err = io.ReadFull(z.r, data); err != nil {
return err;
}
if save {
n, err = z.inflater.Read(p);
z.digest.Write(p[0:n]);
z.size += uint32(n);
- if n != 0 || err != nil {
+ if n != 0 || err != os.EOF {
z.err = err;
return;
}
// Finished file; check checksum + size.
- if _, err := io.FullRead(z.r, z.buf[0:8]); err != nil {
- z.err = err;
- return 0, err;
- }
- if err != nil {
+ if _, err := io.ReadFull(z.r, z.buf[0:8]); err != nil {
z.err = err;
return 0, err;
}
}
// File is ok; is there another?
- switch err = z.readHeader(false); {
- case err == io.ErrEOF:
- err = nil;
- z.eof = true;
- return;
- case err != nil:
+ if err = z.readHeader(false); err != nil {
z.err = err;
return;
}
type gzipTest struct {
name string;
+ desc string;
raw string;
gzip []byte;
err os.Error;
var gzipTests = []gzipTest {
gzipTest { // has 1 empty fixed-huffman block
+ "empty.txt",
"empty.txt",
"",
[]byte {
nil
},
gzipTest { // has 1 non-empty fixed huffman block
+ "hello.txt",
"hello.txt",
"hello world\n",
[]byte {
},
gzipTest { // concatenation
"hello.txt",
+ "hello.txt x2",
"hello world\n"
"hello world\n",
[]byte {
nil
},
gzipTest { // has dynamic huffman blocks
+ "gettysburg",
"gettysburg",
" Four score and seven years ago our fathers brought forth on\n"
"this continent, a new nation, conceived in Liberty, and dedicated\n"
},
gzipTest { // has 1 non-empty fixed huffman block then garbage
"hello.txt",
+ "hello.txt + garbage",
"hello world\n",
[]byte {
0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
- 0x00, 0x00, 'g', 'a', 'r', 'b', 'a', 'g', 'e', '!',
+ 0x00, 0x00, 'g', 'a', 'r', 'b', 'a', 'g', 'e', '!', '!', '!',
},
HeaderError,
},
+ gzipTest { // has 1 non-empty fixed huffman block not enough header
+ "hello.txt",
+ "hello.txt + garbage",
+ "hello world\n",
+ []byte {
+ 0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
+ 0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
+ 0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
+ 0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
+ 0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
+ 0x00, 0x00, gzipID1,
+ },
+ io.ErrUnexpectedEOF,
+ },
gzipTest { // has 1 non-empty fixed huffman block but corrupt checksum
"hello.txt",
+ "hello.txt + corrupt checksum",
"hello world\n",
[]byte {
0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
},
gzipTest { // has 1 non-empty fixed huffman block but corrupt size
"hello.txt",
+ "hello.txt + corrupt size",
"hello world\n",
[]byte {
0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
b.Reset();
n, err := io.Copy(gzip, b);
if err != tt.err {
- t.Errorf("%s: io.Copy: %s want %s", tt.name, err, tt.err);
+ t.Errorf("%s: io.Copy: %v want %v", tt.name, err, tt.err);
}
s := string(b.Data());
if s != tt.raw {
tag := cr.tag;
if len(tag) < cap(tag) {
nt := len(tag);
- nn, err1 := io.FullRead(cr.r, tag[nt:cap(tag)]);
+ nn, err1 := io.ReadFull(cr.r, tag[nt:cap(tag)]);
tag = tag[0:nt+nn];
cr.tag = tag;
if err1 != nil {
// Read and decrypt directly in caller's buffer.
n, err = io.ReadAtLeast(x.r, p, x.blockSize);
- if err == io.ErrEOF && n == 0 {
- // EOF is okay on block boundary
- err = nil;
+ if err == os.EOF && n > 0 {
+ // EOF is only okay on block boundary
+ err = os.ErrorString("block fragment at EOF during decryption");
return;
}
var i int;
}
io.WriteString(cmd.Stdin, "hello, world\n");
cmd.Stdin.Close();
- var buf [64]byte;
- n, err1 := io.FullRead(cmd.Stdout, &buf);
- if err1 != nil && err1 != io.ErrEOF {
- t.Fatalf("reading from /bin/cat: %v", err1);
+ buf, err := io.ReadAll(cmd.Stdout);
+ if err != nil {
+ t.Fatalf("reading from /bin/cat: %v", err);
}
- if string(buf[0:n]) != "hello, world\n" {
- t.Fatalf("reading from /bin/cat: got %q", buf[0:n]);
+ if string(buf) != "hello, world\n" {
+ t.Fatalf("reading from /bin/cat: got %q", buf);
}
- if err1 = cmd.Close(); err1 != nil {
- t.Fatalf("closing /bin/cat: %v", err1);
+ if err = cmd.Close(); err != nil {
+ t.Fatalf("closing /bin/cat: %v", err);
}
}
if err != nil {
t.Fatalf("opencmd /bin/echo: %v", err);
}
- var buf [64]byte;
- n, err1 := io.FullRead(cmd.Stdout, &buf);
- if err1 != nil && err1 != io.ErrEOF {
- t.Fatalf("reading from /bin/echo: %v", err1);
+ buf, err := io.ReadAll(cmd.Stdout);
+ if err != nil {
+ t.Fatalf("reading from /bin/echo: %v", err);
}
- if string(buf[0:n]) != "hello world\n" {
- t.Fatalf("reading from /bin/echo: got %q", buf[0:n]);
+ if string(buf) != "hello world\n" {
+ t.Fatalf("reading from /bin/echo: got %q", buf);
}
- if err1 = cmd.Close(); err1 != nil {
- t.Fatalf("closing /bin/echo: %v", err1);
+ if err = cmd.Close(); err != nil {
+ t.Fatalf("closing /bin/echo: %v", err);
}
}
r.Body.Close();
}
- // TODO: io.ErrEOF check is needed because we're sometimes getting
- // this error when nothing is actually wrong. rsc suspects a bug
- // in bufio. Can remove the ErrEOF check once the bug is fixed
- // (expected to occur within a few weeks of this writing, 6/9/09).
- if err != nil && err != io.ErrEOF {
+ if err != nil {
t.Errorf("Error fetching URL: %v", err);
} else {
s := string(b);
} else {
// read first chunk to decide between utf-8 text and binary
var buf [1024]byte;
- n, err := io.FullRead(f, &buf);
+ n, err := io.ReadFull(f, &buf);
b := buf[0:n];
if isText(b) {
c.SetHeader("Content-Type", "text-plain; charset=utf-8");
io.WriteString(w, "\r\n");
if req.Body != nil {
- nCopied, err := io.Copy(req.Body, w);
- if err != nil && err != io.ErrEOF {
+ _, err := io.Copy(req.Body, w);
+ if err != nil {
return err;
}
}
}
// ReadByte reads and returns the next byte from the buffer.
-// If no byte is available, it returns error ErrEOF.
+// If no byte is available, it returns error os.EOF.
func (b *ByteBuffer) ReadByte() (c byte, err os.Error) {
if b.off >= len(b.buf) {
- return 0, ErrEOF;
+ return 0, os.EOF;
}
c = b.buf[b.off];
b.off++;
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"}
+// 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.
-// 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).
+//
+// Read reads up to len(p) bytes into p. It returns the number of bytes
+// read 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);
}
return w.Write(StringBytes(s))
}
-// ReadAtLeast reads r into buf until at least min bytes have been read,
-// or until EOF or error.
+// 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 {
n += nn
}
if e != nil {
+ if e == os.EOF && n > 0 {
+ e = ErrUnexpectedEOF;
+ }
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
+// 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;
}
-// 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.
+// 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);
break;
}
if nr != nw {
- err = os.EIO;
+ err = ErrShortWrite;
break;
}
}
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.
+// 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 {
break;
}
if nr != nw {
- err = os.EIO;
+ err = ErrShortWrite;
break;
}
}
- if er != nil {
- err = er;
+ if er == os.EOF {
break;
}
- if nr == 0 {
+ if er != nil {
+ err = er;
break;
}
}
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);
}
}
func (p *pipe) CloseWriter(werr os.Error) os.Error {
+ if werr == nil {
+ werr = os.EOF;
+ }
if p == nil || p.wclosed {
return os.EINVAL;
}
var buf = make([]byte, 64);
for {
n, err := r.Read(buf);
+ if err == os.EOF {
+ c <- 0;
+ break;
+ }
if err != nil {
t.Errorf("read: %v", err);
}
c <- n;
- if n == 0 {
- break;
- }
}
}
tot := 0;
for n := 1; n <= 256; n *= 2 {
nn, err := r.Read(rdat[tot:tot+n]);
- if err != nil {
+ if err != nil && err != os.EOF {
t.Fatalf("read: %v", err);
}
expect = 1;
} else if n == 256 {
expect = 0;
+ if err != os.EOF {
+ t.Fatalf("read at end: %v", err);
+ }
}
if nn != expect {
t.Fatalf("read %d, expected %d, got %d", n, expect, nn);
var buf = make([]byte, 64);
n, err := r.Read(buf);
<-c;
- if err != tt.err {
- t.Errorf("read from closed pipe: %v want %v", err, tt.err);
+ want := tt.err;
+ if want == nil {
+ want = os.EOF;
+ }
+ if err != want {
+ t.Errorf("read from closed pipe: %v want %v", err, want);
}
if n != 0 {
t.Errorf("read on closed pipe returned %d", n);
n, err := fd.Write(req);
buf := make([]byte, 1000);
- n, err = io.FullRead(fd, buf);
+ n, err = io.ReadFull(fd, buf);
if n < 1000 {
t.Errorf("fetchGoogle: short HTTP read from %s %s - %v", network, addr, err);
}
if len(f.data) < cap(f.data) {
ln := len(f.data);
- n, err := io.FullRead(f.file, f.data[ln:cap(f.data)]);
+ n, err := io.ReadFull(f.file, f.data[ln:cap(f.data)]);
if n >= 0 {
f.data = f.data[0:ln+n];
}
return err;
}
+type eofError int
+func (eofError) String() string {
+ return "EOF"
+}
+
+// EOF is the Error returned by Read when no more input is available.
+// Functions should return EOF only to signal a graceful end of input.
+// If the EOF occurs unexpectedly in a structured data stream,
+// the appropriate error is either io.ErrUnexpectedEOF or some other error
+// giving more detail.
+var EOF Error = eofError(0)
+
// Read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an Error, if any.
-// EOF is signaled by a zero count with a nil Error.
+// EOF is signaled by a zero count with err set to EOF.
// TODO(r): Add Pread, Pwrite (maybe ReadAt, WriteAt).
func (file *File) Read(b []byte) (ret int, err Error) {
if file == nil {
if n < 0 {
n = 0;
}
+ if n == 0 && e == 0 {
+ return 0, EOF
+ }
return n, ErrnoToError(e);
}
len := 0;
for {
n, e := file.Read(&buf);
- if n < 0 || e != nil {
- t.Fatal("read failed:", err);
- }
- if n == 0 {
+ len += n;
+ if e == EOF {
break
}
- len += n;
+ if e != nil {
+ t.Fatal("read failed:", err);
+ }
}
return uint64(len)
}
lineno := 0;
for {
line, err2 := b.ReadLineString('\n', false);
- if err2 == io.ErrEOF {
+ if err2 == os.EOF {
break;
}
if err2 != nil {
)
const (
- maxFileSize = 8192; // actual files are closer to 1K
headerSize = 4+16+4*7;
zoneDir = "/usr/share/zoneinfo/";
var errShort = TimeZoneError{ "time: short zone file" }
var errInvalid = TimeZoneError{ "time: invalid zone file" }
-var errLong = TimeZoneError{ "time: zone file too long" }
// Simple I/O interface to binary blob of data.
type data struct {
return zt, nil
}
-func readfile(name string, max int) (p []byte, err os.Error) {
- f, e := os.Open(name, os.O_RDONLY, 0);
- if e != nil {
- return nil, e;
- }
- p = make([]byte, max);
- n, err1 := io.FullRead(f, p);
- f.Close();
- if err1 == nil { // too long
- return nil, errLong;
- }
- if err1 != io.ErrEOF {
- return nil, err1;
- }
- return p[0:n], nil;
-}
-
func readinfofile(name string) ([]zonetime, os.Error) {
- buf, err := readfile(name, maxFileSize);
+ buf, err := io.ReadFile(name);
if err != nil {
goto Error;
}