1
2
3
4
5
6
7
8
9 package stringslite
10
11 import (
12 "internal/bytealg"
13 "unsafe"
14 )
15
16 func HasPrefix(s, prefix string) bool {
17 return len(s) >= len(prefix) && s[:len(prefix)] == prefix
18 }
19
20 func HasSuffix(s, suffix string) bool {
21 return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
22 }
23
24 func IndexByte(s string, c byte) int {
25 return bytealg.IndexByteString(s, c)
26 }
27
28 func Index(s, substr string) int {
29 n := len(substr)
30 switch {
31 case n == 0 || substr == s:
32 return 0
33 case n == 1:
34 return IndexByte(s, substr[0])
35 case n >= len(s):
36 return -1
37 case n <= bytealg.MaxLen && len(s) <= bytealg.MaxBruteForce:
38
39 return bytealg.IndexString(s, substr)
40 }
41 c0 := substr[0]
42 c1 := substr[1]
43 i := 0
44 t := len(s) - n + 1
45 fails := 0
46 for i < t {
47 if s[i] != c0 {
48
49
50 o := IndexByte(s[i+1:t], c0)
51 if o < 0 {
52 return -1
53 }
54 i += o + 1
55 }
56 if s[i+1] == c1 && s[i:i+n] == substr {
57 return i
58 }
59 i++
60 fails++
61 if n <= bytealg.MaxLen && fails > bytealg.Cutover(i) {
62
63 r := bytealg.IndexString(s[i:], substr)
64 if r >= 0 {
65 return r + i
66 }
67 return -1
68 } else if n > bytealg.MaxLen && fails >= 4+i>>4 && i < t {
69
70 j := bytealg.IndexRabinKarp(s[i:], substr)
71 if j < 0 {
72 return -1
73 }
74 return i + j
75 }
76 }
77 return -1
78 }
79
80 func Cut(s, sep string) (before, after string, found bool) {
81 if i := Index(s, sep); i >= 0 {
82 return s[:i], s[i+len(sep):], true
83 }
84 return s, "", false
85 }
86
87 func CutPrefix(s, prefix string) (after string, found bool) {
88 if !HasPrefix(s, prefix) {
89 return s, false
90 }
91 return s[len(prefix):], true
92 }
93
94 func CutSuffix(s, suffix string) (before string, found bool) {
95 if !HasSuffix(s, suffix) {
96 return s, false
97 }
98 return s[:len(s)-len(suffix)], true
99 }
100
101 func TrimPrefix(s, prefix string) string {
102 if HasPrefix(s, prefix) {
103 return s[len(prefix):]
104 }
105 return s
106 }
107
108 func TrimSuffix(s, suffix string) string {
109 if HasSuffix(s, suffix) {
110 return s[:len(s)-len(suffix)]
111 }
112 return s
113 }
114
115
116
117 func IsSpace(r rune) bool {
118 switch r {
119 case '\t', '\n', '\v', '\f', '\r', ' ',
120 0x0085,
121 0x00A0,
122 0x1680,
123 0x2000,
124 0x2001,
125 0x2002,
126 0x2003,
127 0x2004,
128 0x2005,
129 0x2006,
130 0x2007,
131 0x2008,
132 0x2009,
133 0x200A,
134 0x2028,
135 0x2029,
136 0x202F,
137 0x205F,
138 0x3000:
139 return true
140 }
141 return false
142 }
143
144 func Clone(s string) string {
145 if len(s) == 0 {
146 return ""
147 }
148 b := make([]byte, len(s))
149 copy(b, s)
150 return unsafe.String(&b[0], len(b))
151 }
152
View as plain text