mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
bytes.Buffer: export the Grow method
Allows a client to pre-allocate buffer space that is known to be necessary, avoiding expensive reallocations. R=gri, gri, adg CC=golang-dev https://golang.org/cl/6392061
This commit is contained in:
parent
1ca7bc268b
commit
1255a6302d
2 changed files with 45 additions and 0 deletions
|
|
@ -99,6 +99,19 @@ func (b *Buffer) grow(n int) int {
|
||||||
return b.off + m
|
return b.off + m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Grow grows the buffer's capacity, if necessary, to guarantee space for
|
||||||
|
// another n bytes. After Grow(n), at least n bytes can be written to the
|
||||||
|
// buffer without another allocation.
|
||||||
|
// If n is negative, Grow will panic.
|
||||||
|
// If the buffer can't grow it will panic with ErrTooLarge.
|
||||||
|
func (b *Buffer) Grow(n int) {
|
||||||
|
if n < 0 {
|
||||||
|
panic("bytes.Buffer.Grow: negative count")
|
||||||
|
}
|
||||||
|
m := b.grow(n)
|
||||||
|
b.buf = b.buf[0:m]
|
||||||
|
}
|
||||||
|
|
||||||
// Write appends the contents of p to the buffer. The return
|
// Write appends the contents of p to the buffer. The return
|
||||||
// value n is the length of p; err is always nil.
|
// value n is the length of p; err is always nil.
|
||||||
// If the buffer becomes too large, Write will panic with
|
// If the buffer becomes too large, Write will panic with
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
. "bytes"
|
. "bytes"
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
@ -374,6 +375,37 @@ func TestReadBytes(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGrow(t *testing.T) {
|
||||||
|
x := []byte{'x'}
|
||||||
|
y := []byte{'y'}
|
||||||
|
tmp := make([]byte, 72)
|
||||||
|
for _, startLen := range []int{0, 100, 1000, 10000, 100000} {
|
||||||
|
xBytes := Repeat(x, startLen)
|
||||||
|
for _, growLen := range []int{0, 100, 1000, 10000, 100000} {
|
||||||
|
buf := NewBuffer(xBytes)
|
||||||
|
// If we read, this affects buf.off, which is good to test.
|
||||||
|
readBytes, _ := buf.Read(tmp)
|
||||||
|
buf.Grow(growLen)
|
||||||
|
yBytes := Repeat(y, growLen)
|
||||||
|
// Check no allocation occurs in write, as long as we're single-threaded.
|
||||||
|
var m1, m2 runtime.MemStats
|
||||||
|
runtime.ReadMemStats(&m1)
|
||||||
|
buf.Write(yBytes)
|
||||||
|
runtime.ReadMemStats(&m2)
|
||||||
|
if runtime.GOMAXPROCS(-1) == 1 && m1.Mallocs != m2.Mallocs {
|
||||||
|
t.Errorf("allocation occurred during write")
|
||||||
|
}
|
||||||
|
// Check that buffer has correct data.
|
||||||
|
if !Equal(buf.Bytes()[0:startLen-readBytes], xBytes[readBytes:]) {
|
||||||
|
t.Errorf("bad initial data at %d %d", startLen, growLen)
|
||||||
|
}
|
||||||
|
if !Equal(buf.Bytes()[startLen-readBytes:startLen-readBytes+growLen], yBytes) {
|
||||||
|
t.Errorf("bad written data at %d %d", startLen, growLen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Was a bug: used to give EOF reading empty slice at EOF.
|
// Was a bug: used to give EOF reading empty slice at EOF.
|
||||||
func TestReadEmptyAtEOF(t *testing.T) {
|
func TestReadEmptyAtEOF(t *testing.T) {
|
||||||
b := new(Buffer)
|
b := new(Buffer)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue