tree: Use strings instead of []byte for indices
decreases memory usage
diff --git a/tree.go b/tree.go
index e96d361..f697008 100644
--- a/tree.go
+++ b/tree.go
@@ -43,30 +43,36 @@
wildChild bool
nType nodeType
maxParams uint8
- indices []byte
+ indices string
children []*node
handle Handle
priority uint32
}
// increments priority of the given child and reorders if necessary
-func (n *node) incrementChildPrio(i int) int {
- n.children[i].priority++
- prio := n.children[i].priority
+func (n *node) incrementChildPrio(pos int) int {
+ n.children[pos].priority++
+ prio := n.children[pos].priority
// adjust position (move to front)
- for j := i - 1; j >= 0 && n.children[j].priority < prio; j-- {
+ newPos := pos
+ for newPos > 0 && n.children[newPos-1].priority < prio {
// swap node positions
- tmpN := n.children[j]
- n.children[j] = n.children[i]
- n.children[i] = tmpN
- tmpI := n.indices[j]
- n.indices[j] = n.indices[i]
- n.indices[i] = tmpI
+ tmpN := n.children[newPos-1]
+ n.children[newPos-1] = n.children[newPos]
+ n.children[newPos] = tmpN
- i--
+ newPos--
}
- return i
+
+ // build new index char string
+ if newPos != pos {
+ n.indices = n.indices[:newPos] + // unchanged prefix, might be empty
+ n.indices[pos:pos+1] + // the index char we move
+ n.indices[newPos:pos] + n.indices[pos+1:] // rest without char at 'pos'
+ }
+
+ return newPos
}
// addRoute adds a node with the given handle to the path.
@@ -110,7 +116,7 @@
}
n.children = []*node{&child}
- n.indices = []byte{n.path[i]}
+ n.indices = string(n.path[i])
n.path = path[:i]
n.handle = nil
n.wildChild = false
@@ -151,8 +157,8 @@
}
// Check if a child with the next path byte exists
- for i, index := range n.indices {
- if c == index {
+ for i := 0; i < len(n.indices); i++ {
+ if c == n.indices[i] {
i = n.incrementChildPrio(i)
n = n.children[i]
continue WALK
@@ -161,7 +167,7 @@
// Otherwise insert it
if c != ':' && c != '*' {
- n.indices = append(n.indices, c)
+ n.indices += string(c)
child := &node{
maxParams: numParams,
}
@@ -273,7 +279,7 @@
maxParams: 1,
}
n.children = []*node{child}
- n.indices = []byte{path[i]}
+ n.indices = string(path[i])
n = child
n.priority++
@@ -312,8 +318,8 @@
// to walk down the tree
if !n.wildChild {
c := path[0]
- for i, index := range n.indices {
- if c == index {
+ for i := 0; i < len(n.indices); i++ {
+ if c == n.indices[i] {
n = n.children[i]
continue walk
}
@@ -398,10 +404,10 @@
// No handle found. Check if a handle for this path + a
// trailing slash exists for trailing slash recommendation
- for i, index := range n.indices {
- if index == '/' {
+ for i := 0; i < len(n.indices); i++ {
+ if n.indices[i] == '/' {
n = n.children[i]
- tsr = (n.path == "/" && n.handle != nil) ||
+ tsr = (len(n.path) == 1 && n.handle != nil) ||
(n.nType == catchAll && n.children[0].handle != nil)
return
}
@@ -440,7 +446,7 @@
for i, index := range n.indices {
// must use recursive approach since both index and
// ToLower(index) could exist. We must check both.
- if r == unicode.ToLower(rune(index)) {
+ if r == unicode.ToLower(index) {
out, found := n.children[i].findCaseInsensitivePath(path, fixTrailingSlash)
if found {
return append(ciPath, out...), true
@@ -509,10 +515,10 @@
// No handle found.
// Try to fix the path by adding a trailing slash
if fixTrailingSlash {
- for i, index := range n.indices {
- if index == '/' {
+ for i := 0; i < len(n.indices); i++ {
+ if n.indices[i] == '/' {
n = n.children[i]
- if (n.path == "/" && n.handle != nil) ||
+ if (len(n.path) == 1 && n.handle != nil) ||
(n.nType == catchAll && n.children[0].handle != nil) {
return append(ciPath, '/'), true
}