Initial commit: Go 1.23 release state
This commit is contained in:
150
src/internal/stringslite/strings.go
Normal file
150
src/internal/stringslite/strings.go
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package stringslite implements a subset of strings,
|
||||
// only using packages that may be imported by "os".
|
||||
//
|
||||
// Tests for these functions are in the strings package.
|
||||
package stringslite
|
||||
|
||||
import (
|
||||
"internal/bytealg"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func HasPrefix(s, prefix string) bool {
|
||||
return len(s) >= len(prefix) && s[0:len(prefix)] == prefix
|
||||
}
|
||||
|
||||
func HasSuffix(s, suffix string) bool {
|
||||
return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
|
||||
}
|
||||
|
||||
func IndexByte(s string, c byte) int {
|
||||
return bytealg.IndexByteString(s, c)
|
||||
}
|
||||
|
||||
func Index(s, substr string) int {
|
||||
n := len(substr)
|
||||
switch {
|
||||
case n == 0:
|
||||
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):
|
||||
return -1
|
||||
case n <= bytealg.MaxLen:
|
||||
// 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
|
||||
}
|
||||
c0 := substr[0]
|
||||
c1 := substr[1]
|
||||
i := 0
|
||||
t := len(s) - n + 1
|
||||
fails := 0
|
||||
for i < t {
|
||||
if s[i] != c0 {
|
||||
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
|
||||
}
|
||||
i++
|
||||
fails++
|
||||
if fails >= 4+i>>4 && i < t {
|
||||
// See comment in ../bytes/bytes.go.
|
||||
j := bytealg.IndexRabinKarp(s[i:], substr)
|
||||
if j < 0 {
|
||||
return -1
|
||||
}
|
||||
return i + j
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func Cut(s, sep string) (before, after string, found bool) {
|
||||
if i := Index(s, sep); i >= 0 {
|
||||
return s[:i], s[i+len(sep):], true
|
||||
}
|
||||
return s, "", false
|
||||
}
|
||||
|
||||
func CutPrefix(s, prefix string) (after string, found bool) {
|
||||
if !HasPrefix(s, prefix) {
|
||||
return s, false
|
||||
}
|
||||
return s[len(prefix):], true
|
||||
}
|
||||
|
||||
func CutSuffix(s, suffix string) (before string, found bool) {
|
||||
if !HasSuffix(s, suffix) {
|
||||
return s, false
|
||||
}
|
||||
return s[:len(s)-len(suffix)], true
|
||||
}
|
||||
|
||||
func TrimPrefix(s, prefix string) string {
|
||||
if HasPrefix(s, prefix) {
|
||||
return s[len(prefix):]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func TrimSuffix(s, suffix string) string {
|
||||
if HasSuffix(s, suffix) {
|
||||
return s[:len(s)-len(suffix)]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func Clone(s string) string {
|
||||
if len(s) == 0 {
|
||||
return ""
|
||||
}
|
||||
b := make([]byte, len(s))
|
||||
copy(b, s)
|
||||
return unsafe.String(&b[0], len(b))
|
||||
}
|
||||
Reference in New Issue
Block a user