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 ( |
| 13 | "os"; |
| 14 | "syscall"; |
| 15 | ) |
| 16 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame^] | 17 | // ErrEOF is the error returned by Readn and Copyn when they encounter EOF. |
Russ Cox | 839a684 | 2009-01-20 14:40:40 -0800 | [diff] [blame] | 18 | var ErrEOF = os.NewError("EOF") |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 19 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame^] | 20 | // Read is the interface that wraps the basic Read method. |
Russ Cox | 839a684 | 2009-01-20 14:40:40 -0800 | [diff] [blame] | 21 | type Read interface { |
Russ Cox | d47d888 | 2008-12-18 22:37:22 -0800 | [diff] [blame] | 22 | Read(p []byte) (n int, err *os.Error); |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 23 | } |
| 24 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame^] | 25 | // Write is the interface that wraps the basic Write method. |
Russ Cox | 839a684 | 2009-01-20 14:40:40 -0800 | [diff] [blame] | 26 | type Write interface { |
Russ Cox | d47d888 | 2008-12-18 22:37:22 -0800 | [diff] [blame] | 27 | Write(p []byte) (n int, err *os.Error); |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 28 | } |
| 29 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame^] | 30 | // Close is the interface that wraps the basic Close method. |
Russ Cox | 78906c3 | 2009-02-16 16:32:30 -0800 | [diff] [blame] | 31 | type Close interface { |
| 32 | Close() *os.Error; |
| 33 | } |
| 34 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame^] | 35 | // ReadWrite is the interface that groups the basic Read and Write methods. |
Russ Cox | 839a684 | 2009-01-20 14:40:40 -0800 | [diff] [blame] | 36 | type ReadWrite interface { |
Russ Cox | dfad8ea | 2009-02-16 16:37:49 -0800 | [diff] [blame] | 37 | Read; |
| 38 | Write; |
Russ Cox | 9350ef4 | 2008-09-17 13:49:23 -0700 | [diff] [blame] | 39 | } |
| 40 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame^] | 41 | // ReadClose is the interface that groups the basic Read and Close methods. |
Russ Cox | 78906c3 | 2009-02-16 16:32:30 -0800 | [diff] [blame] | 42 | type ReadClose interface { |
Russ Cox | dfad8ea | 2009-02-16 16:37:49 -0800 | [diff] [blame] | 43 | Read; |
| 44 | Close; |
Russ Cox | 78906c3 | 2009-02-16 16:32:30 -0800 | [diff] [blame] | 45 | } |
| 46 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame^] | 47 | // WriteClose is the interface that groups the basic Write and Close methods. |
Russ Cox | 78906c3 | 2009-02-16 16:32:30 -0800 | [diff] [blame] | 48 | type WriteClose interface { |
Russ Cox | dfad8ea | 2009-02-16 16:37:49 -0800 | [diff] [blame] | 49 | Write; |
| 50 | Close; |
Russ Cox | 7c7a525 | 2008-10-20 12:37:07 -0700 | [diff] [blame] | 51 | } |
| 52 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame^] | 53 | // ReadWriteClose is the interface that groups the basic Read, Write and Close methods. |
Russ Cox | 78906c3 | 2009-02-16 16:32:30 -0800 | [diff] [blame] | 54 | type ReadWriteClose interface { |
Russ Cox | dfad8ea | 2009-02-16 16:37:49 -0800 | [diff] [blame] | 55 | Read; |
| 56 | Write; |
| 57 | Close; |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 58 | } |
| 59 | |
Rob Pike | 704bc9d | 2009-02-06 17:54:26 -0800 | [diff] [blame] | 60 | // Convert a string to an array of bytes for easy marshaling. |
Rob Pike | 704bc9d | 2009-02-06 17:54:26 -0800 | [diff] [blame] | 61 | func StringBytes(s string) []byte { |
| 62 | b := make([]byte, len(s)); |
| 63 | for i := 0; i < len(s); i++ { |
| 64 | b[i] = s[i]; |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 65 | } |
Rob Pike | 704bc9d | 2009-02-06 17:54:26 -0800 | [diff] [blame] | 66 | return b; |
| 67 | } |
| 68 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame^] | 69 | // WriteString writes the contents of the string s to w, which accepts an array of bytes. |
Rob Pike | 704bc9d | 2009-02-06 17:54:26 -0800 | [diff] [blame] | 70 | func WriteString(w Write, s string) (n int, err *os.Error) { |
| 71 | return w.Write(StringBytes(s)) |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 72 | } |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 73 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame^] | 74 | // Readn reads r until the buffer buf is full, or until EOF or error. |
Russ Cox | e9b4058 | 2009-03-02 16:12:04 -0800 | [diff] [blame] | 75 | func Readn(r Read, buf []byte) (n int, err *os.Error) { |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 76 | n = 0; |
| 77 | for n < len(buf) { |
Russ Cox | e9b4058 | 2009-03-02 16:12:04 -0800 | [diff] [blame] | 78 | nn, e := r.Read(buf[n:len(buf)]); |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 79 | if nn > 0 { |
| 80 | n += nn |
| 81 | } |
| 82 | if e != nil { |
| 83 | return n, e |
| 84 | } |
| 85 | if nn <= 0 { |
| 86 | return n, ErrEOF // no error but insufficient data |
| 87 | } |
| 88 | } |
| 89 | return n, nil |
| 90 | } |
| 91 | |
| 92 | // Convert something that implements Read into something |
| 93 | // whose Reads are always Readn |
Russ Cox | 78906c3 | 2009-02-16 16:32:30 -0800 | [diff] [blame] | 94 | type fullRead struct { |
Russ Cox | e9b4058 | 2009-03-02 16:12:04 -0800 | [diff] [blame] | 95 | r Read; |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 96 | } |
| 97 | |
Russ Cox | e9b4058 | 2009-03-02 16:12:04 -0800 | [diff] [blame] | 98 | func (fr *fullRead) Read(p []byte) (n int, err *os.Error) { |
| 99 | n, err = Readn(fr.r, p); |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 100 | return n, err |
| 101 | } |
| 102 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame^] | 103 | // MakeFullReader takes r, an implementation of Read, and returns an object |
| 104 | // that still implements Read but always calls Readn underneath. |
Russ Cox | e9b4058 | 2009-03-02 16:12:04 -0800 | [diff] [blame] | 105 | func MakeFullReader(r Read) Read { |
| 106 | if fr, ok := r.(*fullRead); ok { |
Russ Cox | 78906c3 | 2009-02-16 16:32:30 -0800 | [diff] [blame] | 107 | // already a fullRead |
Russ Cox | e9b4058 | 2009-03-02 16:12:04 -0800 | [diff] [blame] | 108 | return r |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 109 | } |
Russ Cox | be2edb5 | 2009-03-03 08:39:12 -0800 | [diff] [blame] | 110 | return &fullRead{r} |
Rob Pike | 6ee7fe5 | 2008-11-11 17:28:36 -0800 | [diff] [blame] | 111 | } |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 112 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame^] | 113 | // Copy n copies n bytes (or until EOF is reached) from src to dst. |
| 114 | // It returns the number of bytes copied and the error, if any. |
Russ Cox | 839a684 | 2009-01-20 14:40:40 -0800 | [diff] [blame] | 115 | func Copyn(src Read, dst Write, n int64) (written int64, err *os.Error) { |
Russ Cox | 5564504 | 2009-01-06 15:19:02 -0800 | [diff] [blame] | 116 | buf := make([]byte, 32*1024); |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 117 | for written < n { |
Robert Griesemer | 60ee27d | 2008-11-19 10:20:52 -0800 | [diff] [blame] | 118 | l := len(buf); |
| 119 | if d := n - written; d < int64(l) { |
| 120 | l = int(d); |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 121 | } |
| 122 | nr, er := src.Read(buf[0 : l]); |
| 123 | if nr > 0 { |
| 124 | nw, ew := dst.Write(buf[0 : nr]); |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 125 | if nw > 0 { |
| 126 | written += int64(nw); |
| 127 | } |
| 128 | if ew != nil { |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 129 | err = ew; |
| 130 | break; |
| 131 | } |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 132 | if nr != nw { |
| 133 | err = os.EIO; |
| 134 | break; |
| 135 | } |
| 136 | } |
| 137 | if er != nil { |
| 138 | err = er; |
| 139 | break; |
| 140 | } |
| 141 | if nr == 0 { |
| 142 | err = ErrEOF; |
| 143 | break; |
| 144 | } |
| 145 | } |
| 146 | return written, err |
| 147 | } |
| 148 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame^] | 149 | // Copy copies from src to dst until EOF is reached. |
| 150 | // It returns the number of bytes copied and the error, if any. |
Russ Cox | 839a684 | 2009-01-20 14:40:40 -0800 | [diff] [blame] | 151 | func Copy(src Read, dst Write) (written int64, err *os.Error) { |
Russ Cox | 5564504 | 2009-01-06 15:19:02 -0800 | [diff] [blame] | 152 | buf := make([]byte, 32*1024); |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 153 | for { |
| 154 | nr, er := src.Read(buf); |
| 155 | if nr > 0 { |
| 156 | nw, ew := dst.Write(buf[0:nr]); |
| 157 | if nw > 0 { |
| 158 | written += int64(nw); |
| 159 | } |
| 160 | if ew != nil { |
| 161 | err = ew; |
| 162 | break; |
| 163 | } |
| 164 | if nr != nw { |
| 165 | err = os.EIO; |
| 166 | break; |
| 167 | } |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 168 | } |
| 169 | if er != nil { |
| 170 | err = er; |
| 171 | break; |
| 172 | } |
| 173 | if nr == 0 { |
| 174 | break; |
| 175 | } |
| 176 | } |
Russ Cox | 9dc4b1c | 2008-11-18 18:45:51 -0800 | [diff] [blame] | 177 | return written, err |
Robert Griesemer | 79d94d5 | 2008-11-18 18:08:05 -0800 | [diff] [blame] | 178 | } |