// non-overlapping instances of old replaced by new.
// If n < 0, there is no limit on the number of replacements.
func Replace(s, old, new []byte, n int) []byte {
- if n == 0 {
- return s // avoid allocation
- }
- // Compute number of replacements.
- if m := Count(s, old); m == 0 {
- return s // avoid allocation
- } else if n <= 0 || m < n {
+ m := 0
+ if n != 0 {
+ // Compute number of replacements.
+ m = Count(s, old)
+ }
+ if m == 0 {
+ // Nothing to do. Just copy.
+ t := make([]byte, len(s))
+ copy(t, s)
+ return t
+ }
+ if n < 0 || m < n {
n = m
}
func TestReplace(t *testing.T) {
for _, tt := range ReplaceTests {
- if s := string(Replace([]byte(tt.in), []byte(tt.old), []byte(tt.new), tt.n)); s != tt.out {
+ in := append([]byte(tt.in), []byte("<spare>")...)
+ in = in[:len(tt.in)]
+ out := Replace(in, []byte(tt.old), []byte(tt.new), tt.n)
+ if s := string(out); s != tt.out {
t.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt.in, tt.old, tt.new, tt.n, s, tt.out)
}
+ 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)
+ }
}
}