aboutsummaryrefslogtreecommitdiffstats
path: root/ethutil/trie.go
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-02-24 19:11:00 +0800
committerobscuren <geffobscura@gmail.com>2014-02-24 19:11:00 +0800
commit1a98bbf1c858ed4bafcc7ffa146a30e40ef919b0 (patch)
tree20a96e133bf40c54c963e90fdd49f5987597a355 /ethutil/trie.go
parent377c9951033d4f8d157221fd36d15c39ae17cddc (diff)
downloaddexon-1a98bbf1c858ed4bafcc7ffa146a30e40ef919b0.tar
dexon-1a98bbf1c858ed4bafcc7ffa146a30e40ef919b0.tar.gz
dexon-1a98bbf1c858ed4bafcc7ffa146a30e40ef919b0.tar.bz2
dexon-1a98bbf1c858ed4bafcc7ffa146a30e40ef919b0.tar.lz
dexon-1a98bbf1c858ed4bafcc7ffa146a30e40ef919b0.tar.xz
dexon-1a98bbf1c858ed4bafcc7ffa146a30e40ef919b0.tar.zst
dexon-1a98bbf1c858ed4bafcc7ffa146a30e40ef919b0.zip
Added a trie iterator
Diffstat (limited to 'ethutil/trie.go')
-rw-r--r--ethutil/trie.go85
1 files changed, 85 insertions, 0 deletions
diff --git a/ethutil/trie.go b/ethutil/trie.go
index 322f77647..83527d364 100644
--- a/ethutil/trie.go
+++ b/ethutil/trie.go
@@ -70,6 +70,12 @@ func (cache *Cache) Get(key []byte) *Value {
return value
}
+func (cache *Cache) Delete(key []byte) {
+ delete(cache.nodes, string(key))
+
+ cache.db.Delete(key)
+}
+
func (cache *Cache) Commit() {
// Don't try to commit if it isn't dirty
if !cache.IsDirty {
@@ -413,3 +419,82 @@ func (t *Trie) Copy() *Trie {
return trie
}
+
+type TrieIterator struct {
+ trie *Trie
+ key string
+ value string
+
+ shas [][]byte
+ values []string
+}
+
+func (t *Trie) NewIterator() *TrieIterator {
+ return &TrieIterator{trie: t}
+}
+
+// Some time in the near future this will need refactoring :-)
+// XXX Note to self, IsSlice == inline node. Str == sha3 to node
+func (it *TrieIterator) workNode(currentNode *Value) {
+ if currentNode.Len() == 2 {
+ k := CompactDecode(currentNode.Get(0).Str())
+
+ if currentNode.Get(1).IsSlice() {
+ it.workNode(currentNode.Get(1))
+ } else {
+ if k[len(k)-1] == 16 {
+ it.values = append(it.values, currentNode.Get(1).Str())
+ } else {
+ it.shas = append(it.shas, currentNode.Get(1).Bytes())
+ it.getNode(currentNode.Get(1).Bytes())
+ }
+ }
+ } else {
+ for i := 0; i < currentNode.Len(); i++ {
+ if i == 16 && currentNode.Get(i).Len() != 0 {
+ it.values = append(it.values, currentNode.Get(i).Str())
+ } else {
+ if currentNode.Get(i).IsSlice() {
+ it.workNode(currentNode.Get(i))
+ } else {
+ val := currentNode.Get(i).Str()
+ if val != "" {
+ it.shas = append(it.shas, currentNode.Get(1).Bytes())
+ it.getNode([]byte(val))
+ }
+ }
+ }
+ }
+ }
+}
+
+func (it *TrieIterator) getNode(node []byte) {
+ currentNode := it.trie.cache.Get(node)
+ it.workNode(currentNode)
+}
+
+func (it *TrieIterator) Collect() [][]byte {
+ if it.trie.Root == "" {
+ return nil
+ }
+
+ it.getNode(NewValue(it.trie.Root).Bytes())
+
+ return it.shas
+}
+
+func (it *TrieIterator) Purge() int {
+ shas := it.Collect()
+ for _, sha := range shas {
+ it.trie.cache.Delete(sha)
+ }
+ return len(it.values)
+}
+
+func (it *TrieIterator) Key() string {
+ return ""
+}
+
+func (it *TrieIterator) Value() string {
+ return ""
+}