2020-11-08 23:55:22 +01:00
|
|
|
// Copyright 2020 Joshua J Baker. All rights reserved.
|
|
|
|
// Use of this source code is governed by an MIT-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package btree
|
2020-02-12 19:19:23 +01:00
|
|
|
|
2022-06-16 19:36:02 +02:00
|
|
|
import btree "github.com/tidwall/btree/internal"
|
2020-02-12 19:19:23 +01:00
|
|
|
|
2020-11-08 23:55:22 +01:00
|
|
|
type BTree struct {
|
2022-06-16 19:36:02 +02:00
|
|
|
base *btree.BTree
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
|
|
|
|
2020-11-08 23:55:22 +01:00
|
|
|
// PathHint is a utility type used with the *Hint() functions. Hints provide
|
|
|
|
// faster operations for clustered keys.
|
2022-06-16 19:36:02 +02:00
|
|
|
type PathHint = btree.PathHint
|
2020-02-12 19:19:23 +01:00
|
|
|
|
2020-11-08 23:55:22 +01:00
|
|
|
// New returns a new BTree
|
|
|
|
func New(less func(a, b interface{}) bool) *BTree {
|
2022-06-16 19:36:02 +02:00
|
|
|
if less == nil {
|
|
|
|
panic("nil less")
|
|
|
|
}
|
|
|
|
return &BTree{
|
|
|
|
base: btree.NewOptions(btree.Options{
|
|
|
|
Context: less,
|
|
|
|
}),
|
|
|
|
}
|
2021-08-03 07:46:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewNonConcurrent returns a new BTree which is not safe for concurrent
|
|
|
|
// write operations by multiple goroutines.
|
|
|
|
//
|
|
|
|
// This is useful for when you do not need the BTree to manage the locking,
|
|
|
|
// but would rather do it yourself.
|
|
|
|
func NewNonConcurrent(less func(a, b interface{}) bool) *BTree {
|
2020-11-08 23:55:22 +01:00
|
|
|
if less == nil {
|
|
|
|
panic("nil less")
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
return &BTree{
|
|
|
|
base: btree.NewOptions(btree.Options{
|
|
|
|
Context: less,
|
|
|
|
NoLocks: true,
|
|
|
|
}),
|
|
|
|
}
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
|
|
|
|
2020-11-08 23:55:22 +01:00
|
|
|
// Less is a convenience function that performs a comparison of two items
|
|
|
|
// using the same "less" function provided to New.
|
|
|
|
func (tr *BTree) Less(a, b interface{}) bool {
|
2022-06-16 19:36:02 +02:00
|
|
|
return tr.base.Less(a, b)
|
|
|
|
}
|
2021-08-03 07:46:20 +02:00
|
|
|
|
2022-06-16 19:36:02 +02:00
|
|
|
// Set or replace a value for a key
|
|
|
|
func (tr *BTree) Set(item interface{}) interface{} {
|
|
|
|
return tr.SetHint(item, nil)
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
|
|
|
|
2020-11-08 23:55:22 +01:00
|
|
|
// SetHint sets or replace a value for a key using a path hint
|
|
|
|
func (tr *BTree) SetHint(item interface{}, hint *PathHint) (prev interface{}) {
|
|
|
|
if item == nil {
|
|
|
|
panic("nil item")
|
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
v, ok := tr.base.SetHint(item, hint)
|
|
|
|
if !ok {
|
2020-02-12 19:19:23 +01:00
|
|
|
return nil
|
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
return v
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
|
|
|
|
2020-11-08 23:55:22 +01:00
|
|
|
// Get a value for key
|
|
|
|
func (tr *BTree) Get(key interface{}) interface{} {
|
2022-06-16 19:36:02 +02:00
|
|
|
return tr.GetHint(key, nil)
|
2020-11-08 23:55:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetHint gets a value for key using a path hint
|
|
|
|
func (tr *BTree) GetHint(key interface{}, hint *PathHint) interface{} {
|
2022-06-16 19:36:02 +02:00
|
|
|
if key == nil {
|
2020-02-12 19:19:23 +01:00
|
|
|
return nil
|
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
v, ok := tr.base.GetHint(key, hint)
|
|
|
|
if !ok {
|
|
|
|
return nil
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
return v
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
|
|
|
|
2020-11-08 23:55:22 +01:00
|
|
|
// Len returns the number of items in the tree
|
|
|
|
func (tr *BTree) Len() int {
|
2022-06-16 19:36:02 +02:00
|
|
|
return tr.base.Len()
|
2020-11-08 23:55:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Delete a value for a key
|
|
|
|
func (tr *BTree) Delete(key interface{}) interface{} {
|
|
|
|
return tr.DeleteHint(key, nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteHint deletes a value for a key using a path hint
|
|
|
|
func (tr *BTree) DeleteHint(key interface{}, hint *PathHint) interface{} {
|
2022-06-16 19:36:02 +02:00
|
|
|
if key == nil {
|
2020-02-12 19:19:23 +01:00
|
|
|
return nil
|
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
v, ok := tr.base.DeleteHint(key, nil)
|
|
|
|
if !ok {
|
2020-02-12 19:19:23 +01:00
|
|
|
return nil
|
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
return v
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
|
|
|
|
2020-11-08 23:55:22 +01:00
|
|
|
// Ascend the tree within the range [pivot, last]
|
|
|
|
// Pass nil for pivot to scan all item in ascending order
|
|
|
|
// Return false to stop iterating
|
|
|
|
func (tr *BTree) Ascend(pivot interface{}, iter func(item interface{}) bool) {
|
|
|
|
if pivot == nil {
|
2022-06-16 19:36:02 +02:00
|
|
|
tr.base.Scan(iter)
|
|
|
|
} else {
|
|
|
|
tr.base.Ascend(pivot, iter)
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-08 23:55:22 +01:00
|
|
|
// Descend the tree within the range [pivot, first]
|
|
|
|
// Pass nil for pivot to scan all item in descending order
|
|
|
|
// Return false to stop iterating
|
|
|
|
func (tr *BTree) Descend(pivot interface{}, iter func(item interface{}) bool) {
|
|
|
|
if pivot == nil {
|
2022-06-16 19:36:02 +02:00
|
|
|
tr.base.Reverse(iter)
|
|
|
|
} else {
|
|
|
|
tr.base.Descend(pivot, iter)
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-08 23:55:22 +01:00
|
|
|
// Load is for bulk loading pre-sorted items
|
|
|
|
func (tr *BTree) Load(item interface{}) interface{} {
|
|
|
|
if item == nil {
|
|
|
|
panic("nil item")
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
v, ok := tr.base.Load(item)
|
|
|
|
if !ok {
|
|
|
|
return nil
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
return v
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
|
|
|
|
2020-11-08 23:55:22 +01:00
|
|
|
// Min returns the minimum item in tree.
|
|
|
|
// Returns nil if the tree has no items.
|
|
|
|
func (tr *BTree) Min() interface{} {
|
2022-06-16 19:36:02 +02:00
|
|
|
v, ok := tr.base.Min()
|
|
|
|
if !ok {
|
2020-02-12 19:19:23 +01:00
|
|
|
return nil
|
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
return v
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
|
|
|
|
2020-11-08 23:55:22 +01:00
|
|
|
// Max returns the maximum item in tree.
|
|
|
|
// Returns nil if the tree has no items.
|
|
|
|
func (tr *BTree) Max() interface{} {
|
2022-06-16 19:36:02 +02:00
|
|
|
v, ok := tr.base.Max()
|
|
|
|
if !ok {
|
2020-02-12 19:19:23 +01:00
|
|
|
return nil
|
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
return v
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
|
|
|
|
2020-11-08 23:55:22 +01:00
|
|
|
// PopMin removes the minimum item in tree and returns it.
|
|
|
|
// Returns nil if the tree has no items.
|
|
|
|
func (tr *BTree) PopMin() interface{} {
|
2022-06-16 19:36:02 +02:00
|
|
|
v, ok := tr.base.PopMin()
|
|
|
|
if !ok {
|
2020-02-12 19:19:23 +01:00
|
|
|
return nil
|
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
return v
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
|
|
|
|
2020-11-08 23:55:22 +01:00
|
|
|
// PopMax removes the minimum item in tree and returns it.
|
|
|
|
// Returns nil if the tree has no items.
|
|
|
|
func (tr *BTree) PopMax() interface{} {
|
2022-06-16 19:36:02 +02:00
|
|
|
v, ok := tr.base.PopMax()
|
|
|
|
if !ok {
|
2020-02-12 19:19:23 +01:00
|
|
|
return nil
|
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
return v
|
2021-08-03 07:46:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetAt returns the value at index.
|
|
|
|
// Return nil if the tree is empty or the index is out of bounds.
|
|
|
|
func (tr *BTree) GetAt(index int) interface{} {
|
2022-06-16 19:36:02 +02:00
|
|
|
v, ok := tr.base.GetAt(index)
|
|
|
|
if !ok {
|
2021-08-03 07:46:20 +02:00
|
|
|
return nil
|
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
return v
|
2021-08-03 07:46:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteAt deletes the item at index.
|
|
|
|
// Return nil if the tree is empty or the index is out of bounds.
|
|
|
|
func (tr *BTree) DeleteAt(index int) interface{} {
|
2022-06-16 19:36:02 +02:00
|
|
|
v, ok := tr.base.DeleteAt(index)
|
|
|
|
if !ok {
|
2021-08-03 07:46:20 +02:00
|
|
|
return nil
|
|
|
|
}
|
2022-06-16 19:36:02 +02:00
|
|
|
return v
|
2020-11-08 23:55:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Height returns the height of the tree.
|
|
|
|
// Returns zero if tree has no items.
|
|
|
|
func (tr *BTree) Height() int {
|
2022-06-16 19:36:02 +02:00
|
|
|
return tr.base.Height()
|
2020-11-08 23:55:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Walk iterates over all items in tree, in order.
|
|
|
|
// The items param will contain one or more items.
|
2022-06-16 19:36:02 +02:00
|
|
|
func (tr *BTree) Walk(iter func(items []interface{})) {
|
|
|
|
tr.base.Walk(func(items []interface{}) bool {
|
|
|
|
iter(items)
|
|
|
|
return true
|
|
|
|
})
|
2020-11-08 23:55:22 +01:00
|
|
|
}
|
|
|
|
|
2022-06-16 19:36:02 +02:00
|
|
|
// Copy the tree. This is a copy-on-write operation and is very fast because
|
|
|
|
// it only performs a shadowed copy.
|
|
|
|
func (tr *BTree) Copy() *BTree {
|
|
|
|
return &BTree{base: tr.base.Copy()}
|
2020-02-12 19:19:23 +01:00
|
|
|
}
|
2021-04-02 02:45:15 +02:00
|
|
|
|
2022-06-16 19:36:02 +02:00
|
|
|
type Iter struct {
|
|
|
|
base btree.Iter
|
2021-04-02 02:45:15 +02:00
|
|
|
}
|
2021-08-03 07:46:20 +02:00
|
|
|
|
2022-06-16 19:36:02 +02:00
|
|
|
// Iter returns a read-only iterator.
|
|
|
|
// The Release method must be called finished with iterator.
|
|
|
|
func (tr *BTree) Iter() Iter {
|
|
|
|
return Iter{tr.base.Iter()}
|
2021-08-03 07:46:20 +02:00
|
|
|
}
|
|
|
|
|
2022-06-16 19:36:02 +02:00
|
|
|
// Seek to item greater-or-equal-to key.
|
|
|
|
// Returns false if there was no item found.
|
|
|
|
func (iter *Iter) Seek(key interface{}) bool {
|
|
|
|
return iter.base.Seek(key)
|
2021-08-03 07:46:20 +02:00
|
|
|
}
|
|
|
|
|
2022-06-16 19:36:02 +02:00
|
|
|
// First moves iterator to first item in tree.
|
|
|
|
// Returns false if the tree is empty.
|
|
|
|
func (iter *Iter) First() bool {
|
|
|
|
return iter.base.First()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Last moves iterator to last item in tree.
|
|
|
|
// Returns false if the tree is empty.
|
|
|
|
func (iter *Iter) Last() bool {
|
|
|
|
return iter.base.Last()
|
|
|
|
}
|
|
|
|
|
|
|
|
// First moves iterator to first item in tree.
|
|
|
|
// Returns false if the tree is empty.
|
|
|
|
func (iter *Iter) Release() {
|
|
|
|
iter.base.Release()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next moves iterator to the next item in iterator.
|
|
|
|
// Returns false if the tree is empty or the iterator is at the end of
|
|
|
|
// the tree.
|
|
|
|
func (iter *Iter) Next() bool {
|
|
|
|
return iter.base.Next()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prev moves iterator to the previous item in iterator.
|
|
|
|
// Returns false if the tree is empty or the iterator is at the beginning of
|
|
|
|
// the tree.
|
|
|
|
func (iter *Iter) Prev() bool {
|
|
|
|
return iter.base.Prev()
|
2021-08-03 07:46:20 +02:00
|
|
|
}
|
|
|
|
|
2022-06-16 19:36:02 +02:00
|
|
|
// Item returns the current iterator item.
|
|
|
|
func (iter *Iter) Item() interface{} {
|
|
|
|
return iter.base.Item()
|
2021-08-03 07:46:20 +02:00
|
|
|
}
|