From f98dd1a338867a408f7c72d73fbad7fe7fc93e3a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 3 Feb 2016 21:58:02 +0000 Subject: libgo: Update to go1.6rc1. Reviewed-on: https://go-review.googlesource.com/19200 From-SVN: r233110 --- libgo/go/io/example_test.go | 223 +++++++++++++++++++++++++++++++++++++ libgo/go/io/io.go | 13 +-- libgo/go/io/ioutil/example_test.go | 73 ++++++++++++ libgo/go/io/ioutil/ioutil.go | 2 +- libgo/go/io/multi.go | 24 ++++ libgo/go/io/multi_test.go | 54 ++++++++- 6 files changed, 380 insertions(+), 9 deletions(-) create mode 100644 libgo/go/io/example_test.go create mode 100644 libgo/go/io/ioutil/example_test.go (limited to 'libgo/go/io') diff --git a/libgo/go/io/example_test.go b/libgo/go/io/example_test.go new file mode 100644 index 0000000..412dfb3 --- /dev/null +++ b/libgo/go/io/example_test.go @@ -0,0 +1,223 @@ +// Copyright 2015 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_test + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "strings" +) + +func ExampleCopy() { + r := strings.NewReader("some io.Reader stream to be read\n") + + if _, err := io.Copy(os.Stdout, r); err != nil { + log.Fatal(err) + } + + // Output: + // some io.Reader stream to be read +} + +func ExampleCopyBuffer() { + r1 := strings.NewReader("first reader\n") + r2 := strings.NewReader("second reader\n") + buf := make([]byte, 8) + + // buf is used here... + if _, err := io.CopyBuffer(os.Stdout, r1, buf); err != nil { + log.Fatal(err) + } + + // ... reused here also. No need to allocate an extra buffer. + if _, err := io.CopyBuffer(os.Stdout, r2, buf); err != nil { + log.Fatal(err) + } + + // Output: + // first reader + // second reader +} + +func ExampleCopyN() { + r := strings.NewReader("some io.Reader stream to be read") + + if _, err := io.CopyN(os.Stdout, r, 5); err != nil { + log.Fatal(err) + } + + // Output: + // some +} + +func ExampleReadAtLeast() { + r := strings.NewReader("some io.Reader stream to be read\n") + + buf := make([]byte, 33) + if _, err := io.ReadAtLeast(r, buf, 4); err != nil { + log.Fatal(err) + } + fmt.Printf("%s\n", buf) + + // buffer smaller than minimal read size. + shortBuf := make([]byte, 3) + if _, err := io.ReadAtLeast(r, shortBuf, 4); err != nil { + fmt.Println("error:", err) + } + + // minimal read size bigger than io.Reader stream + longBuf := make([]byte, 64) + if _, err := io.ReadAtLeast(r, longBuf, 64); err != nil { + fmt.Println("error:", err) + } + + // Output: + // some io.Reader stream to be read + // + // error: short buffer + // error: EOF +} + +func ExampleReadFull() { + r := strings.NewReader("some io.Reader stream to be read\n") + + buf := make([]byte, 4) + if _, err := io.ReadFull(r, buf); err != nil { + log.Fatal(err) + } + fmt.Printf("%s\n", buf) + + // minimal read size bigger than io.Reader stream + longBuf := make([]byte, 64) + if _, err := io.ReadFull(r, longBuf); err != nil { + fmt.Println("error:", err) + } + + // Output: + // some + // error: unexpected EOF +} + +func ExampleWriteString() { + io.WriteString(os.Stdout, "Hello World") + + // Output: Hello World +} + +func ExampleLimitReader() { + r := strings.NewReader("some io.Reader stream to be read\n") + lr := io.LimitReader(r, 4) + + if _, err := io.Copy(os.Stdout, lr); err != nil { + log.Fatal(err) + } + + // Output: + // some +} + +func ExampleMultiReader() { + r1 := strings.NewReader("first reader ") + r2 := strings.NewReader("second reader ") + r3 := strings.NewReader("third reader\n") + r := io.MultiReader(r1, r2, r3) + + if _, err := io.Copy(os.Stdout, r); err != nil { + log.Fatal(err) + } + + // Output: + // first reader second reader third reader +} + +func ExampleTeeReader() { + r := strings.NewReader("some io.Reader stream to be read\n") + var buf bytes.Buffer + tee := io.TeeReader(r, &buf) + + printall := func(r io.Reader) { + b, err := ioutil.ReadAll(r) + if err != nil { + log.Fatal(err) + } + + fmt.Printf("%s", b) + } + + printall(tee) + printall(&buf) + + // Output: + // some io.Reader stream to be read + // some io.Reader stream to be read +} + +func ExampleSectionReader() { + r := strings.NewReader("some io.Reader stream to be read\n") + s := io.NewSectionReader(r, 5, 17) + + if _, err := io.Copy(os.Stdout, s); err != nil { + log.Fatal(err) + } + + // Output: + // io.Reader stream +} + +func ExampleSectionReader_ReadAt() { + r := strings.NewReader("some io.Reader stream to be read\n") + s := io.NewSectionReader(r, 5, 16) + + buf := make([]byte, 6) + if _, err := s.ReadAt(buf, 10); err != nil { + log.Fatal(err) + } + + fmt.Printf("%s\n", buf) + + // Output: + // stream +} + +func ExampleSectionReader_Seek() { + r := strings.NewReader("some io.Reader stream to be read\n") + s := io.NewSectionReader(r, 5, 16) + + if _, err := s.Seek(10, 0); err != nil { + log.Fatal(err) + } + + buf := make([]byte, 6) + if _, err := s.Read(buf); err != nil { + log.Fatal(err) + } + + fmt.Printf("%s\n", buf) + + // Output: + // stream +} + +func ExampleMultiWriter() { + r := strings.NewReader("some io.Reader stream to be read\n") + + var buf1, buf2 bytes.Buffer + w := io.MultiWriter(&buf1, &buf2) + + if _, err := io.Copy(w, r); err != nil { + log.Fatal(err) + } + + fmt.Print(buf1.String()) + fmt.Print(buf2.String()) + + // Output: + // some io.Reader stream to be read + // some io.Reader stream to be read +} diff --git a/libgo/go/io/io.go b/libgo/go/io/io.go index 8851eaf..8e7855c 100644 --- a/libgo/go/io/io.go +++ b/libgo/go/io/io.go @@ -95,14 +95,14 @@ type Closer interface { // Seeker is the interface that wraps the basic Seek method. // // Seek sets the offset for the next Read or Write to offset, -// interpreted according to whence: 0 means relative to the origin of +// interpreted according to whence: 0 means relative to the start of // the file, 1 means relative to the current offset, and 2 means -// relative to the end. Seek returns the new offset and an error, if -// any. +// relative to the end. Seek returns the new offset relative to the +// start of the file and an error, if any. // -// Seeking to a negative offset is an error. Seeking to any positive -// offset is legal, but the behavior of subsequent I/O operations on -// the underlying object is implementation-dependent. +// Seeking to an offset before the start of the file is an error. +// Seeking to any positive offset is legal, but the behavior of subsequent +// I/O operations on the underlying object is implementation-dependent. type Seeker interface { Seek(offset int64, whence int) (int64, error) } @@ -225,7 +225,6 @@ type WriterAt interface { // ByteReader is the interface that wraps the ReadByte method. // // ReadByte reads and returns the next byte from the input. -// If no byte is available, err will be set. type ByteReader interface { ReadByte() (c byte, err error) } diff --git a/libgo/go/io/ioutil/example_test.go b/libgo/go/io/ioutil/example_test.go new file mode 100644 index 0000000..74a7791 --- /dev/null +++ b/libgo/go/io/ioutil/example_test.go @@ -0,0 +1,73 @@ +// Copyright 2015 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. + +// +build ignore + +package ioutil_test + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" +) + +func ExampleReadAll() { + r := strings.NewReader("Go is a general-purpose language designed with systems programming in mind.") + + b, err := ioutil.ReadAll(r) + if err != nil { + log.Fatal(err) + } + + fmt.Printf("%s", b) + + // Output: + // Go is a general-purpose language designed with systems programming in mind. +} + +func ExampleReadDir() { + files, err := ioutil.ReadDir(".") + if err != nil { + log.Fatal(err) + } + + for _, file := range files { + fmt.Println(file.Name()) + } +} + +func ExampleTempDir() { + content := []byte("temporary file's content") + dir, err := ioutil.TempDir("", "example") + if err != nil { + log.Fatal(err) + } + + defer os.RemoveAll(dir) // clean up + + tmpfn := filepath.Join(dir, "tmpfile") + if err := ioutil.WriteFile(tmpfn, content, 0666); err != nil { + log.Fatal(err) + } +} + +func ExampleTempFile() { + content := []byte("temporary file's content") + tmpfile, err := ioutil.TempFile("", "example") + if err != nil { + log.Fatal(err) + } + + defer os.Remove(tmpfile.Name()) // clean up + + if _, err := tmpfile.Write(content); err != nil { + log.Fatal(err) + } + if err := tmpfile.Close(); err != nil { + log.Fatal(err) + } +} diff --git a/libgo/go/io/ioutil/ioutil.go b/libgo/go/io/ioutil/ioutil.go index 909a815..e90a33f 100644 --- a/libgo/go/io/ioutil/ioutil.go +++ b/libgo/go/io/ioutil/ioutil.go @@ -96,7 +96,7 @@ func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() } func (f byName) Swap(i, j int) { f[i], f[j] = f[j], f[i] } // ReadDir reads the directory named by dirname and returns -// a list of sorted directory entries. +// a list of directory entries sorted by filename. func ReadDir(dirname string) ([]os.FileInfo, error) { f, err := os.Open(dirname) if err != nil { diff --git a/libgo/go/io/multi.go b/libgo/go/io/multi.go index e26cc53..16860aa 100644 --- a/libgo/go/io/multi.go +++ b/libgo/go/io/multi.go @@ -52,6 +52,30 @@ func (t *multiWriter) Write(p []byte) (n int, err error) { return len(p), nil } +var _ stringWriter = (*multiWriter)(nil) + +func (t *multiWriter) WriteString(s string) (n int, err error) { + var p []byte // lazily initialized if/when needed + for _, w := range t.writers { + if sw, ok := w.(stringWriter); ok { + n, err = sw.WriteString(s) + } else { + if p == nil { + p = []byte(s) + } + n, err = w.Write(p) + } + if err != nil { + return + } + if n != len(s) { + err = ErrShortWrite + return + } + } + return len(s), nil +} + // MultiWriter creates a writer that duplicates its writes to all the // provided writers, similar to the Unix tee(1) command. func MultiWriter(writers ...Writer) Writer { diff --git a/libgo/go/io/multi_test.go b/libgo/go/io/multi_test.go index 56c6769..c5d1b95 100644 --- a/libgo/go/io/multi_test.go +++ b/libgo/go/io/multi_test.go @@ -62,8 +62,60 @@ func TestMultiReader(t *testing.T) { } func TestMultiWriter(t *testing.T) { - sha1 := sha1.New() sink := new(bytes.Buffer) + // Hide bytes.Buffer's WriteString method: + testMultiWriter(t, struct { + Writer + fmt.Stringer + }{sink, sink}) +} + +func TestMultiWriter_String(t *testing.T) { + testMultiWriter(t, new(bytes.Buffer)) +} + +// test that a multiWriter.WriteString calls results in at most 1 allocation, +// even if multiple targets don't support WriteString. +func TestMultiWriter_WriteStringSingleAlloc(t *testing.T) { + t.Skip("skipping on gccgo until we have escape analysis") + var sink1, sink2 bytes.Buffer + type simpleWriter struct { // hide bytes.Buffer's WriteString + Writer + } + mw := MultiWriter(simpleWriter{&sink1}, simpleWriter{&sink2}) + allocs := int(testing.AllocsPerRun(1000, func() { + WriteString(mw, "foo") + })) + if allocs != 1 { + t.Errorf("num allocations = %d; want 1", allocs) + } +} + +type writeStringChecker struct{ called bool } + +func (c *writeStringChecker) WriteString(s string) (n int, err error) { + c.called = true + return len(s), nil +} + +func (c *writeStringChecker) Write(p []byte) (n int, err error) { + return len(p), nil +} + +func TestMultiWriter_StringCheckCall(t *testing.T) { + var c writeStringChecker + mw := MultiWriter(&c) + WriteString(mw, "foo") + if !c.called { + t.Error("did not see WriteString call to writeStringChecker") + } +} + +func testMultiWriter(t *testing.T, sink interface { + Writer + fmt.Stringer +}) { + sha1 := sha1.New() mw := MultiWriter(sha1, sink) sourceString := "My input text." -- cgit v1.1