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

136 lines
2.9 KiB
Go
Raw Normal View History

2018-11-18 11:08:38 +01:00
// 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"
"regexp/syntax"
)
func compile(r *syntax.Regexp) (stringMatcher, error) {
switch {
case r.Op == syntax.OpLiteral:
s := string(r.Rune)
return &substringMatcher{s, []byte(s)}, nil
case isExactLiteral(r):
s := string(r.Sub[1].Rune)
return &equalsMatcher{s, []byte(s)}, nil
case isAltLiterals(r):
var literals [][]byte
for _, sub := range r.Sub {
literals = append(literals, []byte(string(sub.Rune)))
}
return &altSubstringMatcher{literals}, nil
case isOneOfLiterals(r):
var literals [][]byte
for _, sub := range r.Sub[1].Sub {
literals = append(literals, []byte(string(sub.Rune)))
}
return &oneOfMatcher{literals}, nil
case isPrefixLiteral(r):
s := []byte(string(r.Sub[1].Rune))
return &prefixMatcher{s}, nil
case isPrefixAltLiterals(r):
var literals [][]byte
for _, sub := range r.Sub[1].Sub {
literals = append(literals, []byte(string(sub.Rune)))
}
return &altPrefixMatcher{literals}, nil
case isPrefixNumDate(r):
return compilePrefixNumDate(r)
case isEmptyText(r):
var m *emptyStringMatcher
return m, nil
case isEmptyTextWithWhitespace(r):
var m *emptyWhiteStringMatcher
return m, nil
case isAnyMatch(r):
var m *matchAny
return m, nil
default:
r, err := regexp.Compile(r.String())
if err != nil {
return nil, err
}
return r, nil
}
}
func compilePrefixNumDate(r *syntax.Regexp) (stringMatcher, error) {
m := &prefixNumDate{}
i := 1
if r.Sub[i].Op == syntax.OpLiteral {
m.prefix = []byte(string(r.Sub[i].Rune))
i++
}
digitLen := func(r *syntax.Regexp) int {
if r.Op == syntax.OpConcat {
return len(r.Sub)
}
return 1
}
var digits []int
var seps [][]byte
digits = append(digits, digitLen(r.Sub[i]))
i++
for i < len(r.Sub) {
lit := []byte(string(r.Sub[i].Rune))
i++
// capture literal suffix
if i == len(r.Sub) {
m.suffix = lit
break
}
seps = append(seps, lit)
digits = append(digits, digitLen(r.Sub[i]))
i++
}
minLen := len(m.prefix) + len(m.suffix)
for _, d := range digits {
minLen += d
}
for _, sep := range seps {
minLen += len(sep)
}
m.digits = digits
m.seps = seps
m.minLen = minLen
return m, nil
}