diff --git a/btree.go b/btree.go index 969b910..194725a 100644 --- a/btree.go +++ b/btree.go @@ -504,13 +504,18 @@ const ( // "greaterThan" or "lessThan" queries. func (n *node) iterate(dir direction, start, stop Item, includeStart bool, hit bool, iter ItemIterator) (bool, bool) { var ok, found bool - var index int + var index, stopIndex int switch dir { case ascend: if start != nil { index, _ = n.items.find(start) } - for i := index; i < len(n.items); i++ { + if stop != nil { + stopIndex, _ = n.items.find(stop) + } else { + stopIndex = len(n.items) + } + for i := index; i < stopIndex; i++ { if len(n.children) > 0 { if hit, ok = n.children[i].iterate(dir, start, stop, includeStart, hit, iter); !ok { return hit, false @@ -521,15 +526,12 @@ func (n *node) iterate(dir direction, start, stop Item, includeStart bool, hit b continue } hit = true - if stop != nil && !n.items[i].Less(stop) { - return hit, false - } if !iter(n.items[i]) { return hit, false } } if len(n.children) > 0 { - if hit, ok = n.children[len(n.children)-1].iterate(dir, start, stop, includeStart, hit, iter); !ok { + if hit, ok = n.children[stopIndex].iterate(dir, start, stop, includeStart, hit, iter); !ok { return hit, false } } @@ -542,6 +544,16 @@ func (n *node) iterate(dir direction, start, stop Item, includeStart bool, hit b } else { index = len(n.items) - 1 } + + if stop != nil { + stopIndex, found = n.items.find(stop) + if found { + stopIndex += 1 + } + } else { + stopIndex = 0 + } + for i := index; i >= 0; i-- { if start != nil && !n.items[i].Less(start) { if !includeStart || hit || start.Less(n.items[i]) { @@ -562,7 +574,7 @@ func (n *node) iterate(dir direction, start, stop Item, includeStart bool, hit b } } if len(n.children) > 0 { - if hit, ok = n.children[0].iterate(dir, start, stop, includeStart, hit, iter); !ok { + if hit, ok = n.children[stopIndex].iterate(dir, start, stop, includeStart, hit, iter); !ok { return hit, false } } diff --git a/btree_generic.go b/btree_generic.go index e44a0f4..713b1ae 100644 --- a/btree_generic.go +++ b/btree_generic.go @@ -499,13 +499,18 @@ func empty[T any]() optionalItem[T] { // "greaterThan" or "lessThan" queries. func (n *node[T]) iterate(dir direction, start, stop optionalItem[T], includeStart bool, hit bool, iter ItemIteratorG[T]) (bool, bool) { var ok, found bool - var index int + var index, stopIndex int switch dir { case ascend: if start.valid { index, _ = n.items.find(start.item, n.cow.less) } - for i := index; i < len(n.items); i++ { + if stop.valid { + stopIndex, _ = n.items.find(stop.item, n.cow.less) + } else { + stopIndex = len(n.items) + } + for i := index; i < stopIndex; i++ { if len(n.children) > 0 { if hit, ok = n.children[i].iterate(dir, start, stop, includeStart, hit, iter); !ok { return hit, false @@ -516,15 +521,12 @@ func (n *node[T]) iterate(dir direction, start, stop optionalItem[T], includeSta continue } hit = true - if stop.valid && !n.cow.less(n.items[i], stop.item) { - return hit, false - } if !iter(n.items[i]) { return hit, false } } if len(n.children) > 0 { - if hit, ok = n.children[len(n.children)-1].iterate(dir, start, stop, includeStart, hit, iter); !ok { + if hit, ok = n.children[stopIndex].iterate(dir, start, stop, includeStart, hit, iter); !ok { return hit, false } } @@ -537,7 +539,15 @@ func (n *node[T]) iterate(dir direction, start, stop optionalItem[T], includeSta } else { index = len(n.items) - 1 } - for i := index; i >= 0; i-- { + if stop.valid { + stopIndex, found = n.items.find(stop.item, n.cow.less) + if found { + stopIndex += 1 + } + } else { + stopIndex = 0 + } + for i := index; i >= stopIndex; i-- { if start.valid && !n.cow.less(n.items[i], start.item) { if !includeStart || hit || n.cow.less(start.item, n.items[i]) { continue @@ -548,16 +558,13 @@ func (n *node[T]) iterate(dir direction, start, stop optionalItem[T], includeSta return hit, false } } - if stop.valid && !n.cow.less(stop.item, n.items[i]) { - return hit, false // continue - } hit = true if !iter(n.items[i]) { return hit, false } } if len(n.children) > 0 { - if hit, ok = n.children[0].iterate(dir, start, stop, includeStart, hit, iter); !ok { + if hit, ok = n.children[stopIndex].iterate(dir, start, stop, includeStart, hit, iter); !ok { return hit, false } }