LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Package strings implements simple functions to manipulate strings. | 5 // Package strings implements simple functions to manipulate strings. |
6 package strings | 6 package strings |
7 | 7 |
8 import ( | 8 import ( |
9 "unicode" | 9 "unicode" |
10 "unicode/utf8" | 10 "unicode/utf8" |
(...skipping 25 matching lines...) Expand all Loading... |
36 // add the rest, if there is any | 36 // add the rest, if there is any |
37 if cur < len(s) { | 37 if cur < len(s) { |
38 a[i] = s[cur:] | 38 a[i] = s[cur:] |
39 } | 39 } |
40 return a | 40 return a |
41 } | 41 } |
42 | 42 |
43 // primeRK is the prime base used in Rabin-Karp algorithm. | 43 // primeRK is the prime base used in Rabin-Karp algorithm. |
44 const primeRK = 16777619 | 44 const primeRK = 16777619 |
45 | 45 |
46 // hashstr returns the hash and the appropriate multiplicative | 46 // hashStr returns the hash and the appropriate multiplicative |
47 // factor for use in Rabin-Karp algorithm. | 47 // factor for use in Rabin-Karp algorithm. |
48 func hashstr(sep string) (uint32, uint32) { | 48 func hashStr(sep string) (uint32, uint32) { |
49 hash := uint32(0) | 49 hash := uint32(0) |
50 for i := 0; i < len(sep); i++ { | 50 for i := 0; i < len(sep); i++ { |
51 hash = hash*primeRK + uint32(sep[i]) | 51 hash = hash*primeRK + uint32(sep[i]) |
52 | 52 » } |
| 53 » var pow, sq uint32 = 1, primeRK |
| 54 » for i := len(sep); i > 0; i >>= 1 { |
| 55 » » if i&1 != 0 { |
| 56 » » » pow *= sq |
| 57 » » } |
| 58 » » sq *= sq |
| 59 » } |
| 60 » return hash, pow |
| 61 } |
| 62 |
| 63 // hashStrRev returns the hash of the reverse of sep and the |
| 64 // appropriate multiplicative factor for use in Rabin-Karp algorithm. |
| 65 func hashStrRev(sep string) (uint32, uint32) { |
| 66 » hash := uint32(0) |
| 67 » for i := len(sep) - 1; i >= 0; i-- { |
| 68 » » hash = hash*primeRK + uint32(sep[i]) |
53 } | 69 } |
54 var pow, sq uint32 = 1, primeRK | 70 var pow, sq uint32 = 1, primeRK |
55 for i := len(sep); i > 0; i >>= 1 { | 71 for i := len(sep); i > 0; i >>= 1 { |
56 if i&1 != 0 { | 72 if i&1 != 0 { |
57 pow *= sq | 73 pow *= sq |
58 } | 74 } |
59 sq *= sq | 75 sq *= sq |
60 } | 76 } |
61 return hash, pow | 77 return hash, pow |
62 } | 78 } |
(...skipping 15 matching lines...) Expand all Loading... |
78 } | 94 } |
79 return n | 95 return n |
80 case len(sep) > len(s): | 96 case len(sep) > len(s): |
81 return 0 | 97 return 0 |
82 case len(sep) == len(s): | 98 case len(sep) == len(s): |
83 if sep == s { | 99 if sep == s { |
84 return 1 | 100 return 1 |
85 } | 101 } |
86 return 0 | 102 return 0 |
87 } | 103 } |
88 » hashsep, pow := hashstr(sep) | 104 » // Rabin-Karp search |
| 105 » hashsep, pow := hashStr(sep) |
89 h := uint32(0) | 106 h := uint32(0) |
90 for i := 0; i < len(sep); i++ { | 107 for i := 0; i < len(sep); i++ { |
91 h = h*primeRK + uint32(s[i]) | 108 h = h*primeRK + uint32(s[i]) |
92 } | 109 } |
93 lastmatch := 0 | 110 lastmatch := 0 |
94 if h == hashsep && s[:len(sep)] == sep { | 111 if h == hashsep && s[:len(sep)] == sep { |
95 n++ | 112 n++ |
96 lastmatch = len(sep) | 113 lastmatch = len(sep) |
97 } | 114 } |
98 for i := len(sep); i < len(s); { | 115 for i := len(sep); i < len(s); { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 case n == 1: | 149 case n == 1: |
133 return IndexByte(s, sep[0]) | 150 return IndexByte(s, sep[0]) |
134 case n == len(s): | 151 case n == len(s): |
135 if sep == s { | 152 if sep == s { |
136 return 0 | 153 return 0 |
137 } | 154 } |
138 return -1 | 155 return -1 |
139 case n > len(s): | 156 case n > len(s): |
140 return -1 | 157 return -1 |
141 } | 158 } |
142 » // Hash sep. | 159 » // Rabin-Karp search |
143 » hashsep, pow := hashstr(sep) | 160 » hashsep, pow := hashStr(sep) |
144 var h uint32 | 161 var h uint32 |
145 for i := 0; i < n; i++ { | 162 for i := 0; i < n; i++ { |
146 h = h*primeRK + uint32(s[i]) | 163 h = h*primeRK + uint32(s[i]) |
147 } | 164 } |
148 if h == hashsep && s[:n] == sep { | 165 if h == hashsep && s[:n] == sep { |
149 return 0 | 166 return 0 |
150 } | 167 } |
151 for i := n; i < len(s); { | 168 for i := n; i < len(s); { |
152 h *= primeRK | 169 h *= primeRK |
153 h += uint32(s[i]) | 170 h += uint32(s[i]) |
154 h -= pow * uint32(s[i-n]) | 171 h -= pow * uint32(s[i-n]) |
155 i++ | 172 i++ |
156 if h == hashsep && s[i-n:i] == sep { | 173 if h == hashsep && s[i-n:i] == sep { |
157 return i - n | 174 return i - n |
158 } | 175 } |
159 } | 176 } |
160 return -1 | 177 return -1 |
161 } | 178 } |
162 | 179 |
163 // LastIndex returns the index of the last instance of sep in s, or -1 if sep is
not present in s. | 180 // LastIndex returns the index of the last instance of sep in s, or -1 if sep is
not present in s. |
164 func LastIndex(s, sep string) int { | 181 func LastIndex(s, sep string) int { |
165 n := len(sep) | 182 n := len(sep) |
166 » if n == 0 { | 183 » switch { |
| 184 » case n == 0: |
167 return len(s) | 185 return len(s) |
168 » } | 186 » case n == 1: |
169 » c := sep[0] | |
170 » if n == 1 { | |
171 // special case worth making fast | 187 // special case worth making fast |
| 188 c := sep[0] |
172 for i := len(s) - 1; i >= 0; i-- { | 189 for i := len(s) - 1; i >= 0; i-- { |
173 if s[i] == c { | 190 if s[i] == c { |
174 return i | 191 return i |
175 } | 192 } |
176 } | 193 } |
177 return -1 | 194 return -1 |
178 » } | 195 » case n == len(s): |
179 » // n > 1 | 196 » » if sep == s { |
180 » for i := len(s) - n; i >= 0; i-- { | 197 » » » return 0 |
181 » » if s[i] == c && s[i:i+n] == sep { | 198 » » } |
| 199 » » return -1 |
| 200 » case n > len(s): |
| 201 » » return -1 |
| 202 » } |
| 203 » // Rabin-Karp search from the end of the string |
| 204 » hashsep, pow := hashStrRev(sep) |
| 205 » last := len(s) - n |
| 206 » var h uint32 |
| 207 » for i := len(s) - 1; i >= last; i-- { |
| 208 » » h = h*primeRK + uint32(s[i]) |
| 209 » } |
| 210 » if h == hashsep && s[last:] == sep { |
| 211 » » return last |
| 212 » } |
| 213 » for i := last - 1; i >= 0; i-- { |
| 214 » » h *= primeRK |
| 215 » » h += uint32(s[i]) |
| 216 » » h -= pow * uint32(s[i+n]) |
| 217 » » if h == hashsep && s[i:i+n] == sep { |
182 return i | 218 return i |
183 } | 219 } |
184 } | 220 } |
185 return -1 | 221 return -1 |
186 } | 222 } |
187 | 223 |
188 // IndexRune returns the index of the first instance of the Unicode code point | 224 // IndexRune returns the index of the first instance of the Unicode code point |
189 // r, or -1 if rune is not present in s. | 225 // r, or -1 if rune is not present in s. |
190 func IndexRune(s string, r rune) int { | 226 func IndexRune(s string, r rune) int { |
191 switch { | 227 switch { |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 // If s doesn't end with suffix, s is returned unchanged. | 664 // If s doesn't end with suffix, s is returned unchanged. |
629 func TrimSuffix(s, suffix string) string { | 665 func TrimSuffix(s, suffix string) string { |
630 if HasSuffix(s, suffix) { | 666 if HasSuffix(s, suffix) { |
631 return s[:len(s)-len(suffix)] | 667 return s[:len(s)-len(suffix)] |
632 } | 668 } |
633 return s | 669 return s |
634 } | 670 } |
635 | 671 |
636 // Replace returns a copy of the string s with the first n | 672 // Replace returns a copy of the string s with the first n |
637 // non-overlapping instances of old replaced by new. | 673 // non-overlapping instances of old replaced by new. |
| 674 // If old is empty, it matches at the beginning of the string |
| 675 // and after each UTF-8 sequence, yielding up to k+1 replacements |
| 676 // for a k-rune string. |
638 // If n < 0, there is no limit on the number of replacements. | 677 // If n < 0, there is no limit on the number of replacements. |
639 func Replace(s, old, new string, n int) string { | 678 func Replace(s, old, new string, n int) string { |
640 if old == new || n == 0 { | 679 if old == new || n == 0 { |
641 return s // avoid allocation | 680 return s // avoid allocation |
642 } | 681 } |
643 | 682 |
644 // Compute number of replacements. | 683 // Compute number of replacements. |
645 if m := Count(s, old); m == 0 { | 684 if m := Count(s, old); m == 0 { |
646 return s // avoid allocation | 685 return s // avoid allocation |
647 } else if n < 0 || m < n { | 686 } else if n < 0 || m < n { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 } | 756 } |
718 if r == tr { | 757 if r == tr { |
719 continue | 758 continue |
720 } | 759 } |
721 return false | 760 return false |
722 } | 761 } |
723 | 762 |
724 // One string is empty. Are both? | 763 // One string is empty. Are both? |
725 return s == t | 764 return s == t |
726 } | 765 } |
LEFT | RIGHT |