@@ -77,12 +77,13 @@ function ancestors(
7777
7878 # Change the filtering function if we also want to remove nodes with nothing values.
7979 filter_fun_ = filter_fun_nothing (filter_fun, ignore_nothing, key)
80+ use_no_filter = no_node_filters (scale, symbol, link, filter_fun_)
8081
8182 val = Array {type,1} ()
8283 # Put the recursivity level into an array so it is mutable in-place:
8384
8485 if self
85- if is_filtered (node, scale, symbol, link, filter_fun_)
86+ if use_no_filter || is_filtered (node, scale, symbol, link, filter_fun_)
8687 val_ = unsafe_getindex (node, key)
8788 push! (val, val_)
8889 elseif ! all
@@ -91,31 +92,47 @@ function ancestors(
9192 end
9293 end
9394
94- ancestors_ (node, key, scale, symbol, link, all, filter_fun, val, recursivity_level)
95+ if use_no_filter
96+ ancestors_values_no_filter! (node, key, val, recursivity_level)
97+ else
98+ ancestors_values! (node, key, scale, symbol, link, all, filter_fun_, val, recursivity_level)
99+ end
95100 return val
96101end
97102
98103
99- function ancestors_ (node, key, scale, symbol, link, all, filter_fun, val, recursivity_level)
100-
101- if ! isroot (node) && recursivity_level != 0
102- parent_ = parent (node)
104+ function ancestors_values! (node, key, scale, symbol, link, all, filter_fun, val, recursivity_level)
105+ current = node
106+ remaining = recursivity_level
103107
104- # Is there any filter happening for the current node? (FALSE if filtered out):
108+ while ! isroot (current) && remaining != 0
109+ parent_ = parent (current)
105110 keep = is_filtered (parent_, scale, symbol, link, filter_fun)
106111
107112 if keep
108- val_ = unsafe_getindex (parent_, key)
109- push! (val, val_)
113+ push! (val, unsafe_getindex (parent_, key))
110114 # Only decrement the recursivity level when the current node is not filtered-out
111- recursivity_level -= 1
115+ remaining -= 1
112116 end
113117
114118 # If we want to continue even if the current node is filtered-out
115- if all || keep
116- ancestors_ (parent_, key, scale, symbol, link, all, filter_fun, val, recursivity_level)
117- end
119+ (all || keep) || break
120+ current = parent_
121+ end
122+ return val
123+ end
124+
125+ function ancestors_values_no_filter! (node, key, val, recursivity_level)
126+ current = node
127+ remaining = recursivity_level
128+
129+ while ! isroot (current) && remaining != 0
130+ parent_ = parent (current)
131+ push! (val, unsafe_getindex (parent_, key))
132+ remaining -= 1
133+ current = parent_
118134 end
135+ return val
119136end
120137
121138# Version that returns the nodes instead of the values:
@@ -133,41 +150,123 @@ function ancestors(
133150 # Check the filters once, and then compute the ancestors recursively using `ancestors_`
134151 check_filters (node, scale= scale, symbol= symbol, link= link)
135152
136- # Change the filtering function if we also want to remove nodes with nothing values.
153+ use_no_filter = no_node_filters (scale, symbol, link, filter_fun)
137154 val = Array {typeof(node),1} ()
138155 # Put the recursivity level into an array so it is mutable in-place:
139156
140157 if self
141- if is_filtered (node, scale, symbol, link, filter_fun)
158+ if use_no_filter || is_filtered (node, scale, symbol, link, filter_fun)
142159 push! (val, node)
143160 elseif ! all
144161 # We don't keep the value and we have to stop at the first filtered-out value
145162 return val
146163 end
147164 end
148165
149- ancestors_ (node, scale, symbol, link, all, filter_fun, val, recursivity_level)
166+ if use_no_filter
167+ ancestors_nodes_no_filter! (node, val, recursivity_level)
168+ else
169+ ancestors_nodes! (node, scale, symbol, link, all, filter_fun, val, recursivity_level)
170+ end
150171 return val
151172end
152173
153174
154- function ancestors_ (node, scale, symbol, link, all, filter_fun, val, recursivity_level)
155-
156- if ! isroot (node) && recursivity_level != 0
157- parent_ = parent (node)
175+ function ancestors_nodes! (node, scale, symbol, link, all, filter_fun, val, recursivity_level)
176+ current = node
177+ remaining = recursivity_level
158178
159- # Is there any filter happening for the current node? (FALSE if filtered out):
179+ while ! isroot (current) && remaining != 0
180+ parent_ = parent (current)
160181 keep = is_filtered (parent_, scale, symbol, link, filter_fun)
161182
162183 if keep
163184 push! (val, parent_)
164185 # Only decrement the recursivity level when the current node is not filtered-out
165- recursivity_level -= 1
186+ remaining -= 1
166187 end
167188
168189 # If we want to continue even if the current node is filtered-out
169- if all || keep
170- ancestors_ (parent_, scale, symbol, link, all, filter_fun, val, recursivity_level)
190+ (all || keep) || break
191+ current = parent_
192+ end
193+ return val
194+ end
195+
196+ function ancestors_nodes_no_filter! (node, val, recursivity_level)
197+ current = node
198+ remaining = recursivity_level
199+
200+ while ! isroot (current) && remaining != 0
201+ parent_ = parent (current)
202+ push! (val, parent_)
203+ remaining -= 1
204+ current = parent_
205+ end
206+ return val
207+ end
208+
209+ function ancestors! (
210+ out:: AbstractVector ,
211+ node, key;
212+ scale= nothing ,
213+ symbol= nothing ,
214+ link= nothing ,
215+ all:: Bool = true ,
216+ self= false ,
217+ filter_fun= nothing ,
218+ recursivity_level= - 1 ,
219+ ignore_nothing= false ,
220+ type:: Union{Union,DataType} = Any,
221+ )
222+ check_filters (node, scale= scale, symbol= symbol, link= link)
223+ filter_fun_ = filter_fun_nothing (filter_fun, ignore_nothing, key)
224+ use_no_filter = no_node_filters (scale, symbol, link, filter_fun_)
225+
226+ empty! (out)
227+ if self
228+ if use_no_filter || is_filtered (node, scale, symbol, link, filter_fun_)
229+ push! (out, unsafe_getindex (node, key))
230+ elseif ! all
231+ return out
232+ end
233+ end
234+
235+ if use_no_filter
236+ ancestors_values_no_filter! (node, key, out, recursivity_level)
237+ else
238+ ancestors_values! (node, key, scale, symbol, link, all, filter_fun_, out, recursivity_level)
239+ end
240+ return out
241+ end
242+
243+ function ancestors! (
244+ out:: AbstractVector ,
245+ node;
246+ scale= nothing ,
247+ symbol= nothing ,
248+ link= nothing ,
249+ all:: Bool = true ,
250+ self= false ,
251+ filter_fun= nothing ,
252+ recursivity_level= - 1 ,
253+ )
254+ check_filters (node, scale= scale, symbol= symbol, link= link)
255+ use_no_filter = no_node_filters (scale, symbol, link, filter_fun)
256+
257+ empty! (out)
258+ if self
259+ if use_no_filter || is_filtered (node, scale, symbol, link, filter_fun)
260+ push! (out, node)
261+ elseif ! all
262+ return out
171263 end
172264 end
265+
266+ if use_no_filter
267+ ancestors_nodes_no_filter! (node, out, recursivity_level)
268+ else
269+ ancestors_nodes! (node, scale, symbol, link, all, filter_fun, out, recursivity_level)
270+ end
271+ return out
173272end
0 commit comments