youtubebeat/vendor/github.com/elastic/beats/libbeat/common/match/matcher.go

164 lines
3.8 KiB
Go

// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package match
import "regexp/syntax"
type Matcher struct {
stringMatcher
}
type ExactMatcher struct {
stringMatcher
}
type stringMatcher interface {
// MatchString tries to find a matching substring.
MatchString(s string) (matched bool)
// Match tries to find a matching substring.
Match(bs []byte) (matched bool)
// Describe the generator
String() string
}
func MustCompile(pattern string) Matcher {
m, err := Compile(pattern)
if err != nil {
panic(err)
}
return m
}
func MustCompileExact(pattern string) ExactMatcher {
m, err := CompileExact(pattern)
if err != nil {
panic(err)
}
return m
}
// CompileString matches a substring only, the input is not interpreted as
// regular expression
func CompileString(in string) (Matcher, error) {
if in == "" {
return Matcher{(*emptyStringMatcher)(nil)}, nil
}
return Matcher{&substringMatcher{in, []byte(in)}}, nil
}
// Compile regular expression to string matcher. String matcher by default uses
// regular expressions as provided by regexp library, but tries to optimize some
// common cases, replacing expensive patterns with cheaper custom implementations
// or removing terms not necessary for string matching.
func Compile(pattern string) (Matcher, error) {
regex, err := syntax.Parse(pattern, syntax.Perl)
if err != nil {
return Matcher{}, err
}
regex = optimize(regex).Simplify()
m, err := compile(regex)
return Matcher{m}, err
}
func CompileExact(pattern string) (ExactMatcher, error) {
regex, err := syntax.Parse(pattern, syntax.Perl)
if err != nil {
return ExactMatcher{}, err
}
regex = regex.Simplify()
if regex.Op != syntax.OpConcat {
regex = &syntax.Regexp{
Op: syntax.OpConcat,
Sub: []*syntax.Regexp{
patBeginText,
regex,
patEndText,
},
Flags: regex.Flags,
}
} else {
if !eqPrefixRegex(regex, patBeginText) {
regex.Sub = append([]*syntax.Regexp{patBeginText}, regex.Sub...)
}
if !eqSuffixRegex(regex, patEndText) {
regex.Sub = append(regex.Sub, patEndText)
}
}
regex = optimize(regex).Simplify()
m, err := compile(regex)
return ExactMatcher{m}, err
}
func (m *Matcher) Unpack(s string) error {
tmp, err := Compile(s)
if err != nil {
return err
}
*m = tmp
return nil
}
func (m *Matcher) MatchAnyString(strs []string) bool {
return matchAnyStrings(m.stringMatcher, strs)
}
func (m *Matcher) MatchAllStrings(strs []string) bool {
return matchAllStrings(m.stringMatcher, strs)
}
func (m *ExactMatcher) MatchAnyString(strs []string) bool {
return matchAnyStrings(m.stringMatcher, strs)
}
func (m *ExactMatcher) MatchAllStrings(strs []string) bool {
return matchAllStrings(m.stringMatcher, strs)
}
func (m *ExactMatcher) Unpack(s string) error {
tmp, err := CompileExact(s)
if err != nil {
return err
}
*m = tmp
return nil
}
func matchAnyStrings(m stringMatcher, strs []string) bool {
for _, s := range strs {
if m.MatchString(s) {
return true
}
}
return false
}
func matchAllStrings(m stringMatcher, strs []string) bool {
for _, s := range strs {
if !m.MatchString(s) {
return false
}
}
return true
}