2014-05-19 20:46:41 -07:00
|
|
|
package merkle
|
|
|
|
|
|
|
|
import (
|
2014-05-21 21:48:41 -07:00
|
|
|
"bytes"
|
2014-05-21 16:24:50 -07:00
|
|
|
"math"
|
2014-05-21 21:48:41 -07:00
|
|
|
"io"
|
2014-05-19 20:46:41 -07:00
|
|
|
"crypto/sha256"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Immutable AVL Tree (wraps the Node root)
|
|
|
|
|
|
|
|
type IAVLTree struct {
|
|
|
|
root *IAVLNode
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewIAVLTree() *IAVLTree {
|
|
|
|
return &IAVLTree{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *IAVLTree) Root() Node {
|
2014-05-21 21:48:41 -07:00
|
|
|
return self.root
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
|
2014-05-21 21:48:41 -07:00
|
|
|
func (self *IAVLTree) Size() uint64 {
|
2014-05-19 20:46:41 -07:00
|
|
|
return self.root.Size()
|
|
|
|
}
|
|
|
|
|
2014-05-21 21:48:41 -07:00
|
|
|
func (self *IAVLTree) Height() uint8 {
|
|
|
|
return self.root.Height()
|
|
|
|
}
|
|
|
|
|
2014-05-21 16:24:50 -07:00
|
|
|
func (self *IAVLTree) Has(key Key) bool {
|
2014-05-22 02:34:07 -07:00
|
|
|
return self.root.Has(nil, key)
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
|
2014-05-21 16:24:50 -07:00
|
|
|
func (self *IAVLTree) Put(key Key, value Value) (err error) {
|
2014-05-22 02:34:07 -07:00
|
|
|
self.root, _ = self.root.Put(nil, key, value)
|
2014-05-19 20:46:41 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2014-05-21 21:48:41 -07:00
|
|
|
func (self *IAVLTree) Hash() ([]byte, uint64) {
|
2014-05-21 16:24:50 -07:00
|
|
|
return self.root.Hash()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *IAVLTree) Get(key Key) (value Value, err error) {
|
2014-05-22 02:34:07 -07:00
|
|
|
return self.root.Get(nil, key)
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
|
2014-05-21 16:24:50 -07:00
|
|
|
func (self *IAVLTree) Remove(key Key) (value Value, err error) {
|
2014-05-22 02:34:07 -07:00
|
|
|
new_root, value, err := self.root.Remove(nil, key)
|
2014-05-19 20:46:41 -07:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
self.root = new_root
|
|
|
|
return value, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Node
|
|
|
|
|
|
|
|
type IAVLNode struct {
|
2014-05-21 16:24:50 -07:00
|
|
|
key Key
|
|
|
|
value Value
|
2014-05-21 21:48:41 -07:00
|
|
|
size uint64
|
|
|
|
height uint8
|
2014-05-19 20:46:41 -07:00
|
|
|
hash []byte
|
|
|
|
left *IAVLNode
|
|
|
|
right *IAVLNode
|
2014-05-21 21:48:41 -07:00
|
|
|
|
|
|
|
// volatile
|
|
|
|
flags byte
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
|
2014-05-21 21:48:41 -07:00
|
|
|
func (self *IAVLNode) Copy() *IAVLNode {
|
2014-05-19 20:46:41 -07:00
|
|
|
if self == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return &IAVLNode{
|
|
|
|
key: self.key,
|
|
|
|
value: self.value,
|
2014-05-21 21:48:41 -07:00
|
|
|
size: self.size,
|
2014-05-19 20:46:41 -07:00
|
|
|
height: self.height,
|
|
|
|
left: self.left,
|
|
|
|
right: self.right,
|
2014-05-21 21:48:41 -07:00
|
|
|
hash: nil,
|
|
|
|
flags: byte(0),
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-21 16:24:50 -07:00
|
|
|
func (self *IAVLNode) Key() Key {
|
|
|
|
return self.key
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *IAVLNode) Value() Value {
|
|
|
|
return self.value
|
|
|
|
}
|
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
func (self *IAVLNode) Left(db Db) Node {
|
2014-05-21 16:24:50 -07:00
|
|
|
if self.left == nil { return nil }
|
2014-05-22 02:34:07 -07:00
|
|
|
return self.left_filled(db)
|
2014-05-21 16:24:50 -07:00
|
|
|
}
|
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
func (self *IAVLNode) Right(db Db) Node {
|
2014-05-21 16:24:50 -07:00
|
|
|
if self.right == nil { return nil }
|
2014-05-22 02:34:07 -07:00
|
|
|
return self.right_filled(db)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *IAVLNode) left_filled(db Db) *IAVLNode {
|
|
|
|
// XXX
|
|
|
|
return self.left
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *IAVLNode) right_filled(db Db) *IAVLNode {
|
|
|
|
// XXX
|
2014-05-21 16:24:50 -07:00
|
|
|
return self.right
|
|
|
|
}
|
|
|
|
|
2014-05-21 21:48:41 -07:00
|
|
|
func (self *IAVLNode) Size() uint64 {
|
2014-05-21 16:24:50 -07:00
|
|
|
if self == nil {
|
|
|
|
return 0
|
|
|
|
}
|
2014-05-21 21:48:41 -07:00
|
|
|
return self.size
|
2014-05-21 16:24:50 -07:00
|
|
|
}
|
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
func (self *IAVLNode) Has(db Db, key Key) (has bool) {
|
2014-05-19 20:46:41 -07:00
|
|
|
if self == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if self.key.Equals(key) {
|
|
|
|
return true
|
|
|
|
} else if key.Less(self.key) {
|
2014-05-22 02:34:07 -07:00
|
|
|
return self.left_filled(db).Has(db, key)
|
2014-05-19 20:46:41 -07:00
|
|
|
} else {
|
2014-05-22 02:34:07 -07:00
|
|
|
return self.right_filled(db).Has(db, key)
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
func (self *IAVLNode) Get(db Db, key Key) (value Value, err error) {
|
2014-05-19 20:46:41 -07:00
|
|
|
if self == nil {
|
|
|
|
return nil, NotFound(key)
|
|
|
|
}
|
|
|
|
if self.key.Equals(key) {
|
|
|
|
return self.value, nil
|
|
|
|
} else if key.Less(self.key) {
|
2014-05-22 02:34:07 -07:00
|
|
|
return self.left_filled(db).Get(db, key)
|
2014-05-19 20:46:41 -07:00
|
|
|
} else {
|
2014-05-22 02:34:07 -07:00
|
|
|
return self.right_filled(db).Get(db, key)
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-21 21:48:41 -07:00
|
|
|
func (self *IAVLNode) Bytes() []byte {
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
self.WriteTo(b)
|
|
|
|
return b.Bytes()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *IAVLNode) Hash() ([]byte, uint64) {
|
2014-05-21 16:24:50 -07:00
|
|
|
if self == nil {
|
2014-05-21 16:57:30 -07:00
|
|
|
return nil, 0
|
|
|
|
}
|
|
|
|
if self.hash != nil {
|
|
|
|
return self.hash, 0
|
2014-05-21 16:24:50 -07:00
|
|
|
}
|
2014-05-21 21:48:41 -07:00
|
|
|
|
2014-05-21 16:24:50 -07:00
|
|
|
hasher := sha256.New()
|
2014-05-21 21:48:41 -07:00
|
|
|
_, hashCount, err := self.WriteTo(hasher)
|
|
|
|
if err != nil { panic(err) }
|
|
|
|
self.hash = hasher.Sum(nil)
|
|
|
|
|
|
|
|
return self.hash, hashCount
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *IAVLNode) WriteTo(writer io.Writer) (written int64, hashCount uint64, err error) {
|
|
|
|
|
|
|
|
write := func(bytes []byte) {
|
|
|
|
if err == nil {
|
|
|
|
var n int
|
|
|
|
n, err = writer.Write(bytes)
|
|
|
|
written += int64(n)
|
|
|
|
}
|
|
|
|
}
|
2014-05-21 16:24:50 -07:00
|
|
|
|
|
|
|
// node descriptor
|
|
|
|
nodeDesc := byte(0)
|
|
|
|
if self.value != nil { nodeDesc |= 0x01 }
|
|
|
|
if self.left != nil { nodeDesc |= 0x02 }
|
|
|
|
if self.right != nil { nodeDesc |= 0x04 }
|
2014-05-21 21:48:41 -07:00
|
|
|
write([]byte{nodeDesc})
|
2014-05-21 16:24:50 -07:00
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
// node height & size
|
|
|
|
write(UInt8(self.height).Bytes())
|
|
|
|
write(UInt64(self.size).Bytes())
|
|
|
|
|
2014-05-21 16:24:50 -07:00
|
|
|
// node key
|
|
|
|
keyBytes := self.key.Bytes()
|
|
|
|
if len(keyBytes) > 255 { panic("key is too long") }
|
2014-05-21 21:48:41 -07:00
|
|
|
write([]byte{byte(len(keyBytes))})
|
|
|
|
write(keyBytes)
|
2014-05-21 16:24:50 -07:00
|
|
|
|
|
|
|
// node value
|
|
|
|
if self.value != nil {
|
|
|
|
valueBytes := self.value.Bytes()
|
|
|
|
if len(valueBytes) > math.MaxUint32 { panic("value is too long") }
|
2014-05-21 21:48:41 -07:00
|
|
|
write([]byte{byte(len(valueBytes))})
|
|
|
|
write(valueBytes)
|
2014-05-21 16:24:50 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// left child
|
|
|
|
if self.left != nil {
|
2014-05-21 16:57:30 -07:00
|
|
|
leftHash, leftCount := self.left.Hash()
|
|
|
|
hashCount += leftCount
|
2014-05-21 21:48:41 -07:00
|
|
|
write(leftHash)
|
2014-05-21 16:24:50 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// right child
|
|
|
|
if self.right != nil {
|
2014-05-21 16:57:30 -07:00
|
|
|
rightHash, rightCount := self.right.Hash()
|
|
|
|
hashCount += rightCount
|
2014-05-21 21:48:41 -07:00
|
|
|
write(rightHash)
|
2014-05-21 16:24:50 -07:00
|
|
|
}
|
|
|
|
|
2014-05-21 21:48:41 -07:00
|
|
|
return written, hashCount+1, err
|
2014-05-21 16:24:50 -07:00
|
|
|
}
|
|
|
|
|
2014-05-20 16:33:10 -07:00
|
|
|
// Returns a new tree (unless node is the root) & a copy of the popped node.
|
|
|
|
// Can only pop nodes that have one or no children.
|
2014-05-22 02:34:07 -07:00
|
|
|
func (self *IAVLNode) pop_node(db Db, node *IAVLNode) (new_self, new_node *IAVLNode) {
|
2014-05-20 16:33:10 -07:00
|
|
|
if self == nil {
|
|
|
|
panic("self can't be nil")
|
|
|
|
} else if node == nil {
|
2014-05-19 20:46:41 -07:00
|
|
|
panic("node can't be nil")
|
|
|
|
} else if node.left != nil && node.right != nil {
|
|
|
|
panic("node must not have both left and right")
|
|
|
|
}
|
|
|
|
|
2014-05-20 16:33:10 -07:00
|
|
|
if self == node {
|
|
|
|
|
2014-05-19 20:46:41 -07:00
|
|
|
var n *IAVLNode
|
|
|
|
if node.left != nil {
|
2014-05-22 02:34:07 -07:00
|
|
|
n = node.left_filled(db)
|
2014-05-19 20:46:41 -07:00
|
|
|
} else if node.right != nil {
|
2014-05-22 02:34:07 -07:00
|
|
|
n = node.right_filled(db)
|
2014-05-19 20:46:41 -07:00
|
|
|
} else {
|
|
|
|
n = nil
|
|
|
|
}
|
2014-05-21 21:48:41 -07:00
|
|
|
node = node.Copy()
|
2014-05-19 20:46:41 -07:00
|
|
|
node.left = nil
|
|
|
|
node.right = nil
|
2014-05-22 02:34:07 -07:00
|
|
|
node.calc_height_and_size(db)
|
2014-05-19 20:46:41 -07:00
|
|
|
return n, node
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2014-05-21 21:48:41 -07:00
|
|
|
self = self.Copy()
|
2014-05-20 16:33:10 -07:00
|
|
|
if node.key.Less(self.key) {
|
2014-05-22 02:34:07 -07:00
|
|
|
self.left, node = self.left_filled(db).pop_node(db, node)
|
2014-05-20 16:33:10 -07:00
|
|
|
} else {
|
2014-05-22 02:34:07 -07:00
|
|
|
self.right, node = self.right_filled(db).pop_node(db, node)
|
2014-05-20 16:33:10 -07:00
|
|
|
}
|
2014-05-22 02:34:07 -07:00
|
|
|
self.calc_height_and_size(db)
|
2014-05-20 16:33:10 -07:00
|
|
|
return self, node
|
|
|
|
|
|
|
|
}
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
func (self *IAVLNode) rotate_right(db Db) *IAVLNode {
|
2014-05-21 21:48:41 -07:00
|
|
|
self = self.Copy()
|
2014-05-22 02:34:07 -07:00
|
|
|
sl := self.left_filled(db).Copy()
|
2014-05-20 16:33:10 -07:00
|
|
|
slr := sl.right
|
|
|
|
|
|
|
|
sl.right = self
|
|
|
|
self.left = slr
|
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
self.calc_height_and_size(db)
|
|
|
|
sl.calc_height_and_size(db)
|
2014-05-20 16:33:10 -07:00
|
|
|
|
|
|
|
return sl
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
func (self *IAVLNode) rotate_left(db Db) *IAVLNode {
|
2014-05-21 21:48:41 -07:00
|
|
|
self = self.Copy()
|
2014-05-22 02:34:07 -07:00
|
|
|
sr := self.right_filled(db).Copy()
|
2014-05-20 16:33:10 -07:00
|
|
|
srl := sr.left
|
|
|
|
|
|
|
|
sr.left = self
|
|
|
|
self.right = srl
|
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
self.calc_height_and_size(db)
|
|
|
|
sr.calc_height_and_size(db)
|
2014-05-20 16:33:10 -07:00
|
|
|
|
|
|
|
return sr
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
func (self *IAVLNode) calc_height_and_size(db Db) {
|
|
|
|
self.height = maxUint8(self.left_filled(db).Height(), self.right_filled(db).Height()) + 1
|
|
|
|
self.size = self.left_filled(db).Size() + self.right_filled(db).Size() + 1
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
func (self *IAVLNode) calc_balance(db Db) int {
|
2014-05-19 20:46:41 -07:00
|
|
|
if self == nil {
|
2014-05-20 16:33:10 -07:00
|
|
|
return 0
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
2014-05-22 02:34:07 -07:00
|
|
|
return int(self.left_filled(db).Height()) - int(self.right_filled(db).Height())
|
2014-05-20 16:33:10 -07:00
|
|
|
}
|
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
func (self *IAVLNode) balance(db Db) (new_self *IAVLNode) {
|
|
|
|
balance := self.calc_balance(db)
|
2014-05-20 16:33:10 -07:00
|
|
|
if (balance > 1) {
|
2014-05-22 02:34:07 -07:00
|
|
|
if (self.left_filled(db).calc_balance(db) >= 0) {
|
2014-05-20 16:33:10 -07:00
|
|
|
// Left Left Case
|
2014-05-22 02:34:07 -07:00
|
|
|
return self.rotate_right(db)
|
2014-05-19 20:46:41 -07:00
|
|
|
} else {
|
2014-05-20 16:33:10 -07:00
|
|
|
// Left Right Case
|
2014-05-21 21:48:41 -07:00
|
|
|
self = self.Copy()
|
2014-05-22 02:34:07 -07:00
|
|
|
self.left = self.left_filled(db).rotate_left(db)
|
2014-05-21 21:48:41 -07:00
|
|
|
//self.calc_height_and_size()
|
2014-05-22 02:34:07 -07:00
|
|
|
return self.rotate_right(db)
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
}
|
2014-05-20 16:33:10 -07:00
|
|
|
if (balance < -1) {
|
2014-05-22 02:34:07 -07:00
|
|
|
if (self.right_filled(db).calc_balance(db) <= 0) {
|
2014-05-20 16:33:10 -07:00
|
|
|
// Right Right Case
|
2014-05-22 02:34:07 -07:00
|
|
|
return self.rotate_left(db)
|
2014-05-20 16:33:10 -07:00
|
|
|
} else {
|
|
|
|
// Right Left Case
|
2014-05-21 21:48:41 -07:00
|
|
|
self = self.Copy()
|
2014-05-22 02:34:07 -07:00
|
|
|
self.right = self.right_filled(db).rotate_right(db)
|
2014-05-21 21:48:41 -07:00
|
|
|
//self.calc_height_and_size()
|
2014-05-22 02:34:07 -07:00
|
|
|
return self.rotate_left(db)
|
2014-05-20 16:33:10 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Nothing changed
|
2014-05-19 20:46:41 -07:00
|
|
|
return self
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: don't clear the hash if the value hasn't changed.
|
2014-05-22 02:34:07 -07:00
|
|
|
func (self *IAVLNode) Put(db Db, key Key, value Value) (_ *IAVLNode, updated bool) {
|
2014-05-19 20:46:41 -07:00
|
|
|
if self == nil {
|
2014-05-21 21:48:41 -07:00
|
|
|
return &IAVLNode{key: key, value: value, height: 1, size: 1, hash: nil}, false
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
|
2014-05-21 21:48:41 -07:00
|
|
|
self = self.Copy()
|
2014-05-19 20:46:41 -07:00
|
|
|
|
|
|
|
if self.key.Equals(key) {
|
|
|
|
self.value = value
|
|
|
|
return self, true
|
|
|
|
}
|
|
|
|
|
|
|
|
if key.Less(self.key) {
|
2014-05-22 02:34:07 -07:00
|
|
|
self.left, updated = self.left_filled(db).Put(db, key, value)
|
2014-05-19 20:46:41 -07:00
|
|
|
} else {
|
2014-05-22 02:34:07 -07:00
|
|
|
self.right, updated = self.right_filled(db).Put(db, key, value)
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
2014-05-20 16:33:10 -07:00
|
|
|
if updated {
|
|
|
|
return self, updated
|
|
|
|
} else {
|
2014-05-22 02:34:07 -07:00
|
|
|
self.calc_height_and_size(db)
|
|
|
|
return self.balance(db), updated
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
func (self *IAVLNode) Remove(db Db, key Key) (new_self *IAVLNode, value Value, err error) {
|
2014-05-19 20:46:41 -07:00
|
|
|
if self == nil {
|
|
|
|
return nil, nil, NotFound(key)
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.key.Equals(key) {
|
|
|
|
if self.left != nil && self.right != nil {
|
2014-05-22 02:34:07 -07:00
|
|
|
if self.left_filled(db).Size() < self.right_filled(db).Size() {
|
|
|
|
self, new_self = self.pop_node(db, self.right_filled(db).lmd(db))
|
2014-05-19 20:46:41 -07:00
|
|
|
} else {
|
2014-05-22 02:34:07 -07:00
|
|
|
self, new_self = self.pop_node(db, self.left_filled(db).rmd(db))
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
2014-05-20 16:33:10 -07:00
|
|
|
new_self.left = self.left
|
|
|
|
new_self.right = self.right
|
2014-05-22 02:34:07 -07:00
|
|
|
new_self.calc_height_and_size(db)
|
2014-05-20 16:33:10 -07:00
|
|
|
return new_self, self.value, nil
|
2014-05-19 20:46:41 -07:00
|
|
|
} else if self.left == nil {
|
2014-05-22 02:34:07 -07:00
|
|
|
return self.right_filled(db), self.value, nil
|
2014-05-19 20:46:41 -07:00
|
|
|
} else if self.right == nil {
|
2014-05-22 02:34:07 -07:00
|
|
|
return self.left_filled(db), self.value, nil
|
2014-05-19 20:46:41 -07:00
|
|
|
} else {
|
|
|
|
return nil, self.value, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if key.Less(self.key) {
|
2014-05-20 16:33:10 -07:00
|
|
|
if self.left == nil {
|
|
|
|
return self, nil, NotFound(key)
|
|
|
|
}
|
|
|
|
var new_left *IAVLNode
|
2014-05-22 02:34:07 -07:00
|
|
|
new_left, value, err = self.left_filled(db).Remove(db, key)
|
|
|
|
if new_left == self.left_filled(db) { // not found
|
2014-05-20 16:33:10 -07:00
|
|
|
return self, nil, err
|
|
|
|
} else if err != nil { // some other error
|
|
|
|
return self, value, err
|
|
|
|
}
|
2014-05-21 21:48:41 -07:00
|
|
|
self = self.Copy()
|
2014-05-20 16:33:10 -07:00
|
|
|
self.left = new_left
|
2014-05-19 20:46:41 -07:00
|
|
|
} else {
|
2014-05-20 16:33:10 -07:00
|
|
|
if self.right == nil {
|
|
|
|
return self, nil, NotFound(key)
|
|
|
|
}
|
|
|
|
var new_right *IAVLNode
|
2014-05-22 02:34:07 -07:00
|
|
|
new_right, value, err = self.right_filled(db).Remove(db, key)
|
|
|
|
if new_right == self.right_filled(db) { // not found
|
2014-05-20 16:33:10 -07:00
|
|
|
return self, nil, err
|
|
|
|
} else if err != nil { // some other error
|
|
|
|
return self, value, err
|
|
|
|
}
|
2014-05-21 21:48:41 -07:00
|
|
|
self = self.Copy()
|
2014-05-20 16:33:10 -07:00
|
|
|
self.right = new_right
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
2014-05-22 02:34:07 -07:00
|
|
|
self.calc_height_and_size(db)
|
|
|
|
return self.balance(db), value, err
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
|
2014-05-21 21:48:41 -07:00
|
|
|
func (self *IAVLNode) Height() uint8 {
|
2014-05-19 20:46:41 -07:00
|
|
|
if self == nil {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return self.height
|
|
|
|
}
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
func (self *IAVLNode) _md(side func(*IAVLNode)*IAVLNode) (*IAVLNode) {
|
|
|
|
if self == nil {
|
|
|
|
return nil
|
|
|
|
} else if side(self) != nil {
|
|
|
|
return side(self)._md(side)
|
|
|
|
} else {
|
|
|
|
return self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
func (self *IAVLNode) lmd(db Db) (*IAVLNode) {
|
|
|
|
return self._md(func(node *IAVLNode)*IAVLNode { return node.left_filled(db) })
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
|
2014-05-22 02:34:07 -07:00
|
|
|
func (self *IAVLNode) rmd(db Db) (*IAVLNode) {
|
|
|
|
return self._md(func(node *IAVLNode)*IAVLNode { return node.right_filled(db) })
|
2014-05-19 20:46:41 -07:00
|
|
|
}
|
|
|
|
|
2014-05-21 21:48:41 -07:00
|
|
|
func maxUint8(a, b uint8) uint8 {
|
2014-05-19 20:46:41 -07:00
|
|
|
if a > b {
|
|
|
|
return a
|
|
|
|
}
|
|
|
|
return b
|
|
|
|
}
|