Move maxParams logic to router
diff --git a/router.go b/router.go
index bdee266..ce19f86 100644
--- a/router.go
+++ b/router.go
@@ -116,6 +116,9 @@
// pool to recycle Param slices
psPool sync.Pool
+ // max number of params any of the pathes contains
+ maxParams int
+
// Enables automatic redirection if the current route can't be matched but a
// handler for the path with (without) the trailing slash exists.
// For example if /foo/ is requested but a route only exists for /foo, the
@@ -175,12 +178,14 @@
func (r *Router) paramsGet() *Params {
if vp := r.psPool.Get(); vp != nil {
psp := vp.(*Params)
- *psp = (*psp)[0:0] // reset slice
- return psp
+ if cap(*psp) >= r.maxParams {
+ *psp = (*psp)[0:0] // reset slice
+ return psp
+ }
}
// Allocate new slice if none is available
- ps := make(Params, 0, 20) // TODO
+ ps := make(Params, 0, r.maxParams)
return &ps
}
@@ -248,6 +253,11 @@
r.trees[method] = root
}
+ // Update maxParams
+ if pc := countParams(path); pc > r.maxParams {
+ r.maxParams = pc
+ }
+
root.addRoute(path, handle)
}
diff --git a/tree.go b/tree.go
index f248a57..e1359ef 100644
--- a/tree.go
+++ b/tree.go
@@ -13,18 +13,14 @@
return b
}
-func countParams(path string) uint8 {
- var n uint
+func countParams(path string) (n int) {
for i := 0; i < len(path); i++ {
if path[i] != ':' && path[i] != '*' {
continue
}
n++
}
- if n >= 255 {
- return 255
- }
- return uint8(n)
+ return n
}
func toLower(b byte) byte {
@@ -46,7 +42,6 @@
pfx string // first len(children) bytes are indices, rest is path prefix
wildChild bool
nType nodeType
- maxParams uint8
priority uint32
children []*node
handle Handle
@@ -83,18 +78,12 @@
func (n *node) addRoute(path string, handle Handle) {
fullPath := path
n.priority++
- numParams := countParams(path)
// non-empty tree
if len(n.pfx) > 0 {
prefix := n.pfx[len(n.children):]
walk:
for {
- // Update maxParams of the current node
- if numParams > n.maxParams {
- n.maxParams = numParams
- }
-
// Find the longest common prefix.
// This also implies that the common prefix contains no ':' or '*'
// since the existing key can't contain those chars.
@@ -109,16 +98,9 @@
child := node{
pfx: n.pfx[:len(n.children)] + prefix[i:],
wildChild: n.wildChild,
+ priority: n.priority - 1,
children: n.children,
handle: n.handle,
- priority: n.priority - 1,
- }
-
- // Update maxParams (max of all children)
- for i := range child.children {
- if child.children[i].maxParams > child.maxParams {
- child.maxParams = child.children[i].maxParams
- }
}
n.children = []*node{&child}
@@ -137,12 +119,6 @@
n.priority++
prefix = n.pfx[len(n.children):]
- // Update maxParams of the child node
- if numParams > n.maxParams {
- n.maxParams = numParams
- }
- numParams--
-
// Check if the wildcard matches
if len(path) >= len(prefix) && prefix == path[:len(prefix)] {
// check for longer wildcard, e.g. :name and :names
@@ -180,14 +156,12 @@
if c != ':' && c != '*' {
// []byte for proper unicode char conversion, see #65
n.pfx = n.pfx[:len(n.children)] + string([]byte{c}) + n.pfx[len(n.children):]
- child := &node{
- maxParams: numParams,
- }
+ child := new(node)
n.children = append(n.children, child)
n.incrementChildPrio(len(n.children) - 1)
n = child
}
- n.insertChild(numParams, path, fullPath, handle)
+ n.insertChild(path, fullPath, handle)
return
} else if i == len(path) { // Make node a (in-path) leaf
@@ -199,15 +173,15 @@
return
}
} else { // Empty tree
- n.insertChild(numParams, path, fullPath, handle)
+ n.insertChild(path, fullPath, handle)
}
}
-func (n *node) insertChild(numParams uint8, path, fullPath string, handle Handle) {
+func (n *node) insertChild(path, fullPath string, handle Handle) {
var offset int // already handled bytes of the path
// find prefix until first wildcard (beginning with ':'' or '*'')
- for i, max := 0, len(path); numParams > 0; i++ {
+ for i, max := 0, len(path); i < max; i++ {
c := path[i]
if c != ':' && c != '*' {
continue
@@ -248,14 +222,12 @@
}
child := &node{
- nType: param,
- maxParams: numParams,
+ nType: param,
}
n.children = []*node{child}
n.wildChild = true
n = child
n.priority++
- numParams--
// if the path doesn't end with the wildcard, then there
// will be another non-wildcard subpath starting with '/'
@@ -264,15 +236,14 @@
offset = end
child := &node{
- maxParams: numParams,
- priority: 1,
+ priority: 1,
}
n.children = []*node{child}
n = child
}
} else { // catchAll
- if end != max || numParams > 1 {
+ if end != max {
panic("catch-all routes are only allowed at the end of the path in path '" + fullPath + "'")
}
@@ -293,7 +264,6 @@
pfx: "/",
wildChild: true,
nType: catchAll,
- maxParams: 1,
}
n.children = []*node{child}
n = child
@@ -301,11 +271,10 @@
// second node: node holding the variable
child = &node{
- pfx: path[i:],
- nType: catchAll,
- maxParams: 1,
- handle: handle,
- priority: 1,
+ pfx: path[i:],
+ nType: catchAll,
+ priority: 1,
+ handle: handle,
}
n.children = []*node{child}
diff --git a/tree_test.go b/tree_test.go
index eb83499..87ccdc6 100644
--- a/tree_test.go
+++ b/tree_test.go
@@ -15,7 +15,7 @@
func printChildren(n *node, prefix string) {
indices := n.pfx[:len(n.children)]
path := n.pfx[len(n.children):]
- fmt.Printf(" %02d:%02d %s%s [%d:%s] %v %t %d \r\n", n.priority, n.maxParams, prefix, path, len(n.children), indices, n.handle, n.wildChild, n.nType)
+ fmt.Printf(" %02d %s%s [%d:%s] %v %t %d \r\n", n.priority, prefix, path, len(n.children), indices, n.handle, n.wildChild, n.nType)
for l := len(path); l > 0; l-- {
prefix += " "
}
@@ -89,33 +89,11 @@
return prio
}
-func checkMaxParams(t *testing.T, n *node) uint8 {
- var maxParams uint8
- for i := range n.children {
- params := checkMaxParams(t, n.children[i])
- if params > maxParams {
- maxParams = params
- }
- }
- if n.nType != static && !n.wildChild {
- maxParams++
- }
-
- if n.maxParams != maxParams {
- t.Errorf(
- "maxParams mismatch for node '%s': is %d, should be %d",
- n.pfx[:len(n.children)], n.maxParams, maxParams,
- )
- }
-
- return maxParams
-}
-
func TestCountParams(t *testing.T) {
if countParams("/path/:param1/static/*catch-all") != 2 {
t.Fail()
}
- if countParams(strings.Repeat("/:param", 256)) != 255 {
+ if countParams(strings.Repeat("/:param", 256)) != 256 {
t.Fail()
}
}
@@ -157,7 +135,6 @@
})
checkPriorities(t, tree)
- checkMaxParams(t, tree)
}
func TestTreeWildcard(t *testing.T) {
@@ -203,7 +180,6 @@
})
checkPriorities(t, tree)
- checkMaxParams(t, tree)
}
func catchPanic(testFunc func()) (recv interface{}) {