-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstl.gregex.go
179 lines (157 loc) · 5.55 KB
/
stl.gregex.go
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package stl
import (
"regexp"
"sync"
)
type XPRegexpImpl struct {
}
// Quote quotes <s> by replacing special chars in <s>
// to match the rules of regular expression pattern.
// And returns the copy.
//
// Eg: Quote(`[foo]`) returns `\[foo\]`.
func (instance *XPRegexpImpl) Quote(s string) string {
return regexp.QuoteMeta(s)
}
// Validate checks whether given regular expression pattern <pattern> valid.
func (instance *XPRegexpImpl) Validate(pattern string) error {
_, err := getRegexp(pattern)
return err
}
// IsMatch checks whether given bytes <src> matches <pattern>.
func (instance *XPRegexpImpl) IsMatch(pattern string, src []byte) bool {
if r, err := getRegexp(pattern); err == nil {
return r.Match(src)
}
return false
}
// IsMatchString checks whether given string <src> matches <pattern>.
func (instance *XPRegexpImpl) IsMatchString(pattern string, src string) bool {
return instance.IsMatch(pattern, []byte(src))
}
// MatchString return bytes slice that matched <pattern>.
func (instance *XPRegexpImpl) Match(pattern string, src []byte) ([][]byte, error) {
if r, err := getRegexp(pattern); err == nil {
return r.FindSubmatch(src), nil
} else {
return nil, err
}
}
// MatchString return strings that matched <pattern>.
func (instance *XPRegexpImpl) MatchString(pattern string, src string) ([]string, error) {
if r, err := getRegexp(pattern); err == nil {
return r.FindStringSubmatch(src), nil
} else {
return nil, err
}
}
// MatchAll return all bytes slices that matched <pattern>.
func (instance *XPRegexpImpl) MatchAll(pattern string, src []byte) ([][][]byte, error) {
if r, err := getRegexp(pattern); err == nil {
return r.FindAllSubmatch(src, -1), nil
} else {
return nil, err
}
}
// MatchAllString return all strings that matched <pattern>.
func (instance *XPRegexpImpl) MatchAllString(pattern string, src string) ([][]string, error) {
if r, err := getRegexp(pattern); err == nil {
return r.FindAllStringSubmatch(src, -1), nil
} else {
return nil, err
}
}
// ReplaceString replace all matched <pattern> in bytes <src> with bytes <replace>.
func (instance *XPRegexpImpl) Replace(pattern string, replace, src []byte) ([]byte, error) {
if r, err := getRegexp(pattern); err == nil {
return r.ReplaceAll(src, replace), nil
} else {
return nil, err
}
}
// ReplaceString replace all matched <pattern> in string <src> with string <replace>.
func (instance *XPRegexpImpl) ReplaceString(pattern, replace, src string) (string, error) {
r, e := instance.Replace(pattern, []byte(replace), []byte(src))
return string(r), e
}
// ReplaceFunc replace all matched <pattern> in bytes <src>
// with custom replacement function <replaceFunc>.
func (instance *XPRegexpImpl) ReplaceFunc(pattern string, src []byte, replaceFunc func(b []byte) []byte) ([]byte, error) {
if r, err := getRegexp(pattern); err == nil {
return r.ReplaceAllFunc(src, replaceFunc), nil
} else {
return nil, err
}
}
// ReplaceFunc replace all matched <pattern> in bytes <src>
// with custom replacement function <replaceFunc>.
// The parameter <match> type for <replaceFunc> is [][]byte,
// which is the result contains all sub-patterns of <pattern> using Match function.
func (instance *XPRegexpImpl) ReplaceFuncMatch(pattern string, src []byte, replaceFunc func(match [][]byte) []byte) ([]byte, error) {
if r, err := getRegexp(pattern); err == nil {
return r.ReplaceAllFunc(src, func(bytes []byte) []byte {
match, _ := instance.Match(pattern, src)
return replaceFunc(match)
}), nil
} else {
return nil, err
}
}
// ReplaceStringFunc replace all matched <pattern> in string <src>
// with custom replacement function <replaceFunc>.
func (instance *XPRegexpImpl) ReplaceStringFunc(pattern string, src string, replaceFunc func(s string) string) (string, error) {
bytes, err := instance.ReplaceFunc(pattern, []byte(src), func(bytes []byte) []byte {
return []byte(replaceFunc(string(bytes)))
})
return string(bytes), err
}
// ReplaceStringFuncMatch replace all matched <pattern> in string <src>
// with custom replacement function <replaceFunc>.
// The parameter <match> type for <replaceFunc> is []string,
// which is the result contains all sub-patterns of <pattern> using MatchString function.
func (instance *XPRegexpImpl) ReplaceStringFuncMatch(pattern string, src string, replaceFunc func(match []string) string) (string, error) {
if r, err := getRegexp(pattern); err == nil {
return string(r.ReplaceAllFunc([]byte(src), func(bytes []byte) []byte {
match, _ := instance.MatchString(pattern, src)
return []byte(replaceFunc(match))
})), nil
} else {
return "", err
}
}
// Split slices <src> into substrings separated by the expression and returns a slice of
// the substrings between those expression matches.
func (instance *XPRegexpImpl) Split(pattern string, src string) []string {
if r, err := getRegexp(pattern); err == nil {
return r.Split(src, -1)
}
return nil
}
var (
regexMu = sync.RWMutex{}
regexMap = make(map[string]*regexp.Regexp)
)
func getRegexp(pattern string) (*regexp.Regexp, error) {
if r := getCache(pattern); r != nil {
return r, nil
}
if r, err := regexp.Compile(pattern); err == nil {
setCache(pattern, r)
return r, nil
} else {
return nil, err
}
}
// getCache returns *regexp.Regexp object from cache by given <pattern>, for internal usage.
func getCache(pattern string) (regex *regexp.Regexp) {
regexMu.RLock()
regex = regexMap[pattern]
regexMu.RUnlock()
return
}
// setCache stores *regexp.Regexp object into cache, for internal usage.
func setCache(pattern string, regex *regexp.Regexp) {
regexMu.Lock()
regexMap[pattern] = regex
regexMu.Unlock()
}