|
|
@ -1,5 +1,5 @@ |
|
|
|
/* |
|
|
|
/* |
|
|
|
* Minio Cloud Storage, (C) 2015 Minio, Inc. |
|
|
|
* Minio Cloud Storage, (C) 2014, 2015, 2016, 2017 Minio, Inc. |
|
|
|
* |
|
|
|
* |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
@ -14,80 +14,78 @@ |
|
|
|
* limitations under the License. |
|
|
|
* limitations under the License. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
package cmd |
|
|
|
// Package trie implements a simple trie tree for minio server/tools borrows
|
|
|
|
|
|
|
|
// idea from - https://godoc.org/golang.org/x/text/internal/triegen.
|
|
|
|
|
|
|
|
package trie |
|
|
|
|
|
|
|
|
|
|
|
// This package borrows idea from - https://godoc.org/golang.org/x/text/internal/triegen
|
|
|
|
// Node trie tree node container carries value and children.
|
|
|
|
|
|
|
|
type Node struct { |
|
|
|
// Trie trie container
|
|
|
|
|
|
|
|
type Trie struct { |
|
|
|
|
|
|
|
root *trieNode |
|
|
|
|
|
|
|
size int |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// newTrie get new trie
|
|
|
|
|
|
|
|
func newTrie() *Trie { |
|
|
|
|
|
|
|
return &Trie{ |
|
|
|
|
|
|
|
root: newTrieNode(), |
|
|
|
|
|
|
|
size: 0, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// trieNode trie tree node container carries value and children
|
|
|
|
|
|
|
|
type trieNode struct { |
|
|
|
|
|
|
|
exists bool |
|
|
|
exists bool |
|
|
|
value interface{} |
|
|
|
value interface{} |
|
|
|
child map[rune]*trieNode // runes as child
|
|
|
|
child map[rune]*Node // runes as child.
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func newTrieNode() *trieNode { |
|
|
|
// newNode create a new trie node.
|
|
|
|
return &trieNode{ |
|
|
|
func newNode() *Node { |
|
|
|
|
|
|
|
return &Node{ |
|
|
|
exists: false, |
|
|
|
exists: false, |
|
|
|
value: nil, |
|
|
|
value: nil, |
|
|
|
child: make(map[rune]*trieNode), |
|
|
|
child: make(map[rune]*Node), |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Insert insert a key
|
|
|
|
// Trie is a trie container.
|
|
|
|
|
|
|
|
type Trie struct { |
|
|
|
|
|
|
|
root *Node |
|
|
|
|
|
|
|
size int |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Root returns root node.
|
|
|
|
|
|
|
|
func (t *Trie) Root() *Node { |
|
|
|
|
|
|
|
return t.root |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Insert insert a key.
|
|
|
|
func (t *Trie) Insert(key string) { |
|
|
|
func (t *Trie) Insert(key string) { |
|
|
|
curNode := t.root |
|
|
|
curNode := t.root |
|
|
|
for _, v := range key { |
|
|
|
for _, v := range key { |
|
|
|
if curNode.child[v] == nil { |
|
|
|
if curNode.child[v] == nil { |
|
|
|
curNode.child[v] = newTrieNode() |
|
|
|
curNode.child[v] = newNode() |
|
|
|
} |
|
|
|
} |
|
|
|
curNode = curNode.child[v] |
|
|
|
curNode = curNode.child[v] |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if !curNode.exists { |
|
|
|
if !curNode.exists { |
|
|
|
// increment when new rune child is added
|
|
|
|
// increment when new rune child is added.
|
|
|
|
t.size++ |
|
|
|
t.size++ |
|
|
|
curNode.exists = true |
|
|
|
curNode.exists = true |
|
|
|
} |
|
|
|
} |
|
|
|
// value is stored for retrieval in future
|
|
|
|
// value is stored for retrieval in future.
|
|
|
|
curNode.value = key |
|
|
|
curNode.value = key |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// PrefixMatch - prefix match
|
|
|
|
// PrefixMatch - prefix match.
|
|
|
|
func (t *Trie) PrefixMatch(key string) []interface{} { |
|
|
|
func (t *Trie) PrefixMatch(key string) []interface{} { |
|
|
|
node, _ := t.findNode(key) |
|
|
|
node, _ := t.findNode(key) |
|
|
|
if node != nil { |
|
|
|
if node != nil { |
|
|
|
return t.walk(node) |
|
|
|
return t.Walk(node) |
|
|
|
} |
|
|
|
} |
|
|
|
return []interface{}{} |
|
|
|
return []interface{}{} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// walk the tree
|
|
|
|
// Walk the tree.
|
|
|
|
func (t *Trie) walk(node *trieNode) (ret []interface{}) { |
|
|
|
func (t *Trie) Walk(node *Node) (ret []interface{}) { |
|
|
|
if node.exists { |
|
|
|
if node.exists { |
|
|
|
ret = append(ret, node.value) |
|
|
|
ret = append(ret, node.value) |
|
|
|
} |
|
|
|
} |
|
|
|
for _, v := range node.child { |
|
|
|
for _, v := range node.child { |
|
|
|
ret = append(ret, t.walk(v)...) |
|
|
|
ret = append(ret, t.Walk(v)...) |
|
|
|
} |
|
|
|
} |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// find nodes corresponding to key
|
|
|
|
// find nodes corresponding to key.
|
|
|
|
func (t *Trie) findNode(key string) (node *trieNode, index int) { |
|
|
|
func (t *Trie) findNode(key string) (node *Node, index int) { |
|
|
|
curNode := t.root |
|
|
|
curNode := t.root |
|
|
|
f := false |
|
|
|
f := false |
|
|
|
for k, v := range key { |
|
|
|
for k, v := range key { |
|
|
@ -110,3 +108,11 @@ func (t *Trie) findNode(key string) (node *trieNode, index int) { |
|
|
|
|
|
|
|
|
|
|
|
return curNode, index |
|
|
|
return curNode, index |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// NewTrie create a new trie.
|
|
|
|
|
|
|
|
func NewTrie() *Trie { |
|
|
|
|
|
|
|
return &Trie{ |
|
|
|
|
|
|
|
root: newNode(), |
|
|
|
|
|
|
|
size: 0, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |