go/src/pkg/bytes/buffer.go
Robert Griesemer 5a1d3323fe 1) Change default gofmt default settings for
parsing and printing to new syntax.

                  Use -oldparser to parse the old syntax,
                  use -oldprinter to print the old syntax.

               2) Change default gofmt formatting settings
                  to use tabs for indentation only and to use
                  spaces for alignment. This will make the code
                  alignment insensitive to an editor's tabwidth.

                  Use -spaces=false to use tabs for alignment.

               3) Manually changed src/exp/parser/parser_test.go
                  so that it doesn't try to parse the parser's
                  source files using the old syntax (they have
                  new syntax now).

               4) gofmt -w src misc test/bench

	       1st set of files.

R=rsc
CC=agl, golang-dev, iant, ken2, r
https://golang.org/cl/180047
2009-12-15 15:33:31 -08:00

232 lines
6.3 KiB
Go

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bytes
// Simple byte buffer for marshaling data.
import (
"io"
"os"
)
// Copy from string to byte array at offset doff. Assume there's room.
func copyString(dst []byte, doff int, str string) {
for soff := 0; soff < len(str); soff++ {
dst[doff] = str[soff]
doff++
}
}
// A Buffer is a variable-sized buffer of bytes
// with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
buf []byte // contents are the bytes buf[off : len(buf)]
off int // read at &buf[off], write at &buf[len(buf)]
oneByte [1]byte // avoid allocation of slice on each WriteByte
bootstrap [64]byte // memory to hold first slice; helps small buffers (Printf) avoid allocation.
}
// Bytes returns the contents of the unread portion of the buffer;
// len(b.Bytes()) == b.Len().
func (b *Buffer) Bytes() []byte { return b.buf[b.off:] }
// String returns the contents of the unread portion of the buffer
// as a string. If the Buffer is a nil pointer, it returns "<nil>".
func (b *Buffer) String() string {
if b == nil {
// Special case, useful in debugging.
return "<nil>"
}
return string(b.buf[b.off:])
}
// Len returns the number of bytes of the unread portion of the buffer;
// b.Len() == len(b.Bytes()).
func (b *Buffer) Len() int { return len(b.buf) - b.off }
// Truncate discards all but the first n unread bytes from the buffer.
// It is an error to call b.Truncate(n) with n > b.Len().
func (b *Buffer) Truncate(n int) {
if n == 0 {
// Reuse buffer space.
b.off = 0
}
b.buf = b.buf[0 : b.off+n]
}
// Reset resets the buffer so it has no content.
// b.Reset() is the same as b.Truncate(0).
func (b *Buffer) Reset() { b.Truncate(0) }
// Resize buffer to guarantee enough space for n more bytes.
// After this call, the state of b.buf is inconsistent.
// It must be fixed up as is done in Write and WriteString.
func (b *Buffer) resize(n int) {
var buf []byte
if b.buf == nil && n <= len(b.bootstrap) {
buf = &b.bootstrap
} else {
buf = b.buf
if len(b.buf)+n > cap(b.buf) {
// not enough space anywhere
buf = make([]byte, 2*cap(b.buf)+n)
}
copy(buf, b.buf[b.off:])
}
b.buf = buf
b.off = 0
}
// Write appends the contents of p to the buffer. The return
// value n is the length of p; err is always nil.
func (b *Buffer) Write(p []byte) (n int, err os.Error) {
m := b.Len()
// If buffer is empty, reset to recover space.
if m == 0 && b.off != 0 {
b.Truncate(0)
}
n = len(p)
if len(b.buf)+n > cap(b.buf) {
b.resize(n)
}
b.buf = b.buf[0 : b.off+m+n]
copy(b.buf[b.off+m:], p)
return n, nil
}
// 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) {
m := b.Len()
// If buffer is empty, reset to recover space.
if m == 0 && b.off != 0 {
b.Truncate(0)
}
n = len(s)
if len(b.buf)+n > cap(b.buf) {
b.resize(n)
}
b.buf = b.buf[0 : b.off+m+n]
copyString(b.buf, b.off+m, s)
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) {
// If buffer is empty, reset to recover space.
if b.off >= len(b.buf) {
b.Truncate(0)
}
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
}
}
// Buffer is now empty; reset.
b.Truncate(0)
return
}
// WriteByte appends the byte c to the buffer.
// The returned error is always nil, but is included
// to match bufio.Writer's WriteByte.
func (b *Buffer) WriteByte(c byte) os.Error {
b.oneByte[0] = c
b.Write(&b.oneByte)
return nil
}
// Read reads the next len(p) bytes from the buffer or until the buffer
// is drained. The return value n is the number of bytes read. If the
// buffer has no data to return, err is os.EOF even if len(p) is zero;
// otherwise it is nil.
func (b *Buffer) Read(p []byte) (n int, err os.Error) {
if b.off >= len(b.buf) {
// Buffer is empty, reset to recover space.
b.Truncate(0)
return 0, os.EOF
}
m := b.Len()
n = len(p)
if n > m {
// more bytes requested than available
n = m
}
copy(p, b.buf[b.off:b.off+n])
b.off += n
return n, err
}
// ReadByte reads and returns the next byte from the buffer.
// If no byte is available, it returns error os.EOF.
func (b *Buffer) ReadByte() (c byte, err os.Error) {
if b.off >= len(b.buf) {
// Buffer is empty, reset to recover space.
b.Truncate(0)
return 0, os.EOF
}
c = b.buf[b.off]
b.off++
return c, nil
}
// NewBuffer creates and initializes a new Buffer
// using buf as its initial contents.
func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} }
// NewBufferString creates and initializes a new Buffer
// using string s as its initial contents.
func NewBufferString(s string) *Buffer {
buf := make([]byte, len(s))
copyString(buf, 0, s)
return &Buffer{buf: buf}
}