|
|
|
@ -8,19 +8,27 @@ import (
|
|
|
|
|
"v2ray.com/core/common/task"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Matcher is the interface to determine a string matches a pattern.
|
|
|
|
|
type Matcher interface {
|
|
|
|
|
// Match returns true if the given string matches a predefined pattern.
|
|
|
|
|
Match(string) bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type is the type of the matcher.
|
|
|
|
|
type Type byte
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
// Full is the type of matcher that the input string must exactly equal to the pattern.
|
|
|
|
|
Full Type = iota
|
|
|
|
|
// Substr is the type of matcher that the input string must contain the pattern as a sub-string.
|
|
|
|
|
Substr
|
|
|
|
|
// Domain is the type of matcher that the input string must be a sub-domain or itself of the pattern.
|
|
|
|
|
Domain
|
|
|
|
|
// Regex is the type of matcher that the input string must matches the regular-expression pattern.
|
|
|
|
|
Regex
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// New creates a new Matcher based on the given pattern.
|
|
|
|
|
func (t Type) New(pattern string) (Matcher, error) {
|
|
|
|
|
switch t {
|
|
|
|
|
case Full:
|
|
|
|
@ -42,8 +50,10 @@ func (t Type) New(pattern string) (Matcher, error) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IndexMatcher is the interface for matching with a group of matchers.
|
|
|
|
|
type IndexMatcher interface {
|
|
|
|
|
Match(pattern string) uint32
|
|
|
|
|
// Match returns the the index of a matcher that matches the input. It returns 0 if no such matcher exists.
|
|
|
|
|
Match(input string) uint32
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type matcherEntry struct {
|
|
|
|
@ -51,6 +61,8 @@ type matcherEntry struct {
|
|
|
|
|
id uint32
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MatcherGroup is an implementation of IndexMatcher.
|
|
|
|
|
// Empty initialization works.
|
|
|
|
|
type MatcherGroup struct {
|
|
|
|
|
count uint32
|
|
|
|
|
fullMatcher FullMatcherGroup
|
|
|
|
@ -58,10 +70,7 @@ type MatcherGroup struct {
|
|
|
|
|
otherMatchers []matcherEntry
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewMatcherGroup() *MatcherGroup {
|
|
|
|
|
return &MatcherGroup{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add adds a new Matcher into the MatcherGroup, and returns its index. The index will never be 0.
|
|
|
|
|
func (g *MatcherGroup) Add(m Matcher) uint32 {
|
|
|
|
|
g.count++
|
|
|
|
|
c := g.count
|
|
|
|
@ -81,6 +90,7 @@ func (g *MatcherGroup) Add(m Matcher) uint32 {
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Match implements IndexMatcher.Match.
|
|
|
|
|
func (g *MatcherGroup) Match(pattern string) uint32 {
|
|
|
|
|
if c := g.fullMatcher.Match(pattern); c > 0 {
|
|
|
|
|
return c
|
|
|
|
@ -99,6 +109,7 @@ func (g *MatcherGroup) Match(pattern string) uint32 {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Size returns the number of matchers in the MatcherGroup.
|
|
|
|
|
func (g *MatcherGroup) Size() uint32 {
|
|
|
|
|
return g.count
|
|
|
|
|
}
|
|
|
|
@ -108,6 +119,7 @@ type cacheEntry struct {
|
|
|
|
|
result uint32
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CachedMatcherGroup is a IndexMatcher with cachable results.
|
|
|
|
|
type CachedMatcherGroup struct {
|
|
|
|
|
sync.RWMutex
|
|
|
|
|
group *MatcherGroup
|
|
|
|
@ -115,6 +127,7 @@ type CachedMatcherGroup struct {
|
|
|
|
|
cleanup *task.Periodic
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewCachedMatcherGroup creats a new CachedMatcherGroup.
|
|
|
|
|
func NewCachedMatcherGroup(g *MatcherGroup) *CachedMatcherGroup {
|
|
|
|
|
r := &CachedMatcherGroup{
|
|
|
|
|
group: g,
|
|
|
|
@ -139,6 +152,7 @@ func NewCachedMatcherGroup(g *MatcherGroup) *CachedMatcherGroup {
|
|
|
|
|
return r
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Match implements IndexMatcher.Match.
|
|
|
|
|
func (g *CachedMatcherGroup) Match(pattern string) uint32 {
|
|
|
|
|
g.RLock()
|
|
|
|
|
r, f := g.cache[pattern]
|
|
|
|
|