Skip to content

Commit f4fca54

Browse files
authored
Merge branch 'master' into actions
2 parents ccc2c19 + dd74d1e commit f4fca54

File tree

8 files changed

+1862
-380
lines changed

8 files changed

+1862
-380
lines changed

README.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ An efficient [B-tree](https://en.wikipedia.org/wiki/B-tree) implementation in Go
1010
- `Map` and `Set` types for ordered key-value maps and sets,
1111
- Fast bulk loading for pre-ordered data using the `Load()` method.
1212
- `Copy()` method with copy-on-write support.
13-
- Thread-safe operations.
1413
- [Path hinting](PATH_HINT.md) optimization for operations with nearby keys.
14+
- Allows for array-like operations. ([Counted B-tree](https://www.chiark.greenend.org.uk/~sgtatham/algorithms/cbtree.html))
1515

1616
## Using
1717

@@ -27,16 +27,15 @@ This package includes the following types of B-trees:
2727

2828
- [`btree.Map`](#btreemap):
2929
A fast B-tree for storing ordered key value pairs.
30-
Go 1.18+
30+
3131
- [`btree.Set`](#btreeset):
3232
Like `Map`, but only for storing keys.
33-
Go 1.18+
34-
- [`btree.BTreeG`](#btreegeneric):
35-
A feature-rich B-tree for storing data using a custom comparator.
36-
Go 1.18+
33+
34+
- [`btree.BTreeG`](#btreebtreeg):
35+
A feature-rich B-tree for storing data using a custom comparator. Thread-safe.
36+
3737
- [`btree.BTree`](#btreebtree):
38-
Like `BTreeG` but uses the `interface{}` type for data. Backwards compatible.
39-
Go 1.16+
38+
Like `BTreeG` but uses the `interface{}` type for data. Backwards compatible. Thread-safe.
4039

4140
### btree.Map
4241

@@ -221,6 +220,9 @@ Load(item) // load presorted items into tree
221220
SetHint(item, *hint) // insert or replace an existing item
222221
GetHint(item, *hint) // get an existing item
223222
DeleteHint(item, *hint) // delete an item
223+
AscendHint(key, iter, *hint)
224+
DescendHint(key, iter, *hint)
225+
SeekHint(key, iter, *hint)
224226

225227
// Copy-on-write
226228
Copy() // copy the btree
@@ -341,6 +343,9 @@ Load(item) // load presorted items into tree
341343
SetHint(item, *hint) // insert or replace an existing item
342344
GetHint(item, *hint) // get an existing item
343345
DeleteHint(item, *hint) // delete an item
346+
AscendHint(key, iter, *hint)
347+
DescendHint(key, iter, *hint)
348+
SeekHint(key, iter, *hint)
344349

345350
// Copy-on-write
346351
Copy() // copy the btree

btree.go

Lines changed: 124 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func New(less func(a, b any) bool) *BTree {
2020
//
2121
// This is useful for when you do not need the BTree to manage the locking,
2222
// but would rather do it yourself.
23+
//
2324
// Deprecated: use NewOptions
2425
func NewNonConcurrent(less func(a, b any) bool) *BTree {
2526
if less == nil {
@@ -64,16 +65,34 @@ func (tr *BTree) SetHint(item any, hint *PathHint) (prev any) {
6465
// Get a value for key.
6566
// Returns nil if the key was not found.
6667
func (tr *BTree) Get(key any) any {
67-
return tr.GetHint(key, nil)
68+
return tr.getHintMut(key, nil, false)
69+
}
70+
71+
func (tr *BTree) GetMut(key any) any {
72+
return tr.getHintMut(key, nil, true)
73+
}
74+
75+
func (tr *BTree) GetHint(key any, hint *PathHint) any {
76+
return tr.getHintMut(key, hint, false)
77+
}
78+
79+
func (tr *BTree) GetHintMut(key any, hint *PathHint) any {
80+
return tr.getHintMut(key, hint, true)
6881
}
6982

7083
// GetHint gets a value for key using a path hint.
7184
// Returns nil if the item was not found.
72-
func (tr *BTree) GetHint(key any, hint *PathHint) (value any) {
85+
func (tr *BTree) getHintMut(key any, hint *PathHint, mut bool) (value any) {
7386
if key == nil {
7487
return nil
7588
}
76-
v, ok := tr.base.GetHint(key, hint)
89+
var v any
90+
var ok bool
91+
if mut {
92+
v, ok = tr.base.GetHintMut(key, hint)
93+
} else {
94+
v, ok = tr.base.GetHint(key, hint)
95+
}
7796
if !ok {
7897
return nil
7998
}
@@ -97,7 +116,7 @@ func (tr *BTree) DeleteHint(key any, hint *PathHint) (prev any) {
97116
if key == nil {
98117
return nil
99118
}
100-
v, ok := tr.base.DeleteHint(key, nil)
119+
v, ok := tr.base.DeleteHint(key, hint)
101120
if !ok {
102121
return nil
103122
}
@@ -115,6 +134,34 @@ func (tr *BTree) Ascend(pivot any, iter func(item any) bool) {
115134
}
116135
}
117136

137+
func (tr *BTree) AscendMut(pivot any, iter func(item any) bool) {
138+
if pivot == nil {
139+
tr.base.ScanMut(iter)
140+
} else {
141+
tr.base.AscendMut(pivot, iter)
142+
}
143+
}
144+
145+
func (tr *BTree) AscendHint(pivot any, iter func(item any) bool,
146+
hint *PathHint,
147+
) {
148+
if pivot == nil {
149+
tr.base.Scan(iter)
150+
} else {
151+
tr.base.AscendHint(pivot, iter, hint)
152+
}
153+
}
154+
155+
func (tr *BTree) AscendHintMut(pivot any, iter func(item any) bool,
156+
hint *PathHint,
157+
) {
158+
if pivot == nil {
159+
tr.base.ScanMut(iter)
160+
} else {
161+
tr.base.AscendHintMut(pivot, iter, hint)
162+
}
163+
}
164+
118165
// Descend the tree within the range [pivot, first]
119166
// Pass nil for pivot to scan all item in descending order
120167
// Return false to stop iterating
@@ -126,6 +173,34 @@ func (tr *BTree) Descend(pivot any, iter func(item any) bool) {
126173
}
127174
}
128175

176+
func (tr *BTree) DescendMut(pivot any, iter func(item any) bool) {
177+
if pivot == nil {
178+
tr.base.ReverseMut(iter)
179+
} else {
180+
tr.base.DescendMut(pivot, iter)
181+
}
182+
}
183+
184+
func (tr *BTree) DescendHint(pivot any, iter func(item any) bool,
185+
hint *PathHint,
186+
) {
187+
if pivot == nil {
188+
tr.base.Reverse(iter)
189+
} else {
190+
tr.base.DescendHint(pivot, iter, hint)
191+
}
192+
}
193+
194+
func (tr *BTree) DescendHintMut(pivot any, iter func(item any) bool,
195+
hint *PathHint,
196+
) {
197+
if pivot == nil {
198+
tr.base.ReverseMut(iter)
199+
} else {
200+
tr.base.DescendHintMut(pivot, iter, hint)
201+
}
202+
}
203+
129204
// Load is for bulk loading pre-sorted items
130205
// If the load replaces and existing item then the value for the replaced item
131206
// is returned.
@@ -150,6 +225,14 @@ func (tr *BTree) Min() any {
150225
return v
151226
}
152227

228+
func (tr *BTree) MinMut() any {
229+
v, ok := tr.base.MinMut()
230+
if !ok {
231+
return nil
232+
}
233+
return v
234+
}
235+
153236
// Max returns the maximum item in tree.
154237
// Returns nil if the tree has no items.
155238
func (tr *BTree) Max() any {
@@ -160,6 +243,14 @@ func (tr *BTree) Max() any {
160243
return v
161244
}
162245

246+
func (tr *BTree) MaxMut() any {
247+
v, ok := tr.base.Max()
248+
if !ok {
249+
return nil
250+
}
251+
return v
252+
}
253+
163254
// PopMin removes the minimum item in tree and returns it.
164255
// Returns nil if the tree has no items.
165256
func (tr *BTree) PopMin() any {
@@ -190,6 +281,14 @@ func (tr *BTree) GetAt(index int) any {
190281
return v
191282
}
192283

284+
func (tr *BTree) GetAtMut(index int) any {
285+
v, ok := tr.base.GetAtMut(index)
286+
if !ok {
287+
return nil
288+
}
289+
return v
290+
}
291+
193292
// DeleteAt deletes the item at index.
194293
// Return nil if the tree is empty or the index is out of bounds.
195294
func (tr *BTree) DeleteAt(index int) any {
@@ -215,19 +314,31 @@ func (tr *BTree) Walk(iter func(items []any)) {
215314
})
216315
}
217316

317+
func (tr *BTree) WalkMut(iter func(items []any)) {
318+
tr.base.WalkMut(func(items []any) bool {
319+
iter(items)
320+
return true
321+
})
322+
}
323+
218324
// Copy the tree. This is a copy-on-write operation and is very fast because
219325
// it only performs a shadowed copy.
220326
func (tr *BTree) Copy() *BTree {
221327
return &BTree{base: tr.base.Copy()}
222328
}
223329

330+
func (tr *BTree) IsoCopy() *BTree {
331+
return &BTree{base: tr.base.IsoCopy()}
332+
}
333+
224334
// Clear will delete all items.
225335
func (tr *BTree) Clear() {
226336
tr.base.Clear()
227337
}
228338

339+
// Iter is an iterator for
229340
type Iter struct {
230-
base GenericIter[any]
341+
base IterG[any]
231342
}
232343

233344
// Iter returns a read-only iterator.
@@ -236,12 +347,20 @@ func (tr *BTree) Iter() Iter {
236347
return Iter{tr.base.Iter()}
237348
}
238349

350+
func (tr *BTree) IterMut() Iter {
351+
return Iter{tr.base.IterMut()}
352+
}
353+
239354
// Seek to item greater-or-equal-to key.
240355
// Returns false if there was no item found.
241356
func (iter *Iter) Seek(key any) bool {
242357
return iter.base.Seek(key)
243358
}
244359

360+
func (iter *Iter) SeekHint(key any, hint *PathHint) bool {
361+
return iter.base.SeekHint(key, hint)
362+
}
363+
245364
// First moves iterator to first item in tree.
246365
// Returns false if the tree is empty.
247366
func (iter *Iter) First() bool {

0 commit comments

Comments
 (0)