blob: 16860aa361f13ab62f6afc33857a2d308a7ac7c5 [file] [log] [blame]
Brad Fitzpatrick719cde22010-07-28 11:30:00 -07001// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package io
6
Brad Fitzpatrick719cde22010-07-28 11:30:00 -07007type multiReader struct {
8 readers []Reader
9}
10
Russ Coxc06cf032011-11-01 21:48:52 -040011func (mr *multiReader) Read(p []byte) (n int, err error) {
Brad Fitzpatrick719cde22010-07-28 11:30:00 -070012 for len(mr.readers) > 0 {
13 n, err = mr.readers[0].Read(p)
Russ Coxc06cf032011-11-01 21:48:52 -040014 if n > 0 || err != EOF {
15 if err == EOF {
Robert Hencke8dc0ba72011-04-08 13:45:56 -040016 // Don't return EOF yet. There may be more bytes
17 // in the remaining readers.
Brad Fitzpatrick719cde22010-07-28 11:30:00 -070018 err = nil
19 }
20 return
21 }
22 mr.readers = mr.readers[1:]
23 }
Russ Coxc06cf032011-11-01 21:48:52 -040024 return 0, EOF
Brad Fitzpatrick719cde22010-07-28 11:30:00 -070025}
26
27// MultiReader returns a Reader that's the logical concatenation of
28// the provided input readers. They're read sequentially. Once all
Andrew Gerrand5be96aa2014-01-28 19:49:29 +110029// inputs have returned EOF, Read will return EOF. If any of the readers
30// return a non-nil, non-EOF error, Read will return that error.
Brad Fitzpatrick719cde22010-07-28 11:30:00 -070031func MultiReader(readers ...Reader) Reader {
Russ Cox211618c2014-05-12 23:38:35 -040032 r := make([]Reader, len(readers))
33 copy(r, readers)
34 return &multiReader{r}
Brad Fitzpatrick719cde22010-07-28 11:30:00 -070035}
Rob Pike3f5966d2010-08-03 08:04:33 +100036
37type multiWriter struct {
38 writers []Writer
39}
40
Russ Coxc06cf032011-11-01 21:48:52 -040041func (t *multiWriter) Write(p []byte) (n int, err error) {
Rob Pike3f5966d2010-08-03 08:04:33 +100042 for _, w := range t.writers {
43 n, err = w.Write(p)
44 if err != nil {
45 return
46 }
47 if n != len(p) {
48 err = ErrShortWrite
49 return
50 }
51 }
52 return len(p), nil
53}
54
Brad Fitzpatrick9c514e12015-07-21 12:24:33 -070055var _ stringWriter = (*multiWriter)(nil)
56
57func (t *multiWriter) WriteString(s string) (n int, err error) {
58 var p []byte // lazily initialized if/when needed
59 for _, w := range t.writers {
60 if sw, ok := w.(stringWriter); ok {
61 n, err = sw.WriteString(s)
62 } else {
63 if p == nil {
64 p = []byte(s)
65 }
66 n, err = w.Write(p)
67 }
68 if err != nil {
69 return
70 }
71 if n != len(s) {
72 err = ErrShortWrite
73 return
74 }
75 }
76 return len(s), nil
77}
78
Rob Pike3f5966d2010-08-03 08:04:33 +100079// MultiWriter creates a writer that duplicates its writes to all the
80// provided writers, similar to the Unix tee(1) command.
81func MultiWriter(writers ...Writer) Writer {
Russ Cox211618c2014-05-12 23:38:35 -040082 w := make([]Writer, len(writers))
83 copy(w, writers)
84 return &multiWriter{w}
Rob Pike3f5966d2010-08-03 08:04:33 +100085}