diff options
| author | Robert Griesemer <gri@golang.org> | 2009-05-05 12:00:52 -0700 | 
|---|---|---|
| committer | Robert Griesemer <gri@golang.org> | 2009-05-05 12:00:52 -0700 | 
| commit | 1f08f367c5030005b6f0c3efb6c870605cc5bef0 (patch) | |
| tree | 4f4c0e73d7e8eeb0d044f0f5db20e51b07d128a3 /src/lib/io/bytebuffer.go | |
| parent | 766efb91969446a5242bd22aa09c65227e2641b6 (diff) | |
| download | golang-1f08f367c5030005b6f0c3efb6c870605cc5bef0.tar.gz | |
better io.ByteBuffer implementation:
- more light-weight
- better buffer management
- added test cases
R=r
DELTA=227  (167 added, 35 deleted, 25 changed)
OCL=28252
CL=28289
Diffstat (limited to 'src/lib/io/bytebuffer.go')
| -rw-r--r-- | src/lib/io/bytebuffer.go | 104 | 
1 files changed, 45 insertions, 59 deletions
| diff --git a/src/lib/io/bytebuffer.go b/src/lib/io/bytebuffer.go index 9c78e8566..011166e9c 100644 --- a/src/lib/io/bytebuffer.go +++ b/src/lib/io/bytebuffer.go @@ -11,11 +11,8 @@ import (  	"os";  ) - -// TODO(r): Do better memory management. -  func bytecopy(dst []byte, doff int, src []byte, soff int, count int) { -	for i := 0; i < count; i++ { +	for ; count > 0; count-- {  		dst[doff] = src[soff];  		doff++;  		soff++; @@ -26,79 +23,68 @@ func bytecopy(dst []byte, doff int, src []byte, soff int, count int) {  // connected to a buffer of bytes.  // The zero value for ByteBuffer is an empty buffer ready to use.  type ByteBuffer struct { -	buf	[]byte; -	off	int;	// Read from here -	len	int;	// Write to here -	cap	int; +	buf	[]byte;	// contents are the bytes buf[off : len(buf)] +	off	int;	// read at &buf[off], write at &buf[len(buf)] +} + +// Data returns the contents of the unread portion of the buffer; +// len(b.Data()) == b.Len(). +func (b *ByteBuffer) Data() []byte { +	return b.buf[b.off : len(b.buf)] +} + +// Len returns the number of bytes of the unread portion of the buffer; +// b.Len() == len(b.Data()). +func (b *ByteBuffer) Len() int { +	return len(b.buf) - b.off  }  // Reset resets the buffer so it has no content.  func (b *ByteBuffer) Reset() { -	b.off = 0; -	b.len = 0; +	b.off = len(b.buf)  }  // Write appends the contents of p to the buffer.  The return -// value is the length of p; err is always nil. +// value n is the length of p; err is always nil.  func (b *ByteBuffer) Write(p []byte) (n int, err os.Error) { -	plen := len(p); -	if len(b.buf) == 0 { -		b.cap = plen + 1024; -		b.buf = make([]byte, b.cap); -		b.len = 0; -	} -	if b.len + plen > b.cap { -		b.cap = 2*(b.cap + plen); -		nb := make([]byte, b.cap); -		bytecopy(nb, 0, b.buf, 0, b.len); -		b.buf = nb; +	m := b.Len(); +	n = len(p); + +	if len(b.buf) + n > cap(b.buf) { +		// not enough space at end +		buf := b.buf; +		if m + n > cap(b.buf) { +			// not enough space anywhere +			buf = make([]byte, 2*cap(b.buf) + n) +		} +		bytecopy(buf, 0, b.buf, b.off, m); +		b.buf = buf; +		b.off = 0  	} -	bytecopy(b.buf, b.len, p, 0, plen); -	b.len += plen; -	return plen, nil; + +	b.buf = b.buf[0 : b.off + m + n]; +	bytecopy(b.buf, b.off + m, p, 0, n); +	return n, nil  }  // Read reads the next len(p) bytes from the buffer or until the buffer -// is drained.  The return value is the number of bytes read; err is always nil. +// is drained.  The return value n is the number of bytes read; err is always nil.  func (b *ByteBuffer) Read(p []byte) (n int, err os.Error) { -	plen := len(p); -	if len(b.buf) == 0 { -		return 0, nil -	} -	if b.off == b.len {	// empty buffer -		b.Reset(); -		return 0, nil -	} -	if plen > b.len - b.off { -		plen = b.len - b.off -	} -	bytecopy(p, 0, b.buf, b.off, plen); -	b.off += plen; -	return plen, nil; -} - -// Len returns the length of the underlying buffer. -func (b *ByteBuffer) Len() int { -	return b.len -} +	m := b.Len(); +	n = len(p); -// Off returns the location within the buffer of the next byte to be read. -func (b *ByteBuffer) Off() int { -	return b.off -} +	if n > m { +		// more bytes requested than available +		n = m +	} -// Data returns the contents of the unread portion of the buffer. -func (b *ByteBuffer) Data() []byte { -	return b.buf[b.off:b.len] +	bytecopy(p, 0, b.buf, b.off, n); +	b.off += n; +	return n, nil  }  // NewByteBufferFromArray creates and initializes a new ByteBuffer  // with buf as its initial contents.  func NewByteBufferFromArray(buf []byte) *ByteBuffer { -	b := new(ByteBuffer); -	b.buf = buf; -	b.off = 0; -	b.len = len(buf); -	b.cap = len(buf); -	return b; +	return &ByteBuffer{buf, 0};  } | 
