113 lines
1.8 KiB
Go
113 lines
1.8 KiB
Go
package internal
|
|
|
|
import (
|
|
"bytes"
|
|
|
|
"github.com/boltdb/bolt"
|
|
)
|
|
|
|
// Cursor that can be reversed
|
|
type Cursor struct {
|
|
C *bolt.Cursor
|
|
Reverse bool
|
|
}
|
|
|
|
// First element
|
|
func (c *Cursor) First() ([]byte, []byte) {
|
|
if c.Reverse {
|
|
return c.C.Last()
|
|
}
|
|
|
|
return c.C.First()
|
|
}
|
|
|
|
// Next element
|
|
func (c *Cursor) Next() ([]byte, []byte) {
|
|
if c.Reverse {
|
|
return c.C.Prev()
|
|
}
|
|
|
|
return c.C.Next()
|
|
}
|
|
|
|
// RangeCursor that can be reversed
|
|
type RangeCursor struct {
|
|
C *bolt.Cursor
|
|
Reverse bool
|
|
Min []byte
|
|
Max []byte
|
|
CompareFn func([]byte, []byte) int
|
|
}
|
|
|
|
// First element
|
|
func (c *RangeCursor) First() ([]byte, []byte) {
|
|
if c.Reverse {
|
|
return c.C.Seek(c.Max)
|
|
}
|
|
|
|
return c.C.Seek(c.Min)
|
|
}
|
|
|
|
// Next element
|
|
func (c *RangeCursor) Next() ([]byte, []byte) {
|
|
if c.Reverse {
|
|
return c.C.Prev()
|
|
}
|
|
|
|
return c.C.Next()
|
|
}
|
|
|
|
// Continue tells if the loop needs to continue
|
|
func (c *RangeCursor) Continue(val []byte) bool {
|
|
if c.Reverse {
|
|
return val != nil && c.CompareFn(val, c.Min) >= 0
|
|
}
|
|
|
|
return val != nil && c.CompareFn(val, c.Max) <= 0
|
|
}
|
|
|
|
// PrefixCursor that can be reversed
|
|
type PrefixCursor struct {
|
|
C *bolt.Cursor
|
|
Reverse bool
|
|
Prefix []byte
|
|
}
|
|
|
|
// First element
|
|
func (c *PrefixCursor) First() ([]byte, []byte) {
|
|
var k, v []byte
|
|
|
|
for k, v = c.C.First(); k != nil && !bytes.HasPrefix(k, c.Prefix); k, v = c.C.Next() {
|
|
}
|
|
|
|
if k == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
if c.Reverse {
|
|
kc, vc := k, v
|
|
for ; kc != nil && bytes.HasPrefix(kc, c.Prefix); kc, vc = c.C.Next() {
|
|
k, v = kc, vc
|
|
}
|
|
if kc != nil {
|
|
k, v = c.C.Prev()
|
|
}
|
|
}
|
|
|
|
return k, v
|
|
}
|
|
|
|
// Next element
|
|
func (c *PrefixCursor) Next() ([]byte, []byte) {
|
|
if c.Reverse {
|
|
return c.C.Prev()
|
|
}
|
|
|
|
return c.C.Next()
|
|
}
|
|
|
|
// Continue tells if the loop needs to continue
|
|
func (c *PrefixCursor) Continue(val []byte) bool {
|
|
return val != nil && bytes.HasPrefix(val, c.Prefix)
|
|
}
|