| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- package trie
- import (
- "bytes"
- "github.com/ethereum/go-ethereum/ethutil"
- )
- type NodeType byte
- const (
- EmptyNode NodeType = iota
- BranchNode
- LeafNode
- ExtNode
- )
- func getType(node *ethutil.Value) NodeType {
- if node.Len() == 0 {
- return EmptyNode
- }
- if node.Len() == 2 {
- k := CompactDecode(node.Get(0).Str())
- if HasTerm(k) {
- return LeafNode
- }
- return ExtNode
- }
- return BranchNode
- }
- type Iterator struct {
- Path [][]byte
- trie *Trie
- Key []byte
- Value *ethutil.Value
- }
- func NewIterator(trie *Trie) *Iterator {
- return &Iterator{trie: trie}
- }
- func (self *Iterator) key(node *ethutil.Value, path [][]byte) []byte {
- switch getType(node) {
- case LeafNode:
- k := RemTerm(CompactDecode(node.Get(0).Str()))
- self.Path = append(path, k)
- self.Value = node.Get(1)
- return k
- case BranchNode:
- if node.Get(16).Len() > 0 {
- return []byte{16}
- }
- for i := byte(0); i < 16; i++ {
- o := self.key(self.trie.getNode(node.Get(int(i)).Raw()), append(path, []byte{i}))
- if o != nil {
- return append([]byte{i}, o...)
- }
- }
- case ExtNode:
- currKey := node.Get(0).Bytes()
- return self.key(self.trie.getNode(node.Get(1).Raw()), append(path, currKey))
- }
- return nil
- }
- func (self *Iterator) next(node *ethutil.Value, key []byte, path [][]byte) []byte {
- switch typ := getType(node); typ {
- case EmptyNode:
- return nil
- case BranchNode:
- if len(key) > 0 {
- subNode := self.trie.getNode(node.Get(int(key[0])).Raw())
- o := self.next(subNode, key[1:], append(path, key[:1]))
- if o != nil {
- return append([]byte{key[0]}, o...)
- }
- }
- var r byte = 0
- if len(key) > 0 {
- r = key[0] + 1
- }
- for i := r; i < 16; i++ {
- subNode := self.trie.getNode(node.Get(int(i)).Raw())
- o := self.key(subNode, append(path, []byte{i}))
- if o != nil {
- return append([]byte{i}, o...)
- }
- }
- case LeafNode, ExtNode:
- k := RemTerm(CompactDecode(node.Get(0).Str()))
- if typ == LeafNode {
- if bytes.Compare([]byte(k), []byte(key)) > 0 {
- self.Value = node.Get(1)
- self.Path = append(path, k)
- return k
- }
- } else {
- subNode := self.trie.getNode(node.Get(1).Raw())
- subKey := key[len(k):]
- var ret []byte
- if BeginsWith(key, k) {
- ret = self.next(subNode, subKey, append(path, k))
- } else if bytes.Compare(k, key[:len(k)]) > 0 {
- ret = self.key(node, append(path, k))
- } else {
- ret = nil
- }
- if ret != nil {
- return append(k, ret...)
- }
- }
- }
- return nil
- }
- // Get the next in keys
- func (self *Iterator) Next(key string) []byte {
- self.trie.mut.Lock()
- defer self.trie.mut.Unlock()
- k := RemTerm(CompactHexDecode(key))
- n := self.next(self.trie.getNode(self.trie.Root), k, nil)
- self.Key = []byte(DecodeCompact(n))
- return self.Key
- }
|