*
*/
-#include <config.h>
-
-#include <assert.h>
-#include <stdlib.h>
+/**
+ * \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. */
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);
/*
*
*/
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;
}
/* Initialize it */
rbtree->root = RBTREE_NULL;
rbtree->count = 0;
- rbtree->region = region;
rbtree->cmp = cmpf;
return rbtree;
}
}
-/* 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;
}
/* 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;
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 */
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);
}
int r;
rbnode_t *node;
- assert(result);
+ log_assert(result);
/* We start at root... */
node = rbtree->root;
*
*/
-#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_ */