forked from Loyalsoldier/domain-list-custom
-
Notifications
You must be signed in to change notification settings - Fork 0
/
trie.go
73 lines (61 loc) · 1.27 KB
/
trie.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package main
import (
"errors"
"strings"
)
type node struct {
leaf bool
children map[string]*node
}
func newNode() *node {
return &node{
leaf: false,
children: make(map[string]*node),
}
}
func (n *node) getChild(s string) *node {
return n.children[s]
}
func (n *node) hasChild(s string) bool {
return n.getChild(s) != nil
}
func (n *node) addChild(s string, child *node) {
n.children[s] = child
}
func (n *node) isLeaf() bool {
return n.leaf
}
// DomainTrie is a domain trie for domain type rules.
type DomainTrie struct {
root *node
}
// NewDomainTrie creates and returns a new domain trie.
func NewDomainTrie() *DomainTrie {
return &DomainTrie{
root: newNode(),
}
}
// Insert inserts a domain rule string into the domain trie
// and return whether is inserted successfully or not.
func (t *DomainTrie) Insert(domain string) (bool, error) {
if domain == "" {
return false, errors.New("empty domain")
}
parts := strings.Split(domain, ".")
node := t.root
for i := len(parts) - 1; i >= 0; i-- {
part := parts[i]
if node.isLeaf() {
return false, nil
}
if !node.hasChild(part) {
node.addChild(part, newNode())
if i == 0 {
node.getChild(part).leaf = true
return true, nil
}
}
node = node.getChild(part)
}
return false, nil
}