1 #include "ecore_private.h"
3 #include "Ecore_Data.h"
5 /* A macro for determining the highest node at given branch */
6 #define MAX_HEIGHT(node) (node ? MAX(node->max_left, node->max_right) : 0)
8 /* Utility functions for searching the tree and returning a node, or its
10 static Ecore_Tree_Node *tree_node_find(Ecore_Tree * tree, const void *key);
11 static Ecore_Tree_Node *tree_node_find_parent(Ecore_Tree * tree, const void *key);
13 /* Balancing functions, keep the tree balanced within a one node height
15 static int tree_node_balance(Ecore_Tree * Tree, Ecore_Tree_Node * top_node);
16 static int tree_node_rotate_right(Ecore_Tree * tree, Ecore_Tree_Node * top_node);
17 static int tree_node_rotate_left(Ecore_Tree * tree, Ecore_Tree_Node * top_node);
19 /* Fucntions for executing a specified function on each node of a tree */
20 static int tree_for_each_node(Ecore_Tree_Node * node, Ecore_For_Each for_each_func,
22 static int tree_for_each_node_value(Ecore_Tree_Node * node,
23 Ecore_For_Each for_each_func, void *user_data);
26 * @brief Allocate a new tree structure.
27 * @param compare_func: function used to compare the two values
28 * @return Returns NULL if the operation fails, otherwise the new tree
31 ecore_tree_new(Ecore_Compare_Cb compare_func)
35 new_tree = ECORE_TREE(malloc(sizeof(Ecore_Tree)));
39 if (!ecore_tree_init(new_tree, compare_func))
49 * @brief Initialize a tree structure to some sane initial values
50 * @param new_tree: the new tree structure to be initialized
51 * @param compare_func: the function used to compare node keys
52 * @return Returns TRUE on successful initialization, FALSE on an error
55 ecore_tree_init(Ecore_Tree *new_tree, Ecore_Compare_Cb compare_func)
57 CHECK_PARAM_POINTER_RETURN("new_tree", new_tree, FALSE);
59 memset(new_tree, 0, sizeof(Ecore_Tree));
62 new_tree->compare_func = ecore_direct_compare;
64 new_tree->compare_func = compare_func;
70 * @brief Add a function to be called at node destroy time
71 * @param tree: the tree that will use this function when nodes are destroyed
72 * @param free_func: the function that will be passed the node being freed
73 * @return Returns TRUE on successful set, FALSE otherwise.
76 ecore_tree_free_value_cb_set(Ecore_Tree *tree, Ecore_Free_Cb free_value)
78 CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE);
80 tree->free_value = free_value;
86 * @brief Add a function to be called at node destroy time
87 * @param tree: the tree that will use this function when nodes are destroyed
88 * @param free_key: the function that will be passed the node being freed
89 * @return Returns TRUE on successful set, FALSE otherwise.
92 ecore_tree_free_key_cb_set(Ecore_Tree *tree, Ecore_Free_Cb free_key)
94 CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE);
96 tree->free_key = free_key;
102 * @brief Initialize a new tree node
103 * @return Returns FALSE if the operation fails, otherwise TRUE
106 ecore_tree_node_init(Ecore_Tree_Node *new_node)
108 CHECK_PARAM_POINTER_RETURN("new_node", new_node, FALSE);
110 new_node->key = NULL;
111 new_node->value = NULL;
113 new_node->parent = NULL;
114 new_node->right_child = NULL;
115 new_node->left_child = NULL;
117 new_node->max_left = new_node->max_right = 0;
123 * @brief Allocate a new tree node
124 * @return Returns NULL if the operation fails, otherwise the new node.
126 EAPI Ecore_Tree_Node *
127 ecore_tree_node_new()
129 Ecore_Tree_Node *new_node;
131 new_node = ECORE_TREE_NODE(malloc(sizeof(Ecore_Tree_Node)));
135 if (!ecore_tree_node_init(new_node))
145 * @brief Free a tree node and it's children.
146 * @param node: tree node to be free()'d
147 * @param data_free: callback for destroying the data held in node
148 * @return Returns TRUE if the node is destroyed successfully, FALSE if not.
150 * If you don't want the children free'd then you need to remove the node first.
153 ecore_tree_node_destroy(Ecore_Tree_Node *node, Ecore_Free_Cb value_free, Ecore_Free_Cb key_free)
155 CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
160 value_free(node->value);
168 * @brief Set the value of the node to value
169 * @param node: the node to be set
170 * @param value: the value to set the node to.
171 * @return Returns TRUE if the node is set successfully, FALSE if not.
174 ecore_tree_node_value_set(Ecore_Tree_Node *node, void *value)
176 CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
184 * @brief Get the value of the node
185 * @param node: the node that contains the desired value
186 * @return Returns NULL if an error, otherwise the value associated with node
189 ecore_tree_node_value_get(Ecore_Tree_Node *node)
193 CHECK_PARAM_POINTER_RETURN("node", node, NULL);
200 * @brief Set the value of the node's key to key
201 * @param node: the node to be set
202 * @param key: the value to set it's key to.
203 * @return Returns TRUE if the node is set successfully, FALSE if not.
206 ecore_tree_node_key_set(Ecore_Tree_Node *node, void *key)
208 CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
216 * @brief Get the value of the node's key
217 * @param node: the node that contains the desired key
219 * @return Returns NULL if an error occurs, otherwise the key is returned
222 ecore_tree_node_key_get(Ecore_Tree_Node *node)
226 CHECK_PARAM_POINTER_RETURN("node", node, NULL);
233 * @brief Free the tree and it's stored data
234 * @param tree: the tree to destroy
236 * @return Returns TRUE if tree destroyed successfully, FALSE if not.
239 ecore_tree_destroy(Ecore_Tree *tree)
241 Ecore_Tree_Node *node;
243 CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE);
245 while ((node = tree->tree))
247 ecore_tree_node_remove(tree, node);
248 ecore_tree_node_destroy(node, tree->free_value, tree->free_key);
257 * @brief Return the node corresponding to key
258 * @param tree: the tree to search
259 * @param key: the key to search for in the tree
261 * @return Returns the node corresponding to the key if found, otherwise NULL.
263 EAPI Ecore_Tree_Node *
264 ecore_tree_get_node(Ecore_Tree *tree, const void *key)
266 Ecore_Tree_Node *ret;
268 CHECK_PARAM_POINTER_RETURN("tree", tree, NULL);
270 ret = tree_node_find(tree, key);
276 * @brief Return the value corresponding to key
277 * @param tree: the tree to search
278 * @param key: the key to search for in @a tree
279 * @return Returns the value corresponding to the key if found, otherwise NULL.
282 ecore_tree_get(Ecore_Tree *tree, const void *key)
285 Ecore_Tree_Node *node;
287 CHECK_PARAM_POINTER_RETURN("tree", tree, NULL);
289 node = tree_node_find(tree, key);
290 ret = (node ? node->value : NULL);
296 * @brief Find the closest value greater than or equal to the key.
297 * @param tree The tree to search.
298 * @param key The key to search for in @a tree.
299 * @return NULL if no valid nodes, otherwise the node greater than or
303 ecore_tree_closest_larger_get(Ecore_Tree *tree, const void *key)
305 Ecore_Tree_Node *node;
307 CHECK_PARAM_POINTER_RETURN("tree", tree, NULL);
309 node = tree_node_find(tree, key);
313 node = tree_node_find_parent(tree, key);
317 if (tree->compare_func(node->key, key) < 0)
324 * @brief Find the closest value <= key
325 * @param tree the tree to search
326 * @param key the key to search for in tree
327 * @return Returns NULL if no valid nodes, otherwise the node <= key
330 ecore_tree_closest_smaller_get(Ecore_Tree *tree, const void *key)
332 Ecore_Tree_Node *node;
334 CHECK_PARAM_POINTER_RETURN("tree", tree, NULL);
336 node = tree_node_find(tree, key);
340 node = tree_node_find_parent(tree, key);
342 node = node->right_child;
348 * Set the value associated with key to @a value.
349 * @param tree The tree that contains the key/value pair.
350 * @param key The key to identify which node to set a value.
351 * @param value Value to set the found node.
352 * @return TRUE if successful, FALSE if not.
355 ecore_tree_set(Ecore_Tree *tree, void *key, void *value)
357 Ecore_Tree_Node *node = NULL;
359 CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE);
361 node = tree_node_find(tree, key);
364 node = ecore_tree_node_new();
365 ecore_tree_node_key_set(node, key);
366 if (!ecore_tree_node_add(tree, node))
373 if (node->value && tree->free_value)
374 tree->free_value(node->value);
377 ecore_tree_node_value_set(node, value);
379 for (; node; node = node->parent)
380 tree_node_balance(tree, node);
386 * Place a node in the tree.
387 * @param tree The tree to add @a node.
388 * @param node The node to add to @a tree.
389 * @return TRUE on a successful add, FALSE otherwise.
392 ecore_tree_node_add(Ecore_Tree *tree, Ecore_Tree_Node *node)
394 Ecore_Tree_Node *travel = NULL;
396 CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE);
397 CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
399 /* Find where to put this new node. */
404 travel = tree_node_find_parent(tree, node->key);
405 node->parent = travel;
407 /* The node is less than travel */
408 if (tree->compare_func(node->key, travel->key) < 0)
410 travel->right_child = node;
411 travel->max_left = 1;
412 /* The node is greater than travel */
416 travel->left_child = node;
417 travel->max_right = 1;
425 * Remove the node from the tree.
426 * @param tree The tree to remove @a node from.
427 * @param node The node to remove from @a tree.
428 * @return TRUE on a successful remove, FALSE otherwise.
431 ecore_tree_node_remove(Ecore_Tree *tree, Ecore_Tree_Node *node)
433 Ecore_Tree_Node *traverse;
435 CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE);
436 CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
439 * Find the nearest value to the balanced one.
441 if (node->left_child)
443 traverse = node->left_child;
445 /* Now work our way down right side of the traverse node.
446 * This will give us the node with the next closest value
447 * to the current node. If traverse had no right node, then
448 * this will stop at node's left node. */
449 while (traverse->right_child)
451 traverse = traverse->right_child;
455 * Hook any dropped leaves into the moved nodes spot
457 if (traverse->parent)
458 traverse->parent->left_child = traverse->left_child;
460 else if (node->right_child)
462 traverse = node->right_child;
464 /* Now work our way down left side of the traverse node.
465 * This will give us the node with the next closest value
466 * to the current node. If traverse had no left node, then
467 * this will stop at node's right node. */
468 while (traverse->left_child)
470 traverse = traverse->left_child;
474 * Hook any dropped leaves into the moved nodes spot
476 if (traverse->right_child)
477 traverse->right_child->parent = traverse->parent;
479 if (traverse->parent)
480 traverse->parent->right_child = traverse->right_child;
482 tree->tree = traverse->right_child;
491 * Ensure that we don't get a recursive reference.
493 if (node->right_child && node->right_child != traverse)
495 node->right_child->parent = traverse;
496 traverse->right_child = node->right_child;
499 if (node->left_child && node->left_child != traverse)
501 node->left_child->parent = traverse;
502 traverse->left_child = node->left_child;
506 * Unlink the node to be moved from it's parent.
508 if (traverse->parent)
510 if (traverse->parent->left_child == traverse)
511 traverse->parent->left_child = NULL;
513 traverse->parent->right_child = NULL;
515 traverse->parent = node->parent;
520 if (node == node->parent->left_child)
521 node->parent->left_child = traverse;
523 node->parent->right_child = traverse;
526 if (tree->tree == node)
527 tree->tree = traverse;
529 node->parent = node->left_child = node->right_child = NULL;
532 * Rebalance the tree to ensure short search paths.
536 tree_node_balance(tree, traverse);
537 traverse = traverse->parent;
544 * Remove the key from the tree.
545 * @param tree The tree to remove @a key.
546 * @param key The key to remove from @a tree.
547 * @return TRUE on a successful remove, FALSE otherwise.
550 ecore_tree_remove(Ecore_Tree *tree, const void *key)
552 Ecore_Tree_Node *node;
554 CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE);
558 /* Find the node we need to remove */
559 node = tree_node_find(tree, key);
563 if (!ecore_tree_node_remove(tree, node))
566 ecore_tree_node_destroy(node, tree->free_value, tree->free_key);
572 * @brief Test to see if the tree has any nodes
573 * @param tree: the tree to check for nodes
574 * @return Returns TRUE if no nodes exist, FALSE otherwise
577 ecore_tree_empty_is(Ecore_Tree *tree)
579 CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE);
588 * @brief Execute function for each value in the tree
589 * @param tree: the tree to traverse
590 * @param for_each_func: the function to execute for each value in the tree
591 * @param user_data: data passed to each for_each_func call
592 * @return Returns TRUE on success, FALSE on failure.
595 ecore_tree_for_each_node_value(Ecore_Tree *tree, Ecore_For_Each for_each_func, void *user_data)
597 CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE);
598 CHECK_PARAM_POINTER_RETURN("for_each_func", for_each_func, FALSE);
603 return tree_for_each_node_value(tree->tree, for_each_func, user_data);
607 * @brief Execute the function for each node in the tree
608 * @param tree: the tree to traverse
609 * @param for_each_func: the function to execute for each node
610 * @param user_data: data passed to each for_each_func call
611 * @return Returns TRUE on success, FALSE on failure.
614 ecore_tree_for_each_node(Ecore_Tree *tree, Ecore_For_Each for_each_func, void *user_data)
616 CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE);
617 CHECK_PARAM_POINTER_RETURN("for_each_func", for_each_func, FALSE);
622 return tree_for_each_node(tree->tree, for_each_func, user_data);
625 /* Find the parent for the key */
626 static Ecore_Tree_Node *
627 tree_node_find_parent(Ecore_Tree *tree, const void *key)
629 Ecore_Tree_Node *parent, *travel;
631 CHECK_PARAM_POINTER_RETURN("tree", tree, NULL);
633 parent = tree_node_find(tree, key);
635 parent = parent->parent;
645 if ((compare = tree->compare_func(key, travel->key)) < 0)
647 if (!travel->right_child)
649 travel = travel->right_child;
653 if (!travel->left_child)
655 travel = travel->left_child;
662 /* Search for the node with a specified key */
663 static Ecore_Tree_Node *
664 tree_node_find(Ecore_Tree *tree, const void *key)
667 Ecore_Tree_Node *node;
669 CHECK_PARAM_POINTER_RETURN("tree", tree, NULL);
672 while (node && (compare = tree->compare_func(key, node->key)) != 0)
677 if (!node->right_child)
680 node = node->right_child;
684 if (!node->left_child)
687 node = node->left_child;
694 /* Balance the tree with respect to node */
696 tree_node_balance(Ecore_Tree *tree, Ecore_Tree_Node *top_node)
700 CHECK_PARAM_POINTER_RETURN("top_node", top_node, FALSE);
702 /* Get the height of the left branch. */
703 if (top_node->right_child)
704 top_node->max_left = MAX_HEIGHT(top_node->right_child) + 1;
706 top_node->max_left = 0;
708 /* Get the height of the right branch. */
709 if (top_node->left_child)
710 top_node->max_right = MAX_HEIGHT(top_node->left_child) + 1;
712 top_node->max_right = 0;
714 /* Determine which side has a larger height. */
715 balance = top_node->max_right - top_node->max_left;
717 /* if the left side has a height advantage >1 rotate right */
719 tree_node_rotate_right(tree, top_node);
720 /* else if the left side has a height advantage >1 rotate left */
721 else if (balance > 1)
722 tree_node_rotate_left(tree, top_node);
727 /* Tree is overbalanced to the left, so rotate nodes to the right. */
729 tree_node_rotate_right(Ecore_Tree *tree, Ecore_Tree_Node *top_node)
731 Ecore_Tree_Node *temp;
733 CHECK_PARAM_POINTER_RETURN("top_node", top_node, FALSE);
735 /* The left branch's right branch becomes the nodes left branch,
736 * the left branch becomes the top node, and the node becomes the
738 temp = top_node->right_child;
739 top_node->right_child = temp->left_child;
740 temp->left_child = top_node;
742 /* Make sure the nodes know who their new parents are and the tree
743 * structure knows the start of the tree. */
744 temp->parent = top_node->parent;
745 if (temp->parent == NULL)
749 if (temp->parent->left_child == top_node)
750 temp->parent->left_child = temp;
752 temp->parent->right_child = temp;
754 top_node->parent = temp;
756 /* And recalculate node heights */
757 tree_node_balance(tree, top_node);
758 tree_node_balance(tree, temp);
763 /* The tree is overbalanced to the right, so we rotate nodes to the left */
765 tree_node_rotate_left(Ecore_Tree *tree, Ecore_Tree_Node *top_node)
767 Ecore_Tree_Node *temp;
769 CHECK_PARAM_POINTER_RETURN("top_node", top_node, FALSE);
772 * The right branch's left branch becomes the nodes right branch,
773 * the right branch becomes the top node, and the node becomes the
776 temp = top_node->left_child;
777 top_node->left_child = temp->right_child;
778 temp->right_child = top_node;
780 /* Make sure the nodes know who their new parents are. */
781 temp->parent = top_node->parent;
782 if (temp->parent == NULL)
786 if (temp->parent->left_child == top_node)
787 temp->parent->left_child = temp;
789 temp->parent->right_child = temp;
791 top_node->parent = temp;
793 /* And recalculate node heights */
794 tree_node_balance(tree, top_node);
795 tree_node_balance(tree, temp);
801 * @brief Execute a function for each node below this point in the tree.
802 * @param node: the highest node in the tree the function will be executed for
803 * @param for_each_func: the function to pass the nodes as data into
804 * @param user_data: data passed to each for_each_func call
805 * @return Returns FALSE if an error condition occurs, otherwise TRUE
808 tree_for_each_node(Ecore_Tree_Node * node, Ecore_For_Each for_each_func, void *user_data)
810 CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
812 if (node->right_child)
813 tree_for_each_node(node->right_child, for_each_func, user_data);
815 if (node->left_child)
816 tree_for_each_node(node->left_child, for_each_func, user_data);
818 for_each_func(node, user_data);
824 * @brief Execute a function for each node below this point in the tree.
825 * @param node: the highest node in the tree the function will be executed for
826 * @param for_each_func: the function to pass the nodes values as data
827 * @return Returns FALSE if an error condition occurs, otherwise TRUE
830 tree_for_each_node_value(Ecore_Tree_Node *node, Ecore_For_Each for_each_func, void *user_data)
832 CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
834 if (node->right_child)
835 tree_for_each_node_value(node->right_child, for_each_func, user_data);
837 if (node->left_child)
838 tree_for_each_node_value(node->left_child, for_each_func, user_data);
840 for_each_func(node->value, user_data);