|
@@ -5,16 +5,22 @@
|
|
|
|
|
|
package patricia
|
|
|
|
|
|
-import "sort"
|
|
|
+import (
|
|
|
+ "fmt"
|
|
|
+ "io"
|
|
|
+ "sort"
|
|
|
+)
|
|
|
|
|
|
type childList interface {
|
|
|
length() int
|
|
|
head() *Trie
|
|
|
add(child *Trie) childList
|
|
|
+ remove(b byte)
|
|
|
replace(b byte, child *Trie)
|
|
|
- remove(child *Trie)
|
|
|
next(b byte) *Trie
|
|
|
walk(prefix *Prefix, visitor VisitorFunc) error
|
|
|
+ print(w io.Writer, indent int)
|
|
|
+ total() int
|
|
|
}
|
|
|
|
|
|
type tries []*Trie
|
|
@@ -38,7 +44,7 @@ type sparseChildList struct {
|
|
|
|
|
|
func newSparseChildList(maxChildrenPerSparseNode int) childList {
|
|
|
return &sparseChildList{
|
|
|
- children: make(tries, 0, DefaultMaxChildrenPerSparseNode),
|
|
|
+ children: make(tries, 0, maxChildrenPerSparseNode),
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -61,26 +67,33 @@ func (list *sparseChildList) add(child *Trie) childList {
|
|
|
return newDenseChildList(list, child)
|
|
|
}
|
|
|
|
|
|
-func (list *sparseChildList) replace(b byte, child *Trie) {
|
|
|
- // Seek the child and replace it.
|
|
|
+func (list *sparseChildList) remove(b byte) {
|
|
|
for i, node := range list.children {
|
|
|
if node.prefix[0] == b {
|
|
|
- list.children[i] = child
|
|
|
+ list.children, list.children[len(list.children)-1] =
|
|
|
+ append(list.children[:i], list.children[i+1:]...),
|
|
|
+ nil
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // This is not supposed to be reached.
|
|
|
+ panic("removing non-existent child")
|
|
|
}
|
|
|
|
|
|
-func (list *sparseChildList) remove(child *Trie) {
|
|
|
+func (list *sparseChildList) replace(b byte, child *Trie) {
|
|
|
+ // Make a consistency check.
|
|
|
+ if p0 := child.prefix[0]; p0 != b {
|
|
|
+ panic(fmt.Errorf("child prefix mismatch: %v != %v", p0, b))
|
|
|
+ }
|
|
|
+
|
|
|
+ // Seek the child and replace it.
|
|
|
for i, node := range list.children {
|
|
|
- if node.prefix[0] == child.prefix[0] {
|
|
|
- list.children = append(list.children[:i], list.children[i+1:]...)
|
|
|
+ if node.prefix[0] == b {
|
|
|
+ list.children[i] = child
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- // This is not supposed to be reached.
|
|
|
- panic("removing non-existent child")
|
|
|
}
|
|
|
|
|
|
func (list *sparseChildList) next(b byte) *Trie {
|
|
@@ -120,10 +133,30 @@ func (list *sparseChildList) walk(prefix *Prefix, visitor VisitorFunc) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+func (list *sparseChildList) total() int {
|
|
|
+ tot := 0
|
|
|
+ for _, child := range list.children {
|
|
|
+ if child != nil {
|
|
|
+ tot = tot + child.total()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return tot
|
|
|
+}
|
|
|
+
|
|
|
+func (list *sparseChildList) print(w io.Writer, indent int) {
|
|
|
+ for _, child := range list.children {
|
|
|
+ if child != nil {
|
|
|
+ child.print(w, indent)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
type denseChildList struct {
|
|
|
- min int
|
|
|
- max int
|
|
|
- children []*Trie
|
|
|
+ min int
|
|
|
+ max int
|
|
|
+ numChildren int
|
|
|
+ headIndex int
|
|
|
+ children []*Trie
|
|
|
}
|
|
|
|
|
|
func newDenseChildList(list *sparseChildList, child *Trie) childList {
|
|
@@ -155,57 +188,87 @@ func newDenseChildList(list *sparseChildList, child *Trie) childList {
|
|
|
}
|
|
|
children[int(child.prefix[0])-min] = child
|
|
|
|
|
|
- return &denseChildList{min, max, children}
|
|
|
+ return &denseChildList{
|
|
|
+ min: min,
|
|
|
+ max: max,
|
|
|
+ numChildren: list.length() + 1,
|
|
|
+ headIndex: 0,
|
|
|
+ children: children,
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func (list *denseChildList) length() int {
|
|
|
- return list.max - list.min + 1
|
|
|
+ return list.numChildren
|
|
|
}
|
|
|
|
|
|
func (list *denseChildList) head() *Trie {
|
|
|
- return list.children[0]
|
|
|
+ return list.children[list.headIndex]
|
|
|
}
|
|
|
|
|
|
func (list *denseChildList) add(child *Trie) childList {
|
|
|
b := int(child.prefix[0])
|
|
|
+ var i int
|
|
|
|
|
|
switch {
|
|
|
case list.min <= b && b <= list.max:
|
|
|
if list.children[b-list.min] != nil {
|
|
|
panic("dense child list collision detected")
|
|
|
}
|
|
|
- list.children[b-list.min] = child
|
|
|
+ i = b - list.min
|
|
|
+ list.children[i] = child
|
|
|
|
|
|
case b < list.min:
|
|
|
children := make([]*Trie, list.max-b+1)
|
|
|
- children[0] = child
|
|
|
+ i = 0
|
|
|
+ children[i] = child
|
|
|
copy(children[list.min-b:], list.children)
|
|
|
list.children = children
|
|
|
list.min = b
|
|
|
|
|
|
default: // b > list.max
|
|
|
children := make([]*Trie, b-list.min+1)
|
|
|
- children[b-list.min] = child
|
|
|
+ i = b - list.min
|
|
|
+ children[i] = child
|
|
|
copy(children, list.children)
|
|
|
list.children = children
|
|
|
list.max = b
|
|
|
}
|
|
|
|
|
|
+ list.numChildren++
|
|
|
+ if i < list.headIndex {
|
|
|
+ list.headIndex = i
|
|
|
+ }
|
|
|
return list
|
|
|
}
|
|
|
|
|
|
-func (list *denseChildList) replace(b byte, child *Trie) {
|
|
|
- list.children[int(b)-list.min] = nil
|
|
|
- list.children[int(child.prefix[0])-list.min] = child
|
|
|
-}
|
|
|
-
|
|
|
-func (list *denseChildList) remove(child *Trie) {
|
|
|
- i := int(child.prefix[0]) - list.min
|
|
|
+func (list *denseChildList) remove(b byte) {
|
|
|
+ i := int(b) - list.min
|
|
|
if list.children[i] == nil {
|
|
|
// This is not supposed to be reached.
|
|
|
panic("removing non-existent child")
|
|
|
}
|
|
|
+ list.numChildren--
|
|
|
list.children[i] = nil
|
|
|
+
|
|
|
+ // Update head index.
|
|
|
+ if i == list.headIndex {
|
|
|
+ for ; i < len(list.children); i++ {
|
|
|
+ if list.children[i] != nil {
|
|
|
+ list.headIndex = i
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func (list *denseChildList) replace(b byte, child *Trie) {
|
|
|
+ // Make a consistency check.
|
|
|
+ if p0 := child.prefix[0]; p0 != b {
|
|
|
+ panic(fmt.Errorf("child prefix mismatch: %v != %v", p0, b))
|
|
|
+ }
|
|
|
+
|
|
|
+ // Replace the child.
|
|
|
+ list.children[int(b)-list.min] = child
|
|
|
}
|
|
|
|
|
|
func (list *denseChildList) next(b byte) *Trie {
|
|
@@ -242,3 +305,21 @@ func (list *denseChildList) walk(prefix *Prefix, visitor VisitorFunc) error {
|
|
|
|
|
|
return nil
|
|
|
}
|
|
|
+
|
|
|
+func (list *denseChildList) print(w io.Writer, indent int) {
|
|
|
+ for _, child := range list.children {
|
|
|
+ if child != nil {
|
|
|
+ child.print(w, indent)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func (list *denseChildList) total() int {
|
|
|
+ tot := 0
|
|
|
+ for _, child := range list.children {
|
|
|
+ if child != nil {
|
|
|
+ tot = tot + child.total()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return tot
|
|
|
+}
|