New Trie iterator

This commit is contained in:
obscuren 2014-05-27 01:08:51 +02:00
parent 4c7bd75c1a
commit 5cdfee5143
3 changed files with 71 additions and 12 deletions

View File

@ -59,3 +59,18 @@ func CompactHexDecode(str string) []int {
return hexSlice return hexSlice
} }
func DecodeCompact(key []int) string {
base := "0123456789abcdef"
var str string
for _, v := range key {
if v < 16 {
str += string(base[v])
}
}
res, _ := hex.DecodeString(str)
return string(res)
}

View File

@ -442,6 +442,8 @@ type TrieIterator struct {
shas [][]byte shas [][]byte
values []string values []string
lastNode []byte
} }
func (t *Trie) NewIterator() *TrieIterator { func (t *Trie) NewIterator() *TrieIterator {
@ -513,3 +515,47 @@ func (it *TrieIterator) Key() string {
func (it *TrieIterator) Value() string { func (it *TrieIterator) Value() string {
return "" return ""
} }
type EachCallback func(key string, node *Value)
func (it *TrieIterator) Each(cb EachCallback) {
it.fetchNode(nil, NewValue(it.trie.Root).Bytes(), cb)
}
func (it *TrieIterator) fetchNode(key []int, node []byte, cb EachCallback) {
it.iterateNode(key, it.trie.cache.Get(node), cb)
}
func (it *TrieIterator) iterateNode(key []int, currentNode *Value, cb EachCallback) {
if currentNode.Len() == 2 {
k := CompactDecode(currentNode.Get(0).Str())
if currentNode.Get(1).Str() == "" {
it.iterateNode(key, currentNode.Get(1), cb)
} else {
pk := append(key, k...)
if k[len(k)-1] == 16 {
cb(DecodeCompact(pk), currentNode.Get(1))
} else {
it.fetchNode(pk, currentNode.Get(1).Bytes(), cb)
}
}
} else {
for i := 0; i < currentNode.Len(); i++ {
pk := append(key, i)
if i == 16 && currentNode.Get(i).Len() != 0 {
cb(DecodeCompact(pk), currentNode.Get(i))
} else {
if currentNode.Get(i).Str() == "" {
it.iterateNode(pk, currentNode.Get(i), cb)
} else {
val := currentNode.Get(i).Str()
if val != "" {
it.fetchNode(pk, []byte(val), cb)
}
}
}
}
}
}

View File

@ -154,7 +154,7 @@ func TestTrieDeleteWithValue(t *testing.T) {
} }
func TestTrieIterator(t *testing.T) { func TestTriePurge(t *testing.T) {
_, trie := New() _, trie := New()
trie.Update("c", LONG_WORD) trie.Update("c", LONG_WORD)
trie.Update("ca", LONG_WORD) trie.Update("ca", LONG_WORD)
@ -171,16 +171,14 @@ func TestTrieIterator(t *testing.T) {
} }
} }
func TestHashes(t *testing.T) { func TestTrieIt(t *testing.T) {
_, trie := New() _, trie := New()
trie.Update("cat", "dog") trie.Update("c", LONG_WORD)
trie.Update("ca", "dude") trie.Update("ca", LONG_WORD)
trie.Update("doge", "1234567890abcdefghijklmnopqrstuvwxxzABCEFGHIJKLMNOPQRSTUVWXYZ") trie.Update("cat", LONG_WORD)
trie.Update("dog", "test")
trie.Update("test", "1234567890abcdefghijklmnopqrstuvwxxzABCEFGHIJKLMNOPQRSTUVWXYZ") it := trie.NewIterator()
fmt.Printf("%x\n", trie.Root) it.Each(func(key string, node *Value) {
trie.Delete("dog") fmt.Println(key, ":", node.Str())
fmt.Printf("%x\n", trie.Root) })
trie.Delete("test")
fmt.Printf("%x\n", trie.Root)
} }