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>
This commit is contained in:
Олег Световидов 2026-02-03 11:02:27 +03:00 committed by Gopher Robot
parent f766b8da6c
commit 044fe174d7

View file

@ -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
}
case n >= len(s):
return -1
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 {