Rob Pike | 5f9254c | 2008-11-25 09:41:58 -0800 | [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 | |
Russ Cox | d3a412a | 2009-06-29 15:24:23 -0700 | [diff] [blame] | 5 | package bytes |
Rob Pike | 5f9254c | 2008-11-25 09:41:58 -0800 | [diff] [blame] | 6 | |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 7 | // Simple byte buffer for marshaling data. |
Rob Pike | 5f9254c | 2008-11-25 09:41:58 -0800 | [diff] [blame] | 8 | |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 9 | import ( |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 10 | "io" |
| 11 | "os" |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 12 | "utf8" |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 13 | ) |
Rob Pike | 5f9254c | 2008-11-25 09:41:58 -0800 | [diff] [blame] | 14 | |
Rob Pike | 1f0e6a4 | 2009-12-19 08:42:31 +1100 | [diff] [blame] | 15 | // A Buffer is a variable-sized buffer of bytes with Read and Write methods. |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 16 | // The zero value for Buffer is an empty buffer ready to use. |
| 17 | type Buffer struct { |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 18 | buf []byte // contents are the bytes buf[off : len(buf)] |
| 19 | off int // read at &buf[off], write at &buf[len(buf)] |
| 20 | runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each WriteByte or Rune |
| 21 | bootstrap [64]byte // memory to hold first slice; helps small buffers (Printf) avoid allocation. |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 22 | lastRead readOp // last read operation, so that Unread* can work correctly. |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 23 | } |
| 24 | |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 25 | // The readOp constants describe the last action performed on |
| 26 | // the buffer, so that UnreadRune and UnreadByte can |
| 27 | // check for invalid usage. |
| 28 | type readOp int |
| 29 | |
| 30 | const ( |
| 31 | opInvalid readOp = iota // Non-read operation. |
| 32 | opReadRune // Read rune. |
| 33 | opRead // Any other read operation. |
| 34 | ) |
| 35 | |
Rob Pike | 1f0e6a4 | 2009-12-19 08:42:31 +1100 | [diff] [blame] | 36 | // Bytes returns a slice of the contents of the unread portion of the buffer; |
| 37 | // len(b.Bytes()) == b.Len(). If the caller changes the contents of the |
| 38 | // returned slice, the contents of the buffer will change provided there |
| 39 | // are no intervening method calls on the Buffer. |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 40 | func (b *Buffer) Bytes() []byte { return b.buf[b.off:] } |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 41 | |
Rob Pike | d5be41f | 2009-09-16 15:15:00 -0700 | [diff] [blame] | 42 | // String returns the contents of the unread portion of the buffer |
Rob Pike | 63e668d | 2009-10-31 13:28:22 -0700 | [diff] [blame] | 43 | // as a string. If the Buffer is a nil pointer, it returns "<nil>". |
Rob Pike | d5be41f | 2009-09-16 15:15:00 -0700 | [diff] [blame] | 44 | func (b *Buffer) String() string { |
Rob Pike | 63e668d | 2009-10-31 13:28:22 -0700 | [diff] [blame] | 45 | if b == nil { |
| 46 | // Special case, useful in debugging. |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 47 | return "<nil>" |
Rob Pike | 63e668d | 2009-10-31 13:28:22 -0700 | [diff] [blame] | 48 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 49 | return string(b.buf[b.off:]) |
Rob Pike | d5be41f | 2009-09-16 15:15:00 -0700 | [diff] [blame] | 50 | } |
| 51 | |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 52 | // Len returns the number of bytes of the unread portion of the buffer; |
| 53 | // b.Len() == len(b.Bytes()). |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 54 | func (b *Buffer) Len() int { return len(b.buf) - b.off } |
Rob Pike | 5f9254c | 2008-11-25 09:41:58 -0800 | [diff] [blame] | 55 | |
Russ Cox | ea79b82 | 2009-05-14 13:39:17 -0700 | [diff] [blame] | 56 | // Truncate discards all but the first n unread bytes from the buffer. |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 57 | // It is an error to call b.Truncate(n) with n > b.Len(). |
Russ Cox | d3a412a | 2009-06-29 15:24:23 -0700 | [diff] [blame] | 58 | func (b *Buffer) Truncate(n int) { |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 59 | b.lastRead = opInvalid |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 60 | if n == 0 { |
| 61 | // Reuse buffer space. |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 62 | b.off = 0 |
Russ Cox | be869ba | 2009-05-18 13:31:56 -0700 | [diff] [blame] | 63 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 64 | b.buf = b.buf[0 : b.off+n] |
Robert Griesemer | 28db3e8 | 2009-05-14 10:14:29 -0700 | [diff] [blame] | 65 | } |
| 66 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame] | 67 | // Reset resets the buffer so it has no content. |
Robert Griesemer | 28db3e8 | 2009-05-14 10:14:29 -0700 | [diff] [blame] | 68 | // b.Reset() is the same as b.Truncate(0). |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 69 | func (b *Buffer) Reset() { b.Truncate(0) } |
Rob Pike | 5f9254c | 2008-11-25 09:41:58 -0800 | [diff] [blame] | 70 | |
Russ Cox | 1baf35e | 2010-04-14 01:52:56 -0700 | [diff] [blame] | 71 | // Grow buffer to guarantee space for n more bytes. |
| 72 | // Return index where bytes should be written. |
| 73 | func (b *Buffer) grow(n int) int { |
| 74 | m := b.Len() |
| 75 | // If buffer is empty, reset to recover space. |
| 76 | if m == 0 && b.off != 0 { |
| 77 | b.Truncate(0) |
Rob Pike | 4c0e51c | 2009-12-06 12:03:52 -0800 | [diff] [blame] | 78 | } |
Russ Cox | 1baf35e | 2010-04-14 01:52:56 -0700 | [diff] [blame] | 79 | if len(b.buf)+n > cap(b.buf) { |
| 80 | var buf []byte |
| 81 | if b.buf == nil && n <= len(b.bootstrap) { |
Russ Cox | bb84f4b | 2010-05-27 14:51:47 -0700 | [diff] [blame] | 82 | buf = b.bootstrap[0:] |
Russ Cox | 1baf35e | 2010-04-14 01:52:56 -0700 | [diff] [blame] | 83 | } else { |
| 84 | // not enough space anywhere |
| 85 | buf = make([]byte, 2*cap(b.buf)+n) |
| 86 | copy(buf, b.buf[b.off:]) |
| 87 | } |
| 88 | b.buf = buf |
| 89 | b.off = 0 |
| 90 | } |
| 91 | b.buf = b.buf[0 : b.off+m+n] |
| 92 | return b.off + m |
Rob Pike | 4c0e51c | 2009-12-06 12:03:52 -0800 | [diff] [blame] | 93 | } |
| 94 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame] | 95 | // Write appends the contents of p to the buffer. The return |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 96 | // value n is the length of p; err is always nil. |
Russ Cox | d3a412a | 2009-06-29 15:24:23 -0700 | [diff] [blame] | 97 | func (b *Buffer) Write(p []byte) (n int, err os.Error) { |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 98 | b.lastRead = opInvalid |
Russ Cox | 1baf35e | 2010-04-14 01:52:56 -0700 | [diff] [blame] | 99 | m := b.grow(len(p)) |
| 100 | copy(b.buf[m:], p) |
| 101 | return len(p), nil |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 102 | } |
| 103 | |
Rob Pike | 4c0e51c | 2009-12-06 12:03:52 -0800 | [diff] [blame] | 104 | // WriteString appends the contents of s to the buffer. The return |
| 105 | // value n is the length of s; err is always nil. |
| 106 | func (b *Buffer) WriteString(s string) (n int, err os.Error) { |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 107 | b.lastRead = opInvalid |
Russ Cox | 1baf35e | 2010-04-14 01:52:56 -0700 | [diff] [blame] | 108 | m := b.grow(len(s)) |
Russ Cox | d86ab01 | 2010-10-26 21:52:54 -0700 | [diff] [blame] | 109 | return copy(b.buf[m:], s), nil |
Rob Pike | 4c0e51c | 2009-12-06 12:03:52 -0800 | [diff] [blame] | 110 | } |
| 111 | |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 112 | // MinRead is the minimum slice size passed to a Read call by |
| 113 | // Buffer.ReadFrom. As long as the Buffer has at least MinRead bytes beyond |
| 114 | // what is required to hold the contents of r, ReadFrom will not grow the |
| 115 | // underlying buffer. |
| 116 | const MinRead = 512 |
| 117 | |
| 118 | // ReadFrom reads data from r until EOF and appends it to the buffer. |
| 119 | // The return value n is the number of bytes read. |
| 120 | // Any error except os.EOF encountered during the read |
| 121 | // is also returned. |
| 122 | func (b *Buffer) ReadFrom(r io.Reader) (n int64, err os.Error) { |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 123 | b.lastRead = opInvalid |
Rob Pike | d14c813 | 2009-12-14 13:13:01 +1100 | [diff] [blame] | 124 | // If buffer is empty, reset to recover space. |
| 125 | if b.off >= len(b.buf) { |
| 126 | b.Truncate(0) |
| 127 | } |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 128 | for { |
| 129 | if cap(b.buf)-len(b.buf) < MinRead { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 130 | var newBuf []byte |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 131 | // can we get space without allocation? |
| 132 | if b.off+cap(b.buf)-len(b.buf) >= MinRead { |
| 133 | // reuse beginning of buffer |
| 134 | newBuf = b.buf[0 : len(b.buf)-b.off] |
| 135 | } else { |
| 136 | // not enough space at end; put space on end |
| 137 | newBuf = make([]byte, len(b.buf)-b.off, 2*(cap(b.buf)-b.off)+MinRead) |
| 138 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 139 | copy(newBuf, b.buf[b.off:]) |
| 140 | b.buf = newBuf |
| 141 | b.off = 0 |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 142 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 143 | m, e := r.Read(b.buf[len(b.buf):cap(b.buf)]) |
Rob Pike | 9baa7a5 | 2010-06-15 17:40:47 -0700 | [diff] [blame] | 144 | b.buf = b.buf[0 : len(b.buf)+m] |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 145 | n += int64(m) |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 146 | if e == os.EOF { |
| 147 | break |
| 148 | } |
| 149 | if e != nil { |
| 150 | return n, e |
| 151 | } |
| 152 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 153 | return n, nil // err is EOF, so return nil explicitly |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 154 | } |
| 155 | |
| 156 | // WriteTo writes data to w until the buffer is drained or an error |
Robert Griesemer | 4438f50 | 2011-02-09 15:09:08 -0800 | [diff] [blame] | 157 | // occurs. The return value n is the number of bytes written; it always |
| 158 | // fits into an int, but it is int64 to match the io.WriterTo interface. |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 159 | // Any error encountered during the write is also returned. |
| 160 | func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) { |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 161 | b.lastRead = opInvalid |
Robert Griesemer | 4438f50 | 2011-02-09 15:09:08 -0800 | [diff] [blame] | 162 | if b.off < len(b.buf) { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 163 | m, e := w.Write(b.buf[b.off:]) |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 164 | b.off += m |
Robert Griesemer | 4438f50 | 2011-02-09 15:09:08 -0800 | [diff] [blame] | 165 | n = int64(m) |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 166 | if e != nil { |
| 167 | return n, e |
| 168 | } |
Robert Griesemer | 4438f50 | 2011-02-09 15:09:08 -0800 | [diff] [blame] | 169 | // otherwise all bytes were written, by definition of |
| 170 | // Write method in io.Writer |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 171 | } |
Rob Pike | d14c813 | 2009-12-14 13:13:01 +1100 | [diff] [blame] | 172 | // Buffer is now empty; reset. |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 173 | b.Truncate(0) |
| 174 | return |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 175 | } |
| 176 | |
Robert Griesemer | 472e191 | 2009-05-14 17:03:47 -0700 | [diff] [blame] | 177 | // WriteByte appends the byte c to the buffer. |
Russ Cox | 55b70d6c | 2009-05-15 10:46:14 -0700 | [diff] [blame] | 178 | // The returned error is always nil, but is included |
| 179 | // to match bufio.Writer's WriteByte. |
Russ Cox | d3a412a | 2009-06-29 15:24:23 -0700 | [diff] [blame] | 180 | func (b *Buffer) WriteByte(c byte) os.Error { |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 181 | b.lastRead = opInvalid |
Russ Cox | 1baf35e | 2010-04-14 01:52:56 -0700 | [diff] [blame] | 182 | m := b.grow(1) |
| 183 | b.buf[m] = c |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 184 | return nil |
Robert Griesemer | 472e191 | 2009-05-14 17:03:47 -0700 | [diff] [blame] | 185 | } |
| 186 | |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 187 | // WriteRune appends the UTF-8 encoding of Unicode |
| 188 | // code point r to the buffer, returning its length and |
| 189 | // an error, which is always nil but is included |
| 190 | // to match bufio.Writer's WriteRune. |
Russ Cox | 8f57181 | 2011-10-25 22:22:09 -0700 | [diff] [blame] | 191 | func (b *Buffer) WriteRune(r rune) (n int, err os.Error) { |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 192 | if r < utf8.RuneSelf { |
| 193 | b.WriteByte(byte(r)) |
| 194 | return 1, nil |
| 195 | } |
Adam Langley | 3cb4bdb | 2010-11-30 16:59:43 -0500 | [diff] [blame] | 196 | n = utf8.EncodeRune(b.runeBytes[0:], r) |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 197 | b.Write(b.runeBytes[0:n]) |
| 198 | return n, nil |
| 199 | } |
| 200 | |
Rob Pike | 7bb335c | 2009-03-06 03:43:44 -0800 | [diff] [blame] | 201 | // Read reads the next len(p) bytes from the buffer or until the buffer |
Rob Pike | 5766553 | 2009-06-23 15:20:40 -0700 | [diff] [blame] | 202 | // is drained. The return value n is the number of bytes read. If the |
| 203 | // buffer has no data to return, err is os.EOF even if len(p) is zero; |
| 204 | // otherwise it is nil. |
Russ Cox | d3a412a | 2009-06-29 15:24:23 -0700 | [diff] [blame] | 205 | func (b *Buffer) Read(p []byte) (n int, err os.Error) { |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 206 | b.lastRead = opInvalid |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 207 | if b.off >= len(b.buf) { |
Rob Pike | d14c813 | 2009-12-14 13:13:01 +1100 | [diff] [blame] | 208 | // Buffer is empty, reset to recover space. |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 209 | b.Truncate(0) |
| 210 | return 0, os.EOF |
Rob Pike | 5766553 | 2009-06-23 15:20:40 -0700 | [diff] [blame] | 211 | } |
Russ Cox | 78551a9 | 2010-04-26 10:02:01 -0700 | [diff] [blame] | 212 | n = copy(p, b.buf[b.off:]) |
| 213 | b.off += n |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 214 | if n > 0 { |
| 215 | b.lastRead = opRead |
| 216 | } |
Russ Cox | 78551a9 | 2010-04-26 10:02:01 -0700 | [diff] [blame] | 217 | return |
| 218 | } |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 219 | |
Russ Cox | 78551a9 | 2010-04-26 10:02:01 -0700 | [diff] [blame] | 220 | // Next returns a slice containing the next n bytes from the buffer, |
| 221 | // advancing the buffer as if the bytes had been returned by Read. |
| 222 | // If there are fewer than n bytes in the buffer, Next returns the entire buffer. |
| 223 | // The slice is only valid until the next call to a read or write method. |
| 224 | func (b *Buffer) Next(n int) []byte { |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 225 | b.lastRead = opInvalid |
Russ Cox | 78551a9 | 2010-04-26 10:02:01 -0700 | [diff] [blame] | 226 | m := b.Len() |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 227 | if n > m { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 228 | n = m |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 229 | } |
Russ Cox | 78551a9 | 2010-04-26 10:02:01 -0700 | [diff] [blame] | 230 | data := b.buf[b.off : b.off+n] |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 231 | b.off += n |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 232 | if n > 0 { |
| 233 | b.lastRead = opRead |
| 234 | } |
Russ Cox | 78551a9 | 2010-04-26 10:02:01 -0700 | [diff] [blame] | 235 | return data |
Rob Pike | 5f9254c | 2008-11-25 09:41:58 -0800 | [diff] [blame] | 236 | } |
| 237 | |
Scott Schwartz | 08aab44 | 2009-06-19 16:29:30 -0700 | [diff] [blame] | 238 | // ReadByte reads and returns the next byte from the buffer. |
Russ Cox | 64684cc | 2009-06-22 13:26:13 -0700 | [diff] [blame] | 239 | // If no byte is available, it returns error os.EOF. |
Russ Cox | d3a412a | 2009-06-29 15:24:23 -0700 | [diff] [blame] | 240 | func (b *Buffer) ReadByte() (c byte, err os.Error) { |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 241 | b.lastRead = opInvalid |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 242 | if b.off >= len(b.buf) { |
Rob Pike | d14c813 | 2009-12-14 13:13:01 +1100 | [diff] [blame] | 243 | // Buffer is empty, reset to recover space. |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 244 | b.Truncate(0) |
| 245 | return 0, os.EOF |
Scott Schwartz | 08aab44 | 2009-06-19 16:29:30 -0700 | [diff] [blame] | 246 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 247 | c = b.buf[b.off] |
| 248 | b.off++ |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 249 | b.lastRead = opRead |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 250 | return c, nil |
Scott Schwartz | 08aab44 | 2009-06-19 16:29:30 -0700 | [diff] [blame] | 251 | } |
| 252 | |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 253 | // ReadRune reads and returns the next UTF-8-encoded |
| 254 | // Unicode code point from the buffer. |
| 255 | // If no bytes are available, the error returned is os.EOF. |
| 256 | // If the bytes are an erroneous UTF-8 encoding, it |
| 257 | // consumes one byte and returns U+FFFD, 1. |
Russ Cox | 8f57181 | 2011-10-25 22:22:09 -0700 | [diff] [blame] | 258 | func (b *Buffer) ReadRune() (r rune, size int, err os.Error) { |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 259 | b.lastRead = opInvalid |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 260 | if b.off >= len(b.buf) { |
| 261 | // Buffer is empty, reset to recover space. |
| 262 | b.Truncate(0) |
| 263 | return 0, 0, os.EOF |
| 264 | } |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 265 | b.lastRead = opReadRune |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 266 | c := b.buf[b.off] |
| 267 | if c < utf8.RuneSelf { |
| 268 | b.off++ |
Russ Cox | 8f57181 | 2011-10-25 22:22:09 -0700 | [diff] [blame] | 269 | return rune(c), 1, nil |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 270 | } |
| 271 | r, n := utf8.DecodeRune(b.buf[b.off:]) |
| 272 | b.off += n |
| 273 | return r, n, nil |
| 274 | } |
| 275 | |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 276 | // UnreadRune unreads the last rune returned by ReadRune. |
| 277 | // If the most recent read or write operation on the buffer was |
| 278 | // not a ReadRune, UnreadRune returns an error. (In this regard |
| 279 | // it is stricter than UnreadByte, which will unread the last byte |
| 280 | // from any read operation.) |
| 281 | func (b *Buffer) UnreadRune() os.Error { |
| 282 | if b.lastRead != opReadRune { |
Robert Griesemer | 712fb6d | 2011-06-22 10:52:47 -0700 | [diff] [blame] | 283 | return os.NewError("bytes.Buffer: UnreadRune: previous operation was not ReadRune") |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 284 | } |
| 285 | b.lastRead = opInvalid |
| 286 | if b.off > 0 { |
| 287 | _, n := utf8.DecodeLastRune(b.buf[0:b.off]) |
| 288 | b.off -= n |
| 289 | } |
| 290 | return nil |
| 291 | } |
| 292 | |
| 293 | // UnreadByte unreads the last byte returned by the most recent |
| 294 | // read operation. If write has happened since the last read, UnreadByte |
| 295 | // returns an error. |
| 296 | func (b *Buffer) UnreadByte() os.Error { |
Rob Pike | 353fd10 | 2011-01-07 14:41:33 -0800 | [diff] [blame] | 297 | if b.lastRead != opReadRune && b.lastRead != opRead { |
Robert Griesemer | 712fb6d | 2011-06-22 10:52:47 -0700 | [diff] [blame] | 298 | return os.NewError("bytes.Buffer: UnreadByte: previous operation was not a read") |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 299 | } |
| 300 | b.lastRead = opInvalid |
| 301 | if b.off > 0 { |
| 302 | b.off-- |
| 303 | } |
| 304 | return nil |
| 305 | } |
| 306 | |
Evan Shaw | c9bf30c | 2011-01-27 14:00:31 -0800 | [diff] [blame] | 307 | // ReadBytes reads until the first occurrence of delim in the input, |
| 308 | // returning a slice containing the data up to and including the delimiter. |
| 309 | // If ReadBytes encounters an error before finding a delimiter, |
| 310 | // it returns the data read before the error and the error itself (often os.EOF). |
| 311 | // ReadBytes returns err != nil if and only if the returned data does not end in |
| 312 | // delim. |
| 313 | func (b *Buffer) ReadBytes(delim byte) (line []byte, err os.Error) { |
| 314 | i := IndexByte(b.buf[b.off:], delim) |
Evan Shaw | bbfad5f | 2011-02-11 12:39:18 -0500 | [diff] [blame] | 315 | size := i + 1 |
Evan Shaw | c9bf30c | 2011-01-27 14:00:31 -0800 | [diff] [blame] | 316 | if i < 0 { |
| 317 | size = len(b.buf) - b.off |
| 318 | err = os.EOF |
| 319 | } |
| 320 | line = make([]byte, size) |
| 321 | copy(line, b.buf[b.off:]) |
Evan Shaw | bbfad5f | 2011-02-11 12:39:18 -0500 | [diff] [blame] | 322 | b.off += size |
Evan Shaw | c9bf30c | 2011-01-27 14:00:31 -0800 | [diff] [blame] | 323 | return |
| 324 | } |
| 325 | |
| 326 | // ReadString reads until the first occurrence of delim in the input, |
| 327 | // returning a string containing the data up to and including the delimiter. |
| 328 | // If ReadString encounters an error before finding a delimiter, |
| 329 | // it returns the data read before the error and the error itself (often os.EOF). |
| 330 | // ReadString returns err != nil if and only if the returned data does not end |
| 331 | // in delim. |
| 332 | func (b *Buffer) ReadString(delim byte) (line string, err os.Error) { |
| 333 | bytes, err := b.ReadBytes(delim) |
| 334 | return string(bytes), err |
| 335 | } |
| 336 | |
Rob Pike | 1f0e6a4 | 2009-12-19 08:42:31 +1100 | [diff] [blame] | 337 | // NewBuffer creates and initializes a new Buffer using buf as its initial |
| 338 | // contents. It is intended to prepare a Buffer to read existing data. It |
Rob Pike | a45c657 | 2011-08-26 15:09:23 +1000 | [diff] [blame] | 339 | // can also be used to size the internal buffer for writing. To do that, |
Rob Pike | 1f0e6a4 | 2009-12-19 08:42:31 +1100 | [diff] [blame] | 340 | // buf should have the desired capacity but a length of zero. |
Rob Pike | a45c657 | 2011-08-26 15:09:23 +1000 | [diff] [blame] | 341 | // |
| 342 | // In most cases, new(Buffer) (or just declaring a Buffer variable) is |
| 343 | // preferable to NewBuffer. In particular, passing a non-empty buf to |
| 344 | // NewBuffer and then writing to the Buffer will overwrite buf, not append to |
| 345 | // it. |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 346 | func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} } |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 347 | |
Rob Pike | 1f0e6a4 | 2009-12-19 08:42:31 +1100 | [diff] [blame] | 348 | // NewBufferString creates and initializes a new Buffer using string s as its |
| 349 | // initial contents. It is intended to prepare a buffer to read an existing |
Rob Pike | a45c657 | 2011-08-26 15:09:23 +1000 | [diff] [blame] | 350 | // string. See the warnings about NewBuffer; similar issues apply here. |
Rob Pike | 9e7f3a4 | 2009-09-22 14:53:48 -0700 | [diff] [blame] | 351 | func NewBufferString(s string) *Buffer { |
Russ Cox | d86ab01 | 2010-10-26 21:52:54 -0700 | [diff] [blame] | 352 | return &Buffer{buf: []byte(s)} |
Rob Pike | 5f9254c | 2008-11-25 09:41:58 -0800 | [diff] [blame] | 353 | } |