11package art
22
3+ import "errors"
4+
35// state represents the iteration state during tree traversal.
46type state struct {
57 items []* iteratorContext
68}
79
10+ // push adds a new iterator context to the state.
811func (s * state ) push (ctx * iteratorContext ) {
912 s .items = append (s .items , ctx )
1013}
1114
15+ // current returns the current iterator context and a flag indicating if there is any.
1216func (s * state ) current () (* iteratorContext , bool ) {
1317 if len (s .items ) == 0 {
1418 return nil , false
@@ -17,6 +21,7 @@ func (s *state) current() (*iteratorContext, bool) {
1721 return s .items [len (s .items )- 1 ], true
1822}
1923
24+ // discard removes the last iterator context from the state.
2025func (s * state ) discard () {
2126 if len (s .items ) == 0 {
2227 return
@@ -67,6 +72,7 @@ type iterator struct {
6772// assert that iterator implements the Iterator interface.
6873var _ Iterator = (* iterator )(nil )
6974
75+ // newTreeIterator creates a new tree iterator.
7076func newTreeIterator (tr * tree , opts traverseOpts ) Iterator {
7177 state := & state {}
7278 state .push (newIteratorContext (tr .root , opts .hasReverse ()))
@@ -83,10 +89,15 @@ func newTreeIterator(tr *tree, opts traverseOpts) Iterator {
8389 return it
8490 }
8591
86- return & bufferedIterator {
92+ bit := & bufferedIterator {
8793 opts : opts ,
8894 it : it ,
8995 }
96+
97+ // peek the first node or leaf
98+ bit .peek ()
99+
100+ return bit
90101}
91102
92103// hasConcurrentModification checks if the tree has been modified concurrently.
@@ -148,52 +159,67 @@ type bufferedIterator struct {
148159 nextErr error
149160}
150161
162+ // HasNext returns true if there are more nodes to iterate.
151163func (bit * bufferedIterator ) HasNext () bool {
152- for bit .hasNext () {
153- nxt , err := bit .peek ()
154- if err != nil {
155- return true
156- }
164+ return bit .nextNode != nil
165+ }
157166
158- // are we looking for a leaf node?
159- if bit .hasLeafIterator () && nxt .Kind () == Leaf {
160- return true
161- }
167+ // Next returns the next node or leaf node and an error if any.
168+ // ErrNoMoreNodes is returned if there are no more nodes to iterate.
169+ // ErrConcurrentModification is returned if the tree has been modified concurrently.
170+ func (bit * bufferedIterator ) Next () (Node , error ) {
171+ current := bit .nextNode
162172
163- // are we looking for a non-leaf node?
164- if bit .hasNodeIterator () && nxt .Kind () != Leaf {
165- return true
166- }
173+ if ! bit .HasNext () {
174+ return nil , bit .nextErr
167175 }
168176
169- bit .resetNext ()
177+ bit .peek ()
170178
171- return false
172- }
179+ // ErrConcurrentModification should be returned immediately.
180+ // ErrNoMoreNodes will be return on the next call.
181+ if errors .Is (bit .nextErr , ErrConcurrentModification ) {
182+ return nil , bit .nextErr
183+ }
173184
174- func (bit * bufferedIterator ) Next () (Node , error ) {
175- return bit .nextNode , bit .nextErr
185+ return current , nil
176186}
177187
188+ // hasLeafIterator checks if the iterator is for leaf nodes.
178189func (bit * bufferedIterator ) hasLeafIterator () bool {
179190 return bit .opts & TraverseLeaf == TraverseLeaf
180191}
181192
193+ // hasNodeIterator checks if the iterator is for non-leaf nodes.
182194func (bit * bufferedIterator ) hasNodeIterator () bool {
183195 return bit .opts & TraverseNode == TraverseNode
184196}
185197
186- func (bit * bufferedIterator ) hasNext () bool {
187- return bit .it .HasNext ()
198+ // peek looks for the next node or leaf node to iterate.
199+ func (bit * bufferedIterator ) peek () {
200+ for {
201+ bit .nextNode , bit .nextErr = bit .it .Next ()
202+ if bit .nextErr != nil {
203+ return
204+ }
205+
206+ if bit .matchesFilter () {
207+ return
208+ }
209+ }
188210}
189211
190- func (bit * bufferedIterator ) peek () (Node , error ) {
191- bit .nextNode , bit .nextErr = bit .it .Next ()
212+ // matchesFilter checks if the next node matches the iterator filter.
213+ func (bit * bufferedIterator ) matchesFilter () bool {
214+ // check if the iterator is looking for leaf nodes
215+ if bit .hasLeafIterator () && bit .nextNode .Kind () == Leaf {
216+ return true
217+ }
192218
193- return bit .nextNode , bit .nextErr
194- }
219+ // check if the iterator is looking for non-leaf nodes
220+ if bit .hasNodeIterator () && bit .nextNode .Kind () != Leaf {
221+ return true
222+ }
195223
196- func (bit * bufferedIterator ) resetNext () {
197- bit .nextNode = nil
198- bit .nextErr = nil
224+ return false
199225}
0 commit comments