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 | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 5 | // This package implements buffered I/O. It wraps an io.Reader or io.Writer |
| 6 | // object, creating another object (Reader or Writer) that also implements |
Rob Pike | 5dd4ef5 | 2009-03-07 16:57:01 -0800 | [diff] [blame] | 7 | // the interface but provides buffering and some help for textual I/O. |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 8 | package bufio |
Russ Cox | 387df5e | 2008-11-24 14:51:33 -0800 | [diff] [blame] | 9 | |
| 10 | import ( |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 11 | "bytes" |
| 12 | "io" |
| 13 | "os" |
| 14 | "strconv" |
| 15 | "utf8" |
Russ Cox | 387df5e | 2008-11-24 14:51:33 -0800 | [diff] [blame] | 16 | ) |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 17 | |
| 18 | |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 19 | const ( |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 20 | defaultBufSize = 4096 |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 21 | ) |
| 22 | |
Rob Pike | 5dd4ef5 | 2009-03-07 16:57:01 -0800 | [diff] [blame] | 23 | // Errors introduced by this package. |
Russ Cox | 1b301ba | 2009-05-08 14:40:20 -0700 | [diff] [blame] | 24 | type Error struct { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 25 | os.ErrorString |
Russ Cox | 1b301ba | 2009-05-08 14:40:20 -0700 | [diff] [blame] | 26 | } |
| 27 | |
Russ Cox | 839a684 | 2009-01-20 14:40:40 -0800 | [diff] [blame] | 28 | var ( |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 29 | ErrInvalidUnreadByte os.Error = &Error{"bufio: invalid use of UnreadByte"} |
Rob Pike | acb695f | 2010-09-12 17:40:27 +1000 | [diff] [blame] | 30 | ErrInvalidUnreadRune os.Error = &Error{"bufio: invalid use of UnreadRune"} |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 31 | ErrBufferFull os.Error = &Error{"bufio: buffer full"} |
Nigel Tao | 27e2490 | 2010-08-04 09:44:02 +1000 | [diff] [blame] | 32 | ErrNegativeCount os.Error = &Error{"bufio: negative count"} |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 33 | errInternal os.Error = &Error{"bufio: internal error"} |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 34 | ) |
| 35 | |
Russ Cox | a0bcaf4 | 2009-06-25 20:24:55 -0700 | [diff] [blame] | 36 | // BufSizeError is the error representing an invalid buffer size. |
| 37 | type BufSizeError int |
Russ Cox | 094f1d5 | 2009-10-08 15:14:54 -0700 | [diff] [blame] | 38 | |
Russ Cox | a0bcaf4 | 2009-06-25 20:24:55 -0700 | [diff] [blame] | 39 | func (b BufSizeError) String() string { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 40 | return "bufio: bad buffer size " + strconv.Itoa(int(b)) |
Russ Cox | a0bcaf4 | 2009-06-25 20:24:55 -0700 | [diff] [blame] | 41 | } |
| 42 | |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 43 | |
| 44 | // Buffered input. |
| 45 | |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 46 | // Reader implements buffering for an io.Reader object. |
| 47 | type Reader struct { |
Rob Pike | acb695f | 2010-09-12 17:40:27 +1000 | [diff] [blame] | 48 | buf []byte |
| 49 | rd io.Reader |
| 50 | r, w int |
| 51 | err os.Error |
| 52 | lastByte int |
| 53 | lastRuneSize int |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 54 | } |
| 55 | |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 56 | // NewReaderSize creates a new Reader whose buffer has the specified size, |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 57 | // which must be greater than zero. If the argument io.Reader is already a |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 58 | // Reader with large enough size, it returns the underlying Reader. |
| 59 | // It returns the Reader and any error. |
| 60 | func NewReaderSize(rd io.Reader, size int) (*Reader, os.Error) { |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 61 | if size <= 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 62 | return nil, BufSizeError(size) |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 63 | } |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 64 | // Is it already a Reader? |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 65 | b, ok := rd.(*Reader) |
Rob Pike | ee19695 | 2009-04-06 21:42:14 -0700 | [diff] [blame] | 66 | if ok && len(b.buf) >= size { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 67 | return b, nil |
Rob Pike | ee19695 | 2009-04-06 21:42:14 -0700 | [diff] [blame] | 68 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 69 | b = new(Reader) |
| 70 | b.buf = make([]byte, size) |
| 71 | b.rd = rd |
Rob Pike | acb695f | 2010-09-12 17:40:27 +1000 | [diff] [blame] | 72 | b.lastByte = -1 |
| 73 | b.lastRuneSize = -1 |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 74 | return b, nil |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 75 | } |
| 76 | |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 77 | // NewReader returns a new Reader whose buffer has the default size. |
| 78 | func NewReader(rd io.Reader) *Reader { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 79 | b, err := NewReaderSize(rd, defaultBufSize) |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 80 | if err != nil { |
| 81 | // cannot happen - defaultBufSize is a valid size |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 82 | panic(err) |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 83 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 84 | return b |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 85 | } |
| 86 | |
Russ Cox | 29415d0 | 2009-08-26 16:23:34 -0700 | [diff] [blame] | 87 | // fill reads a new chunk into the buffer. |
| 88 | func (b *Reader) fill() { |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 89 | // Slide existing data to beginning. |
Nigel Tao | 27e2490 | 2010-08-04 09:44:02 +1000 | [diff] [blame] | 90 | if b.r > 0 { |
| 91 | copy(b.buf, b.buf[b.r:b.w]) |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 92 | b.w -= b.r |
Nigel Tao | 27e2490 | 2010-08-04 09:44:02 +1000 | [diff] [blame] | 93 | b.r = 0 |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 94 | } |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 95 | |
| 96 | // Read new data. |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 97 | n, e := b.rd.Read(b.buf[b.w:]) |
| 98 | b.w += n |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 99 | if e != nil { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 100 | b.err = e |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 101 | } |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 102 | } |
| 103 | |
Nigel Tao | 27e2490 | 2010-08-04 09:44:02 +1000 | [diff] [blame] | 104 | // Peek returns the next n bytes without advancing the reader. The bytes stop |
| 105 | // being valid at the next read call. If Peek returns fewer than n bytes, it |
| 106 | // also returns an error explaining why the read is short. The error is |
| 107 | // ErrBufferFull if n is larger than b's buffer size. |
| 108 | func (b *Reader) Peek(n int) ([]byte, os.Error) { |
| 109 | if n < 0 { |
| 110 | return nil, ErrNegativeCount |
| 111 | } |
| 112 | if n > len(b.buf) { |
| 113 | return nil, ErrBufferFull |
| 114 | } |
| 115 | for b.w-b.r < n && b.err == nil { |
| 116 | b.fill() |
| 117 | } |
| 118 | m := b.w - b.r |
| 119 | if m > n { |
| 120 | m = n |
| 121 | } |
| 122 | err := b.err |
| 123 | if m < n && err == nil { |
| 124 | err = ErrBufferFull |
| 125 | } |
| 126 | return b.buf[b.r : b.r+m], err |
| 127 | } |
| 128 | |
Russ Cox | ca2fe5d | 2009-05-22 22:43:57 -0700 | [diff] [blame] | 129 | // Read reads data into p. |
| 130 | // It returns the number of bytes read into p. |
Roger Peppe | 24a78a0 | 2010-12-07 14:54:15 -0500 | [diff] [blame] | 131 | // It calls Read at most once on the underlying Reader, |
| 132 | // hence n may be less than len(p). |
| 133 | // At EOF, the count will be zero and err will be os.EOF. |
| 134 | func (b *Reader) Read(p []byte) (n int, err os.Error) { |
| 135 | n = len(p) |
| 136 | if n == 0 { |
| 137 | return 0, b.err |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 138 | } |
Roger Peppe | 24a78a0 | 2010-12-07 14:54:15 -0500 | [diff] [blame] | 139 | if b.w == b.r { |
| 140 | if b.err != nil { |
| 141 | return 0, b.err |
| 142 | } |
| 143 | if len(p) >= len(b.buf) { |
| 144 | // Large read, empty buffer. |
| 145 | // Read directly into p to avoid copy. |
| 146 | n, b.err = b.rd.Read(p) |
| 147 | if n > 0 { |
| 148 | b.lastByte = int(p[n-1]) |
| 149 | b.lastRuneSize = -1 |
| 150 | } |
Roger Peppe | 24a78a0 | 2010-12-07 14:54:15 -0500 | [diff] [blame] | 151 | return n, b.err |
| 152 | } |
| 153 | b.fill() |
| 154 | if b.w == b.r { |
| 155 | return 0, b.err |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | if n > b.w-b.r { |
| 160 | n = b.w - b.r |
| 161 | } |
| 162 | copy(p[0:n], b.buf[b.r:]) |
Roger Peppe | 24a78a0 | 2010-12-07 14:54:15 -0500 | [diff] [blame] | 163 | b.r += n |
| 164 | b.lastByte = int(b.buf[b.r-1]) |
| 165 | b.lastRuneSize = -1 |
| 166 | return n, nil |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 167 | } |
| 168 | |
Rob Pike | 5dd4ef5 | 2009-03-07 16:57:01 -0800 | [diff] [blame] | 169 | // ReadByte reads and returns a single byte. |
| 170 | // If no byte is available, returns an error. |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 171 | func (b *Reader) ReadByte() (c byte, err os.Error) { |
Rob Pike | acb695f | 2010-09-12 17:40:27 +1000 | [diff] [blame] | 172 | b.lastRuneSize = -1 |
Russ Cox | 29415d0 | 2009-08-26 16:23:34 -0700 | [diff] [blame] | 173 | for b.w == b.r { |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 174 | if b.err != nil { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 175 | return 0, b.err |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 176 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 177 | b.fill() |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 178 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 179 | c = b.buf[b.r] |
| 180 | b.r++ |
Rob Pike | acb695f | 2010-09-12 17:40:27 +1000 | [diff] [blame] | 181 | b.lastByte = int(c) |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 182 | return c, nil |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 183 | } |
| 184 | |
Russ Cox | a0bcaf4 | 2009-06-25 20:24:55 -0700 | [diff] [blame] | 185 | // UnreadByte unreads the last byte. Only the most recently read byte can be unread. |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 186 | func (b *Reader) UnreadByte() os.Error { |
Rob Pike | acb695f | 2010-09-12 17:40:27 +1000 | [diff] [blame] | 187 | b.lastRuneSize = -1 |
| 188 | if b.r == b.w && b.lastByte >= 0 { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 189 | b.w = 1 |
| 190 | b.r = 0 |
Rob Pike | acb695f | 2010-09-12 17:40:27 +1000 | [diff] [blame] | 191 | b.buf[0] = byte(b.lastByte) |
| 192 | b.lastByte = -1 |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 193 | return nil |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 194 | } |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 195 | if b.r <= 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 196 | return ErrInvalidUnreadByte |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 197 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 198 | b.r-- |
Rob Pike | acb695f | 2010-09-12 17:40:27 +1000 | [diff] [blame] | 199 | b.lastByte = -1 |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 200 | return nil |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 201 | } |
| 202 | |
Rob Pike | 5dd4ef5 | 2009-03-07 16:57:01 -0800 | [diff] [blame] | 203 | // ReadRune reads a single UTF-8 encoded Unicode character and returns the |
| 204 | // rune and its size in bytes. |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 205 | func (b *Reader) ReadRune() (rune int, size int, err os.Error) { |
Robert Griesemer | 1698934 | 2009-11-09 21:09:34 -0800 | [diff] [blame] | 206 | for b.r+utf8.UTFMax > b.w && !utf8.FullRune(b.buf[b.r:b.w]) && b.err == nil { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 207 | b.fill() |
Russ Cox | 29415d0 | 2009-08-26 16:23:34 -0700 | [diff] [blame] | 208 | } |
Rob Pike | e439345 | 2010-09-24 12:28:14 +1000 | [diff] [blame] | 209 | b.lastRuneSize = -1 |
Russ Cox | 29415d0 | 2009-08-26 16:23:34 -0700 | [diff] [blame] | 210 | if b.r == b.w { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 211 | return 0, 0, b.err |
Russ Cox | 387df5e | 2008-11-24 14:51:33 -0800 | [diff] [blame] | 212 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 213 | rune, size = int(b.buf[b.r]), 1 |
Russ Cox | 387df5e | 2008-11-24 14:51:33 -0800 | [diff] [blame] | 214 | if rune >= 0x80 { |
Robert Griesemer | 1698934 | 2009-11-09 21:09:34 -0800 | [diff] [blame] | 215 | rune, size = utf8.DecodeRune(b.buf[b.r:b.w]) |
Russ Cox | 387df5e | 2008-11-24 14:51:33 -0800 | [diff] [blame] | 216 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 217 | b.r += size |
Rob Pike | acb695f | 2010-09-12 17:40:27 +1000 | [diff] [blame] | 218 | b.lastByte = int(b.buf[b.r-1]) |
| 219 | b.lastRuneSize = size |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 220 | return rune, size, nil |
Russ Cox | 387df5e | 2008-11-24 14:51:33 -0800 | [diff] [blame] | 221 | } |
| 222 | |
Rob Pike | acb695f | 2010-09-12 17:40:27 +1000 | [diff] [blame] | 223 | // UnreadRune unreads the last rune. If the most recent read operation on |
| 224 | // the buffer was not a ReadRune, UnreadRune returns an error. (In this |
| 225 | // regard it is stricter than UnreadByte, which will unread the last byte |
| 226 | // from any read operation.) |
| 227 | func (b *Reader) UnreadRune() os.Error { |
Rob Pike | 52e3c99 | 2010-10-13 17:12:43 -0700 | [diff] [blame] | 228 | if b.lastRuneSize < 0 || b.r == 0 { |
Rob Pike | acb695f | 2010-09-12 17:40:27 +1000 | [diff] [blame] | 229 | return ErrInvalidUnreadRune |
| 230 | } |
| 231 | b.r -= b.lastRuneSize |
| 232 | b.lastByte = -1 |
| 233 | b.lastRuneSize = -1 |
| 234 | return nil |
| 235 | } |
| 236 | |
Rob Pike | 5dd4ef5 | 2009-03-07 16:57:01 -0800 | [diff] [blame] | 237 | // Buffered returns the number of bytes that can be read from the current buffer. |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 238 | func (b *Reader) Buffered() int { return b.w - b.r } |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 239 | |
Russ Cox | 4b40928 | 2009-08-27 11:20:15 -0700 | [diff] [blame] | 240 | // ReadSlice reads until the first occurrence of delim in the input, |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 241 | // returning a slice pointing at the bytes in the buffer. |
| 242 | // The bytes stop being valid at the next read call. |
Russ Cox | 4b40928 | 2009-08-27 11:20:15 -0700 | [diff] [blame] | 243 | // If ReadSlice encounters an error before finding a delimiter, |
| 244 | // it returns all the data in the buffer and the error itself (often os.EOF). |
| 245 | // ReadSlice fails with error ErrBufferFull if the buffer fills without a delim. |
| 246 | // Because the data returned from ReadSlice will be overwritten |
| 247 | // by the next I/O operation, most clients should use |
| 248 | // ReadBytes or ReadString instead. |
| 249 | // ReadSlice returns err != nil if and only if line does not end in delim. |
| 250 | func (b *Reader) ReadSlice(delim byte) (line []byte, err os.Error) { |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 251 | // Look in buffer. |
Rob Pike | 02df7db | 2009-11-18 19:58:32 -0800 | [diff] [blame] | 252 | if i := bytes.IndexByte(b.buf[b.r:b.w], delim); i >= 0 { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 253 | line1 := b.buf[b.r : b.r+i+1] |
| 254 | b.r += i + 1 |
| 255 | return line1, nil |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 256 | } |
Russ Cox | 983f06b | 2008-10-07 12:31:31 -0700 | [diff] [blame] | 257 | |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 258 | // Read more into buffer, until buffer fills or we find delim. |
| 259 | for { |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 260 | if b.err != nil { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 261 | line := b.buf[b.r:b.w] |
| 262 | b.r = b.w |
| 263 | return line, b.err |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 264 | } |
Russ Cox | 983f06b | 2008-10-07 12:31:31 -0700 | [diff] [blame] | 265 | |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 266 | n := b.Buffered() |
| 267 | b.fill() |
Russ Cox | 29415d0 | 2009-08-26 16:23:34 -0700 | [diff] [blame] | 268 | |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 269 | // Search new part of buffer |
Rob Pike | 02df7db | 2009-11-18 19:58:32 -0800 | [diff] [blame] | 270 | if i := bytes.IndexByte(b.buf[n:b.w], delim); i >= 0 { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 271 | line := b.buf[0 : n+i+1] |
| 272 | b.r = n + i + 1 |
| 273 | return line, nil |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 274 | } |
Russ Cox | 983f06b | 2008-10-07 12:31:31 -0700 | [diff] [blame] | 275 | |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 276 | // Buffer is full? |
| 277 | if b.Buffered() >= len(b.buf) { |
Russ Cox | 041d978 | 2010-06-02 16:17:18 -0700 | [diff] [blame] | 278 | b.r = b.w |
| 279 | return b.buf, ErrBufferFull |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 280 | } |
| 281 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 282 | panic("not reached") |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 283 | } |
| 284 | |
Russ Cox | 4b40928 | 2009-08-27 11:20:15 -0700 | [diff] [blame] | 285 | // ReadBytes reads until the first occurrence of delim in the input, |
Stephen Ma | 5043f0a | 2010-10-06 19:39:30 +1100 | [diff] [blame] | 286 | // returning a slice containing the data up to and including the delimiter. |
Russ Cox | 4b40928 | 2009-08-27 11:20:15 -0700 | [diff] [blame] | 287 | // If ReadBytes encounters an error before finding a delimiter, |
| 288 | // it returns the data read before the error and the error itself (often os.EOF). |
| 289 | // ReadBytes returns err != nil if and only if line does not end in delim. |
| 290 | func (b *Reader) ReadBytes(delim byte) (line []byte, err os.Error) { |
| 291 | // Use ReadSlice to look for array, |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 292 | // accumulating full buffers. |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 293 | var frag []byte |
| 294 | var full [][]byte |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 295 | err = nil |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 296 | |
| 297 | for { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 298 | var e os.Error |
| 299 | frag, e = b.ReadSlice(delim) |
| 300 | if e == nil { // got final fragment |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 301 | break |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 302 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 303 | if e != ErrBufferFull { // unexpected error |
| 304 | err = e |
| 305 | break |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 306 | } |
Russ Cox | 983f06b | 2008-10-07 12:31:31 -0700 | [diff] [blame] | 307 | |
Russ Cox | 041d978 | 2010-06-02 16:17:18 -0700 | [diff] [blame] | 308 | // Make a copy of the buffer. |
| 309 | buf := make([]byte, len(frag)) |
| 310 | copy(buf, frag) |
Russ Cox | 69c4e93 | 2010-10-27 19:47:23 -0700 | [diff] [blame] | 311 | full = append(full, buf) |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 312 | } |
Russ Cox | 983f06b | 2008-10-07 12:31:31 -0700 | [diff] [blame] | 313 | |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 314 | // Allocate new buffer to hold the full pieces and the fragment. |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 315 | n := 0 |
Russ Cox | 69c4e93 | 2010-10-27 19:47:23 -0700 | [diff] [blame] | 316 | for i := range full { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 317 | n += len(full[i]) |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 318 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 319 | n += len(frag) |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 320 | |
| 321 | // Copy full pieces and fragment in. |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 322 | buf := make([]byte, n) |
| 323 | n = 0 |
Russ Cox | 69c4e93 | 2010-10-27 19:47:23 -0700 | [diff] [blame] | 324 | for i := range full { |
| 325 | n += copy(buf[n:], full[i]) |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 326 | } |
Nigel Tao | 27e2490 | 2010-08-04 09:44:02 +1000 | [diff] [blame] | 327 | copy(buf[n:], frag) |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 328 | return buf, err |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 329 | } |
| 330 | |
Russ Cox | 4b40928 | 2009-08-27 11:20:15 -0700 | [diff] [blame] | 331 | // ReadString reads until the first occurrence of delim in the input, |
| 332 | // returning a string containing the data up to and including the delimiter. |
| 333 | // If ReadString encounters an error before finding a delimiter, |
| 334 | // it returns the data read before the error and the error itself (often os.EOF). |
| 335 | // ReadString returns err != nil if and only if line does not end in delim. |
| 336 | func (b *Reader) ReadString(delim byte) (line string, err os.Error) { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 337 | bytes, e := b.ReadBytes(delim) |
| 338 | return string(bytes), e |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 339 | } |
| 340 | |
| 341 | |
| 342 | // buffered output |
| 343 | |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 344 | // Writer implements buffering for an io.Writer object. |
| 345 | type Writer struct { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 346 | err os.Error |
| 347 | buf []byte |
| 348 | n int |
| 349 | wr io.Writer |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 350 | } |
| 351 | |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 352 | // NewWriterSize creates a new Writer whose buffer has the specified size, |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 353 | // which must be greater than zero. If the argument io.Writer is already a |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 354 | // Writer with large enough size, it returns the underlying Writer. |
| 355 | // It returns the Writer and any error. |
| 356 | func NewWriterSize(wr io.Writer, size int) (*Writer, os.Error) { |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 357 | if size <= 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 358 | return nil, BufSizeError(size) |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 359 | } |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 360 | // Is it already a Writer? |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 361 | b, ok := wr.(*Writer) |
Rob Pike | ee19695 | 2009-04-06 21:42:14 -0700 | [diff] [blame] | 362 | if ok && len(b.buf) >= size { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 363 | return b, nil |
Rob Pike | ee19695 | 2009-04-06 21:42:14 -0700 | [diff] [blame] | 364 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 365 | b = new(Writer) |
| 366 | b.buf = make([]byte, size) |
| 367 | b.wr = wr |
| 368 | return b, nil |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 369 | } |
| 370 | |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 371 | // NewWriter returns a new Writer whose buffer has the default size. |
| 372 | func NewWriter(wr io.Writer) *Writer { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 373 | b, err := NewWriterSize(wr, defaultBufSize) |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 374 | if err != nil { |
| 375 | // cannot happen - defaultBufSize is valid size |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 376 | panic(err) |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 377 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 378 | return b |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 379 | } |
| 380 | |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 381 | // Flush writes any buffered data to the underlying io.Writer. |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 382 | func (b *Writer) Flush() os.Error { |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 383 | if b.err != nil { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 384 | return b.err |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 385 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 386 | n, e := b.wr.Write(b.buf[0:b.n]) |
Russ Cox | be869ba | 2009-05-18 13:31:56 -0700 | [diff] [blame] | 387 | if n < b.n && e == nil { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 388 | e = io.ErrShortWrite |
Russ Cox | be869ba | 2009-05-18 13:31:56 -0700 | [diff] [blame] | 389 | } |
| 390 | if e != nil { |
| 391 | if n > 0 && n < b.n { |
Russ Cox | 132c42f | 2009-12-08 18:19:48 -0800 | [diff] [blame] | 392 | copy(b.buf[0:b.n-n], b.buf[n:b.n]) |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 393 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 394 | b.n -= n |
| 395 | b.err = e |
| 396 | return e |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 397 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 398 | b.n = 0 |
| 399 | return nil |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 400 | } |
| 401 | |
Rob Pike | 5dd4ef5 | 2009-03-07 16:57:01 -0800 | [diff] [blame] | 402 | // Available returns how many bytes are unused in the buffer. |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 403 | func (b *Writer) Available() int { return len(b.buf) - b.n } |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 404 | |
Rob Pike | 5dd4ef5 | 2009-03-07 16:57:01 -0800 | [diff] [blame] | 405 | // Buffered returns the number of bytes that have been written into the current buffer. |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 406 | func (b *Writer) Buffered() int { return b.n } |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 407 | |
Rob Pike | 5dd4ef5 | 2009-03-07 16:57:01 -0800 | [diff] [blame] | 408 | // Write writes the contents of p into the buffer. |
| 409 | // It returns the number of bytes written. |
Rob Pike | 11b459c | 2010-01-16 13:06:50 +1100 | [diff] [blame] | 410 | // If nn < len(p), it also returns an error explaining |
Rob Pike | 5dd4ef5 | 2009-03-07 16:57:01 -0800 | [diff] [blame] | 411 | // why the write is short. |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 412 | func (b *Writer) Write(p []byte) (nn int, err os.Error) { |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 413 | if b.err != nil { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 414 | return 0, b.err |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 415 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 416 | nn = 0 |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 417 | for len(p) > 0 { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 418 | n := b.Available() |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 419 | if n <= 0 { |
| 420 | if b.Flush(); b.err != nil { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 421 | break |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 422 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 423 | n = b.Available() |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 424 | } |
Andrew Gerrand | 4501e18 | 2010-07-27 17:22:45 +1000 | [diff] [blame] | 425 | if b.Buffered() == 0 && len(p) >= len(b.buf) { |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 426 | // Large write, empty buffer. |
| 427 | // Write directly from p to avoid copy. |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 428 | n, b.err = b.wr.Write(p) |
| 429 | nn += n |
| 430 | p = p[n:] |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 431 | if b.err != nil { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 432 | break |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 433 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 434 | continue |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 435 | } |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 436 | if n > len(p) { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 437 | n = len(p) |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 438 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 439 | copy(b.buf[b.n:b.n+n], p[0:n]) |
| 440 | b.n += n |
| 441 | nn += n |
| 442 | p = p[n:] |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 443 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 444 | return nn, b.err |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 445 | } |
| 446 | |
Rob Pike | 5dd4ef5 | 2009-03-07 16:57:01 -0800 | [diff] [blame] | 447 | // WriteByte writes a single byte. |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 448 | func (b *Writer) WriteByte(c byte) os.Error { |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 449 | if b.err != nil { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 450 | return b.err |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 451 | } |
| 452 | if b.Available() <= 0 && b.Flush() != nil { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 453 | return b.err |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 454 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 455 | b.buf[b.n] = c |
| 456 | b.n++ |
| 457 | return nil |
Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame] | 458 | } |
| 459 | |
Rob Pike | 8c9944d | 2010-03-05 14:03:17 -0800 | [diff] [blame] | 460 | // WriteRune writes a single Unicode code point, returning |
| 461 | // the number of bytes written and any error. |
| 462 | func (b *Writer) WriteRune(rune int) (size int, err os.Error) { |
| 463 | if rune < utf8.RuneSelf { |
| 464 | err = b.WriteByte(byte(rune)) |
| 465 | if err != nil { |
| 466 | return 0, err |
| 467 | } |
| 468 | return 1, nil |
| 469 | } |
| 470 | if b.err != nil { |
| 471 | return 0, b.err |
| 472 | } |
| 473 | n := b.Available() |
| 474 | if n < utf8.UTFMax { |
| 475 | if b.Flush(); b.err != nil { |
| 476 | return 0, b.err |
| 477 | } |
| 478 | n = b.Available() |
| 479 | if n < utf8.UTFMax { |
| 480 | // Can only happen if buffer is silly small. |
| 481 | return b.WriteString(string(rune)) |
| 482 | } |
| 483 | } |
Adam Langley | 3cb4bdb | 2010-11-30 16:59:43 -0500 | [diff] [blame] | 484 | size = utf8.EncodeRune(b.buf[b.n:], rune) |
Rob Pike | 8c9944d | 2010-03-05 14:03:17 -0800 | [diff] [blame] | 485 | b.n += size |
| 486 | return size, nil |
| 487 | } |
| 488 | |
Rob Pike | 2495c14 | 2009-08-03 18:28:05 -0700 | [diff] [blame] | 489 | // WriteString writes a string. |
Rob Pike | 11b459c | 2010-01-16 13:06:50 +1100 | [diff] [blame] | 490 | // It returns the number of bytes written. |
| 491 | // If the count is less than len(s), it also returns an error explaining |
| 492 | // why the write is short. |
| 493 | func (b *Writer) WriteString(s string) (int, os.Error) { |
Rob Pike | 2495c14 | 2009-08-03 18:28:05 -0700 | [diff] [blame] | 494 | if b.err != nil { |
Rob Pike | 11b459c | 2010-01-16 13:06:50 +1100 | [diff] [blame] | 495 | return 0, b.err |
Rob Pike | 2495c14 | 2009-08-03 18:28:05 -0700 | [diff] [blame] | 496 | } |
| 497 | // Common case, worth making fast. |
| 498 | if b.Available() >= len(s) || len(b.buf) >= len(s) && b.Flush() == nil { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 499 | for i := 0; i < len(s); i++ { // loop over bytes, not runes. |
| 500 | b.buf[b.n] = s[i] |
| 501 | b.n++ |
Rob Pike | 2495c14 | 2009-08-03 18:28:05 -0700 | [diff] [blame] | 502 | } |
Rob Pike | 11b459c | 2010-01-16 13:06:50 +1100 | [diff] [blame] | 503 | return len(s), nil |
Rob Pike | 2495c14 | 2009-08-03 18:28:05 -0700 | [diff] [blame] | 504 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 505 | for i := 0; i < len(s); i++ { // loop over bytes, not runes. |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 506 | b.WriteByte(s[i]) |
Rob Pike | 11b459c | 2010-01-16 13:06:50 +1100 | [diff] [blame] | 507 | if b.err != nil { |
| 508 | return i, b.err |
| 509 | } |
Rob Pike | 2495c14 | 2009-08-03 18:28:05 -0700 | [diff] [blame] | 510 | } |
Rob Pike | 11b459c | 2010-01-16 13:06:50 +1100 | [diff] [blame] | 511 | return len(s), nil |
Rob Pike | 2495c14 | 2009-08-03 18:28:05 -0700 | [diff] [blame] | 512 | } |
| 513 | |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 514 | // buffered input and output |
| 515 | |
Russ Cox | be869ba | 2009-05-18 13:31:56 -0700 | [diff] [blame] | 516 | // ReadWriter stores pointers to a Reader and a Writer. |
Rob Pike | c8b47c6 | 2009-05-08 11:22:57 -0700 | [diff] [blame] | 517 | // It implements io.ReadWriter. |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 518 | type ReadWriter struct { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 519 | *Reader |
| 520 | *Writer |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 521 | } |
| 522 | |
Russ Cox | be869ba | 2009-05-18 13:31:56 -0700 | [diff] [blame] | 523 | // NewReadWriter allocates a new ReadWriter that dispatches to r and w. |
Rob Pike | 01712ae | 2009-05-08 11:52:39 -0700 | [diff] [blame] | 524 | func NewReadWriter(r *Reader, w *Writer) *ReadWriter { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 525 | return &ReadWriter{r, w} |
Russ Cox | 9aa28f9 | 2009-02-03 14:16:22 -0800 | [diff] [blame] | 526 | } |