good morning!!!!

Skip to content
Snippets Groups Projects
Commit 9bc5c4a0 authored by Jeffrey Wilcke's avatar Jeffrey Wilcke
Browse files

Long over due Trie delete implemented

parent 4afb624c
Branches
Tags
No related merge requests found
...@@ -148,6 +148,10 @@ func (t *Trie) Get(key string) string { ...@@ -148,6 +148,10 @@ func (t *Trie) Get(key string) string {
return c.Str() return c.Str()
} }
func (t *Trie) Delete(key string) {
t.Update(key, "")
}
func (t *Trie) GetState(node interface{}, key []int) interface{} { func (t *Trie) GetState(node interface{}, key []int) interface{} {
n := NewValue(node) n := NewValue(node)
// Return the node if key is empty (= found) // Return the node if key is empty (= found)
...@@ -202,9 +206,10 @@ func (t *Trie) UpdateState(node interface{}, key []int, value string) interface{ ...@@ -202,9 +206,10 @@ func (t *Trie) UpdateState(node interface{}, key []int, value string) interface{
return t.InsertState(node, key, value) return t.InsertState(node, key, value)
} else { } else {
// delete it // delete it
return t.DeleteState(node, key)
} }
return "" return t.Root
} }
func (t *Trie) Put(node interface{}) interface{} { func (t *Trie) Put(node interface{}) interface{} {
...@@ -313,6 +318,87 @@ func (t *Trie) InsertState(node interface{}, key []int, value interface{}) inter ...@@ -313,6 +318,87 @@ func (t *Trie) InsertState(node interface{}, key []int, value interface{}) inter
return "" return ""
} }
func (t *Trie) DeleteState(node interface{}, key []int) interface{} {
if len(key) == 0 {
return ""
}
// New node
n := NewValue(node)
if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 {
return ""
}
currentNode := t.GetNode(node)
// Check for "special" 2 slice type node
if currentNode.Len() == 2 {
// Decode the key
k := CompactDecode(currentNode.Get(0).Str())
v := currentNode.Get(1).Raw()
// Matching key pair (ie. there's already an object with this key)
if CompareIntSlice(k, key) {
return ""
} else if CompareIntSlice(key[:len(k)], k) {
hash := t.DeleteState(v, key[len(k):])
child := t.GetNode(hash)
var newNode []interface{}
if child.Len() == 2 {
newKey := append(k, CompactDecode(child.Get(0).Str())...)
newNode = []interface{}{CompactEncode(newKey), child.Get(1).Raw()}
} else {
newNode = []interface{}{currentNode.Get(0).Str(), hash}
}
return t.Put(newNode)
} else {
return node
}
} else {
// Copy the current node over to the new node and replace the first nibble in the key
n := EmptyStringSlice(17)
var newNode []interface{}
for i := 0; i < 17; i++ {
cpy := currentNode.Get(i).Raw()
if cpy != nil {
n[i] = cpy
}
}
n[key[0]] = t.DeleteState(n[key[0]], key[1:])
amount := -1
for i := 0; i < 17; i++ {
if n[i] != "" {
if amount == -1 {
amount = i
} else {
amount = -2
}
}
}
if amount == 16 {
newNode = []interface{}{CompactEncode([]int{16}), n[amount]}
} else if amount >= 0 {
child := t.GetNode(n[amount])
if child.Len() == 17 {
newNode = []interface{}{CompactEncode([]int{amount}), n[amount]}
} else if child.Len() == 2 {
key := append([]int{amount}, CompactDecode(child.Get(0).Str())...)
newNode = []interface{}{CompactEncode(key), child.Get(1).Str()}
}
} else {
newNode = n
}
return t.Put(newNode)
}
return ""
}
// Simple compare function which creates a rlp value out of the evaluated objects // Simple compare function which creates a rlp value out of the evaluated objects
func (t *Trie) Cmp(trie *Trie) bool { func (t *Trie) Cmp(trie *Trie) bool {
return NewValue(t.Root).Cmp(NewValue(trie.Root)) return NewValue(t.Root).Cmp(NewValue(trie.Root))
......
package ethutil package ethutil
import ( import (
_ "encoding/hex" "reflect"
_ "fmt"
"testing" "testing"
) )
...@@ -116,3 +115,36 @@ func TestTrieCmp(t *testing.T) { ...@@ -116,3 +115,36 @@ func TestTrieCmp(t *testing.T) {
t.Errorf("Expected tries not to be equal %x %x", trie1.Root, trie2.Root) t.Errorf("Expected tries not to be equal %x %x", trie1.Root, trie2.Root)
} }
} }
func TestTrieDelete(t *testing.T) {
_, trie := New()
trie.Update("cat", LONG_WORD)
exp := trie.Root
trie.Update("dog", LONG_WORD)
trie.Delete("dog")
if !reflect.DeepEqual(exp, trie.Root) {
t.Errorf("Expected tries to be equal %x : %x", exp, trie.Root)
}
trie.Update("dog", LONG_WORD)
exp = trie.Root
trie.Update("dude", LONG_WORD)
trie.Delete("dude")
if !reflect.DeepEqual(exp, trie.Root) {
t.Errorf("Expected tries to be equal %x : %x", exp, trie.Root)
}
}
func TestTrieDeleteWithValue(t *testing.T) {
_, trie := New()
trie.Update("c", LONG_WORD)
exp := trie.Root
trie.Update("ca", LONG_WORD)
trie.Update("cat", LONG_WORD)
trie.Delete("ca")
trie.Delete("cat")
if !reflect.DeepEqual(exp, trie.Root) {
t.Errorf("Expected tries to be equal %x : %x", exp, trie.Root)
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment