1
1
package art
2
2
3
+ import "errors"
4
+
3
5
// state represents the iteration state during tree traversal.
4
6
type state struct {
5
7
items []* iteratorContext
6
8
}
7
9
10
+ // push adds a new iterator context to the state.
8
11
func (s * state ) push (ctx * iteratorContext ) {
9
12
s .items = append (s .items , ctx )
10
13
}
11
14
15
+ // current returns the current iterator context and a flag indicating if there is any.
12
16
func (s * state ) current () (* iteratorContext , bool ) {
13
17
if len (s .items ) == 0 {
14
18
return nil , false
@@ -17,6 +21,7 @@ func (s *state) current() (*iteratorContext, bool) {
17
21
return s .items [len (s .items )- 1 ], true
18
22
}
19
23
24
+ // discard removes the last iterator context from the state.
20
25
func (s * state ) discard () {
21
26
if len (s .items ) == 0 {
22
27
return
@@ -67,6 +72,7 @@ type iterator struct {
67
72
// assert that iterator implements the Iterator interface.
68
73
var _ Iterator = (* iterator )(nil )
69
74
75
+ // newTreeIterator creates a new tree iterator.
70
76
func newTreeIterator (tr * tree , opts traverseOpts ) Iterator {
71
77
state := & state {}
72
78
state .push (newIteratorContext (tr .root , opts .hasReverse ()))
@@ -83,10 +89,15 @@ func newTreeIterator(tr *tree, opts traverseOpts) Iterator {
83
89
return it
84
90
}
85
91
86
- return & bufferedIterator {
92
+ bit := & bufferedIterator {
87
93
opts : opts ,
88
94
it : it ,
89
95
}
96
+
97
+ // peek the first node or leaf
98
+ bit .peek ()
99
+
100
+ return bit
90
101
}
91
102
92
103
// hasConcurrentModification checks if the tree has been modified concurrently.
@@ -148,52 +159,67 @@ type bufferedIterator struct {
148
159
nextErr error
149
160
}
150
161
162
+ // HasNext returns true if there are more nodes to iterate.
151
163
func (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
+ }
157
166
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
162
172
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
167
175
}
168
176
169
- bit .resetNext ()
177
+ bit .peek ()
170
178
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
+ }
173
184
174
- func (bit * bufferedIterator ) Next () (Node , error ) {
175
- return bit .nextNode , bit .nextErr
185
+ return current , nil
176
186
}
177
187
188
+ // hasLeafIterator checks if the iterator is for leaf nodes.
178
189
func (bit * bufferedIterator ) hasLeafIterator () bool {
179
190
return bit .opts & TraverseLeaf == TraverseLeaf
180
191
}
181
192
193
+ // hasNodeIterator checks if the iterator is for non-leaf nodes.
182
194
func (bit * bufferedIterator ) hasNodeIterator () bool {
183
195
return bit .opts & TraverseNode == TraverseNode
184
196
}
185
197
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
+ }
188
210
}
189
211
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
+ }
192
218
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
+ }
195
223
196
- func (bit * bufferedIterator ) resetNext () {
197
- bit .nextNode = nil
198
- bit .nextErr = nil
224
+ return false
199
225
}
0 commit comments