diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index 1871814c6e0..9c3c7fb0f4e 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -1336,6 +1336,19 @@ func Cut(s, sep []byte) (before, after []byte, found bool) { return s, nil, false } +// CutByte slices s around the first instance of sep, +// returning the text before and after sep. +// The found result reports whether sep appears in s. +// If sep does not appear in s, cut returns s, nil, false. +// +// CutByte returns slices of the original slice s, not copies. +func CutByte(s []byte, sep byte) (before, after []byte, found bool) { + if i := IndexByte(s, sep); i >= 0 { + return s[:i], s[i+1:], true + } + return s, nil, false +} + // Clone returns a copy of b[:len(b)]. // The result may have additional unused capacity. // Clone(nil) returns nil. diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go index 5e8cf85fd90..312a7cbdec0 100644 --- a/src/bytes/bytes_test.go +++ b/src/bytes/bytes_test.go @@ -1742,6 +1742,26 @@ func TestCut(t *testing.T) { } } +var cutByteTests = []struct { + s string + sep byte + before, after string + found bool +}{ + {"abc", 'b', "a", "c", true}, + {"abc", 'a', "", "bc", true}, + {"abc", 'c', "ab", "", true}, + {"", 'd', "", "", false}, +} + +func TestCutByte(t *testing.T) { + for _, tt := range cutByteTests { + if before, after, found := CutByte([]byte(tt.s), tt.sep); string(before) != tt.before || string(after) != tt.after || found != tt.found { + t.Errorf("Cut(%q, %q) = %q, %q, %v, want %q, %q, %v", tt.s, tt.sep, before, after, found, tt.before, tt.after, tt.found) + } + } +} + var cutPrefixTests = []struct { s, sep string after string diff --git a/src/strings/strings.go b/src/strings/strings.go index f53ae1f9a78..85fb6215351 100644 --- a/src/strings/strings.go +++ b/src/strings/strings.go @@ -1315,6 +1315,17 @@ func Cut(s, sep string) (before, after string, found bool) { return s, "", false } +// CutByte slices s around the first instance of sep, +// returning the text before and after sep. +// The found result reports whether sep appears in s. +// If sep does not appear in s, cut returns s, "", false. +func CutByte(s string, sep byte) (before, after string, found bool) { + if i := IndexByte(s, sep); i >= 0 { + return s[:i], s[i+1:], true + } + return s, "", false +} + // CutPrefix returns s without the provided leading prefix string // and reports whether it found the prefix. // If s doesn't start with prefix, CutPrefix returns s, false. diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go index ac493c7dcd4..73c0655158f 100644 --- a/src/strings/strings_test.go +++ b/src/strings/strings_test.go @@ -1669,6 +1669,26 @@ func TestCut(t *testing.T) { } } +var cutByteTests = []struct { + s string + sep byte + before, after string + found bool +}{ + {"abc", 'b', "a", "c", true}, + {"abc", 'a', "", "bc", true}, + {"abc", 'c', "ab", "", true}, + {"", 'd', "", "", false}, +} + +func TestCutByte(t *testing.T) { + for _, tt := range cutByteTests { + if before, after, found := CutByte(tt.s, tt.sep); before != tt.before || after != tt.after || found != tt.found { + t.Errorf("Cut(%q, %q) = %q, %q, %v, want %q, %q, %v", tt.s, tt.sep, before, after, found, tt.before, tt.after, tt.found) + } + } +} + var cutPrefixTests = []struct { s, sep string after string