1b7579f77SDag-Erling Smørgrav /* 2b7579f77SDag-Erling Smørgrav * rbtree.h -- generic red-black tree 3b7579f77SDag-Erling Smørgrav * 4b7579f77SDag-Erling Smørgrav * Copyright (c) 2001-2007, NLnet Labs. All rights reserved. 5b7579f77SDag-Erling Smørgrav * 6b7579f77SDag-Erling Smørgrav * This software is open source. 7b7579f77SDag-Erling Smørgrav * 8b7579f77SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 9b7579f77SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 10b7579f77SDag-Erling Smørgrav * are met: 11b7579f77SDag-Erling Smørgrav * 12b7579f77SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 13b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer. 14b7579f77SDag-Erling Smørgrav * 15b7579f77SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 16b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 17b7579f77SDag-Erling Smørgrav * and/or other materials provided with the distribution. 18b7579f77SDag-Erling Smørgrav * 19b7579f77SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 20b7579f77SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 21b7579f77SDag-Erling Smørgrav * specific prior written permission. 22b7579f77SDag-Erling Smørgrav * 23b7579f77SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2417d15b25SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2517d15b25SDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2617d15b25SDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2717d15b25SDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2817d15b25SDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2917d15b25SDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3017d15b25SDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3117d15b25SDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3217d15b25SDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3317d15b25SDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34b7579f77SDag-Erling Smørgrav * 35b7579f77SDag-Erling Smørgrav */ 36b7579f77SDag-Erling Smørgrav 37b7579f77SDag-Erling Smørgrav /** 38b7579f77SDag-Erling Smørgrav * \file 39b7579f77SDag-Erling Smørgrav * Red black tree. Implementation taken from NSD 3.0.5, adjusted for use 40b7579f77SDag-Erling Smørgrav * in unbound (memory allocation, logging and so on). 41b7579f77SDag-Erling Smørgrav */ 42b7579f77SDag-Erling Smørgrav 43b7579f77SDag-Erling Smørgrav #ifndef UTIL_RBTREE_H_ 44b7579f77SDag-Erling Smørgrav #define UTIL_RBTREE_H_ 45b7579f77SDag-Erling Smørgrav 46b7579f77SDag-Erling Smørgrav /** 47b7579f77SDag-Erling Smørgrav * This structure must be the first member of the data structure in 48*3005e0a3SDag-Erling Smørgrav * the rbtree. This allows easy casting between an rbnode_type and the 49b7579f77SDag-Erling Smørgrav * user data (poor man's inheritance). 50b7579f77SDag-Erling Smørgrav */ 51*3005e0a3SDag-Erling Smørgrav typedef struct rbnode_type rbnode_type; 52b7579f77SDag-Erling Smørgrav /** 53*3005e0a3SDag-Erling Smørgrav * The rbnode_type struct definition. 54b7579f77SDag-Erling Smørgrav */ 55*3005e0a3SDag-Erling Smørgrav struct rbnode_type { 56b7579f77SDag-Erling Smørgrav /** parent in rbtree, RBTREE_NULL for root */ 57*3005e0a3SDag-Erling Smørgrav rbnode_type *parent; 58b7579f77SDag-Erling Smørgrav /** left node (smaller items) */ 59*3005e0a3SDag-Erling Smørgrav rbnode_type *left; 60b7579f77SDag-Erling Smørgrav /** right node (larger items) */ 61*3005e0a3SDag-Erling Smørgrav rbnode_type *right; 62b7579f77SDag-Erling Smørgrav /** pointer to sorting key */ 63b7579f77SDag-Erling Smørgrav const void *key; 64b7579f77SDag-Erling Smørgrav /** colour of this node */ 65b7579f77SDag-Erling Smørgrav uint8_t color; 66b7579f77SDag-Erling Smørgrav }; 67b7579f77SDag-Erling Smørgrav 68b7579f77SDag-Erling Smørgrav /** The nullpointer, points to empty node */ 69b7579f77SDag-Erling Smørgrav #define RBTREE_NULL &rbtree_null_node 70b7579f77SDag-Erling Smørgrav /** the global empty node */ 71*3005e0a3SDag-Erling Smørgrav extern rbnode_type rbtree_null_node; 72b7579f77SDag-Erling Smørgrav 73b7579f77SDag-Erling Smørgrav /** An entire red black tree */ 74*3005e0a3SDag-Erling Smørgrav typedef struct rbtree_type rbtree_type; 75b7579f77SDag-Erling Smørgrav /** definition for tree struct */ 76*3005e0a3SDag-Erling Smørgrav struct rbtree_type { 77b7579f77SDag-Erling Smørgrav /** The root of the red-black tree */ 78*3005e0a3SDag-Erling Smørgrav rbnode_type *root; 79b7579f77SDag-Erling Smørgrav 80b7579f77SDag-Erling Smørgrav /** The number of the nodes in the tree */ 81b7579f77SDag-Erling Smørgrav size_t count; 82b7579f77SDag-Erling Smørgrav 83b7579f77SDag-Erling Smørgrav /** 84b7579f77SDag-Erling Smørgrav * Key compare function. <0,0,>0 like strcmp. 85b7579f77SDag-Erling Smørgrav * Return 0 on two NULL ptrs. 86b7579f77SDag-Erling Smørgrav */ 87b7579f77SDag-Erling Smørgrav int (*cmp) (const void *, const void *); 88b7579f77SDag-Erling Smørgrav }; 89b7579f77SDag-Erling Smørgrav 90b7579f77SDag-Erling Smørgrav /** 91b7579f77SDag-Erling Smørgrav * Create new tree (malloced) with given key compare function. 92b7579f77SDag-Erling Smørgrav * @param cmpf: compare function (like strcmp) takes pointers to two keys. 93b7579f77SDag-Erling Smørgrav * @return: new tree, empty. 94b7579f77SDag-Erling Smørgrav */ 95*3005e0a3SDag-Erling Smørgrav rbtree_type *rbtree_create(int (*cmpf)(const void *, const void *)); 96b7579f77SDag-Erling Smørgrav 97b7579f77SDag-Erling Smørgrav /** 98b7579f77SDag-Erling Smørgrav * Init a new tree (malloced by caller) with given key compare function. 99b7579f77SDag-Erling Smørgrav * @param rbtree: uninitialised memory for new tree, returned empty. 100b7579f77SDag-Erling Smørgrav * @param cmpf: compare function (like strcmp) takes pointers to two keys. 101b7579f77SDag-Erling Smørgrav */ 102*3005e0a3SDag-Erling Smørgrav void rbtree_init(rbtree_type *rbtree, int (*cmpf)(const void *, const void *)); 103b7579f77SDag-Erling Smørgrav 104b7579f77SDag-Erling Smørgrav /** 105b7579f77SDag-Erling Smørgrav * Insert data into the tree. 106b7579f77SDag-Erling Smørgrav * @param rbtree: tree to insert to. 107b7579f77SDag-Erling Smørgrav * @param data: element to insert. 108b7579f77SDag-Erling Smørgrav * @return: data ptr or NULL if key already present. 109b7579f77SDag-Erling Smørgrav */ 110*3005e0a3SDag-Erling Smørgrav rbnode_type *rbtree_insert(rbtree_type *rbtree, rbnode_type *data); 111b7579f77SDag-Erling Smørgrav 112b7579f77SDag-Erling Smørgrav /** 113b7579f77SDag-Erling Smørgrav * Delete element from tree. 114b7579f77SDag-Erling Smørgrav * @param rbtree: tree to delete from. 115b7579f77SDag-Erling Smørgrav * @param key: key of item to delete. 116b7579f77SDag-Erling Smørgrav * @return: node that is now unlinked from the tree. User to delete it. 117b7579f77SDag-Erling Smørgrav * returns 0 if node not present 118b7579f77SDag-Erling Smørgrav */ 119*3005e0a3SDag-Erling Smørgrav rbnode_type *rbtree_delete(rbtree_type *rbtree, const void *key); 120b7579f77SDag-Erling Smørgrav 121b7579f77SDag-Erling Smørgrav /** 122b7579f77SDag-Erling Smørgrav * Find key in tree. Returns NULL if not found. 123b7579f77SDag-Erling Smørgrav * @param rbtree: tree to find in. 124b7579f77SDag-Erling Smørgrav * @param key: key that must match. 125b7579f77SDag-Erling Smørgrav * @return: node that fits or NULL. 126b7579f77SDag-Erling Smørgrav */ 127*3005e0a3SDag-Erling Smørgrav rbnode_type *rbtree_search(rbtree_type *rbtree, const void *key); 128b7579f77SDag-Erling Smørgrav 129b7579f77SDag-Erling Smørgrav /** 130b7579f77SDag-Erling Smørgrav * Find, but match does not have to be exact. 131b7579f77SDag-Erling Smørgrav * @param rbtree: tree to find in. 132b7579f77SDag-Erling Smørgrav * @param key: key to find position of. 133b7579f77SDag-Erling Smørgrav * @param result: set to the exact node if present, otherwise to element that 134b7579f77SDag-Erling Smørgrav * precedes the position of key in the tree. NULL if no smaller element. 135b7579f77SDag-Erling Smørgrav * @return: true if exact match in result. Else result points to <= element, 136b7579f77SDag-Erling Smørgrav * or NULL if key is smaller than the smallest key. 137b7579f77SDag-Erling Smørgrav */ 138*3005e0a3SDag-Erling Smørgrav int rbtree_find_less_equal(rbtree_type *rbtree, const void *key, 139*3005e0a3SDag-Erling Smørgrav rbnode_type **result); 140b7579f77SDag-Erling Smørgrav 141b7579f77SDag-Erling Smørgrav /** 142b7579f77SDag-Erling Smørgrav * Returns first (smallest) node in the tree 143b7579f77SDag-Erling Smørgrav * @param rbtree: tree 144b7579f77SDag-Erling Smørgrav * @return: smallest element or NULL if tree empty. 145b7579f77SDag-Erling Smørgrav */ 146*3005e0a3SDag-Erling Smørgrav rbnode_type *rbtree_first(rbtree_type *rbtree); 147b7579f77SDag-Erling Smørgrav 148b7579f77SDag-Erling Smørgrav /** 149b7579f77SDag-Erling Smørgrav * Returns last (largest) node in the tree 150b7579f77SDag-Erling Smørgrav * @param rbtree: tree 151b7579f77SDag-Erling Smørgrav * @return: largest element or NULL if tree empty. 152b7579f77SDag-Erling Smørgrav */ 153*3005e0a3SDag-Erling Smørgrav rbnode_type *rbtree_last(rbtree_type *rbtree); 154b7579f77SDag-Erling Smørgrav 155b7579f77SDag-Erling Smørgrav /** 156b7579f77SDag-Erling Smørgrav * Returns next larger node in the tree 157b7579f77SDag-Erling Smørgrav * @param rbtree: tree 158b7579f77SDag-Erling Smørgrav * @return: next larger element or NULL if no larger in tree. 159b7579f77SDag-Erling Smørgrav */ 160*3005e0a3SDag-Erling Smørgrav rbnode_type *rbtree_next(rbnode_type *rbtree); 161b7579f77SDag-Erling Smørgrav 162b7579f77SDag-Erling Smørgrav /** 163b7579f77SDag-Erling Smørgrav * Returns previous smaller node in the tree 164b7579f77SDag-Erling Smørgrav * @param rbtree: tree 165b7579f77SDag-Erling Smørgrav * @return: previous smaller element or NULL if no previous in tree. 166b7579f77SDag-Erling Smørgrav */ 167*3005e0a3SDag-Erling Smørgrav rbnode_type *rbtree_previous(rbnode_type *rbtree); 168b7579f77SDag-Erling Smørgrav 169b7579f77SDag-Erling Smørgrav /** 170*3005e0a3SDag-Erling Smørgrav * Call with node=variable of struct* with rbnode_type as first element. 171b7579f77SDag-Erling Smørgrav * with type is the type of a pointer to that struct. 172b7579f77SDag-Erling Smørgrav */ 173b7579f77SDag-Erling Smørgrav #define RBTREE_FOR(node, type, rbtree) \ 174b7579f77SDag-Erling Smørgrav for(node=(type)rbtree_first(rbtree); \ 175*3005e0a3SDag-Erling Smørgrav (rbnode_type*)node != RBTREE_NULL; \ 176*3005e0a3SDag-Erling Smørgrav node = (type)rbtree_next((rbnode_type*)node)) 177b7579f77SDag-Erling Smørgrav 178b7579f77SDag-Erling Smørgrav /** 179b7579f77SDag-Erling Smørgrav * Call function for all elements in the redblack tree, such that 180b7579f77SDag-Erling Smørgrav * leaf elements are called before parent elements. So that all 181b7579f77SDag-Erling Smørgrav * elements can be safely free()d. 182b7579f77SDag-Erling Smørgrav * Note that your function must not remove the nodes from the tree. 183b7579f77SDag-Erling Smørgrav * Since that may trigger rebalances of the rbtree. 184b7579f77SDag-Erling Smørgrav * @param tree: the tree 185b7579f77SDag-Erling Smørgrav * @param func: function called with element and user arg. 186b7579f77SDag-Erling Smørgrav * The function must not alter the rbtree. 187b7579f77SDag-Erling Smørgrav * @param arg: user argument. 188b7579f77SDag-Erling Smørgrav */ 189*3005e0a3SDag-Erling Smørgrav void traverse_postorder(rbtree_type* tree, void (*func)(rbnode_type*, void*), 190b7579f77SDag-Erling Smørgrav void* arg); 191b7579f77SDag-Erling Smørgrav 192b7579f77SDag-Erling Smørgrav #endif /* UTIL_RBTREE_H_ */ 193