#include #include "WUtil.h" typedef struct W_TreeNode { void *data; /*unsigned int uflags:16; */ WMArray *leaves; int depth; WMFreeDataProc *destructor; } W_TreeNode; static void destroyNode(void *data) { WMTreeNode *aNode = (WMTreeNode *) data; if (aNode->destructor) { (*aNode->destructor) (aNode->data); } if (aNode->leaves) { WMFreeArray(aNode->leaves); } wfree(aNode); } WMTreeNode *WMCreateTreeNode(void *data) { return WMCreateTreeNodeWithDestructor(data, NULL); } WMTreeNode *WMCreateTreeNodeWithDestructor(void *data, WMFreeDataProc * destructor) { WMTreeNode *aNode; aNode = (WMTreeNode *) wmalloc(sizeof(W_TreeNode)); aNode->destructor = destructor; aNode->data = data; aNode->depth = 0; aNode->leaves = NULL; /*aNode->leaves = WMCreateArrayWithDestructor(1, destroyNode); */ return aNode; } WMTreeNode *WMInsertItemInTree(WMTreeNode * parent, int index, void *item) { WMTreeNode *aNode; wassertrv(parent != NULL, NULL); aNode = WMCreateTreeNodeWithDestructor(item, parent->destructor); aNode->depth = parent->depth + 1; if (!parent->leaves) { parent->leaves = WMCreateArrayWithDestructor(1, destroyNode); } if (index < 0) { WMAddToArray(parent->leaves, aNode); } else { WMInsertInArray(parent->leaves, index, aNode); } return aNode; } static void updateNodeDepth(WMTreeNode * aNode, int depth) { int i; aNode->depth = depth; if (aNode->leaves) { for (i = 0; i < WMGetArrayItemCount(aNode->leaves); i++) { updateNodeDepth(WMGetFromArray(aNode->leaves, i), depth + 1); } } } WMTreeNode *WMInsertNodeInTree(WMTreeNode * parent, int index, WMTreeNode * aNode) { wassertrv(parent != NULL, NULL); wassertrv(aNode != NULL, NULL); updateNodeDepth(aNode, parent->depth + 1); if (!parent->leaves) { parent->leaves = WMCreateArrayWithDestructor(1, destroyNode); } if (index < 0) { WMAddToArray(parent->leaves, aNode); } else { WMInsertInArray(parent->leaves, index, aNode); } return aNode; } void *WMGetDataForTreeNode(WMTreeNode * aNode) { return aNode->data; } int WMGetTreeNodeDepth(WMTreeNode * aNode) { return aNode->depth; } static void sortLeavesForNode(WMTreeNode * aNode, WMCompareDataProc * comparer) { int i; if (!aNode->leaves) return; WMSortArray(aNode->leaves, comparer); for (i = 0; i < WMGetArrayItemCount(aNode->leaves); i++) { sortLeavesForNode(WMGetFromArray(aNode->leaves, i), comparer); } } void WMSortTree(WMTreeNode * aNode, WMCompareDataProc * comparer) { wassertr(aNode != NULL); sortLeavesForNode(aNode, comparer); } static WMTreeNode *findNodeInTree(WMTreeNode * aNode, WMMatchDataProc * match, void *cdata, int limit) { if (match == NULL && aNode->data == cdata) return aNode; else if (match && (*match) (aNode->data, cdata)) return aNode; 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, limit > 0 ? limit - 1 : limit); if (leaf) return leaf; } } return NULL; } 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) { int i; WMTreeNode *leaf; wassertr(aNode != NULL); (*walk)(aNode, data); if (aNode->leaves) { for (i = 0; i < WMGetArrayItemCount(aNode->leaves); i++) { leaf = (WMTreeNode *)WMGetFromArray(aNode->leaves, i); WMTreeWalk(leaf, walk, data); } } }