github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/common/strmatcher/indexmatcher_linear.go (about)

     1  package strmatcher
     2  
     3  // LinearIndexMatcher is an implementation of IndexMatcher.
     4  type LinearIndexMatcher struct {
     5  	count  uint32
     6  	full   *FullMatcherGroup
     7  	domain *DomainMatcherGroup
     8  	substr *SubstrMatcherGroup
     9  	regex  *SimpleMatcherGroup
    10  }
    11  
    12  func NewLinearIndexMatcher() *LinearIndexMatcher {
    13  	return new(LinearIndexMatcher)
    14  }
    15  
    16  // Add implements IndexMatcher.Add.
    17  func (g *LinearIndexMatcher) Add(matcher Matcher) uint32 {
    18  	g.count++
    19  	index := g.count
    20  
    21  	switch matcher := matcher.(type) {
    22  	case FullMatcher:
    23  		if g.full == nil {
    24  			g.full = NewFullMatcherGroup()
    25  		}
    26  		g.full.AddFullMatcher(matcher, index)
    27  	case DomainMatcher:
    28  		if g.domain == nil {
    29  			g.domain = NewDomainMatcherGroup()
    30  		}
    31  		g.domain.AddDomainMatcher(matcher, index)
    32  	case SubstrMatcher:
    33  		if g.substr == nil {
    34  			g.substr = new(SubstrMatcherGroup)
    35  		}
    36  		g.substr.AddSubstrMatcher(matcher, index)
    37  	default:
    38  		if g.regex == nil {
    39  			g.regex = new(SimpleMatcherGroup)
    40  		}
    41  		g.regex.AddMatcher(matcher, index)
    42  	}
    43  
    44  	return index
    45  }
    46  
    47  // Build implements IndexMatcher.Build.
    48  func (*LinearIndexMatcher) Build() error {
    49  	return nil
    50  }
    51  
    52  // Match implements IndexMatcher.Match.
    53  func (g *LinearIndexMatcher) Match(input string) []uint32 {
    54  	// Allocate capacity to prevent matches escaping to heap
    55  	result := make([][]uint32, 0, 5)
    56  	if g.full != nil {
    57  		if matches := g.full.Match(input); len(matches) > 0 {
    58  			result = append(result, matches)
    59  		}
    60  	}
    61  	if g.domain != nil {
    62  		if matches := g.domain.Match(input); len(matches) > 0 {
    63  			result = append(result, matches)
    64  		}
    65  	}
    66  	if g.substr != nil {
    67  		if matches := g.substr.Match(input); len(matches) > 0 {
    68  			result = append(result, matches)
    69  		}
    70  	}
    71  	if g.regex != nil {
    72  		if matches := g.regex.Match(input); len(matches) > 0 {
    73  			result = append(result, matches)
    74  		}
    75  	}
    76  	return CompositeMatches(result)
    77  }
    78  
    79  // MatchAny implements IndexMatcher.MatchAny.
    80  func (g *LinearIndexMatcher) MatchAny(input string) bool {
    81  	if g.full != nil && g.full.MatchAny(input) {
    82  		return true
    83  	}
    84  	if g.domain != nil && g.domain.MatchAny(input) {
    85  		return true
    86  	}
    87  	if g.substr != nil && g.substr.MatchAny(input) {
    88  		return true
    89  	}
    90  	return g.regex != nil && g.regex.MatchAny(input)
    91  }
    92  
    93  // Size implements IndexMatcher.Size.
    94  func (g *LinearIndexMatcher) Size() uint32 {
    95  	return g.count
    96  }