pike.git
/
src
/
rbtree.h
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/rbtree.h:1:
/* An implementation of a threaded red/black balanced binary tree. * * Created 2001-04-27 by Martin Stjernholm *
-
* $Id: rbtree.h,v 1.
1
2001/
04
/
30
17
:
30
:
25
mast Exp $
+
* $Id: rbtree.h,v 1.
2
2001/
05
/
01
01
:
11
:
23
mast Exp $
*/ #ifndef RBTREE_H #define RBTREE_H
-
+
#include "array.h"
+
/* A red/black tree is a binary tree with one extra bit of info in * each node - the color of it. The following properties holds: * * o Every node is either red or black. * o A NULL leaf is considered black. * o If a node is red, its children must be black. * o Every path from a node down to all its leafs have the same * number of black nodes. * * The longest possible path in a given tree thus have alternating red
pike.git/src/rbtree.h:24:
*/ struct rb_node_hdr { struct rb_node_hdr *prev, *next; unsigned INT16 flags; /* Overlays svalue type field in * rb_node_ind and rb_node_indval. */ }; /* Note: Don't access the ind svalue (or at least not its type field) * in the following directly, since the flags above overlay that. Use
-
* assign_rb_node_ind_no_free() instead. */
+
* assign_rb_node_ind_no_free()
or similar
instead. */
struct rb_node_ind { struct rb_node_ind *prev, *next; /* Must be first. */ struct svalue ind; }; struct rb_node_indval { struct rb_node_indval *prev, *next; /* Must be first. */ struct svalue ind, val; };
pike.git/src/rbtree.h:72:
* ... . thread pointer . ... * \ . . / * c . . c * / \.. ../ \ */ #define RB_FLAG_MARKER 0x1000 #define RB_IND_FLAG_MASK 0xf000 /* The flag marker is set to nail direct uses of the ind type field. */
+
PMOD_EXPORT int rb_ind_default_cmp (struct svalue *key, union rb_node *node);
+
typedef int low_rb_cmp_fn (void *key, struct rb_node_hdr *node);
+
+
PMOD_EXPORT union rb_node *rb_find_eq_extcmp (union rb_node *tree, struct svalue *key,
+
struct svalue *cmp_less);
+
PMOD_EXPORT union rb_node *rb_find_lt_extcmp (union rb_node *tree, struct svalue *key,
+
struct svalue *cmp_less);
+
PMOD_EXPORT union rb_node *rb_find_gt_extcmp (union rb_node *tree, struct svalue *key,
+
struct svalue *cmp_less);
+
PMOD_EXPORT union rb_node *rb_find_le_extcmp (union rb_node *tree, struct svalue *key,
+
struct svalue *cmp_less);
+
PMOD_EXPORT union rb_node *rb_find_ge_extcmp (union rb_node *tree, struct svalue *key,
+
struct svalue *cmp_less);
+
PMOD_EXPORT struct rb_node_hdr *rb_first (struct rb_node_hdr *tree);
+
PMOD_EXPORT struct rb_node_hdr *rb_last (struct rb_node_hdr *tree);
+
PMOD_EXPORT struct rb_node_hdr *rb_prev (struct rb_node_hdr *node);
+
PMOD_EXPORT struct rb_node_hdr *rb_next (struct rb_node_hdr *node);
+
+
#ifdef PIKE_DEBUG
+
/* To get good type checking. */
+
static inline struct rb_node_hdr *rb_node_ind_check (struct rb_node_ind *node)
+
{return (struct rb_node_hdr *) node;}
+
static inline struct rb_node_hdr *rb_node_indval_check (struct rb_node_indval *node)
+
{return (struct rb_node_hdr *) node;}
+
#else
+
#define rb_node_ind_check(node) ((struct rb_node_hdr *) (node))
+
#define rb_node_indval_check(node) ((struct rb_node_hdr *) (node))
+
#endif
+
+
#define RB_DECL_FIND_FUNC(type, func, tree, key, cmp_less) \
+
((struct type *) debug_malloc_pass ( \
+
(cmp_less) ? (struct rb_node_hdr *) PIKE_CONCAT (func, _extcmp) ( \
+
(union rb_node *) debug_malloc_pass (PIKE_CONCAT (type, _check) (tree)), \
+
dmalloc_touch (struct svalue *, key), \
+
(cmp_less)) \
+
: PIKE_CONCAT (low_, func) ( \
+
(struct rb_node_hdr *) debug_malloc_pass (PIKE_CONCAT (type, _check) (tree)), \
+
(low_rb_cmp_fn *) rb_ind_default_cmp, \
+
dmalloc_touch (struct svalue *, key))))
+
#define RB_DECL_STEP_FUNC(type, func, node) \
+
((struct type *) debug_malloc_pass ( \
+
func ((struct rb_node_hdr *) debug_malloc_pass (PIKE_CONCAT (type, _check) (node)))))
+
/* Operations: * * insert: * Adds a new entry only if one with the same index doesn't exist * already, replaces it otherwise. If a node was added it's * returned, otherwise zero is returned. * * add: * Adds a new entry, even if one with the same index already * exists. Returns the newly created node.
pike.git/src/rbtree.h:98:
* Deletes an arbitrary entry with the specified index, if one * exists. Returns nonzero in that case, zero otherwise. * * delete_node: * Deletes the given node from the tree. Useful to get the right * entry when several have the same index. The node is assumed to * exist in the tree. Note that it's a linear search to get the * right node among several with the same index. * * find_eq:
-
* Returns an arbitrary entry which
have
the given index, or zero
+
* Returns an arbitrary entry which
has
the given index, or zero
* if none exists. * * find_lt, find_gt, find_le, find_ge: * find_lt and find_le returns the biggest entry which satisfy the * condition, and vice versa for the other two. This means that * e.g. rb_next when used on the returned node from find_le never * returns an entry with the same index. * * If cmp_less is nonzero, it's a function pointer used as `< to * compare the entries. If it's zero the internal set order is used.
pike.git/src/rbtree.h:124:
struct svalue *ind, struct svalue *cmp_less); PMOD_EXPORT struct rb_node_ind *rb_ind_add (struct rb_node_ind **tree, struct svalue *ind, struct svalue *cmp_less); PMOD_EXPORT int rb_ind_delete (struct rb_node_ind **tree, struct svalue *ind, struct svalue *cmp_less); PMOD_EXPORT struct rb_node_ind *rb_ind_copy (struct rb_node_ind *tree); PMOD_EXPORT void rb_ind_free (struct rb_node_ind *tree);
+
#define rb_ind_find_eq(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_ind, rb_find_eq, tree, key, cmp_less)
+
#define rb_ind_find_lt(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_ind, rb_find_lt, tree, key, cmp_less)
+
#define rb_ind_find_gt(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_ind, rb_find_gt, tree, key, cmp_less)
+
#define rb_ind_find_le(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_ind, rb_find_le, tree, key, cmp_less)
+
#define rb_ind_find_ge(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_ind, rb_find_ge, tree, key, cmp_less)
+
#define rb_ind_first(tree) RB_DECL_STEP_FUNC (rb_node_ind, rb_first, tree)
+
#define rb_ind_last(tree) RB_DECL_STEP_FUNC (rb_node_ind, rb_last, tree)
+
#define rb_ind_prev(tree) RB_DECL_STEP_FUNC (rb_node_ind, rb_prev, tree)
+
#define rb_ind_next(tree) RB_DECL_STEP_FUNC (rb_node_ind, rb_next, tree)
/* Functions for handling nodes with index and value. */ PMOD_EXPORT struct rb_node_indval *rb_indval_insert (struct rb_node_indval **tree, struct svalue *ind, struct svalue *val, struct svalue *cmp_less); PMOD_EXPORT struct rb_node_indval *rb_indval_add (struct rb_node_indval **tree, struct svalue *ind, struct svalue *val, struct svalue *cmp_less);
pike.git/src/rbtree.h:147:
struct svalue *val, struct svalue *cmp_less); PMOD_EXPORT int rb_indval_delete (struct rb_node_indval **tree, struct svalue *ind, struct svalue *cmp_less); PMOD_EXPORT struct rb_node_indval *rb_indval_delete_node (struct rb_node_indval **tree, struct rb_node_indval *node, struct svalue *cmp_less); PMOD_EXPORT struct rb_node_indval *rb_indval_copy (struct rb_node_indval *tree); PMOD_EXPORT void rb_indval_free (struct rb_node_indval *tree);
+
#define rb_indval_find_eq(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_indval, rb_find_eq, tree, key, cmp_less)
+
#define rb_indval_find_lt(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_indval, rb_find_lt, tree, key, cmp_less)
+
#define rb_indval_find_gt(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_indval, rb_find_gt, tree, key, cmp_less)
+
#define rb_indval_find_le(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_indval, rb_find_le, tree, key, cmp_less)
+
#define rb_indval_find_ge(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_indval, rb_find_ge, tree, key, cmp_less)
+
#define rb_indval_first(tree) RB_DECL_STEP_FUNC (rb_node_indval, rb_first, tree)
+
#define rb_indval_last(tree) RB_DECL_STEP_FUNC (rb_node_indval, rb_last, tree)
+
#define rb_indval_prev(tree) RB_DECL_STEP_FUNC (rb_node_indval, rb_prev, tree)
+
#define rb_indval_next(tree) RB_DECL_STEP_FUNC (rb_node_indval, rb_next, tree)
-
/* Functions for handling both types of nodes. */
-
PMOD_EXPORT union rb_node *rb_find_eq (union rb_node *tree, struct svalue *key,
-
struct svalue *cmp_less);
-
PMOD_EXPORT union rb_node *rb_find_lt (union rb_node *tree, struct svalue *key,
-
struct svalue *cmp_less);
-
PMOD_EXPORT union rb_node *rb_find_gt (union rb_node *tree, struct svalue *key,
-
struct svalue *cmp_less);
-
PMOD_EXPORT union rb_node *rb_find_le (union rb_node *tree, struct svalue *key,
-
struct svalue *cmp_less);
-
PMOD_EXPORT union rb_node *rb_find_ge (union rb_node *tree, struct svalue *key,
-
struct svalue *cmp_less);
-
-
/* Functions for handling any type of node. */
-
PMOD_EXPORT struct rb_node_hdr *rb_first (struct rb_node_hdr *tree);
-
PMOD_EXPORT struct rb_node_hdr *rb_last (struct rb_node_hdr *tree);
-
PMOD_EXPORT struct rb_node_hdr *rb_prev (struct rb_node_hdr *node);
-
PMOD_EXPORT struct rb_node_hdr *rb_next (struct rb_node_hdr *node);
-
-
#define RB_IND_FIND_FUNC(func, tree, key, cmp_less) \
-
((struct rb_node_ind *) func ((union rb_node *) (tree), (key), (cmp_less)))
-
#define RB_IND_STEP_FUNC(func, tree) \
-
((struct rb_node_ind *) func ((struct rb_node_hdr *) (tree)))
-
-
#define rb_ind_find_eq(tree, key, cmp_less) \
-
RB_IND_FIND_FUNC (rb_find_eq, tree, key, cmp_less)
-
#define rb_ind_find_lt(tree, key, cmp_less) \
-
RB_IND_FIND_FUNC (rb_find_lt, tree, key, cmp_less)
-
#define rb_ind_find_gt(tree, key, cmp_less) \
-
RB_IND_FIND_FUNC (rb_find_gt, tree, key, cmp_less)
-
#define rb_ind_find_le(tree, key, cmp_less) \
-
RB_IND_FIND_FUNC (rb_find_le, tree, key, cmp_less)
-
#define rb_ind_find_ge(tree, key, cmp_less) \
-
RB_IND_FIND_FUNC (rb_find_ge, tree, key, cmp_less)
-
#define rb_ind_first(tree) RB_IND_STEP_FUNC (rb_first, tree)
-
#define rb_ind_last(tree) RB_IND_STEP_FUNC (rb_last, tree)
-
#define rb_ind_prev(tree) RB_IND_STEP_FUNC (rb_prev, tree)
-
#define rb_ind_next(tree) RB_IND_STEP_FUNC (rb_next, tree)
-
-
#define RB_INDVAL_FIND_FUNC(func, tree, key, cmp_less) \
-
((struct rb_node_indval *) func ((union rb_node *) (tree), (key), (cmp_less)))
-
#define RB_INDVAL_STEP_FUNC(func, tree) \
-
((struct rb_node_indval *) func ((struct rb_node_hdr *) (tree)))
-
-
#define rb_indval_find_eq(tree, key, cmp_less) \
-
RB_INDVAL_FIND_FUNC (rb_find_eq, tree, key, cmp_less)
-
#define rb_indval_find_lt(tree, key, cmp_less) \
-
RB_INDVAL_FIND_FUNC (rb_find_lt, tree, key, cmp_less)
-
#define rb_indval_find_gt(tree, key, cmp_less) \
-
RB_INDVAL_FIND_FUNC (rb_find_gt, tree, key, cmp_less)
-
#define rb_indval_find_le(tree, key, cmp_less) \
-
RB_INDVAL_FIND_FUNC (rb_find_le, tree, key, cmp_less)
-
#define rb_indval_find_ge(tree, key, cmp_less) \
-
RB_INDVAL_FIND_FUNC (rb_find_ge, tree, key, cmp_less)
-
#define rb_indval_first(tree) RB_INDVAL_STEP_FUNC (rb_first, tree)
-
#define rb_indval_last(tree) RB_INDVAL_STEP_FUNC (rb_last, tree)
-
#define rb_indval_prev(tree) RB_INDVAL_STEP_FUNC (rb_prev, tree)
-
#define rb_indval_next(tree) RB_INDVAL_STEP_FUNC (rb_next, tree)
-
+
/* Accessing the index svalue in a node. */ #define assign_rb_node_ind_no_free(to, node) do { \ struct svalue *_rb_node_to = (to); \ *_rb_node_to = (node)->ind; \ _rb_node_to->type &= ~RB_IND_FLAG_MASK; \ add_ref_svalue (_rb_node_to); \ } while (0) #define assign_rb_node_ind(to, node) do { \ struct svalue *_rb_node_to2 = (to); \
pike.git/src/rbtree.h:390:
fprintf (stderr, "%*s%p between\n", \ PIKE_CONCAT (depth_, label) - 1, "", node); {between;}, \ fprintf (stderr, "%*s%p next leaf\n", \ PIKE_CONCAT (depth_, label), "", node); {n_leaf;}, \ fprintf (stderr, "%*s%p next subtree\n", \ PIKE_CONCAT (depth_, label), "", node); {n_sub;}, \ fprintf (stderr, "%*s%p leave\n", \ --PIKE_CONCAT (depth_, label), "", node); {pop;}); \ } while (0)
+
/* The `cmp' code should set the variable cmp_res to the result of the
+
* comparison between the key and the current node `node'. */
#define LOW_RB_FIND(node, cmp, got_lt, got_eq, got_gt) \ do { \ int cmp_res; \ while (1) { \ DO_IF_DEBUG (if (!node) fatal ("Recursing into null node.\n")); \ {cmp;} \ if (cmp_res > 0) { \ if ((node)->flags & RB_THREAD_NEXT) { \ {got_lt;} \ break; \
pike.git/src/rbtree.h:452:
else { \ node = node->next; \ RBSTACK_PUSH (slice, ssp, node); \ while (!(node->flags & RB_THREAD_PREV)) { \ node = node->prev; \ RBSTACK_PUSH (slice, ssp, node); \ } \ } \ } while (0)
-
typedef
int
low_rb_
cmp
_
fn
(
void
*
key
,
struct
rb_node_
hdr
*node);
+
/*
An
alternative to
low_rb_
insert, which might or might not insert
+
* the newly created node. This one compares nodes like LOW
_
RB_FIND
+
* and will only run the code `insert' when a new node actually is to
+
* be inserted, otherwise it runs the code `replace' on the matching
+
* existing node. */
+
#define LOW_RB_INSERT
(
tree,
node, cmp, insert, replace) \
+
do { \
+
if (((node) =
*
(tree))) { \
+
RBSTACK_INIT (slice
,
ssp);
\
+
LOW_RB_TRACK (slice, ssp, node, cmp, { \
+
DO_IF_DEBUG ((node) = 0); \
+
{insert;} \
+
low_
rb_
link_at_next ((tree), slice, ssp, (
node
)); \
+
}, { \
+
{replace;} \
+
RBSTACK
_
FREE
(slice); \
+
}, { \
+
DO_IF_DEBUG ((node) = 0); \
+
{insert;} \
+
low_rb_link_at_prev ((tree), slice, ssp, (node)); \
+
}); \
+
} \
+
else { \
+
{insert;} \
+
low_rb_init_root (
*
(tree) = (
node)
)
;
\
+
} \
+
} while (0)
/* Used when unlinking nodes. Since an interior node can't be unlinked * we need to move over the data from a leaf node and unlink that * instead. */ typedef void low_rb_move_data_fn (struct rb_node_hdr *to, struct rb_node_hdr *from); typedef struct rb_node_hdr *low_rb_alloc_copy_fn (struct rb_node_hdr *node); void low_rb_init_root (struct rb_node_hdr *new_root);