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 &regexMatcher{
    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  }