Repository navigation
Expand file tree
/
Copy pathregexp_codegen.go
More file actions
88 lines (80 loc) · 2.84 KB
/
Copy pathregexp_codegen.go
File metadata and controls
88 lines (80 loc) · 2.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package regexp2
import (
"sync"
)
type RuntimeEngineData struct {
Caps map[int]int // capnum->index
CapNames map[string]int // cap group name -> index
CapsList []string // sorted list of capture group names
CapSize int // size of the capture array
FindFirstChar func(*Runner) bool // generated candidate search
Execute func(*Runner) error
ExecuteQuick func(*Runner) error // optional bool-only execution with unobservable captures removed
StringPrefixFilter StringPrefixFilter // optional pre-decode candidate search for string input
// LeftContextKnown reports that LeftContextRunes was computed by the
// code generator. If it is false, decoded string input is never sliced;
// older generated engines omit the field and must keep the full string.
LeftContextKnown bool
// LeftContextRunes is how many runes before a candidate start matching
// may inspect. 0 means none, 1 means a single previous rune, and -1
// means do not slice (lookbehind or \G). Ignored unless LeftContextKnown.
LeftContextRunes int
}
type cacheKey struct {
pattern string
opt RegexOptions
maintainCaptureOrder bool
maxBacktrackingStackSize int
}
func RegisterEngine(pattern string, engine RuntimeEngineData, options ...CompileOption) {
c := newCompileConfig(options)
enginesMu.Lock()
engines[cacheKeyFromConfig(pattern, c)] = engine
enginesMu.Unlock()
}
func newEngineRegexp(pattern string, c compileConfig, engine RuntimeEngineData) *Regexp {
leftContext := -1
if engine.LeftContextKnown {
leftContext = engine.LeftContextRunes
}
re := &Regexp{
pattern: pattern,
options: c.regexOptions,
debug: c.debug,
caps: engine.Caps,
capnames: engine.CapNames,
capslist: engine.CapsList,
capsize: engine.CapSize,
MatchTimeout: DefaultMatchTimeout,
optimizations: c.optimizations,
findFirstChar: engine.FindFirstChar,
execute: engine.Execute,
executeQuick: engine.ExecuteQuick,
stringPrefixFilter: engine.StringPrefixFilter,
leftContextRunes: leftContext,
}
re.initCaptureNames()
re.initCaches()
return re
}
func getEngineRegexp(pattern string, c compileConfig) *Regexp {
enginesMu.RLock()
engine, ok := engines[cacheKeyFromConfig(pattern, c)]
enginesMu.RUnlock()
if !ok {
return nil
}
return newEngineRegexp(pattern, c, engine)
}
func cacheKeyFromConfig(pattern string, c compileConfig) cacheKey {
return cacheKey{
pattern: pattern,
opt: c.regexOptions,
maintainCaptureOrder: c.maintainCaptureOrder,
maxBacktrackingStackSize: c.optimizations.MaxBacktrackingStackSize,
}
}
var (
enginesMu sync.RWMutex
engines = map[cacheKey]RuntimeEngineData{}
)