diff options
| author | Олег Световидов <olegsvetovidov@gmail.com> | 2026-02-03 11:02:27 +0300 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2026-02-04 12:19:11 -0800 |
| commit | 044fe174d7a45ab0c7872500de63e6c61b01bf27 (patch) | |
| tree | de912d908ae814d89b7ec9101d380ea48df045bd /src | |
| parent | f766b8da6c6e78bfbd549931ad44e0a2386a32ba (diff) | |
| download | go-044fe174d7a45ab0c7872500de63e6c61b01bf27.tar.xz | |
internal/stringslite: remove duplicate code in Index
Merge two nearly identical loops into one by selecting the fallback
method (IndexString vs IndexRabinKarp) inside the loop based on
whether n <= bytealg.MaxLen.
Fixes #77364#
Change-Id: Iefbef60922ca24e4dda3016127f54290096bcfed
Reviewed-on: https://go-review.googlesource.com/c/go/+/741340
Reviewed-by: Keith Randall <khr@golang.org>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/internal/stringslite/strings.go | 56 |
1 files changed, 14 insertions, 42 deletions
diff --git a/src/internal/stringslite/strings.go b/src/internal/stringslite/strings.go index 3a09e08cf4..6c825df5e4 100644 --- a/src/internal/stringslite/strings.go +++ b/src/internal/stringslite/strings.go @@ -28,52 +28,15 @@ func IndexByte(s string, c byte) int { func Index(s, substr string) int { n := len(substr) switch { - case n == 0: + case n == 0 || substr == s: return 0 case n == 1: return IndexByte(s, substr[0]) - case n == len(s): - if substr == s { - return 0 - } - return -1 - case n > len(s): + case n >= len(s): return -1 - case n <= bytealg.MaxLen: + case n <= bytealg.MaxLen && len(s) <= bytealg.MaxBruteForce: // Use brute force when s and substr both are small - if len(s) <= bytealg.MaxBruteForce { - return bytealg.IndexString(s, substr) - } - c0 := substr[0] - c1 := substr[1] - i := 0 - t := len(s) - n + 1 - fails := 0 - for i < t { - if s[i] != c0 { - // IndexByte is faster than bytealg.IndexString, so use it as long as - // we're not getting lots of false positives. - o := IndexByte(s[i+1:t], c0) - if o < 0 { - return -1 - } - i += o + 1 - } - if s[i+1] == c1 && s[i:i+n] == substr { - return i - } - fails++ - i++ - // Switch to bytealg.IndexString when IndexByte produces too many false positives. - if fails > bytealg.Cutover(i) { - r := bytealg.IndexString(s[i:], substr) - if r >= 0 { - return r + i - } - return -1 - } - } - return -1 + return bytealg.IndexString(s, substr) } c0 := substr[0] c1 := substr[1] @@ -82,6 +45,8 @@ func Index(s, substr string) int { fails := 0 for i < t { if s[i] != c0 { + // IndexByte is faster than bytealg.IndexString, so use it as long as + // we're not getting lots of false positives. o := IndexByte(s[i+1:t], c0) if o < 0 { return -1 @@ -93,7 +58,14 @@ func Index(s, substr string) int { } i++ fails++ - if fails >= 4+i>>4 && i < t { + if n <= bytealg.MaxLen && fails > bytealg.Cutover(i) { + // Switch to bytealg.IndexString when IndexByte produces too many false positives. + r := bytealg.IndexString(s[i:], substr) + if r >= 0 { + return r + i + } + return -1 + } else if fails >= 4+i>>4 && i < t { // See comment in ../bytes/bytes.go. j := bytealg.IndexRabinKarp(s[i:], substr) if j < 0 { |
