github.com/anuvu/tyk@v2.9.0-beta9-dl-apic+incompatible/regexp/regexp.go (about) 1 /* 2 Package regexp implmenets API of Go's native "regexp" but with caching results in memory 3 */ 4 package regexp 5 6 import ( 7 "io" 8 "regexp" 9 "strconv" 10 "time" 11 ) 12 13 var ( 14 compileCache = newRegexpCache(defaultCacheItemTTL, true, regexp.Compile) 15 compilePOSIXCache = newRegexpCache(defaultCacheItemTTL, true, regexp.CompilePOSIX) 16 matchStringCache = newRegexpStrRetBoolCache(defaultCacheItemTTL, true) 17 matchCache = newRegexpByteRetBoolCache(defaultCacheItemTTL, true) 18 replaceAllStringCache = newRegexpStrStrRetStrCache(defaultCacheItemTTL, true) 19 replaceAllLiteralStringCache = newRegexpStrStrRetStrCache(defaultCacheItemTTL, true) 20 replaceAllStringFuncCache = newRegexpStrFuncRetStrCache(defaultCacheItemTTL, true) 21 findStringSubmatchCache = newRegexpStrRetSliceStrCache(defaultCacheItemTTL, true) 22 findAllStringCache = newRegexpStrIntRetSliceStrCache(defaultCacheItemTTL, true) 23 findAllStringSubmatchCache = newRegexpStrIntRetSliceSliceStrCache(defaultCacheItemTTL, true) 24 ) 25 26 // Regexp is a wrapper around regexp.Regexp but with caching 27 type Regexp struct { 28 *regexp.Regexp 29 FromCache bool 30 } 31 32 // ResetCache resets cache to initial state 33 func ResetCache(ttl time.Duration, isEnabled bool) { 34 if ttl == 0 { 35 ttl = defaultCacheItemTTL 36 } 37 38 compileCache.reset(ttl, isEnabled) 39 compilePOSIXCache.reset(ttl, isEnabled) 40 matchStringCache.reset(ttl, isEnabled) 41 matchCache.reset(ttl, isEnabled) 42 replaceAllStringCache.reset(ttl, isEnabled) 43 replaceAllLiteralStringCache.reset(ttl, isEnabled) 44 replaceAllStringFuncCache.reset(ttl, isEnabled) 45 findStringSubmatchCache.reset(ttl, isEnabled) 46 findAllStringCache.reset(ttl, isEnabled) 47 findAllStringSubmatchCache.reset(ttl, isEnabled) 48 } 49 50 // Compile does the same as regexp.Compile but returns cached *Regexp instead. 51 func Compile(expr string) (*Regexp, error) { 52 return compileCache.do(expr) 53 } 54 55 // CompilePOSIX does the same as regexp.CompilePOSIX but returns cached *Regexp instead. 56 func CompilePOSIX(expr string) (*Regexp, error) { 57 return compilePOSIXCache.do(expr) 58 } 59 60 // MustCompile is the same as regexp.MustCompile but returns cached *Regexp instead. 61 func MustCompile(str string) *Regexp { 62 regexp, err := Compile(str) 63 if err != nil { 64 panic(`regexp: Compile(` + quote(str) + `): ` + err.Error()) 65 } 66 return regexp 67 } 68 69 // MustCompilePOSIX is the same as regexp.MustCompilePOSIX but returns cached *Regexp instead. 70 func MustCompilePOSIX(str string) *Regexp { 71 regexp, err := CompilePOSIX(str) 72 if err != nil { 73 panic(`regexp: CompilePOSIX(` + quote(str) + `): ` + err.Error()) 74 } 75 return regexp 76 } 77 78 // MatchString is the same as regexp.MatchString but returns cached result instead. 79 func MatchString(pattern string, s string) (matched bool, err error) { 80 re, err := Compile(pattern) 81 if err != nil { 82 return false, err 83 } 84 return re.MatchString(s), nil 85 } 86 87 // Match is the same as regexp.Match but returns cached result instead. 88 func Match(pattern string, b []byte) (matched bool, err error) { 89 re, err := Compile(pattern) 90 if err != nil { 91 return false, err 92 } 93 return re.Match(b), nil 94 } 95 96 // QuoteMeta is the same as regexp.QuoteMeta but returns cached result instead. 97 func QuoteMeta(s string) string { 98 // TODO: add cache for QuoteMeta 99 return regexp.QuoteMeta(s) 100 } 101 102 func quote(s string) string { 103 if strconv.CanBackquote(s) { 104 return "`" + s + "`" 105 } 106 return strconv.Quote(s) 107 } 108 109 // String returns the source text used to compile the wrapped regular expression. 110 func (re *Regexp) String() string { 111 if re.Regexp == nil { 112 return "" 113 } 114 return re.Regexp.String() 115 } 116 117 // Copy returns a new Regexp object copied from re. 118 // 119 // When using a Regexp in multiple goroutines, giving each goroutine 120 // its own copy helps to avoid lock contention. 121 func (re *Regexp) Copy() *Regexp { 122 reCopy := &Regexp{ 123 FromCache: re.FromCache, 124 } 125 if re.Regexp != nil { 126 reCopy.Regexp = re.Regexp.Copy() 127 } 128 return reCopy 129 } 130 131 // Longest calls regexp.Regexp.Longest of wrapped regular expression 132 func (re *Regexp) Longest() { 133 if re.Regexp == nil { 134 re.Regexp.Longest() 135 } 136 } 137 138 // NumSubexp returns result of regexp.Regexp.NumSubexp of wrapped regular expression. 139 func (re *Regexp) NumSubexp() int { 140 if re.Regexp == nil { 141 return 0 142 } 143 return re.Regexp.NumSubexp() 144 } 145 146 // SubexpNames returns result of regexp.Regexp.SubexpNames of wrapped regular expression. 147 func (re *Regexp) SubexpNames() []string { 148 if re.Regexp == nil { 149 return []string{} 150 } 151 return re.Regexp.SubexpNames() 152 } 153 154 // LiteralPrefix returns a literal string that must begin any match 155 // Calls regexp.Regexp.LiteralPrefix 156 func (re *Regexp) LiteralPrefix() (prefix string, complete bool) { 157 if re.Regexp == nil { 158 return "", false 159 } 160 return re.Regexp.LiteralPrefix() 161 } 162 163 // MatchReader reports whether the Regexp matches the text read by the 164 // RuneReader. 165 // Calls regexp.Regexp.MatchReader (NO CACHE) 166 func (re *Regexp) MatchReader(r io.RuneReader) bool { 167 if re.Regexp == nil { 168 return false 169 } 170 return re.Regexp.MatchReader(r) 171 } 172 173 // MatchString reports whether the Regexp matches the string s. 174 func (re *Regexp) MatchString(s string) bool { 175 if re.Regexp == nil { 176 return false 177 } 178 return matchStringCache.do(re.Regexp, s, re.Regexp.MatchString) 179 } 180 181 // Match reports whether the Regexp matches the byte slice b. 182 func (re *Regexp) Match(b []byte) bool { 183 if re.Regexp == nil { 184 return false 185 } 186 return matchCache.do(re.Regexp, b, re.Regexp.Match) 187 } 188 189 // ReplaceAllString is the same as regexp.Regexp.ReplaceAllString but returns cached result instead. 190 func (re *Regexp) ReplaceAllString(src, repl string) string { 191 if re.Regexp == nil { 192 return "" 193 } 194 return replaceAllStringCache.do(re.Regexp, src, repl, re.Regexp.ReplaceAllString) 195 } 196 197 // ReplaceAllLiteralString is the same as regexp.Regexp.ReplaceAllLiteralString but returns cached result instead. 198 func (re *Regexp) ReplaceAllLiteralString(src, repl string) string { 199 if re.Regexp == nil { 200 return "" 201 } 202 return replaceAllLiteralStringCache.do(re.Regexp, src, repl, re.Regexp.ReplaceAllLiteralString) 203 } 204 205 // ReplaceAllStringFunc is the same as regexp.Regexp.ReplaceAllStringFunc but returns cached result instead. 206 func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string { 207 if re.Regexp == nil { 208 return "" 209 } 210 return replaceAllStringFuncCache.do(re.Regexp, src, repl, re.Regexp.ReplaceAllStringFunc) 211 } 212 213 // ReplaceAll is the same as regexp.Regexp.ReplaceAll but returns cached result instead. 214 func (re *Regexp) ReplaceAll(src, repl []byte) []byte { 215 if re.Regexp == nil { 216 return []byte{} 217 } 218 // TODO: add cache for ReplaceAll 219 return re.Regexp.ReplaceAll(src, repl) 220 } 221 222 // ReplaceAllLiteral is the same as regexp.Regexp.ReplaceAllLiteral but returns cached result instead. 223 func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte { 224 if re.Regexp == nil { 225 return []byte{} 226 } 227 // TODO: add cache for ReplaceAllLiteral 228 return re.Regexp.ReplaceAllLiteral(src, repl) 229 } 230 231 // ReplaceAllFunc is the same as regexp.Regexp.ReplaceAllFunc but returns cached result instead. 232 func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte { 233 if re.Regexp == nil { 234 return []byte{} 235 } 236 // TODO: add cache for ReplaceAllFunc 237 return re.Regexp.ReplaceAllFunc(src, repl) 238 } 239 240 // Find is the same as regexp.Regexp.Find but returns cached result instead. 241 func (re *Regexp) Find(b []byte) []byte { 242 if re.Regexp == nil { 243 return []byte{} 244 } 245 // TODO: add cache for Find 246 return re.Regexp.Find(b) 247 } 248 249 // FindIndex is the same as regexp.Regexp.FindIndex but returns cached result instead. 250 func (re *Regexp) FindIndex(b []byte) (loc []int) { 251 if re.Regexp == nil { 252 return 253 } 254 // TODO: add cache for FindIndex 255 return re.Regexp.FindIndex(b) 256 } 257 258 // FindString is the same as regexp.Regexp.FindString but returns cached result instead. 259 func (re *Regexp) FindString(s string) string { 260 if re.Regexp == nil { 261 return "" 262 } 263 // TODO: add cache for FindString 264 return re.Regexp.FindString(s) 265 } 266 267 // FindStringIndex is the same as regexp.Regexp.FindStringIndex but returns cached result instead. 268 func (re *Regexp) FindStringIndex(s string) (loc []int) { 269 if re.Regexp == nil { 270 return 271 } 272 // TODO: add cache for FindStringIndex 273 return re.Regexp.FindStringIndex(s) 274 } 275 276 // FindReaderIndex is the same as regexp.Regexp.FindReaderIndex (NO CACHE). 277 func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int) { 278 if re.Regexp == nil { 279 return 280 } 281 return re.Regexp.FindReaderIndex(r) 282 } 283 284 // FindSubmatch is the same as regexp.Regexp.FindSubmatch but returns cached result instead. 285 func (re *Regexp) FindSubmatch(b []byte) [][]byte { 286 if re.Regexp == nil { 287 return [][]byte{} 288 } 289 // TODO: add cache for FindSubmatch 290 return re.Regexp.FindSubmatch(b) 291 } 292 293 // Expand is the same as regexp.Regexp.Expand but returns cached result instead. 294 func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte { 295 if re.Regexp == nil { 296 return []byte{} 297 } 298 // TODO: add cache for Expand 299 return re.Regexp.Expand(dst, template, src, match) 300 } 301 302 // ExpandString is the same as regexp.Regexp.ExpandString but returns cached result instead. 303 func (re *Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte { 304 if re.Regexp == nil { 305 return []byte{} 306 } 307 // TODO: add cache for ExpandString 308 return re.Regexp.ExpandString(dst, template, src, match) 309 } 310 311 // FindSubmatchIndex is the same as regexp.Regexp.FindSubmatchIndex but returns cached result instead. 312 func (re *Regexp) FindSubmatchIndex(b []byte) []int { 313 if re.Regexp == nil { 314 return []int{} 315 } 316 // TODO: add cache for ExpandString 317 return re.Regexp.FindSubmatchIndex(b) 318 } 319 320 // FindStringSubmatch is the same as regexp.Regexp.FindStringSubmatch but returns cached result instead. 321 func (re *Regexp) FindStringSubmatch(s string) []string { 322 if re.Regexp == nil { 323 return []string{} 324 } 325 return findStringSubmatchCache.do(re.Regexp, s, re.Regexp.FindStringSubmatch) 326 } 327 328 // FindStringSubmatchIndex is the same as regexp.Regexp.FindStringSubmatchIndex but returns cached result instead. 329 func (re *Regexp) FindStringSubmatchIndex(s string) []int { 330 if re.Regexp == nil { 331 return []int{} 332 } 333 // TODO: add cache for FindStringSubmatchIndex 334 return re.Regexp.FindStringSubmatchIndex(s) 335 } 336 337 // FindReaderSubmatchIndex is the same as regexp.Regexp.FindReaderSubmatchIndex (NO CACHE). 338 func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int { 339 if re.Regexp == nil { 340 return []int{} 341 } 342 return re.Regexp.FindReaderSubmatchIndex(r) 343 } 344 345 // FindAll is the same as regexp.Regexp.FindAll but returns cached result instead. 346 func (re *Regexp) FindAll(b []byte, n int) [][]byte { 347 if re.Regexp == nil { 348 return [][]byte{} 349 } 350 // TODO: add cache for FindAll 351 return re.Regexp.FindAll(b, n) 352 } 353 354 // FindAllIndex is the same as regexp.Regexp.FindAllIndex but returns cached result instead. 355 func (re *Regexp) FindAllIndex(b []byte, n int) [][]int { 356 if re.Regexp == nil { 357 return [][]int{} 358 } 359 // TODO: add cache for FindAllIndex 360 return re.Regexp.FindAllIndex(b, n) 361 } 362 363 // FindAllString is the same as regexp.Regexp.FindAllString but returns cached result instead. 364 func (re *Regexp) FindAllString(s string, n int) []string { 365 if re.Regexp == nil { 366 return []string{} 367 } 368 return findAllStringCache.do(re.Regexp, s, n, re.Regexp.FindAllString) 369 } 370 371 // FindAllStringIndex is the same as regexp.Regexp.FindAllStringIndex but returns cached result instead. 372 func (re *Regexp) FindAllStringIndex(s string, n int) [][]int { 373 if re.Regexp == nil { 374 return [][]int{} 375 } 376 // TODO: add cache for FindAllStringIndex 377 return re.Regexp.FindAllStringIndex(s, n) 378 } 379 380 // FindAllSubmatch is the same as regexp.Regexp.FindAllSubmatch but returns cached result instead. 381 func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte { 382 if re.Regexp == nil { 383 return [][][]byte{} 384 } 385 // TODO: add cache for FindAllSubmatch 386 return re.Regexp.FindAllSubmatch(b, n) 387 } 388 389 // FindAllSubmatchIndex is the same as regexp.Regexp.FindAllSubmatchIndex but returns cached result instead. 390 func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int { 391 if re.Regexp == nil { 392 return [][]int{} 393 } 394 // TODO: add cache for FindAllSubmatchIndex 395 return re.Regexp.FindAllSubmatchIndex(b, n) 396 } 397 398 // FindAllStringSubmatch is the same as regexp.Regexp.FindAllStringSubmatch but returns cached result instead. 399 func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string { 400 if re.Regexp == nil { 401 return [][]string{} 402 } 403 return findAllStringSubmatchCache.do(re.Regexp, s, n, re.Regexp.FindAllStringSubmatch) 404 } 405 406 // FindAllStringSubmatchIndex is the same as regexp.Regexp.FindAllStringSubmatchIndex but returns cached result instead. 407 func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int { 408 if re.Regexp == nil { 409 return [][]int{} 410 } 411 // TODO: add cache for FindAllStringSubmatchIndex 412 return re.Regexp.FindAllStringSubmatchIndex(s, n) 413 } 414 415 // Split is the same as regexp.Regexp.Split but returns cached result instead. 416 func (re *Regexp) Split(s string, n int) []string { 417 if re.Regexp == nil { 418 return []string{} 419 } 420 // TODO: add cache for Split 421 return re.Regexp.Split(s, n) 422 }