Commit c06cf03f authored by Russ Cox's avatar Russ Cox

io: use error, add EOF, avoid os

R=r, r
CC=golang-dev
https://golang.org/cl/5311068
parent c14f71c7
This diff is collapsed.
...@@ -7,7 +7,6 @@ package io_test ...@@ -7,7 +7,6 @@ package io_test
import ( import (
"bytes" "bytes"
. "io" . "io"
"os"
"strings" "strings"
"testing" "testing"
) )
...@@ -85,7 +84,7 @@ type noReadFrom struct { ...@@ -85,7 +84,7 @@ type noReadFrom struct {
w Writer w Writer
} }
func (w *noReadFrom) Write(p []byte) (n int, err os.Error) { func (w *noReadFrom) Write(p []byte) (n int, err error) {
return w.w.Write(p) return w.w.Write(p)
} }
...@@ -101,7 +100,7 @@ func TestCopyNEOF(t *testing.T) { ...@@ -101,7 +100,7 @@ func TestCopyNEOF(t *testing.T) {
} }
n, err = CopyN(&noReadFrom{b}, strings.NewReader("foo"), 4) n, err = CopyN(&noReadFrom{b}, strings.NewReader("foo"), 4)
if n != 3 || err != os.EOF { if n != 3 || err != EOF {
t.Errorf("CopyN(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n, err) t.Errorf("CopyN(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n, err)
} }
...@@ -111,7 +110,7 @@ func TestCopyNEOF(t *testing.T) { ...@@ -111,7 +110,7 @@ func TestCopyNEOF(t *testing.T) {
} }
n, err = CopyN(b, strings.NewReader("foo"), 4) // b has read from n, err = CopyN(b, strings.NewReader("foo"), 4) // b has read from
if n != 3 || err != os.EOF { if n != 3 || err != EOF {
t.Errorf("CopyN(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err) t.Errorf("CopyN(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err)
} }
} }
...@@ -121,16 +120,16 @@ func TestReadAtLeast(t *testing.T) { ...@@ -121,16 +120,16 @@ func TestReadAtLeast(t *testing.T) {
testReadAtLeast(t, &rb) testReadAtLeast(t, &rb)
} }
// A version of bytes.Buffer that returns n > 0, os.EOF on Read // A version of bytes.Buffer that returns n > 0, EOF on Read
// when the input is exhausted. // when the input is exhausted.
type dataAndEOFBuffer struct { type dataAndEOFBuffer struct {
bytes.Buffer bytes.Buffer
} }
func (r *dataAndEOFBuffer) Read(p []byte) (n int, err os.Error) { func (r *dataAndEOFBuffer) Read(p []byte) (n int, err error) {
n, err = r.Buffer.Read(p) n, err = r.Buffer.Read(p)
if n > 0 && r.Buffer.Len() == 0 && err == nil { if n > 0 && r.Buffer.Len() == 0 && err == nil {
err = os.EOF err = EOF
} }
return return
} }
...@@ -162,7 +161,7 @@ func testReadAtLeast(t *testing.T, rb ReadWriter) { ...@@ -162,7 +161,7 @@ func testReadAtLeast(t *testing.T, rb ReadWriter) {
t.Errorf("expected to have read 2 bytes, got %v", n) t.Errorf("expected to have read 2 bytes, got %v", n)
} }
n, err = ReadAtLeast(rb, buf, 2) n, err = ReadAtLeast(rb, buf, 2)
if err != os.EOF { if err != EOF {
t.Errorf("expected EOF, got %v", err) t.Errorf("expected EOF, got %v", err)
} }
if n != 0 { if n != 0 {
...@@ -193,14 +192,14 @@ func TestTeeReader(t *testing.T) { ...@@ -193,14 +192,14 @@ func TestTeeReader(t *testing.T) {
if !bytes.Equal(wb.Bytes(), src) { if !bytes.Equal(wb.Bytes(), src) {
t.Errorf("bytes written = %q want %q", wb.Bytes(), src) t.Errorf("bytes written = %q want %q", wb.Bytes(), src)
} }
if n, err := r.Read(dst); n != 0 || err != os.EOF { if n, err := r.Read(dst); n != 0 || err != EOF {
t.Errorf("r.Read at EOF = %d, %v want 0, EOF", n, err) t.Errorf("r.Read at EOF = %d, %v want 0, EOF", n, err)
} }
rb = bytes.NewBuffer(src) rb = bytes.NewBuffer(src)
pr, pw := Pipe() pr, pw := Pipe()
pr.Close() pr.Close()
r = TeeReader(rb, pw) r = TeeReader(rb, pw)
if n, err := ReadFull(r, dst); n != 0 || err != os.EPIPE { if n, err := ReadFull(r, dst); n != 0 || err != ErrClosedPipe {
t.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n, err) t.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n, err)
} }
} }
...@@ -4,17 +4,15 @@ ...@@ -4,17 +4,15 @@
package io package io
import "os"
type multiReader struct { type multiReader struct {
readers []Reader readers []Reader
} }
func (mr *multiReader) Read(p []byte) (n int, err os.Error) { func (mr *multiReader) Read(p []byte) (n int, err error) {
for len(mr.readers) > 0 { for len(mr.readers) > 0 {
n, err = mr.readers[0].Read(p) n, err = mr.readers[0].Read(p)
if n > 0 || err != os.EOF { if n > 0 || err != EOF {
if err == os.EOF { if err == EOF {
// Don't return EOF yet. There may be more bytes // Don't return EOF yet. There may be more bytes
// in the remaining readers. // in the remaining readers.
err = nil err = nil
...@@ -23,12 +21,12 @@ func (mr *multiReader) Read(p []byte) (n int, err os.Error) { ...@@ -23,12 +21,12 @@ func (mr *multiReader) Read(p []byte) (n int, err os.Error) {
} }
mr.readers = mr.readers[1:] mr.readers = mr.readers[1:]
} }
return 0, os.EOF return 0, EOF
} }
// MultiReader returns a Reader that's the logical concatenation of // MultiReader returns a Reader that's the logical concatenation of
// the provided input readers. They're read sequentially. Once all // the provided input readers. They're read sequentially. Once all
// inputs are drained, Read will return os.EOF. // inputs are drained, Read will return EOF.
func MultiReader(readers ...Reader) Reader { func MultiReader(readers ...Reader) Reader {
return &multiReader{readers} return &multiReader{readers}
} }
...@@ -37,7 +35,7 @@ type multiWriter struct { ...@@ -37,7 +35,7 @@ type multiWriter struct {
writers []Writer writers []Writer
} }
func (t *multiWriter) Write(p []byte) (n int, err os.Error) { func (t *multiWriter) Write(p []byte) (n int, err error) {
for _, w := range t.writers { for _, w := range t.writers {
n, err = w.Write(p) n, err = w.Write(p)
if err != nil { if err != nil {
......
...@@ -9,7 +9,6 @@ import ( ...@@ -9,7 +9,6 @@ import (
"bytes" "bytes"
"crypto/sha1" "crypto/sha1"
"fmt" "fmt"
"os"
"strings" "strings"
"testing" "testing"
) )
...@@ -26,7 +25,7 @@ func TestMultiReader(t *testing.T) { ...@@ -26,7 +25,7 @@ func TestMultiReader(t *testing.T) {
buf = make([]byte, 20) buf = make([]byte, 20)
tests() tests()
} }
expectRead := func(size int, expected string, eerr os.Error) { expectRead := func(size int, expected string, eerr error) {
nread++ nread++
n, gerr := mr.Read(buf[0:size]) n, gerr := mr.Read(buf[0:size])
if n != len(expected) { if n != len(expected) {
...@@ -48,13 +47,13 @@ func TestMultiReader(t *testing.T) { ...@@ -48,13 +47,13 @@ func TestMultiReader(t *testing.T) {
expectRead(2, "fo", nil) expectRead(2, "fo", nil)
expectRead(5, "o ", nil) expectRead(5, "o ", nil)
expectRead(5, "bar", nil) expectRead(5, "bar", nil)
expectRead(5, "", os.EOF) expectRead(5, "", EOF)
}) })
withFooBar(func() { withFooBar(func() {
expectRead(4, "foo ", nil) expectRead(4, "foo ", nil)
expectRead(1, "b", nil) expectRead(1, "b", nil)
expectRead(3, "ar", nil) expectRead(3, "ar", nil)
expectRead(1, "", os.EOF) expectRead(1, "", EOF)
}) })
withFooBar(func() { withFooBar(func() {
expectRead(5, "foo ", nil) expectRead(5, "foo ", nil)
......
...@@ -7,14 +7,14 @@ ...@@ -7,14 +7,14 @@
package io package io
import ( import "sync"
"os"
"sync" // ErrClosedPipe is the error used for read or write operations on a closed pipe.
) var ErrClosedPipe = &Error{"io: read/write on closed pipe"}
type pipeResult struct { type pipeResult struct {
n int n int
err os.Error err error
} }
// A pipe is the shared pipe structure underlying PipeReader and PipeWriter. // A pipe is the shared pipe structure underlying PipeReader and PipeWriter.
...@@ -25,11 +25,11 @@ type pipe struct { ...@@ -25,11 +25,11 @@ type pipe struct {
data []byte // data remaining in pending write data []byte // data remaining in pending write
rwait sync.Cond // waiting reader rwait sync.Cond // waiting reader
wwait sync.Cond // waiting writer wwait sync.Cond // waiting writer
rerr os.Error // if reader closed, error to give writes rerr error // if reader closed, error to give writes
werr os.Error // if writer closed, error to give reads werr error // if writer closed, error to give reads
} }
func (p *pipe) read(b []byte) (n int, err os.Error) { func (p *pipe) read(b []byte) (n int, err error) {
// One reader at a time. // One reader at a time.
p.rl.Lock() p.rl.Lock()
defer p.rl.Unlock() defer p.rl.Unlock()
...@@ -38,7 +38,7 @@ func (p *pipe) read(b []byte) (n int, err os.Error) { ...@@ -38,7 +38,7 @@ func (p *pipe) read(b []byte) (n int, err os.Error) {
defer p.l.Unlock() defer p.l.Unlock()
for { for {
if p.rerr != nil { if p.rerr != nil {
return 0, os.EINVAL return 0, ErrClosedPipe
} }
if p.data != nil { if p.data != nil {
break break
...@@ -59,7 +59,7 @@ func (p *pipe) read(b []byte) (n int, err os.Error) { ...@@ -59,7 +59,7 @@ func (p *pipe) read(b []byte) (n int, err os.Error) {
var zero [0]byte var zero [0]byte
func (p *pipe) write(b []byte) (n int, err os.Error) { func (p *pipe) write(b []byte) (n int, err error) {
// pipe uses nil to mean not available // pipe uses nil to mean not available
if b == nil { if b == nil {
b = zero[:] b = zero[:]
...@@ -82,7 +82,7 @@ func (p *pipe) write(b []byte) (n int, err os.Error) { ...@@ -82,7 +82,7 @@ func (p *pipe) write(b []byte) (n int, err os.Error) {
break break
} }
if p.werr != nil { if p.werr != nil {
err = os.EINVAL err = ErrClosedPipe
} }
p.wwait.Wait() p.wwait.Wait()
} }
...@@ -91,9 +91,9 @@ func (p *pipe) write(b []byte) (n int, err os.Error) { ...@@ -91,9 +91,9 @@ func (p *pipe) write(b []byte) (n int, err os.Error) {
return return
} }
func (p *pipe) rclose(err os.Error) { func (p *pipe) rclose(err error) {
if err == nil { if err == nil {
err = os.EPIPE err = ErrClosedPipe
} }
p.l.Lock() p.l.Lock()
defer p.l.Unlock() defer p.l.Unlock()
...@@ -102,9 +102,9 @@ func (p *pipe) rclose(err os.Error) { ...@@ -102,9 +102,9 @@ func (p *pipe) rclose(err os.Error) {
p.wwait.Signal() p.wwait.Signal()
} }
func (p *pipe) wclose(err os.Error) { func (p *pipe) wclose(err error) {
if err == nil { if err == nil {
err = os.EOF err = EOF
} }
p.l.Lock() p.l.Lock()
defer p.l.Unlock() defer p.l.Unlock()
...@@ -122,20 +122,20 @@ type PipeReader struct { ...@@ -122,20 +122,20 @@ type PipeReader struct {
// it reads data from the pipe, blocking until a writer // it reads data from the pipe, blocking until a writer
// arrives or the write end is closed. // arrives or the write end is closed.
// If the write end is closed with an error, that error is // If the write end is closed with an error, that error is
// returned as err; otherwise err is os.EOF. // returned as err; otherwise err is EOF.
func (r *PipeReader) Read(data []byte) (n int, err os.Error) { func (r *PipeReader) Read(data []byte) (n int, err error) {
return r.p.read(data) return r.p.read(data)
} }
// Close closes the reader; subsequent writes to the // Close closes the reader; subsequent writes to the
// write half of the pipe will return the error os.EPIPE. // write half of the pipe will return the error ErrClosedPipe.
func (r *PipeReader) Close() os.Error { func (r *PipeReader) Close() error {
return r.CloseWithError(nil) return r.CloseWithError(nil)
} }
// CloseWithError closes the reader; subsequent writes // CloseWithError closes the reader; subsequent writes
// to the write half of the pipe will return the error err. // to the write half of the pipe will return the error err.
func (r *PipeReader) CloseWithError(err os.Error) os.Error { func (r *PipeReader) CloseWithError(err error) error {
r.p.rclose(err) r.p.rclose(err)
return nil return nil
} }
...@@ -149,20 +149,20 @@ type PipeWriter struct { ...@@ -149,20 +149,20 @@ type PipeWriter struct {
// it writes data to the pipe, blocking until readers // it writes data to the pipe, blocking until readers
// have consumed all the data or the read end is closed. // have consumed all the data or the read end is closed.
// If the read end is closed with an error, that err is // If the read end is closed with an error, that err is
// returned as err; otherwise err is os.EPIPE. // returned as err; otherwise err is ErrClosedPipe.
func (w *PipeWriter) Write(data []byte) (n int, err os.Error) { func (w *PipeWriter) Write(data []byte) (n int, err error) {
return w.p.write(data) return w.p.write(data)
} }
// Close closes the writer; subsequent reads from the // Close closes the writer; subsequent reads from the
// read half of the pipe will return no bytes and os.EOF. // read half of the pipe will return no bytes and EOF.
func (w *PipeWriter) Close() os.Error { func (w *PipeWriter) Close() error {
return w.CloseWithError(nil) return w.CloseWithError(nil)
} }
// CloseWithError closes the writer; subsequent reads from the // CloseWithError closes the writer; subsequent reads from the
// read half of the pipe will return no bytes and the error err. // read half of the pipe will return no bytes and the error err.
func (w *PipeWriter) CloseWithError(err os.Error) os.Error { func (w *PipeWriter) CloseWithError(err error) error {
w.p.wclose(err) w.p.wclose(err)
return nil return nil
} }
......
...@@ -7,7 +7,6 @@ package io_test ...@@ -7,7 +7,6 @@ package io_test
import ( import (
"fmt" "fmt"
. "io" . "io"
"os"
"testing" "testing"
"time" "time"
) )
...@@ -44,7 +43,7 @@ func reader(t *testing.T, r Reader, c chan int) { ...@@ -44,7 +43,7 @@ func reader(t *testing.T, r Reader, c chan int) {
var buf = make([]byte, 64) var buf = make([]byte, 64)
for { for {
n, err := r.Read(buf) n, err := r.Read(buf)
if err == os.EOF { if err == EOF {
c <- 0 c <- 0
break break
} }
...@@ -84,7 +83,7 @@ func TestPipe2(t *testing.T) { ...@@ -84,7 +83,7 @@ func TestPipe2(t *testing.T) {
type pipeReturn struct { type pipeReturn struct {
n int n int
err os.Error err error
} }
// Test a large write that requires multiple reads to satisfy. // Test a large write that requires multiple reads to satisfy.
...@@ -106,7 +105,7 @@ func TestPipe3(t *testing.T) { ...@@ -106,7 +105,7 @@ func TestPipe3(t *testing.T) {
tot := 0 tot := 0
for n := 1; n <= 256; n *= 2 { for n := 1; n <= 256; n *= 2 {
nn, err := r.Read(rdat[tot : tot+n]) nn, err := r.Read(rdat[tot : tot+n])
if err != nil && err != os.EOF { if err != nil && err != EOF {
t.Fatalf("read: %v", err) t.Fatalf("read: %v", err)
} }
...@@ -116,7 +115,7 @@ func TestPipe3(t *testing.T) { ...@@ -116,7 +115,7 @@ func TestPipe3(t *testing.T) {
expect = 1 expect = 1
} else if n == 256 { } else if n == 256 {
expect = 0 expect = 0
if err != os.EOF { if err != EOF {
t.Fatalf("read at end: %v", err) t.Fatalf("read at end: %v", err)
} }
} }
...@@ -142,13 +141,13 @@ func TestPipe3(t *testing.T) { ...@@ -142,13 +141,13 @@ func TestPipe3(t *testing.T) {
// Test read after/before writer close. // Test read after/before writer close.
type closer interface { type closer interface {
CloseWithError(os.Error) os.Error CloseWithError(error) error
Close() os.Error Close() error
} }
type pipeTest struct { type pipeTest struct {
async bool async bool
err os.Error err error
closeWithError bool closeWithError bool
} }
...@@ -167,7 +166,7 @@ var pipeTests = []pipeTest{ ...@@ -167,7 +166,7 @@ var pipeTests = []pipeTest{
func delayClose(t *testing.T, cl closer, ch chan int, tt pipeTest) { func delayClose(t *testing.T, cl closer, ch chan int, tt pipeTest) {
time.Sleep(1e6) // 1 ms time.Sleep(1e6) // 1 ms
var err os.Error var err error
if tt.closeWithError { if tt.closeWithError {
err = cl.CloseWithError(tt.err) err = cl.CloseWithError(tt.err)
} else { } else {
...@@ -193,7 +192,7 @@ func TestPipeReadClose(t *testing.T) { ...@@ -193,7 +192,7 @@ func TestPipeReadClose(t *testing.T) {
<-c <-c
want := tt.err want := tt.err
if want == nil { if want == nil {
want = os.EOF want = EOF
} }
if err != want { if err != want {
t.Errorf("read from closed pipe: %v want %v", err, want) t.Errorf("read from closed pipe: %v want %v", err, want)
...@@ -214,8 +213,8 @@ func TestPipeReadClose2(t *testing.T) { ...@@ -214,8 +213,8 @@ func TestPipeReadClose2(t *testing.T) {
go delayClose(t, r, c, pipeTest{}) go delayClose(t, r, c, pipeTest{})
n, err := r.Read(make([]byte, 64)) n, err := r.Read(make([]byte, 64))
<-c <-c
if n != 0 || err != os.EINVAL { if n != 0 || err != ErrClosedPipe {
t.Errorf("read from closed pipe: %v, %v want %v, %v", n, err, 0, os.EINVAL) t.Errorf("read from closed pipe: %v, %v want %v, %v", n, err, 0, ErrClosedPipe)
} }
} }
...@@ -234,7 +233,7 @@ func TestPipeWriteClose(t *testing.T) { ...@@ -234,7 +233,7 @@ func TestPipeWriteClose(t *testing.T) {
<-c <-c
expect := tt.err expect := tt.err
if expect == nil { if expect == nil {
expect = os.EPIPE expect = ErrClosedPipe
} }
if err != expect { if err != expect {
t.Errorf("write on closed pipe: %v want %v", err, expect) t.Errorf("write on closed pipe: %v want %v", err, expect)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment