From: Wouter Wijngaards Date: Wed, 31 Jan 2007 12:25:06 +0000 (+0000) Subject: Rework rbtree to fit into unbound, doxygen comments. X-Git-Tag: release-0.0~78 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b48cc913ff3878b569c5dbb91ca42f23d30afe8c;p=thirdparty%2Funbound.git Rework rbtree to fit into unbound, doxygen comments. git-svn-id: file:///svn/unbound/trunk@47 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/util/rbtree.c b/util/rbtree.c index aaca1a043..76cef3df1 100644 --- a/util/rbtree.c +++ b/util/rbtree.c @@ -36,16 +36,21 @@ * */ -#include - -#include -#include +/** + * \file + * Implementation of a redblack tree. + */ -#include "rbtree.h" +#include "config.h" +#include "log.h" +#include "util/rbtree.h" +/** Node colour black */ #define BLACK 0 +/** Node colour red */ #define RED 1 +/** the NULL node, global alloc */ rbnode_t rbtree_null_node = { RBTREE_NULL, /* Parent. */ RBTREE_NULL, /* Left. */ @@ -54,9 +59,13 @@ rbnode_t rbtree_null_node = { BLACK /* Color. */ }; +/** rotate subtree left (to preserve redblack property). */ static void rbtree_rotate_left(rbtree_t *rbtree, rbnode_t *node); +/** rotate subtree right (to preserve redblack property). */ static void rbtree_rotate_right(rbtree_t *rbtree, rbnode_t *node); +/** Fixup node colours when insert happened */ static void rbtree_insert_fixup(rbtree_t *rbtree, rbnode_t *node); +/** Fixup node colours when delete happened */ static void rbtree_delete_fixup(rbtree_t* rbtree, rbnode_t* child, rbnode_t* child_parent); /* @@ -66,12 +75,12 @@ static void rbtree_delete_fixup(rbtree_t* rbtree, rbnode_t* child, rbnode_t* chi * */ rbtree_t * -rbtree_create (region_type *region, int (*cmpf)(const void *, const void *)) +rbtree_create (int (*cmpf)(const void *, const void *)) { rbtree_t *rbtree; /* Allocate memory for it */ - rbtree = (rbtree_t *) region_alloc(region, sizeof(rbtree_t)); + rbtree = (rbtree_t *) malloc(sizeof(rbtree_t)); if (!rbtree) { return NULL; } @@ -79,7 +88,6 @@ rbtree_create (region_type *region, int (*cmpf)(const void *, const void *)) /* Initialize it */ rbtree->root = RBTREE_NULL; rbtree->count = 0; - rbtree->region = region; rbtree->cmp = cmpf; return rbtree; @@ -273,34 +281,37 @@ rbtree_search (rbtree_t *rbtree, const void *key) } } -/* helpers for delete */ +/** helpers for delete: swap node colours */ static void swap_int8(uint8_t* x, uint8_t* y) { uint8_t t = *x; *x = *y; *y = t; } +/** helpers for delete: swap node pointers */ static void swap_np(rbnode_t** x, rbnode_t** y) { rbnode_t* t = *x; *x = *y; *y = t; } +/** Update parent pointers of child trees of 'parent'. */ static void change_parent_ptr(rbtree_t* rbtree, rbnode_t* parent, rbnode_t* old, rbnode_t* new) { if(parent == RBTREE_NULL) { - assert(rbtree->root == old); + log_assert(rbtree->root == old); if(rbtree->root == old) rbtree->root = new; return; } - assert(parent->left == old || parent->right == old + log_assert(parent->left == old || parent->right == old || parent->left == new || parent->right == new); if(parent->left == old) parent->left = new; if(parent->right == old) parent->right = new; } +/** Update parent pointer of a node 'child'. */ static void change_child_ptr(rbnode_t* child, rbnode_t* old, rbnode_t* new) { if(child == RBTREE_NULL) return; - assert(child->parent == old || child->parent == new); + log_assert(child->parent == old || child->parent == new); if(child->parent == old) child->parent = new; } @@ -354,7 +365,7 @@ rbtree_delete(rbtree_t *rbtree, const void *key) /* now delete to_delete (which is at the location where the smright previously was) */ } - assert(to_delete->left == RBTREE_NULL || to_delete->right == RBTREE_NULL); + log_assert(to_delete->left == RBTREE_NULL || to_delete->right == RBTREE_NULL); if(to_delete->left != RBTREE_NULL) child = to_delete->left; else child = to_delete->right; @@ -439,7 +450,7 @@ static void rbtree_delete_fixup(rbtree_t* rbtree, rbnode_t* child, rbnode_t* chi child_parent->color = BLACK; return; } - assert(sibling != RBTREE_NULL); + log_assert(sibling != RBTREE_NULL); /* get a new sibling, by rotating at sibling. See which child of sibling is red */ @@ -473,13 +484,13 @@ static void rbtree_delete_fixup(rbtree_t* rbtree, rbnode_t* child, rbnode_t* chi child_parent->color = BLACK; if(child_parent->right == child) { - assert(sibling->left->color == RED); + log_assert(sibling->left->color == RED); sibling->left->color = BLACK; rbtree_rotate_right(rbtree, child_parent); } else { - assert(sibling->right->color == RED); + log_assert(sibling->right->color == RED); sibling->right->color = BLACK; rbtree_rotate_left(rbtree, child_parent); } @@ -491,7 +502,7 @@ rbtree_find_less_equal(rbtree_t *rbtree, const void *key, rbnode_t **result) int r; rbnode_t *node; - assert(result); + log_assert(result); /* We start at root... */ node = rbtree->root; diff --git a/util/rbtree.h b/util/rbtree.h index c95f24301..e2353e8c2 100644 --- a/util/rbtree.h +++ b/util/rbtree.h @@ -36,70 +36,148 @@ * */ -#ifndef _RBTREE_H_ -#define _RBTREE_H_ +/** + * Red black tree. Implementation taken from NSD 3.0.5, adjusted for use + * in unbound (memory allocation, logging and so on). + */ -#include "region-allocator.h" +#ifndef UTIL_RBTREE_H_ +#define UTIL_RBTREE_H_ -/* +/** * This structure must be the first member of the data structure in * the rbtree. This allows easy casting between an rbnode_t and the * user data (poor man's inheritance). */ typedef struct rbnode_t rbnode_t; +/** + * The rbnore_t struct definition. + */ struct rbnode_t { + /** parent in rbtree, RBTREE_NULL for root */ rbnode_t *parent; + /** left node (smaller items) */ rbnode_t *left; + /** right node (larger items) */ rbnode_t *right; + /** pointer to sorting key */ const void *key; + /** colour of this node */ uint8_t color; }; +/** The nullpointer, points to empty node */ #define RBTREE_NULL &rbtree_null_node +/** the global empty node */ extern rbnode_t rbtree_null_node; +/** An entire red black tree */ typedef struct rbtree_t rbtree_t; +/** definition for tree struct */ struct rbtree_t { - region_type *region; - - /* The root of the red-black tree */ + /** The root of the red-black tree */ rbnode_t *root; - /* The number of the nodes in the tree */ + /** The number of the nodes in the tree */ size_t count; - /* Current node for walks... */ + /** Current node for walks... */ rbnode_t *_node; - /* Key compare function. <0,0,>0 like strcmp. Return 0 on two NULL ptrs. */ + /** + * Key compare function. <0,0,>0 like strcmp. + * Return 0 on two NULL ptrs. + */ int (*cmp) (const void *, const void *); }; -/* rbtree.c */ -rbtree_t *rbtree_create(region_type *region, int (*cmpf)(const void *, const void *)); +/** + * Create new tree (malloced) with given key compare function. + * @param cmpf: compare function (like strcmp) takes pointers to two keys. + * @return: new tree, empty. + */ +rbtree_t *rbtree_create(int (*cmpf)(const void *, const void *)); + +/** + * Insert data into the tree. + * @param rbtree: tree to insert to. + * @param data: element to insert. + * @return: data ptr or NULL if key already present. + */ rbnode_t *rbtree_insert(rbtree_t *rbtree, rbnode_t *data); -/* returns node that is now unlinked from the tree. User to delete it. - * returns 0 if node not present */ + +/** + * Delete element from tree. + * @param rbtree: tree to delete from. + * @param key: key of item to delete. + * @return: node that is now unlinked from the tree. User to delete it. + * returns 0 if node not present + */ rbnode_t *rbtree_delete(rbtree_t *rbtree, const void *key); + +/** + * Find key in tree. Returns NULL if not found. + * @param rbtree: tree to find in. + * @param key: key that must match. + * @return: node that fits or NULL. + */ rbnode_t *rbtree_search(rbtree_t *rbtree, const void *key); -/* returns true if exact match in result. Else result points to <= element, - or NULL if key is smaller than the smallest key. */ -int rbtree_find_less_equal(rbtree_t *rbtree, const void *key, rbnode_t **result); + +/** + * Find, but match does not have to be exact. + * @param rbtree: tree to find in. + * @param key: key to find position of. + * @param result: set to the exact node if present, otherwise to element that + * precedes the position of key in the tree. NULL if no smaller element. + * @return: true if exact match in result. Else result points to <= element, + * or NULL if key is smaller than the smallest key. + */ +int rbtree_find_less_equal(rbtree_t *rbtree, const void *key, + rbnode_t **result); + +/** + * Returns first (smallest) node in the tree + * @param rbtree: tree + * @return: smallest element or NULL if tree empty. + */ rbnode_t *rbtree_first(rbtree_t *rbtree); + +/** + * Returns last (largest) node in the tree + * @param rbtree: tree + * @return: largest element or NULL if tree empty. + */ rbnode_t *rbtree_last(rbtree_t *rbtree); + +/** + * Returns next larger node in the tree + * @param rbtree: tree + * @return: next larger element or NULL if no larger in tree. + */ rbnode_t *rbtree_next(rbnode_t *rbtree); + +/** + * Returns previous smaller node in the tree + * @param rbtree: tree + * @return: previous smaller element or NULL if no previous in tree. + */ rbnode_t *rbtree_previous(rbnode_t *rbtree); +/** + * Macro to walk through the tree, sets k to key, d to data, for every element. + */ #define RBTREE_WALK(rbtree, k, d) \ for((rbtree)->_node = rbtree_first(rbtree);\ (rbtree)->_node != RBTREE_NULL && ((k) = (rbtree)->_node->key) && \ ((d) = (void *) (rbtree)->_node); (rbtree)->_node = rbtree_next((rbtree)->_node)) -/* call with node=variable of struct* with rbnode_t as first element. - with type is the type of a pointer to that struct. */ +/** + * call with node=variable of struct* with rbnode_t as first element. + * with type is the type of a pointer to that struct. + */ #define RBTREE_FOR(node, type, rbtree) \ for(node=(type)rbtree_first(rbtree); \ (rbnode_t*)node != RBTREE_NULL; \ node = (type)rbtree_next((rbnode_t*)node)) -#endif /* _RBTREE_H_ */ +#endif /* UTIL_RBTREE_H_ */