diff options
Diffstat (limited to 'src/bytes')
| -rw-r--r-- | src/bytes/buffer.go | 15 | ||||
| -rw-r--r-- | src/bytes/bytes.go | 37 | ||||
| -rw-r--r-- | src/bytes/bytes_test.go | 6 |
3 files changed, 38 insertions, 20 deletions
diff --git a/src/bytes/buffer.go b/src/bytes/buffer.go index 14c5bc38d6..087cc0e427 100644 --- a/src/bytes/buffer.go +++ b/src/bytes/buffer.go @@ -12,13 +12,15 @@ import ( "unicode/utf8" ) +// smallBufferSize is an initial allocation minimal capacity. +const smallBufferSize = 64 + // 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)] - bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation. - lastRead readOp // last read operation, so that Unread* can work correctly. + buf []byte // contents are the bytes buf[off : len(buf)] + off int // read at &buf[off], write at &buf[len(buf)] + lastRead readOp // last read operation, so that Unread* can work correctly. // FIXME: it would be advisable to align Buffer to cachelines to avoid false // sharing. @@ -125,9 +127,8 @@ func (b *Buffer) grow(n int) int { if i, ok := b.tryGrowByReslice(n); ok { return i } - // Check if we can make use of bootstrap array. - if b.buf == nil && n <= len(b.bootstrap) { - b.buf = b.bootstrap[:n] + if b.buf == nil && n <= smallBufferSize { + b.buf = make([]byte, n, smallBufferSize) return 0 } c := cap(b.buf) diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index 77a7ce98e0..6492db088a 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -774,6 +774,15 @@ func Replace(s, old, new []byte, n int) []byte { return t[0:w] } +// ReplaceAll returns a copy of the slice s with all +// non-overlapping instances of old replaced by new. +// If old is empty, it matches at the beginning of the slice +// and after each UTF-8 sequence, yielding up to k+1 replacements +// for a k-rune slice. +func ReplaceAll(s, old, new []byte) []byte { + return Replace(s, old, new, -1) +} + // EqualFold reports whether s and t, interpreted as UTF-8 strings, // are equal under Unicode case-folding. func EqualFold(s, t []byte) bool { @@ -849,21 +858,22 @@ func Index(s, sep []byte) int { if len(s) <= bytealg.MaxBruteForce { return bytealg.Index(s, sep) } - c := sep[0] + c0 := sep[0] + c1 := sep[1] i := 0 - t := s[:len(s)-n+1] + t := len(s) - n + 1 fails := 0 - for i < len(t) { - if t[i] != c { + for i < t { + if s[i] != c0 { // IndexByte is faster than bytealg.Index, so use it as long as // we're not getting lots of false positives. - o := IndexByte(t[i:], c) + o := IndexByte(s[i:t], c0) if o < 0 { return -1 } i += o } - if Equal(s[i:i+n], sep) { + if s[i+1] == c1 && Equal(s[i:i+n], sep) { return i } fails++ @@ -879,24 +889,25 @@ func Index(s, sep []byte) int { } return -1 } - c := sep[0] + c0 := sep[0] + c1 := sep[1] i := 0 fails := 0 - t := s[:len(s)-n+1] - for i < len(t) { - if t[i] != c { - o := IndexByte(t[i:], c) + t := len(s) - n + 1 + for i < t { + if s[i] != c0 { + o := IndexByte(s[i:t], c0) if o < 0 { break } i += o } - if Equal(s[i:i+n], sep) { + if s[i+1] == c1 && Equal(s[i:i+n], sep) { return i } i++ fails++ - if fails >= 4+i>>4 && i < len(t) { + if fails >= 4+i>>4 && i < t { // Give up on IndexByte, it isn't skipping ahead // far enough to be better than Rabin-Karp. // Experiments (using IndexPeriodic) suggest diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go index 55a22bae22..f4c0ffd2a9 100644 --- a/src/bytes/bytes_test.go +++ b/src/bytes/bytes_test.go @@ -1362,6 +1362,12 @@ func TestReplace(t *testing.T) { if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] { t.Errorf("Replace(%q, %q, %q, %d) didn't copy", tt.in, tt.old, tt.new, tt.n) } + if tt.n == -1 { + out := ReplaceAll(in, []byte(tt.old), []byte(tt.new)) + if s := string(out); s != tt.out { + t.Errorf("ReplaceAll(%q, %q, %q) = %q, want %q", tt.in, tt.old, tt.new, s, tt.out) + } + } } } |
