From c182faba0ddb8a4b2201e9b6e72ac662f9120716 Mon Sep 17 00:00:00 2001 From: Niels Thykier Date: Sat, 17 Feb 2018 14:18:14 +0000 Subject: [PATCH] Rewrite findReferencedElements without recursion A classic "Depth-First-Search via call stack recusion to Depth-First-Search with stack" rewrite. The only thing worth noting is that the nodes with same parent are visited in opposite order than originally. While trivially fixable, none of the callers appear to rely on the order for anything at all, so I have left that out. Signed-off-by: Niels Thykier --- scour/scour.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/scour/scour.py b/scour/scour.py index 6f32dd3..16af5b5 100644 --- a/scour/scour.py +++ b/scour/scour.py @@ -549,20 +549,23 @@ def findElementsWithId(node, elems=None): referencingProps = ['fill', 'stroke', 'filter', 'clip-path', 'mask', 'marker-start', 'marker-end', 'marker-mid'] -def findReferencedElements(node, ids=None): +def findReferencedElements(start_node): """ Returns IDs of all referenced elements - - node is the node at which to start the search. + - start_node is the node at which to start the search. - returns a map which has the id as key and each value is is a list of nodes Currently looks at 'xlink:href' and all attributes in 'referencingProps' """ global referencingProps - if ids is None: - ids = {} + ids = {} - if 1: # Indent-only + # Search all nodes in depth-first search + stack = [start_node] + + while stack: + node = stack.pop() # TODO: input argument ids is clunky here (see below how it is called) # GZ: alternative to passing dict, use **kwargs @@ -578,7 +581,7 @@ def findReferencedElements(node, ids=None): for propname in rule['properties']: propval = rule['properties'][propname] findReferencingProperty(node, propname, propval, ids) - return ids + continue # else if xlink:href is set, then grab the id href = node.getAttributeNS(NS['XLINK'], 'href') @@ -607,9 +610,8 @@ def findReferencedElements(node, ids=None): findReferencingProperty(node, attr, val, ids) if node.hasChildNodes(): - for child in node.childNodes: - if child.nodeType == Node.ELEMENT_NODE: - findReferencedElements(child, ids) + stack.extend(n for n in node.childNodes if n.nodeType == Node.ELEMENT_NODE) + return ids