github.com/lingyao2333/mo-zero@v1.4.1/core/stringx/replacer.go (about) 1 package stringx 2 3 import "strings" 4 5 type ( 6 // Replacer interface wraps the Replace method. 7 Replacer interface { 8 Replace(text string) string 9 } 10 11 replacer struct { 12 *node 13 mapping map[string]string 14 } 15 ) 16 17 // NewReplacer returns a Replacer. 18 func NewReplacer(mapping map[string]string) Replacer { 19 rep := &replacer{ 20 node: new(node), 21 mapping: mapping, 22 } 23 for k := range mapping { 24 rep.add(k) 25 } 26 rep.build() 27 28 return rep 29 } 30 31 // Replace replaces text with given substitutes. 32 func (r *replacer) Replace(text string) string { 33 var builder strings.Builder 34 var start int 35 chars := []rune(text) 36 size := len(chars) 37 38 for start < size { 39 cur := r.node 40 41 if start > 0 { 42 builder.WriteString(string(chars[:start])) 43 } 44 45 for i := start; i < size; i++ { 46 child, ok := cur.children[chars[i]] 47 if ok { 48 cur = child 49 } else if cur == r.node { 50 builder.WriteRune(chars[i]) 51 // cur already points to root, set start only 52 start = i + 1 53 continue 54 } else { 55 curDepth := cur.depth 56 cur = cur.fail 57 child, ok = cur.children[chars[i]] 58 if !ok { 59 // write this path 60 builder.WriteString(string(chars[i-curDepth : i+1])) 61 // go to root 62 cur = r.node 63 start = i + 1 64 continue 65 } 66 67 failDepth := cur.depth 68 // write path before jump 69 builder.WriteString(string(chars[start : start+curDepth-failDepth])) 70 start += curDepth - failDepth 71 cur = child 72 } 73 74 if cur.end { 75 val := string(chars[i+1-cur.depth : i+1]) 76 builder.WriteString(r.mapping[val]) 77 builder.WriteString(string(chars[i+1:])) 78 // only matching this path, all previous paths are done 79 if start >= i+1-cur.depth && i+1 >= size { 80 return builder.String() 81 } 82 83 chars = []rune(builder.String()) 84 size = len(chars) 85 builder.Reset() 86 break 87 } 88 } 89 90 if !cur.end { 91 builder.WriteString(string(chars[start:])) 92 return builder.String() 93 } 94 } 95 96 return string(chars) 97 }