github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/common/strmatcher/indexmatcher_mph.go (about) 1 package strmatcher 2 3 // A MphIndexMatcher is divided into three parts: 4 // 1. `full` and `domain` patterns are matched by Rabin-Karp algorithm and minimal perfect hash table; 5 // 2. `substr` patterns are matched by ac automaton; 6 // 3. `regex` patterns are matched with the regex library. 7 type MphIndexMatcher struct { 8 count uint32 9 mph *MphMatcherGroup 10 ac *ACAutomatonMatcherGroup 11 regex *SimpleMatcherGroup 12 } 13 14 func NewMphIndexMatcher() *MphIndexMatcher { 15 return new(MphIndexMatcher) 16 } 17 18 // Add implements IndexMatcher.Add. 19 func (g *MphIndexMatcher) Add(matcher Matcher) uint32 { 20 g.count++ 21 index := g.count 22 23 switch matcher := matcher.(type) { 24 case FullMatcher: 25 if g.mph == nil { 26 g.mph = NewMphMatcherGroup() 27 } 28 g.mph.AddFullMatcher(matcher, index) 29 case DomainMatcher: 30 if g.mph == nil { 31 g.mph = NewMphMatcherGroup() 32 } 33 g.mph.AddDomainMatcher(matcher, index) 34 case SubstrMatcher: 35 if g.ac == nil { 36 g.ac = NewACAutomatonMatcherGroup() 37 } 38 g.ac.AddSubstrMatcher(matcher, index) 39 case *RegexMatcher: 40 if g.regex == nil { 41 g.regex = &SimpleMatcherGroup{} 42 } 43 g.regex.AddMatcher(matcher, index) 44 } 45 46 return index 47 } 48 49 // Build implements IndexMatcher.Build. 50 func (g *MphIndexMatcher) Build() error { 51 if g.mph != nil { 52 g.mph.Build() 53 } 54 if g.ac != nil { 55 g.ac.Build() 56 } 57 return nil 58 } 59 60 // Match implements IndexMatcher.Match. 61 func (g *MphIndexMatcher) Match(input string) []uint32 { 62 result := make([][]uint32, 0, 5) 63 if g.mph != nil { 64 if matches := g.mph.Match(input); len(matches) > 0 { 65 result = append(result, matches) 66 } 67 } 68 if g.ac != nil { 69 if matches := g.ac.Match(input); len(matches) > 0 { 70 result = append(result, matches) 71 } 72 } 73 if g.regex != nil { 74 if matches := g.regex.Match(input); len(matches) > 0 { 75 result = append(result, matches) 76 } 77 } 78 return CompositeMatches(result) 79 } 80 81 // MatchAny implements IndexMatcher.MatchAny. 82 func (g *MphIndexMatcher) MatchAny(input string) bool { 83 if g.mph != nil && g.mph.MatchAny(input) { 84 return true 85 } 86 if g.ac != nil && g.ac.MatchAny(input) { 87 return true 88 } 89 return g.regex != nil && g.regex.MatchAny(input) 90 } 91 92 // Size implements IndexMatcher.Size. 93 func (g *MphIndexMatcher) Size() uint32 { 94 return g.count 95 }