|
|
|
|
|
|
|
|
|
|
|
|
#ifndef RBTREE_H |
#define RBTREE_H |
|
|
|
#include "array.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct rb_node_hdr |
{ |
struct rb_node_hdr *prev, *next; |
unsigned INT16 flags; |
|
}; |
|
#define RB_RED 0x2000 |
#define RB_THREAD_PREV 0x4000 |
#define RB_THREAD_NEXT 0x8000 |
#define RB_FLAG_MASK 0xe000 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define keep_flags(node, code) do { \ |
INT16 kept_flags_ = (node)->flags; \ |
{code;} \ |
(node)->flags = \ |
((node)->flags & ~RB_FLAG_MASK) | (kept_flags_ & RB_FLAG_MASK); \ |
} while (0) |
|
PMOD_EXPORT struct rb_node_hdr *rb_first (struct rb_node_hdr *root); |
PMOD_EXPORT struct rb_node_hdr *rb_last (struct rb_node_hdr *root); |
PMOD_EXPORT struct rb_node_hdr *rb_link_prev (struct rb_node_hdr *node); |
PMOD_EXPORT struct rb_node_hdr *rb_link_next (struct rb_node_hdr *node); |
|
#define rb_prev(node) \ |
(DO_IF_RB_STATS (rb_num_sidesteps++ COMMA) \ |
(node)->flags & RB_THREAD_PREV ? \ |
DO_IF_RB_STATS (rb_num_sidestep_ops++ COMMA) (node)->prev : \ |
rb_link_prev (node)) |
#define rb_next(node) \ |
(DO_IF_RB_STATS (rb_num_sidesteps++ COMMA) \ |
(node)->flags & RB_THREAD_NEXT ? \ |
DO_IF_RB_STATS (rb_num_sidestep_ops++ COMMA) (node)->next : \ |
rb_link_next (node)) |
|
#ifdef PIKE_DEBUG |
|
static inline struct rb_node_hdr *rb_node_check (struct rb_node_hdr *node) |
{return node;} |
#else |
#define rb_node_check(node) ((struct rb_node_hdr *) (node)) |
#endif |
|
typedef int rb_find_fn (void *key, struct rb_node_hdr *node); |
typedef int rb_cmp_fn (struct rb_node_hdr *a, struct rb_node_hdr *b, void *extra); |
typedef int rb_equal_fn (struct rb_node_hdr *a, struct rb_node_hdr *b, void *extra); |
typedef struct rb_node_hdr *rb_copy_fn (struct rb_node_hdr *node, void *extra); |
typedef void rb_free_fn (struct rb_node_hdr *node, void *extra); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct rb_node_hdr *rb_insert (struct rb_node_hdr **root, |
rb_find_fn *find_fn, void *key, |
struct rb_node_hdr *new); |
void rb_add (struct rb_node_hdr **root, |
rb_find_fn *find_fn, void *key, |
struct rb_node_hdr *new); |
void rb_add_after (struct rb_node_hdr **root, |
rb_find_fn *find_fn, void *key, |
struct rb_node_hdr *new, |
struct rb_node_hdr *existing); |
struct rb_node_hdr *rb_remove (struct rb_node_hdr **root, |
rb_find_fn *find_fn, void *key); |
void rb_remove_node (struct rb_node_hdr **root, |
rb_find_fn *find_fn, void *key, |
struct rb_node_hdr *node); |
struct rb_node_hdr *rb_remove_with_move (struct rb_node_hdr **root, |
rb_find_fn *find_fn, void *key, |
size_t node_size, |
rb_free_fn *cleanup_fn, |
void *cleanup_fn_extra); |
struct rb_node_hdr *rb_remove_node_with_move (struct rb_node_hdr **root, |
rb_find_fn *find_fn, void *key, |
struct rb_node_hdr *node, |
size_t node_size); |
|
struct rb_node_hdr *rb_find_eq (struct rb_node_hdr *root, |
rb_find_fn *find_fn, void *key); |
struct rb_node_hdr *rb_find_lt (struct rb_node_hdr *root, |
rb_find_fn *find_fn, void *key); |
struct rb_node_hdr *rb_find_gt (struct rb_node_hdr *root, |
rb_find_fn *find_fn, void *key); |
struct rb_node_hdr *rb_find_le (struct rb_node_hdr *root, |
rb_find_fn *find_fn, void *key); |
struct rb_node_hdr *rb_find_ge (struct rb_node_hdr *root, |
rb_find_fn *find_fn, void *key); |
struct rb_node_hdr *rb_get_nth (struct rb_node_hdr *root, size_t n); |
size_t rb_sizeof (struct rb_node_hdr *root); |
|
void rb_free (struct rb_node_hdr *root, rb_free_fn *free_node_fn, void *extra); |
int rb_equal (struct rb_node_hdr *a, struct rb_node_hdr *b, |
rb_equal_fn *node_equal_fn, void *extra); |
struct rb_node_hdr *rb_copy (struct rb_node_hdr *source, |
rb_copy_fn *copy_node_fn, void *extra); |
|
struct rb_node_hdr *rb_make_list (struct rb_node_hdr *tree); |
struct rb_node_hdr *rb_make_tree (struct rb_node_hdr *list, size_t length); |
|
#define PIKE_MERGE_DESTR_A 0x2000 |
#define PIKE_MERGE_DESTR_B 0x1000 |
|
enum rb_merge_trees {MERGE_TREE_A, MERGE_TREE_B, MERGE_TREE_RES}; |
|
typedef struct rb_node_hdr *rb_merge_copy_fn (struct rb_node_hdr *node, void *extra, |
enum rb_merge_trees tree); |
typedef void rb_merge_free_fn (struct rb_node_hdr *node, void *extra, |
enum rb_merge_trees tree); |
|
struct rb_node_hdr *rb_linear_merge ( |
struct rb_node_hdr *a, struct rb_node_hdr *b, int operation, |
rb_cmp_fn *cmp_fn, void *cmp_fn_extra, |
rb_merge_copy_fn *copy_node_fn, void *copy_fn_extra, |
rb_merge_free_fn *free_node_fn, void *free_fn_extra, |
size_t *length); |
|
#ifdef RB_STATS |
extern size_t rb_num_sidesteps, rb_num_sidestep_ops; |
extern size_t rb_num_finds, rb_find_depth; |
extern size_t rb_num_tracks, rb_track_depth; |
extern size_t rb_num_sidetracks, rb_num_sidetrack_ops; |
extern size_t rb_max_depth; |
extern size_t rb_num_traverses, rb_num_traverse_ops; |
extern size_t rbstack_slice_allocs; |
extern size_t rb_num_adds, rb_add_rebalance_cnt; |
extern size_t rb_num_deletes, rb_del_rebalance_cnt; |
void reset_rb_stats(); |
void print_rb_stats (int reset); |
#define DO_IF_RB_STATS(X) X |
#else |
#define DO_IF_RB_STATS(X) |
#endif |
|
#endif /* RBTREE_H */ |
|
|