| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- 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 domain == "" {
- 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
- }
|