diff options
| author | Michael Biebl <biebl@debian.org> | 2021-10-01 23:05:04 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2021-10-01 23:05:04 +0200 |
| commit | e74c568b07b50b97873fb4ee1d776dedefbd54d6 (patch) | |
| tree | 3469f17ea9af91f7ff169b890633bda68b0cf76e /shared/c-rbtree/src/c-rbtree.h | |
| parent | bfe522304da217296e2a61040f58e35ec5d6f3f2 (diff) | |
New upstream version 1.32.12 upstream/1.32.12
Diffstat (limited to 'shared/c-rbtree/src/c-rbtree.h')
| -rw-r--r-- | shared/c-rbtree/src/c-rbtree.h | 437 |
1 files changed, 0 insertions, 437 deletions
diff --git a/shared/c-rbtree/src/c-rbtree.h b/shared/c-rbtree/src/c-rbtree.h deleted file mode 100644 index d4d0fe45..00000000 --- a/shared/c-rbtree/src/c-rbtree.h +++ /dev/null @@ -1,437 +0,0 @@ -#pragma once - -/** - * Standalone Red-Black-Tree Implementation in Standard ISO-C11 - * - * This library provides an RB-Tree API, that is fully implemented in ISO-C11 - * and has no external dependencies. Furthermore, tree traversal, memory - * allocations, and key comparisons are completely controlled by the API user. - * The implementation only provides the RB-Tree specific rebalancing and - * coloring. - * - * A tree is represented by the "CRBTree" structure. It contains a *single* - * field, which is a pointer to the root node. If NULL, the tree is empty. If - * non-NULL, there is at least a single element in the tree. - * - * Each node of the tree is represented by the "CRBNode" structure. It has - * three fields. The @left and @right members can be accessed by the API user - * directly to traverse the tree. The third member is a combination of the - * parent pointer and a set of flags. - * API users are required to embed the CRBNode object into their own objects - * and then use offsetof() (i.e., container_of() and friends) to turn CRBNode - * pointers into pointers to their own structure. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include <assert.h> -#include <stdalign.h> -#include <stddef.h> - -typedef struct CRBNode CRBNode; -typedef struct CRBTree CRBTree; - -/* implementation detail */ -#define C_RBNODE_RED (0x1UL) -#define C_RBNODE_ROOT (0x2UL) -#define C_RBNODE_FLAG_MASK (0x3UL) - -/** - * struct CRBNode - Node of a Red-Black Tree - * @__parent_and_flags: internal state - * @left: left child, or NULL - * @right: right child, or NULL - * - * Each node in an RB-Tree must embed a CRBNode object. This object contains - * pointers to its left and right child, which can be freely accessed by the - * API user at any time. They are NULL, if the node does not have a left/right - * child. - * - * The @__parent_and_flags field must never be accessed directly. It encodes - * the pointer to the parent node, and the color of the node. Use the accessor - * functions instead. - * - * There is no reason to initialize a CRBNode object before linking it. - * However, if you need a boolean state that tells you whether the node is - * linked or not, you should initialize the node via c_rbnode_init() or - * C_RBNODE_INIT. - */ -struct CRBNode { - union { - unsigned long __parent_and_flags; - /* enforce >=4-byte alignment for @__parent_and_flags */ - alignas(4) unsigned char __align_dummy; - }; - CRBNode *left; - CRBNode *right; -}; - -#define C_RBNODE_INIT(_var) { .__parent_and_flags = (unsigned long)&(_var) } - -CRBNode *c_rbnode_leftmost(CRBNode *n); -CRBNode *c_rbnode_rightmost(CRBNode *n); -CRBNode *c_rbnode_leftdeepest(CRBNode *n); -CRBNode *c_rbnode_rightdeepest(CRBNode *n); -CRBNode *c_rbnode_next(CRBNode *n); -CRBNode *c_rbnode_prev(CRBNode *n); -CRBNode *c_rbnode_next_postorder(CRBNode *n); -CRBNode *c_rbnode_prev_postorder(CRBNode *n); - -void c_rbnode_link(CRBNode *p, CRBNode **l, CRBNode *n); -void c_rbnode_unlink_stale(CRBNode *n); - -/** - * struct CRBTree - Red-Black Tree - * @root: pointer to the root node, or NULL - * - * Each Red-Black Tree is rooted in an CRBTree object. This object contains a - * pointer to the root node of the tree. The API user is free to access the - * @root member at any time, and use it to traverse the tree. - * - * To initialize an RB-Tree, set it to NULL / all zero. - */ -struct CRBTree { - union { - CRBNode *root; - /* enforce >=4-byte alignment for @root */ - alignas(4) unsigned char __align_dummy; - }; -}; - -#define C_RBTREE_INIT {} - -CRBNode *c_rbtree_first(CRBTree *t); -CRBNode *c_rbtree_last(CRBTree *t); -CRBNode *c_rbtree_first_postorder(CRBTree *t); -CRBNode *c_rbtree_last_postorder(CRBTree *t); - -void c_rbtree_move(CRBTree *to, CRBTree *from); -void c_rbtree_add(CRBTree *t, CRBNode *p, CRBNode **l, CRBNode *n); - -/** - * c_rbnode_init() - mark a node as unlinked - * @n: node to operate on - * - * This marks the node @n as unlinked. The node will be set to a valid state - * that can never happen if the node is linked in a tree. Furthermore, this - * state is fully known to the implementation, and as such handled gracefully - * in all cases. - * - * You are *NOT* required to call this on your node. c_rbtree_add() can handle - * uninitialized nodes just fine. However, calling this allows to use - * c_rbnode_is_linked() to check for the state of a node. Furthermore, - * iterators and accessors can be called on initialized (yet unlinked) nodes. - * - * Use the C_RBNODE_INIT macro if you want to initialize static variables. - */ -static inline void c_rbnode_init(CRBNode *n) { - *n = (CRBNode)C_RBNODE_INIT(*n); -} - -/** - * c_rbnode_entry() - get parent container of tree node - * @_what: tree node, or NULL - * @_t: type of parent container - * @_m: member name of tree node in @_t - * - * If the tree node @_what is embedded into a surrounding structure, this will - * turn the tree node pointer @_what into a pointer to the parent container - * (using offsetof(3), or sometimes called container_of(3)). - * - * If @_what is NULL, this will also return NULL. - * - * Return: Pointer to parent container, or NULL. - */ -#define c_rbnode_entry(_what, _t, _m) \ - ((_t *)(void *)(((unsigned long)(void *)(_what) ?: \ - offsetof(_t, _m)) - offsetof(_t, _m))) - -/** - * c_rbnode_parent() - return parent pointer - * @n node to access - * - * This returns a pointer to the parent of the given node @n. If @n does not - * have a parent, NULL is returned. If @n is not linked, @n itself is returned. - * - * You should not call this on unlinked or uninitialized nodes! If you do, you - * better know its semantics. - * - * Return: Pointer to parent. - */ -static inline CRBNode *c_rbnode_parent(CRBNode *n) { - return (n->__parent_and_flags & C_RBNODE_ROOT) ? - NULL : - (void *)(n->__parent_and_flags & ~C_RBNODE_FLAG_MASK); -} - -/** - * c_rbnode_is_linked() - check whether a node is linked - * @n: node to check, or NULL - * - * This checks whether the passed node is linked. If you pass NULL, or if the - * node is not linked into a tree, this will return false. Otherwise, this - * returns true. - * - * Note that you must have either linked the node or initialized it, before - * calling this function. Never call this function on uninitialized nodes. - * Furthermore, removing a node via c_rbnode_unlink_stale() does *NOT* mark the - * node as unlinked. You have to call c_rbnode_init() yourself after removal, or - * use the c_rbnode_unlink() helper. - * - * Return: true if the node is linked, false if not. - */ -static inline _Bool c_rbnode_is_linked(CRBNode *n) { - return n && c_rbnode_parent(n) != n; -} - -/** - * c_rbnode_unlink() - safely remove node from tree and reinitialize it - * @n: node to remove, or NULL - * - * This is almost the same as c_rbnode_unlink_stale(), but extends it slightly, to be - * more convenient to use in many cases: - * - if @n is unlinked or NULL, this is a no-op - * - @n is reinitialized after being removed - */ -static inline void c_rbnode_unlink(CRBNode *n) { - if (c_rbnode_is_linked(n)) { - c_rbnode_unlink_stale(n); - c_rbnode_init(n); - } -} - -/** - * c_rbtree_init() - initialize a new RB-Tree - * @t: tree to operate on - * - * This initializes a new, empty RB-Tree. An RB-Tree must be initialized before - * any other functions are called on it. Alternatively, you can zero its memory - * or assign C_RBTREE_INIT. - */ -static inline void c_rbtree_init(CRBTree *t) { - *t = (CRBTree)C_RBTREE_INIT; -} - -/** - * c_rbtree_is_empty() - check whether an RB-tree is empty - * @t: tree to operate on - * - * This checks whether the passed RB-Tree is empty. - * - * Return: True if tree is empty, false otherwise. - */ -static inline _Bool c_rbtree_is_empty(CRBTree *t) { - return !t->root; -} - -/** - * CRBCompareFunc - compare a node to a key - * @t: tree where the node is linked to - * @k: key to compare - * @n: node to compare - * - * If you use the tree-traversal helpers (which are optional), you need to - * provide this callback so they can compare nodes in a tree to the key you - * look for. - * - * The tree @t is provided as optional context to this callback. The key you - * look for is provided as @k, the current node that should be compared to is - * provided as @n. This function should work like strcmp(), that is, return <0 - * if @key orders before @n, 0 if both compare equal, and >0 if it orders after - * @n. - */ -typedef int (*CRBCompareFunc) (CRBTree *t, void *k, CRBNode *n); - -/** - * c_rbtree_find_node() - find node - * @t: tree to search through - * @f: comparison function - * @k: key to search for - * - * This searches through @t for a node that compares equal to @k. The function - * @f must be provided by the caller, which is used to compare nodes to @k. See - * the documentation of CRBCompareFunc for details. - * - * If there are multiple entries that compare equal to @k, this will return a - * pseudo-randomly picked node. If you need stable lookup functions for trees - * where duplicate entries are allowed, you better code your own lookup. - * - * Return: Pointer to matching node, or NULL. - */ -static inline CRBNode *c_rbtree_find_node(CRBTree *t, CRBCompareFunc f, const void *k) { - CRBNode *i; - - assert(t); - assert(f); - - i = t->root; - while (i) { - int v = f(t, (void *)k, i); - if (v < 0) - i = i->left; - else if (v > 0) - i = i->right; - else - return i; - } - - return NULL; -} - -/** - * c_rbtree_find_entry() - find entry - * @_t: tree to search through - * @_f: comparison function - * @_k: key to search for - * @_s: type of the structure that embeds the nodes - * @_m: name of the node-member in type @_t - * - * This is very similar to c_rbtree_find_node(), but instead of returning a - * pointer to the CRBNode, it returns a pointer to the surrounding object. This - * object must embed the CRBNode object. The type of the surrounding object - * must be given as @_s, and the name of the embedded CRBNode member as @_m. - * - * See c_rbtree_find_node() and c_rbnode_entry() for more details. - * - * Return: Pointer to found entry, NULL if not found. - */ -#define c_rbtree_find_entry(_t, _f, _k, _s, _m) \ - c_rbnode_entry(c_rbtree_find_node((_t), (_f), (_k)), _s, _m) - -/** - * c_rbtree_find_slot() - find slot to insert new node - * @t: tree to search through - * @f: comparison function - * @k: key to search for - * @p: output storage for parent pointer - * - * This searches through @t just like c_rbtree_find_node() does. However, - * instead of returning a pointer to a node that compares equal to @k, this - * searches for a slot to insert a node with key @k. A pointer to the slot is - * returned, and a pointer to the parent of the slot is stored in @p. Both - * can be passed directly to c_rbtree_add(), together with your node to insert. - * - * If there already is a node in the tree, that compares equal to @k, this will - * return NULL and store the conflicting node in @p. In all other cases, - * this will return a pointer (non-NULL) to the empty slot to insert the node - * at. @p will point to the parent node of that slot. - * - * If you want trees that allow duplicate nodes, you better code your own - * insertion function. - * - * Return: Pointer to slot to insert node, or NULL on conflicts. - */ -static inline CRBNode **c_rbtree_find_slot(CRBTree *t, CRBCompareFunc f, const void *k, CRBNode **p) { - CRBNode **i; - - assert(t); - assert(f); - assert(p); - - i = &t->root; - *p = NULL; - while (*i) { - int v = f(t, (void *)k, *i); - *p = *i; - if (v < 0) - i = &(*i)->left; - else if (v > 0) - i = &(*i)->right; - else - return NULL; - } - - return i; -} - -/** - * c_rbtree_for_each*() - iterators - * - * The c_rbtree_for_each*() macros provide simple for-loop wrappers to iterate - * an RB-Tree. They come in a set of flavours: - * - * - "entry": This combines c_rbnode_entry() with the loop iterator, so the - * iterator always has the type of the surrounding object, rather - * than CRBNode. - * - * - "safe": The loop iterator always keeps track of the next element to - * visit. This means, you can safely modify the current element, - * while retaining loop-integrity. - * You still must not touch any other entry of the tree. Otherwise, - * the loop-iterator will be corrupted. Also remember to only - * modify the tree in a way compatible with your iterator-order. - * That is, if you use in-order iteration (default), you can unlink - * your current object, including re-balancing the tree. However, - * if you use post-order, you must not trigger a tree rebalance - * operation, since it is not an invariant of post-order iteration. - * - * - "postorder": Rather than the default in-order iteration, this iterates - * the tree in post-order. - * - * - "unlink": This unlinks the current element from the tree before the loop - * code is run. Note that the tree is not rebalanced. That is, - * you must never break out of the loop. If you do so, the tree - * is corrupted. - */ - -#define c_rbtree_for_each(_iter, _tree) \ - for (_iter = c_rbtree_first(_tree); \ - _iter; \ - _iter = c_rbnode_next(_iter)) - -#define c_rbtree_for_each_entry(_iter, _tree, _m) \ - for (_iter = c_rbnode_entry(c_rbtree_first(_tree), __typeof__(*_iter), _m); \ - _iter; \ - _iter = c_rbnode_entry(c_rbnode_next(&_iter->_m), __typeof__(*_iter), _m)) - -#define c_rbtree_for_each_safe(_iter, _safe, _tree) \ - for (_iter = c_rbtree_first(_tree), _safe = c_rbnode_next(_iter); \ - _iter; \ - _iter = _safe, _safe = c_rbnode_next(_safe)) - -#define c_rbtree_for_each_entry_safe(_iter, _safe, _tree, _m) \ - for (_iter = c_rbnode_entry(c_rbtree_first(_tree), __typeof__(*_iter), _m), \ - _safe = _iter ? c_rbnode_entry(c_rbnode_next(&_iter->_m), __typeof__(*_iter), _m) : NULL; \ - _iter; \ - _iter = _safe, \ - _safe = _safe ? c_rbnode_entry(c_rbnode_next(&_safe->_m), __typeof__(*_iter), _m) : NULL) - -#define c_rbtree_for_each_postorder(_iter, _tree) \ - for (_iter = c_rbtree_first_postorder(_tree); \ - _iter; \ - _iter = c_rbnode_next_postorder(_iter)) \ - -#define c_rbtree_for_each_entry_postorder(_iter, _tree, _m) \ - for (_iter = c_rbnode_entry(c_rbtree_first_postorder(_tree), __typeof__(*_iter), _m); \ - _iter; \ - _iter = c_rbnode_entry(c_rbnode_next_postorder(&_iter->_m), __typeof__(*_iter), _m)) - -#define c_rbtree_for_each_safe_postorder(_iter, _safe, _tree) \ - for (_iter = c_rbtree_first_postorder(_tree), _safe = c_rbnode_next_postorder(_iter); \ - _iter; \ - _iter = _safe, _safe = c_rbnode_next_postorder(_safe)) - -#define c_rbtree_for_each_entry_safe_postorder(_iter, _safe, _tree, _m) \ - for (_iter = c_rbnode_entry(c_rbtree_first_postorder(_tree), __typeof__(*_iter), _m), \ - _safe = _iter ? c_rbnode_entry(c_rbnode_next_postorder(&_iter->_m), __typeof__(*_iter), _m) : NULL; \ - _iter; \ - _iter = _safe, \ - _safe = _safe ? c_rbnode_entry(c_rbnode_next_postorder(&_safe->_m), __typeof__(*_iter), _m) : NULL) - -#define c_rbtree_for_each_safe_postorder_unlink(_iter, _safe, _tree) \ - for (_iter = c_rbtree_first_postorder(_tree), _safe = c_rbnode_next_postorder(_iter); \ - _iter ? ((*_iter = (CRBNode)C_RBNODE_INIT(*_iter)), 1) : (((_tree)->root = NULL), 0); \ - _iter = _safe, _safe = c_rbnode_next_postorder(_safe)) \ - -#define c_rbtree_for_each_entry_safe_postorder_unlink(_iter, _safe, _tree, _m) \ - for (_iter = c_rbnode_entry(c_rbtree_first_postorder(_tree), __typeof__(*_iter), _m), \ - _safe = _iter ? c_rbnode_entry(c_rbnode_next_postorder(&_iter->_m), __typeof__(*_iter), _m) : NULL; \ - _iter ? ((_iter->_m = (CRBNode)C_RBNODE_INIT(_iter->_m)), 1) : (((_tree)->root = NULL), 0); \ - _iter = _safe, \ - _safe = _safe ? c_rbnode_entry(c_rbnode_next_postorder(&_safe->_m), __typeof__(*_iter), _m) : NULL) - -#ifdef __cplusplus -} -#endif |