diff options
| -rw-r--r-- | api/next/71151.txt | 2 | ||||
| -rw-r--r-- | doc/next/6-stdlib/99-minor/bytes/71151.md | 3 | ||||
| -rw-r--r-- | doc/next/6-stdlib/99-minor/strings/71151.md | 3 | ||||
| -rw-r--r-- | src/bytes/bytes.go | 13 | ||||
| -rw-r--r-- | src/bytes/bytes_test.go | 21 | ||||
| -rw-r--r-- | src/strings/strings.go | 11 | ||||
| -rw-r--r-- | src/strings/strings_test.go | 21 |
7 files changed, 74 insertions, 0 deletions
diff --git a/api/next/71151.txt b/api/next/71151.txt new file mode 100644 index 0000000000..30ed124879 --- /dev/null +++ b/api/next/71151.txt @@ -0,0 +1,2 @@ +pkg bytes, func CutLast([]uint8, []uint8) ([]uint8, []uint8, bool) #71151 +pkg strings, func CutLast(string, string) (string, string, bool) #71151 diff --git a/doc/next/6-stdlib/99-minor/bytes/71151.md b/doc/next/6-stdlib/99-minor/bytes/71151.md new file mode 100644 index 0000000000..a86361ef5a --- /dev/null +++ b/doc/next/6-stdlib/99-minor/bytes/71151.md @@ -0,0 +1,3 @@ +The new [CutLast] function slices a []byte +around the last occurrence of a separator. +It can replace and simplify some common uses of LastIndex. diff --git a/doc/next/6-stdlib/99-minor/strings/71151.md b/doc/next/6-stdlib/99-minor/strings/71151.md new file mode 100644 index 0000000000..b979f84553 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/strings/71151.md @@ -0,0 +1,3 @@ +The new [CutLast] function slices a string +around the last occurrence of a separator. +It can replace and simplify some common uses of LastIndex.
\ No newline at end of file diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index 98f78f10c3..2bd1284296 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -1422,3 +1422,16 @@ func CutSuffix(s, suffix []byte) (before []byte, found bool) { } return s[:len(s)-len(suffix)], true } + +// CutLast slices s around the last 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, CutLast returns s, nil, false. +// +// CutLast returns slices of the original slice s, not copies. +func CutLast(s, sep []byte) (before, after []byte, found bool) { + if i := LastIndex(s, sep); i >= 0 { + return s[:i], s[i+len(sep):], true + } + return s, nil, false +} diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go index 07280464d2..20d333217e 100644 --- a/src/bytes/bytes_test.go +++ b/src/bytes/bytes_test.go @@ -1976,6 +1976,27 @@ func TestCut(t *testing.T) { } } +func TestCutLast(t *testing.T) { + tests := []struct { + s, sep string + before, after string + found bool + }{ + {"a/b/c", "/", "a/b", "c", true}, + {"a//b//c", "//", "a//b", "c", true}, + {"abc", "/", "abc", "", false}, + {"abc", "", "abc", "", true}, + {"", "", "", "", true}, + {"/abc", "/", "", "abc", true}, + {"abc/", "/", "abc", "", true}, + } + for _, tt := range tests { + if before, after, found := CutLast([]byte(tt.s), []byte(tt.sep)); string(before) != tt.before || string(after) != tt.after || found != tt.found { + t.Errorf("CutLast(%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 367e0a8e24..70297f1e69 100644 --- a/src/strings/strings.go +++ b/src/strings/strings.go @@ -1289,3 +1289,14 @@ func CutPrefix(s, prefix string) (after string, found bool) { func CutSuffix(s, suffix string) (before string, found bool) { return stringslite.CutSuffix(s, suffix) } + +// CutLast slices s around the last 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, CutLast returns s, "", false. +func CutLast(s, sep string) (before, after string, found bool) { + if i := LastIndex(s, sep); i >= 0 { + return s[:i], s[i+len(sep):], true + } + return s, "", false +} diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go index edfeb0e813..4ff3a2a825 100644 --- a/src/strings/strings_test.go +++ b/src/strings/strings_test.go @@ -1826,6 +1826,27 @@ func TestCut(t *testing.T) { } } +func TestCutLast(t *testing.T) { + tests := []struct { + s, sep string + before, after string + found bool + }{ + {"a/b/c", "/", "a/b", "c", true}, + {"a//b//c", "//", "a//b", "c", true}, + {"abc", "/", "abc", "", false}, + {"abc", "", "abc", "", true}, + {"", "", "", "", true}, + {"/abc", "/", "", "abc", true}, + {"abc/", "/", "abc", "", true}, + } + for _, tt := range tests { + if before, after, found := CutLast(tt.s, tt.sep); before != tt.before || after != tt.after || found != tt.found { + t.Errorf("CutLast(%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 |
