Source file
src/strings/replace.go
1
2
3
4
5 package strings
6
7 import (
8 "io"
9 "sync"
10 )
11
12
13
14 type Replacer struct {
15 once sync.Once
16 r replacer
17 oldnew []string
18 }
19
20
21 type replacer interface {
22 Replace(s string) string
23 WriteString(w io.Writer, s string) (n int, err error)
24 }
25
26
27
28
29
30
31
32 func NewReplacer(oldnew ...string) *Replacer {
33 if len(oldnew)%2 == 1 {
34 panic("strings.NewReplacer: odd argument count")
35 }
36 return &Replacer{oldnew: append([]string(nil), oldnew...)}
37 }
38
39 func (r *Replacer) buildOnce() {
40 r.r = r.build()
41 r.oldnew = nil
42 }
43
44 func (b *Replacer) build() replacer {
45 oldnew := b.oldnew
46 if len(oldnew) == 2 && len(oldnew[0]) > 1 {
47 return makeSingleStringReplacer(oldnew[0], oldnew[1])
48 }
49
50 allNewBytes := true
51 for i := 0; i < len(oldnew); i += 2 {
52 if len(oldnew[i]) != 1 {
53 return makeGenericReplacer(oldnew)
54 }
55 if len(oldnew[i+1]) != 1 {
56 allNewBytes = false
57 }
58 }
59
60 if allNewBytes {
61 r := byteReplacer{}
62 for i := range r {
63 r[i] = byte(i)
64 }
65
66
67 for i := len(oldnew) - 2; i >= 0; i -= 2 {
68 o := oldnew[i][0]
69 n := oldnew[i+1][0]
70 r[o] = n
71 }
72 return &r
73 }
74
75 r := byteStringReplacer{toReplace: make([]string, 0, len(oldnew)/2)}
76
77
78 for i := len(oldnew) - 2; i >= 0; i -= 2 {
79 o := oldnew[i][0]
80 n := oldnew[i+1]
81
82 if r.replacements[o] == nil {
83
84
85
86 r.toReplace = append(r.toReplace, string([]byte{o}))
87 }
88 r.replacements[o] = []byte(n)
89
90 }
91 return &r
92 }
93
94
95 func (r *Replacer) Replace(s string) string {
96 r.once.Do(r.buildOnce)
97 return r.r.Replace(s)
98 }
99
100
101 func (r *Replacer) WriteString(w io.Writer, s string) (n int, err error) {
102 r.once.Do(r.buildOnce)
103 return r.r.WriteString(w, s)
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 type trieNode struct {
124
125
126 value string
127
128
129
130
131
132 priority int
133
134
135
136
137
138
139
140
141
142
143
144
145 prefix string
146 next *trieNode
147
148
149
150
151
152
153
154
155 table []*trieNode
156 }
157
158 func (t *trieNode) add(key, val string, priority int, r *genericReplacer) {
159 if key == "" {
160 if t.priority == 0 {
161 t.value = val
162 t.priority = priority
163 }
164 return
165 }
166
167 if t.prefix != "" {
168
169 var n int
170 for ; n < len(t.prefix) && n < len(key); n++ {
171 if t.prefix[n] != key[n] {
172 break
173 }
174 }
175 if n == len(t.prefix) {
176 t.next.add(key[n:], val, priority, r)
177 } else if n == 0 {
178
179
180
181 var prefixNode *trieNode
182 if len(t.prefix) == 1 {
183 prefixNode = t.next
184 } else {
185 prefixNode = &trieNode{
186 prefix: t.prefix[1:],
187 next: t.next,
188 }
189 }
190 keyNode := new(trieNode)
191 t.table = make([]*trieNode, r.tableSize)
192 t.table[r.mapping[t.prefix[0]]] = prefixNode
193 t.table[r.mapping[key[0]]] = keyNode
194 t.prefix = ""
195 t.next = nil
196 keyNode.add(key[1:], val, priority, r)
197 } else {
198
199 next := &trieNode{
200 prefix: t.prefix[n:],
201 next: t.next,
202 }
203 t.prefix = t.prefix[:n]
204 t.next = next
205 next.add(key[n:], val, priority, r)
206 }
207 } else if t.table != nil {
208
209 m := r.mapping[key[0]]
210 if t.table[m] == nil {
211 t.table[m] = new(trieNode)
212 }
213 t.table[m].add(key[1:], val, priority, r)
214 } else {
215 t.prefix = key
216 t.next = new(trieNode)
217 t.next.add("", val, priority, r)
218 }
219 }
220
221 func (r *genericReplacer) lookup(s string, ignoreRoot bool) (val string, keylen int, found bool) {
222
223
224 bestPriority := 0
225 node := &r.root
226 n := 0
227 for node != nil {
228 if node.priority > bestPriority && !(ignoreRoot && node == &r.root) {
229 bestPriority = node.priority
230 val = node.value
231 keylen = n
232 found = true
233 }
234
235 if s == "" {
236 break
237 }
238 if node.table != nil {
239 index := r.mapping[s[0]]
240 if int(index) == r.tableSize {
241 break
242 }
243 node = node.table[index]
244 s = s[1:]
245 n++
246 } else if node.prefix != "" && HasPrefix(s, node.prefix) {
247 n += len(node.prefix)
248 s = s[len(node.prefix):]
249 node = node.next
250 } else {
251 break
252 }
253 }
254 return
255 }
256
257
258
259 type genericReplacer struct {
260 root trieNode
261
262
263 tableSize int
264
265 mapping [256]byte
266 }
267
268 func makeGenericReplacer(oldnew []string) *genericReplacer {
269 r := new(genericReplacer)
270
271 for i := 0; i < len(oldnew); i += 2 {
272 key := oldnew[i]
273 for j := 0; j < len(key); j++ {
274 r.mapping[key[j]] = 1
275 }
276 }
277
278 for _, b := range r.mapping {
279 r.tableSize += int(b)
280 }
281
282 var index byte
283 for i, b := range r.mapping {
284 if b == 0 {
285 r.mapping[i] = byte(r.tableSize)
286 } else {
287 r.mapping[i] = index
288 index++
289 }
290 }
291
292 r.root.table = make([]*trieNode, r.tableSize)
293
294 for i := 0; i < len(oldnew); i += 2 {
295 r.root.add(oldnew[i], oldnew[i+1], len(oldnew)-i, r)
296 }
297 return r
298 }
299
300 type appendSliceWriter []byte
301
302
303 func (w *appendSliceWriter) Write(p []byte) (int, error) {
304 *w = append(*w, p...)
305 return len(p), nil
306 }
307
308
309 func (w *appendSliceWriter) WriteString(s string) (int, error) {
310 *w = append(*w, s...)
311 return len(s), nil
312 }
313
314 type stringWriter struct {
315 w io.Writer
316 }
317
318 func (w stringWriter) WriteString(s string) (int, error) {
319 return w.w.Write([]byte(s))
320 }
321
322 func getStringWriter(w io.Writer) io.StringWriter {
323 sw, ok := w.(io.StringWriter)
324 if !ok {
325 sw = stringWriter{w}
326 }
327 return sw
328 }
329
330 func (r *genericReplacer) Replace(s string) string {
331 buf := make(appendSliceWriter, 0, len(s))
332 r.WriteString(&buf, s)
333 return string(buf)
334 }
335
336 func (r *genericReplacer) WriteString(w io.Writer, s string) (n int, err error) {
337 sw := getStringWriter(w)
338 var last, wn int
339 var prevMatchEmpty bool
340 for i := 0; i <= len(s); {
341
342 if i != len(s) && r.root.priority == 0 {
343 index := int(r.mapping[s[i]])
344 if index == r.tableSize || r.root.table[index] == nil {
345 i++
346 continue
347 }
348 }
349
350
351 val, keylen, match := r.lookup(s[i:], prevMatchEmpty)
352 prevMatchEmpty = match && keylen == 0
353 if match {
354 wn, err = sw.WriteString(s[last:i])
355 n += wn
356 if err != nil {
357 return
358 }
359 wn, err = sw.WriteString(val)
360 n += wn
361 if err != nil {
362 return
363 }
364 i += keylen
365 last = i
366 continue
367 }
368 i++
369 }
370 if last != len(s) {
371 wn, err = sw.WriteString(s[last:])
372 n += wn
373 }
374 return
375 }
376
377
378
379 type singleStringReplacer struct {
380 finder *stringFinder
381
382 value string
383 }
384
385 func makeSingleStringReplacer(pattern string, value string) *singleStringReplacer {
386 return &singleStringReplacer{finder: makeStringFinder(pattern), value: value}
387 }
388
389 func (r *singleStringReplacer) Replace(s string) string {
390 var buf Builder
391 i, matched := 0, false
392 for {
393 match := r.finder.next(s[i:])
394 if match == -1 {
395 break
396 }
397 matched = true
398 buf.Grow(match + len(r.value))
399 buf.WriteString(s[i : i+match])
400 buf.WriteString(r.value)
401 i += match + len(r.finder.pattern)
402 }
403 if !matched {
404 return s
405 }
406 buf.WriteString(s[i:])
407 return buf.String()
408 }
409
410 func (r *singleStringReplacer) WriteString(w io.Writer, s string) (n int, err error) {
411 sw := getStringWriter(w)
412 var i, wn int
413 for {
414 match := r.finder.next(s[i:])
415 if match == -1 {
416 break
417 }
418 wn, err = sw.WriteString(s[i : i+match])
419 n += wn
420 if err != nil {
421 return
422 }
423 wn, err = sw.WriteString(r.value)
424 n += wn
425 if err != nil {
426 return
427 }
428 i += match + len(r.finder.pattern)
429 }
430 wn, err = sw.WriteString(s[i:])
431 n += wn
432 return
433 }
434
435
436
437
438 type byteReplacer [256]byte
439
440 func (r *byteReplacer) Replace(s string) string {
441 var buf []byte
442 for i := 0; i < len(s); i++ {
443 b := s[i]
444 if r[b] != b {
445 if buf == nil {
446 buf = []byte(s)
447 }
448 buf[i] = r[b]
449 }
450 }
451 if buf == nil {
452 return s
453 }
454 return string(buf)
455 }
456
457 func (r *byteReplacer) WriteString(w io.Writer, s string) (n int, err error) {
458 sw := getStringWriter(w)
459 last := 0
460 for i := 0; i < len(s); i++ {
461 b := s[i]
462 if r[b] == b {
463 continue
464 }
465 if last != i {
466 wn, err := sw.WriteString(s[last:i])
467 n += wn
468 if err != nil {
469 return n, err
470 }
471 }
472 last = i + 1
473 nw, err := w.Write(r[b : int(b)+1])
474 n += nw
475 if err != nil {
476 return n, err
477 }
478 }
479 if last != len(s) {
480 nw, err := sw.WriteString(s[last:])
481 n += nw
482 if err != nil {
483 return n, err
484 }
485 }
486 return n, nil
487 }
488
489
490
491 type byteStringReplacer struct {
492
493
494 replacements [256][]byte
495
496
497
498 toReplace []string
499 }
500
501
502
503
504
505
506
507
508 const countCutOff = 8
509
510 func (r *byteStringReplacer) Replace(s string) string {
511 newSize := len(s)
512 anyChanges := false
513
514 if len(r.toReplace)*countCutOff <= len(s) {
515 for _, x := range r.toReplace {
516 if c := Count(s, x); c != 0 {
517
518 newSize += c * (len(r.replacements[x[0]]) - 1)
519 anyChanges = true
520 }
521
522 }
523 } else {
524 for i := 0; i < len(s); i++ {
525 b := s[i]
526 if r.replacements[b] != nil {
527
528 newSize += len(r.replacements[b]) - 1
529 anyChanges = true
530 }
531 }
532 }
533 if !anyChanges {
534 return s
535 }
536 buf := make([]byte, newSize)
537 j := 0
538 for i := 0; i < len(s); i++ {
539 b := s[i]
540 if r.replacements[b] != nil {
541 j += copy(buf[j:], r.replacements[b])
542 } else {
543 buf[j] = b
544 j++
545 }
546 }
547 return string(buf)
548 }
549
550 func (r *byteStringReplacer) WriteString(w io.Writer, s string) (n int, err error) {
551 sw := getStringWriter(w)
552 last := 0
553 for i := 0; i < len(s); i++ {
554 b := s[i]
555 if r.replacements[b] == nil {
556 continue
557 }
558 if last != i {
559 nw, err := sw.WriteString(s[last:i])
560 n += nw
561 if err != nil {
562 return n, err
563 }
564 }
565 last = i + 1
566 nw, err := w.Write(r.replacements[b])
567 n += nw
568 if err != nil {
569 return n, err
570 }
571 }
572 if last != len(s) {
573 var nw int
574 nw, err = sw.WriteString(s[last:])
575 n += nw
576 }
577 return
578 }
579
View as plain text