replacer.go 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. package stringx
  2. import (
  3. "strings"
  4. )
  5. type (
  6. // Replacer interface wraps the Replace method.
  7. Replacer interface {
  8. Replace(text string) string
  9. }
  10. replacer struct {
  11. *node
  12. mapping map[string]string
  13. }
  14. )
  15. // NewReplacer returns a Replacer.
  16. func NewReplacer(mapping map[string]string) Replacer {
  17. rep := &replacer{
  18. node: new(node),
  19. mapping: mapping,
  20. }
  21. for k := range mapping {
  22. rep.add(k)
  23. }
  24. rep.build()
  25. return rep
  26. }
  27. // Replace replaces text with given substitutes.
  28. func (r *replacer) Replace(text string) string {
  29. var buf strings.Builder
  30. var paths []*node
  31. target := []rune(text)
  32. cur := r.node
  33. for len(target) != 0 {
  34. uselessLen, matchLen, nextPaths := cur.longestMatch(target, paths)
  35. if uselessLen > 0 {
  36. buf.WriteString(string(target[:uselessLen]))
  37. target = target[uselessLen:]
  38. }
  39. if matchLen > 0 {
  40. replaced := r.mapping[string(target[:matchLen])]
  41. target = append([]rune(replaced), target[matchLen:]...)
  42. }
  43. if len(nextPaths) != 0 {
  44. cur = nextPaths[len(nextPaths)-1]
  45. paths = nextPaths
  46. } else {
  47. cur = r.node
  48. paths = nil
  49. }
  50. }
  51. return buf.String()
  52. }