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]
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++
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 {