123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- package stringx
- import (
- "sort"
- "strings"
- )
- // replace more than once to avoid overlapped keywords after replace.
- // only try 2 times to avoid too many or infinite loops.
- const replaceTimes = 2
- type (
- // Replacer interface wraps the Replace method.
- Replacer interface {
- Replace(text string) string
- }
- replacer struct {
- *node
- mapping map[string]string
- }
- )
- // NewReplacer returns a Replacer.
- func NewReplacer(mapping map[string]string) Replacer {
- rep := &replacer{
- node: new(node),
- mapping: mapping,
- }
- for k := range mapping {
- rep.add(k)
- }
- rep.build()
- return rep
- }
- // Replace replaces text with given substitutes.
- func (r *replacer) Replace(text string) string {
- for i := 0; i < replaceTimes; i++ {
- var replaced bool
- if text, replaced = r.doReplace(text); !replaced {
- return text
- }
- }
- return text
- }
- func (r *replacer) doReplace(text string) (string, bool) {
- chars := []rune(text)
- scopes := r.find(chars)
- if len(scopes) == 0 {
- return text, false
- }
- sort.Slice(scopes, func(i, j int) bool {
- if scopes[i].start < scopes[j].start {
- return true
- }
- if scopes[i].start == scopes[j].start {
- return scopes[i].stop > scopes[j].stop
- }
- return false
- })
- var buf strings.Builder
- var index int
- for i := 0; i < len(scopes); i++ {
- scp := &scopes[i]
- if scp.start < index {
- continue
- }
- buf.WriteString(string(chars[index:scp.start]))
- buf.WriteString(r.mapping[string(chars[scp.start:scp.stop])])
- index = scp.stop
- }
- if index < len(chars) {
- buf.WriteString(string(chars[index:]))
- }
- return buf.String(), true
- }
|