| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | package stringslite |
| |
|
| | import ( |
| | "internal/bytealg" |
| | "unsafe" |
| | ) |
| |
|
| | func HasPrefix(s, prefix string) bool { |
| | return len(s) >= len(prefix) && s[: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: |
| | |
| | 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 { |
| | |
| | |
| | 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++ |
| | |
| | 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 { |
| | |
| | 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)) |
| | } |
| |
|