private void Parse() { if (this.children != null) { return; } Resolve(); LList list = this.parsed_rlp == null?RLP.DecodeLazyList(this.rlp) : this.parsed_rlp; if (list != null && list.Count == 2) { this.children = new object[2]; TrieKey key = TrieKey.FromPacked(list.GetBytes(0)); this.children[0] = key; if (key.IsTerminal) { this.children[1] = list.GetBytes(1); } else { this.children[1] = list.IsList(1) ? new TrieNode(this.reference, list.GetList(1)) : new TrieNode(this.reference, list.GetBytes(1)); } } else { this.children = new object[17]; this.parsed_rlp = list; } }
public void ScanTree(TrieNode node, TrieKey key, IScanAction scan_action) { if (node != null) { if (node.Hash != null) { scan_action.OnNode(node.Hash, node); } if (node.NodeType == TrieNode.TrieNodeType.BranchNode) { if (node.BranchNodeGetValue() != null) { scan_action.OnValue(node.Hash, node, key.ToNormal(), node.BranchNodeGetValue()); } for (int i = 0; i < 16; i++) { ScanTree(node.BranchNodeGetChild(i), key.Concat(TrieKey.SingleHex(i)), scan_action); } } else if (node.NodeType == TrieNode.TrieNodeType.KVNodeNode) { ScanTree(node.KVNodeGetChildNode(), key.Concat(node.KVNodeGetKey()), scan_action); } else { scan_action.OnValue(node.Hash, node, key.Concat(node.KVNodeGetKey()).ToNormal(), node.KVNodeGetValue()); } } }
public byte[] Get(TrieNode node, TrieKey key) { if (node == null) { return(null); } if (node.NodeType == TrieNode.TrieNodeType.BranchNode) { if (key.IsEmpty) { return(node.BranchNodeGetValue()); } TrieNode child = node.BranchNodeGetChild(key.GetHex(0)); return(Get(child, key.Shift(1))); } else { TrieKey k = key.MatchAndShift(node.KVNodeGetKey()); if (k == null) { return(null); } if (node.NodeType == TrieNode.TrieNodeType.KVNodeValue) { return(k.IsEmpty ? node.KVNodeGetValue() : null); } else { return(Get(node.KVNodeGetChildNode(), k)); } } }
public static TrieKey SingleHex(int hex) { TrieKey ret = new TrieKey(new byte[1], 1, false); ret.SetHex(0, hex); return(ret); }
public override bool Equals(object obj) { if (obj == null) { return(false); } if (GetType() != obj.GetType()) { return(false); } TrieKey k = (TrieKey)obj; int len = GetLength(); if (len != k.GetLength()) { return(false); } for (int i = 0; i < len; i++) { if (GetHex(i) != k.GetHex(i)) { return(false); } } return(IsTerminal == k.IsTerminal); }
public void Delete(byte[] key) { TrieKey k = TrieKey.FromNormal(key); if (this.root != null) { this.root = Delete(this.root, k); } }
public byte[] Get(byte[] key) { if (!HasRoot) { return(null); } return(Get(root, TrieKey.FromNormal(key))); }
public TrieKey GetCommonPrefix(TrieKey k) { int prefix_length = 0; int thisLength = GetLength(); int klen = k.GetLength(); while (prefix_length < thisLength && prefix_length < klen && GetHex(prefix_length) == k.GetHex(prefix_length)) { prefix_length++; } byte[] prefix_key = new byte[(prefix_length + 1) >> 1]; TrieKey ret = new TrieKey(prefix_key, (prefix_length & 1) == 0 ? 0 : 1, prefix_length == GetLength() && prefix_length == k.GetLength() && terminal && k.IsTerminal); for (int i = 0; i < prefix_length; i++) { ret.SetHex(i, k.GetHex(i)); } return(ret); }
public TrieKey MatchAndShift(TrieKey k) { int len = GetLength(); int klen = k.GetLength(); if (len < klen) { return(null); } if ((this.off & 1) == (k.off & 1)) { // optimization to compare whole keys bytes if ((this.off & 1) == 1 && GetHex(0) != k.GetHex(0)) { return(null); } int idx1 = (this.off + 1) >> 1; int idx2 = (k.off + 1) >> 1; int l = klen >> 1; for (int i = 0; i < l; i++, idx1++, idx2++) { if (this.key[idx1] != k.key[idx2]) { return(null); } } } else { for (int i = 0; i < klen; i++) { if (GetHex(i) != k.GetHex(i)) { return(null); } } } return(Shift(klen)); }
public void Put(byte[] key, byte[] value) { TrieKey k = TrieKey.FromNormal(key); if (this.root == null) { if (value != null && value.Length > 0) { this.root = new TrieNode(this, k, value); } } else { if (value == null || value.Length == 0) { this.root = Delete(this.root, k); } else { this.root = Insert(root, k, value); } } }
public TrieKey Concat(TrieKey k) { if (IsTerminal) { throw new System.Exception("Can' append to terminal key: " + this + " + " + k); } int len = GetLength(); int klen = k.GetLength(); int new_len = len + klen; byte[] newKeyBytes = new byte[(new_len + 1) >> 1]; TrieKey ret = new TrieKey(newKeyBytes, new_len & 1, k.IsTerminal); for (int i = 0; i < len; i++) { ret.SetHex(i, GetHex(i)); } for (int i = 0; i < klen; i++) { ret.SetHex(len + i, k.GetHex(i)); } return(ret); }
public TrieNode(Trie reference, TrieKey key, object value_or_node) : this(reference, new object[] { key, value_or_node }) { this.reference = reference; dirty = true; }
private TrieNode Insert(TrieNode node, TrieKey key, object node_or_value) { if (node.NodeType == TrieNode.TrieNodeType.BranchNode) { if (key.IsEmpty) { return(node.BranchNodeSetValue((byte[])node_or_value)); } TrieNode child = node.BranchNodeGetChild(key.GetHex(0)); if (child != null) { return(node.BranchNodeSetChild(key.GetHex(0), Insert(child, key.Shift(1), node_or_value))); } else { TrieKey child_key = key.Shift(1); TrieNode new_child; if (!child_key.IsEmpty) { new_child = new TrieNode(this, child_key, node_or_value); } else { new_child = node_or_value is TrieNode ? (TrieNode)node_or_value : new TrieNode(this, child_key, node_or_value); } return(node.BranchNodeSetChild(key.GetHex(0), new_child)); } } else { TrieKey current_node_key = node.KVNodeGetKey(); TrieKey common_prefix = key.GetCommonPrefix(current_node_key); if (common_prefix.IsEmpty) { TrieNode new_branch = new TrieNode(this); Insert(new_branch, current_node_key, node.KVNodeGetValueOrNode()); Insert(new_branch, key, node_or_value); node.Dispose(); return(new_branch); } else if (common_prefix.Equals(key)) { return(node.KVNodeSetValueOrNode(node_or_value)); } else if (common_prefix.Equals(current_node_key)) { Insert(node.KVNodeGetChildNode(), key.Shift(common_prefix.GetLength()), node_or_value); return(node.Invalidate()); } else { TrieNode new_branch = new TrieNode(this); TrieNode newKvNode = new TrieNode(this, common_prefix, new_branch); Insert(newKvNode, current_node_key, node.KVNodeGetValueOrNode()); Insert(newKvNode, key, node_or_value); node.Dispose(); return(newKvNode); } } }
public void ScanTree(IScanAction scan_action) { ScanTree(this.root, TrieKey.Empty(false), scan_action); }
public TrieNode Delete(TrieNode node, TrieKey key) { TrieNode kv_node = null; if (node.NodeType == TrieNode.TrieNodeType.BranchNode) { if (key.IsEmpty) { node.BranchNodeSetValue(null); } else { int index = key.GetHex(0); TrieNode child = node.BranchNodeGetChild(index); if (child == null) { return(node); } TrieNode new_node = Delete(child, key.Shift(1)); node.BranchNodeSetChild(index, new_node); if (new_node != null) { return(node); } } int compact_index = node.BranchNodeCompactIndex(); if (compact_index < 0) { return(node); } node.Dispose(); if (compact_index == 16) { return(new TrieNode(this, TrieKey.Empty(true), node.BranchNodeGetValue())); } else { kv_node = new TrieNode(this, TrieKey.SingleHex(compact_index), node.BranchNodeGetChild(compact_index)); } } else { TrieKey k = key.MatchAndShift(node.KVNodeGetKey()); if (k == null) { return(node); } else if (node.NodeType == TrieNode.TrieNodeType.KVNodeValue) { if (k.IsEmpty) { node.Dispose(); return(null); } else { return(node); } } else { TrieNode child = Delete(node.KVNodeGetChildNode(), k); if (child == null) { throw new System.Exception("Shouldn't happen"); } kv_node = node.KVNodeSetValueOrNode(child); } } TrieNode new_child = kv_node.KVNodeGetChildNode(); if (new_child.NodeType != TrieNode.TrieNodeType.BranchNode) { TrieKey new_key = kv_node.KVNodeGetKey().Concat(new_child.KVNodeGetKey()); TrieNode new_node = new TrieNode(this, new_key, new_child.KVNodeGetValueOrNode()); new_child.Dispose(); kv_node.Dispose(); return(new_node); } else { return(kv_node); } }