annotate vendor/github.com/dlclark/regexp2/regexp.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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
66
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1 /*
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2 Package regexp2 is a regexp package that has an interface similar to Go's framework regexp engine but uses a
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
3 more feature full regex engine behind the scenes.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
4
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
5 It doesn't have constant time guarantees, but it allows backtracking and is compatible with Perl5 and .NET.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
6 You'll likely be better off with the RE2 engine from the regexp package and should only use this if you
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
7 need to write very complex patterns or require compatibility with .NET.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
8 */
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
9 package regexp2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
10
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
11 import (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
12 "errors"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
13 "math"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
14 "strconv"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
15 "sync"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
16 "time"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
17
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
18 "github.com/dlclark/regexp2/syntax"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
19 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
20
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
21 // Default timeout used when running regexp matches -- "forever"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
22 var DefaultMatchTimeout = time.Duration(math.MaxInt64)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
23
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
24 // Regexp is the representation of a compiled regular expression.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
25 // A Regexp is safe for concurrent use by multiple goroutines.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
26 type Regexp struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
27 //timeout when trying to find matches
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
28 MatchTimeout time.Duration
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
29
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
30 // read-only after Compile
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
31 pattern string // as passed to Compile
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
32 options RegexOptions // options
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
33
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
34 caps map[int]int // capnum->index
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
35 capnames map[string]int //capture group name -> index
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
36 capslist []string //sorted list of capture group names
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
37 capsize int // size of the capture array
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
38
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
39 code *syntax.Code // compiled program
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
40
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
41 // cache of machines for running regexp
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
42 muRun sync.Mutex
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
43 runner []*runner
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
44 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
45
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
46 // Compile parses a regular expression and returns, if successful,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
47 // a Regexp object that can be used to match against text.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
48 func Compile(expr string, opt RegexOptions) (*Regexp, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
49 // parse it
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
50 tree, err := syntax.Parse(expr, syntax.RegexOptions(opt))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
51 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
52 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
53 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
54
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
55 // translate it to code
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
56 code, err := syntax.Write(tree)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
57 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
58 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
59 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
60
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
61 // return it
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
62 return &Regexp{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
63 pattern: expr,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
64 options: opt,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
65 caps: code.Caps,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
66 capnames: tree.Capnames,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
67 capslist: tree.Caplist,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
68 capsize: code.Capsize,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
69 code: code,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
70 MatchTimeout: DefaultMatchTimeout,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
71 }, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
72 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
73
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
74 // MustCompile is like Compile but panics if the expression cannot be parsed.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
75 // It simplifies safe initialization of global variables holding compiled regular
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
76 // expressions.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
77 func MustCompile(str string, opt RegexOptions) *Regexp {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
78 regexp, error := Compile(str, opt)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
79 if error != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
80 panic(`regexp2: Compile(` + quote(str) + `): ` + error.Error())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
81 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
82 return regexp
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
83 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
84
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
85 // Escape adds backslashes to any special characters in the input string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
86 func Escape(input string) string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
87 return syntax.Escape(input)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
88 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
89
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
90 // Unescape removes any backslashes from previously-escaped special characters in the input string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
91 func Unescape(input string) (string, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
92 return syntax.Unescape(input)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
93 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
94
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
95 // String returns the source text used to compile the regular expression.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
96 func (re *Regexp) String() string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
97 return re.pattern
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
98 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
99
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
100 func quote(s string) string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
101 if strconv.CanBackquote(s) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
102 return "`" + s + "`"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
103 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
104 return strconv.Quote(s)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
105 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
106
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
107 // RegexOptions impact the runtime and parsing behavior
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
108 // for each specific regex. They are setable in code as well
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
109 // as in the regex pattern itself.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
110 type RegexOptions int32
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
111
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
112 const (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
113 None RegexOptions = 0x0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
114 IgnoreCase = 0x0001 // "i"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
115 Multiline = 0x0002 // "m"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
116 ExplicitCapture = 0x0004 // "n"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
117 Compiled = 0x0008 // "c"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
118 Singleline = 0x0010 // "s"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
119 IgnorePatternWhitespace = 0x0020 // "x"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
120 RightToLeft = 0x0040 // "r"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
121 Debug = 0x0080 // "d"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
122 ECMAScript = 0x0100 // "e"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
123 RE2 = 0x0200 // RE2 (regexp package) compatibility mode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
124 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
125
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
126 func (re *Regexp) RightToLeft() bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
127 return re.options&RightToLeft != 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
128 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
129
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
130 func (re *Regexp) Debug() bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
131 return re.options&Debug != 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
132 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
133
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
134 // Replace searches the input string and replaces each match found with the replacement text.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
135 // Count will limit the number of matches attempted and startAt will allow
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
136 // us to skip past possible matches at the start of the input (left or right depending on RightToLeft option).
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
137 // Set startAt and count to -1 to go through the whole string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
138 func (re *Regexp) Replace(input, replacement string, startAt, count int) (string, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
139 data, err := syntax.NewReplacerData(replacement, re.caps, re.capsize, re.capnames, syntax.RegexOptions(re.options))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
140 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
141 return "", err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
142 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
143 //TODO: cache ReplacerData
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
144
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
145 return replace(re, data, nil, input, startAt, count)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
146 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
147
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
148 // ReplaceFunc searches the input string and replaces each match found using the string from the evaluator
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
149 // Count will limit the number of matches attempted and startAt will allow
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
150 // us to skip past possible matches at the start of the input (left or right depending on RightToLeft option).
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
151 // Set startAt and count to -1 to go through the whole string.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
152 func (re *Regexp) ReplaceFunc(input string, evaluator MatchEvaluator, startAt, count int) (string, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
153 return replace(re, nil, evaluator, input, startAt, count)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
154 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
155
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
156 // FindStringMatch searches the input string for a Regexp match
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
157 func (re *Regexp) FindStringMatch(s string) (*Match, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
158 // convert string to runes
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
159 return re.run(false, -1, getRunes(s))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
160 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
161
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
162 // FindRunesMatch searches the input rune slice for a Regexp match
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
163 func (re *Regexp) FindRunesMatch(r []rune) (*Match, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
164 return re.run(false, -1, r)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
165 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
166
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
167 // FindStringMatchStartingAt searches the input string for a Regexp match starting at the startAt index
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
168 func (re *Regexp) FindStringMatchStartingAt(s string, startAt int) (*Match, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
169 if startAt > len(s) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
170 return nil, errors.New("startAt must be less than the length of the input string")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
171 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
172 r, startAt := re.getRunesAndStart(s, startAt)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
173 if startAt == -1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
174 // we didn't find our start index in the string -- that's a problem
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
175 return nil, errors.New("startAt must align to the start of a valid rune in the input string")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
176 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
177
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
178 return re.run(false, startAt, r)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
179 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
180
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
181 // FindRunesMatchStartingAt searches the input rune slice for a Regexp match starting at the startAt index
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
182 func (re *Regexp) FindRunesMatchStartingAt(r []rune, startAt int) (*Match, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
183 return re.run(false, startAt, r)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
184 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
185
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
186 // FindNextMatch returns the next match in the same input string as the match parameter.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
187 // Will return nil if there is no next match or if given a nil match.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
188 func (re *Regexp) FindNextMatch(m *Match) (*Match, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
189 if m == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
190 return nil, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
191 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
192
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
193 // If previous match was empty, advance by one before matching to prevent
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
194 // infinite loop
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
195 startAt := m.textpos
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
196 if m.Length == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
197 if m.textpos == len(m.text) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
198 return nil, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
199 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
200
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
201 if re.RightToLeft() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
202 startAt--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
203 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
204 startAt++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
205 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
206 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
207 return re.run(false, startAt, m.text)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
208 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
209
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
210 // MatchString return true if the string matches the regex
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
211 // error will be set if a timeout occurs
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
212 func (re *Regexp) MatchString(s string) (bool, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
213 m, err := re.run(true, -1, getRunes(s))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
214 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
215 return false, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
216 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
217 return m != nil, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
218 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
219
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
220 func (re *Regexp) getRunesAndStart(s string, startAt int) ([]rune, int) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
221 if startAt < 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
222 if re.RightToLeft() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
223 r := getRunes(s)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
224 return r, len(r)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
225 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
226 return getRunes(s), 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
227 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
228 ret := make([]rune, len(s))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
229 i := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
230 runeIdx := -1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
231 for strIdx, r := range s {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
232 if strIdx == startAt {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
233 runeIdx = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
234 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
235 ret[i] = r
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
236 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
237 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
238 if startAt == len(s) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
239 runeIdx = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
240 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
241 return ret[:i], runeIdx
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
242 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
243
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
244 func getRunes(s string) []rune {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
245 return []rune(s)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
246 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
247
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
248 // MatchRunes return true if the runes matches the regex
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
249 // error will be set if a timeout occurs
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
250 func (re *Regexp) MatchRunes(r []rune) (bool, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
251 m, err := re.run(true, -1, r)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
252 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
253 return false, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
254 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
255 return m != nil, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
256 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
257
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
258 // GetGroupNames Returns the set of strings used to name capturing groups in the expression.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
259 func (re *Regexp) GetGroupNames() []string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
260 var result []string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
261
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
262 if re.capslist == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
263 result = make([]string, re.capsize)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
264
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
265 for i := 0; i < len(result); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
266 result[i] = strconv.Itoa(i)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
267 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
268 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
269 result = make([]string, len(re.capslist))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
270 copy(result, re.capslist)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
271 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
272
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
273 return result
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
274 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
275
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
276 // GetGroupNumbers returns the integer group numbers corresponding to a group name.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
277 func (re *Regexp) GetGroupNumbers() []int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
278 var result []int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
279
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
280 if re.caps == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
281 result = make([]int, re.capsize)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
282
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
283 for i := 0; i < len(result); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
284 result[i] = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
285 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
286 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
287 result = make([]int, len(re.caps))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
288
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
289 for k, v := range re.caps {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
290 result[v] = k
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
291 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
292 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
293
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
294 return result
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
295 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
296
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
297 // GroupNameFromNumber retrieves a group name that corresponds to a group number.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
298 // It will return "" for and unknown group number. Unnamed groups automatically
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
299 // receive a name that is the decimal string equivalent of its number.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
300 func (re *Regexp) GroupNameFromNumber(i int) string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
301 if re.capslist == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
302 if i >= 0 && i < re.capsize {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
303 return strconv.Itoa(i)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
304 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
305
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
306 return ""
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
307 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
308
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
309 if re.caps != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
310 var ok bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
311 if i, ok = re.caps[i]; !ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
312 return ""
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
313 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
314 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
315
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
316 if i >= 0 && i < len(re.capslist) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
317 return re.capslist[i]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
318 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
319
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
320 return ""
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
321 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
322
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
323 // GroupNumberFromName returns a group number that corresponds to a group name.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
324 // Returns -1 if the name is not a recognized group name. Numbered groups
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
325 // automatically get a group name that is the decimal string equivalent of its number.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
326 func (re *Regexp) GroupNumberFromName(name string) int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
327 // look up name if we have a hashtable of names
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
328 if re.capnames != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
329 if k, ok := re.capnames[name]; ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
330 return k
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
331 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
332
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
333 return -1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
334 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
335
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
336 // convert to an int if it looks like a number
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
337 result := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
338 for i := 0; i < len(name); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
339 ch := name[i]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
340
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
341 if ch > '9' || ch < '0' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
342 return -1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
343 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
344
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
345 result *= 10
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
346 result += int(ch - '0')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
347 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
348
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
349 // return int if it's in range
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
350 if result >= 0 && result < re.capsize {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
351 return result
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
352 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
353
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
354 return -1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
355 }