52 lines
1.1 KiB
Go
52 lines
1.1 KiB
Go
|
package q
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"regexp"
|
||
|
"sync"
|
||
|
)
|
||
|
|
||
|
// Re creates a regexp matcher. It checks if the given field matches the given regexp.
|
||
|
// Note that this only supports fields of type string or []byte.
|
||
|
func Re(field string, re string) Matcher {
|
||
|
regexpCache.RLock()
|
||
|
if r, ok := regexpCache.m[re]; ok {
|
||
|
regexpCache.RUnlock()
|
||
|
return NewFieldMatcher(field, ®expMatcher{r: r})
|
||
|
}
|
||
|
regexpCache.RUnlock()
|
||
|
|
||
|
regexpCache.Lock()
|
||
|
r, err := regexp.Compile(re)
|
||
|
if err == nil {
|
||
|
regexpCache.m[re] = r
|
||
|
}
|
||
|
regexpCache.Unlock()
|
||
|
|
||
|
return NewFieldMatcher(field, ®expMatcher{r: r, err: err})
|
||
|
}
|
||
|
|
||
|
var regexpCache = struct {
|
||
|
sync.RWMutex
|
||
|
m map[string]*regexp.Regexp
|
||
|
}{m: make(map[string]*regexp.Regexp)}
|
||
|
|
||
|
type regexpMatcher struct {
|
||
|
r *regexp.Regexp
|
||
|
err error
|
||
|
}
|
||
|
|
||
|
func (r *regexpMatcher) MatchField(v interface{}) (bool, error) {
|
||
|
if r.err != nil {
|
||
|
return false, r.err
|
||
|
}
|
||
|
switch fieldValue := v.(type) {
|
||
|
case string:
|
||
|
return r.r.MatchString(fieldValue), nil
|
||
|
case []byte:
|
||
|
return r.r.Match(fieldValue), nil
|
||
|
default:
|
||
|
return false, fmt.Errorf("Only string and []byte supported for regexp matcher, got %T", fieldValue)
|
||
|
}
|
||
|
}
|