aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorОлег Световидов <olegsvetovidov@gmail.com>2026-02-03 11:02:27 +0300
committerGopher Robot <gobot@golang.org>2026-02-04 12:19:11 -0800
commit044fe174d7a45ab0c7872500de63e6c61b01bf27 (patch)
treede912d908ae814d89b7ec9101d380ea48df045bd /src
parentf766b8da6c6e78bfbd549931ad44e0a2386a32ba (diff)
downloadgo-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.go56
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 {