Source file
src/strings/strings.go
1
2
3
4
5
6
7
8 package strings
9
10 import (
11 "internal/bytealg"
12 "unicode"
13 "unicode/utf8"
14 )
15
16 const maxInt = int(^uint(0) >> 1)
17
18
19
20
21 func explode(s string, n int) []string {
22 l := utf8.RuneCountInString(s)
23 if n < 0 || n > l {
24 n = l
25 }
26 a := make([]string, n)
27 for i := 0; i < n-1; i++ {
28 _, size := utf8.DecodeRuneInString(s)
29 a[i] = s[:size]
30 s = s[size:]
31 }
32 if n > 0 {
33 a[n-1] = s
34 }
35 return a
36 }
37
38
39
40 func Count(s, substr string) int {
41
42 if len(substr) == 0 {
43 return utf8.RuneCountInString(s) + 1
44 }
45 if len(substr) == 1 {
46 return bytealg.CountString(s, substr[0])
47 }
48 n := 0
49 for {
50 i := Index(s, substr)
51 if i == -1 {
52 return n
53 }
54 n++
55 s = s[i+len(substr):]
56 }
57 }
58
59
60 func Contains(s, substr string) bool {
61 return Index(s, substr) >= 0
62 }
63
64
65 func ContainsAny(s, chars string) bool {
66 return IndexAny(s, chars) >= 0
67 }
68
69
70 func ContainsRune(s string, r rune) bool {
71 return IndexRune(s, r) >= 0
72 }
73
74
75 func ContainsFunc(s string, f func(rune) bool) bool {
76 return IndexFunc(s, f) >= 0
77 }
78
79
80 func LastIndex(s, substr string) int {
81 n := len(substr)
82 switch {
83 case n == 0:
84 return len(s)
85 case n == 1:
86 return LastIndexByte(s, substr[0])
87 case n == len(s):
88 if substr == s {
89 return 0
90 }
91 return -1
92 case n > len(s):
93 return -1
94 }
95
96 hashss, pow := bytealg.HashStrRev(substr)
97 last := len(s) - n
98 var h uint32
99 for i := len(s) - 1; i >= last; i-- {
100 h = h*bytealg.PrimeRK + uint32(s[i])
101 }
102 if h == hashss && s[last:] == substr {
103 return last
104 }
105 for i := last - 1; i >= 0; i-- {
106 h *= bytealg.PrimeRK
107 h += uint32(s[i])
108 h -= pow * uint32(s[i+n])
109 if h == hashss && s[i:i+n] == substr {
110 return i
111 }
112 }
113 return -1
114 }
115
116
117 func IndexByte(s string, c byte) int {
118 return bytealg.IndexByteString(s, c)
119 }
120
121
122
123
124
125 func IndexRune(s string, r rune) int {
126 switch {
127 case 0 <= r && r < utf8.RuneSelf:
128 return IndexByte(s, byte(r))
129 case r == utf8.RuneError:
130 for i, r := range s {
131 if r == utf8.RuneError {
132 return i
133 }
134 }
135 return -1
136 case !utf8.ValidRune(r):
137 return -1
138 default:
139 return Index(s, string(r))
140 }
141 }
142
143
144
145 func IndexAny(s, chars string) int {
146 if chars == "" {
147
148 return -1
149 }
150 if len(chars) == 1 {
151
152 r := rune(chars[0])
153 if r >= utf8.RuneSelf {
154 r = utf8.RuneError
155 }
156 return IndexRune(s, r)
157 }
158 if len(s) > 8 {
159 if as, isASCII := makeASCIISet(chars); isASCII {
160 for i := 0; i < len(s); i++ {
161 if as.contains(s[i]) {
162 return i
163 }
164 }
165 return -1
166 }
167 }
168 for i, c := range s {
169 if IndexRune(chars, c) >= 0 {
170 return i
171 }
172 }
173 return -1
174 }
175
176
177
178
179 func LastIndexAny(s, chars string) int {
180 if chars == "" {
181
182 return -1
183 }
184 if len(s) == 1 {
185 rc := rune(s[0])
186 if rc >= utf8.RuneSelf {
187 rc = utf8.RuneError
188 }
189 if IndexRune(chars, rc) >= 0 {
190 return 0
191 }
192 return -1
193 }
194 if len(s) > 8 {
195 if as, isASCII := makeASCIISet(chars); isASCII {
196 for i := len(s) - 1; i >= 0; i-- {
197 if as.contains(s[i]) {
198 return i
199 }
200 }
201 return -1
202 }
203 }
204 if len(chars) == 1 {
205 rc := rune(chars[0])
206 if rc >= utf8.RuneSelf {
207 rc = utf8.RuneError
208 }
209 for i := len(s); i > 0; {
210 r, size := utf8.DecodeLastRuneInString(s[:i])
211 i -= size
212 if rc == r {
213 return i
214 }
215 }
216 return -1
217 }
218 for i := len(s); i > 0; {
219 r, size := utf8.DecodeLastRuneInString(s[:i])
220 i -= size
221 if IndexRune(chars, r) >= 0 {
222 return i
223 }
224 }
225 return -1
226 }
227
228
229 func LastIndexByte(s string, c byte) int {
230 for i := len(s) - 1; i >= 0; i-- {
231 if s[i] == c {
232 return i
233 }
234 }
235 return -1
236 }
237
238
239
240 func genSplit(s, sep string, sepSave, n int) []string {
241 if n == 0 {
242 return nil
243 }
244 if sep == "" {
245 return explode(s, n)
246 }
247 if n < 0 {
248 n = Count(s, sep) + 1
249 }
250
251 if n > len(s)+1 {
252 n = len(s) + 1
253 }
254 a := make([]string, n)
255 n--
256 i := 0
257 for i < n {
258 m := Index(s, sep)
259 if m < 0 {
260 break
261 }
262 a[i] = s[:m+sepSave]
263 s = s[m+len(sep):]
264 i++
265 }
266 a[i] = s
267 return a[:i+1]
268 }
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283 func SplitN(s, sep string, n int) []string { return genSplit(s, sep, 0, n) }
284
285
286
287
288
289
290
291
292
293
294
295
296 func SplitAfterN(s, sep string, n int) []string {
297 return genSplit(s, sep, len(sep), n)
298 }
299
300
301
302
303
304
305
306
307
308
309
310
311
312 func Split(s, sep string) []string { return genSplit(s, sep, 0, -1) }
313
314
315
316
317
318
319
320
321
322
323
324 func SplitAfter(s, sep string) []string {
325 return genSplit(s, sep, len(sep), -1)
326 }
327
328 var asciiSpace = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1}
329
330
331
332
333 func Fields(s string) []string {
334
335
336 n := 0
337 wasSpace := 1
338
339 setBits := uint8(0)
340 for i := 0; i < len(s); i++ {
341 r := s[i]
342 setBits |= r
343 isSpace := int(asciiSpace[r])
344 n += wasSpace & ^isSpace
345 wasSpace = isSpace
346 }
347
348 if setBits >= utf8.RuneSelf {
349
350 return FieldsFunc(s, unicode.IsSpace)
351 }
352
353 a := make([]string, n)
354 na := 0
355 fieldStart := 0
356 i := 0
357
358 for i < len(s) && asciiSpace[s[i]] != 0 {
359 i++
360 }
361 fieldStart = i
362 for i < len(s) {
363 if asciiSpace[s[i]] == 0 {
364 i++
365 continue
366 }
367 a[na] = s[fieldStart:i]
368 na++
369 i++
370
371 for i < len(s) && asciiSpace[s[i]] != 0 {
372 i++
373 }
374 fieldStart = i
375 }
376 if fieldStart < len(s) {
377 a[na] = s[fieldStart:]
378 }
379 return a
380 }
381
382
383
384
385
386
387
388 func FieldsFunc(s string, f func(rune) bool) []string {
389
390
391 type span struct {
392 start int
393 end int
394 }
395 spans := make([]span, 0, 32)
396
397
398
399
400
401 start := -1
402 for end, rune := range s {
403 if f(rune) {
404 if start >= 0 {
405 spans = append(spans, span{start, end})
406
407
408
409 start = ^start
410 }
411 } else {
412 if start < 0 {
413 start = end
414 }
415 }
416 }
417
418
419 if start >= 0 {
420 spans = append(spans, span{start, len(s)})
421 }
422
423
424 a := make([]string, len(spans))
425 for i, span := range spans {
426 a[i] = s[span.start:span.end]
427 }
428
429 return a
430 }
431
432
433
434 func Join(elems []string, sep string) string {
435 switch len(elems) {
436 case 0:
437 return ""
438 case 1:
439 return elems[0]
440 }
441
442 var n int
443 if len(sep) > 0 {
444 if len(sep) >= maxInt/(len(elems)-1) {
445 panic("strings: Join output length overflow")
446 }
447 n += len(sep) * (len(elems) - 1)
448 }
449 for _, elem := range elems {
450 if len(elem) > maxInt-n {
451 panic("strings: Join output length overflow")
452 }
453 n += len(elem)
454 }
455
456 var b Builder
457 b.Grow(n)
458 b.WriteString(elems[0])
459 for _, s := range elems[1:] {
460 b.WriteString(sep)
461 b.WriteString(s)
462 }
463 return b.String()
464 }
465
466
467 func HasPrefix(s, prefix string) bool {
468 return len(s) >= len(prefix) && s[0:len(prefix)] == prefix
469 }
470
471
472 func HasSuffix(s, suffix string) bool {
473 return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
474 }
475
476
477
478
479 func Map(mapping func(rune) rune, s string) string {
480
481
482
483
484
485
486 var b Builder
487
488 for i, c := range s {
489 r := mapping(c)
490 if r == c && c != utf8.RuneError {
491 continue
492 }
493
494 var width int
495 if c == utf8.RuneError {
496 c, width = utf8.DecodeRuneInString(s[i:])
497 if width != 1 && r == c {
498 continue
499 }
500 } else {
501 width = utf8.RuneLen(c)
502 }
503
504 b.Grow(len(s) + utf8.UTFMax)
505 b.WriteString(s[:i])
506 if r >= 0 {
507 b.WriteRune(r)
508 }
509
510 s = s[i+width:]
511 break
512 }
513
514
515 if b.Cap() == 0 {
516 return s
517 }
518
519 for _, c := range s {
520 r := mapping(c)
521
522 if r >= 0 {
523
524
525
526 if r < utf8.RuneSelf {
527 b.WriteByte(byte(r))
528 } else {
529
530 b.WriteRune(r)
531 }
532 }
533 }
534
535 return b.String()
536 }
537
538
539
540
541
542 func Repeat(s string, count int) string {
543 switch count {
544 case 0:
545 return ""
546 case 1:
547 return s
548 }
549
550
551
552
553 if count < 0 {
554 panic("strings: negative Repeat count")
555 }
556 if len(s) >= maxInt/count {
557 panic("strings: Repeat output length overflow")
558 }
559 n := len(s) * count
560
561 if len(s) == 0 {
562 return ""
563 }
564
565
566
567
568
569
570
571
572
573
574
575 const chunkLimit = 8 * 1024
576 chunkMax := n
577 if n > chunkLimit {
578 chunkMax = chunkLimit / len(s) * len(s)
579 if chunkMax == 0 {
580 chunkMax = len(s)
581 }
582 }
583
584 var b Builder
585 b.Grow(n)
586 b.WriteString(s)
587 for b.Len() < n {
588 chunk := n - b.Len()
589 if chunk > b.Len() {
590 chunk = b.Len()
591 }
592 if chunk > chunkMax {
593 chunk = chunkMax
594 }
595 b.WriteString(b.String()[:chunk])
596 }
597 return b.String()
598 }
599
600
601 func ToUpper(s string) string {
602 isASCII, hasLower := true, false
603 for i := 0; i < len(s); i++ {
604 c := s[i]
605 if c >= utf8.RuneSelf {
606 isASCII = false
607 break
608 }
609 hasLower = hasLower || ('a' <= c && c <= 'z')
610 }
611
612 if isASCII {
613 if !hasLower {
614 return s
615 }
616 var (
617 b Builder
618 pos int
619 )
620 b.Grow(len(s))
621 for i := 0; i < len(s); i++ {
622 c := s[i]
623 if 'a' <= c && c <= 'z' {
624 c -= 'a' - 'A'
625 if pos < i {
626 b.WriteString(s[pos:i])
627 }
628 b.WriteByte(c)
629 pos = i + 1
630 }
631 }
632 if pos < len(s) {
633 b.WriteString(s[pos:])
634 }
635 return b.String()
636 }
637 return Map(unicode.ToUpper, s)
638 }
639
640
641 func ToLower(s string) string {
642 isASCII, hasUpper := true, false
643 for i := 0; i < len(s); i++ {
644 c := s[i]
645 if c >= utf8.RuneSelf {
646 isASCII = false
647 break
648 }
649 hasUpper = hasUpper || ('A' <= c && c <= 'Z')
650 }
651
652 if isASCII {
653 if !hasUpper {
654 return s
655 }
656 var (
657 b Builder
658 pos int
659 )
660 b.Grow(len(s))
661 for i := 0; i < len(s); i++ {
662 c := s[i]
663 if 'A' <= c && c <= 'Z' {
664 c += 'a' - 'A'
665 if pos < i {
666 b.WriteString(s[pos:i])
667 }
668 b.WriteByte(c)
669 pos = i + 1
670 }
671 }
672 if pos < len(s) {
673 b.WriteString(s[pos:])
674 }
675 return b.String()
676 }
677 return Map(unicode.ToLower, s)
678 }
679
680
681
682 func ToTitle(s string) string { return Map(unicode.ToTitle, s) }
683
684
685
686 func ToUpperSpecial(c unicode.SpecialCase, s string) string {
687 return Map(c.ToUpper, s)
688 }
689
690
691
692 func ToLowerSpecial(c unicode.SpecialCase, s string) string {
693 return Map(c.ToLower, s)
694 }
695
696
697
698 func ToTitleSpecial(c unicode.SpecialCase, s string) string {
699 return Map(c.ToTitle, s)
700 }
701
702
703
704 func ToValidUTF8(s, replacement string) string {
705 var b Builder
706
707 for i, c := range s {
708 if c != utf8.RuneError {
709 continue
710 }
711
712 _, wid := utf8.DecodeRuneInString(s[i:])
713 if wid == 1 {
714 b.Grow(len(s) + len(replacement))
715 b.WriteString(s[:i])
716 s = s[i:]
717 break
718 }
719 }
720
721
722 if b.Cap() == 0 {
723 return s
724 }
725
726 invalid := false
727 for i := 0; i < len(s); {
728 c := s[i]
729 if c < utf8.RuneSelf {
730 i++
731 invalid = false
732 b.WriteByte(c)
733 continue
734 }
735 _, wid := utf8.DecodeRuneInString(s[i:])
736 if wid == 1 {
737 i++
738 if !invalid {
739 invalid = true
740 b.WriteString(replacement)
741 }
742 continue
743 }
744 invalid = false
745 b.WriteString(s[i : i+wid])
746 i += wid
747 }
748
749 return b.String()
750 }
751
752
753
754 func isSeparator(r rune) bool {
755
756 if r <= 0x7F {
757 switch {
758 case '0' <= r && r <= '9':
759 return false
760 case 'a' <= r && r <= 'z':
761 return false
762 case 'A' <= r && r <= 'Z':
763 return false
764 case r == '_':
765 return false
766 }
767 return true
768 }
769
770 if unicode.IsLetter(r) || unicode.IsDigit(r) {
771 return false
772 }
773
774 return unicode.IsSpace(r)
775 }
776
777
778
779
780
781
782 func Title(s string) string {
783
784
785
786 prev := ' '
787 return Map(
788 func(r rune) rune {
789 if isSeparator(prev) {
790 prev = r
791 return unicode.ToTitle(r)
792 }
793 prev = r
794 return r
795 },
796 s)
797 }
798
799
800
801 func TrimLeftFunc(s string, f func(rune) bool) string {
802 i := indexFunc(s, f, false)
803 if i == -1 {
804 return ""
805 }
806 return s[i:]
807 }
808
809
810
811 func TrimRightFunc(s string, f func(rune) bool) string {
812 i := lastIndexFunc(s, f, false)
813 if i >= 0 && s[i] >= utf8.RuneSelf {
814 _, wid := utf8.DecodeRuneInString(s[i:])
815 i += wid
816 } else {
817 i++
818 }
819 return s[0:i]
820 }
821
822
823
824 func TrimFunc(s string, f func(rune) bool) string {
825 return TrimRightFunc(TrimLeftFunc(s, f), f)
826 }
827
828
829
830 func IndexFunc(s string, f func(rune) bool) int {
831 return indexFunc(s, f, true)
832 }
833
834
835
836 func LastIndexFunc(s string, f func(rune) bool) int {
837 return lastIndexFunc(s, f, true)
838 }
839
840
841
842
843 func indexFunc(s string, f func(rune) bool, truth bool) int {
844 for i, r := range s {
845 if f(r) == truth {
846 return i
847 }
848 }
849 return -1
850 }
851
852
853
854
855 func lastIndexFunc(s string, f func(rune) bool, truth bool) int {
856 for i := len(s); i > 0; {
857 r, size := utf8.DecodeLastRuneInString(s[0:i])
858 i -= size
859 if f(r) == truth {
860 return i
861 }
862 }
863 return -1
864 }
865
866
867
868
869
870
871
872
873
874 type asciiSet [8]uint32
875
876
877
878 func makeASCIISet(chars string) (as asciiSet, ok bool) {
879 for i := 0; i < len(chars); i++ {
880 c := chars[i]
881 if c >= utf8.RuneSelf {
882 return as, false
883 }
884 as[c/32] |= 1 << (c % 32)
885 }
886 return as, true
887 }
888
889
890 func (as *asciiSet) contains(c byte) bool {
891 return (as[c/32] & (1 << (c % 32))) != 0
892 }
893
894
895
896 func Trim(s, cutset string) string {
897 if s == "" || cutset == "" {
898 return s
899 }
900 if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
901 return trimLeftByte(trimRightByte(s, cutset[0]), cutset[0])
902 }
903 if as, ok := makeASCIISet(cutset); ok {
904 return trimLeftASCII(trimRightASCII(s, &as), &as)
905 }
906 return trimLeftUnicode(trimRightUnicode(s, cutset), cutset)
907 }
908
909
910
911
912
913 func TrimLeft(s, cutset string) string {
914 if s == "" || cutset == "" {
915 return s
916 }
917 if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
918 return trimLeftByte(s, cutset[0])
919 }
920 if as, ok := makeASCIISet(cutset); ok {
921 return trimLeftASCII(s, &as)
922 }
923 return trimLeftUnicode(s, cutset)
924 }
925
926 func trimLeftByte(s string, c byte) string {
927 for len(s) > 0 && s[0] == c {
928 s = s[1:]
929 }
930 return s
931 }
932
933 func trimLeftASCII(s string, as *asciiSet) string {
934 for len(s) > 0 {
935 if !as.contains(s[0]) {
936 break
937 }
938 s = s[1:]
939 }
940 return s
941 }
942
943 func trimLeftUnicode(s, cutset string) string {
944 for len(s) > 0 {
945 r, n := rune(s[0]), 1
946 if r >= utf8.RuneSelf {
947 r, n = utf8.DecodeRuneInString(s)
948 }
949 if !ContainsRune(cutset, r) {
950 break
951 }
952 s = s[n:]
953 }
954 return s
955 }
956
957
958
959
960
961 func TrimRight(s, cutset string) string {
962 if s == "" || cutset == "" {
963 return s
964 }
965 if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
966 return trimRightByte(s, cutset[0])
967 }
968 if as, ok := makeASCIISet(cutset); ok {
969 return trimRightASCII(s, &as)
970 }
971 return trimRightUnicode(s, cutset)
972 }
973
974 func trimRightByte(s string, c byte) string {
975 for len(s) > 0 && s[len(s)-1] == c {
976 s = s[:len(s)-1]
977 }
978 return s
979 }
980
981 func trimRightASCII(s string, as *asciiSet) string {
982 for len(s) > 0 {
983 if !as.contains(s[len(s)-1]) {
984 break
985 }
986 s = s[:len(s)-1]
987 }
988 return s
989 }
990
991 func trimRightUnicode(s, cutset string) string {
992 for len(s) > 0 {
993 r, n := rune(s[len(s)-1]), 1
994 if r >= utf8.RuneSelf {
995 r, n = utf8.DecodeLastRuneInString(s)
996 }
997 if !ContainsRune(cutset, r) {
998 break
999 }
1000 s = s[:len(s)-n]
1001 }
1002 return s
1003 }
1004
1005
1006
1007 func TrimSpace(s string) string {
1008
1009 start := 0
1010 for ; start < len(s); start++ {
1011 c := s[start]
1012 if c >= utf8.RuneSelf {
1013
1014
1015 return TrimFunc(s[start:], unicode.IsSpace)
1016 }
1017 if asciiSpace[c] == 0 {
1018 break
1019 }
1020 }
1021
1022
1023 stop := len(s)
1024 for ; stop > start; stop-- {
1025 c := s[stop-1]
1026 if c >= utf8.RuneSelf {
1027
1028 return TrimRightFunc(s[start:stop], unicode.IsSpace)
1029 }
1030 if asciiSpace[c] == 0 {
1031 break
1032 }
1033 }
1034
1035
1036
1037
1038 return s[start:stop]
1039 }
1040
1041
1042
1043 func TrimPrefix(s, prefix string) string {
1044 if HasPrefix(s, prefix) {
1045 return s[len(prefix):]
1046 }
1047 return s
1048 }
1049
1050
1051
1052 func TrimSuffix(s, suffix string) string {
1053 if HasSuffix(s, suffix) {
1054 return s[:len(s)-len(suffix)]
1055 }
1056 return s
1057 }
1058
1059
1060
1061
1062
1063
1064
1065 func Replace(s, old, new string, n int) string {
1066 if old == new || n == 0 {
1067 return s
1068 }
1069
1070
1071 if m := Count(s, old); m == 0 {
1072 return s
1073 } else if n < 0 || m < n {
1074 n = m
1075 }
1076
1077
1078 var b Builder
1079 b.Grow(len(s) + n*(len(new)-len(old)))
1080 start := 0
1081 for i := 0; i < n; i++ {
1082 j := start
1083 if len(old) == 0 {
1084 if i > 0 {
1085 _, wid := utf8.DecodeRuneInString(s[start:])
1086 j += wid
1087 }
1088 } else {
1089 j += Index(s[start:], old)
1090 }
1091 b.WriteString(s[start:j])
1092 b.WriteString(new)
1093 start = j + len(old)
1094 }
1095 b.WriteString(s[start:])
1096 return b.String()
1097 }
1098
1099
1100
1101
1102
1103
1104 func ReplaceAll(s, old, new string) string {
1105 return Replace(s, old, new, -1)
1106 }
1107
1108
1109
1110
1111 func EqualFold(s, t string) bool {
1112
1113 i := 0
1114 for ; i < len(s) && i < len(t); i++ {
1115 sr := s[i]
1116 tr := t[i]
1117 if sr|tr >= utf8.RuneSelf {
1118 goto hasUnicode
1119 }
1120
1121
1122 if tr == sr {
1123 continue
1124 }
1125
1126
1127 if tr < sr {
1128 tr, sr = sr, tr
1129 }
1130
1131 if 'A' <= sr && sr <= 'Z' && tr == sr+'a'-'A' {
1132 continue
1133 }
1134 return false
1135 }
1136
1137 return len(s) == len(t)
1138
1139 hasUnicode:
1140 s = s[i:]
1141 t = t[i:]
1142 for _, sr := range s {
1143
1144 if len(t) == 0 {
1145 return false
1146 }
1147
1148
1149 var tr rune
1150 if t[0] < utf8.RuneSelf {
1151 tr, t = rune(t[0]), t[1:]
1152 } else {
1153 r, size := utf8.DecodeRuneInString(t)
1154 tr, t = r, t[size:]
1155 }
1156
1157
1158
1159
1160 if tr == sr {
1161 continue
1162 }
1163
1164
1165 if tr < sr {
1166 tr, sr = sr, tr
1167 }
1168
1169 if tr < utf8.RuneSelf {
1170
1171 if 'A' <= sr && sr <= 'Z' && tr == sr+'a'-'A' {
1172 continue
1173 }
1174 return false
1175 }
1176
1177
1178
1179 r := unicode.SimpleFold(sr)
1180 for r != sr && r < tr {
1181 r = unicode.SimpleFold(r)
1182 }
1183 if r == tr {
1184 continue
1185 }
1186 return false
1187 }
1188
1189
1190 return len(t) == 0
1191 }
1192
1193
1194 func Index(s, substr string) int {
1195 n := len(substr)
1196 switch {
1197 case n == 0:
1198 return 0
1199 case n == 1:
1200 return IndexByte(s, substr[0])
1201 case n == len(s):
1202 if substr == s {
1203 return 0
1204 }
1205 return -1
1206 case n > len(s):
1207 return -1
1208 case n <= bytealg.MaxLen:
1209
1210 if len(s) <= bytealg.MaxBruteForce {
1211 return bytealg.IndexString(s, substr)
1212 }
1213 c0 := substr[0]
1214 c1 := substr[1]
1215 i := 0
1216 t := len(s) - n + 1
1217 fails := 0
1218 for i < t {
1219 if s[i] != c0 {
1220
1221
1222 o := IndexByte(s[i+1:t], c0)
1223 if o < 0 {
1224 return -1
1225 }
1226 i += o + 1
1227 }
1228 if s[i+1] == c1 && s[i:i+n] == substr {
1229 return i
1230 }
1231 fails++
1232 i++
1233
1234 if fails > bytealg.Cutover(i) {
1235 r := bytealg.IndexString(s[i:], substr)
1236 if r >= 0 {
1237 return r + i
1238 }
1239 return -1
1240 }
1241 }
1242 return -1
1243 }
1244 c0 := substr[0]
1245 c1 := substr[1]
1246 i := 0
1247 t := len(s) - n + 1
1248 fails := 0
1249 for i < t {
1250 if s[i] != c0 {
1251 o := IndexByte(s[i+1:t], c0)
1252 if o < 0 {
1253 return -1
1254 }
1255 i += o + 1
1256 }
1257 if s[i+1] == c1 && s[i:i+n] == substr {
1258 return i
1259 }
1260 i++
1261 fails++
1262 if fails >= 4+i>>4 && i < t {
1263
1264 j := bytealg.IndexRabinKarp(s[i:], substr)
1265 if j < 0 {
1266 return -1
1267 }
1268 return i + j
1269 }
1270 }
1271 return -1
1272 }
1273
1274
1275
1276
1277
1278 func Cut(s, sep string) (before, after string, found bool) {
1279 if i := Index(s, sep); i >= 0 {
1280 return s[:i], s[i+len(sep):], true
1281 }
1282 return s, "", false
1283 }
1284
1285
1286
1287
1288
1289 func CutPrefix(s, prefix string) (after string, found bool) {
1290 if !HasPrefix(s, prefix) {
1291 return s, false
1292 }
1293 return s[len(prefix):], true
1294 }
1295
1296
1297
1298
1299
1300 func CutSuffix(s, suffix string) (before string, found bool) {
1301 if !HasSuffix(s, suffix) {
1302 return s, false
1303 }
1304 return s[:len(s)-len(suffix)], true
1305 }
1306
View as plain text