diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-10-28 13:43:33 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-10-28 13:43:33 +0000 |
commit | bab85b65e545231656361b997a81fb8a44b266b4 (patch) | |
tree | 25b3da36ffb0e65619ba42780e8707ba0937daea /libgo/go/io | |
parent | 739016b56c81a76c269a10fec5844a608b97c09c (diff) | |
download | gcc-bab85b65e545231656361b997a81fb8a44b266b4.tar.gz |
2011-10-28 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 180613 using svnmerge
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@180615 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/go/io')
-rw-r--r-- | libgo/go/io/io.go | 30 | ||||
-rw-r--r-- | libgo/go/io/io_test.go | 67 | ||||
-rw-r--r-- | libgo/go/io/ioutil/ioutil.go | 4 |
3 files changed, 78 insertions, 23 deletions
diff --git a/libgo/go/io/io.go b/libgo/go/io/io.go index b879fe5b721..55206348e42 100644 --- a/libgo/go/io/io.go +++ b/libgo/go/io/io.go @@ -256,15 +256,15 @@ func ReadFull(r Reader, buf []byte) (n int, err os.Error) { return ReadAtLeast(r, buf, len(buf)) } -// Copyn copies n bytes (or until an error) 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 earliest // error encountered while copying. Because Read can // return the full amount requested as well as an error -// (including os.EOF), so can Copyn. +// (including os.EOF), so can CopyN. // // If dst implements the ReaderFrom interface, // the copy is implemented by calling dst.ReadFrom(src). -func Copyn(dst Writer, src Reader, n int64) (written int64, err os.Error) { +func CopyN(dst Writer, src Reader, n int64) (written int64, err os.Error) { // If the writer has a ReadFrom method, use it to do the copy. // Avoids a buffer allocation and a copy. if rt, ok := dst.(ReaderFrom); ok { @@ -437,3 +437,27 @@ func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err os.Error) { // Size returns the size of the section in bytes. func (s *SectionReader) Size() int64 { return s.limit - s.base } + +// TeeReader returns a Reader that writes to w what it reads from r. +// All reads from r performed through it are matched with +// corresponding writes to w. There is no internal buffering - +// the write must complete before the read completes. +// Any error encountered while writing is reported as a read error. +func TeeReader(r Reader, w Writer) Reader { + return &teeReader{r, w} +} + +type teeReader struct { + r Reader + w Writer +} + +func (t *teeReader) Read(p []byte) (n int, err os.Error) { + n, err = t.r.Read(p) + if n > 0 { + if n, err := t.w.Write(p[:n]); err != nil { + return n, err + } + } + return +} diff --git a/libgo/go/io/io_test.go b/libgo/go/io/io_test.go index bc4f354af40..f1b23e9461b 100644 --- a/libgo/go/io/io_test.go +++ b/libgo/go/io/io_test.go @@ -19,7 +19,7 @@ type Buffer struct { WriterTo // conflicts with and hides bytes.Buffer's WriterTo. } -// Simple tests, primarily to verify the ReadFrom and WriteTo callouts inside Copy and Copyn. +// Simple tests, primarily to verify the ReadFrom and WriteTo callouts inside Copy and CopyN. func TestCopy(t *testing.T) { rb := new(Buffer) @@ -51,33 +51,33 @@ func TestCopyWriteTo(t *testing.T) { } } -func TestCopyn(t *testing.T) { +func TestCopyN(t *testing.T) { rb := new(Buffer) wb := new(Buffer) rb.WriteString("hello, world.") - Copyn(wb, rb, 5) + CopyN(wb, rb, 5) if wb.String() != "hello" { - t.Errorf("Copyn did not work properly") + t.Errorf("CopyN did not work properly") } } -func TestCopynReadFrom(t *testing.T) { +func TestCopyNReadFrom(t *testing.T) { rb := new(Buffer) wb := new(bytes.Buffer) // implements ReadFrom. rb.WriteString("hello") - Copyn(wb, rb, 5) + CopyN(wb, rb, 5) if wb.String() != "hello" { - t.Errorf("Copyn did not work properly") + t.Errorf("CopyN did not work properly") } } -func TestCopynWriteTo(t *testing.T) { +func TestCopyNWriteTo(t *testing.T) { rb := new(bytes.Buffer) // implements WriteTo. wb := new(Buffer) rb.WriteString("hello, world.") - Copyn(wb, rb, 5) + CopyN(wb, rb, 5) if wb.String() != "hello" { - t.Errorf("Copyn did not work properly") + t.Errorf("CopyN did not work properly") } } @@ -89,30 +89,30 @@ func (w *noReadFrom) Write(p []byte) (n int, err os.Error) { return w.w.Write(p) } -func TestCopynEOF(t *testing.T) { +func TestCopyNEOF(t *testing.T) { // Test that EOF behavior is the same regardless of whether - // argument to Copyn has ReadFrom. + // argument to CopyN has ReadFrom. b := new(bytes.Buffer) - n, err := Copyn(&noReadFrom{b}, strings.NewReader("foo"), 3) + n, err := CopyN(&noReadFrom{b}, strings.NewReader("foo"), 3) if n != 3 || err != nil { - t.Errorf("Copyn(noReadFrom, foo, 3) = %d, %v; want 3, nil", n, err) + t.Errorf("CopyN(noReadFrom, foo, 3) = %d, %v; want 3, nil", n, err) } - n, err = Copyn(&noReadFrom{b}, strings.NewReader("foo"), 4) + n, err = CopyN(&noReadFrom{b}, strings.NewReader("foo"), 4) if n != 3 || err != os.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) } - n, err = Copyn(b, strings.NewReader("foo"), 3) // b has read from + n, err = CopyN(b, strings.NewReader("foo"), 3) // b has read from if n != 3 || err != nil { - t.Errorf("Copyn(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n, err) + t.Errorf("CopyN(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n, err) } - 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 { - 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) } } @@ -177,3 +177,30 @@ func testReadAtLeast(t *testing.T, rb ReadWriter) { t.Errorf("expected to have read 1 bytes, got %v", n) } } + +func TestTeeReader(t *testing.T) { + src := []byte("hello, world") + dst := make([]byte, len(src)) + rb := bytes.NewBuffer(src) + wb := new(bytes.Buffer) + r := TeeReader(rb, wb) + if n, err := ReadFull(r, dst); err != nil || n != len(src) { + t.Fatalf("ReadFull(r, dst) = %d, %v; want %d, nil", n, err, len(src)) + } + if !bytes.Equal(dst, src) { + t.Errorf("bytes read = %q want %q", dst, src) + } + if !bytes.Equal(wb.Bytes(), src) { + t.Errorf("bytes written = %q want %q", wb.Bytes(), src) + } + if n, err := r.Read(dst); n != 0 || err != os.EOF { + t.Errorf("r.Read at EOF = %d, %v want 0, EOF", n, err) + } + rb = bytes.NewBuffer(src) + pr, pw := Pipe() + pr.Close() + r = TeeReader(rb, pw) + if n, err := ReadFull(r, dst); n != 0 || err != os.EPIPE { + t.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n, err) + } +} diff --git a/libgo/go/io/ioutil/ioutil.go b/libgo/go/io/ioutil/ioutil.go index fffa1320f59..dd50d96869e 100644 --- a/libgo/go/io/ioutil/ioutil.go +++ b/libgo/go/io/ioutil/ioutil.go @@ -104,6 +104,10 @@ func NopCloser(r io.Reader) io.ReadCloser { type devNull int +// devNull implements ReaderFrom as an optimization so io.Copy to +// ioutil.Discard can avoid doing unnecessary work. +var _ io.ReaderFrom = devNull(0) + func (devNull) Write(p []byte) (int, os.Error) { return len(p), nil } |