From 210bcec4de7e6d3102cec8ebc22a144afc58728e Mon Sep 17 00:00:00 2001 From: Tamas TEVESZ Date: Thu, 7 Oct 2010 23:46:43 +0200 Subject: [PATCH] WINGs: tree enhancements - add WMFindInTreeWithDepthLimit, which is like WMFindInTree, but does not descend down more than a set limit. - add WMTreeWalk, which will walk a WMTreeNode, running a callback function on each node. Signed-off-by: Tamas TEVESZ --- WINGs/WINGs/WUtil.h | 8 +++++++ WINGs/tree.c | 54 ++++++++++++++++++++++++++++++++------------- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/WINGs/WINGs/WUtil.h b/WINGs/WINGs/WUtil.h index c26b67a1..b78cc85a 100644 --- a/WINGs/WINGs/WUtil.h +++ b/WINGs/WINGs/WUtil.h @@ -117,6 +117,7 @@ typedef void WMInputProc(int fd, int mask, void *clientData); typedef int WMCompareDataProc(const void *item1, const void *item2); +typedef void WMTreeWalkProc(WMTreeNode *aNode, void *data); typedef void WMFreeDataProc(void *data); @@ -642,9 +643,16 @@ void WMSortTree(WMTreeNode *aNode, WMCompareDataProc *comparer); /* Returns the first node which matches node's data with cdata by 'match' */ WMTreeNode* WMFindInTree(WMTreeNode *aTree, WMMatchDataProc *match, void *cdata); +/* Returns the first node where node's data matches cdata by 'match' and node is + * at most `limit' depths down from `aTree'. */ +WMTreeNode *WMFindInTreeWithDepthLimit(WMTreeNode * aTree, WMMatchDataProc * match, void *cdata, int limit); + /* Returns first tree node that has data == cdata */ #define WMGetFirstInTree(aTree, cdata) WMFindInTree(aTree, NULL, cdata) +/* Walk every node of aNode with `walk' */ +void WMTreeWalk(WMTreeNode *aNode, WMTreeWalkProc * walk, void *data, Bool DepthFirst); + /* ---[ WINGs/data.c ]---------------------------------------------------- */ diff --git a/WINGs/tree.c b/WINGs/tree.c index 875d46d8..e72e34a7 100644 --- a/WINGs/tree.c +++ b/WINGs/tree.c @@ -196,27 +196,22 @@ void WMSortTree(WMTreeNode * aNode, WMCompareDataProc * comparer) sortLeavesForNode(aNode, comparer); } -static WMTreeNode *findNodeInTree(WMTreeNode * aNode, WMMatchDataProc * match, void *cdata) +static WMTreeNode *findNodeInTree(WMTreeNode * aNode, WMMatchDataProc * match, void *cdata, int limit) { - if (match == NULL) { - if (aNode->data == cdata) { - return aNode; - } - } else { - if ((*match) (aNode->data, cdata)) { - return aNode; - } - } + if (match == NULL && aNode->data == cdata) + return aNode; + else if ((*match) (aNode->data, cdata)) + return aNode; - if (aNode->leaves) { + if (aNode->leaves && limit != 0) { WMTreeNode *leaf; int i; for (i = 0; i < WMGetArrayItemCount(aNode->leaves); i++) { - leaf = findNodeInTree(WMGetFromArray(aNode->leaves, i), match, cdata); - if (leaf) { + leaf = findNodeInTree(WMGetFromArray(aNode->leaves, i), + match, cdata, limit > 0 ? limit - 1 : limit); + if (leaf) return leaf; - } } } @@ -227,5 +222,34 @@ WMTreeNode *WMFindInTree(WMTreeNode * aTree, WMMatchDataProc * match, void *cdat { wassertrv(aTree != NULL, NULL); - return findNodeInTree(aTree, match, cdata); + return findNodeInTree(aTree, match, cdata, -1); +} + +WMTreeNode *WMFindInTreeWithDepthLimit(WMTreeNode * aTree, WMMatchDataProc * match, void *cdata, int limit) +{ + wassertrv(aTree != NULL, NULL); + wassertrv(limit >= 0, NULL); + + return findNodeInTree(aTree, match, cdata, limit); +} + +void WMTreeWalk(WMTreeNode * aNode, WMTreeWalkProc * walk, void *data, Bool DepthFirst) +{ + int i; + WMTreeNode *leaf; + + wassertr(aNode != NULL); + + if (DepthFirst) + (*walk)(aNode, data); + + if (aNode->leaves) { + for (i = 0; i < WMGetArrayItemCount(aNode->leaves); i++) { + leaf = (WMTreeNode *)WMGetFromArray(aNode->leaves, i); + WMTreeWalk(leaf, walk, data, DepthFirst); + } + } + + if (!DepthFirst) + (*walk)(aNode, data); }