Improved performance
This commit is contained in:
79
Tree.go
79
Tree.go
@ -79,11 +79,11 @@ func (tree *Tree[T]) Add(path string, data T) {
|
||||
}
|
||||
|
||||
// Lookup finds the data for the given path.
|
||||
func (tree *Tree[T]) Lookup(path string) (T, []keyValue) {
|
||||
var params []keyValue
|
||||
func (tree *Tree[T]) Lookup(path string) (T, []Parameter) {
|
||||
var params []Parameter
|
||||
|
||||
data := tree.LookupNoAlloc(path, func(key string, value string) {
|
||||
params = append(params, keyValue{key, value})
|
||||
params = append(params, Parameter{key, value})
|
||||
})
|
||||
|
||||
return data, params
|
||||
@ -92,44 +92,28 @@ func (tree *Tree[T]) Lookup(path string) (T, []keyValue) {
|
||||
// LookupNoAlloc finds the data for the given path without using any memory allocations.
|
||||
func (tree *Tree[T]) LookupNoAlloc(path string, addParameter func(key string, value string)) T {
|
||||
var (
|
||||
i uint
|
||||
offset uint
|
||||
lastWildcardOffset uint
|
||||
lastWildcard *treeNode[T]
|
||||
empty T
|
||||
node = &tree.root
|
||||
i uint
|
||||
offset uint
|
||||
wildcardOffset uint
|
||||
wildcard *treeNode[T]
|
||||
node = &tree.root
|
||||
)
|
||||
|
||||
// Skip the first loop iteration if the starting characters are equal
|
||||
if len(path) > 0 && len(node.prefix) > 0 && path[0] == node.prefix[0] {
|
||||
i = 1
|
||||
}
|
||||
|
||||
begin:
|
||||
// Search tree for equal parts until we can no longer proceed
|
||||
for {
|
||||
// We reached the end.
|
||||
if i == uint(len(path)) {
|
||||
// node: /blog|
|
||||
// path: /blog|
|
||||
if i-offset == uint(len(node.prefix)) {
|
||||
return node.data
|
||||
}
|
||||
|
||||
// node: /|*any
|
||||
// path: /|image.png
|
||||
if lastWildcard != nil {
|
||||
addParameter(lastWildcard.prefix, path[lastWildcardOffset:])
|
||||
return lastWildcard.data
|
||||
}
|
||||
|
||||
// node: /blog|feed
|
||||
// path: /blog|
|
||||
return empty
|
||||
}
|
||||
|
||||
for i < uint(len(path)) {
|
||||
// The node we just checked is entirely included in our path.
|
||||
// node: /|
|
||||
// path: /|blog
|
||||
if i-offset == uint(len(node.prefix)) {
|
||||
if node.wildcard != nil {
|
||||
lastWildcard = node.wildcard
|
||||
lastWildcardOffset = i
|
||||
wildcard = node.wildcard
|
||||
wildcardOffset = i
|
||||
}
|
||||
|
||||
char := path[i]
|
||||
@ -176,28 +160,35 @@ begin:
|
||||
|
||||
// node: /|*any
|
||||
// path: /|image.png
|
||||
if lastWildcard != nil {
|
||||
addParameter(lastWildcard.prefix, path[lastWildcardOffset:])
|
||||
return lastWildcard.data
|
||||
}
|
||||
|
||||
return empty
|
||||
goto notFound
|
||||
}
|
||||
|
||||
// We got a conflict.
|
||||
// node: /b|ag
|
||||
// path: /b|riefcase
|
||||
if path[i] != node.prefix[i-offset] {
|
||||
if lastWildcard != nil {
|
||||
addParameter(lastWildcard.prefix, path[lastWildcardOffset:])
|
||||
return lastWildcard.data
|
||||
}
|
||||
|
||||
return empty
|
||||
goto notFound
|
||||
}
|
||||
|
||||
i++
|
||||
}
|
||||
|
||||
// node: /blog|
|
||||
// path: /blog|
|
||||
if i-offset == uint(len(node.prefix)) {
|
||||
return node.data
|
||||
}
|
||||
|
||||
// node: /|*any
|
||||
// path: /|image.png
|
||||
notFound:
|
||||
if wildcard != nil {
|
||||
addParameter(wildcard.prefix, path[wildcardOffset:])
|
||||
return wildcard.data
|
||||
}
|
||||
|
||||
var empty T
|
||||
return empty
|
||||
}
|
||||
|
||||
// Map binds all handlers to a new one provided by the callback.
|
||||
|
Reference in New Issue
Block a user