github.com/cilium/statedb@v0.3.2/part/iterator.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package part
     5  
     6  import (
     7  	"bytes"
     8  	"slices"
     9  	"sort"
    10  )
    11  
    12  // Iterator for key and value pairs where value is of type T
    13  type Iterator[T any] struct {
    14  	next [][]*header[T] // sets of edges to explore
    15  }
    16  
    17  // Clone returns a copy of the iterator, allowing restarting
    18  // the iterator from scratch.
    19  func (it *Iterator[T]) Clone() *Iterator[T] {
    20  	// Since the iterator does not mutate the edge array elements themselves ([]*header[T])
    21  	// it is enough to do a shallow clone here.
    22  	return &Iterator[T]{slices.Clone(it.next)}
    23  }
    24  
    25  // Next returns the next key, value and true if the value exists,
    26  // otherwise it returns false.
    27  func (it *Iterator[T]) Next() (key []byte, value T, ok bool) {
    28  	for len(it.next) > 0 {
    29  		// Pop the next set of edges to explore
    30  		edges := it.next[len(it.next)-1]
    31  		for len(edges) > 0 && edges[0] == nil {
    32  			// Node256 may have nil children, so jump over them.
    33  			edges = edges[1:]
    34  		}
    35  		it.next = it.next[:len(it.next)-1]
    36  
    37  		if len(edges) == 0 {
    38  			continue
    39  		} else if len(edges) > 1 {
    40  			// More edges remain to be explored, add them back.
    41  			it.next = append(it.next, edges[1:])
    42  		}
    43  
    44  		// Follow the smallest edge and add its children to the queue.
    45  		node := edges[0]
    46  
    47  		if node.size() > 0 {
    48  			it.next = append(it.next, node.children())
    49  		}
    50  		if leaf := node.getLeaf(); leaf != nil {
    51  			key = leaf.key
    52  			value = leaf.value
    53  			ok = true
    54  			return
    55  		}
    56  	}
    57  	return
    58  }
    59  
    60  func newIterator[T any](start *header[T]) *Iterator[T] {
    61  	if start == nil {
    62  		return &Iterator[T]{nil}
    63  	}
    64  	return &Iterator[T]{[][]*header[T]{{start}}}
    65  }
    66  
    67  func prefixSearch[T any](root *header[T], key []byte) (*Iterator[T], <-chan struct{}) {
    68  	this := root
    69  	var watch <-chan struct{}
    70  	for {
    71  		if !this.isLeaf() && this.watch != nil {
    72  			// Leaf watch channels only close when the leaf is manipulated,
    73  			// thus we only return non-leaf watch channels.
    74  			watch = this.watch
    75  		}
    76  
    77  		switch {
    78  		case bytes.Equal(key, this.prefix[:min(len(key), len(this.prefix))]):
    79  			return newIterator(this), watch
    80  
    81  		case bytes.HasPrefix(key, this.prefix):
    82  			key = key[len(this.prefix):]
    83  			if len(key) == 0 {
    84  				return newIterator(this), this.watch
    85  			}
    86  
    87  		default:
    88  			return newIterator[T](nil), root.watch
    89  		}
    90  
    91  		this = this.find(key[0])
    92  		if this == nil {
    93  			return newIterator[T](nil), root.watch
    94  		}
    95  	}
    96  }
    97  
    98  func traverseToMin[T any](n *header[T], edges [][]*header[T]) [][]*header[T] {
    99  	if leaf := n.getLeaf(); leaf != nil {
   100  		return append(edges, []*header[T]{n})
   101  	}
   102  	children := n.children()
   103  
   104  	// Find the first non-nil child
   105  	for len(children) > 0 && children[0] == nil {
   106  		children = children[1:]
   107  	}
   108  
   109  	if len(children) > 0 {
   110  		// Add the larger children.
   111  		if len(children) > 1 {
   112  			edges = append(edges, children[1:])
   113  		}
   114  		// Recurse into the smallest child
   115  		return traverseToMin(children[0], edges)
   116  	}
   117  	return edges
   118  }
   119  
   120  func lowerbound[T any](start *header[T], key []byte) *Iterator[T] {
   121  	// The starting edges to explore. This contains all larger nodes encountered
   122  	// on the path to the node larger or equal to the key.
   123  	edges := [][]*header[T]{}
   124  	this := start
   125  loop:
   126  	for {
   127  		switch bytes.Compare(this.prefix, key[:min(len(key), len(this.prefix))]) {
   128  		case -1:
   129  			// Prefix is smaller, stop here and return an iterator for
   130  			// the larger nodes in the parent's.
   131  			break loop
   132  
   133  		case 0:
   134  			if len(this.prefix) == len(key) {
   135  				// Exact match.
   136  				edges = append(edges, []*header[T]{this})
   137  				break loop
   138  			}
   139  
   140  			// Prefix matches the beginning of the key, but more
   141  			// remains of the key. Drop the matching part and keep
   142  			// going further.
   143  			key = key[len(this.prefix):]
   144  
   145  			if this.kind() == nodeKind256 {
   146  				children := this.node256().children[:]
   147  				idx := int(key[0])
   148  				this = children[idx]
   149  
   150  				// Add all larger children and recurse further.
   151  				children = children[idx+1:]
   152  				for len(children) > 0 && children[0] == nil {
   153  					children = children[1:]
   154  				}
   155  				edges = append(edges, children)
   156  
   157  				if this == nil {
   158  					break loop
   159  				}
   160  			} else {
   161  				children := this.children()
   162  
   163  				// Find the smallest child that is equal or larger than the lower bound
   164  				idx := sort.Search(len(children), func(i int) bool {
   165  					return children[i].prefix[0] >= key[0]
   166  				})
   167  				if idx >= this.size() {
   168  					break loop
   169  				}
   170  				// Add all larger children and recurse further.
   171  				if len(children) > idx+1 {
   172  					edges = append(edges, children[idx+1:])
   173  				}
   174  				this = children[idx]
   175  			}
   176  
   177  		case 1:
   178  			// Prefix bigger than lowerbound, go to smallest node and stop.
   179  			edges = traverseToMin(this, edges)
   180  			break loop
   181  		}
   182  	}
   183  
   184  	if len(edges) > 0 {
   185  		return &Iterator[T]{edges}
   186  	}
   187  	return &Iterator[T]{nil}
   188  }