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