mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-07-11 14:18:53 +00:00
Xray-core: Refactor geodata (#5814)
https://github.com/XTLS/Xray-core/issues/4422#issuecomment-3533007890 Breaking changes https://github.com/XTLS/Xray-core/pull/5569 Reverts https://github.com/XTLS/Xray-core/pull/5505 Closes https://github.com/XTLS/Xray-core/pull/643
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
package strmatcher
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SubstrMatcherGroup is implementation of MatcherGroup,
|
||||
// It is simply implmeneted to comply with the priority specification of Substr matchers.
|
||||
type SubstrMatcherGroup struct {
|
||||
patterns []string
|
||||
values []uint32
|
||||
}
|
||||
|
||||
// AddSubstrMatcher implements MatcherGroupForSubstr.AddSubstrMatcher.
|
||||
func (g *SubstrMatcherGroup) AddSubstrMatcher(matcher SubstrMatcher, value uint32) {
|
||||
g.patterns = append(g.patterns, matcher.Pattern())
|
||||
g.values = append(g.values, value)
|
||||
}
|
||||
|
||||
// Match implements MatcherGroup.Match.
|
||||
func (g *SubstrMatcherGroup) Match(input string) []uint32 {
|
||||
var result []uint32
|
||||
for i, pattern := range g.patterns {
|
||||
for j := strings.LastIndex(input, pattern); j != -1; j = strings.LastIndex(input[:j], pattern) {
|
||||
result = append(result, uint32(j)<<16|uint32(i)&0xffff) // uint32: position (higher 16 bit) | patternIdx (lower 16 bit)
|
||||
}
|
||||
}
|
||||
// sort.Slice will trigger allocation no matter what input is. See https://github.com/golang/go/issues/17332
|
||||
// We optimize the sorting by length to prevent memory allocation as possible.
|
||||
switch len(result) {
|
||||
case 0:
|
||||
return nil
|
||||
case 1:
|
||||
// No need to sort
|
||||
case 2:
|
||||
// Do a simple swap if unsorted
|
||||
if result[0] > result[1] {
|
||||
result[0], result[1] = result[1], result[0]
|
||||
}
|
||||
default:
|
||||
// Sort the match results in dictionary order, so that:
|
||||
// 1. Pattern matched at smaller position (meaning matched further) takes precedence.
|
||||
// 2. When patterns matched at same position, pattern with smaller index (meaning inserted early) takes precedence.
|
||||
sort.Slice(result, func(i, j int) bool { return result[i] < result[j] })
|
||||
}
|
||||
for i, entry := range result {
|
||||
result[i] = g.values[entry&0xffff] // Get pattern value from its index (the lower 16 bit)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// MatchAny implements MatcherGroup.MatchAny.
|
||||
func (g *SubstrMatcherGroup) MatchAny(input string) bool {
|
||||
for _, pattern := range g.patterns {
|
||||
if strings.Contains(input, pattern) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user