go.mod: update to github.com/tchap/go-patricia/v2 v2.3.1
Signed-off-by: Shengjing Zhu <zhsj@debian.org>
This commit is contained in:
		
							
								
								
									
										3
									
								
								vendor/github.com/tchap/go-patricia/v2/AUTHORS
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/tchap/go-patricia/v2/AUTHORS
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
This is the complete list of go-patricia copyright holders:
 | 
			
		||||
 | 
			
		||||
Ondřej Kupka <ondra.cap@gmail.com>
 | 
			
		||||
							
								
								
									
										20
									
								
								vendor/github.com/tchap/go-patricia/v2/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/tchap/go-patricia/v2/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2014 The AUTHORS
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
the Software without restriction, including without limitation the rights to
 | 
			
		||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
							
								
								
									
										363
									
								
								vendor/github.com/tchap/go-patricia/v2/patricia/children.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										363
									
								
								vendor/github.com/tchap/go-patricia/v2/patricia/children.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,363 @@
 | 
			
		||||
// 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 (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"sort"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type childList interface {
 | 
			
		||||
	length() int
 | 
			
		||||
	head() *Trie
 | 
			
		||||
	add(child *Trie) childList
 | 
			
		||||
	remove(b byte)
 | 
			
		||||
	replace(b byte, child *Trie)
 | 
			
		||||
	next(b byte) *Trie
 | 
			
		||||
	walk(prefix *Prefix, visitor VisitorFunc) error
 | 
			
		||||
	print(w io.Writer, indent int)
 | 
			
		||||
	clone() childList
 | 
			
		||||
	total() int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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, maxChildrenPerSparseNode),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) remove(b byte) {
 | 
			
		||||
	for i, node := range list.children {
 | 
			
		||||
		if node.prefix[0] == b {
 | 
			
		||||
			list.children[i] = list.children[len(list.children)-1]
 | 
			
		||||
			list.children[len(list.children)-1] = nil
 | 
			
		||||
			list.children = list.children[:len(list.children)-1]
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// This is not supposed to be reached.
 | 
			
		||||
	panic("removing non-existent child")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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] == b {
 | 
			
		||||
			list.children[i] = child
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (list *sparseChildList) total() int {
 | 
			
		||||
	tot := 0
 | 
			
		||||
	for _, child := range list.children {
 | 
			
		||||
		if child != nil {
 | 
			
		||||
			tot = tot + child.total()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return tot
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (list *sparseChildList) clone() childList {
 | 
			
		||||
	clones := make(tries, len(list.children), cap(list.children))
 | 
			
		||||
	for i, child := range list.children {
 | 
			
		||||
		clones[i] = child.Clone()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &sparseChildList{
 | 
			
		||||
		children: clones,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
	numChildren int
 | 
			
		||||
	headIndex   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:         min,
 | 
			
		||||
		max:         max,
 | 
			
		||||
		numChildren: list.length() + 1,
 | 
			
		||||
		headIndex:   0,
 | 
			
		||||
		children:    children,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (list *denseChildList) length() int {
 | 
			
		||||
	return list.numChildren
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (list *denseChildList) head() *Trie {
 | 
			
		||||
	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")
 | 
			
		||||
		}
 | 
			
		||||
		i = b - list.min
 | 
			
		||||
		list.children[i] = child
 | 
			
		||||
 | 
			
		||||
	case b < list.min:
 | 
			
		||||
		children := make([]*Trie, list.max-b+1)
 | 
			
		||||
		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)
 | 
			
		||||
		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) 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 {
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (list *denseChildList) print(w io.Writer, indent int) {
 | 
			
		||||
	for _, child := range list.children {
 | 
			
		||||
		if child != nil {
 | 
			
		||||
			child.print(w, indent)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (list *denseChildList) clone() childList {
 | 
			
		||||
	clones := make(tries, cap(list.children))
 | 
			
		||||
 | 
			
		||||
	if list.numChildren != 0 {
 | 
			
		||||
		clonedCount := 0
 | 
			
		||||
		for i := list.headIndex; i < len(list.children); i++ {
 | 
			
		||||
			child := list.children[i]
 | 
			
		||||
			if child != nil {
 | 
			
		||||
				clones[i] = child.Clone()
 | 
			
		||||
				clonedCount++
 | 
			
		||||
				if clonedCount == list.numChildren {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &denseChildList{
 | 
			
		||||
		min:         list.min,
 | 
			
		||||
		max:         list.max,
 | 
			
		||||
		numChildren: list.numChildren,
 | 
			
		||||
		headIndex:   list.headIndex,
 | 
			
		||||
		children:    clones,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (list *denseChildList) total() int {
 | 
			
		||||
	tot := 0
 | 
			
		||||
	for _, child := range list.children {
 | 
			
		||||
		if child != nil {
 | 
			
		||||
			tot = tot + child.total()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return tot
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										606
									
								
								vendor/github.com/tchap/go-patricia/v2/patricia/patricia.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										606
									
								
								vendor/github.com/tchap/go-patricia/v2/patricia/patricia.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,606 @@
 | 
			
		||||
// 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 (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// Trie
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	DefaultMaxPrefixPerNode         = 10
 | 
			
		||||
	DefaultMaxChildrenPerSparseNode = 8
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type (
 | 
			
		||||
	Prefix      []byte
 | 
			
		||||
	Item        interface{}
 | 
			
		||||
	VisitorFunc func(prefix Prefix, item Item) error
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Trie is a generic patricia trie that allows fast retrieval of items by prefix.
 | 
			
		||||
// and other funky stuff.
 | 
			
		||||
//
 | 
			
		||||
// Trie is not thread-safe.
 | 
			
		||||
type Trie struct {
 | 
			
		||||
	prefix Prefix
 | 
			
		||||
	item   Item
 | 
			
		||||
 | 
			
		||||
	maxPrefixPerNode         int
 | 
			
		||||
	maxChildrenPerSparseNode int
 | 
			
		||||
 | 
			
		||||
	children childList
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Public API ------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
type Option func(*Trie)
 | 
			
		||||
 | 
			
		||||
// Trie constructor.
 | 
			
		||||
func NewTrie(options ...Option) *Trie {
 | 
			
		||||
	trie := &Trie{}
 | 
			
		||||
 | 
			
		||||
	for _, opt := range options {
 | 
			
		||||
		opt(trie)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if trie.maxPrefixPerNode <= 0 {
 | 
			
		||||
		trie.maxPrefixPerNode = DefaultMaxPrefixPerNode
 | 
			
		||||
	}
 | 
			
		||||
	if trie.maxChildrenPerSparseNode <= 0 {
 | 
			
		||||
		trie.maxChildrenPerSparseNode = DefaultMaxChildrenPerSparseNode
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	trie.children = newSparseChildList(trie.maxChildrenPerSparseNode)
 | 
			
		||||
	return trie
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func MaxPrefixPerNode(value int) Option {
 | 
			
		||||
	return func(trie *Trie) {
 | 
			
		||||
		trie.maxPrefixPerNode = value
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func MaxChildrenPerSparseNode(value int) Option {
 | 
			
		||||
	return func(trie *Trie) {
 | 
			
		||||
		trie.maxChildrenPerSparseNode = value
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Clone makes a copy of an existing trie.
 | 
			
		||||
// Items stored in both tries become shared, obviously.
 | 
			
		||||
func (trie *Trie) Clone() *Trie {
 | 
			
		||||
	return &Trie{
 | 
			
		||||
		prefix:                   append(Prefix(nil), trie.prefix...),
 | 
			
		||||
		item:                     trie.item,
 | 
			
		||||
		maxPrefixPerNode:         trie.maxPrefixPerNode,
 | 
			
		||||
		maxChildrenPerSparseNode: trie.maxChildrenPerSparseNode,
 | 
			
		||||
		children:                 trie.children.clone(),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Item returns the item stored in the root of this trie.
 | 
			
		||||
func (trie *Trie) Item() Item {
 | 
			
		||||
	return trie.item
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Insert inserts a new item into the trie using the given prefix. Insert does
 | 
			
		||||
// not replace existing items. It returns false if an item was already in place.
 | 
			
		||||
func (trie *Trie) Insert(key Prefix, item Item) (inserted bool) {
 | 
			
		||||
	return trie.put(key, item, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set works much like Insert, but it always sets the item, possibly replacing
 | 
			
		||||
// the item previously inserted.
 | 
			
		||||
func (trie *Trie) Set(key Prefix, item Item) {
 | 
			
		||||
	trie.put(key, item, true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get returns the item located at key.
 | 
			
		||||
//
 | 
			
		||||
// This method is a bit dangerous, because Get can as well end up in an internal
 | 
			
		||||
// node that is not really representing any user-defined value. So when nil is
 | 
			
		||||
// a valid value being used, it is not possible to tell if the value was inserted
 | 
			
		||||
// into the tree by the user or not. A possible workaround for this is not to use
 | 
			
		||||
// nil interface as a valid value, even using zero value of any type is enough
 | 
			
		||||
// to prevent this bad behaviour.
 | 
			
		||||
func (trie *Trie) Get(key Prefix) (item Item) {
 | 
			
		||||
	_, node, found, leftover := trie.findSubtree(key)
 | 
			
		||||
	if !found || len(leftover) != 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return node.item
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Match returns what Get(prefix) != nil would return. The same warning as for
 | 
			
		||||
// Get applies here as well.
 | 
			
		||||
func (trie *Trie) Match(prefix Prefix) (matchedExactly bool) {
 | 
			
		||||
	return trie.Get(prefix) != nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MatchSubtree returns true when there is a subtree representing extensions
 | 
			
		||||
// to key, that is if there are any keys in the tree which have key as prefix.
 | 
			
		||||
func (trie *Trie) MatchSubtree(key Prefix) (matched bool) {
 | 
			
		||||
	_, _, matched, _ = trie.findSubtree(key)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Visit calls visitor on every node containing a non-nil item
 | 
			
		||||
// in alphabetical order.
 | 
			
		||||
//
 | 
			
		||||
// If an error is returned from visitor, the function stops visiting the tree
 | 
			
		||||
// and returns that error, unless it is a special error - SkipSubtree. In that
 | 
			
		||||
// case Visit skips the subtree represented by the current node and continues
 | 
			
		||||
// elsewhere.
 | 
			
		||||
func (trie *Trie) Visit(visitor VisitorFunc) error {
 | 
			
		||||
	return trie.walk(nil, visitor)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (trie *Trie) size() int {
 | 
			
		||||
	n := 0
 | 
			
		||||
 | 
			
		||||
	trie.walk(nil, func(prefix Prefix, item Item) error {
 | 
			
		||||
		n++
 | 
			
		||||
		return nil
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (trie *Trie) total() int {
 | 
			
		||||
	return 1 + trie.children.total()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VisitSubtree works much like Visit, but it only visits nodes matching prefix.
 | 
			
		||||
func (trie *Trie) VisitSubtree(prefix Prefix, visitor VisitorFunc) error {
 | 
			
		||||
	// Nil prefix not allowed.
 | 
			
		||||
	if prefix == nil {
 | 
			
		||||
		panic(ErrNilPrefix)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Empty trie must be handled explicitly.
 | 
			
		||||
	if trie.prefix == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Locate the relevant subtree.
 | 
			
		||||
	_, root, found, leftover := trie.findSubtree(prefix)
 | 
			
		||||
	if !found {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	prefix = append(prefix, leftover...)
 | 
			
		||||
 | 
			
		||||
	// Visit it.
 | 
			
		||||
	return root.walk(prefix, visitor)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VisitPrefixes visits only nodes that represent prefixes of key.
 | 
			
		||||
// To say the obvious, returning SkipSubtree from visitor makes no sense here.
 | 
			
		||||
func (trie *Trie) VisitPrefixes(key Prefix, visitor VisitorFunc) error {
 | 
			
		||||
	// Nil key not allowed.
 | 
			
		||||
	if key == nil {
 | 
			
		||||
		panic(ErrNilPrefix)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Empty trie must be handled explicitly.
 | 
			
		||||
	if trie.prefix == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Walk the path matching key prefixes.
 | 
			
		||||
	node := trie
 | 
			
		||||
	prefix := key
 | 
			
		||||
	offset := 0
 | 
			
		||||
	for {
 | 
			
		||||
		// Compute what part of prefix matches.
 | 
			
		||||
		common := node.longestCommonPrefixLength(key)
 | 
			
		||||
		key = key[common:]
 | 
			
		||||
		offset += common
 | 
			
		||||
 | 
			
		||||
		// Partial match means that there is no subtree matching prefix.
 | 
			
		||||
		if common < len(node.prefix) {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Call the visitor.
 | 
			
		||||
		if item := node.item; item != nil {
 | 
			
		||||
			if err := visitor(prefix[:offset], item); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(key) == 0 {
 | 
			
		||||
			// This node represents key, we are finished.
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// There is some key suffix left, move to the children.
 | 
			
		||||
		child := node.children.next(key[0])
 | 
			
		||||
		if child == nil {
 | 
			
		||||
			// There is nowhere to continue, return.
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		node = child
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete deletes the item represented by the given prefix.
 | 
			
		||||
//
 | 
			
		||||
// True is returned if the matching node was found and deleted.
 | 
			
		||||
func (trie *Trie) Delete(key Prefix) (deleted bool) {
 | 
			
		||||
	// Nil prefix not allowed.
 | 
			
		||||
	if key == nil {
 | 
			
		||||
		panic(ErrNilPrefix)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Empty trie must be handled explicitly.
 | 
			
		||||
	if trie.prefix == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Find the relevant node.
 | 
			
		||||
	path, found, _ := trie.findSubtreePath(key)
 | 
			
		||||
	if !found {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	node := path[len(path)-1]
 | 
			
		||||
	var parent *Trie
 | 
			
		||||
	if len(path) != 1 {
 | 
			
		||||
		parent = path[len(path)-2]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If the item is already set to nil, there is nothing to do.
 | 
			
		||||
	if node.item == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Delete the item.
 | 
			
		||||
	node.item = nil
 | 
			
		||||
 | 
			
		||||
	// Initialise i before goto.
 | 
			
		||||
	// Will be used later in a loop.
 | 
			
		||||
	i := len(path) - 1
 | 
			
		||||
 | 
			
		||||
	// In case there are some child nodes, we cannot drop the whole subtree.
 | 
			
		||||
	// We can try to compact nodes, though.
 | 
			
		||||
	if node.children.length() != 0 {
 | 
			
		||||
		goto Compact
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// In case we are at the root, just reset it and we are done.
 | 
			
		||||
	if parent == nil {
 | 
			
		||||
		node.reset()
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We can drop a subtree.
 | 
			
		||||
	// Find the first ancestor that has its value set or it has 2 or more child nodes.
 | 
			
		||||
	// That will be the node where to drop the subtree at.
 | 
			
		||||
	for ; i >= 0; i-- {
 | 
			
		||||
		if current := path[i]; current.item != nil || current.children.length() >= 2 {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Handle the case when there is no such node.
 | 
			
		||||
	// In other words, we can reset the whole tree.
 | 
			
		||||
	if i == -1 {
 | 
			
		||||
		path[0].reset()
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We can just remove the subtree here.
 | 
			
		||||
	node = path[i]
 | 
			
		||||
	if i == 0 {
 | 
			
		||||
		parent = nil
 | 
			
		||||
	} else {
 | 
			
		||||
		parent = path[i-1]
 | 
			
		||||
	}
 | 
			
		||||
	// i+1 is always a valid index since i is never pointing to the last node.
 | 
			
		||||
	// The loop above skips at least the last node since we are sure that the item
 | 
			
		||||
	// is set to nil and it has no children, othewise we would be compacting instead.
 | 
			
		||||
	node.children.remove(path[i+1].prefix[0])
 | 
			
		||||
 | 
			
		||||
Compact:
 | 
			
		||||
	// The node is set to the first non-empty ancestor,
 | 
			
		||||
	// so try to compact since that might be possible now.
 | 
			
		||||
	if compacted := node.compact(); compacted != node {
 | 
			
		||||
		if parent == nil {
 | 
			
		||||
			*node = *compacted
 | 
			
		||||
		} else {
 | 
			
		||||
			parent.children.replace(node.prefix[0], compacted)
 | 
			
		||||
			*parent = *parent.compact()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteSubtree finds the subtree exactly matching prefix and deletes it.
 | 
			
		||||
//
 | 
			
		||||
// True is returned if the subtree was found and deleted.
 | 
			
		||||
func (trie *Trie) DeleteSubtree(prefix Prefix) (deleted bool) {
 | 
			
		||||
	// Nil prefix not allowed.
 | 
			
		||||
	if prefix == nil {
 | 
			
		||||
		panic(ErrNilPrefix)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Empty trie must be handled explicitly.
 | 
			
		||||
	if trie.prefix == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Locate the relevant subtree.
 | 
			
		||||
	parent, root, found, _ := trie.findSubtree(prefix)
 | 
			
		||||
	if !found {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If we are in the root of the trie, reset the trie.
 | 
			
		||||
	if parent == nil {
 | 
			
		||||
		root.reset()
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Otherwise remove the root node from its parent.
 | 
			
		||||
	parent.children.remove(root.prefix[0])
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Internal helper methods -----------------------------------------------------
 | 
			
		||||
 | 
			
		||||
func (trie *Trie) empty() bool {
 | 
			
		||||
	return trie.item == nil && trie.children.length() == 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (trie *Trie) reset() {
 | 
			
		||||
	trie.prefix = nil
 | 
			
		||||
	trie.children = newSparseChildList(trie.maxPrefixPerNode)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (trie *Trie) put(key Prefix, item Item, replace bool) (inserted bool) {
 | 
			
		||||
	// Nil prefix not allowed.
 | 
			
		||||
	if key == nil {
 | 
			
		||||
		panic(ErrNilPrefix)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
		common int
 | 
			
		||||
		node   *Trie = trie
 | 
			
		||||
		child  *Trie
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if node.prefix == nil {
 | 
			
		||||
		if len(key) <= trie.maxPrefixPerNode {
 | 
			
		||||
			node.prefix = key
 | 
			
		||||
			goto InsertItem
 | 
			
		||||
		}
 | 
			
		||||
		node.prefix = key[:trie.maxPrefixPerNode]
 | 
			
		||||
		key = key[trie.maxPrefixPerNode:]
 | 
			
		||||
		goto AppendChild
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		// Compute the longest common prefix length.
 | 
			
		||||
		common = node.longestCommonPrefixLength(key)
 | 
			
		||||
		key = key[common:]
 | 
			
		||||
 | 
			
		||||
		// Only a part matches, split.
 | 
			
		||||
		if common < len(node.prefix) {
 | 
			
		||||
			goto SplitPrefix
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// common == len(node.prefix) since never (common > len(node.prefix))
 | 
			
		||||
		// common == len(former key) <-> 0 == len(key)
 | 
			
		||||
		// -> former key == node.prefix
 | 
			
		||||
		if len(key) == 0 {
 | 
			
		||||
			goto InsertItem
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Check children for matching prefix.
 | 
			
		||||
		child = node.children.next(key[0])
 | 
			
		||||
		if child == nil {
 | 
			
		||||
			goto AppendChild
 | 
			
		||||
		}
 | 
			
		||||
		node = child
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
SplitPrefix:
 | 
			
		||||
	// Split the prefix if necessary.
 | 
			
		||||
	child = new(Trie)
 | 
			
		||||
	*child = *node
 | 
			
		||||
	*node = *NewTrie()
 | 
			
		||||
	node.prefix = child.prefix[:common]
 | 
			
		||||
	child.prefix = child.prefix[common:]
 | 
			
		||||
	child = child.compact()
 | 
			
		||||
	node.children = node.children.add(child)
 | 
			
		||||
 | 
			
		||||
AppendChild:
 | 
			
		||||
	// Keep appending children until whole prefix is inserted.
 | 
			
		||||
	// This loop starts with empty node.prefix that needs to be filled.
 | 
			
		||||
	for len(key) != 0 {
 | 
			
		||||
		child := NewTrie()
 | 
			
		||||
		if len(key) <= trie.maxPrefixPerNode {
 | 
			
		||||
			child.prefix = key
 | 
			
		||||
			node.children = node.children.add(child)
 | 
			
		||||
			node = child
 | 
			
		||||
			goto InsertItem
 | 
			
		||||
		} else {
 | 
			
		||||
			child.prefix = key[:trie.maxPrefixPerNode]
 | 
			
		||||
			key = key[trie.maxPrefixPerNode:]
 | 
			
		||||
			node.children = node.children.add(child)
 | 
			
		||||
			node = child
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
InsertItem:
 | 
			
		||||
	// Try to insert the item if possible.
 | 
			
		||||
	if replace || node.item == nil {
 | 
			
		||||
		node.item = item
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (trie *Trie) compact() *Trie {
 | 
			
		||||
	// Only a node with a single child can be compacted.
 | 
			
		||||
	if trie.children.length() != 1 {
 | 
			
		||||
		return trie
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	child := trie.children.head()
 | 
			
		||||
 | 
			
		||||
	// If any item is set, we cannot compact since we want to retain
 | 
			
		||||
	// the ability to do searching by key. This makes compaction less usable,
 | 
			
		||||
	// but that simply cannot be avoided.
 | 
			
		||||
	if trie.item != nil || child.item != nil {
 | 
			
		||||
		return trie
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Make sure the combined prefixes fit into a single node.
 | 
			
		||||
	if len(trie.prefix)+len(child.prefix) > trie.maxPrefixPerNode {
 | 
			
		||||
		return trie
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Concatenate the prefixes, move the items.
 | 
			
		||||
	child.prefix = append(trie.prefix, child.prefix...)
 | 
			
		||||
	if trie.item != nil {
 | 
			
		||||
		child.item = trie.item
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return child
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (trie *Trie) findSubtree(prefix Prefix) (parent *Trie, root *Trie, found bool, leftover Prefix) {
 | 
			
		||||
	// Find the subtree matching prefix.
 | 
			
		||||
	root = trie
 | 
			
		||||
	for {
 | 
			
		||||
		// Compute what part of prefix matches.
 | 
			
		||||
		common := root.longestCommonPrefixLength(prefix)
 | 
			
		||||
		prefix = prefix[common:]
 | 
			
		||||
 | 
			
		||||
		// We used up the whole prefix, subtree found.
 | 
			
		||||
		if len(prefix) == 0 {
 | 
			
		||||
			found = true
 | 
			
		||||
			leftover = root.prefix[common:]
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Partial match means that there is no subtree matching prefix.
 | 
			
		||||
		if common < len(root.prefix) {
 | 
			
		||||
			leftover = root.prefix[common:]
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// There is some prefix left, move to the children.
 | 
			
		||||
		child := root.children.next(prefix[0])
 | 
			
		||||
		if child == nil {
 | 
			
		||||
			// There is nowhere to continue, there is no subtree matching prefix.
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		parent = root
 | 
			
		||||
		root = child
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (trie *Trie) findSubtreePath(prefix Prefix) (path []*Trie, found bool, leftover Prefix) {
 | 
			
		||||
	// Find the subtree matching prefix.
 | 
			
		||||
	root := trie
 | 
			
		||||
	var subtreePath []*Trie
 | 
			
		||||
	for {
 | 
			
		||||
		// Append the current root to the path.
 | 
			
		||||
		subtreePath = append(subtreePath, root)
 | 
			
		||||
 | 
			
		||||
		// Compute what part of prefix matches.
 | 
			
		||||
		common := root.longestCommonPrefixLength(prefix)
 | 
			
		||||
		prefix = prefix[common:]
 | 
			
		||||
 | 
			
		||||
		// We used up the whole prefix, subtree found.
 | 
			
		||||
		if len(prefix) == 0 {
 | 
			
		||||
			path = subtreePath
 | 
			
		||||
			found = true
 | 
			
		||||
			leftover = root.prefix[common:]
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Partial match means that there is no subtree matching prefix.
 | 
			
		||||
		if common < len(root.prefix) {
 | 
			
		||||
			leftover = root.prefix[common:]
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// There is some prefix left, move to the children.
 | 
			
		||||
		child := root.children.next(prefix[0])
 | 
			
		||||
		if child == nil {
 | 
			
		||||
			// There is nowhere to continue, there is no subtree matching prefix.
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		root = child
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (trie *Trie) walk(actualRootPrefix Prefix, visitor VisitorFunc) error {
 | 
			
		||||
	var prefix Prefix
 | 
			
		||||
	// Allocate a bit more space for prefix at the beginning.
 | 
			
		||||
	if actualRootPrefix == nil {
 | 
			
		||||
		prefix = make(Prefix, 32+len(trie.prefix))
 | 
			
		||||
		copy(prefix, trie.prefix)
 | 
			
		||||
		prefix = prefix[:len(trie.prefix)]
 | 
			
		||||
	} else {
 | 
			
		||||
		prefix = make(Prefix, 32+len(actualRootPrefix))
 | 
			
		||||
		copy(prefix, actualRootPrefix)
 | 
			
		||||
		prefix = prefix[:len(actualRootPrefix)]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Visit the root first. Not that this works for empty trie as well since
 | 
			
		||||
	// in that case item == nil && len(children) == 0.
 | 
			
		||||
	if trie.item != nil {
 | 
			
		||||
		if err := visitor(prefix, trie.item); err != nil {
 | 
			
		||||
			if err == SkipSubtree {
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Then continue to the children.
 | 
			
		||||
	return trie.children.walk(&prefix, visitor)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (trie *Trie) longestCommonPrefixLength(prefix Prefix) (i int) {
 | 
			
		||||
	for ; i < len(prefix) && i < len(trie.prefix) && prefix[i] == trie.prefix[i]; i++ {
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (trie *Trie) dump() string {
 | 
			
		||||
	writer := &bytes.Buffer{}
 | 
			
		||||
	trie.print(writer, 0)
 | 
			
		||||
	return writer.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (trie *Trie) print(writer io.Writer, indent int) {
 | 
			
		||||
	fmt.Fprintf(writer, "%s%s %v\n", strings.Repeat(" ", indent), string(trie.prefix), trie.item)
 | 
			
		||||
	trie.children.print(writer, indent+2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Errors ----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	SkipSubtree  = errors.New("Skip this subtree")
 | 
			
		||||
	ErrNilPrefix = errors.New("Nil prefix passed into a method call")
 | 
			
		||||
)
 | 
			
		||||
		Reference in New Issue
	
	Block a user