mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-10-30 18:23:35 +08:00
fix radix tree
This commit is contained in:
+29
-24
@@ -5,6 +5,8 @@ import (
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/log"
|
||||
)
|
||||
|
||||
type RadixNode struct {
|
||||
@@ -44,14 +46,8 @@ func (r *RadixNode) add(segments []string, data interface{}, depth int, segNames
|
||||
if r.data != nil {
|
||||
return fmt.Errorf("Duplicate data for node")
|
||||
} else {
|
||||
if depth == 1 {
|
||||
node := NewRadix()
|
||||
node.data = data
|
||||
r.regexpNodes[".*"] = node
|
||||
} else {
|
||||
r.data = data
|
||||
r.segNames = segNames
|
||||
}
|
||||
r.data = data
|
||||
r.segNames = segNames
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
@@ -96,7 +92,7 @@ func (r *RadixNode) add(segments []string, data interface{}, depth int, segNames
|
||||
}
|
||||
|
||||
func (r *RadixNode) Match(segments []string, params map[string]string) interface{} {
|
||||
node := r.match(segments, true)
|
||||
node, _ := r.match(segments)
|
||||
if node == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -106,32 +102,41 @@ func (r *RadixNode) Match(segments []string, params map[string]string) interface
|
||||
return node.data
|
||||
}
|
||||
|
||||
func (r *RadixNode) match(segments []string, isRoot bool) *RadixNode {
|
||||
func (r *RadixNode) match(segments []string) (*RadixNode, bool) {
|
||||
if len(segments) == 0 {
|
||||
return r
|
||||
}
|
||||
|
||||
if len(r.stringNodes) == 0 && len(r.regexpNodes) == 0 {
|
||||
if isRoot {
|
||||
return nil
|
||||
} else {
|
||||
return r
|
||||
}
|
||||
return r, true
|
||||
} else if len(r.stringNodes) == 0 && len(r.regexpNodes) == 0 {
|
||||
return r, false
|
||||
}
|
||||
|
||||
if node, ok := r.stringNodes[segments[0]]; ok {
|
||||
if rnode := node.match(segments[1:], false); rnode != nil && rnode.data != nil {
|
||||
return rnode
|
||||
if rnode, _ := node.match(segments[1:]); rnode != nil && rnode.data != nil {
|
||||
return rnode, true
|
||||
}
|
||||
}
|
||||
|
||||
var nodeTmp *RadixNode
|
||||
for regstr, node := range r.regexpNodes {
|
||||
if regexp.MustCompile(regstr).MatchString(segments[0]) {
|
||||
if rnode := node.match(segments[1:], false); rnode != nil && rnode.data != nil {
|
||||
return rnode
|
||||
if rnode, fullMatch := node.match(segments[1:]); rnode != nil && rnode.data != nil {
|
||||
if fullMatch {
|
||||
return rnode, fullMatch
|
||||
} else {
|
||||
if nodeTmp != nil {
|
||||
log.Errorf("segments %v match mutil node", segments)
|
||||
continue
|
||||
}
|
||||
nodeTmp = rnode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
if nodeTmp != nil {
|
||||
return nodeTmp, false
|
||||
} else {
|
||||
return r, false
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RadixNode) Walk(f func(spath string, data interface{})) {
|
||||
|
||||
@@ -23,6 +23,11 @@ func TestRadixNode(t *testing.T) {
|
||||
}
|
||||
r.Walk(f)
|
||||
params := make(map[string]string)
|
||||
|
||||
ret = r.Match([]string{"layer1", "layer1.0", "layer2.0"}, params)
|
||||
if ret.(string) != "layer1.0" {
|
||||
t.Error("0 Unexpect result:", ret, "!= layer1.0")
|
||||
}
|
||||
ret = r.Match([]string{"layer1", "layer1.0"}, params)
|
||||
if ret.(string) != "layer1.0" {
|
||||
t.Error("0 Unexpect result:", ret, "!= layer1.0")
|
||||
@@ -73,6 +78,13 @@ func TestRadixNode(t *testing.T) {
|
||||
if ret.(string) != "root" {
|
||||
t.Error("9 Unexpect result:", ret, "!= root")
|
||||
}
|
||||
|
||||
r.Add([]string{"<phone_number:^1[0-9-]{10}$>"}, "phonelayer1")
|
||||
ret = r.Match([]string{"12345678900"}, params)
|
||||
if ret.(string) != "phonelayer1" {
|
||||
t.Error("13 Unexpect result:", ret, "!= phonelayer1")
|
||||
}
|
||||
|
||||
if r.Add([]string{"layer1"}, "layer1") == nil {
|
||||
t.Error("10 Add duplicate data should fail")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user