|
@@ -1,6 +1,9 @@
|
|
package search
|
|
package search
|
|
|
|
|
|
-import "errors"
|
|
|
|
|
|
+import (
|
|
|
|
+ "errors"
|
|
|
|
+ "fmt"
|
|
|
|
+)
|
|
|
|
|
|
const (
|
|
const (
|
|
colon = ':'
|
|
colon = ':'
|
|
@@ -8,16 +11,16 @@ const (
|
|
)
|
|
)
|
|
|
|
|
|
var (
|
|
var (
|
|
- // ErrDupItem means adding duplicated item.
|
|
|
|
- ErrDupItem = errors.New("duplicated item")
|
|
|
|
- // ErrDupSlash means item is started with more than one slash.
|
|
|
|
- ErrDupSlash = errors.New("duplicated slash")
|
|
|
|
- // ErrEmptyItem means adding empty item.
|
|
|
|
- ErrEmptyItem = errors.New("empty item")
|
|
|
|
- // ErrInvalidState means search tree is in an invalid state.
|
|
|
|
- ErrInvalidState = errors.New("search tree is in an invalid state")
|
|
|
|
- // ErrNotFromRoot means path is not starting with slash.
|
|
|
|
- ErrNotFromRoot = errors.New("path should start with /")
|
|
|
|
|
|
+ // errDupItem means adding duplicated item.
|
|
|
|
+ errDupItem = errors.New("duplicated item")
|
|
|
|
+ // errDupSlash means item is started with more than one slash.
|
|
|
|
+ errDupSlash = errors.New("duplicated slash")
|
|
|
|
+ // errEmptyItem means adding empty item.
|
|
|
|
+ errEmptyItem = errors.New("empty item")
|
|
|
|
+ // errInvalidState means search tree is in an invalid state.
|
|
|
|
+ errInvalidState = errors.New("search tree is in an invalid state")
|
|
|
|
+ // errNotFromRoot means path is not starting with slash.
|
|
|
|
+ errNotFromRoot = errors.New("path should start with /")
|
|
|
|
|
|
// NotFound is used to hold the not found result.
|
|
// NotFound is used to hold the not found result.
|
|
NotFound Result
|
|
NotFound Result
|
|
@@ -58,14 +61,22 @@ func NewTree() *Tree {
|
|
// Add adds item to associate with route.
|
|
// Add adds item to associate with route.
|
|
func (t *Tree) Add(route string, item interface{}) error {
|
|
func (t *Tree) Add(route string, item interface{}) error {
|
|
if len(route) == 0 || route[0] != slash {
|
|
if len(route) == 0 || route[0] != slash {
|
|
- return ErrNotFromRoot
|
|
|
|
|
|
+ return errNotFromRoot
|
|
}
|
|
}
|
|
|
|
|
|
if item == nil {
|
|
if item == nil {
|
|
- return ErrEmptyItem
|
|
|
|
|
|
+ return errEmptyItem
|
|
}
|
|
}
|
|
|
|
|
|
- return add(t.root, route[1:], item)
|
|
|
|
|
|
+ err := add(t.root, route[1:], item)
|
|
|
|
+ switch err {
|
|
|
|
+ case errDupItem:
|
|
|
|
+ return duplicatedItem(route)
|
|
|
|
+ case errDupSlash:
|
|
|
|
+ return duplicatedSlash(route)
|
|
|
|
+ default:
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
// Search searches item that associates with given route.
|
|
// Search searches item that associates with given route.
|
|
@@ -141,7 +152,7 @@ func (nd *node) getChildren(route string) map[string]*node {
|
|
func add(nd *node, route string, item interface{}) error {
|
|
func add(nd *node, route string, item interface{}) error {
|
|
if len(route) == 0 {
|
|
if len(route) == 0 {
|
|
if nd.item != nil {
|
|
if nd.item != nil {
|
|
- return ErrDupItem
|
|
|
|
|
|
+ return errDupItem
|
|
}
|
|
}
|
|
|
|
|
|
nd.item = item
|
|
nd.item = item
|
|
@@ -149,7 +160,7 @@ func add(nd *node, route string, item interface{}) error {
|
|
}
|
|
}
|
|
|
|
|
|
if route[0] == slash {
|
|
if route[0] == slash {
|
|
- return ErrDupSlash
|
|
|
|
|
|
+ return errDupSlash
|
|
}
|
|
}
|
|
|
|
|
|
for i := range route {
|
|
for i := range route {
|
|
@@ -161,7 +172,7 @@ func add(nd *node, route string, item interface{}) error {
|
|
return add(child, route[i+1:], item)
|
|
return add(child, route[i+1:], item)
|
|
}
|
|
}
|
|
|
|
|
|
- return ErrInvalidState
|
|
|
|
|
|
+ return errInvalidState
|
|
}
|
|
}
|
|
|
|
|
|
child := newNode(nil)
|
|
child := newNode(nil)
|
|
@@ -173,7 +184,7 @@ func add(nd *node, route string, item interface{}) error {
|
|
children := nd.getChildren(route)
|
|
children := nd.getChildren(route)
|
|
if child, ok := children[route]; ok {
|
|
if child, ok := children[route]; ok {
|
|
if child.item != nil {
|
|
if child.item != nil {
|
|
- return ErrDupItem
|
|
|
|
|
|
+ return errDupItem
|
|
}
|
|
}
|
|
|
|
|
|
child.item = item
|
|
child.item = item
|
|
@@ -192,6 +203,14 @@ func addParam(result *Result, k, v string) {
|
|
result.Params[k] = v
|
|
result.Params[k] = v
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func duplicatedItem(item string) error {
|
|
|
|
+ return fmt.Errorf("duplicated item for %s", item)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func duplicatedSlash(item string) error {
|
|
|
|
+ return fmt.Errorf("duplicated slash for %s", item)
|
|
|
|
+}
|
|
|
|
+
|
|
func match(pat, token string) innerResult {
|
|
func match(pat, token string) innerResult {
|
|
if pat[0] == colon {
|
|
if pat[0] == colon {
|
|
return innerResult{
|
|
return innerResult{
|