github.com/metacubex/mihomo@v1.18.5/component/trie/node.go (about)

     1  package trie
     2  
     3  import "strings"
     4  
     5  // Node is the trie's node
     6  type Node[T any] struct {
     7  	childMap  map[string]*Node[T]
     8  	childNode *Node[T] // optimize for only one child
     9  	childStr  string
    10  	inited    bool
    11  	data      T
    12  }
    13  
    14  func (n *Node[T]) getChild(s string) *Node[T] {
    15  	if n.childMap == nil {
    16  		if n.childNode != nil && n.childStr == s {
    17  			return n.childNode
    18  		}
    19  		return nil
    20  	}
    21  	return n.childMap[s]
    22  }
    23  
    24  func (n *Node[T]) hasChild(s string) bool {
    25  	return n.getChild(s) != nil
    26  }
    27  
    28  func (n *Node[T]) addChild(s string, child *Node[T]) {
    29  	if n.childMap == nil {
    30  		if n.childNode == nil {
    31  			n.childStr = s
    32  			n.childNode = child
    33  			return
    34  		}
    35  		n.childMap = map[string]*Node[T]{}
    36  		if n.childNode != nil {
    37  			n.childMap[n.childStr] = n.childNode
    38  		}
    39  		n.childStr = ""
    40  		n.childNode = nil
    41  	}
    42  
    43  	n.childMap[s] = child
    44  }
    45  
    46  func (n *Node[T]) getOrNewChild(s string) *Node[T] {
    47  	node := n.getChild(s)
    48  	if node == nil {
    49  		node = newNode[T]()
    50  		n.addChild(s, node)
    51  	}
    52  	return node
    53  }
    54  
    55  func (n *Node[T]) optimize() {
    56  	if len(n.childStr) > 0 {
    57  		n.childStr = strClone(n.childStr)
    58  	}
    59  	if n.childNode != nil {
    60  		n.childNode.optimize()
    61  	}
    62  	if n.childMap == nil {
    63  		return
    64  	}
    65  	switch len(n.childMap) {
    66  	case 0:
    67  		n.childMap = nil
    68  		return
    69  	case 1:
    70  		for key := range n.childMap {
    71  			n.childStr = key
    72  			n.childNode = n.childMap[key]
    73  		}
    74  		n.childMap = nil
    75  		n.optimize()
    76  		return
    77  	}
    78  	children := make(map[string]*Node[T], len(n.childMap)) // avoid map reallocate memory
    79  	for key := range n.childMap {
    80  		child := n.childMap[key]
    81  		if child == nil {
    82  			continue
    83  		}
    84  		key = strClone(key)
    85  		children[key] = child
    86  		child.optimize()
    87  	}
    88  	n.childMap = children
    89  }
    90  
    91  func strClone(key string) string {
    92  	switch key { // try to save string's memory
    93  	case wildcard:
    94  		key = wildcard
    95  	case dotWildcard:
    96  		key = dotWildcard
    97  	case complexWildcard:
    98  		key = complexWildcard
    99  	case domainStep:
   100  		key = domainStep
   101  	default:
   102  		key = strings.Clone(key)
   103  	}
   104  	return key
   105  }
   106  
   107  func (n *Node[T]) isEmpty() bool {
   108  	if n == nil || n.inited == false {
   109  		return true
   110  	}
   111  	return false
   112  }
   113  
   114  func (n *Node[T]) setData(data T) {
   115  	n.data = data
   116  	n.inited = true
   117  }
   118  
   119  func (n *Node[T]) getChildren() map[string]*Node[T] {
   120  	if n.childMap == nil {
   121  		if n.childNode != nil {
   122  			m := make(map[string]*Node[T])
   123  			m[n.childStr] = n.childNode
   124  			return m
   125  		}
   126  	} else {
   127  		return n.childMap
   128  	}
   129  	return nil
   130  }
   131  func (n *Node[T]) Data() T {
   132  	return n.data
   133  }
   134  
   135  func newNode[T any]() *Node[T] {
   136  	return &Node[T]{}
   137  }