123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- package iradix
- import (
- "bytes"
- )
- // ReverseIterator is used to iterate over a set of nodes
- // in reverse in-order
- type ReverseIterator struct {
- i *Iterator
- // expandedParents stores the set of parent nodes whose relevant children have
- // already been pushed into the stack. This can happen during seek or during
- // iteration.
- //
- // Unlike forward iteration we need to recurse into children before we can
- // output the value stored in an internal leaf since all children are greater.
- // We use this to track whether we have already ensured all the children are
- // in the stack.
- expandedParents map[*Node]struct{}
- }
- // NewReverseIterator returns a new ReverseIterator at a node
- func NewReverseIterator(n *Node) *ReverseIterator {
- return &ReverseIterator{
- i: &Iterator{node: n},
- }
- }
- // SeekPrefixWatch is used to seek the iterator to a given prefix
- // and returns the watch channel of the finest granularity
- func (ri *ReverseIterator) SeekPrefixWatch(prefix []byte) (watch <-chan struct{}) {
- return ri.i.SeekPrefixWatch(prefix)
- }
- // SeekPrefix is used to seek the iterator to a given prefix
- func (ri *ReverseIterator) SeekPrefix(prefix []byte) {
- ri.i.SeekPrefixWatch(prefix)
- }
- // SeekReverseLowerBound is used to seek the iterator to the largest key that is
- // lower or equal to the given key. There is no watch variant as it's hard to
- // predict based on the radix structure which node(s) changes might affect the
- // result.
- func (ri *ReverseIterator) SeekReverseLowerBound(key []byte) {
- // Wipe the stack. Unlike Prefix iteration, we need to build the stack as we
- // go because we need only a subset of edges of many nodes in the path to the
- // leaf with the lower bound. Note that the iterator will still recurse into
- // children that we don't traverse on the way to the reverse lower bound as it
- // walks the stack.
- ri.i.stack = []edges{}
- // ri.i.node starts off in the common case as pointing to the root node of the
- // tree. By the time we return we have either found a lower bound and setup
- // the stack to traverse all larger keys, or we have not and the stack and
- // node should both be nil to prevent the iterator from assuming it is just
- // iterating the whole tree from the root node. Either way this needs to end
- // up as nil so just set it here.
- n := ri.i.node
- ri.i.node = nil
- search := key
- if ri.expandedParents == nil {
- ri.expandedParents = make(map[*Node]struct{})
- }
- found := func(n *Node) {
- ri.i.stack = append(ri.i.stack, edges{edge{node: n}})
- // We need to mark this node as expanded in advance too otherwise the
- // iterator will attempt to walk all of its children even though they are
- // greater than the lower bound we have found. We've expanded it in the
- // sense that all of its children that we want to walk are already in the
- // stack (i.e. none of them).
- ri.expandedParents[n] = struct{}{}
- }
- for {
- // Compare current prefix with the search key's same-length prefix.
- var prefixCmp int
- if len(n.prefix) < len(search) {
- prefixCmp = bytes.Compare(n.prefix, search[0:len(n.prefix)])
- } else {
- prefixCmp = bytes.Compare(n.prefix, search)
- }
- if prefixCmp < 0 {
- // Prefix is smaller than search prefix, that means there is no exact
- // match for the search key. But we are looking in reverse, so the reverse
- // lower bound will be the largest leaf under this subtree, since it is
- // the value that would come right before the current search key if it
- // were in the tree. So we need to follow the maximum path in this subtree
- // to find it. Note that this is exactly what the iterator will already do
- // if it finds a node in the stack that has _not_ been marked as expanded
- // so in this one case we don't call `found` and instead let the iterator
- // do the expansion and recursion through all the children.
- ri.i.stack = append(ri.i.stack, edges{edge{node: n}})
- return
- }
- if prefixCmp > 0 {
- // Prefix is larger than search prefix, or there is no prefix but we've
- // also exhausted the search key. Either way, that means there is no
- // reverse lower bound since nothing comes before our current search
- // prefix.
- return
- }
- // If this is a leaf, something needs to happen! Note that if it's a leaf
- // and prefixCmp was zero (which it must be to get here) then the leaf value
- // is either an exact match for the search, or it's lower. It can't be
- // greater.
- if n.isLeaf() {
- // Firstly, if it's an exact match, we're done!
- if bytes.Equal(n.leaf.key, key) {
- found(n)
- return
- }
- // It's not so this node's leaf value must be lower and could still be a
- // valid contender for reverse lower bound.
- // If it has no children then we are also done.
- if len(n.edges) == 0 {
- // This leaf is the lower bound.
- found(n)
- return
- }
- // Finally, this leaf is internal (has children) so we'll keep searching,
- // but we need to add it to the iterator's stack since it has a leaf value
- // that needs to be iterated over. It needs to be added to the stack
- // before its children below as it comes first.
- ri.i.stack = append(ri.i.stack, edges{edge{node: n}})
- // We also need to mark it as expanded since we'll be adding any of its
- // relevant children below and so don't want the iterator to re-add them
- // on its way back up the stack.
- ri.expandedParents[n] = struct{}{}
- }
- // Consume the search prefix. Note that this is safe because if n.prefix is
- // longer than the search slice prefixCmp would have been > 0 above and the
- // method would have already returned.
- search = search[len(n.prefix):]
- if len(search) == 0 {
- // We've exhausted the search key but we are not at a leaf. That means all
- // children are greater than the search key so a reverse lower bound
- // doesn't exist in this subtree. Note that there might still be one in
- // the whole radix tree by following a different path somewhere further
- // up. If that's the case then the iterator's stack will contain all the
- // smaller nodes already and Previous will walk through them correctly.
- return
- }
- // Otherwise, take the lower bound next edge.
- idx, lbNode := n.getLowerBoundEdge(search[0])
- // From here, we need to update the stack with all values lower than
- // the lower bound edge. Since getLowerBoundEdge() returns -1 when the
- // search prefix is larger than all edges, we need to place idx at the
- // last edge index so they can all be place in the stack, since they
- // come before our search prefix.
- if idx == -1 {
- idx = len(n.edges)
- }
- // Create stack edges for the all strictly lower edges in this node.
- if len(n.edges[:idx]) > 0 {
- ri.i.stack = append(ri.i.stack, n.edges[:idx])
- }
- // Exit if there's no lower bound edge. The stack will have the previous
- // nodes already.
- if lbNode == nil {
- return
- }
- // Recurse
- n = lbNode
- }
- }
- // Previous returns the previous node in reverse order
- func (ri *ReverseIterator) Previous() ([]byte, interface{}, bool) {
- // Initialize our stack if needed
- if ri.i.stack == nil && ri.i.node != nil {
- ri.i.stack = []edges{
- {
- edge{node: ri.i.node},
- },
- }
- }
- if ri.expandedParents == nil {
- ri.expandedParents = make(map[*Node]struct{})
- }
- for len(ri.i.stack) > 0 {
- // Inspect the last element of the stack
- n := len(ri.i.stack)
- last := ri.i.stack[n-1]
- m := len(last)
- elem := last[m-1].node
- _, alreadyExpanded := ri.expandedParents[elem]
- // If this is an internal node and we've not seen it already, we need to
- // leave it in the stack so we can return its possible leaf value _after_
- // we've recursed through all its children.
- if len(elem.edges) > 0 && !alreadyExpanded {
- // record that we've seen this node!
- ri.expandedParents[elem] = struct{}{}
- // push child edges onto stack and skip the rest of the loop to recurse
- // into the largest one.
- ri.i.stack = append(ri.i.stack, elem.edges)
- continue
- }
- // Remove the node from the stack
- if m > 1 {
- ri.i.stack[n-1] = last[:m-1]
- } else {
- ri.i.stack = ri.i.stack[:n-1]
- }
- // We don't need this state any more as it's no longer in the stack so we
- // won't visit it again
- if alreadyExpanded {
- delete(ri.expandedParents, elem)
- }
- // If this is a leaf, return it
- if elem.leaf != nil {
- return elem.leaf.key, elem.leaf.val, true
- }
- // it's not a leaf so keep walking the stack to find the previous leaf
- }
- return nil, nil, false
- }
|