package regexp2
import (
"bytes"
"errors"
"github.com/dlclark/regexp2/syntax"
)
const (
replaceSpecials = 4
replaceLeftPortion = -1
replaceRightPortion = -2
replaceLastGroup = -3
replaceWholeString = -4
)
type MatchEvaluator func (Match ) string
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
}
func replacementImpl(data *syntax .ReplacerData , buf *bytes .Buffer , m *Match ) {
for _ , r := range data .Rules {
if r >= 0 {
buf .WriteString (data .Strings [r ])
} else if r < -replaceSpecials {
m .groupValueAppendToBuf (-replaceSpecials -1 -r , buf )
} else {
switch -replaceSpecials - 1 - r {
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 {
l = append (l , data .Strings [r ])
} else if r < -replaceSpecials {
m .groupValueAppendToBuf (-replaceSpecials -1 -r , buf )
l = append (l , buf .String ())
} else {
switch -replaceSpecials - 1 - r {
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
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .