diff options
author | Rob Pike <r@golang.org> | 2009-12-03 12:56:16 -0800 |
---|---|---|
committer | Rob Pike <r@golang.org> | 2009-12-03 12:56:16 -0800 |
commit | cc74bcd3184136dd6a578a8b88f6027f1d94891c (patch) | |
tree | 0f4e9f9e8d22137c9cb112e5b4333e40c53218e3 /src/pkg/bytes/buffer.go | |
parent | c263db17c6083a4cacb03da16a507ba23a54515f (diff) | |
download | golang-cc74bcd3184136dd6a578a8b88f6027f1d94891c.tar.gz |
Add ReadFrom and WriteTo methods to bytes.Buffer, to enable i/o without buffer allocation.
Use them in Copy and Copyn.
Speed up ReadFile by using ReadFrom and avoiding Copy altogether (a minor win).
R=rsc, gri
CC=golang-dev
http://codereview.appspot.com/166041
Diffstat (limited to 'src/pkg/bytes/buffer.go')
-rw-r--r-- | src/pkg/bytes/buffer.go | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/src/pkg/bytes/buffer.go b/src/pkg/bytes/buffer.go index ab6f837aa..8fa64524c 100644 --- a/src/pkg/bytes/buffer.go +++ b/src/pkg/bytes/buffer.go @@ -7,6 +7,7 @@ package bytes // Simple byte buffer for marshaling data. import ( + "io"; "os"; ) @@ -91,6 +92,60 @@ func (b *Buffer) Write(p []byte) (n int, err os.Error) { return n, nil; } +// MinRead is the minimum slice size passed to a Read call by +// Buffer.ReadFrom. As long as the Buffer has at least MinRead bytes beyond +// what is required to hold the contents of r, ReadFrom will not grow the +// underlying buffer. +const MinRead = 512 + +// ReadFrom reads data from r until EOF and appends it to the buffer. +// The return value n is the number of bytes read. +// Any error except os.EOF encountered during the read +// is also returned. +func (b *Buffer) ReadFrom(r io.Reader) (n int64, err os.Error) { + for { + if cap(b.buf)-len(b.buf) < MinRead { + var newBuf []byte; + // can we get space without allocation? + if b.off+cap(b.buf)-len(b.buf) >= MinRead { + // reuse beginning of buffer + newBuf = b.buf[0 : len(b.buf)-b.off] + } else { + // not enough space at end; put space on end + newBuf = make([]byte, len(b.buf)-b.off, 2*(cap(b.buf)-b.off)+MinRead) + } + copy(newBuf, b.buf[b.off:]); + b.buf = newBuf; + b.off = 0; + } + m, e := r.Read(b.buf[len(b.buf):cap(b.buf)]); + b.buf = b.buf[b.off : len(b.buf)+m]; + n += int64(m); + if e == os.EOF { + break + } + if e != nil { + return n, e + } + } + return n, nil; // err is EOF, so return nil explicitly +} + +// WriteTo writes data to w until the buffer is drained or an error +// occurs. The return value n is the number of bytes written. +// Any error encountered during the write is also returned. +func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) { + for b.off < len(b.buf) { + m, e := w.Write(b.buf[b.off:]); + n += int64(m); + b.off += m; + if e != nil { + return n, e + } + } + return; +} + // WriteString appends the contents of s to the buffer. The return // value n is the length of s; err is always nil. func (b *Buffer) WriteString(s string) (n int, err os.Error) { |