bytes: shuffle implementation, making WriteByte 50% faster

R=r
CC=golang-dev
https://golang.org/cl/920041
diff --git a/src/pkg/bytes/buffer.go b/src/pkg/bytes/buffer.go
index acd4523..faccca3 100644
--- a/src/pkg/bytes/buffer.go
+++ b/src/pkg/bytes/buffer.go
@@ -63,54 +63,44 @@
 // 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 {
-		// not enough space anywhere
-		buf = make([]byte, 2*cap(b.buf)+n)
-		copy(buf, b.buf[b.off:])
+// Grow buffer to guarantee space for n more bytes.
+// Return index where bytes should be written.
+func (b *Buffer) grow(n int) int {
+	m := b.Len()
+	// If buffer is empty, reset to recover space.
+	if m == 0 && b.off != 0 {
+		b.Truncate(0)
 	}
-	b.buf = buf
-	b.off = 0
+	if len(b.buf)+n > cap(b.buf) {
+		var buf []byte
+		if b.buf == nil && n <= len(b.bootstrap) {
+			buf = &b.bootstrap
+		} else {
+			// not enough space anywhere
+			buf = make([]byte, 2*cap(b.buf)+n)
+			copy(buf, b.buf[b.off:])
+		}
+		b.buf = buf
+		b.off = 0
+	}
+	b.buf = b.buf[0 : b.off+m+n]
+	return b.off + m
 }
 
 // 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
+	m := b.grow(len(p))
+	copy(b.buf[m:], p)
+	return len(p), 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
+	m := b.grow(len(s))
+	copyString(b.buf, m, s)
+	return len(s), nil
 }
 
 // MinRead is the minimum slice size passed to a Read call by
@@ -177,8 +167,8 @@
 // The returned error is always nil, but is included
 // to match bufio.Writer's WriteByte.
 func (b *Buffer) WriteByte(c byte) os.Error {
-	b.runeBytes[0] = c
-	b.Write(b.runeBytes[0:1])
+	m := b.grow(1)
+	b.buf[m] = c
 	return nil
 }