mirror of
https://github.com/v2ray/v2ray-core.git
synced 2024-04-21 12:31:52 +00:00
Amending domain matcher with returning array of all matches
This commit is contained in:
@@ -7,8 +7,8 @@ func breakDomain(domain string) []string {
|
||||
}
|
||||
|
||||
type node struct {
|
||||
value uint32
|
||||
sub map[string]*node
|
||||
values []uint32
|
||||
sub map[string]*node
|
||||
}
|
||||
|
||||
// DomainMatcherGroup is a IndexMatcher for a large set of Domain matchers.
|
||||
@@ -25,7 +25,7 @@ func (g *DomainMatcherGroup) Add(domain string, value uint32) {
|
||||
current := g.root
|
||||
parts := breakDomain(domain)
|
||||
for i := len(parts) - 1; i >= 0; i-- {
|
||||
if current.value > 0 {
|
||||
if len(current.values) > 0 {
|
||||
// if current node is already a match, it is not necessary to match further.
|
||||
return
|
||||
}
|
||||
@@ -42,7 +42,7 @@ func (g *DomainMatcherGroup) Add(domain string, value uint32) {
|
||||
current = next
|
||||
}
|
||||
|
||||
current.value = value
|
||||
current.values = append(current.values, value)
|
||||
current.sub = nil // shortcut sub nodes as current node is a match.
|
||||
}
|
||||
|
||||
@@ -50,14 +50,14 @@ func (g *DomainMatcherGroup) addMatcher(m domainMatcher, value uint32) {
|
||||
g.Add(string(m), value)
|
||||
}
|
||||
|
||||
func (g *DomainMatcherGroup) Match(domain string) uint32 {
|
||||
func (g *DomainMatcherGroup) Match(domain string) []uint32 {
|
||||
if domain == "" {
|
||||
return 0
|
||||
return nil
|
||||
}
|
||||
|
||||
current := g.root
|
||||
if current == nil {
|
||||
return 0
|
||||
return nil
|
||||
}
|
||||
|
||||
nextPart := func(idx int) int {
|
||||
@@ -84,5 +84,5 @@ func (g *DomainMatcherGroup) Match(domain string) uint32 {
|
||||
current = next
|
||||
idx = nidx
|
||||
}
|
||||
return current.value
|
||||
return current.values
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package strmatcher_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
. "v2ray.com/core/common/strmatcher"
|
||||
@@ -13,48 +14,54 @@ func TestDomainMatcherGroup(t *testing.T) {
|
||||
g.Add("x.a.com", 3)
|
||||
g.Add("a.b.com", 4)
|
||||
g.Add("c.a.b.com", 5)
|
||||
g.Add("x.y.com", 4)
|
||||
g.Add("x.y.com", 6)
|
||||
|
||||
testCases := []struct {
|
||||
Domain string
|
||||
Result uint32
|
||||
Result []uint32
|
||||
}{
|
||||
{
|
||||
Domain: "x.v2ray.com",
|
||||
Result: 1,
|
||||
Result: []uint32{1},
|
||||
},
|
||||
{
|
||||
Domain: "y.com",
|
||||
Result: 0,
|
||||
Result: nil,
|
||||
},
|
||||
{
|
||||
Domain: "a.b.com",
|
||||
Result: 4,
|
||||
Result: []uint32{4},
|
||||
},
|
||||
{
|
||||
Domain: "c.a.b.com",
|
||||
Result: 4,
|
||||
Result: []uint32{4},
|
||||
},
|
||||
{
|
||||
Domain: "c.a..b.com",
|
||||
Result: 0,
|
||||
Result: nil,
|
||||
},
|
||||
{
|
||||
Domain: ".com",
|
||||
Result: 0,
|
||||
Result: nil,
|
||||
},
|
||||
{
|
||||
Domain: "com",
|
||||
Result: 0,
|
||||
Result: nil,
|
||||
},
|
||||
{
|
||||
Domain: "",
|
||||
Result: 0,
|
||||
Result: nil,
|
||||
},
|
||||
{
|
||||
Domain: "x.y.com",
|
||||
Result: []uint32{4, 6},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
r := g.Match(testCase.Domain)
|
||||
if r != testCase.Result {
|
||||
if !reflect.DeepEqual(r, testCase.Result) {
|
||||
t.Error("Failed to match domain: ", testCase.Domain, ", expect ", testCase.Result, ", but got ", r)
|
||||
}
|
||||
}
|
||||
@@ -63,7 +70,7 @@ func TestDomainMatcherGroup(t *testing.T) {
|
||||
func TestEmptyDomainMatcherGroup(t *testing.T) {
|
||||
g := new(DomainMatcherGroup)
|
||||
r := g.Match("v2ray.com")
|
||||
if r != 0 {
|
||||
t.Error("Expect 0, but ", r)
|
||||
if len(r) != 0 {
|
||||
t.Error("Expect [], but ", r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
package strmatcher
|
||||
|
||||
type FullMatcherGroup struct {
|
||||
matchers map[string]uint32
|
||||
matchers map[string][]uint32
|
||||
}
|
||||
|
||||
func (g *FullMatcherGroup) Add(domain string, value uint32) {
|
||||
if g.matchers == nil {
|
||||
g.matchers = make(map[string]uint32)
|
||||
g.matchers = make(map[string][]uint32)
|
||||
}
|
||||
|
||||
g.matchers[domain] = value
|
||||
g.matchers[domain] = append(g.matchers[domain], value)
|
||||
}
|
||||
|
||||
func (g *FullMatcherGroup) addMatcher(m fullMatcher, value uint32) {
|
||||
g.Add(string(m), value)
|
||||
}
|
||||
|
||||
func (g *FullMatcherGroup) Match(str string) uint32 {
|
||||
func (g *FullMatcherGroup) Match(str string) []uint32 {
|
||||
if g.matchers == nil {
|
||||
return 0
|
||||
return nil
|
||||
}
|
||||
|
||||
return g.matchers[str]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package strmatcher_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
. "v2ray.com/core/common/strmatcher"
|
||||
@@ -11,24 +12,30 @@ func TestFullMatcherGroup(t *testing.T) {
|
||||
g.Add("v2ray.com", 1)
|
||||
g.Add("google.com", 2)
|
||||
g.Add("x.a.com", 3)
|
||||
g.Add("x.y.com", 4)
|
||||
g.Add("x.y.com", 6)
|
||||
|
||||
testCases := []struct {
|
||||
Domain string
|
||||
Result uint32
|
||||
Result []uint32
|
||||
}{
|
||||
{
|
||||
Domain: "v2ray.com",
|
||||
Result: 1,
|
||||
Result: []uint32{1},
|
||||
},
|
||||
{
|
||||
Domain: "y.com",
|
||||
Result: 0,
|
||||
Result: nil,
|
||||
},
|
||||
{
|
||||
Domain: "x.y.com",
|
||||
Result: []uint32{4, 6},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
r := g.Match(testCase.Domain)
|
||||
if r != testCase.Result {
|
||||
if !reflect.DeepEqual(r, testCase.Result) {
|
||||
t.Error("Failed to match domain: ", testCase.Domain, ", expect ", testCase.Result, ", but got ", r)
|
||||
}
|
||||
}
|
||||
@@ -37,7 +44,7 @@ func TestFullMatcherGroup(t *testing.T) {
|
||||
func TestEmptyFullMatcherGroup(t *testing.T) {
|
||||
g := new(FullMatcherGroup)
|
||||
r := g.Match("v2ray.com")
|
||||
if r != 0 {
|
||||
t.Error("Expect 0, but ", r)
|
||||
if len(r) != 0 {
|
||||
t.Error("Expect [], but ", r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ func (t Type) New(pattern string) (Matcher, error) {
|
||||
// IndexMatcher is the interface for matching with a group of matchers.
|
||||
type IndexMatcher interface {
|
||||
// Match returns the the index of a matcher that matches the input. It returns 0 if no such matcher exists.
|
||||
Match(input string) uint32
|
||||
Match(input string) []uint32
|
||||
}
|
||||
|
||||
type matcherEntry struct {
|
||||
@@ -87,22 +87,16 @@ func (g *MatcherGroup) Add(m Matcher) uint32 {
|
||||
}
|
||||
|
||||
// Match implements IndexMatcher.Match.
|
||||
func (g *MatcherGroup) Match(pattern string) uint32 {
|
||||
if c := g.fullMatcher.Match(pattern); c > 0 {
|
||||
return c
|
||||
}
|
||||
|
||||
if c := g.domainMatcher.Match(pattern); c > 0 {
|
||||
return c
|
||||
}
|
||||
|
||||
func (g *MatcherGroup) Match(pattern string) []uint32 {
|
||||
result := []uint32{}
|
||||
result = append(result, g.fullMatcher.Match(pattern)...)
|
||||
result = append(result, g.domainMatcher.Match(pattern)...)
|
||||
for _, e := range g.otherMatchers {
|
||||
if e.m.Match(pattern) {
|
||||
return e.id
|
||||
result = append(result, e.id)
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
return result
|
||||
}
|
||||
|
||||
// Size returns the number of matchers in the MatcherGroup.
|
||||
|
||||
Reference in New Issue
Block a user