-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathiterator.go
97 lines (85 loc) · 2.71 KB
/
iterator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package lmdb
import (
"bytes"
mdb "github.com/libreoscar/gomdb"
)
// In a write txn, iterator will be closed automatically when the txn commits/aborts, but in a
// read txn, they must be closed explicitly. Thus the best practice is to close them all explicitly
// before txn ends.
//
// Attention:
// The bytes returned from GetNoCopy() are memory-mapped database contents, DO NOT modify them.
type Iterator mdb.Cursor
func (itr *Iterator) Close() {
(*mdb.Cursor)(itr).Close() // Possible errors: Iterator already closed (ignored)
}
func (itr *Iterator) SeekFirst() bool {
_, _, err := (*mdb.Cursor)(itr).GetVal(nil, nil, mdb.FIRST)
if err != nil && err != mdb.NotFound {
panic(err)
}
return err == nil
}
func (itr *Iterator) SeekLast() bool {
_, _, err := (*mdb.Cursor)(itr).GetVal(nil, nil, mdb.LAST)
if err != nil && err != mdb.NotFound {
panic(err)
}
return err == nil
}
// If current position is the first element, Prev() returns false, and stays its current position.
func (itr *Iterator) Prev() bool {
_, _, err := (*mdb.Cursor)(itr).GetVal(nil, nil, mdb.PREV)
if err != nil && err != mdb.NotFound {
panic(err)
}
return err == nil
}
// If current position is the last element, Next() returns false, and stays its current position.
func (itr *Iterator) Next() bool {
_, _, err := (*mdb.Cursor)(itr).GetVal(nil, nil, mdb.NEXT)
if err != nil && err != mdb.NotFound {
panic(err)
}
return err == nil
}
// Position at the key that matches {k} exactly
func (itr *Iterator) SeekExact(k []byte) bool {
key, _, err := (*mdb.Cursor)(itr).GetVal(k, nil, mdb.SET_RANGE)
if err != nil && err != mdb.NotFound {
panic(err)
}
return err == nil && bytes.Equal(key.BytesNoCopy(), k)
}
// Position at first key greater than or equal to specified key.
func (itr *Iterator) SeekGE(k []byte) bool {
_, _, err := (*mdb.Cursor)(itr).GetVal(k, nil, mdb.SET_RANGE)
if err != nil && err != mdb.NotFound {
panic(err)
}
return err == nil
}
// Position at first key that has the specified prefix
func (itr *Iterator) SeekByPrefix(prefix []byte) bool {
key, _, err := (*mdb.Cursor)(itr).GetVal(prefix, nil, mdb.SET_RANGE)
if err != nil && err != mdb.NotFound {
panic(err)
}
return err == nil && bytes.HasPrefix(key.BytesNoCopy(), prefix)
}
// Returns (key, value) pair.
func (itr *Iterator) Get() ([]byte, []byte) {
key, val, err := (*mdb.Cursor)(itr).GetVal(nil, nil, mdb.GET_CURRENT)
if err != nil {
panic(err)
}
return key.Bytes(), val.Bytes()
}
// Returns (key, value) pair. DO NOT modify them in-place, make a copy instead.
func (itr *Iterator) GetNoCopy() ([]byte, []byte) {
key, val, err := (*mdb.Cursor)(itr).GetVal(nil, nil, mdb.GET_CURRENT)
if err != nil {
panic(err)
}
return key.BytesNoCopy(), val.BytesNoCopy()
}