Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 1 | // Copyright 2009 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 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame] | 5 | // This package provides basic interfaces to I/O primitives. |
| 6 | // Its primary job is to wrap existing implementations of such primitives, |
| 7 | // such as those in package os, into shared public interfaces that |
Rob Pike | b0683bd | 2009-12-02 22:02:14 -0800 | [diff] [blame] | 8 | // abstract the functionality, plus some other related primitives. |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 9 | package io |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 10 | |
Russ Cox | 9750adb | 2010-02-25 16:01:29 -0800 | [diff] [blame] | 11 | import "os" |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 12 | |
Russ Cox | 3b36acc | 2009-05-18 11:47:35 -0700 | [diff] [blame] | 13 | // Error represents an unexpected I/O behavior. |
Russ Cox | 1b301ba | 2009-05-08 14:40:20 -0700 | [diff] [blame] | 14 | type Error struct { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 15 | os.ErrorString |
Russ Cox | 1b301ba | 2009-05-08 14:40:20 -0700 | [diff] [blame] | 16 | } |
Russ Cox | 3b36acc | 2009-05-18 11:47:35 -0700 | [diff] [blame] | 17 | |
Russ Cox | 3b36acc | 2009-05-18 11:47:35 -0700 | [diff] [blame] | 18 | // ErrShortWrite means that a write accepted fewer bytes than requested |
| 19 | // but failed to return an explicit error. |
| 20 | var ErrShortWrite os.Error = &Error{"short write"} |
| 21 | |
Andrew Gerrand | 4642708 | 2010-08-23 12:04:15 +1000 | [diff] [blame] | 22 | // ErrShortBuffer means that a read required a longer buffer than was provided. |
| 23 | var ErrShortBuffer os.Error = &Error{"short buffer"} |
| 24 | |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 25 | // ErrUnexpectedEOF means that os.EOF was encountered in the |
| 26 | // middle of reading a fixed-size block or data structure. |
| 27 | var ErrUnexpectedEOF os.Error = &Error{"unexpected EOF"} |
Russ Cox | 3b36acc | 2009-05-18 11:47:35 -0700 | [diff] [blame] | 28 | |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 29 | // Reader is the interface that wraps the basic Read method. |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 30 | // |
| 31 | // Read reads up to len(p) bytes into p. It returns the number of bytes |
Russ Cox | 71f19d6 | 2009-06-22 14:44:07 -0700 | [diff] [blame] | 32 | // read (0 <= n <= len(p)) and any error encountered. |
| 33 | // Even if Read returns n < len(p), |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 34 | // it may use all of p as scratch space during the call. |
| 35 | // If some data is available but not len(p) bytes, Read conventionally |
| 36 | // returns what is available rather than block waiting for more. |
| 37 | // |
| 38 | // At the end of the input stream, Read returns 0, os.EOF. |
| 39 | // Read may return a non-zero number of bytes with a non-nil err. |
| 40 | // In particular, a Read that exhausts the input may return n > 0, os.EOF. |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 41 | type Reader interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 42 | Read(p []byte) (n int, err os.Error) |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 43 | } |
| 44 | |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 45 | // Writer is the interface that wraps the basic Write method. |
Russ Cox | 71f19d6 | 2009-06-22 14:44:07 -0700 | [diff] [blame] | 46 | // |
| 47 | // Write writes len(p) bytes from p to the underlying data stream. |
| 48 | // It returns the number of bytes written from p (0 <= n <= len(p)) |
| 49 | // and any error encountered that caused the write to stop early. |
| 50 | // Write must return a non-nil error if it returns n < len(p). |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 51 | type Writer interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 52 | Write(p []byte) (n int, err os.Error) |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 53 | } |
| 54 | |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 55 | // Closer is the interface that wraps the basic Close method. |
| 56 | type Closer interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 57 | Close() os.Error |
Russ Cox | 78906c3 | 2009-02-16 16:32:30 -0800 | [diff] [blame] | 58 | } |
| 59 | |
Austin Clements | b3062f1 | 2009-08-18 17:47:03 -0700 | [diff] [blame] | 60 | // Seeker is the interface that wraps the basic Seek method. |
| 61 | // |
| 62 | // Seek sets the offset for the next Read or Write to offset, |
| 63 | // interpreted according to whence: 0 means relative to the origin of |
| 64 | // the file, 1 means relative to the current offset, and 2 means |
| 65 | // relative to the end. Seek returns the new offset and an Error, if |
| 66 | // any. |
| 67 | type Seeker interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 68 | Seek(offset int64, whence int) (ret int64, err os.Error) |
Austin Clements | b3062f1 | 2009-08-18 17:47:03 -0700 | [diff] [blame] | 69 | } |
| 70 | |
Russ Cox | b90f673 | 2009-11-23 14:22:56 -0800 | [diff] [blame] | 71 | // ReadWriter is the interface that groups the basic Read and Write methods. |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 72 | type ReadWriter interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 73 | Reader |
| 74 | Writer |
Russ Cox | 9350ef4 | 2008-09-17 13:49:23 -0700 | [diff] [blame] | 75 | } |
| 76 | |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 77 | // ReadCloser is the interface that groups the basic Read and Close methods. |
| 78 | type ReadCloser interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 79 | Reader |
| 80 | Closer |
Russ Cox | 78906c3 | 2009-02-16 16:32:30 -0800 | [diff] [blame] | 81 | } |
| 82 | |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 83 | // WriteCloser is the interface that groups the basic Write and Close methods. |
| 84 | type WriteCloser interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 85 | Writer |
| 86 | Closer |
Russ Cox | 7c7a525 | 2008-10-20 12:37:07 -0700 | [diff] [blame] | 87 | } |
| 88 | |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 89 | // ReadWriteCloser is the interface that groups the basic Read, Write and Close methods. |
| 90 | type ReadWriteCloser interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 91 | Reader |
| 92 | Writer |
| 93 | Closer |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 94 | } |
| 95 | |
Austin Clements | b3062f1 | 2009-08-18 17:47:03 -0700 | [diff] [blame] | 96 | // ReadSeeker is the interface that groups the basic Read and Seek methods. |
| 97 | type ReadSeeker interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 98 | Reader |
| 99 | Seeker |
Austin Clements | b3062f1 | 2009-08-18 17:47:03 -0700 | [diff] [blame] | 100 | } |
| 101 | |
| 102 | // WriteSeeker is the interface that groups the basic Write and Seek methods. |
| 103 | type WriteSeeker interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 104 | Writer |
| 105 | Seeker |
Austin Clements | b3062f1 | 2009-08-18 17:47:03 -0700 | [diff] [blame] | 106 | } |
| 107 | |
| 108 | // ReadWriteSeeker is the interface that groups the basic Read, Write and Seek methods. |
| 109 | type ReadWriteSeeker interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 110 | Reader |
| 111 | Writer |
| 112 | Seeker |
Austin Clements | b3062f1 | 2009-08-18 17:47:03 -0700 | [diff] [blame] | 113 | } |
| 114 | |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 115 | // ReaderFrom is the interface that wraps the ReadFrom method. |
| 116 | type ReaderFrom interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 117 | ReadFrom(r Reader) (n int64, err os.Error) |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 118 | } |
| 119 | |
| 120 | // WriterTo is the interface that wraps the WriteTo method. |
| 121 | type WriterTo interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 122 | WriteTo(w Writer) (n int64, err os.Error) |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 123 | } |
| 124 | |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 125 | // ReaderAt is the interface that wraps the basic ReadAt method. |
| 126 | // |
| 127 | // ReadAt reads len(p) bytes into p starting at offset off in the |
| 128 | // underlying data stream. It returns the number of bytes |
| 129 | // read (0 <= n <= len(p)) and any error encountered. |
| 130 | // |
| 131 | // Even if ReadAt returns n < len(p), |
| 132 | // it may use all of p as scratch space during the call. |
| 133 | // If some data is available but not len(p) bytes, ReadAt blocks |
| 134 | // until either all the data is available or an error occurs. |
| 135 | // |
| 136 | // At the end of the input stream, ReadAt returns 0, os.EOF. |
| 137 | // ReadAt may return a non-zero number of bytes with a non-nil err. |
| 138 | // In particular, a ReadAt that exhausts the input may return n > 0, os.EOF. |
| 139 | type ReaderAt interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 140 | ReadAt(p []byte, off int64) (n int, err os.Error) |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 141 | } |
| 142 | |
| 143 | // WriterAt is the interface that wraps the basic WriteAt method. |
| 144 | // |
| 145 | // WriteAt writes len(p) bytes from p to the underlying data stream |
| 146 | // at offset off. It returns the number of bytes written from p (0 <= n <= len(p)) |
| 147 | // and any error encountered that caused the write to stop early. |
| 148 | // WriteAt must return a non-nil error if it returns n < len(p). |
| 149 | type WriterAt interface { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 150 | WriteAt(p []byte, off int64) (n int, err os.Error) |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 151 | } |
| 152 | |
Robert Griesemer | 827e98d | 2011-02-02 13:42:15 -0800 | [diff] [blame^] | 153 | // ByteReader is the interface that wraps the ReadByte method. |
Rob Pike | fce5d60 | 2010-01-07 13:29:43 +1100 | [diff] [blame] | 154 | // |
| 155 | // ReadByte reads and returns the next byte from the input. |
| 156 | // If no byte is available, err will be set. |
Robert Griesemer | 827e98d | 2011-02-02 13:42:15 -0800 | [diff] [blame^] | 157 | type ByteReader interface { |
Rob Pike | fce5d60 | 2010-01-07 13:29:43 +1100 | [diff] [blame] | 158 | ReadByte() (c byte, err os.Error) |
| 159 | } |
| 160 | |
Robert Griesemer | 827e98d | 2011-02-02 13:42:15 -0800 | [diff] [blame^] | 161 | // RuneReader is the interface that wraps the ReadRune method. |
Rob Pike | 622d729 | 2011-02-01 21:09:33 -0800 | [diff] [blame] | 162 | // |
| 163 | // ReadRune reads a single UTF-8 encoded Unicode character |
| 164 | // and returns the rune and its size in bytes. If no character is |
| 165 | // available, err will be set. |
Robert Griesemer | 827e98d | 2011-02-02 13:42:15 -0800 | [diff] [blame^] | 166 | type RuneReader interface { |
Rob Pike | 622d729 | 2011-02-01 21:09:33 -0800 | [diff] [blame] | 167 | ReadRune() (rune int, size int, err os.Error) |
| 168 | } |
| 169 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame] | 170 | // WriteString writes the contents of the string s to w, which accepts an array of bytes. |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 171 | func WriteString(w Writer, s string) (n int, err os.Error) { |
Russ Cox | 9750adb | 2010-02-25 16:01:29 -0800 | [diff] [blame] | 172 | return w.Write([]byte(s)) |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 173 | } |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 174 | |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 175 | // ReadAtLeast reads from r into buf until it has read at least min bytes. |
| 176 | // It returns the number of bytes copied and an error if fewer bytes were read. |
| 177 | // The error is os.EOF only if no bytes were read. |
| 178 | // If an EOF happens after reading fewer than min bytes, |
| 179 | // ReadAtLeast returns ErrUnexpectedEOF. |
Andrew Gerrand | 4642708 | 2010-08-23 12:04:15 +1000 | [diff] [blame] | 180 | // If min is greater than the length of buf, ReadAtLeast returns ErrShortBuffer. |
Russ Cox | b0608c13 | 2009-05-19 14:01:03 -0700 | [diff] [blame] | 181 | func ReadAtLeast(r Reader, buf []byte, min int) (n int, err os.Error) { |
Andrew Gerrand | 4642708 | 2010-08-23 12:04:15 +1000 | [diff] [blame] | 182 | if len(buf) < min { |
| 183 | return 0, ErrShortBuffer |
| 184 | } |
Russ Cox | b0608c13 | 2009-05-19 14:01:03 -0700 | [diff] [blame] | 185 | for n < min { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 186 | nn, e := r.Read(buf[n:]) |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 187 | if nn > 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 188 | n += nn |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 189 | } |
| 190 | if e != nil { |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 191 | if e == os.EOF && n > 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 192 | e = ErrUnexpectedEOF |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 193 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 194 | return n, e |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 195 | } |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 196 | } |
Andrew Gerrand | 4642708 | 2010-08-23 12:04:15 +1000 | [diff] [blame] | 197 | return |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 198 | } |
| 199 | |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 200 | // ReadFull reads exactly len(buf) bytes from r into buf. |
| 201 | // It returns the number of bytes copied and an error if fewer bytes were read. |
| 202 | // The error is os.EOF only if no bytes were read. |
| 203 | // If an EOF happens after reading some but not all the bytes, |
| 204 | // ReadFull returns ErrUnexpectedEOF. |
| 205 | func ReadFull(r Reader, buf []byte) (n int, err os.Error) { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 206 | return ReadAtLeast(r, buf, len(buf)) |
Russ Cox | b0608c13 | 2009-05-19 14:01:03 -0700 | [diff] [blame] | 207 | } |
| 208 | |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 209 | // Copyn copies n bytes (or until an error) from src to dst. |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame] | 210 | // It returns the number of bytes copied and the error, if any. |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 211 | // |
| 212 | // If dst implements the ReaderFrom interface, |
| 213 | // the copy is implemented by calling dst.ReadFrom(src). |
Rob Pike | 4d310f2 | 2009-11-01 20:59:49 -0800 | [diff] [blame] | 214 | func Copyn(dst Writer, src Reader, n int64) (written int64, err os.Error) { |
Anschel Schaffer-Cohen | 84fc1e2 | 2010-12-31 10:37:55 +1100 | [diff] [blame] | 215 | // If the writer has a ReadFrom method, use it to do the copy. |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 216 | // Avoids a buffer allocation and a copy. |
| 217 | if rt, ok := dst.(ReaderFrom); ok { |
Russ Cox | 0f26608 | 2011-01-05 14:35:13 -0500 | [diff] [blame] | 218 | written, err = rt.ReadFrom(LimitReader(src, n)) |
| 219 | if written < n && err == nil { |
| 220 | // rt stopped early; must have been EOF. |
| 221 | err = os.EOF |
| 222 | } |
| 223 | return |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 224 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 225 | buf := make([]byte, 32*1024) |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 226 | for written < n { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 227 | l := len(buf) |
Robert Griesemer | 3bb0032 | 2009-11-09 21:23:52 -0800 | [diff] [blame] | 228 | if d := n - written; d < int64(l) { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 229 | l = int(d) |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 230 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 231 | nr, er := src.Read(buf[0:l]) |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 232 | if nr > 0 { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 233 | nw, ew := dst.Write(buf[0:nr]) |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 234 | if nw > 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 235 | written += int64(nw) |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 236 | } |
| 237 | if ew != nil { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 238 | err = ew |
| 239 | break |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 240 | } |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 241 | if nr != nw { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 242 | err = ErrShortWrite |
| 243 | break |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 244 | } |
| 245 | } |
| 246 | if er != nil { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 247 | err = er |
| 248 | break |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 249 | } |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 250 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 251 | return written, err |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 252 | } |
| 253 | |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 254 | // Copy copies from src to dst until either EOF is reached |
| 255 | // on src or an error occurs. It returns the number of bytes |
| 256 | // copied and the error, if any. |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 257 | // |
| 258 | // If dst implements the ReaderFrom interface, |
| 259 | // the copy is implemented by calling dst.ReadFrom(src). |
| 260 | // Otherwise, if src implements the WriterTo interface, |
| 261 | // the copy is implemented by calling src.WriteTo(dst). |
Rob Pike | 4d310f2 | 2009-11-01 20:59:49 -0800 | [diff] [blame] | 262 | func Copy(dst Writer, src Reader) (written int64, err os.Error) { |
Anschel Schaffer-Cohen | 84fc1e2 | 2010-12-31 10:37:55 +1100 | [diff] [blame] | 263 | // If the writer has a ReadFrom method, use it to do the copy. |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 264 | // Avoids an allocation and a copy. |
| 265 | if rt, ok := dst.(ReaderFrom); ok { |
| 266 | return rt.ReadFrom(src) |
| 267 | } |
Anschel Schaffer-Cohen | 84fc1e2 | 2010-12-31 10:37:55 +1100 | [diff] [blame] | 268 | // Similarly, if the reader has a WriteTo method, use it to do the copy. |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 269 | if wt, ok := src.(WriterTo); ok { |
| 270 | return wt.WriteTo(dst) |
| 271 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 272 | buf := make([]byte, 32*1024) |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 273 | for { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 274 | nr, er := src.Read(buf) |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 275 | if nr > 0 { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 276 | nw, ew := dst.Write(buf[0:nr]) |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 277 | if nw > 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 278 | written += int64(nw) |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 279 | } |
| 280 | if ew != nil { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 281 | err = ew |
| 282 | break |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 283 | } |
| 284 | if nr != nw { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 285 | err = ErrShortWrite |
| 286 | break |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 287 | } |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 288 | } |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 289 | if er == os.EOF { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 290 | break |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 291 | } |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 292 | if er != nil { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 293 | err = er |
| 294 | break |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 295 | } |
| 296 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 297 | return written, err |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 298 | } |
Russ Cox | be869ba | 2009-05-18 13:31:56 -0700 | [diff] [blame] | 299 | |
Russ Cox | 90dcd5f | 2009-08-26 16:23:54 -0700 | [diff] [blame] | 300 | // LimitReader returns a Reader that reads from r |
| 301 | // but stops with os.EOF after n bytes. |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 302 | func LimitReader(r Reader, n int64) Reader { return &limitedReader{r, n} } |
Russ Cox | be869ba | 2009-05-18 13:31:56 -0700 | [diff] [blame] | 303 | |
Russ Cox | 90dcd5f | 2009-08-26 16:23:54 -0700 | [diff] [blame] | 304 | type limitedReader struct { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 305 | r Reader |
| 306 | n int64 |
Russ Cox | 90dcd5f | 2009-08-26 16:23:54 -0700 | [diff] [blame] | 307 | } |
| 308 | |
| 309 | func (l *limitedReader) Read(p []byte) (n int, err os.Error) { |
| 310 | if l.n <= 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 311 | return 0, os.EOF |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 312 | } |
Russ Cox | 90dcd5f | 2009-08-26 16:23:54 -0700 | [diff] [blame] | 313 | if int64(len(p)) > l.n { |
Robert Griesemer | 3bb0032 | 2009-11-09 21:23:52 -0800 | [diff] [blame] | 314 | p = p[0:l.n] |
Russ Cox | be869ba | 2009-05-18 13:31:56 -0700 | [diff] [blame] | 315 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 316 | n, err = l.r.Read(p) |
| 317 | l.n -= int64(n) |
| 318 | return |
Russ Cox | be869ba | 2009-05-18 13:31:56 -0700 | [diff] [blame] | 319 | } |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 320 | |
| 321 | // NewSectionReader returns a SectionReader that reads from r |
| 322 | // starting at offset off and stops with os.EOF after n bytes. |
| 323 | func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader { |
Robert Griesemer | 3bb0032 | 2009-11-09 21:23:52 -0800 | [diff] [blame] | 324 | return &SectionReader{r, off, off, off + n} |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 325 | } |
| 326 | |
| 327 | // SectionReader implements Read, Seek, and ReadAt on a section |
| 328 | // of an underlying ReaderAt. |
| 329 | type SectionReader struct { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 330 | r ReaderAt |
| 331 | base int64 |
| 332 | off int64 |
| 333 | limit int64 |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 334 | } |
| 335 | |
| 336 | func (s *SectionReader) Read(p []byte) (n int, err os.Error) { |
| 337 | if s.off >= s.limit { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 338 | return 0, os.EOF |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 339 | } |
| 340 | if max := s.limit - s.off; int64(len(p)) > max { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 341 | p = p[0:max] |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 342 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 343 | n, err = s.r.ReadAt(p, s.off) |
| 344 | s.off += int64(n) |
| 345 | return |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 346 | } |
| 347 | |
| 348 | func (s *SectionReader) Seek(offset int64, whence int) (ret int64, err os.Error) { |
| 349 | switch whence { |
| 350 | default: |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 351 | return 0, os.EINVAL |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 352 | case 0: |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 353 | offset += s.base |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 354 | case 1: |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 355 | offset += s.off |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 356 | case 2: |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 357 | offset += s.limit |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 358 | } |
Peter Mundy | 56b3e5d | 2010-07-08 16:57:07 +1000 | [diff] [blame] | 359 | if offset < s.base || offset > s.limit { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 360 | return 0, os.EINVAL |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 361 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 362 | s.off = offset |
| 363 | return offset - s.base, nil |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 364 | } |
| 365 | |
| 366 | func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err os.Error) { |
Robert Griesemer | 3bb0032 | 2009-11-09 21:23:52 -0800 | [diff] [blame] | 367 | if off < 0 || off >= s.limit-s.base { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 368 | return 0, os.EOF |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 369 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 370 | off += s.base |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 371 | if max := s.limit - off; int64(len(p)) > max { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 372 | p = p[0:max] |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 373 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 374 | return s.r.ReadAt(p, off) |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 375 | } |
| 376 | |
Russ Cox | f277ebf | 2009-09-01 16:11:17 -0700 | [diff] [blame] | 377 | // Size returns the size of the section in bytes. |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 378 | func (s *SectionReader) Size() int64 { return s.limit - s.base } |