mirror of
				https://github.com/v2fly/v2ray-core.git
				synced 2025-10-31 01:39:16 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			89 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			89 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package strmatcher
 | |
| 
 | |
| import "strings"
 | |
| 
 | |
| func breakDomain(domain string) []string {
 | |
| 	return strings.Split(domain, ".")
 | |
| }
 | |
| 
 | |
| type node struct {
 | |
| 	value uint32
 | |
| 	sub   map[string]*node
 | |
| }
 | |
| 
 | |
| // DomainMatcherGroup is a IndexMatcher for a large set of Domain matchers.
 | |
| // Visible for testing only.
 | |
| type DomainMatcherGroup struct {
 | |
| 	root *node
 | |
| }
 | |
| 
 | |
| func (g *DomainMatcherGroup) Add(domain string, value uint32) {
 | |
| 	if g.root == nil {
 | |
| 		g.root = new(node)
 | |
| 	}
 | |
| 
 | |
| 	current := g.root
 | |
| 	parts := breakDomain(domain)
 | |
| 	for i := len(parts) - 1; i >= 0; i-- {
 | |
| 		if current.value > 0 {
 | |
| 			// if current node is already a match, it is not necessary to match further.
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		part := parts[i]
 | |
| 		if current.sub == nil {
 | |
| 			current.sub = make(map[string]*node)
 | |
| 		}
 | |
| 		next := current.sub[part]
 | |
| 		if next == nil {
 | |
| 			next = new(node)
 | |
| 			current.sub[part] = next
 | |
| 		}
 | |
| 		current = next
 | |
| 	}
 | |
| 
 | |
| 	current.value = value
 | |
| 	current.sub = nil // shortcut sub nodes as current node is a match.
 | |
| }
 | |
| 
 | |
| func (g *DomainMatcherGroup) addMatcher(m domainMatcher, value uint32) {
 | |
| 	g.Add(string(m), value)
 | |
| }
 | |
| 
 | |
| func (g *DomainMatcherGroup) Match(domain string) uint32 {
 | |
| 	if len(domain) == 0 {
 | |
| 		return 0
 | |
| 	}
 | |
| 
 | |
| 	current := g.root
 | |
| 	if current == nil {
 | |
| 		return 0
 | |
| 	}
 | |
| 
 | |
| 	nextPart := func(idx int) int {
 | |
| 		for i := idx - 1; i >= 0; i-- {
 | |
| 			if domain[i] == '.' {
 | |
| 				return i
 | |
| 			}
 | |
| 		}
 | |
| 		return -1
 | |
| 	}
 | |
| 
 | |
| 	idx := len(domain)
 | |
| 	for {
 | |
| 		if idx == -1 || current.sub == nil {
 | |
| 			break
 | |
| 		}
 | |
| 
 | |
| 		nidx := nextPart(idx)
 | |
| 		part := domain[nidx+1 : idx]
 | |
| 		next := current.sub[part]
 | |
| 		if next == nil {
 | |
| 			break
 | |
| 		}
 | |
| 		current = next
 | |
| 		idx = nidx
 | |
| 	}
 | |
| 	return current.value
 | |
| }
 | 
