Browse Source

upgrade buntdb and dependencies

tags/v2.12.0-rc1
Shivaram Lingamneni 1 year ago
parent
commit
3f5de80afd

+ 3
- 3
go.mod View File

@@ -17,7 +17,7 @@ require (
17 17
 	github.com/onsi/ginkgo v1.12.0 // indirect
18 18
 	github.com/onsi/gomega v1.9.0 // indirect
19 19
 	github.com/stretchr/testify v1.4.0 // indirect
20
-	github.com/tidwall/buntdb v1.2.9
20
+	github.com/tidwall/buntdb v1.2.10
21 21
 	github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208
22 22
 	github.com/xdg-go/scram v1.0.2
23 23
 	golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
@@ -28,8 +28,8 @@ require (
28 28
 require github.com/gofrs/flock v0.8.1
29 29
 
30 30
 require (
31
-	github.com/tidwall/btree v1.1.0 // indirect
32
-	github.com/tidwall/gjson v1.12.1 // indirect
31
+	github.com/tidwall/btree v1.4.2 // indirect
32
+	github.com/tidwall/gjson v1.14.3 // indirect
33 33
 	github.com/tidwall/grect v0.1.4 // indirect
34 34
 	github.com/tidwall/match v1.1.1 // indirect
35 35
 	github.com/tidwall/pretty v1.2.0 // indirect

+ 6
- 0
go.sum View File

@@ -49,14 +49,20 @@ github.com/tidwall/btree v0.6.1 h1:75VVgBeviiDO+3g4U+7+BaNBNhNINxB0ULPT3fs9pMY=
49 49
 github.com/tidwall/btree v0.6.1/go.mod h1:TzIRzen6yHbibdSfK6t8QimqbUnoxUSrZfeW7Uob0q4=
50 50
 github.com/tidwall/btree v1.1.0 h1:5P+9WU8ui5uhmcg3SoPyTwoI0mVyZ1nps7YQzTZFkYM=
51 51
 github.com/tidwall/btree v1.1.0/go.mod h1:TzIRzen6yHbibdSfK6t8QimqbUnoxUSrZfeW7Uob0q4=
52
+github.com/tidwall/btree v1.4.2 h1:PpkaieETJMUxYNADsjgtNRcERX7mGc/GP2zp/r5FM3g=
53
+github.com/tidwall/btree v1.4.2/go.mod h1:LGm8L/DZjPLmeWGjv5kFrY8dL4uVhMmzmmLYmsObdKE=
52 54
 github.com/tidwall/buntdb v1.2.7 h1:SIyObKAymzLyGhDeIhVk2Yc1/EwfCC75Uyu77CHlVoA=
53 55
 github.com/tidwall/buntdb v1.2.7/go.mod h1:b6KvZM27x/8JLI5hgRhRu60pa3q0Tz9c50TyD46OHUM=
54 56
 github.com/tidwall/buntdb v1.2.9 h1:XVz684P7X6HCTrdr385yDZWB1zt/n20ZNG3M1iGyFm4=
55 57
 github.com/tidwall/buntdb v1.2.9/go.mod h1:IwyGSvvDg6hnKSIhtdZ0AqhCZGH8ukdtCAzaP8fI1X4=
58
+github.com/tidwall/buntdb v1.2.10 h1:U/ebfkmYPBnyiNZIirUiWFcxA/mgzjbKlyPynFsPtyM=
59
+github.com/tidwall/buntdb v1.2.10/go.mod h1:lZZrZUWzlyDJKlLQ6DKAy53LnG7m5kHyrEHvvcDmBpU=
56 60
 github.com/tidwall/gjson v1.10.2 h1:APbLGOM0rrEkd8WBw9C24nllro4ajFuJu0Sc9hRz8Bo=
57 61
 github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
58 62
 github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo=
59 63
 github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
64
+github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
65
+github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
60 66
 github.com/tidwall/grect v0.1.3 h1:z9YwQAMUxVSBde3b7Sl8Da37rffgNfZ6Fq6h9t6KdXE=
61 67
 github.com/tidwall/grect v0.1.3/go.mod h1:8GMjwh3gPZVpLBI/jDz9uslCe0dpxRpWDdtN0lWAS/E=
62 68
 github.com/tidwall/grect v0.1.4 h1:dA3oIgNgWdSspFzn1kS4S/RDpZFLrIxAZOdJKjYapOg=

+ 335
- 93
vendor/github.com/tidwall/btree/README.md View File

@@ -2,26 +2,351 @@
2 2
 
3 3
 [![GoDoc](https://godoc.org/github.com/tidwall/btree?status.svg)](https://godoc.org/github.com/tidwall/btree)
4 4
 
5
-An [efficient](#performance) [B-tree](https://en.wikipedia.org/wiki/B-tree) implementation in Go. 
6
-
7
-*Check out the [generics branch](https://github.com/tidwall/btree/tree/generics) if you want to try out btree with generic support for Go 1.18+*
5
+An efficient [B-tree](https://en.wikipedia.org/wiki/B-tree) implementation in Go.
8 6
 
9 7
 ## Features
10 8
 
11
-- `Copy()` method with copy-on-write support.
9
+- Support for [Generics](#generics) (Go 1.18+).
10
+- `Map` and `Set` types for ordered key-value maps and sets,
12 11
 - Fast bulk loading for pre-ordered data using the `Load()` method.
13
-- All operations are thread-safe.
12
+- `Copy()` method with copy-on-write support.
13
+- Thread-safe operations.
14 14
 - [Path hinting](PATH_HINT.md) optimization for operations with nearby keys.
15 15
 
16
-## Installing
16
+## Using
17 17
 
18
-To start using btree, install Go and run `go get`:
18
+To start using this package, install Go and run:
19 19
 
20 20
 ```sh
21
-$ go get -u github.com/tidwall/btree
21
+$ go get github.com/tidwall/btree
22
+```
23
+
24
+## B-tree types
25
+
26
+This package includes the following types of B-trees:
27
+
28
+- [`btree.Map`](#btreemap):
29
+A fast B-tree for storing ordered key value pairs.
30
+Go 1.18+ 
31
+- [`btree.Set`](#btreeset):
32
+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+
37
+- [`btree.BTree`](#btreebtree):
38
+Like `BTreeG` but uses the `interface{}` type for data. Backwards compatible.
39
+Go 1.16+
40
+
41
+### btree.Map
42
+
43
+```go
44
+// Basic
45
+Set(key, value)    // insert or replace an item
46
+Get(key, value)    // get an existing item
47
+Delete(key)        // delete an item
48
+Len()              // return the number of items in the map
49
+
50
+// Iteration
51
+Scan(iter)         // scan items in ascending order
52
+Reverse(iter)      // scan items in descending order
53
+Ascend(key, iter)  // scan items in ascending order that are >= to key
54
+Descend(key, iter) // scan items in descending order that are <= to key.
55
+Iter()             // returns a read-only iterator for for-loops.
56
+
57
+// Array-like operations
58
+GetAt(index)       // returns the item at index
59
+DeleteAt(index)    // deletes the item at index
60
+
61
+// Bulk-loading
62
+Load(key, value)   // load presorted items into tree
63
+```
64
+
65
+#### Example
66
+
67
+```go
68
+package main
69
+
70
+import (
71
+	"fmt"
72
+	"github.com/tidwall/btree"
73
+)
74
+
75
+func main() {
76
+	// create a map
77
+	var users btree.Map[string, string]
78
+
79
+	// add some users
80
+	users.Set("user:4", "Andrea")
81
+	users.Set("user:6", "Andy")
82
+	users.Set("user:2", "Andy")
83
+	users.Set("user:1", "Jane")
84
+	users.Set("user:5", "Janet")
85
+	users.Set("user:3", "Steve")
86
+
87
+	// Iterate over the maps and print each user
88
+	users.Scan(func(key, value string) bool {
89
+		fmt.Printf("%s %s\n", key, value)
90
+		return true
91
+	})
92
+	fmt.Printf("\n")
93
+
94
+	// Delete a couple
95
+	users.Delete("user:5")
96
+	users.Delete("user:1")
97
+
98
+	// print the map again
99
+	users.Scan(func(key, value string) bool {
100
+		fmt.Printf("%s %s\n", key, value)
101
+		return true
102
+	})
103
+	fmt.Printf("\n")
104
+
105
+	// Output:
106
+	// user:1 Jane
107
+	// user:2 Andy
108
+	// user:3 Steve
109
+	// user:4 Andrea
110
+	// user:5 Janet
111
+	// user:6 Andy
112
+	//
113
+	// user:2 Andy
114
+	// user:3 Steve
115
+	// user:4 Andrea
116
+	// user:6 Andy
117
+}
118
+```
119
+
120
+### btree.Set
121
+
122
+```go
123
+// Basic
124
+Insert(key)        // insert an item
125
+Contains(key)      // test if item exists
126
+Delete(key)        // delete an item
127
+Len()              // return the number of items in the set
128
+
129
+// Iteration
130
+Scan(iter)         // scan items in ascending order
131
+Reverse(iter)      // scan items in descending order
132
+Ascend(key, iter)  // scan items in ascending order that are >= to key
133
+Descend(key, iter) // scan items in descending order that are <= to key.
134
+Iter()             // returns a read-only iterator for for-loops.
135
+
136
+// Array-like operations
137
+GetAt(index)       // returns the item at index
138
+DeleteAt(index)    // deletes the item at index
139
+
140
+// Bulk-loading
141
+Load(key)          // load presorted item into tree
22 142
 ```
23 143
 
24
-## Usage
144
+#### Example
145
+
146
+```go
147
+package main
148
+
149
+import (
150
+	"fmt"
151
+	"github.com/tidwall/btree"
152
+)
153
+
154
+func main() {
155
+	// create a set
156
+	var names btree.Set[string]
157
+
158
+	// add some names
159
+	names.Insert("Jane")
160
+	names.Insert("Andrea")
161
+	names.Insert("Steve")
162
+	names.Insert("Andy")
163
+	names.Insert("Janet")
164
+	names.Insert("Andy")
165
+
166
+	// Iterate over the maps and print each user
167
+	names.Scan(func(key string) bool {
168
+		fmt.Printf("%s\n", key)
169
+		return true
170
+	})
171
+	fmt.Printf("\n")
172
+
173
+	// Delete a couple
174
+	names.Delete("Steve")
175
+	names.Delete("Andy")
176
+
177
+	// print the map again
178
+	names.Scan(func(key string) bool {
179
+		fmt.Printf("%s\n", key)
180
+		return true
181
+	})
182
+	fmt.Printf("\n")
183
+
184
+	// Output:
185
+	// Andrea
186
+	// Andy
187
+	// Jane
188
+	// Janet
189
+	// Steve
190
+	//
191
+	// Andrea
192
+	// Jane
193
+	// Janet
194
+}
195
+```
196
+
197
+### btree.BTreeG
198
+
199
+```go
200
+// Basic
201
+Set(item)               // insert or replace an item
202
+Get(item)               // get an existing item
203
+Delete(item)            // delete an item
204
+Len()                   // return the number of items in the btree
205
+
206
+// Iteration
207
+Scan(iter)              // scan items in ascending order
208
+Reverse(iter)           // scan items in descending order
209
+Ascend(key, iter)       // scan items in ascending order that are >= to key
210
+Descend(key, iter)      // scan items in descending order that are <= to key.
211
+Iter()                  // returns a read-only iterator for for-loops.
212
+
213
+// Array-like operations
214
+GetAt(index)            // returns the item at index
215
+DeleteAt(index)         // deletes the item at index
216
+
217
+// Bulk-loading
218
+Load(item)              // load presorted items into tree
219
+
220
+// Path hinting
221
+SetHint(item, *hint)    // insert or replace an existing item
222
+GetHint(item, *hint)    // get an existing item
223
+DeleteHint(item, *hint) // delete an item
224
+
225
+// Copy-on-write
226
+Copy()                  // copy the btree
227
+```
228
+
229
+#### Example
230
+
231
+```go
232
+package main
233
+
234
+import (
235
+	"fmt"
236
+
237
+	"github.com/tidwall/btree"
238
+)
239
+
240
+type Item struct {
241
+	Key, Val string
242
+}
243
+
244
+// byKeys is a comparison function that compares item keys and returns true
245
+// when a is less than b.
246
+func byKeys(a, b Item) bool {
247
+	return a.Key < b.Key
248
+}
249
+
250
+// byVals is a comparison function that compares item values and returns true
251
+// when a is less than b.
252
+func byVals(a, b Item) bool {
253
+	if a.Val < b.Val {
254
+		return true
255
+	}
256
+	if a.Val > b.Val {
257
+		return false
258
+	}
259
+	// Both vals are equal so we should fall though
260
+	// and let the key comparison take over.
261
+	return byKeys(a, b)
262
+}
263
+
264
+func main() {
265
+	// Create a tree for keys and a tree for values.
266
+	// The "keys" tree will be sorted on the Keys field.
267
+	// The "values" tree will be sorted on the Values field.
268
+	keys := btree.NewBTreeG[Item](byKeys)
269
+	vals := btree.NewBTreeG[Item](byVals)
270
+
271
+	// Create some items.
272
+	users := []Item{
273
+		Item{Key: "user:1", Val: "Jane"},
274
+		Item{Key: "user:2", Val: "Andy"},
275
+		Item{Key: "user:3", Val: "Steve"},
276
+		Item{Key: "user:4", Val: "Andrea"},
277
+		Item{Key: "user:5", Val: "Janet"},
278
+		Item{Key: "user:6", Val: "Andy"},
279
+	}
280
+
281
+	// Insert each user into both trees
282
+	for _, user := range users {
283
+		keys.Set(user)
284
+		vals.Set(user)
285
+	}
286
+
287
+	// Iterate over each user in the key tree
288
+	keys.Scan(func(item Item) bool {
289
+		fmt.Printf("%s %s\n", item.Key, item.Val)
290
+		return true
291
+	})
292
+	fmt.Printf("\n")
293
+
294
+	// Iterate over each user in the val tree
295
+	vals.Scan(func(item Item) bool {
296
+		fmt.Printf("%s %s\n", item.Key, item.Val)
297
+		return true
298
+	})
299
+
300
+	// Output:
301
+	// user:1 Jane
302
+	// user:2 Andy
303
+	// user:3 Steve
304
+	// user:4 Andrea
305
+	// user:5 Janet
306
+	// user:6 Andy
307
+	//
308
+	// user:4 Andrea
309
+	// user:2 Andy
310
+	// user:6 Andy
311
+	// user:1 Jane
312
+	// user:5 Janet
313
+	// user:3 Steve
314
+}
315
+```
316
+
317
+### btree.BTree
318
+
319
+```go
320
+// Basic
321
+Set(item)               // insert or replace an item
322
+Get(item)               // get an existing item
323
+Delete(item)            // delete an item
324
+Len()                   // return the number of items in the btree
325
+
326
+// Iteration
327
+Scan(iter)              // scan items in ascending order
328
+Reverse(iter)           // scan items in descending order
329
+Ascend(key, iter)       // scan items in ascending order that are >= to key
330
+Descend(key, iter)      // scan items in descending order that are <= to key.
331
+Iter()                  // returns a read-only iterator for for-loops.
332
+
333
+// Array-like operations
334
+GetAt(index)            // returns the item at index
335
+DeleteAt(index)         // deletes the item at index
336
+
337
+// Bulk-loading
338
+Load(item)              // load presorted items into tree
339
+
340
+// Path hinting
341
+SetHint(item, *hint)    // insert or replace an existing item
342
+GetHint(item, *hint)    // get an existing item
343
+DeleteHint(item, *hint) // delete an item
344
+
345
+// Copy-on-write
346
+Copy()                  // copy the btree
347
+```
348
+
349
+#### Example
25 350
 
26 351
 ```go
27 352
 package main
@@ -113,92 +438,9 @@ func main() {
113 438
 }
114 439
 ```
115 440
 
116
-## Operations
117
-
118
-### Basic
119
-
120
-```
121
-Get(item)               # get an existing item
122
-Set(item)               # insert or replace an existing item
123
-Delete(item)            # delete an item
124
-Len()                   # return the number of items in the btree
125
-```
126
-
127
-### Iteration
128
-
129
-```
130
-Ascend(pivot, iter)     # scan items in ascending order starting at pivot.
131
-Descend(pivot, iter)    # scan items in descending order starting at pivot.
132
-Iter()                  # returns a read-only iterator for for-loops.
133
-```
134
-
135
-### Queues
136
-
137
-```
138
-Min()                   # return the first item in the btree
139
-Max()                   # return the last item in the btree
140
-PopMin()                # remove and return the first item in the btree
141
-PopMax()                # remove and return the last item in the btree
142
-```
143
-### Bulk loading
144
-
145
-```
146
-Load(item)              # load presorted items into tree
147
-```
148
-
149
-### Path hints
150
-
151
-```
152
-SetHint(item, *hint)    # insert or replace an existing item
153
-GetHint(item, *hint)    # get an existing item
154
-DeleteHint(item, *hint) # delete an item
155
-```
156
-
157
-### Array-like operations
158
-
159
-```
160
-GetAt(index)     # returns the value at index
161
-DeleteAt(index)  # deletes the item at index
162
-```
163
-
164 441
 ## Performance
165 442
 
166
-This implementation was designed with performance in mind. 
167
-
168
-The following benchmarks were run on my 2019 Macbook Pro (2.4 GHz 8-Core Intel Core i9) using Go 1.17.3. The items are simple 8-byte ints. 
169
-
170
-- `google`: The [google/btree](https://github.com/google/btree) package
171
-- `tidwall`: The [tidwall/btree](https://github.com/tidwall/btree) package
172
-- `go-arr`: Just a simple Go array
173
-
174
-```
175
-** sequential set **
176
-google:  set-seq        1,000,000 ops in 178ms, 5,618,049/sec, 177 ns/op, 39.0 MB, 40 bytes/op
177
-tidwall: set-seq        1,000,000 ops in 156ms, 6,389,837/sec, 156 ns/op, 23.5 MB, 24 bytes/op
178
-tidwall: set-seq-hint   1,000,000 ops in 78ms, 12,895,355/sec, 77 ns/op, 23.5 MB, 24 bytes/op
179
-tidwall: load-seq       1,000,000 ops in 53ms, 18,937,400/sec, 52 ns/op, 23.5 MB, 24 bytes/op
180
-go-arr:  append         1,000,000 ops in 78ms, 12,843,432/sec, 77 ns/op
181
-
182
-** random set **
183
-google:  set-rand       1,000,000 ops in 555ms, 1,803,133/sec, 554 ns/op, 29.7 MB, 31 bytes/op
184
-tidwall: set-rand       1,000,000 ops in 545ms, 1,835,818/sec, 544 ns/op, 29.6 MB, 31 bytes/op
185
-tidwall: set-rand-hint  1,000,000 ops in 670ms, 1,493,473/sec, 669 ns/op, 29.6 MB, 31 bytes/op
186
-tidwall: set-again      1,000,000 ops in 681ms, 1,469,038/sec, 680 ns/op
187
-tidwall: set-after-copy 1,000,000 ops in 670ms, 1,493,230/sec, 669 ns/op
188
-tidwall: load-rand      1,000,000 ops in 569ms, 1,756,187/sec, 569 ns/op, 29.6 MB, 31 bytes/op
189
-
190
-** sequential get **
191
-google:  get-seq        1,000,000 ops in 165ms, 6,048,307/sec, 165 ns/op
192
-tidwall: get-seq        1,000,000 ops in 144ms, 6,940,120/sec, 144 ns/op
193
-tidwall: get-seq-hint   1,000,000 ops in 78ms, 12,815,243/sec, 78 ns/op
194
-
195
-** random get **
196
-google:  get-rand       1,000,000 ops in 701ms, 1,427,507/sec, 700 ns/op
197
-tidwall: get-rand       1,000,000 ops in 679ms, 1,473,531/sec, 678 ns/op
198
-tidwall: get-rand-hint  1,000,000 ops in 824ms, 1,213,805/sec, 823 ns/op
199
-```
200
-
201
-*You can find the benchmark utility at [tidwall/btree-benchmark](https://github.com/tidwall/btree-benchmark)*
443
+See [tidwall/btree-benchmark](https://github.com/tidwall/btree-benchmark) for benchmark numbers.
202 444
 
203 445
 ## Contact
204 446
 

+ 41
- 41
vendor/github.com/tidwall/btree/btree.go View File

@@ -3,25 +3,17 @@
3 3
 // license that can be found in the LICENSE file.
4 4
 package btree
5 5
 
6
-import btree "github.com/tidwall/btree/internal"
7
-
8 6
 type BTree struct {
9
-	base *btree.BTree
7
+	base *BTreeG[any]
10 8
 }
11 9
 
12
-// PathHint is a utility type used with the *Hint() functions. Hints provide
13
-// faster operations for clustered keys.
14
-type PathHint = btree.PathHint
15
-
16 10
 // New returns a new BTree
17
-func New(less func(a, b interface{}) bool) *BTree {
11
+func New(less func(a, b any) bool) *BTree {
18 12
 	if less == nil {
19 13
 		panic("nil less")
20 14
 	}
21 15
 	return &BTree{
22
-		base: btree.NewOptions(btree.Options{
23
-			Context: less,
24
-		}),
16
+		base: NewBTreeG(less),
25 17
 	}
26 18
 }
27 19
 
@@ -30,31 +22,33 @@ func New(less func(a, b interface{}) bool) *BTree {
30 22
 //
31 23
 // This is useful for when you do not need the BTree to manage the locking,
32 24
 // but would rather do it yourself.
33
-func NewNonConcurrent(less func(a, b interface{}) bool) *BTree {
25
+func NewNonConcurrent(less func(a, b any) bool) *BTree {
34 26
 	if less == nil {
35 27
 		panic("nil less")
36 28
 	}
37 29
 	return &BTree{
38
-		base: btree.NewOptions(btree.Options{
39
-			Context: less,
40
-			NoLocks: true,
41
-		}),
30
+		base: NewBTreeGOptions(less,
31
+			Options{
32
+				NoLocks: true,
33
+			}),
42 34
 	}
43 35
 }
44 36
 
45 37
 // Less is a convenience function that performs a comparison of two items
46 38
 // using the same "less" function provided to New.
47
-func (tr *BTree) Less(a, b interface{}) bool {
39
+func (tr *BTree) Less(a, b any) bool {
48 40
 	return tr.base.Less(a, b)
49 41
 }
50 42
 
51 43
 // Set or replace a value for a key
52
-func (tr *BTree) Set(item interface{}) interface{} {
44
+// Returns the value for the replaced item or nil if the key was not found.
45
+func (tr *BTree) Set(item any) (prev any) {
53 46
 	return tr.SetHint(item, nil)
54 47
 }
55 48
 
56 49
 // SetHint sets or replace a value for a key using a path hint
57
-func (tr *BTree) SetHint(item interface{}, hint *PathHint) (prev interface{}) {
50
+// Returns the value for the replaced item or nil if the key was not found.
51
+func (tr *BTree) SetHint(item any, hint *PathHint) (prev any) {
58 52
 	if item == nil {
59 53
 		panic("nil item")
60 54
 	}
@@ -65,13 +59,15 @@ func (tr *BTree) SetHint(item interface{}, hint *PathHint) (prev interface{}) {
65 59
 	return v
66 60
 }
67 61
 
68
-// Get a value for key
69
-func (tr *BTree) Get(key interface{}) interface{} {
62
+// Get a value for key.
63
+// Returns nil if the key was not found.
64
+func (tr *BTree) Get(key any) any {
70 65
 	return tr.GetHint(key, nil)
71 66
 }
72 67
 
73
-// GetHint gets a value for key using a path hint
74
-func (tr *BTree) GetHint(key interface{}, hint *PathHint) interface{} {
68
+// GetHint gets a value for key using a path hint.
69
+// Returns nil if the item was not found.
70
+func (tr *BTree) GetHint(key any, hint *PathHint) (value any) {
75 71
 	if key == nil {
76 72
 		return nil
77 73
 	}
@@ -87,13 +83,15 @@ func (tr *BTree) Len() int {
87 83
 	return tr.base.Len()
88 84
 }
89 85
 
90
-// Delete a value for a key
91
-func (tr *BTree) Delete(key interface{}) interface{} {
86
+// Delete an item for a key.
87
+// Returns the deleted value or nil if the key was not found.
88
+func (tr *BTree) Delete(key any) (prev any) {
92 89
 	return tr.DeleteHint(key, nil)
93 90
 }
94 91
 
95 92
 // DeleteHint deletes a value for a key using a path hint
96
-func (tr *BTree) DeleteHint(key interface{}, hint *PathHint) interface{} {
93
+// Returns the deleted value or nil if the key was not found.
94
+func (tr *BTree) DeleteHint(key any, hint *PathHint) (prev any) {
97 95
 	if key == nil {
98 96
 		return nil
99 97
 	}
@@ -107,7 +105,7 @@ func (tr *BTree) DeleteHint(key interface{}, hint *PathHint) interface{} {
107 105
 // Ascend the tree within the range [pivot, last]
108 106
 // Pass nil for pivot to scan all item in ascending order
109 107
 // Return false to stop iterating
110
-func (tr *BTree) Ascend(pivot interface{}, iter func(item interface{}) bool) {
108
+func (tr *BTree) Ascend(pivot any, iter func(item any) bool) {
111 109
 	if pivot == nil {
112 110
 		tr.base.Scan(iter)
113 111
 	} else {
@@ -118,7 +116,7 @@ func (tr *BTree) Ascend(pivot interface{}, iter func(item interface{}) bool) {
118 116
 // Descend the tree within the range [pivot, first]
119 117
 // Pass nil for pivot to scan all item in descending order
120 118
 // Return false to stop iterating
121
-func (tr *BTree) Descend(pivot interface{}, iter func(item interface{}) bool) {
119
+func (tr *BTree) Descend(pivot any, iter func(item any) bool) {
122 120
 	if pivot == nil {
123 121
 		tr.base.Reverse(iter)
124 122
 	} else {
@@ -127,7 +125,9 @@ func (tr *BTree) Descend(pivot interface{}, iter func(item interface{}) bool) {
127 125
 }
128 126
 
129 127
 // Load is for bulk loading pre-sorted items
130
-func (tr *BTree) Load(item interface{}) interface{} {
128
+// If the load replaces and existing item then the value for the replaced item
129
+// is returned.
130
+func (tr *BTree) Load(item any) (prev any) {
131 131
 	if item == nil {
132 132
 		panic("nil item")
133 133
 	}
@@ -140,7 +140,7 @@ func (tr *BTree) Load(item interface{}) interface{} {
140 140
 
141 141
 // Min returns the minimum item in tree.
142 142
 // Returns nil if the tree has no items.
143
-func (tr *BTree) Min() interface{} {
143
+func (tr *BTree) Min() any {
144 144
 	v, ok := tr.base.Min()
145 145
 	if !ok {
146 146
 		return nil
@@ -150,7 +150,7 @@ func (tr *BTree) Min() interface{} {
150 150
 
151 151
 // Max returns the maximum item in tree.
152 152
 // Returns nil if the tree has no items.
153
-func (tr *BTree) Max() interface{} {
153
+func (tr *BTree) Max() any {
154 154
 	v, ok := tr.base.Max()
155 155
 	if !ok {
156 156
 		return nil
@@ -160,7 +160,7 @@ func (tr *BTree) Max() interface{} {
160 160
 
161 161
 // PopMin removes the minimum item in tree and returns it.
162 162
 // Returns nil if the tree has no items.
163
-func (tr *BTree) PopMin() interface{} {
163
+func (tr *BTree) PopMin() any {
164 164
 	v, ok := tr.base.PopMin()
165 165
 	if !ok {
166 166
 		return nil
@@ -168,9 +168,9 @@ func (tr *BTree) PopMin() interface{} {
168 168
 	return v
169 169
 }
170 170
 
171
-// PopMax removes the minimum item in tree and returns it.
171
+// PopMax removes the maximum item in tree and returns it.
172 172
 // Returns nil if the tree has no items.
173
-func (tr *BTree) PopMax() interface{} {
173
+func (tr *BTree) PopMax() any {
174 174
 	v, ok := tr.base.PopMax()
175 175
 	if !ok {
176 176
 		return nil
@@ -180,7 +180,7 @@ func (tr *BTree) PopMax() interface{} {
180 180
 
181 181
 // GetAt returns the value at index.
182 182
 // Return nil if the tree is empty or the index is out of bounds.
183
-func (tr *BTree) GetAt(index int) interface{} {
183
+func (tr *BTree) GetAt(index int) any {
184 184
 	v, ok := tr.base.GetAt(index)
185 185
 	if !ok {
186 186
 		return nil
@@ -190,7 +190,7 @@ func (tr *BTree) GetAt(index int) interface{} {
190 190
 
191 191
 // DeleteAt deletes the item at index.
192 192
 // Return nil if the tree is empty or the index is out of bounds.
193
-func (tr *BTree) DeleteAt(index int) interface{} {
193
+func (tr *BTree) DeleteAt(index int) any {
194 194
 	v, ok := tr.base.DeleteAt(index)
195 195
 	if !ok {
196 196
 		return nil
@@ -206,8 +206,8 @@ func (tr *BTree) Height() int {
206 206
 
207 207
 // Walk iterates over all items in tree, in order.
208 208
 // The items param will contain one or more items.
209
-func (tr *BTree) Walk(iter func(items []interface{})) {
210
-	tr.base.Walk(func(items []interface{}) bool {
209
+func (tr *BTree) Walk(iter func(items []any)) {
210
+	tr.base.Walk(func(items []any) bool {
211 211
 		iter(items)
212 212
 		return true
213 213
 	})
@@ -220,7 +220,7 @@ func (tr *BTree) Copy() *BTree {
220 220
 }
221 221
 
222 222
 type Iter struct {
223
-	base btree.Iter
223
+	base GenericIter[any]
224 224
 }
225 225
 
226 226
 // Iter returns a read-only iterator.
@@ -231,7 +231,7 @@ func (tr *BTree) Iter() Iter {
231 231
 
232 232
 // Seek to item greater-or-equal-to key.
233 233
 // Returns false if there was no item found.
234
-func (iter *Iter) Seek(key interface{}) bool {
234
+func (iter *Iter) Seek(key any) bool {
235 235
 	return iter.base.Seek(key)
236 236
 }
237 237
 
@@ -268,6 +268,6 @@ func (iter *Iter) Prev() bool {
268 268
 }
269 269
 
270 270
 // Item returns the current iterator item.
271
-func (iter *Iter) Item() interface{} {
271
+func (iter *Iter) Item() any {
272 272
 	return iter.base.Item()
273 273
 }

vendor/github.com/tidwall/btree/internal/btree.go → vendor/github.com/tidwall/btree/generic.go View File

@@ -1,178 +1,109 @@
1 1
 // Copyright 2020 Joshua J Baker. All rights reserved.
2
-// Use of this source code is governed by an MIT-style license that can be
3
-// found in the LICENSE file at https://github.com/tidwall/btree/LICENSE
4
-
5
-///////////////////////////////////////////////////////////////////////////////
6
-// BEGIN PARAMS
7
-///////////////////////////////////////////////////////////////////////////////
8
-
2
+// Use of this source code is governed by an MIT-style
3
+// license that can be found in the LICENSE file.
9 4
 package btree
10 5
 
11
-import "sync"
12
-
13
-// degree is the B-Tree degree, which is equal to maximum number of children
14
-// pre node times two.
15
-// The default is 128, which means each node can have 255 items and 256 child
16
-// nodes.
17
-const degree = 128
18
-
19
-// kind is the item type.
20
-// It's important to use the equal symbol, which tells Go to create an alias of
21
-// the type, rather than creating an entirely new type.
22
-type kind = interface{}
23
-
24
-// contextKind is the kind of context that can be passed to NewOptions and the
25
-// less function
26
-type contextKind = interface{}
27
-
28
-// less returns true if A is less than B.
29
-// The value of context will be whatever was passed to NewOptions through the
30
-// Options.Context field, otherwise nil if the field was not set.
31
-func less(a, b kind, context contextKind) bool {
32
-	return context.(func(a, b contextKind) bool)(a, b)
33
-}
34
-
35
-// BTree aliases
36
-// These are aliases to the local bTree types and functions, which are exported
37
-// to allow for public use at a package level.
38
-// Rename them if desired, or comment them out to make the library private.
39
-type BTree = bTree
40
-type Options = bOptions
41
-type PathHint = bPathHint
42
-type Iter = bIter
43
-
44
-func New(less func(a, b kind) bool) *bTree { return bNew() }
45
-func NewOptions(opts bOptions) *bTree      { return bNewOptions(opts) }
46
-
47
-// The functions below, which begin with "test*", are required by the
48
-// btree_test.go file. If you choose not use include the btree_test.go file in
49
-// your project then these functions may be omitted.
50
-
51
-// testCustomSeed can be used to generate a custom random seed for testing.
52
-// Returning false will use time.Now().UnixNano()
53
-func testCustomSeed() (seed int64, ok bool) {
54
-	return 0, false
55
-}
56
-
57
-// testMakeItem must return a valid item for testing.
58
-// It's required that the returned item maintains equal order as the
59
-// provided int, such that:
60
-//    testMakeItem(0) < testMakeItem(1) < testMakeItem(2) < testMakeItem(10)
61
-func testMakeItem(x int) (item kind) {
62
-	return x
63
-}
64
-
65
-// testNewBTree must return an operational btree for testing.
66
-func testNewBTree() *bTree {
67
-	return bNewOptions(bOptions{
68
-		Context: func(a, b contextKind) bool {
69
-			if a == nil {
70
-				return b != nil
71
-			} else if b == nil {
72
-				return false
73
-			}
74
-			return a.(int) < b.(int)
75
-		},
76
-	})
77
-}
78
-
79
-///////////////////////////////////////////////////////////////////////////////
80
-// END PARAMS
81
-///////////////////////////////////////////////////////////////////////////////
6
+import (
7
+	"sync"
8
+	"sync/atomic"
9
+)
82 10
 
83
-// Do not edit code below this line.
11
+const (
12
+	degree   = 128
13
+	maxItems = degree*2 - 1 // max items per node. max children is +1
14
+	minItems = maxItems / 2
15
+)
84 16
 
85
-const maxItems = degree*2 - 1 // max items per node. max children is +1
86
-const minItems = maxItems / 2
87
-
88
-type bTree struct {
17
+type BTreeG[T any] struct {
89 18
 	mu    *sync.RWMutex
90
-	cow   *cow
91
-	root  *node
19
+	cow   uint64
20
+	root  *node[T]
92 21
 	count int
93
-	ctx   contextKind
94 22
 	locks bool
95
-	empty kind
23
+	less  func(a, b T) bool
24
+	empty T
96 25
 }
97 26
 
98
-type node struct {
99
-	cow      *cow
27
+type node[T any] struct {
28
+	cow      uint64
100 29
 	count    int
101
-	items    []kind
102
-	children *[]*node
30
+	items    []T
31
+	children *[]*node[T]
103 32
 }
104 33
 
105
-type cow struct {
106
-	_ int // cannot be an empty struct
107
-}
108
-
109
-func (tr *bTree) newNode(leaf bool) *node {
110
-	n := &node{cow: tr.cow}
111
-	if !leaf {
112
-		n.children = new([]*node)
113
-	}
114
-	return n
115
-}
116
-
117
-// leaf returns true if the node is a leaf.
118
-func (n *node) leaf() bool {
119
-	return n.children == nil
120
-}
34
+var gcow uint64
121 35
 
122 36
 // PathHint is a utility type used with the *Hint() functions. Hints provide
123 37
 // faster operations for clustered keys.
124
-type bPathHint struct {
38
+type PathHint struct {
125 39
 	used [8]bool
126 40
 	path [8]uint8
127 41
 }
128 42
 
129
-type bOptions struct {
43
+// Options for passing to New when creating a new BTree.
44
+type Options struct {
130 45
 	NoLocks bool
131
-	Context contextKind
132 46
 }
133 47
 
134 48
 // New returns a new BTree
135
-func bNew() *bTree {
136
-	return bNewOptions(bOptions{})
49
+func NewBTreeG[T any](less func(a, b T) bool) *BTreeG[T] {
50
+	return NewBTreeGOptions(less, Options{})
137 51
 }
138 52
 
139
-func bNewOptions(opts bOptions) *bTree {
140
-	tr := new(bTree)
141
-	tr.cow = new(cow)
53
+func NewBTreeGOptions[T any](less func(a, b T) bool, opts Options) *BTreeG[T] {
54
+	tr := new(BTreeG[T])
55
+	tr.cow = atomic.AddUint64(&gcow, 1)
142 56
 	tr.mu = new(sync.RWMutex)
143
-	tr.ctx = opts.Context
57
+	tr.less = less
144 58
 	tr.locks = !opts.NoLocks
145 59
 	return tr
146 60
 }
147 61
 
148 62
 // Less is a convenience function that performs a comparison of two items
149 63
 // using the same "less" function provided to New.
150
-func (tr *bTree) Less(a, b kind) bool {
151
-	return less(a, b, tr.ctx)
64
+func (tr *BTreeG[T]) Less(a, b T) bool {
65
+	return tr.less(a, b)
66
+}
67
+
68
+func (tr *BTreeG[T]) newNode(leaf bool) *node[T] {
69
+	n := &node[T]{cow: tr.cow}
70
+	if !leaf {
71
+		n.children = new([]*node[T])
72
+	}
73
+	return n
74
+}
75
+
76
+// leaf returns true if the node is a leaf.
77
+func (n *node[T]) leaf() bool {
78
+	return n.children == nil
79
+}
80
+
81
+func (tr *BTreeG[T]) bsearch(n *node[T], key T) (index int, found bool) {
82
+	low, high := 0, len(n.items)
83
+	for low < high {
84
+		h := int(uint(low+high) >> 1)
85
+		if !tr.less(key, n.items[h]) {
86
+			low = h + 1
87
+		} else {
88
+			high = h
89
+		}
90
+	}
91
+	if low > 0 && !tr.less(n.items[low-1], key) {
92
+		return low - 1, true
93
+	}
94
+	return low, false
152 95
 }
153 96
 
154
-func (tr *bTree) find(n *node, key kind,
155
-	hint *bPathHint, depth int,
97
+func (tr *BTreeG[T]) find(n *node[T], key T, hint *PathHint, depth int,
156 98
 ) (index int, found bool) {
157 99
 	if hint == nil {
158
-		// fast path for no hinting
159
-		low := 0
160
-		high := len(n.items)
161
-		for low < high {
162
-			mid := (low + high) / 2
163
-			if !tr.Less(key, n.items[mid]) {
164
-				low = mid + 1
165
-			} else {
166
-				high = mid
167
-			}
168
-		}
169
-		if low > 0 && !tr.Less(n.items[low-1], key) {
170
-			return low - 1, true
171
-		}
172
-		return low, false
100
+		return tr.bsearch(n, key)
173 101
 	}
102
+	return tr.hintsearch(n, key, hint, depth)
103
+}
174 104
 
175
-	// Try using hint.
105
+func (tr *BTreeG[T]) hintsearch(n *node[T], key T, hint *PathHint, depth int,
106
+) (index int, found bool) {
176 107
 	// Best case finds the exact match, updates the hint and returns.
177 108
 	// Worst case, updates the low and high bounds to binary search between.
178 109
 	low := 0
@@ -247,17 +178,21 @@ path_match:
247 178
 }
248 179
 
249 180
 // SetHint sets or replace a value for a key using a path hint
250
-func (tr *bTree) SetHint(item kind, hint *bPathHint) (prev kind, replaced bool) {
251
-	if tr.lock() {
252
-		defer tr.unlock()
181
+func (tr *BTreeG[T]) SetHint(item T, hint *PathHint) (prev T, replaced bool) {
182
+	if tr.locks {
183
+		tr.mu.Lock()
184
+		prev, replaced = tr.setHint(item, hint)
185
+		tr.mu.Unlock()
186
+	} else {
187
+		prev, replaced = tr.setHint(item, hint)
253 188
 	}
254
-	return tr.setHint(item, hint)
189
+	return prev, replaced
255 190
 }
256 191
 
257
-func (tr *bTree) setHint(item kind, hint *bPathHint) (prev kind, replaced bool) {
192
+func (tr *BTreeG[T]) setHint(item T, hint *PathHint) (prev T, replaced bool) {
258 193
 	if tr.root == nil {
259 194
 		tr.root = tr.newNode(true)
260
-		tr.root.items = append([]kind{}, item)
195
+		tr.root.items = append([]T{}, item)
261 196
 		tr.root.count = 1
262 197
 		tr.count = 1
263 198
 		return tr.empty, false
@@ -267,9 +202,9 @@ func (tr *bTree) setHint(item kind, hint *bPathHint) (prev kind, replaced bool)
267 202
 		left := tr.cowLoad(&tr.root)
268 203
 		right, median := tr.nodeSplit(left)
269 204
 		tr.root = tr.newNode(false)
270
-		*tr.root.children = make([]*node, 0, maxItems+1)
271
-		*tr.root.children = append([]*node{}, left, right)
272
-		tr.root.items = append([]kind{}, median)
205
+		*tr.root.children = make([]*node[T], 0, maxItems+1)
206
+		*tr.root.children = append([]*node[T]{}, left, right)
207
+		tr.root.items = append([]T{}, median)
273 208
 		tr.root.updateCount()
274 209
 		return tr.setHint(item, hint)
275 210
 	}
@@ -281,39 +216,61 @@ func (tr *bTree) setHint(item kind, hint *bPathHint) (prev kind, replaced bool)
281 216
 }
282 217
 
283 218
 // Set or replace a value for a key
284
-func (tr *bTree) Set(item kind) (kind, bool) {
219
+func (tr *BTreeG[T]) Set(item T) (T, bool) {
285 220
 	return tr.SetHint(item, nil)
286 221
 }
287 222
 
288
-func (tr *bTree) nodeSplit(n *node) (right *node, median kind) {
223
+func (tr *BTreeG[T]) nodeSplit(n *node[T]) (right *node[T], median T) {
289 224
 	i := maxItems / 2
290 225
 	median = n.items[i]
291 226
 
292
-	// left node
293
-	left := tr.newNode(n.leaf())
294
-	left.items = make([]kind, len(n.items[:i]), maxItems/2)
295
-	copy(left.items, n.items[:i])
296
-	if !n.leaf() {
297
-		*left.children = make([]*node, len((*n.children)[:i+1]), maxItems+1)
298
-		copy(*left.children, (*n.children)[:i+1])
299
-	}
300
-	left.updateCount()
227
+	const sliceItems = true
301 228
 
302 229
 	// right node
303 230
 	right = tr.newNode(n.leaf())
304
-	right.items = make([]kind, len(n.items[i+1:]), maxItems/2)
305
-	copy(right.items, n.items[i+1:])
306
-	if !n.leaf() {
307
-		*right.children = make([]*node, len((*n.children)[i+1:]), maxItems+1)
308
-		copy(*right.children, (*n.children)[i+1:])
231
+	if sliceItems {
232
+		right.items = n.items[i+1:]
233
+		if !n.leaf() {
234
+			*right.children = (*n.children)[i+1:]
235
+		}
236
+	} else {
237
+		right.items = make([]T, len(n.items[i+1:]), maxItems/2)
238
+		copy(right.items, n.items[i+1:])
239
+		if !n.leaf() {
240
+			*right.children =
241
+				make([]*node[T], len((*n.children)[i+1:]), maxItems+1)
242
+			copy(*right.children, (*n.children)[i+1:])
243
+		}
309 244
 	}
310 245
 	right.updateCount()
311 246
 
312
-	*n = *left
247
+	// left node
248
+	if sliceItems {
249
+		n.items[i] = tr.empty
250
+		n.items = n.items[:i:i]
251
+		if !n.leaf() {
252
+			*n.children = (*n.children)[: i+1 : i+1]
253
+		}
254
+	} else {
255
+		for j := i; j < len(n.items); j++ {
256
+			n.items[j] = tr.empty
257
+		}
258
+		if !n.leaf() {
259
+			for j := i + 1; j < len((*n.children)); j++ {
260
+				(*n.children)[j] = nil
261
+			}
262
+		}
263
+		n.items = n.items[:i]
264
+		if !n.leaf() {
265
+			*n.children = (*n.children)[:i+1]
266
+		}
267
+	}
268
+	n.updateCount()
269
+
313 270
 	return right, median
314 271
 }
315 272
 
316
-func (n *node) updateCount() {
273
+func (n *node[T]) updateCount() {
317 274
 	n.count = len(n.items)
318 275
 	if !n.leaf() {
319 276
 		for i := 0; i < len(*n.children); i++ {
@@ -326,33 +283,42 @@ func (n *node) updateCount() {
326 283
 // called outside of heavy copy-on-write situations. Marking it "noinline"
327 284
 // allows for the parent cowLoad to be inlined.
328 285
 // go:noinline
329
-func (tr *bTree) copy(n *node) *node {
330
-	n2 := new(node)
286
+func (tr *BTreeG[T]) copy(n *node[T]) *node[T] {
287
+	n2 := new(node[T])
331 288
 	n2.cow = tr.cow
332 289
 	n2.count = n.count
333
-	n2.items = make([]kind, len(n.items), cap(n.items))
290
+	n2.items = make([]T, len(n.items), cap(n.items))
334 291
 	copy(n2.items, n.items)
335 292
 	if !n.leaf() {
336
-		n2.children = new([]*node)
337
-		*n2.children = make([]*node, len(*n.children), maxItems+1)
293
+		n2.children = new([]*node[T])
294
+		*n2.children = make([]*node[T], len(*n.children), maxItems+1)
338 295
 		copy(*n2.children, *n.children)
339 296
 	}
340 297
 	return n2
341 298
 }
342 299
 
343 300
 // cowLoad loads the provided node and, if needed, performs a copy-on-write.
344
-func (tr *bTree) cowLoad(cn **node) *node {
301
+func (tr *BTreeG[T]) cowLoad(cn **node[T]) *node[T] {
345 302
 	if (*cn).cow != tr.cow {
346 303
 		*cn = tr.copy(*cn)
347 304
 	}
348 305
 	return *cn
349 306
 }
350 307
 
351
-func (tr *bTree) nodeSet(cn **node, item kind,
352
-	hint *bPathHint, depth int,
353
-) (prev kind, replaced bool, split bool) {
354
-	n := tr.cowLoad(cn)
355
-	i, found := tr.find(n, item, hint, depth)
308
+func (tr *BTreeG[T]) nodeSet(cn **node[T], item T,
309
+	hint *PathHint, depth int,
310
+) (prev T, replaced bool, split bool) {
311
+	if (*cn).cow != tr.cow {
312
+		*cn = tr.copy(*cn)
313
+	}
314
+	n := *cn
315
+	var i int
316
+	var found bool
317
+	if hint == nil {
318
+		i, found = tr.bsearch(n, item)
319
+	} else {
320
+		i, found = tr.hintsearch(n, item, hint, depth)
321
+	}
356 322
 	if found {
357 323
 		prev = n.items[i]
358 324
 		n.items[i] = item
@@ -388,7 +354,7 @@ func (tr *bTree) nodeSet(cn **node, item kind,
388 354
 	return prev, replaced, false
389 355
 }
390 356
 
391
-func (tr *bTree) Scan(iter func(item kind) bool) {
357
+func (tr *BTreeG[T]) Scan(iter func(item T) bool) {
392 358
 	if tr.rlock() {
393 359
 		defer tr.runlock()
394 360
 	}
@@ -398,7 +364,7 @@ func (tr *bTree) Scan(iter func(item kind) bool) {
398 364
 	tr.root.scan(iter)
399 365
 }
400 366
 
401
-func (n *node) scan(iter func(item kind) bool) bool {
367
+func (n *node[T]) scan(iter func(item T) bool) bool {
402 368
 	if n.leaf() {
403 369
 		for i := 0; i < len(n.items); i++ {
404 370
 			if !iter(n.items[i]) {
@@ -419,15 +385,36 @@ func (n *node) scan(iter func(item kind) bool) bool {
419 385
 }
420 386
 
421 387
 // Get a value for key
422
-func (tr *bTree) Get(key kind) (kind, bool) {
423
-	return tr.GetHint(key, nil)
388
+func (tr *BTreeG[T]) Get(key T) (T, bool) {
389
+	if tr.locks {
390
+		return tr.GetHint(key, nil)
391
+	}
392
+	if tr.root == nil {
393
+		return tr.empty, false
394
+	}
395
+	n := tr.root
396
+	for {
397
+		i, found := tr.bsearch(n, key)
398
+		if found {
399
+			return n.items[i], true
400
+		}
401
+		if n.children == nil {
402
+			return tr.empty, false
403
+		}
404
+		n = (*n.children)[i]
405
+	}
424 406
 }
425 407
 
426 408
 // GetHint gets a value for key using a path hint
427
-func (tr *bTree) GetHint(key kind, hint *bPathHint) (kind, bool) {
409
+func (tr *BTreeG[T]) GetHint(key T, hint *PathHint) (value T, ok bool) {
428 410
 	if tr.rlock() {
429 411
 		defer tr.runlock()
430 412
 	}
413
+	return tr.getHint(key, hint)
414
+}
415
+
416
+// GetHint gets a value for key using a path hint
417
+func (tr *BTreeG[T]) getHint(key T, hint *PathHint) (T, bool) {
431 418
 	if tr.root == nil {
432 419
 		return tr.empty, false
433 420
 	}
@@ -447,24 +434,27 @@ func (tr *bTree) GetHint(key kind, hint *bPathHint) (kind, bool) {
447 434
 }
448 435
 
449 436
 // Len returns the number of items in the tree
450
-func (tr *bTree) Len() int {
437
+func (tr *BTreeG[T]) Len() int {
451 438
 	return tr.count
452 439
 }
453 440
 
454
-// Delete a value for a key
455
-func (tr *bTree) Delete(key kind) (kind, bool) {
441
+// Delete a value for a key and returns the deleted value.
442
+// Returns false if there was no value by that key found.
443
+func (tr *BTreeG[T]) Delete(key T) (T, bool) {
456 444
 	return tr.DeleteHint(key, nil)
457 445
 }
458 446
 
459
-// DeleteHint deletes a value for a key using a path hint
460
-func (tr *bTree) DeleteHint(key kind, hint *bPathHint) (kind, bool) {
447
+// DeleteHint deletes a value for a key using a path hint and returns the
448
+// deleted value.
449
+// Returns false if there was no value by that key found.
450
+func (tr *BTreeG[T]) DeleteHint(key T, hint *PathHint) (T, bool) {
461 451
 	if tr.lock() {
462 452
 		defer tr.unlock()
463 453
 	}
464 454
 	return tr.deleteHint(key, hint)
465 455
 }
466 456
 
467
-func (tr *bTree) deleteHint(key kind, hint *bPathHint) (kind, bool) {
457
+func (tr *BTreeG[T]) deleteHint(key T, hint *PathHint) (T, bool) {
468 458
 	if tr.root == nil {
469 459
 		return tr.empty, false
470 460
 	}
@@ -482,9 +472,9 @@ func (tr *bTree) deleteHint(key kind, hint *bPathHint) (kind, bool) {
482 472
 	return prev, true
483 473
 }
484 474
 
485
-func (tr *bTree) delete(cn **node, max bool, key kind,
486
-	hint *bPathHint, depth int,
487
-) (kind, bool) {
475
+func (tr *BTreeG[T]) delete(cn **node[T], max bool, key T,
476
+	hint *PathHint, depth int,
477
+) (T, bool) {
488 478
 	n := tr.cowLoad(cn)
489 479
 	var i int
490 480
 	var found bool
@@ -506,7 +496,7 @@ func (tr *bTree) delete(cn **node, max bool, key kind,
506 496
 		return tr.empty, false
507 497
 	}
508 498
 
509
-	var prev kind
499
+	var prev T
510 500
 	var deleted bool
511 501
 	if found {
512 502
 		if max {
@@ -529,13 +519,12 @@ func (tr *bTree) delete(cn **node, max bool, key kind,
529 519
 		tr.nodeRebalance(n, i)
530 520
 	}
531 521
 	return prev, true
532
-
533 522
 }
534 523
 
535 524
 // nodeRebalance rebalances the child nodes following a delete operation.
536 525
 // Provide the index of the child node with the number of items that fell
537 526
 // below minItems.
538
-func (tr *bTree) nodeRebalance(n *node, i int) {
527
+func (tr *BTreeG[T]) nodeRebalance(n *node[T], i int) {
539 528
 	if i == len(n.items) {
540 529
 		i--
541 530
 	}
@@ -618,7 +607,7 @@ func (tr *bTree) nodeRebalance(n *node, i int) {
618 607
 // Ascend the tree within the range [pivot, last]
619 608
 // Pass nil for pivot to scan all item in ascending order
620 609
 // Return false to stop iterating
621
-func (tr *bTree) Ascend(pivot kind, iter func(item kind) bool) {
610
+func (tr *BTreeG[T]) Ascend(pivot T, iter func(item T) bool) {
622 611
 	if tr.rlock() {
623 612
 		defer tr.runlock()
624 613
 	}
@@ -630,8 +619,8 @@ func (tr *bTree) Ascend(pivot kind, iter func(item kind) bool) {
630 619
 
631 620
 // The return value of this function determines whether we should keep iterating
632 621
 // upon this functions return.
633
-func (tr *bTree) ascend(n *node, pivot kind,
634
-	hint *bPathHint, depth int, iter func(item kind) bool,
622
+func (tr *BTreeG[T]) ascend(n *node[T], pivot T,
623
+	hint *PathHint, depth int, iter func(item T) bool,
635 624
 ) bool {
636 625
 	i, found := tr.find(n, pivot, hint, depth)
637 626
 	if !found {
@@ -658,7 +647,7 @@ func (tr *bTree) ascend(n *node, pivot kind,
658 647
 	return true
659 648
 }
660 649
 
661
-func (tr *bTree) Reverse(iter func(item kind) bool) {
650
+func (tr *BTreeG[T]) Reverse(iter func(item T) bool) {
662 651
 	if tr.rlock() {
663 652
 		defer tr.runlock()
664 653
 	}
@@ -668,7 +657,7 @@ func (tr *bTree) Reverse(iter func(item kind) bool) {
668 657
 	tr.root.reverse(iter)
669 658
 }
670 659
 
671
-func (n *node) reverse(iter func(item kind) bool) bool {
660
+func (n *node[T]) reverse(iter func(item T) bool) bool {
672 661
 	if n.leaf() {
673 662
 		for i := len(n.items) - 1; i >= 0; i-- {
674 663
 			if !iter(n.items[i]) {
@@ -694,7 +683,7 @@ func (n *node) reverse(iter func(item kind) bool) bool {
694 683
 // Descend the tree within the range [pivot, first]
695 684
 // Pass nil for pivot to scan all item in descending order
696 685
 // Return false to stop iterating
697
-func (tr *bTree) Descend(pivot kind, iter func(item kind) bool) {
686
+func (tr *BTreeG[T]) Descend(pivot T, iter func(item T) bool) {
698 687
 	if tr.rlock() {
699 688
 		defer tr.runlock()
700 689
 	}
@@ -704,8 +693,8 @@ func (tr *bTree) Descend(pivot kind, iter func(item kind) bool) {
704 693
 	tr.descend(tr.root, pivot, nil, 0, iter)
705 694
 }
706 695
 
707
-func (tr *bTree) descend(n *node, pivot kind,
708
-	hint *bPathHint, depth int, iter func(item kind) bool,
696
+func (tr *BTreeG[T]) descend(n *node[T], pivot T,
697
+	hint *PathHint, depth int, iter func(item T) bool,
709 698
 ) bool {
710 699
 	i, found := tr.find(n, pivot, hint, depth)
711 700
 	if !found {
@@ -730,7 +719,7 @@ func (tr *bTree) descend(n *node, pivot kind,
730 719
 }
731 720
 
732 721
 // Load is for bulk loading pre-sorted items
733
-func (tr *bTree) Load(item kind) (kind, bool) {
722
+func (tr *BTreeG[T]) Load(item T) (T, bool) {
734 723
 	if tr.lock() {
735 724
 		defer tr.unlock()
736 725
 	}
@@ -765,8 +754,8 @@ func (tr *bTree) Load(item kind) (kind, bool) {
765 754
 }
766 755
 
767 756
 // Min returns the minimum item in tree.
768
-// Returns nil if the tree has no items.
769
-func (tr *bTree) Min() (kind, bool) {
757
+// Returns nil if the treex has no items.
758
+func (tr *BTreeG[T]) Min() (T, bool) {
770 759
 	if tr.rlock() {
771 760
 		defer tr.runlock()
772 761
 	}
@@ -784,7 +773,7 @@ func (tr *bTree) Min() (kind, bool) {
784 773
 
785 774
 // Max returns the maximum item in tree.
786 775
 // Returns nil if the tree has no items.
787
-func (tr *bTree) Max() (kind, bool) {
776
+func (tr *BTreeG[T]) Max() (T, bool) {
788 777
 	if tr.rlock() {
789 778
 		defer tr.runlock()
790 779
 	}
@@ -802,7 +791,7 @@ func (tr *bTree) Max() (kind, bool) {
802 791
 
803 792
 // PopMin removes the minimum item in tree and returns it.
804 793
 // Returns nil if the tree has no items.
805
-func (tr *bTree) PopMin() (kind, bool) {
794
+func (tr *BTreeG[T]) PopMin() (T, bool) {
806 795
 	if tr.lock() {
807 796
 		defer tr.unlock()
808 797
 	}
@@ -810,7 +799,7 @@ func (tr *bTree) PopMin() (kind, bool) {
810 799
 		return tr.empty, false
811 800
 	}
812 801
 	n := tr.cowLoad(&tr.root)
813
-	var item kind
802
+	var item T
814 803
 	for {
815 804
 		n.count-- // optimistically update counts
816 805
 		if n.leaf() {
@@ -841,9 +830,9 @@ func (tr *bTree) PopMin() (kind, bool) {
841 830
 	return tr.deleteHint(item, nil)
842 831
 }
843 832
 
844
-// PopMax removes the minimum item in tree and returns it.
833
+// PopMax removes the maximum item in tree and returns it.
845 834
 // Returns nil if the tree has no items.
846
-func (tr *bTree) PopMax() (kind, bool) {
835
+func (tr *BTreeG[T]) PopMax() (T, bool) {
847 836
 	if tr.lock() {
848 837
 		defer tr.unlock()
849 838
 	}
@@ -851,7 +840,7 @@ func (tr *bTree) PopMax() (kind, bool) {
851 840
 		return tr.empty, false
852 841
 	}
853 842
 	n := tr.cowLoad(&tr.root)
854
-	var item kind
843
+	var item T
855 844
 	for {
856 845
 		n.count-- // optimistically update counts
857 846
 		if n.leaf() {
@@ -883,7 +872,7 @@ func (tr *bTree) PopMax() (kind, bool) {
883 872
 
884 873
 // GetAt returns the value at index.
885 874
 // Return nil if the tree is empty or the index is out of bounds.
886
-func (tr *bTree) GetAt(index int) (kind, bool) {
875
+func (tr *BTreeG[T]) GetAt(index int) (T, bool) {
887 876
 	if tr.rlock() {
888 877
 		defer tr.runlock()
889 878
 	}
@@ -910,7 +899,7 @@ func (tr *bTree) GetAt(index int) (kind, bool) {
910 899
 
911 900
 // DeleteAt deletes the item at index.
912 901
 // Return nil if the tree is empty or the index is out of bounds.
913
-func (tr *bTree) DeleteAt(index int) (kind, bool) {
902
+func (tr *BTreeG[T]) DeleteAt(index int) (T, bool) {
914 903
 	if tr.lock() {
915 904
 		defer tr.unlock()
916 905
 	}
@@ -919,7 +908,7 @@ func (tr *bTree) DeleteAt(index int) (kind, bool) {
919 908
 	}
920 909
 	var pathbuf [8]uint8 // track the path
921 910
 	path := pathbuf[:0]
922
-	var item kind
911
+	var item T
923 912
 	n := tr.cowLoad(&tr.root)
924 913
 outer:
925 914
 	for {
@@ -955,7 +944,7 @@ outer:
955 944
 		n = tr.cowLoad(&(*n.children)[i])
956 945
 	}
957 946
 	// revert the counts
958
-	var hint bPathHint
947
+	var hint PathHint
959 948
 	n = tr.root
960 949
 	for i := 0; i < len(path); i++ {
961 950
 		if i < len(hint.path) {
@@ -972,7 +961,7 @@ outer:
972 961
 
973 962
 // Height returns the height of the tree.
974 963
 // Returns zero if tree has no items.
975
-func (tr *bTree) Height() int {
964
+func (tr *BTreeG[T]) Height() int {
976 965
 	if tr.rlock() {
977 966
 		defer tr.runlock()
978 967
 	}
@@ -992,7 +981,7 @@ func (tr *bTree) Height() int {
992 981
 
993 982
 // Walk iterates over all items in tree, in order.
994 983
 // The items param will contain one or more items.
995
-func (tr *bTree) Walk(iter func(item []kind) bool) {
984
+func (tr *BTreeG[T]) Walk(iter func(item []T) bool) {
996 985
 	if tr.rlock() {
997 986
 		defer tr.runlock()
998 987
 	}
@@ -1001,7 +990,7 @@ func (tr *bTree) Walk(iter func(item []kind) bool) {
1001 990
 	}
1002 991
 }
1003 992
 
1004
-func (n *node) walk(iter func(item []kind) bool) bool {
993
+func (n *node[T]) walk(iter func(item []T) bool) bool {
1005 994
 	if n.leaf() {
1006 995
 		if !iter(n.items) {
1007 996
 			return false
@@ -1020,60 +1009,60 @@ func (n *node) walk(iter func(item []kind) bool) bool {
1020 1009
 
1021 1010
 // Copy the tree. This is a copy-on-write operation and is very fast because
1022 1011
 // it only performs a shadowed copy.
1023
-func (tr *bTree) Copy() *bTree {
1012
+func (tr *BTreeG[T]) Copy() *BTreeG[T] {
1024 1013
 	if tr.lock() {
1025 1014
 		defer tr.unlock()
1026 1015
 	}
1027
-	tr.cow = new(cow)
1028
-	tr2 := new(bTree)
1016
+	tr.cow = atomic.AddUint64(&gcow, 1)
1017
+	tr2 := new(BTreeG[T])
1029 1018
 	*tr2 = *tr
1030 1019
 	tr2.mu = new(sync.RWMutex)
1031
-	tr2.cow = new(cow)
1020
+	tr2.cow = atomic.AddUint64(&gcow, 1)
1032 1021
 	return tr2
1033 1022
 }
1034 1023
 
1035
-func (tr *bTree) lock() bool {
1024
+func (tr *BTreeG[T]) lock() bool {
1036 1025
 	if tr.locks {
1037 1026
 		tr.mu.Lock()
1038 1027
 	}
1039 1028
 	return tr.locks
1040 1029
 }
1041 1030
 
1042
-func (tr *bTree) unlock() {
1031
+func (tr *BTreeG[T]) unlock() {
1043 1032
 	tr.mu.Unlock()
1044 1033
 }
1045 1034
 
1046
-func (tr *bTree) rlock() bool {
1035
+func (tr *BTreeG[T]) rlock() bool {
1047 1036
 	if tr.locks {
1048 1037
 		tr.mu.RLock()
1049 1038
 	}
1050 1039
 	return tr.locks
1051 1040
 }
1052 1041
 
1053
-func (tr *bTree) runlock() {
1042
+func (tr *BTreeG[T]) runlock() {
1054 1043
 	tr.mu.RUnlock()
1055 1044
 }
1056 1045
 
1057 1046
 // Iter represents an iterator
1058
-type bIter struct {
1059
-	tr      *bTree
1047
+type GenericIter[T any] struct {
1048
+	tr      *BTreeG[T]
1060 1049
 	locked  bool
1061 1050
 	seeked  bool
1062 1051
 	atstart bool
1063 1052
 	atend   bool
1064
-	stack   []iterStackItem
1065
-	item    kind
1053
+	stack   []genericIterStackItem[T]
1054
+	item    T
1066 1055
 }
1067 1056
 
1068
-type iterStackItem struct {
1069
-	n *node
1057
+type genericIterStackItem[T any] struct {
1058
+	n *node[T]
1070 1059
 	i int
1071 1060
 }
1072 1061
 
1073 1062
 // Iter returns a read-only iterator.
1074 1063
 // The Release method must be called finished with iterator.
1075
-func (tr *bTree) Iter() bIter {
1076
-	var iter bIter
1064
+func (tr *BTreeG[T]) Iter() GenericIter[T] {
1065
+	var iter GenericIter[T]
1077 1066
 	iter.tr = tr
1078 1067
 	iter.locked = tr.rlock()
1079 1068
 	return iter
@@ -1081,7 +1070,7 @@ func (tr *bTree) Iter() bIter {
1081 1070
 
1082 1071
 // Seek to item greater-or-equal-to key.
1083 1072
 // Returns false if there was no item found.
1084
-func (iter *bIter) Seek(key kind) bool {
1073
+func (iter *GenericIter[T]) Seek(key T) bool {
1085 1074
 	if iter.tr == nil {
1086 1075
 		return false
1087 1076
 	}
@@ -1093,16 +1082,14 @@ func (iter *bIter) Seek(key kind) bool {
1093 1082
 	n := iter.tr.root
1094 1083
 	for {
1095 1084
 		i, found := iter.tr.find(n, key, nil, 0)
1096
-		iter.stack = append(iter.stack, iterStackItem{n, i})
1085
+		iter.stack = append(iter.stack, genericIterStackItem[T]{n, i})
1097 1086
 		if found {
1087
+			iter.item = n.items[i]
1098 1088
 			return true
1099 1089
 		}
1100 1090
 		if n.leaf() {
1101
-			if i == len(n.items) {
1102
-				iter.stack = iter.stack[:0]
1103
-				return false
1104
-			}
1105
-			return true
1091
+			iter.stack[len(iter.stack)-1].i--
1092
+			return iter.Next()
1106 1093
 		}
1107 1094
 		n = (*n.children)[i]
1108 1095
 	}
@@ -1110,7 +1097,7 @@ func (iter *bIter) Seek(key kind) bool {
1110 1097
 
1111 1098
 // First moves iterator to first item in tree.
1112 1099
 // Returns false if the tree is empty.
1113
-func (iter *bIter) First() bool {
1100
+func (iter *GenericIter[T]) First() bool {
1114 1101
 	if iter.tr == nil {
1115 1102
 		return false
1116 1103
 	}
@@ -1123,7 +1110,7 @@ func (iter *bIter) First() bool {
1123 1110
 	}
1124 1111
 	n := iter.tr.root
1125 1112
 	for {
1126
-		iter.stack = append(iter.stack, iterStackItem{n, 0})
1113
+		iter.stack = append(iter.stack, genericIterStackItem[T]{n, 0})
1127 1114
 		if n.leaf() {
1128 1115
 			break
1129 1116
 		}
@@ -1136,7 +1123,7 @@ func (iter *bIter) First() bool {
1136 1123
 
1137 1124
 // Last moves iterator to last item in tree.
1138 1125
 // Returns false if the tree is empty.
1139
-func (iter *bIter) Last() bool {
1126
+func (iter *GenericIter[T]) Last() bool {
1140 1127
 	if iter.tr == nil {
1141 1128
 		return false
1142 1129
 	}
@@ -1147,7 +1134,7 @@ func (iter *bIter) Last() bool {
1147 1134
 	}
1148 1135
 	n := iter.tr.root
1149 1136
 	for {
1150
-		iter.stack = append(iter.stack, iterStackItem{n, len(n.items)})
1137
+		iter.stack = append(iter.stack, genericIterStackItem[T]{n, len(n.items)})
1151 1138
 		if n.leaf() {
1152 1139
 			iter.stack[len(iter.stack)-1].i--
1153 1140
 			break
@@ -1159,9 +1146,8 @@ func (iter *bIter) Last() bool {
1159 1146
 	return true
1160 1147
 }
1161 1148
 
1162
-// First moves iterator to first item in tree.
1163
-// Returns false if the tree is empty.
1164
-func (iter *bIter) Release() {
1149
+// Release the iterator.
1150
+func (iter *GenericIter[T]) Release() {
1165 1151
 	if iter.tr == nil {
1166 1152
 		return
1167 1153
 	}
@@ -1176,7 +1162,7 @@ func (iter *bIter) Release() {
1176 1162
 // Next moves iterator to the next item in iterator.
1177 1163
 // Returns false if the tree is empty or the iterator is at the end of
1178 1164
 // the tree.
1179
-func (iter *bIter) Next() bool {
1165
+func (iter *GenericIter[T]) Next() bool {
1180 1166
 	if iter.tr == nil {
1181 1167
 		return false
1182 1168
 	}
@@ -1208,7 +1194,7 @@ func (iter *bIter) Next() bool {
1208 1194
 	} else {
1209 1195
 		n := (*s.n.children)[s.i]
1210 1196
 		for {
1211
-			iter.stack = append(iter.stack, iterStackItem{n, 0})
1197
+			iter.stack = append(iter.stack, genericIterStackItem[T]{n, 0})
1212 1198
 			if n.leaf() {
1213 1199
 				break
1214 1200
 			}
@@ -1223,7 +1209,7 @@ func (iter *bIter) Next() bool {
1223 1209
 // Prev moves iterator to the previous item in iterator.
1224 1210
 // Returns false if the tree is empty or the iterator is at the beginning of
1225 1211
 // the tree.
1226
-func (iter *bIter) Prev() bool {
1212
+func (iter *GenericIter[T]) Prev() bool {
1227 1213
 	if iter.tr == nil {
1228 1214
 		return false
1229 1215
 	}
@@ -1256,7 +1242,7 @@ func (iter *bIter) Prev() bool {
1256 1242
 	} else {
1257 1243
 		n := (*s.n.children)[s.i]
1258 1244
 		for {
1259
-			iter.stack = append(iter.stack, iterStackItem{n, len(n.items)})
1245
+			iter.stack = append(iter.stack, genericIterStackItem[T]{n, len(n.items)})
1260 1246
 			if n.leaf() {
1261 1247
 				iter.stack[len(iter.stack)-1].i--
1262 1248
 				break
@@ -1270,6 +1256,48 @@ func (iter *bIter) Prev() bool {
1270 1256
 }
1271 1257
 
1272 1258
 // Item returns the current iterator item.
1273
-func (iter *bIter) Item() kind {
1259
+func (iter *GenericIter[T]) Item() T {
1274 1260
 	return iter.item
1275 1261
 }
1262
+
1263
+// Items returns all the items in order.
1264
+func (tr *BTreeG[T]) Items() []T {
1265
+	items := make([]T, 0, tr.Len())
1266
+	if tr.root != nil {
1267
+		items = tr.root.aitems(items)
1268
+	}
1269
+	return items
1270
+}
1271
+
1272
+func (n *node[T]) aitems(items []T) []T {
1273
+	if n.leaf() {
1274
+		return append(items, n.items...)
1275
+	}
1276
+	for i := 0; i < len(n.items); i++ {
1277
+		items = (*n.children)[i].aitems(items)
1278
+		items = append(items, n.items[i])
1279
+	}
1280
+	return (*n.children)[len(*n.children)-1].aitems(items)
1281
+}
1282
+
1283
+// Generic BTree
1284
+// Deprecated: use BTreeG
1285
+type Generic[T any] struct {
1286
+	*BTreeG[T]
1287
+}
1288
+
1289
+// NewGeneric returns a generic BTree
1290
+// Deprecated: use NewBTreeG
1291
+func NewGeneric[T any](less func(a, b T) bool) *Generic[T] {
1292
+	return &Generic[T]{NewBTreeGOptions(less, Options{})}
1293
+}
1294
+
1295
+// NewGenericOptions returns a generic BTree
1296
+// Deprecated: use NewBTreeGOptions
1297
+func NewGenericOptions[T any](less func(a, b T) bool, opts Options) *Generic[T] {
1298
+	return &Generic[T]{NewBTreeGOptions(less, opts)}
1299
+}
1300
+
1301
+func (tr *Generic[T]) Copy() *Generic[T] {
1302
+	return &Generic[T]{tr.BTreeG.Copy()}
1303
+}

+ 1056
- 0
vendor/github.com/tidwall/btree/map.go
File diff suppressed because it is too large
View File


+ 168
- 0
vendor/github.com/tidwall/btree/set.go View File

@@ -0,0 +1,168 @@
1
+package btree
2
+
3
+type Set[K ordered] struct {
4
+	base Map[K, struct{}]
5
+}
6
+
7
+// Copy
8
+func (tr *Set[K]) Copy() *Set[K] {
9
+	tr2 := new(Set[K])
10
+	tr2.base = *tr.base.Copy()
11
+	return tr2
12
+}
13
+
14
+// Insert an item
15
+func (tr *Set[K]) Insert(key K) {
16
+	tr.base.Set(key, struct{}{})
17
+}
18
+
19
+func (tr *Set[K]) Scan(iter func(key K) bool) {
20
+	tr.base.Scan(func(key K, value struct{}) bool {
21
+		return iter(key)
22
+	})
23
+}
24
+
25
+// Get a value for key
26
+func (tr *Set[K]) Contains(key K) bool {
27
+	_, ok := tr.base.Get(key)
28
+	return ok
29
+}
30
+
31
+// Len returns the number of items in the tree
32
+func (tr *Set[K]) Len() int {
33
+	return tr.base.Len()
34
+}
35
+
36
+// Delete an item
37
+func (tr *Set[K]) Delete(key K) {
38
+	tr.base.Delete(key)
39
+}
40
+
41
+// Ascend the tree within the range [pivot, last]
42
+// Pass nil for pivot to scan all item in ascending order
43
+// Return false to stop iterating
44
+func (tr *Set[K]) Ascend(pivot K, iter func(key K) bool) {
45
+	tr.base.Ascend(pivot, func(key K, value struct{}) bool {
46
+		return iter(key)
47
+	})
48
+}
49
+
50
+func (tr *Set[K]) Reverse(iter func(key K) bool) {
51
+	tr.base.Reverse(func(key K, value struct{}) bool {
52
+		return iter(key)
53
+	})
54
+}
55
+
56
+// Descend the tree within the range [pivot, first]
57
+// Pass nil for pivot to scan all item in descending order
58
+// Return false to stop iterating
59
+func (tr *Set[K]) Descend(pivot K, iter func(key K) bool) {
60
+	tr.base.Descend(pivot, func(key K, value struct{}) bool {
61
+		return iter(key)
62
+	})
63
+}
64
+
65
+// Load is for bulk loading pre-sorted items
66
+func (tr *Set[K]) Load(key K) {
67
+	tr.base.Load(key, struct{}{})
68
+}
69
+
70
+// Min returns the minimum item in tree.
71
+// Returns nil if the treex has no items.
72
+func (tr *Set[K]) Min() (K, bool) {
73
+	key, _, ok := tr.base.Min()
74
+	return key, ok
75
+}
76
+
77
+// Max returns the maximum item in tree.
78
+// Returns nil if the tree has no items.
79
+func (tr *Set[K]) Max() (K, bool) {
80
+	key, _, ok := tr.base.Max()
81
+	return key, ok
82
+}
83
+
84
+// PopMin removes the minimum item in tree and returns it.
85
+// Returns nil if the tree has no items.
86
+func (tr *Set[K]) PopMin() (K, bool) {
87
+	key, _, ok := tr.base.PopMin()
88
+	return key, ok
89
+}
90
+
91
+// PopMax removes the maximum item in tree and returns it.
92
+// Returns nil if the tree has no items.
93
+func (tr *Set[K]) PopMax() (K, bool) {
94
+	key, _, ok := tr.base.PopMax()
95
+	return key, ok
96
+}
97
+
98
+// GetAt returns the value at index.
99
+// Return nil if the tree is empty or the index is out of bounds.
100
+func (tr *Set[K]) GetAt(index int) (K, bool) {
101
+	key, _, ok := tr.base.GetAt(index)
102
+	return key, ok
103
+}
104
+
105
+// DeleteAt deletes the item at index.
106
+// Return nil if the tree is empty or the index is out of bounds.
107
+func (tr *Set[K]) DeleteAt(index int) (K, bool) {
108
+	key, _, ok := tr.base.DeleteAt(index)
109
+	return key, ok
110
+}
111
+
112
+// Height returns the height of the tree.
113
+// Returns zero if tree has no items.
114
+func (tr *Set[K]) Height() int {
115
+	return tr.base.Height()
116
+}
117
+
118
+// SetIter represents an iterator for btree.Set
119
+type SetIter[K ordered] struct {
120
+	base MapIter[K, struct{}]
121
+}
122
+
123
+// Iter returns a read-only iterator.
124
+func (tr *Set[K]) Iter() SetIter[K] {
125
+	return SetIter[K]{tr.base.Iter()}
126
+}
127
+
128
+// Seek to item greater-or-equal-to key.
129
+// Returns false if there was no item found.
130
+func (iter *SetIter[K]) Seek(key K) bool {
131
+	return iter.base.Seek(key)
132
+}
133
+
134
+// First moves iterator to first item in tree.
135
+// Returns false if the tree is empty.
136
+func (iter *SetIter[K]) First() bool {
137
+	return iter.base.First()
138
+}
139
+
140
+// Last moves iterator to last item in tree.
141
+// Returns false if the tree is empty.
142
+func (iter *SetIter[K]) Last() bool {
143
+	return iter.base.Last()
144
+}
145
+
146
+// Next moves iterator to the next item in iterator.
147
+// Returns false if the tree is empty or the iterator is at the end of
148
+// the tree.
149
+func (iter *SetIter[K]) Next() bool {
150
+	return iter.base.Next()
151
+}
152
+
153
+// Prev moves iterator to the previous item in iterator.
154
+// Returns false if the tree is empty or the iterator is at the beginning of
155
+// the tree.
156
+func (iter *SetIter[K]) Prev() bool {
157
+	return iter.base.Prev()
158
+}
159
+
160
+// Key returns the current iterator item key.
161
+func (iter *SetIter[K]) Key() K {
162
+	return iter.base.Key()
163
+}
164
+
165
+// Keys returns all the keys in order.
166
+func (tr *Set[K]) Keys() []K {
167
+	return tr.base.Keys()
168
+}

+ 10
- 5
vendor/github.com/tidwall/buntdb/buntdb.go View File

@@ -7,6 +7,7 @@ package buntdb
7 7
 import (
8 8
 	"bufio"
9 9
 	"errors"
10
+	"fmt"
10 11
 	"io"
11 12
 	"os"
12 13
 	"sort"
@@ -749,13 +750,13 @@ func (db *DB) Shrink() error {
749 750
 		if err := db.file.Close(); err != nil {
750 751
 			return err
751 752
 		}
752
-		// Any failures below here is really bad. So just panic.
753
+		// Any failures below here are really bad. So just panic.
753 754
 		if err := os.Rename(tmpname, fname); err != nil {
754
-			panic(err)
755
+			panicErr(err)
755 756
 		}
756 757
 		db.file, err = os.OpenFile(fname, os.O_CREATE|os.O_RDWR, 0666)
757 758
 		if err != nil {
758
-			panic(err)
759
+			panicErr(err)
759 760
 		}
760 761
 		pos, err := db.file.Seek(0, 2)
761 762
 		if err != nil {
@@ -766,6 +767,10 @@ func (db *DB) Shrink() error {
766 767
 	}()
767 768
 }
768 769
 
770
+func panicErr(err error) error {
771
+	panic(fmt.Errorf("buntdb: %w", err))
772
+}
773
+
769 774
 // readLoad reads from the reader and loads commands into the database.
770 775
 // modTime is the modified time of the reader, should be no greater than
771 776
 // the current time.Now().
@@ -1209,10 +1214,10 @@ func (tx *Tx) Commit() error {
1209 1214
 				// should be killed to avoid corrupting the file.
1210 1215
 				pos, err := tx.db.file.Seek(-int64(n), 1)
1211 1216
 				if err != nil {
1212
-					panic(err)
1217
+					panicErr(err)
1213 1218
 				}
1214 1219
 				if err := tx.db.file.Truncate(pos); err != nil {
1215
-					panic(err)
1220
+					panicErr(err)
1216 1221
 				}
1217 1222
 			}
1218 1223
 			tx.rollbackInner()

+ 7
- 0
vendor/github.com/tidwall/gjson/README.md View File

@@ -16,6 +16,10 @@ It has features such as [one line retrieval](#get-a-value), [dot notation paths]
16 16
 
17 17
 Also check out [SJSON](https://github.com/tidwall/sjson) for modifying json, and the [JJ](https://github.com/tidwall/jj) command line tool.
18 18
 
19
+This README is a quick overview of how to use GJSON, for more information check out [GJSON Syntax](SYNTAX.md).
20
+
21
+GJSON is also available for [Python](https://github.com/volans-/gjson-py) and [Rust](https://github.com/tidwall/gjson.rs)
22
+
19 23
 Getting Started
20 24
 ===============
21 25
 
@@ -204,6 +208,9 @@ There are currently the following built-in modifiers:
204 208
 - `@join`: Joins multiple objects into a single object.
205 209
 - `@keys`: Returns an array of keys for an object.
206 210
 - `@values`: Returns an array of values for an object.
211
+- `@tostr`: Converts json to a string. Wraps a json string.
212
+- `@fromstr`: Converts a string from json. Unwraps a json string.
213
+- `@group`: Groups arrays of objects. See [e4fc67c](https://github.com/tidwall/gjson/commit/e4fc67c92aeebf2089fabc7872f010e340d105db).
207 214
 
208 215
 ### Modifier arguments
209 216
 

+ 5
- 2
vendor/github.com/tidwall/gjson/SYNTAX.md View File

@@ -22,7 +22,7 @@ Use the [GJSON Playground](https://gjson.dev) to experiment with the syntax onli
22 22
 
23 23
 A GJSON Path is intended to be easily expressed as a series of components seperated by a `.` character. 
24 24
 
25
-Along with `.` character, there are a few more that have special meaning, including `|`, `#`, `@`, `\`, `*`, and `?`.
25
+Along with `.` character, there are a few more that have special meaning, including `|`, `#`, `@`, `\`, `*`, `!`, and `?`.
26 26
 
27 27
 ## Example
28 28
 
@@ -77,7 +77,7 @@ Special purpose characters, such as `.`, `*`, and `?` can be escaped with `\`.
77 77
 fav\.movie             "Deer Hunter"
78 78
 ```
79 79
 
80
-You'll also need to make sure that the `\` character is correctly escaped when hardcoding a path in you source code.
80
+You'll also need to make sure that the `\` character is correctly escaped when hardcoding a path in your source code.
81 81
 
82 82
 ```go
83 83
 // Go
@@ -238,6 +238,9 @@ There are currently the following built-in modifiers:
238 238
 - `@join`: Joins multiple objects into a single object.
239 239
 - `@keys`: Returns an array of keys for an object.
240 240
 - `@values`: Returns an array of values for an object.
241
+- `@tostr`: Converts json to a string. Wraps a json string.
242
+- `@fromstr`: Converts a string from json. Unwraps a json string.
243
+- `@group`: Groups arrays of objects. See [e4fc67c](https://github.com/tidwall/gjson/commit/e4fc67c92aeebf2089fabc7872f010e340d105db).
241 244
 
242 245
 #### Modifier arguments
243 246
 

+ 164
- 19
vendor/github.com/tidwall/gjson/gjson.go View File

@@ -2,7 +2,6 @@
2 2
 package gjson
3 3
 
4 4
 import (
5
-	"encoding/json"
6 5
 	"strconv"
7 6
 	"strings"
8 7
 	"time"
@@ -214,6 +213,11 @@ func (t Result) IsArray() bool {
214 213
 	return t.Type == JSON && len(t.Raw) > 0 && t.Raw[0] == '['
215 214
 }
216 215
 
216
+// IsBool returns true if the result value is a JSON boolean.
217
+func (t Result) IsBool() bool {
218
+	return t.Type == True || t.Type == False
219
+}
220
+
217 221
 // ForEach iterates through values.
218 222
 // If the result represents a non-existent value, then no values will be
219 223
 // iterated. If the result is an Object, the iterator will pass the key and
@@ -771,7 +775,7 @@ func parseArrayPath(path string) (r arrayPathResult) {
771 775
 		}
772 776
 		if path[i] == '.' {
773 777
 			r.part = path[:i]
774
-			if !r.arrch && i < len(path)-1 && isDotPiperChar(path[i+1]) {
778
+			if !r.arrch && i < len(path)-1 && isDotPiperChar(path[i+1:]) {
775 779
 				r.pipe = path[i+1:]
776 780
 				r.piped = true
777 781
 			} else {
@@ -932,8 +936,23 @@ right:
932 936
 }
933 937
 
934 938
 // peek at the next byte and see if it's a '@', '[', or '{'.
935
-func isDotPiperChar(c byte) bool {
936
-	return !DisableModifiers && (c == '@' || c == '[' || c == '{')
939
+func isDotPiperChar(s string) bool {
940
+	if DisableModifiers {
941
+		return false
942
+	}
943
+	c := s[0]
944
+	if c == '@' {
945
+		// check that the next component is *not* a modifier.
946
+		i := 1
947
+		for ; i < len(s); i++ {
948
+			if s[i] == '.' || s[i] == '|' || s[i] == ':' {
949
+				break
950
+			}
951
+		}
952
+		_, ok := modifiers[s[1:i]]
953
+		return ok
954
+	}
955
+	return c == '[' || c == '{'
937 956
 }
938 957
 
939 958
 type objectPathResult struct {
@@ -955,7 +974,7 @@ func parseObjectPath(path string) (r objectPathResult) {
955 974
 		}
956 975
 		if path[i] == '.' {
957 976
 			r.part = path[:i]
958
-			if i < len(path)-1 && isDotPiperChar(path[i+1]) {
977
+			if i < len(path)-1 && isDotPiperChar(path[i+1:]) {
959 978
 				r.pipe = path[i+1:]
960 979
 				r.piped = true
961 980
 			} else {
@@ -985,7 +1004,7 @@ func parseObjectPath(path string) (r objectPathResult) {
985 1004
 						continue
986 1005
 					} else if path[i] == '.' {
987 1006
 						r.part = string(epart)
988
-						if i < len(path)-1 && isDotPiperChar(path[i+1]) {
1007
+						if i < len(path)-1 && isDotPiperChar(path[i+1:]) {
989 1008
 							r.pipe = path[i+1:]
990 1009
 							r.piped = true
991 1010
 						} else {
@@ -1819,17 +1838,64 @@ func isSimpleName(component string) bool {
1819 1838
 	return true
1820 1839
 }
1821 1840
 
1822
-func appendJSONString(dst []byte, s string) []byte {
1841
+var hexchars = [...]byte{
1842
+	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
1843
+	'a', 'b', 'c', 'd', 'e', 'f',
1844
+}
1845
+
1846
+func appendHex16(dst []byte, x uint16) []byte {
1847
+	return append(dst,
1848
+		hexchars[x>>12&0xF], hexchars[x>>8&0xF],
1849
+		hexchars[x>>4&0xF], hexchars[x>>0&0xF],
1850
+	)
1851
+}
1852
+
1853
+// AppendJSONString is a convenience function that converts the provided string
1854
+// to a valid JSON string and appends it to dst.
1855
+func AppendJSONString(dst []byte, s string) []byte {
1856
+	dst = append(dst, make([]byte, len(s)+2)...)
1857
+	dst = append(dst[:len(dst)-len(s)-2], '"')
1823 1858
 	for i := 0; i < len(s); i++ {
1824
-		if s[i] < ' ' || s[i] == '\\' || s[i] == '"' || s[i] > 126 {
1825
-			d, _ := json.Marshal(s)
1826
-			return append(dst, string(d)...)
1859
+		if s[i] < ' ' {
1860
+			dst = append(dst, '\\')
1861
+			switch s[i] {
1862
+			case '\n':
1863
+				dst = append(dst, 'n')
1864
+			case '\r':
1865
+				dst = append(dst, 'r')
1866
+			case '\t':
1867
+				dst = append(dst, 't')
1868
+			default:
1869
+				dst = append(dst, 'u')
1870
+				dst = appendHex16(dst, uint16(s[i]))
1871
+			}
1872
+		} else if s[i] == '>' || s[i] == '<' || s[i] == '&' {
1873
+			dst = append(dst, '\\', 'u')
1874
+			dst = appendHex16(dst, uint16(s[i]))
1875
+		} else if s[i] == '\\' {
1876
+			dst = append(dst, '\\', '\\')
1877
+		} else if s[i] == '"' {
1878
+			dst = append(dst, '\\', '"')
1879
+		} else if s[i] > 127 {
1880
+			// read utf8 character
1881
+			r, n := utf8.DecodeRuneInString(s[i:])
1882
+			if n == 0 {
1883
+				break
1884
+			}
1885
+			if r == utf8.RuneError && n == 1 {
1886
+				dst = append(dst, `\ufffd`...)
1887
+			} else if r == '\u2028' || r == '\u2029' {
1888
+				dst = append(dst, `\u202`...)
1889
+				dst = append(dst, hexchars[r&0xF])
1890
+			} else {
1891
+				dst = append(dst, s[i:i+n]...)
1892
+			}
1893
+			i = i + n - 1
1894
+		} else {
1895
+			dst = append(dst, s[i])
1827 1896
 		}
1828 1897
 	}
1829
-	dst = append(dst, '"')
1830
-	dst = append(dst, s...)
1831
-	dst = append(dst, '"')
1832
-	return dst
1898
+	return append(dst, '"')
1833 1899
 }
1834 1900
 
1835 1901
 type parseContext struct {
@@ -1919,14 +1985,14 @@ func Get(json, path string) Result {
1919 1985
 									if sub.name[0] == '"' && Valid(sub.name) {
1920 1986
 										b = append(b, sub.name...)
1921 1987
 									} else {
1922
-										b = appendJSONString(b, sub.name)
1988
+										b = AppendJSONString(b, sub.name)
1923 1989
 									}
1924 1990
 								} else {
1925 1991
 									last := nameOfLast(sub.path)
1926 1992
 									if isSimpleName(last) {
1927
-										b = appendJSONString(b, last)
1993
+										b = AppendJSONString(b, last)
1928 1994
 									} else {
1929
-										b = appendJSONString(b, "_")
1995
+										b = AppendJSONString(b, "_")
1930 1996
 									}
1931 1997
 								}
1932 1998
 								b = append(b, ':')
@@ -2669,6 +2735,9 @@ var modifiers = map[string]func(json, arg string) string{
2669 2735
 	"valid":   modValid,
2670 2736
 	"keys":    modKeys,
2671 2737
 	"values":  modValues,
2738
+	"tostr":   modToStr,
2739
+	"fromstr": modFromStr,
2740
+	"group":   modGroup,
2672 2741
 }
2673 2742
 
2674 2743
 // AddModifier binds a custom modifier command to the GJSON syntax.
@@ -2954,6 +3023,56 @@ func modValid(json, arg string) string {
2954 3023
 	return json
2955 3024
 }
2956 3025
 
3026
+// @fromstr converts a string to json
3027
+//   "{\"id\":1023,\"name\":\"alert\"}" -> {"id":1023,"name":"alert"}
3028
+func modFromStr(json, arg string) string {
3029
+	if !Valid(json) {
3030
+		return ""
3031
+	}
3032
+	return Parse(json).String()
3033
+}
3034
+
3035
+// @tostr converts a string to json
3036
+//   {"id":1023,"name":"alert"} -> "{\"id\":1023,\"name\":\"alert\"}"
3037
+func modToStr(str, arg string) string {
3038
+	return string(AppendJSONString(nil, str))
3039
+}
3040
+
3041
+func modGroup(json, arg string) string {
3042
+	res := Parse(json)
3043
+	if !res.IsObject() {
3044
+		return ""
3045
+	}
3046
+	var all [][]byte
3047
+	res.ForEach(func(key, value Result) bool {
3048
+		if !value.IsArray() {
3049
+			return true
3050
+		}
3051
+		var idx int
3052
+		value.ForEach(func(_, value Result) bool {
3053
+			if idx == len(all) {
3054
+				all = append(all, []byte{})
3055
+			}
3056
+			all[idx] = append(all[idx], ("," + key.Raw + ":" + value.Raw)...)
3057
+			idx++
3058
+			return true
3059
+		})
3060
+		return true
3061
+	})
3062
+	var data []byte
3063
+	data = append(data, '[')
3064
+	for i, item := range all {
3065
+		if i > 0 {
3066
+			data = append(data, ',')
3067
+		}
3068
+		data = append(data, '{')
3069
+		data = append(data, item[1:]...)
3070
+		data = append(data, '}')
3071
+	}
3072
+	data = append(data, ']')
3073
+	return string(data)
3074
+}
3075
+
2957 3076
 // stringHeader instead of reflect.StringHeader
2958 3077
 type stringHeader struct {
2959 3078
 	data unsafe.Pointer
@@ -3088,6 +3207,20 @@ func revSquash(json string) string {
3088 3207
 	return json
3089 3208
 }
3090 3209
 
3210
+// Paths returns the original GJSON paths for a Result where the Result came
3211
+// from a simple query path that returns an array, like:
3212
+//
3213
+//    gjson.Get(json, "friends.#.first")
3214
+//
3215
+// The returned value will be in the form of a JSON array:
3216
+//
3217
+//    ["friends.0.first","friends.1.first","friends.2.first"]
3218
+//
3219
+// The param 'json' must be the original JSON used when calling Get.
3220
+//
3221
+// Returns an empty string if the paths cannot be determined, which can happen
3222
+// when the Result came from a path that contained a multipath, modifier,
3223
+// or a nested query.
3091 3224
 func (t Result) Paths(json string) []string {
3092 3225
 	if t.Indexes == nil {
3093 3226
 		return nil
@@ -3103,8 +3236,20 @@ func (t Result) Paths(json string) []string {
3103 3236
 	return paths
3104 3237
 }
3105 3238
 
3106
-// Path returns the original GJSON path for Result.
3107
-// The json param must be the original JSON used when calling Get.
3239
+// Path returns the original GJSON path for a Result where the Result came
3240
+// from a simple path that returns a single value, like:
3241
+//
3242
+//    gjson.Get(json, "friends.#(last=Murphy)")
3243
+//
3244
+// The returned value will be in the form of a JSON string:
3245
+//
3246
+//    "friends.0"
3247
+//
3248
+// The param 'json' must be the original JSON used when calling Get.
3249
+//
3250
+// Returns an empty string if the paths cannot be determined, which can happen
3251
+// when the Result came from a path that contained a multipath, modifier,
3252
+// or a nested query.
3108 3253
 func (t Result) Path(json string) string {
3109 3254
 	var path []byte
3110 3255
 	var comps []string // raw components

+ 5
- 6
vendor/modules.txt View File

@@ -45,14 +45,13 @@ github.com/okzk/sdnotify
45 45
 ## explicit
46 46
 # github.com/stretchr/testify v1.4.0
47 47
 ## explicit
48
-# github.com/tidwall/btree v1.1.0
49
-## explicit; go 1.16
48
+# github.com/tidwall/btree v1.4.2
49
+## explicit; go 1.18
50 50
 github.com/tidwall/btree
51
-github.com/tidwall/btree/internal
52
-# github.com/tidwall/buntdb v1.2.9
53
-## explicit; go 1.16
51
+# github.com/tidwall/buntdb v1.2.10
52
+## explicit; go 1.18
54 53
 github.com/tidwall/buntdb
55
-# github.com/tidwall/gjson v1.12.1
54
+# github.com/tidwall/gjson v1.14.3
56 55
 ## explicit; go 1.12
57 56
 github.com/tidwall/gjson
58 57
 # github.com/tidwall/grect v0.1.4

Loading…
Cancel
Save