]> Cypherpunks repositories - gostls13.git/commitdiff
strings, bytes: add CutPrefix and CutSuffix
authorChangkun Ou <hi@changkun.de>
Thu, 19 May 2022 09:57:50 +0000 (11:57 +0200)
committerRobert Griesemer <gri@google.com>
Tue, 16 Aug 2022 19:48:39 +0000 (19:48 +0000)
Fixes #42537

Change-Id: Ie03c2614ffee30ebe707acad6b9f6c28fb134a45
Reviewed-on: https://go-review.googlesource.com/c/go/+/407176
Reviewed-by: Benny Siegert <bsiegert@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Changkun Ou <mail@changkun.de>
Reviewed-by: Ian Lance Taylor <iant@google.com>
api/next/42537.txt [new file with mode: 0644]
src/bytes/bytes.go
src/bytes/bytes_test.go
src/strings/strings.go
src/strings/strings_test.go

diff --git a/api/next/42537.txt b/api/next/42537.txt
new file mode 100644 (file)
index 0000000..4f2446a
--- /dev/null
@@ -0,0 +1,4 @@
+pkg bytes, func CutPrefix([]uint8, []uint8) ([]uint8, bool) #42537
+pkg bytes, func CutSuffix([]uint8, []uint8) ([]uint8, bool) #42537
+pkg strings, func CutPrefix(string, string) (string, bool) #42537
+pkg strings, func CutSuffix(string, string) (string, bool) #42537
\ No newline at end of file
index 27834fc6db723e5b378c96f52a7fa9f66d5db974..c0cd704180b0cd0944a9935267af4012404ac451 100644 (file)
@@ -1309,3 +1309,29 @@ func Clone(b []byte) []byte {
        }
        return append([]byte{}, b...)
 }
+
+// CutPrefix returns s without the provided leading prefix byte slice
+// and reports whether it found the prefix.
+// If s doesn't start with prefix, CutPrefix returns s, false.
+// If prefix is the empty byte slice, CutPrefix returns s, true.
+//
+// CutPrefix returns slices of the original slice s, not copies.
+func CutPrefix(s, prefix []byte) (after []byte, found bool) {
+       if !HasPrefix(s, prefix) {
+               return s, false
+       }
+       return s[len(prefix):], true
+}
+
+// CutSuffix returns s without the provided ending suffix byte slice
+// and reports whether it found the suffix.
+// If s doesn't end with suffix, CutSuffix returns s, false.
+// If suffix is the empty byte slice, CutSuffix returns s, true.
+//
+// CutSuffix returns slices of the original slice s, not copies.
+func CutSuffix(s, suffix []byte) (after []byte, found bool) {
+       if !HasSuffix(s, suffix) {
+               return s, false
+       }
+       return s[:len(s)-len(suffix)], true
+}
index 392657d1fada7a347d4b83b230e0b549f5ea2692..05c7ccc50a5e82805f10cfbd3041c7c9f7d5bb5d 100644 (file)
@@ -1700,6 +1700,48 @@ func TestCut(t *testing.T) {
        }
 }
 
+var cutPrefixTests = []struct {
+       s, sep string
+       after  string
+       found  bool
+}{
+       {"abc", "a", "bc", true},
+       {"abc", "abc", "", true},
+       {"abc", "", "abc", true},
+       {"abc", "d", "abc", false},
+       {"", "d", "", false},
+       {"", "", "", true},
+}
+
+func TestCutPrefix(t *testing.T) {
+       for _, tt := range cutPrefixTests {
+               if after, found := CutPrefix([]byte(tt.s), []byte(tt.sep)); string(after) != tt.after || found != tt.found {
+                       t.Errorf("CutPrefix(%q, %q) = %q, %v, want %q, %v", tt.s, tt.sep, after, found, tt.after, tt.found)
+               }
+       }
+}
+
+var cutSuffixTests = []struct {
+       s, sep string
+       after  string
+       found  bool
+}{
+       {"abc", "bc", "a", true},
+       {"abc", "abc", "", true},
+       {"abc", "", "abc", true},
+       {"abc", "d", "abc", false},
+       {"", "d", "", false},
+       {"", "", "", true},
+}
+
+func TestCutSuffix(t *testing.T) {
+       for _, tt := range cutSuffixTests {
+               if after, found := CutSuffix([]byte(tt.s), []byte(tt.sep)); string(after) != tt.after || found != tt.found {
+                       t.Errorf("CutSuffix(%q, %q) = %q, %v, want %q, %v", tt.s, tt.sep, after, found, tt.after, tt.found)
+               }
+       }
+}
+
 func TestBufferGrowNegative(t *testing.T) {
        defer func() {
                if err := recover(); err == nil {
index 013d71842647b7f188b3c6ddbe2f02f1fd3931e1..4ab78c326bc044a388d59989d5025a0b77eb2fbe 100644 (file)
@@ -1187,3 +1187,25 @@ func Cut(s, sep string) (before, after string, found bool) {
        }
        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.
+// If prefix is the empty string, CutPrefix returns s, true.
+func CutPrefix(s, prefix string) (after string, found bool) {
+       if !HasPrefix(s, prefix) {
+               return s, false
+       }
+       return s[len(prefix):], true
+}
+
+// CutSuffix returns s without the provided ending suffix string
+// and reports whether it found the suffix.
+// If s doesn't end with suffix, CutSuffix returns s, false.
+// If suffix is the empty string, CutSuffix returns s, true.
+func CutSuffix(s, suffix string) (after string, found bool) {
+       if !HasSuffix(s, suffix) {
+               return s, false
+       }
+       return s[:len(s)-len(suffix)], true
+}
index a1604c2c47328d2e853dfeb1d79c22fddc796cfa..d6153aa22634ae025e144578a2547d1c9c139769 100644 (file)
@@ -1611,6 +1611,48 @@ func TestCut(t *testing.T) {
        }
 }
 
+var cutPrefixTests = []struct {
+       s, sep string
+       after  string
+       found  bool
+}{
+       {"abc", "a", "bc", true},
+       {"abc", "abc", "", true},
+       {"abc", "", "abc", true},
+       {"abc", "d", "abc", false},
+       {"", "d", "", false},
+       {"", "", "", true},
+}
+
+func TestCutPrefix(t *testing.T) {
+       for _, tt := range cutPrefixTests {
+               if after, found := CutPrefix(tt.s, tt.sep); after != tt.after || found != tt.found {
+                       t.Errorf("CutPrefix(%q, %q) = %q, %v, want %q, %v", tt.s, tt.sep, after, found, tt.after, tt.found)
+               }
+       }
+}
+
+var cutSuffixTests = []struct {
+       s, sep string
+       after  string
+       found  bool
+}{
+       {"abc", "bc", "a", true},
+       {"abc", "abc", "", true},
+       {"abc", "", "abc", true},
+       {"abc", "d", "abc", false},
+       {"", "d", "", false},
+       {"", "", "", true},
+}
+
+func TestCutSuffix(t *testing.T) {
+       for _, tt := range cutSuffixTests {
+               if after, found := CutSuffix(tt.s, tt.sep); after != tt.after || found != tt.found {
+                       t.Errorf("CutSuffix(%q, %q) = %q, %v, want %q, %v", tt.s, tt.sep, after, found, tt.after, tt.found)
+               }
+       }
+}
+
 func makeBenchInputHard() string {
        tokens := [...]string{
                "<a>", "<p>", "<b>", "<strong>",