diff options
Diffstat (limited to 'fluent-bit/lib/monkey/deps/rbtree/rbtree.c')
-rw-r--r-- | fluent-bit/lib/monkey/deps/rbtree/rbtree.c | 811 |
1 files changed, 0 insertions, 811 deletions
diff --git a/fluent-bit/lib/monkey/deps/rbtree/rbtree.c b/fluent-bit/lib/monkey/deps/rbtree/rbtree.c deleted file mode 100644 index 99e56e0c8..000000000 --- a/fluent-bit/lib/monkey/deps/rbtree/rbtree.c +++ /dev/null @@ -1,811 +0,0 @@ -/* - Copyright (c) 2013, Phil Vachon <phil@cowpig.ca> - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** \defgroup rb_tree_implementation Implementation Details - * All the implementation details for the red-black tree, including functions for - * the maintenance of tree properties. - * @{ - */ - -/** \file rbtree.c - * An implementation of an intrusive red-black self-balancing tree, that can - * be used to implement red-black trees in situations where memory allocation - * is not an option. - * - * This file exclusively contains implementation details for the red-black tree, so - * probably is not of much interest to most people. - * - * \see rbtree.h - * \see rb_tree - * \see rb_tree_node - */ - -#include <rbtree.h> - -#include <stdlib.h> -#include <string.h> - -/** \defgroup rb_tree_colors Colors for the red-black tree nodes - * @{ - */ - -/** - * Node is black - */ -#define COLOR_BLACK 0x0 - -/** - * Node is red - */ -#define COLOR_RED 0x1 -/**@}*/ - -static -int __rb_tree_cmp_mapper(void *state, const void *lhs, const void *rhs) -{ - rb_cmp_func_t cmp = state; - return cmp(lhs, rhs); -} - -rb_result_t rb_tree_new_ex(struct rb_tree *tree, - rb_cmp_func_ex_t compare, - void *state) -{ - rb_result_t ret = RB_OK; - - RB_ASSERT_ARG(tree != NULL); - RB_ASSERT_ARG(compare != NULL); - - tree->root = NULL; - tree->compare = compare; - tree->state = state; - tree->rightmost = NULL; - - return ret; -} - -rb_result_t rb_tree_new(struct rb_tree *tree, - rb_cmp_func_t compare) -{ - RB_ASSERT_ARG(tree != NULL); - RB_ASSERT_ARG(compare != NULL); - - return rb_tree_new_ex(tree, __rb_tree_cmp_mapper, (void *)compare); -} - -rb_result_t rb_tree_destroy(struct rb_tree *tree) -{ - rb_result_t ret = RB_OK; - - RB_ASSERT_ARG(tree != NULL); - - memset(tree, 0, sizeof(struct rb_tree)); - - return ret; -} - -rb_result_t rb_tree_empty(struct rb_tree *tree, - int *is_empty) -{ - rb_result_t ret = RB_OK; - - RB_ASSERT_ARG(tree != NULL); - RB_ASSERT_ARG(is_empty != NULL); - - *is_empty = !!(tree->root == NULL); - - return ret; -} - -rb_result_t rb_tree_find(struct rb_tree *tree, - const void *key, - struct rb_tree_node **value) -{ - rb_result_t ret = RB_OK; - - RB_ASSERT_ARG(tree != NULL); - RB_ASSERT_ARG(value != NULL); - - *value = NULL; - - if (RB_UNLIKELY(tree->root == NULL)) { - ret = RB_NOT_FOUND; - goto done; - } - - struct rb_tree_node *node = tree->root; - - while (node != NULL) { - int compare = tree->compare(tree->state, key, node->key); - - if (compare < 0) { - node = node->left; - } else if (compare == 0) { - break; /* We found our node */ - } else { - /* Otherwise, we want the right node, and continue iteration */ - node = node->right; - } - } - - if (node == NULL) { - ret = RB_NOT_FOUND; - goto done; - } - - /* Return the node we found */ - *value = node; - -done: - return ret; -} - -/* Helper function to get a node's sibling */ -static inline -struct rb_tree_node *__helper_get_sibling(struct rb_tree_node *node) -{ - if (node->parent == NULL) { - return NULL; - } - - struct rb_tree_node *parent = node->parent; - - if (node == parent->left) { - return parent->right; - } else { - return parent->left; - } -} - -/* Helper function to get a node's grandparent */ -static inline -struct rb_tree_node *__helper_get_grandparent(struct rb_tree_node *node) -{ - if (node->parent == NULL) { - return NULL; - } - - struct rb_tree_node *parent_node = node->parent; - - return parent_node->parent; -} - -/* Helper function to get a node's uncle */ -static inline -struct rb_tree_node *__helper_get_uncle(struct rb_tree_node *node) -{ - struct rb_tree_node *grandparent = __helper_get_grandparent(node); - - if (grandparent == NULL) { - return NULL; - } - - if (node->parent == grandparent->left) { - return grandparent->right; - } else { - return grandparent->left; - } -} - -/* Helper function to do a left rotation of a given node */ -static inline -void __helper_rotate_left(struct rb_tree *tree, - struct rb_tree_node *node) -{ - struct rb_tree_node *x = node; - struct rb_tree_node *y = x->right; - - x->right = y->left; - - if (y->left != NULL) { - struct rb_tree_node *yleft = y->left; - yleft->parent = x; - } - - y->parent = x->parent; - - if (x->parent == NULL) { - tree->root = y; - } else { - struct rb_tree_node *xp = x->parent; - if (x == xp->left) { - xp->left = y; - } else { - xp->right = y; - } - } - - y->left = x; - x->parent = y; -} - -/* Helper function to do a right rotation of a given node */ -static inline -void __helper_rotate_right(struct rb_tree *tree, - struct rb_tree_node *node) -{ - struct rb_tree_node *x = node; - struct rb_tree_node *y = x->left; - - x->left = y->right; - - if (y->right != NULL) { - struct rb_tree_node *yright = y->right; - yright->parent = x; - } - - y->parent = x->parent; - - if (x->parent == NULL) { - tree->root = y; - } else { - struct rb_tree_node *xp = x->parent; - if (x == xp->left) { - xp->left = y; - } else { - xp->right = y; - } - } - - y->right = x; - x->parent = y; -} - -/* Function to perform a RB tree rebalancing after an insertion */ -static -void __helper_rb_tree_insert_rebalance(struct rb_tree *tree, - struct rb_tree_node *node) -{ - struct rb_tree_node *new_node_parent = node->parent; - - if (new_node_parent != NULL && new_node_parent->color != COLOR_BLACK) { - struct rb_tree_node *pnode = node; - - /* Iterate until we're at the root (which we just color black) or - * until we the parent node is no longer red. - */ - while ((tree->root != pnode) && (pnode->parent != NULL) && - (pnode->parent->color == COLOR_RED)) - { - struct rb_tree_node *parent = pnode->parent; - struct rb_tree_node *grandparent = __helper_get_grandparent(pnode); - struct rb_tree_node *uncle = NULL; - int uncle_is_left; - - assert(pnode->color == COLOR_RED); - - if (parent == grandparent->left) { - uncle_is_left = 0; - uncle = grandparent->right; - } else { - uncle_is_left = 1; - uncle = grandparent->left; - } - - /* Case 1: Uncle is not black */ - if (uncle && uncle->color == COLOR_RED) { - /* Color parent and uncle black */ - parent->color = COLOR_BLACK; - uncle->color = COLOR_BLACK; - - /* Color Grandparent as Black */ - grandparent->color = COLOR_RED; - pnode = grandparent; - /* Continue iteration, processing grandparent */ - } else { - /* Case 2 - node's parent is red, but uncle is black */ - if (!uncle_is_left && parent->right == pnode) { - pnode = pnode->parent; - __helper_rotate_left(tree, pnode); - } else if (uncle_is_left && parent->left == pnode) { - pnode = pnode->parent; - __helper_rotate_right(tree, pnode); - } - - /* Case 3 - Recolor and rotate*/ - parent = pnode->parent; - parent->color = COLOR_BLACK; - - grandparent = __helper_get_grandparent(pnode); - grandparent->color = COLOR_RED; - if (!uncle_is_left) { - __helper_rotate_right(tree, grandparent); - } else { - __helper_rotate_left(tree, grandparent); - } - } - } - - /* Make sure the tree root is black (Case 1: Continued) */ - struct rb_tree_node *tree_root = tree->root; - tree_root->color = COLOR_BLACK; - } -} - -rb_result_t rb_tree_insert(struct rb_tree *tree, - const void *key, - struct rb_tree_node *node) -{ - rb_result_t ret = RB_OK; - - int rightmost = 1; - struct rb_tree_node *nd = NULL; - - RB_ASSERT_ARG(tree != NULL); - RB_ASSERT_ARG(node != NULL); - - node->left = NULL; - node->right = NULL; - node->parent = NULL; - node->key = key; - - /* Case 1: Simplest case -- tree is empty */ - if (RB_UNLIKELY(tree->root == NULL)) { - tree->root = node; - tree->rightmost = node; - node->color = COLOR_BLACK; - goto done; - } - - /* Otherwise, insert the node as you would typically in a BST */ - nd = tree->root; - node->color = COLOR_RED; - - rightmost = 1; - - /* Insert a node into the tree as you normally would */ - while (nd != NULL) { - int compare = tree->compare(tree->state, node->key, nd->key); - - if (compare == 0) { - ret = RB_DUPLICATE; - goto done; - } - - if (compare < 0) { - rightmost = 0; - if (nd->left == NULL) { - nd->left = node; - break; - } else { - nd = nd->left; - } - } else { - if (nd->right == NULL) { - nd->right = node; - break; - } else { - nd = nd->right; - } - } - } - - node->parent = nd; - - if (1 == rightmost) { - tree->rightmost = node; - } - - /* Rebalance the tree about the node we just added */ - __helper_rb_tree_insert_rebalance(tree, node); - -done: - return ret; -} - -rb_result_t rb_tree_find_or_insert(struct rb_tree *tree, - void *key, - struct rb_tree_node *new_candidate, - struct rb_tree_node **value) -{ - rb_result_t ret = RB_OK; - - RB_ASSERT_ARG(tree != NULL); - RB_ASSERT_ARG(value != NULL); - RB_ASSERT_ARG(new_candidate != NULL); - - *value = NULL; - new_candidate->key = key; - - struct rb_tree_node *node = tree->root; - - /* Case 1: Tree is empty, so we just insert the node */ - if (RB_UNLIKELY(tree->root == NULL)) { - tree->root = new_candidate; - tree->rightmost = new_candidate; - new_candidate->color = COLOR_BLACK; - node = new_candidate; - goto done; - } - - struct rb_tree_node *node_prev = NULL; - int dir = 0, rightmost = 1; - while (node != NULL) { - int compare = tree->compare(tree->state, key, node->key); - - if (compare < 0) { - node_prev = node; - dir = 0; - node = node->left; - rightmost = 0; - } else if (compare == 0) { - break; /* We found our node */ - } else { - /* Otherwise, we want the right node, and continue iteration */ - node_prev = node; - dir = 1; - node = node->right; - } - } - - /* Case 2 - we didn't find the node, so insert the candidate */ - if (node == NULL) { - if (dir == 0) { - rightmost = 0; - node_prev->left = new_candidate; - } else { - node_prev->right = new_candidate; - } - - new_candidate->parent = node_prev; - - node = new_candidate; - node->color = COLOR_RED; - - if (1 == rightmost) { - tree->rightmost = new_candidate; - } - - /* Rebalance the tree, preserving rb properties */ - __helper_rb_tree_insert_rebalance(tree, node); - } - -done: - /* Return the node we found */ - *value = node; - - return ret; -} - -/** - * Find the minimum of the subtree starting at node - */ -static -struct rb_tree_node *__helper_rb_tree_find_minimum(struct rb_tree_node *node) -{ - struct rb_tree_node *x = node; - - while (x->left != NULL) { - x = x->left; - } - - return x; -} - -static -struct rb_tree_node *__helper_rb_tree_find_maximum(struct rb_tree_node *node) -{ - struct rb_tree_node *x = node; - - while (x->right != NULL) { - x = x->right; - } - - return x; -} - -static -struct rb_tree_node *__helper_rb_tree_find_successor(struct rb_tree_node *node) -{ - struct rb_tree_node *x = node; - - if (x->right != NULL) { - return __helper_rb_tree_find_minimum(x->right); - } - - struct rb_tree_node *y = x->parent; - - while (y != NULL && x == y->right) { - x = y; - y = y->parent; - } - - return y; -} - -static -struct rb_tree_node *__helper_rb_tree_find_predecessor(struct rb_tree_node *node) -{ - struct rb_tree_node *x = node; - - if (x->left != NULL) { - return __helper_rb_tree_find_maximum(x->left); - } - - struct rb_tree_node *y = x->parent; - - while (y != NULL && x == y->left) { - x = y; - y = y->parent; - } - - return y; -} - - -/* Replace x with y, inserting y where x previously was */ -static -void __helper_rb_tree_swap_node(struct rb_tree *tree, - struct rb_tree_node *x, - struct rb_tree_node *y) -{ - struct rb_tree_node *left = x->left; - struct rb_tree_node *right = x->right; - struct rb_tree_node *parent = x->parent; - - y->parent = parent; - - if (parent != NULL) { - if (parent->left == x) { - parent->left = y; - } else { - parent->right = y; - } - } else { - if (tree->root == x) { - tree->root = y; - } - } - - y->right = right; - if (right != NULL) { - right->parent = y; - } - x->right = NULL; - - y->left = left; - if (left != NULL) { - left->parent = y; - } - x->left = NULL; - - y->color = x->color; - x->parent = NULL; -} - -static -void __helper_rb_tree_delete_rebalance(struct rb_tree *tree, - struct rb_tree_node *node, - struct rb_tree_node *parent, - int node_is_left) -{ - struct rb_tree_node *x = node; - struct rb_tree_node *xp = parent; - int is_left = node_is_left; - - while (x != tree->root && (x == NULL || x->color == COLOR_BLACK)) { - struct rb_tree_node *w = is_left ? xp->right : xp->left; /* Sibling */ - - if (w != NULL && w->color == COLOR_RED) { - /* Case 1: */ - w->color = COLOR_BLACK; - xp->color = COLOR_RED; - if (is_left) { - __helper_rotate_left(tree, xp); - } else { - __helper_rotate_right(tree, xp); - } - w = is_left ? xp->right : xp->left; - } - - struct rb_tree_node *wleft = w != NULL ? w->left : NULL; - struct rb_tree_node *wright = w != NULL ? w->right : NULL; - if ( (wleft == NULL || wleft->color == COLOR_BLACK) && - (wright == NULL || wright->color == COLOR_BLACK) ) - { - /* Case 2: */ - if (w != NULL) { - w->color = COLOR_RED; - } - x = xp; - xp = x->parent; - is_left = xp && (x == xp->left); - } else { - if (is_left && (wright == NULL || wright->color == COLOR_BLACK)) { - /* Case 3a: */ - w->color = COLOR_RED; - if (wleft) { - wleft->color = COLOR_BLACK; - } - __helper_rotate_right(tree, w); - w = xp->right; - } else if (!is_left && (wleft == NULL || wleft->color == COLOR_BLACK)) { - /* Case 3b: */ - w->color = COLOR_RED; - if (wright) { - wright->color = COLOR_BLACK; - } - __helper_rotate_left(tree, w); - w = xp->left; - } - - /* Case 4: */ - wleft = w->left; - wright = w->right; - - w->color = xp->color; - xp->color = COLOR_BLACK; - - if (is_left && wright != NULL) { - wright->color = COLOR_BLACK; - __helper_rotate_left(tree, xp); - } else if (!is_left && wleft != NULL) { - wleft->color = COLOR_BLACK; - __helper_rotate_right(tree, xp); - } - x = tree->root; - } - } - - if (x != NULL) { - x->color = COLOR_BLACK; - } -} - -rb_result_t rb_tree_remove(struct rb_tree *tree, - struct rb_tree_node *node) -{ - rb_result_t ret = RB_OK; - - RB_ASSERT_ARG(tree != NULL); - RB_ASSERT_ARG(node != NULL); - - struct rb_tree_node *y; - - - if (node->left == NULL || node->right == NULL) { - y = node; - if (node == tree->rightmost) { - /* The new rightmost item is our successor */ - tree->rightmost = __helper_rb_tree_find_predecessor(node); - } - } else { - y = __helper_rb_tree_find_successor(node); - } - - struct rb_tree_node *x, *xp; - - if (y->left != NULL) { - x = y->left; - } else { - x = y->right; - } - - if (x != NULL) { - x->parent = y->parent; - xp = x->parent; - } else { - xp = y->parent; - } - - int is_left = 0; - if (y->parent == NULL) { - tree->root = x; - xp = NULL; - } else { - struct rb_tree_node *yp = y->parent; - if (y == yp->left) { - yp->left = x; - is_left = 1; - } else { - yp->right = x; - is_left = 0; - } - } - - int y_color = y->color; - - /* Swap in the node */ - if (y != node) { - __helper_rb_tree_swap_node(tree, node, y); - if (xp == node) { - xp = y; - } - } - - if (y_color == COLOR_BLACK) { - __helper_rb_tree_delete_rebalance(tree, x, xp, is_left); - } - - node->parent = NULL; - node->left = NULL; - node->right = NULL; - - return ret; -} - -/** - * \mainpage An Intrusive Red-Black Tree - * - * The goal of this implementation is to be both easy to use, but also - * sufficiently powerful enough to perform all the operations that one might - * typically want to do with a red-black tree. - * - * To make a structure usable with an rb_tree, you must embed the structure - * struct rb_tree_node. - * \code - struct my_sample_struct { - const char *name; - int data; - struct rb_tree_node rnode; - }; - * \endcode - * \note `rb_tree_node` need not be initialized -- it is initialized during the - * insertion operation. - * - * Next, you must declare a comparison function that, given a pointer to two - * keys, returns a value less than 0 if the left-hand side is less than the - * right-hand side, 0 if the left-hand side is equal to the right-hand side, - * or greater than 0 if the left-hand side is greater than the left-hand side. - * - * A simple example for a string might use the `strcmp(3)` function directly, - * as such: - * - * \code - int my_sample_struct_compare_keys(void *lhs, void *rhs) - { - return strcmp((const char *)lhs, (const char *)rhs); - } - * \endcode - * \note the function you create for your comparison function must conform to - * rb_cmp_func_t, or the compiler will generate a warning and, if you're - * unlucky, you will fail catastrophically at a later date. - * - * Then, to create a new, empty red-black tree, call rb_tree_new, as so: - * \code - struct rb_tree my_rb_tree; - if (rb_tree_new(&my_rb_tree, my_sample_struct_compare_keys) != RB_OK) { - exit(EXIT_FAILURE); - } - * \endcode - * - * Items can be added to the red-black tree using the function `rb_tree_insert`: - * \code - struct my_sample_struct node = { .name = "test1", .date = 42 }; - if (rb_tree_insert(&my_rb_tree, node.name, &(node.rnode)) != RB_OK) { - printf("Failed to insert a node into the RB tree!\n"); - exit(EXIT_FAILURE); - } - * \endcode - * - * \see rb_tree - * \see rb_tree_node - * \see rb_functions - * \see rbtree.h - */ - |