github.com/kelleygo/clashcore@v1.0.2/component/trie/domain_set.go (about) 1 package trie 2 3 // Package succinct provides several succinct data types. 4 // Modify from https://github.com/openacid/succinct/blob/d4684c35d123f7528b14e03c24327231723db704/sskv.go 5 6 import ( 7 "sort" 8 "strings" 9 10 "github.com/kelleygo/clashcore/common/utils" 11 "github.com/openacid/low/bitmap" 12 ) 13 14 const ( 15 complexWildcardByte = byte('+') 16 wildcardByte = byte('*') 17 domainStepByte = byte('.') 18 ) 19 20 type DomainSet struct { 21 leaves, labelBitmap []uint64 22 labels []byte 23 ranks, selects []int32 24 } 25 26 type qElt struct{ s, e, col int } 27 28 // NewDomainSet creates a new *DomainSet struct, from a DomainTrie. 29 func (t *DomainTrie[T]) NewDomainSet() *DomainSet { 30 reserveDomains := make([]string, 0) 31 t.Foreach(func(domain string, data T) { 32 reserveDomains = append(reserveDomains, utils.Reverse(domain)) 33 }) 34 // ensure that the same prefix is continuous 35 // and according to the ascending sequence of length 36 sort.Strings(reserveDomains) 37 keys := reserveDomains 38 if len(keys) == 0 { 39 return nil 40 } 41 ss := &DomainSet{} 42 lIdx := 0 43 44 queue := []qElt{{0, len(keys), 0}} 45 for i := 0; i < len(queue); i++ { 46 elt := queue[i] 47 if elt.col == len(keys[elt.s]) { 48 elt.s++ 49 // a leaf node 50 setBit(&ss.leaves, i, 1) 51 } 52 53 for j := elt.s; j < elt.e; { 54 55 frm := j 56 57 for ; j < elt.e && keys[j][elt.col] == keys[frm][elt.col]; j++ { 58 } 59 queue = append(queue, qElt{frm, j, elt.col + 1}) 60 ss.labels = append(ss.labels, keys[frm][elt.col]) 61 setBit(&ss.labelBitmap, lIdx, 0) 62 lIdx++ 63 } 64 setBit(&ss.labelBitmap, lIdx, 1) 65 lIdx++ 66 } 67 68 ss.init() 69 return ss 70 } 71 72 // Has query for a key and return whether it presents in the DomainSet. 73 func (ss *DomainSet) Has(key string) bool { 74 if ss == nil { 75 return false 76 } 77 key = utils.Reverse(key) 78 key = strings.ToLower(key) 79 // no more labels in this node 80 // skip character matching 81 // go to next level 82 nodeId, bmIdx := 0, 0 83 type wildcardCursor struct { 84 bmIdx, index int 85 } 86 stack := make([]wildcardCursor, 0) 87 for i := 0; i < len(key); i++ { 88 RESTART: 89 c := key[i] 90 for ; ; bmIdx++ { 91 if getBit(ss.labelBitmap, bmIdx) != 0 { 92 if len(stack) > 0 { 93 cursor := stack[len(stack)-1] 94 stack = stack[0 : len(stack)-1] 95 // back wildcard and find next node 96 nextNodeId := countZeros(ss.labelBitmap, ss.ranks, cursor.bmIdx+1) 97 nextBmIdx := selectIthOne(ss.labelBitmap, ss.ranks, ss.selects, nextNodeId-1) + 1 98 j := cursor.index 99 for ; j < len(key) && key[j] != domainStepByte; j++ { 100 } 101 if j == len(key) { 102 if getBit(ss.leaves, nextNodeId) != 0 { 103 return true 104 } else { 105 goto RESTART 106 } 107 } 108 for ; nextBmIdx-nextNodeId < len(ss.labels); nextBmIdx++ { 109 if ss.labels[nextBmIdx-nextNodeId] == domainStepByte { 110 bmIdx = nextBmIdx 111 nodeId = nextNodeId 112 i = j 113 goto RESTART 114 } 115 } 116 } 117 return false 118 } 119 // handle wildcard for domain 120 if ss.labels[bmIdx-nodeId] == complexWildcardByte { 121 return true 122 } else if ss.labels[bmIdx-nodeId] == wildcardByte { 123 cursor := wildcardCursor{} 124 cursor.bmIdx = bmIdx 125 cursor.index = i 126 stack = append(stack, cursor) 127 } else if ss.labels[bmIdx-nodeId] == c { 128 break 129 } 130 } 131 nodeId = countZeros(ss.labelBitmap, ss.ranks, bmIdx+1) 132 bmIdx = selectIthOne(ss.labelBitmap, ss.ranks, ss.selects, nodeId-1) + 1 133 } 134 135 return getBit(ss.leaves, nodeId) != 0 136 137 } 138 139 func setBit(bm *[]uint64, i int, v int) { 140 for i>>6 >= len(*bm) { 141 *bm = append(*bm, 0) 142 } 143 (*bm)[i>>6] |= uint64(v) << uint(i&63) 144 } 145 146 func getBit(bm []uint64, i int) uint64 { 147 return bm[i>>6] & (1 << uint(i&63)) 148 } 149 150 // init builds pre-calculated cache to speed up rank() and select() 151 func (ss *DomainSet) init() { 152 ss.selects, ss.ranks = bitmap.IndexSelect32R64(ss.labelBitmap) 153 } 154 155 // countZeros counts the number of "0" in a bitmap before the i-th bit(excluding 156 // the i-th bit) on behalf of rank index. 157 // E.g.: 158 // 159 // countZeros("010010", 4) == 3 160 // // 012345 161 func countZeros(bm []uint64, ranks []int32, i int) int { 162 a, _ := bitmap.Rank64(bm, ranks, int32(i)) 163 return i - int(a) 164 } 165 166 // selectIthOne returns the index of the i-th "1" in a bitmap, on behalf of rank 167 // and select indexes. 168 // E.g.: 169 // 170 // selectIthOne("010010", 1) == 4 171 // // 012345 172 func selectIthOne(bm []uint64, ranks, selects []int32, i int) int { 173 a, _ := bitmap.Select32R64(bm, selects, ranks, int32(i)) 174 return int(a) 175 }