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 |
| 8 | // abstract the functionality. |
| 9 | // It also provides buffering primitives and some other basic operations. |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 10 | package io |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 11 | |
| 12 | import ( |
Rob Pike | 424f4f0 | 2009-06-04 15:28:09 -0700 | [diff] [blame] | 13 | "bytes"; |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 14 | "os"; |
Russ Cox | d3a412a | 2009-06-29 15:24:23 -0700 | [diff] [blame] | 15 | "strings"; |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 16 | ) |
| 17 | |
Russ Cox | 3b36acc | 2009-05-18 11:47:35 -0700 | [diff] [blame] | 18 | // Error represents an unexpected I/O behavior. |
Russ Cox | 1b301ba | 2009-05-08 14:40:20 -0700 | [diff] [blame] | 19 | type Error struct { |
| 20 | os.ErrorString |
| 21 | } |
Russ Cox | 3b36acc | 2009-05-18 11:47:35 -0700 | [diff] [blame] | 22 | |
Russ Cox | 3b36acc | 2009-05-18 11:47:35 -0700 | [diff] [blame] | 23 | // ErrShortWrite means that a write accepted fewer bytes than requested |
| 24 | // but failed to return an explicit error. |
| 25 | var ErrShortWrite os.Error = &Error{"short write"} |
| 26 | |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 27 | // ErrUnexpectedEOF means that os.EOF was encountered in the |
| 28 | // middle of reading a fixed-size block or data structure. |
| 29 | var ErrUnexpectedEOF os.Error = &Error{"unexpected EOF"} |
Russ Cox | 3b36acc | 2009-05-18 11:47:35 -0700 | [diff] [blame] | 30 | |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 31 | // Reader is the interface that wraps the basic Read method. |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 32 | // |
| 33 | // 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] | 34 | // read (0 <= n <= len(p)) and any error encountered. |
| 35 | // Even if Read returns n < len(p), |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 36 | // it may use all of p as scratch space during the call. |
| 37 | // If some data is available but not len(p) bytes, Read conventionally |
| 38 | // returns what is available rather than block waiting for more. |
| 39 | // |
| 40 | // At the end of the input stream, Read returns 0, os.EOF. |
| 41 | // Read may return a non-zero number of bytes with a non-nil err. |
| 42 | // 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] | 43 | type Reader interface { |
Rob Pike | aaf63f8 | 2009-04-17 00:08:24 -0700 | [diff] [blame] | 44 | Read(p []byte) (n int, err os.Error); |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 45 | } |
| 46 | |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 47 | // Writer is the interface that wraps the basic Write method. |
Russ Cox | 71f19d6 | 2009-06-22 14:44:07 -0700 | [diff] [blame] | 48 | // |
| 49 | // Write writes len(p) bytes from p to the underlying data stream. |
| 50 | // It returns the number of bytes written from p (0 <= n <= len(p)) |
| 51 | // and any error encountered that caused the write to stop early. |
| 52 | // 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] | 53 | type Writer interface { |
Rob Pike | aaf63f8 | 2009-04-17 00:08:24 -0700 | [diff] [blame] | 54 | Write(p []byte) (n int, err os.Error); |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 55 | } |
| 56 | |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 57 | // Closer is the interface that wraps the basic Close method. |
| 58 | type Closer interface { |
Rob Pike | aaf63f8 | 2009-04-17 00:08:24 -0700 | [diff] [blame] | 59 | Close() os.Error; |
Russ Cox | 78906c3 | 2009-02-16 16:32:30 -0800 | [diff] [blame] | 60 | } |
| 61 | |
Austin Clements | b3062f1 | 2009-08-18 17:47:03 -0700 | [diff] [blame] | 62 | // Seeker is the interface that wraps the basic Seek method. |
| 63 | // |
| 64 | // Seek sets the offset for the next Read or Write to offset, |
| 65 | // interpreted according to whence: 0 means relative to the origin of |
| 66 | // the file, 1 means relative to the current offset, and 2 means |
| 67 | // relative to the end. Seek returns the new offset and an Error, if |
| 68 | // any. |
| 69 | type Seeker interface { |
| 70 | Seek(offset int64, whence int) (ret int64, err os.Error); |
| 71 | } |
| 72 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame] | 73 | // ReadWrite is the interface that groups the basic Read and Write methods. |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 74 | type ReadWriter interface { |
| 75 | Reader; |
| 76 | Writer; |
Russ Cox | 9350ef4 | 2008-09-17 13:49:23 -0700 | [diff] [blame] | 77 | } |
| 78 | |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 79 | // ReadCloser is the interface that groups the basic Read and Close methods. |
| 80 | type ReadCloser interface { |
| 81 | Reader; |
| 82 | Closer; |
Russ Cox | 78906c3 | 2009-02-16 16:32:30 -0800 | [diff] [blame] | 83 | } |
| 84 | |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 85 | // WriteCloser is the interface that groups the basic Write and Close methods. |
| 86 | type WriteCloser interface { |
| 87 | Writer; |
| 88 | Closer; |
Russ Cox | 7c7a525 | 2008-10-20 12:37:07 -0700 | [diff] [blame] | 89 | } |
| 90 | |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 91 | // ReadWriteCloser is the interface that groups the basic Read, Write and Close methods. |
| 92 | type ReadWriteCloser interface { |
| 93 | Reader; |
| 94 | Writer; |
| 95 | Closer; |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 96 | } |
| 97 | |
Austin Clements | b3062f1 | 2009-08-18 17:47:03 -0700 | [diff] [blame] | 98 | // ReadSeeker is the interface that groups the basic Read and Seek methods. |
| 99 | type ReadSeeker interface { |
| 100 | Reader; |
| 101 | Seeker; |
| 102 | } |
| 103 | |
| 104 | // WriteSeeker is the interface that groups the basic Write and Seek methods. |
| 105 | type WriteSeeker interface { |
| 106 | Writer; |
| 107 | Seeker; |
| 108 | } |
| 109 | |
| 110 | // ReadWriteSeeker is the interface that groups the basic Read, Write and Seek methods. |
| 111 | type ReadWriteSeeker interface { |
| 112 | Reader; |
| 113 | Writer; |
| 114 | Seeker; |
| 115 | } |
| 116 | |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 117 | // ReaderAt is the interface that wraps the basic ReadAt method. |
| 118 | // |
| 119 | // ReadAt reads len(p) bytes into p starting at offset off in the |
| 120 | // underlying data stream. It returns the number of bytes |
| 121 | // read (0 <= n <= len(p)) and any error encountered. |
| 122 | // |
| 123 | // Even if ReadAt returns n < len(p), |
| 124 | // it may use all of p as scratch space during the call. |
| 125 | // If some data is available but not len(p) bytes, ReadAt blocks |
| 126 | // until either all the data is available or an error occurs. |
| 127 | // |
| 128 | // At the end of the input stream, ReadAt returns 0, os.EOF. |
| 129 | // ReadAt may return a non-zero number of bytes with a non-nil err. |
| 130 | // In particular, a ReadAt that exhausts the input may return n > 0, os.EOF. |
| 131 | type ReaderAt interface { |
| 132 | ReadAt(p []byte, off int64) (n int, err os.Error); |
| 133 | } |
| 134 | |
| 135 | // WriterAt is the interface that wraps the basic WriteAt method. |
| 136 | // |
| 137 | // WriteAt writes len(p) bytes from p to the underlying data stream |
| 138 | // at offset off. It returns the number of bytes written from p (0 <= n <= len(p)) |
| 139 | // and any error encountered that caused the write to stop early. |
| 140 | // WriteAt must return a non-nil error if it returns n < len(p). |
| 141 | type WriterAt interface { |
| 142 | WriteAt(p []byte, off int64) (n int, err os.Error); |
| 143 | } |
| 144 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame] | 145 | // 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] | 146 | func WriteString(w Writer, s string) (n int, err os.Error) { |
Russ Cox | d3a412a | 2009-06-29 15:24:23 -0700 | [diff] [blame] | 147 | return w.Write(strings.Bytes(s)) |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 148 | } |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 149 | |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 150 | // ReadAtLeast reads from r into buf until it has read at least min bytes. |
| 151 | // It returns the number of bytes copied and an error if fewer bytes were read. |
| 152 | // The error is os.EOF only if no bytes were read. |
| 153 | // If an EOF happens after reading fewer than min bytes, |
| 154 | // ReadAtLeast returns ErrUnexpectedEOF. |
Russ Cox | b0608c13 | 2009-05-19 14:01:03 -0700 | [diff] [blame] | 155 | func ReadAtLeast(r Reader, buf []byte, min int) (n int, err os.Error) { |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 156 | n = 0; |
Russ Cox | b0608c13 | 2009-05-19 14:01:03 -0700 | [diff] [blame] | 157 | for n < min { |
Russ Cox | e9b4058 | 2009-03-02 16:12:04 -0800 | [diff] [blame] | 158 | nn, e := r.Read(buf[n:len(buf)]); |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 159 | if nn > 0 { |
| 160 | n += nn |
| 161 | } |
| 162 | if e != nil { |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 163 | if e == os.EOF && n > 0 { |
| 164 | e = ErrUnexpectedEOF; |
| 165 | } |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 166 | return n, e |
| 167 | } |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 168 | } |
| 169 | return n, nil |
| 170 | } |
| 171 | |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 172 | // ReadFull reads exactly len(buf) bytes from r into buf. |
| 173 | // It returns the number of bytes copied and an error if fewer bytes were read. |
| 174 | // The error is os.EOF only if no bytes were read. |
| 175 | // If an EOF happens after reading some but not all the bytes, |
| 176 | // ReadFull returns ErrUnexpectedEOF. |
| 177 | func ReadFull(r Reader, buf []byte) (n int, err os.Error) { |
Russ Cox | 55e790a | 2009-07-01 07:32:04 -0700 | [diff] [blame] | 178 | return ReadAtLeast(r, buf, len(buf)); |
Russ Cox | b0608c13 | 2009-05-19 14:01:03 -0700 | [diff] [blame] | 179 | } |
| 180 | |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 181 | // Copyn copies n bytes (or until an error) from src to dst. |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame] | 182 | // It returns the number of bytes copied and the error, if any. |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 183 | func Copyn(src Reader, dst Writer, n int64) (written int64, err os.Error) { |
Russ Cox | 5564504 | 2009-01-06 15:19:02 -0800 | [diff] [blame] | 184 | buf := make([]byte, 32*1024); |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 185 | for written < n { |
Robert Griesemer | 60ee27d | 2008-11-19 10:20:52 -0800 | [diff] [blame] | 186 | l := len(buf); |
| 187 | if d := n - written; d < int64(l) { |
| 188 | l = int(d); |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 189 | } |
| 190 | nr, er := src.Read(buf[0 : l]); |
| 191 | if nr > 0 { |
| 192 | nw, ew := dst.Write(buf[0 : nr]); |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 193 | if nw > 0 { |
| 194 | written += int64(nw); |
| 195 | } |
| 196 | if ew != nil { |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 197 | err = ew; |
| 198 | break; |
| 199 | } |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 200 | if nr != nw { |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 201 | err = ErrShortWrite; |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 202 | break; |
| 203 | } |
| 204 | } |
| 205 | if er != nil { |
| 206 | err = er; |
| 207 | break; |
| 208 | } |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 209 | } |
| 210 | return written, err |
| 211 | } |
| 212 | |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 213 | // Copy copies from src to dst until either EOF is reached |
| 214 | // on src or an error occurs. It returns the number of bytes |
| 215 | // copied and the error, if any. |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 216 | func Copy(src Reader, dst Writer) (written int64, err os.Error) { |
Russ Cox | 5564504 | 2009-01-06 15:19:02 -0800 | [diff] [blame] | 217 | buf := make([]byte, 32*1024); |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 218 | for { |
| 219 | nr, er := src.Read(buf); |
| 220 | if nr > 0 { |
| 221 | nw, ew := dst.Write(buf[0:nr]); |
| 222 | if nw > 0 { |
| 223 | written += int64(nw); |
| 224 | } |
| 225 | if ew != nil { |
| 226 | err = ew; |
| 227 | break; |
| 228 | } |
| 229 | if nr != nw { |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 230 | err = ErrShortWrite; |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 231 | break; |
| 232 | } |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 233 | } |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 234 | if er == os.EOF { |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 235 | break; |
| 236 | } |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 237 | if er != nil { |
| 238 | err = er; |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 239 | break; |
| 240 | } |
| 241 | } |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 242 | return written, err |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 243 | } |
Russ Cox | be869ba | 2009-05-18 13:31:56 -0700 | [diff] [blame] | 244 | |
Russ Cox | 90dcd5f | 2009-08-26 16:23:54 -0700 | [diff] [blame] | 245 | // LimitReader returns a Reader that reads from r |
| 246 | // but stops with os.EOF after n bytes. |
| 247 | func LimitReader(r Reader, n int64) Reader { |
| 248 | return &limitedReader{r, n}; |
Russ Cox | be869ba | 2009-05-18 13:31:56 -0700 | [diff] [blame] | 249 | } |
| 250 | |
Russ Cox | 90dcd5f | 2009-08-26 16:23:54 -0700 | [diff] [blame] | 251 | type limitedReader struct { |
| 252 | r Reader; |
| 253 | n int64; |
| 254 | } |
| 255 | |
| 256 | func (l *limitedReader) Read(p []byte) (n int, err os.Error) { |
| 257 | if l.n <= 0 { |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 258 | return 0, os.EOF; |
| 259 | } |
Russ Cox | 90dcd5f | 2009-08-26 16:23:54 -0700 | [diff] [blame] | 260 | if int64(len(p)) > l.n { |
| 261 | p = p[0:l.n]; |
Russ Cox | be869ba | 2009-05-18 13:31:56 -0700 | [diff] [blame] | 262 | } |
Russ Cox | 90dcd5f | 2009-08-26 16:23:54 -0700 | [diff] [blame] | 263 | n, err = l.r.Read(p); |
| 264 | l.n -= int64(n); |
| 265 | return; |
Russ Cox | be869ba | 2009-05-18 13:31:56 -0700 | [diff] [blame] | 266 | } |
Russ Cox | e596297 | 2009-08-31 16:34:43 -0700 | [diff] [blame] | 267 | |
| 268 | // NewSectionReader returns a SectionReader that reads from r |
| 269 | // starting at offset off and stops with os.EOF after n bytes. |
| 270 | func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader { |
| 271 | return &SectionReader{r, off, off, off+n}; |
| 272 | } |
| 273 | |
| 274 | // SectionReader implements Read, Seek, and ReadAt on a section |
| 275 | // of an underlying ReaderAt. |
| 276 | type SectionReader struct { |
| 277 | r ReaderAt; |
| 278 | base int64; |
| 279 | off int64; |
| 280 | limit int64; |
| 281 | } |
| 282 | |
| 283 | func (s *SectionReader) Read(p []byte) (n int, err os.Error) { |
| 284 | if s.off >= s.limit { |
| 285 | return 0, os.EOF; |
| 286 | } |
| 287 | if max := s.limit - s.off; int64(len(p)) > max { |
| 288 | p = p[0:max]; |
| 289 | } |
| 290 | n, err = s.r.ReadAt(p, s.off); |
| 291 | s.off += int64(n); |
| 292 | return; |
| 293 | } |
| 294 | |
| 295 | func (s *SectionReader) Seek(offset int64, whence int) (ret int64, err os.Error) { |
| 296 | switch whence { |
| 297 | default: |
| 298 | return 0, os.EINVAL |
| 299 | case 0: |
| 300 | offset += s.base |
| 301 | case 1: |
| 302 | offset += s.off |
| 303 | case 2: |
| 304 | offset += s.limit |
| 305 | } |
| 306 | if offset < s.off || offset > s.limit { |
| 307 | return 0, os.EINVAL |
| 308 | } |
| 309 | s.off = offset; |
| 310 | return offset - s.base, nil |
| 311 | } |
| 312 | |
| 313 | func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err os.Error) { |
| 314 | if off < 0 || off >= s.limit - s.base { |
| 315 | return 0, os.EOF; |
| 316 | } |
| 317 | off += s.base; |
| 318 | if max := s.limit - off; int64(len(p)) > max { |
| 319 | p = p[0:max]; |
| 320 | } |
| 321 | return s.r.ReadAt(p, off); |
| 322 | } |
| 323 | |
Russ Cox | f277ebf | 2009-09-01 16:11:17 -0700 | [diff] [blame^] | 324 | // Size returns the size of the section in bytes. |
| 325 | func (s *SectionReader) Size() int64 { |
| 326 | return s.limit - s.base |
| 327 | } |