github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/common/strmatcher/strmatcher.go (about) 1 package strmatcher 2 3 import ( 4 "regexp" 5 ) 6 7 // Matcher is the interface to determine a string matches a pattern. 8 type Matcher interface { 9 // Match returns true if the given string matches a predefined pattern. 10 Match(string) bool 11 String() string 12 } 13 14 // Type is the type of the matcher. 15 type Type byte 16 17 const ( 18 // Full is the type of matcher that the input string must exactly equal to the pattern. 19 Full Type = iota 20 // Substr is the type of matcher that the input string must contain the pattern as a sub-string. 21 Substr 22 // Domain is the type of matcher that the input string must be a sub-domain or itself of the pattern. 23 Domain 24 // Regex is the type of matcher that the input string must matches the regular-expression pattern. 25 Regex 26 ) 27 28 // New creates a new Matcher based on the given pattern. 29 func (t Type) New(pattern string) (Matcher, error) { 30 switch t { 31 case Full: 32 return fullMatcher(pattern), nil 33 case Substr: 34 return substrMatcher(pattern), nil 35 case Domain: 36 return domainMatcher(pattern), nil 37 case Regex: 38 r, err := regexp.Compile(pattern) 39 if err != nil { 40 return nil, err 41 } 42 return ®exMatcher{ 43 pattern: r, 44 }, nil 45 default: 46 panic("Unknown type") 47 } 48 } 49 50 // IndexMatcher is the interface for matching with a group of matchers. 51 type IndexMatcher interface { 52 // Match returns the index of a matcher that matches the input. It returns empty array if no such matcher exists. 53 Match(input string) []uint32 54 } 55 56 type matcherEntry struct { 57 m Matcher 58 id uint32 59 } 60 61 // MatcherGroup is an implementation of IndexMatcher. 62 // Empty initialization works. 63 type MatcherGroup struct { 64 count uint32 65 fullMatcher FullMatcherGroup 66 domainMatcher DomainMatcherGroup 67 otherMatchers []matcherEntry 68 } 69 70 // Add adds a new Matcher into the MatcherGroup, and returns its index. The index will never be 0. 71 func (g *MatcherGroup) Add(m Matcher) uint32 { 72 g.count++ 73 c := g.count 74 75 switch tm := m.(type) { 76 case fullMatcher: 77 g.fullMatcher.addMatcher(tm, c) 78 case domainMatcher: 79 g.domainMatcher.addMatcher(tm, c) 80 default: 81 g.otherMatchers = append(g.otherMatchers, matcherEntry{ 82 m: m, 83 id: c, 84 }) 85 } 86 87 return c 88 } 89 90 // Match implements IndexMatcher.Match. 91 func (g *MatcherGroup) Match(pattern string) []uint32 { 92 result := []uint32{} 93 result = append(result, g.fullMatcher.Match(pattern)...) 94 result = append(result, g.domainMatcher.Match(pattern)...) 95 for _, e := range g.otherMatchers { 96 if e.m.Match(pattern) { 97 result = append(result, e.id) 98 } 99 } 100 return result 101 } 102 103 // Size returns the number of matchers in the MatcherGroup. 104 func (g *MatcherGroup) Size() uint32 { 105 return g.count 106 }