| 
									
										
										
										
											2014-10-31 14:45:03 +01:00
										 |  |  | package trie | 
					
						
							| 
									
										
										
										
											2014-10-10 16:56:28 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-23 15:01:27 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/ethutil" | 
					
						
							| 
									
										
										
										
											2014-10-10 16:56:28 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							|  |  |  | } |