Skip to content

Commit 826af9c

Browse files
committed
add regular seek
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
1 parent 8aac270 commit 826af9c

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

node.go

+60
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,66 @@ func (n *Node) WalkPath(path []byte, fn WalkFn) {
274274
}
275275
}
276276

277+
func (n *Node) Seek(prefix []byte) *Seeker {
278+
search := prefix
279+
p := &pos{n: n}
280+
for {
281+
// Check for key exhaution
282+
if len(search) == 0 {
283+
return &Seeker{p}
284+
}
285+
286+
num := len(n.edges)
287+
idx := sort.Search(num, func(i int) bool {
288+
return n.edges[i].label >= search[0]
289+
})
290+
p.current = idx
291+
if idx < len(n.edges) {
292+
n = n.edges[idx].node
293+
if bytes.HasPrefix(search, n.prefix) && len(n.edges) > 0 {
294+
search = search[len(n.prefix):]
295+
p.current++
296+
p = &pos{n: n, prev: p}
297+
continue
298+
}
299+
}
300+
p.current++
301+
return &Seeker{p}
302+
}
303+
}
304+
305+
type Seeker struct {
306+
*pos
307+
}
308+
309+
type pos struct {
310+
n *Node
311+
current int
312+
prev *pos
313+
isLeaf bool
314+
}
315+
316+
func (s *Seeker) Next() (k []byte, v interface{}, ok bool) {
317+
if s.current >= len(s.n.edges) {
318+
if s.prev == nil {
319+
return nil, nil, false
320+
}
321+
s.pos = s.prev
322+
return s.Next()
323+
}
324+
325+
edge := s.n.edges[s.current]
326+
s.current++
327+
if edge.node.leaf != nil && !s.isLeaf {
328+
s.isLeaf = true
329+
s.current--
330+
return edge.node.leaf.key, edge.node.leaf.val, true
331+
}
332+
s.isLeaf = false
333+
s.pos = &pos{n: edge.node, prev: s.pos}
334+
return s.Next()
335+
}
336+
277337
// recursiveWalk is used to do a pre-order walk of a node
278338
// recursively. Returns true if the walk should be aborted
279339
func recursiveWalk(n *Node, fn WalkFn) bool {

0 commit comments

Comments
 (0)