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  }