github.com/imannamdari/v2ray-core/v5@v5.0.5/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  }