diff vendor/github.com/dlclark/regexp2/replace.go @ 66:787b5ee0289d draft

Use vendored modules Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja>
author yakumo.izuru
date Sun, 23 Jul 2023 13:18:53 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vendor/github.com/dlclark/regexp2/replace.go	Sun Jul 23 13:18:53 2023 +0000
@@ -0,0 +1,177 @@
+package regexp2
+
+import (
+	"bytes"
+	"errors"
+
+	"github.com/dlclark/regexp2/syntax"
+)
+
+const (
+	replaceSpecials     = 4
+	replaceLeftPortion  = -1
+	replaceRightPortion = -2
+	replaceLastGroup    = -3
+	replaceWholeString  = -4
+)
+
+// MatchEvaluator is a function that takes a match and returns a replacement string to be used
+type MatchEvaluator func(Match) string
+
+// Three very similar algorithms appear below: replace (pattern),
+// replace (evaluator), and split.
+
+// Replace Replaces all occurrences of the regex in the string with the
+// replacement pattern.
+//
+// Note that the special case of no matches is handled on its own:
+// with no matches, the input string is returned unchanged.
+// The right-to-left case is split out because StringBuilder
+// doesn't handle right-to-left string building directly very well.
+func replace(regex *Regexp, data *syntax.ReplacerData, evaluator MatchEvaluator, input string, startAt, count int) (string, error) {
+	if count < -1 {
+		return "", errors.New("Count too small")
+	}
+	if count == 0 {
+		return "", nil
+	}
+
+	m, err := regex.FindStringMatchStartingAt(input, startAt)
+
+	if err != nil {
+		return "", err
+	}
+	if m == nil {
+		return input, nil
+	}
+
+	buf := &bytes.Buffer{}
+	text := m.text
+
+	if !regex.RightToLeft() {
+		prevat := 0
+		for m != nil {
+			if m.Index != prevat {
+				buf.WriteString(string(text[prevat:m.Index]))
+			}
+			prevat = m.Index + m.Length
+			if evaluator == nil {
+				replacementImpl(data, buf, m)
+			} else {
+				buf.WriteString(evaluator(*m))
+			}
+
+			count--
+			if count == 0 {
+				break
+			}
+			m, err = regex.FindNextMatch(m)
+			if err != nil {
+				return "", nil
+			}
+		}
+
+		if prevat < len(text) {
+			buf.WriteString(string(text[prevat:]))
+		}
+	} else {
+		prevat := len(text)
+		var al []string
+
+		for m != nil {
+			if m.Index+m.Length != prevat {
+				al = append(al, string(text[m.Index+m.Length:prevat]))
+			}
+			prevat = m.Index
+			if evaluator == nil {
+				replacementImplRTL(data, &al, m)
+			} else {
+				al = append(al, evaluator(*m))
+			}
+
+			count--
+			if count == 0 {
+				break
+			}
+			m, err = regex.FindNextMatch(m)
+			if err != nil {
+				return "", nil
+			}
+		}
+
+		if prevat > 0 {
+			buf.WriteString(string(text[:prevat]))
+		}
+
+		for i := len(al) - 1; i >= 0; i-- {
+			buf.WriteString(al[i])
+		}
+	}
+
+	return buf.String(), nil
+}
+
+// Given a Match, emits into the StringBuilder the evaluated
+// substitution pattern.
+func replacementImpl(data *syntax.ReplacerData, buf *bytes.Buffer, m *Match) {
+	for _, r := range data.Rules {
+
+		if r >= 0 { // string lookup
+			buf.WriteString(data.Strings[r])
+		} else if r < -replaceSpecials { // group lookup
+			m.groupValueAppendToBuf(-replaceSpecials-1-r, buf)
+		} else {
+			switch -replaceSpecials - 1 - r { // special insertion patterns
+			case replaceLeftPortion:
+				for i := 0; i < m.Index; i++ {
+					buf.WriteRune(m.text[i])
+				}
+			case replaceRightPortion:
+				for i := m.Index + m.Length; i < len(m.text); i++ {
+					buf.WriteRune(m.text[i])
+				}
+			case replaceLastGroup:
+				m.groupValueAppendToBuf(m.GroupCount()-1, buf)
+			case replaceWholeString:
+				for i := 0; i < len(m.text); i++ {
+					buf.WriteRune(m.text[i])
+				}
+			}
+		}
+	}
+}
+
+func replacementImplRTL(data *syntax.ReplacerData, al *[]string, m *Match) {
+	l := *al
+	buf := &bytes.Buffer{}
+
+	for _, r := range data.Rules {
+		buf.Reset()
+		if r >= 0 { // string lookup
+			l = append(l, data.Strings[r])
+		} else if r < -replaceSpecials { // group lookup
+			m.groupValueAppendToBuf(-replaceSpecials-1-r, buf)
+			l = append(l, buf.String())
+		} else {
+			switch -replaceSpecials - 1 - r { // special insertion patterns
+			case replaceLeftPortion:
+				for i := 0; i < m.Index; i++ {
+					buf.WriteRune(m.text[i])
+				}
+			case replaceRightPortion:
+				for i := m.Index + m.Length; i < len(m.text); i++ {
+					buf.WriteRune(m.text[i])
+				}
+			case replaceLastGroup:
+				m.groupValueAppendToBuf(m.GroupCount()-1, buf)
+			case replaceWholeString:
+				for i := 0; i < len(m.text); i++ {
+					buf.WriteRune(m.text[i])
+				}
+			}
+			l = append(l, buf.String())
+		}
+	}
+
+	*al = l
+}