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