sing-box/common/domain/matcher.go

61 lines
1.2 KiB
Go
Raw Normal View History

2022-07-02 14:55:10 +00:00
package domain
2022-07-05 01:05:35 +00:00
import (
"sort"
"unicode/utf8"
)
2022-07-02 14:55:10 +00:00
type Matcher struct {
set *succinctSet
}
func NewMatcher(domains []string, domainSuffix []string) *Matcher {
2022-07-05 01:05:35 +00:00
domainList := make([]string, 0, len(domains)+len(domainSuffix))
seen := make(map[string]bool, len(domainList))
2022-07-02 14:55:10 +00:00
for _, domain := range domainSuffix {
2022-07-05 01:05:35 +00:00
if seen[domain] {
continue
}
seen[domain] = true
2022-07-02 14:55:10 +00:00
domainList = append(domainList, reverseDomainSuffix(domain))
}
2022-07-05 01:05:35 +00:00
for _, domain := range domains {
if seen[domain] {
continue
}
seen[domain] = true
domainList = append(domainList, reverseDomain(domain))
}
sort.Strings(domainList)
2022-07-02 14:55:10 +00:00
return &Matcher{
newSuccinctSet(domainList),
}
}
func (m *Matcher) Match(domain string) bool {
return m.set.Has(reverseDomain(domain))
}
func reverseDomain(domain string) string {
l := len(domain)
b := make([]byte, l)
for i := 0; i < l; {
r, n := utf8.DecodeRuneInString(domain[i:])
i += n
utf8.EncodeRune(b[l-i:], r)
}
return string(b)
}
func reverseDomainSuffix(domain string) string {
l := len(domain)
b := make([]byte, l+1)
for i := 0; i < l; {
r, n := utf8.DecodeRuneInString(domain[i:])
i += n
utf8.EncodeRune(b[l-i:], r)
}
b[l] = prefixLabel
return string(b)
}