// Copyright (c) 2014 The go-patricia AUTHORS // // Use of this source code is governed by The MIT License // that can be found in the LICENSE file. package patricia import "sort" type childList interface { length() int head() *Trie add(child *Trie) childList replace(b byte, child *Trie) remove(child *Trie) next(b byte) *Trie walk(prefix *Prefix, visitor VisitorFunc) error } type tries []*Trie func (t tries) Len() int { return len(t) } func (t tries) Less(i, j int) bool { strings := sort.StringSlice{string(t[i].prefix), string(t[j].prefix)} return strings.Less(0, 1) } func (t tries) Swap(i, j int) { t[i], t[j] = t[j], t[i] } type sparseChildList struct { children tries } func newSparseChildList(maxChildrenPerSparseNode int) childList { return &sparseChildList{ children: make(tries, 0, DefaultMaxChildrenPerSparseNode), } } func (list *sparseChildList) length() int { return len(list.children) } func (list *sparseChildList) head() *Trie { return list.children[0] } func (list *sparseChildList) add(child *Trie) childList { // Search for an empty spot and insert the child if possible. if len(list.children) != cap(list.children) { list.children = append(list.children, child) return list } // Otherwise we have to transform to the dense list type. return newDenseChildList(list, child) } func (list *sparseChildList) replace(b byte, child *Trie) { // Seek the child and replace it. for i, node := range list.children { if node.prefix[0] == b { list.children[i] = child return } } } func (list *sparseChildList) remove(child *Trie) { for i, node := range list.children { if node.prefix[0] == child.prefix[0] { list.children = append(list.children[:i], list.children[i+1:]...) return } } // This is not supposed to be reached. panic("removing non-existent child") } func (list *sparseChildList) next(b byte) *Trie { for _, child := range list.children { if child.prefix[0] == b { return child } } return nil } func (list *sparseChildList) walk(prefix *Prefix, visitor VisitorFunc) error { sort.Sort(list.children) for _, child := range list.children { *prefix = append(*prefix, child.prefix...) if child.item != nil { err := visitor(*prefix, child.item) if err != nil { if err == SkipSubtree { *prefix = (*prefix)[:len(*prefix)-len(child.prefix)] continue } *prefix = (*prefix)[:len(*prefix)-len(child.prefix)] return err } } err := child.children.walk(prefix, visitor) *prefix = (*prefix)[:len(*prefix)-len(child.prefix)] if err != nil { return err } } return nil } type denseChildList struct { min int max int children []*Trie } func newDenseChildList(list *sparseChildList, child *Trie) childList { var ( min int = 255 max int = 0 ) for _, child := range list.children { b := int(child.prefix[0]) if b < min { min = b } if b > max { max = b } } b := int(child.prefix[0]) if b < min { min = b } if b > max { max = b } children := make([]*Trie, max-min+1) for _, child := range list.children { children[int(child.prefix[0])-min] = child } children[int(child.prefix[0])-min] = child return &denseChildList{min, max, children} } func (list *denseChildList) length() int { return list.max - list.min + 1 } func (list *denseChildList) head() *Trie { return list.children[0] } func (list *denseChildList) add(child *Trie) childList { b := int(child.prefix[0]) 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 case b < list.min: children := make([]*Trie, list.max-b+1) children[0] = 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 copy(children, list.children) list.children = children list.max = b } 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 if list.children[i] == nil { // This is not supposed to be reached. panic("removing non-existent child") } list.children[i] = nil } func (list *denseChildList) next(b byte) *Trie { i := int(b) if i < list.min || list.max < i { return nil } return list.children[i-list.min] } func (list *denseChildList) walk(prefix *Prefix, visitor VisitorFunc) error { for _, child := range list.children { if child == nil { continue } *prefix = append(*prefix, child.prefix...) if child.item != nil { if err := visitor(*prefix, child.item); err != nil { if err == SkipSubtree { *prefix = (*prefix)[:len(*prefix)-len(child.prefix)] continue } *prefix = (*prefix)[:len(*prefix)-len(child.prefix)] return err } } err := child.children.walk(prefix, visitor) *prefix = (*prefix)[:len(*prefix)-len(child.prefix)] if err != nil { return err } } return nil }