e576bb | 2002-10-11 | Martin Nilsson | | |
7b62e2 | 2011-04-25 | Martin Stjernholm | | || $Id$
|
e576bb | 2002-10-11 | Martin Nilsson | | */
|
1b10db | 2002-10-08 | Martin Nilsson | |
|
c550c2 | 2001-04-30 | Martin Stjernholm | | |
eed89d | 2001-12-10 | Martin Stjernholm | | * Created 2001-04-27 by Martin Stjernholm <mast@lysator.liu.se>
|
c550c2 | 2001-04-30 | Martin Stjernholm | | */
#include "global.h"
|
7b62e2 | 2011-04-25 | Martin Stjernholm | | RCSID("$Id$");
|
881484 | 2001-05-01 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | #include "interpret.h"
#include "pike_error.h"
#include "rbtree_low.h"
#include <assert.h>
#include <stdlib.h>
#if defined (PIKE_DEBUG) || defined (TEST_MULTISET)
DECLSPEC(noreturn) static void debug_rb_fatal (
struct rb_node_hdr *tree,
const char *fmt, ...) ATTRIBUTE((noreturn, format (printf, 2, 3)));
#define rb_fatal \
(fprintf (stderr, "%s:%d: Fatal in rbtree: ", __FILE__, __LINE__), \
debug_rb_fatal)
DECLSPEC(noreturn) static void debug_custom_rb_fatal (
struct rb_node_hdr *tree, dump_data_fn *dump_data,
void *extra, const char *fmt, ...) ATTRIBUTE((noreturn, format (printf, 4, 5)));
#define custom_rb_fatal \
(fprintf (stderr, "%s:%d: Fatal in rbtree: ", __FILE__, __LINE__), \
debug_custom_rb_fatal)
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
#endif
|
eed89d | 2001-12-10 | Martin Stjernholm | | void rbstack_push (struct rbstack_ptr *rbstack, struct rb_node_hdr *node)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rbstack_slice *new = ALLOC_STRUCT (rbstack_slice);
new->up = rbstack->slice;
new->stack[0] = node;
#ifdef RB_STATS
rbstack_slice_allocs++;
new->depth = rbstack->slice->depth;
new->maxdepth = rbstack->slice->maxdepth;
#endif
rbstack->slice = new;
rbstack->ssp = 1;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | void rbstack_pop (struct rbstack_ptr *rbstack)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rbstack_slice *old = rbstack->slice;
rbstack->slice = old->up;
#ifdef RB_STATS
rbstack->slice->maxdepth = old->maxdepth;
#endif
xfree (old);
rbstack->ssp = STACK_SLICE_SIZE;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | void rbstack_up (struct rbstack_ptr *rbstack)
|
881484 | 2001-05-01 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | rbstack->slice = rbstack->slice->up;
rbstack->ssp = STACK_SLICE_SIZE;
|
881484 | 2001-05-01 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | void rbstack_up_to_root (struct rbstack_ptr *rbstack)
|
881484 | 2001-05-01 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rbstack_slice *up;
while ((up = rbstack->slice->up)) rbstack->slice = up;
rbstack->ssp = 0;
|
881484 | 2001-05-01 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | void rbstack_free (struct rbstack_ptr *rbstack)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rbstack_slice *ptr = rbstack->slice;
do {
struct rbstack_slice *old = ptr;
ptr = ptr->up;
#ifdef RB_STATS
ptr->maxdepth = old->maxdepth;
#endif
xfree (old);
} while (ptr->up);
rbstack->slice = ptr;
rbstack->ssp = 0;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | |
void rbstack_insert (struct rbstack_ptr *top, struct rbstack_ptr *pos,
struct rb_node_hdr *node)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rbstack_ptr rbp1 = *top, rbp2 = *top, rbpos = *pos;
RBSTACK_PUSH (rbp2, NULL);
*top = rbp2;
while (rbp1.ssp != rbpos.ssp || rbp1.slice != rbpos.slice) {
rbp2.slice->stack[--rbp2.ssp] = rbp1.slice->stack[--rbp1.ssp];
if (!rbp2.ssp) rbp2.slice = rbp1.slice, rbp2.ssp = STACK_SLICE_SIZE;
if (!rbp1.ssp) {
if (rbp1.slice->up) rbstack_up (&rbp1);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
eed89d | 2001-12-10 | Martin Stjernholm | | else if (rbp1.ssp != rbpos.ssp || rbp1.slice != rbpos.slice)
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal ("Didn't find the given position on the stack.\n");
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #endif
|
eed89d | 2001-12-10 | Martin Stjernholm | | }
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | RBSTACK_POKE (rbp2, node);
*pos = rbp2;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
401b71 | 2002-12-05 | Martin Stjernholm | | #if 0
|
eed89d | 2001-12-10 | Martin Stjernholm | | void rbstack_assign (struct rbstack_ptr *target, struct rbstack_ptr *source)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rbstack_slice *src_slice = source->slice;
struct rbstack_slice *tgt_slice = target->slice;
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (target->ssp) Pike_fatal ("target rbstack not empty.\n");
|
eed89d | 2001-12-10 | Martin Stjernholm | | #endif
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | target->ssp = source->ssp;
source->ssp = 0;
if (src_slice->up) {
struct rbstack_slice *prev_slice;
target->slice = src_slice;
do {
prev_slice = src_slice;
src_slice = src_slice->up;
} while (src_slice->up);
MEMCPY ((char *) &tgt_slice->stack, (char *) &src_slice->stack,
STACK_SLICE_SIZE * sizeof (struct rb_node_hdr *));
prev_slice->up = tgt_slice;
source->slice = src_slice;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
else {
|
eed89d | 2001-12-10 | Martin Stjernholm | | MEMCPY ((char *) &tgt_slice->stack, (char *) &src_slice->stack,
target->ssp * sizeof (struct rb_node_hdr *));
#ifdef RB_STATS
tgt_slice->maxdepth = src_slice->maxdepth;
tgt_slice->depth = src_slice->depth;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #endif
}
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | void rbstack_copy (struct rbstack_ptr *target, struct rbstack_ptr *source)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rbstack_slice *src_slice = source->slice;
struct rbstack_slice *tgt_stack_slice = target->slice;
size_t ssp = source->ssp;
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
#ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (target->ssp) Pike_fatal ("target rbstack not empty.\n");
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #endif
|
eed89d | 2001-12-10 | Martin Stjernholm | | target->ssp = ssp;
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (src_slice->up) {
struct rbstack_slice *tgt_slice =
target->slice = ALLOC_STRUCT (rbstack_slice);
#ifdef RB_STATS
rbstack_slice_allocs++;
#endif
MEMCPY ((char *) &tgt_slice->stack, (char *) &src_slice->stack,
ssp * sizeof (struct rb_node_hdr *));
ssp = STACK_SLICE_SIZE;
while ((src_slice = src_slice->up)->up) {
tgt_slice->up = ALLOC_STRUCT (rbstack_slice);
tgt_slice = tgt_slice->up;
#ifdef RB_STATS
rbstack_slice_allocs++;
#endif
MEMCPY ((char *) &tgt_slice->stack, (char *) &src_slice->stack,
STACK_SLICE_SIZE * sizeof (struct rb_node_hdr *));
}
tgt_slice->up = tgt_stack_slice;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | MEMCPY ((char *) &tgt_stack_slice->stack, (char *) &src_slice->stack,
ssp * sizeof (struct rb_node_hdr *));
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | #ifdef RB_STATS
target->slice->maxdepth = target->slice->depth = source->slice->depth;
#endif
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
401b71 | 2002-12-05 | Martin Stjernholm | | #endif /* Not tested or used. */
|
eed89d | 2001-12-10 | Martin Stjernholm | |
void rbstack_shift (struct rbstack_ptr rbstack,
struct rb_node_hdr *oldbase,
struct rb_node_hdr *newbase)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *node;
while ((node = RBSTACK_PEEK (rbstack))) {
rbstack.slice->stack[rbstack.ssp - 1] =
(struct rb_node_hdr *) ((char *) node - (char *) oldbase + (char *) newbase);
RBSTACK_UP_IGNORE (rbstack);
}
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
881484 | 2001-05-01 | Martin Stjernholm | |
|
b47c1e | 2002-12-07 | Henrik Grubbström (Grubba) | | PMOD_EXPORT struct rb_node_hdr *rb_first (struct rb_node_hdr *root)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | DO_IF_RB_STATS (rb_num_sidesteps++; rb_num_sidestep_ops++);
if (root)
while (root->prev) {
root = root->prev;
DO_IF_RB_STATS (rb_num_sidestep_ops++);
}
return root;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
b47c1e | 2002-12-07 | Henrik Grubbström (Grubba) | | PMOD_EXPORT struct rb_node_hdr *rb_last (struct rb_node_hdr *root)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | DO_IF_RB_STATS (rb_num_sidesteps++; rb_num_sidestep_ops++);
if (root)
while (root->next) {
root = root->next;
DO_IF_RB_STATS (rb_num_sidestep_ops++);
}
return root;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
b47c1e | 2002-12-07 | Henrik Grubbström (Grubba) | | PMOD_EXPORT struct rb_node_hdr *rb_link_prev (struct rb_node_hdr *node)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | node = node->prev;
DO_IF_RB_STATS (rb_num_sidestep_ops++);
while (!(node->flags & RB_THREAD_NEXT)) {
node = node->next;
DO_IF_RB_STATS (rb_num_sidestep_ops++);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | return node;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
b47c1e | 2002-12-07 | Henrik Grubbström (Grubba) | | PMOD_EXPORT struct rb_node_hdr *rb_link_next (struct rb_node_hdr *node)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | node = node->next;
DO_IF_RB_STATS (rb_num_sidestep_ops++);
while (!(node->flags & RB_THREAD_PREV)) {
node = node->prev;
DO_IF_RB_STATS (rb_num_sidestep_ops++);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | return node;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | #define SET_PTR_TO_CHILD(PARENT, CHILD, PREV_VAL, NEXT_VAL) do { \
if (CHILD == PARENT->prev) \
PARENT->prev = PREV_VAL; \
else { \
DO_IF_DEBUG( \
if (CHILD != PARENT->next) \
rb_fatal (PARENT, "Got invalid parent to %p " \
"(stack probably wrong).\n", CHILD); \
); \
PARENT->next = NEXT_VAL; \
} \
} while (0)
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
8cfc02 | 2002-12-22 | Martin Stjernholm | | static INLINE struct rb_node_hdr *rot_right (struct rb_node_hdr *node)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
struct rb_node_hdr *ret = node->prev;
if (ret->flags & RB_THREAD_NEXT) {
#ifdef PIKE_DEBUG
if (ret->next != node) rb_fatal (node, "Bogus next thread pointer.\n");
#endif
ret->flags &= ~RB_THREAD_NEXT;
node->flags |= RB_THREAD_PREV;
}
else {
node->prev = ret->next;
ret->next = node;
}
return ret;
}
|
8cfc02 | 2002-12-22 | Martin Stjernholm | | static INLINE struct rb_node_hdr *rot_left (struct rb_node_hdr *node)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
struct rb_node_hdr *ret = node->next;
if (ret->flags & RB_THREAD_PREV) {
#ifdef PIKE_DEBUG
if (ret->prev != node) rb_fatal (node, "Bogus prev thread pointer.\n");
#endif
ret->flags &= ~RB_THREAD_PREV;
node->flags |= RB_THREAD_NEXT;
}
else {
node->next = ret->prev;
ret->prev = node;
}
return ret;
}
|
5dc193 | 2001-05-01 | Martin Stjernholm | | static struct rb_node_hdr *rebalance_after_add (struct rb_node_hdr *node,
struct rbstack_ptr rbstack)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
struct rb_node_hdr *parent, *grandparent, *uncle, *top;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_POP (rbstack, parent);
#ifdef PIKE_DEBUG
if (!parent) rb_fatal (node, "No parent on stack.\n");
#endif
RBSTACK_POP (rbstack, grandparent);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | top = grandparent ? grandparent : parent;
while (parent->flags & RB_RED) {
|
5dc193 | 2001-05-01 | Martin Stjernholm | | #ifdef PIKE_DEBUG
if (!grandparent) rb_fatal (parent, "No parent for red node.\n");
#endif
|
eed89d | 2001-12-10 | Martin Stjernholm | | #ifdef RB_STATS
rb_add_rebalance_cnt++;
#endif
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
if (parent == grandparent->prev) {
uncle = grandparent->next;
if (!(grandparent->flags & RB_THREAD_NEXT) && uncle->flags & RB_RED) {
|
5dc193 | 2001-05-01 | Martin Stjernholm | | * grandparent(B) *grandparent(R)
* / \ / \
* / \ / \
* parent(R) uncle(R) ==> parent(B) uncle(B)
* / \ / \
* / \ / \
* *node(R) or *node(R) node(R) or node(R)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | */
parent->flags &= ~RB_RED;
uncle->flags &= ~RB_RED;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_POP (rbstack, parent);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | if (!parent) {
|
5dc193 | 2001-05-01 | Martin Stjernholm | |
top = grandparent;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | break;
}
|
5dc193 | 2001-05-01 | Martin Stjernholm | | grandparent->flags |= RB_RED;
node = grandparent;
RBSTACK_POP (rbstack, grandparent);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | top = grandparent ? grandparent : parent;
}
else {
if (node == parent->next) {
|
5dc193 | 2001-05-01 | Martin Stjernholm | | * grandparent(B) grandparent(B)
* / \ / \
* / \ / \
* parent(R) uncle(B) ==> node(R) uncle(B)
* \ / \
* \ / \
* *node(R) *parent(R) (B)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | */
node = parent;
parent = grandparent->prev = rot_left (node);
}
|
5dc193 | 2001-05-01 | Martin Stjernholm | | * grandparent(B) parent(B)
* / \ / \
* / \ / \
* parent(R) uncle(B) ==> node(R) grandparent(R)
* / \ / \
* / \ / \
* *node(R) (B) (B) uncle(B)
*
|
c550c2 | 2001-04-30 | Martin Stjernholm | | * => Done.
*/
|
5dc193 | 2001-05-01 | Martin Stjernholm | | rot_right (grandparent);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | grandparent->flags |= RB_RED;
parent->flags &= ~RB_RED;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_POP (rbstack, top);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | if (top)
SET_PTR_TO_CHILD (top, grandparent, parent, parent);
else
top = parent;
break;
}
}
else {
#ifdef PIKE_DEBUG
if (parent != grandparent->next)
rb_fatal (grandparent,
"Childs parent doesn't know about it (stack probably wrong).\n");
#endif
uncle = grandparent->prev;
if (!(grandparent->flags & RB_THREAD_PREV) && uncle->flags & RB_RED) {
parent->flags &= ~RB_RED;
uncle->flags &= ~RB_RED;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_POP (rbstack, parent);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | if (!parent) {
|
5dc193 | 2001-05-01 | Martin Stjernholm | | top = grandparent;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | break;
}
|
5dc193 | 2001-05-01 | Martin Stjernholm | | grandparent->flags |= RB_RED;
node = grandparent;
RBSTACK_POP (rbstack, grandparent);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | top = grandparent ? grandparent : parent;
}
else {
if (node == parent->prev) {
node = parent;
parent = grandparent->next = rot_right (node);
}
|
5dc193 | 2001-05-01 | Martin Stjernholm | | rot_left (grandparent);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | grandparent->flags |= RB_RED;
parent->flags &= ~RB_RED;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_POP (rbstack, top);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | if (top)
SET_PTR_TO_CHILD (top, grandparent, parent, parent);
else
top = parent;
break;
}
}
}
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_FREE_SET_ROOT (rbstack, top);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #ifdef PIKE_DEBUG
if (top->flags & RB_RED) rb_fatal (top, "Root node not black.\n");
#endif
return top;
}
|
eed89d | 2001-12-10 | Martin Stjernholm | |
|
5dc193 | 2001-05-01 | Martin Stjernholm | | static struct rb_node_hdr *rebalance_after_delete (struct rb_node_hdr *node,
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rbstack_ptr *rbstack_ptr,
int keep_rbstack)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
struct rb_node_hdr *parent, *sibling, *top = node;
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rbstack_ptr rbstack = *rbstack_ptr, rbstack_top;
if (keep_rbstack) {
rbstack_top = rbstack;
RBSTACK_UP (rbstack, parent);
}
else
RBSTACK_POP (rbstack, parent);
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
if (!parent) {
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (!node) return NULL;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | node->flags &= ~RB_RED;
}
else do {
top = parent;
|
eed89d | 2001-12-10 | Martin Stjernholm | | #ifdef RB_STATS
rb_add_rebalance_cnt++;
#endif
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
if (node == parent->prev) {
if (!(parent->flags & RB_THREAD_PREV) && node->flags & RB_RED) {
node->flags &= ~RB_RED;
break;
}
|
5dc193 | 2001-05-01 | Martin Stjernholm | | #ifdef PIKE_DEBUG
if (parent->flags & RB_THREAD_NEXT)
rb_fatal (parent, "Sibling in next is null; tree was unbalanced.\n");
#endif
|
c550c2 | 2001-04-30 | Martin Stjernholm | | sibling = parent->next;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | if (sibling->flags & RB_RED) {
|
c550c2 | 2001-04-30 | Martin Stjernholm | | |
5dc193 | 2001-05-01 | Martin Stjernholm | | * parent(B) sibling(B)
* / \ / \
* / \ / \
* *node(2B) sibling(R) ==> parent(R) (B)
* / \ / \
* / \ / \
* (B) (B) *node(2B) (B)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | */
parent->flags |= RB_RED;
sibling->flags &= ~RB_RED;
rot_left (parent);
|
eed89d | 2001-12-10 | Martin Stjernholm | | top = RBSTACK_PEEK (rbstack);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | if (top)
SET_PTR_TO_CHILD (top, parent, sibling, sibling);
else
top = sibling;
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (keep_rbstack) rbstack_insert (&rbstack_top, &rbstack, sibling);
else RBSTACK_PUSH (rbstack, sibling);
|
5dc193 | 2001-05-01 | Martin Stjernholm | | #ifdef PIKE_DEBUG
if (parent->flags & RB_THREAD_NEXT)
rb_fatal (parent, "Sibling in next is null; tree was unbalanced.\n");
#endif
|
c550c2 | 2001-04-30 | Martin Stjernholm | | sibling = parent->next;
goto prev_node_red_parent;
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | else if (!(parent->flags & RB_RED)) {
|
5dc193 | 2001-05-01 | Martin Stjernholm | | if ((sibling->flags & RB_THREAD_PREV || !(sibling->prev->flags & RB_RED)) &&
(sibling->flags & RB_THREAD_NEXT || !(sibling->next->flags & RB_RED))) {
|
c550c2 | 2001-04-30 | Martin Stjernholm | | sibling->flags |= RB_RED;
node = parent;
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (keep_rbstack) RBSTACK_UP (rbstack, parent);
else RBSTACK_POP (rbstack, parent);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | continue;
}
}
else {
prev_node_red_parent:
|
5dc193 | 2001-05-01 | Martin Stjernholm | | if ((sibling->flags & RB_THREAD_PREV || !(sibling->prev->flags & RB_RED)) &&
(sibling->flags & RB_THREAD_NEXT || !(sibling->next->flags & RB_RED))) {
|
c550c2 | 2001-04-30 | Martin Stjernholm | | parent->flags &= ~RB_RED;
sibling->flags |= RB_RED;
break;
}
}
if (sibling->flags & RB_THREAD_NEXT || !(sibling->next->flags & RB_RED)) {
|
eed89d | 2001-12-10 | Martin Stjernholm | | * parent(?) parent(?)
* / \ / \
* / \ / \
* *node(2B) sibling(B) *node(2B) new sibling(B)
* / \ / \
* / \ ==> / \
* new sibling(R) (B) (B) sibling(R)
* / \ / \
* / \ / \
* (B) (B) (B) (B)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | */
sibling->flags |= RB_RED;
sibling = parent->next = rot_right (sibling);
sibling->flags &= ~RB_RED;
}
|
5dc193 | 2001-05-01 | Martin Stjernholm | | * parent(?) sibling(?)
* / \ / \
* / \ / \
* *node(2B) sibling(B) ==> parent(B) (B)
* / \ / \
* / \ / \
* (?) (R) node(B) (?)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | * => Done.
*/
|
eed89d | 2001-12-10 | Martin Stjernholm | | assert (!(sibling->flags & RB_RED));
|
c550c2 | 2001-04-30 | Martin Stjernholm | | rot_left (parent);
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (keep_rbstack) top = RBSTACK_PEEK (rbstack);
else RBSTACK_POP (rbstack, top);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | if (top) {
SET_PTR_TO_CHILD (top, parent, sibling, sibling);
if (parent->flags & RB_RED) {
sibling->flags |= RB_RED;
parent->flags &= ~RB_RED;
}
}
else {
top = sibling;
|
eed89d | 2001-12-10 | Martin Stjernholm | |
assert (!(parent->flags & RB_RED));
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
sibling->next->flags &= ~RB_RED;
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (keep_rbstack) {
struct rbstack_ptr tmp = rbstack;
rbstack_insert (&rbstack_top, &tmp, sibling);
}
|
c550c2 | 2001-04-30 | Martin Stjernholm | | break;
}
else {
#ifdef PIKE_DEBUG
if (node != parent->next)
rb_fatal (parent,
"Childs parent doesn't know about it (stack probably wrong).\n");
#endif
|
eed89d | 2001-12-10 | Martin Stjernholm | |
|
c550c2 | 2001-04-30 | Martin Stjernholm | | if (!(parent->flags & RB_THREAD_NEXT) && node->flags & RB_RED) {
node->flags &= ~RB_RED;
break;
}
|
5dc193 | 2001-05-01 | Martin Stjernholm | | #ifdef PIKE_DEBUG
if (parent->flags & RB_THREAD_PREV)
rb_fatal (parent, "Sibling in prev is null; tree was unbalanced.\n");
#endif
|
c550c2 | 2001-04-30 | Martin Stjernholm | | sibling = parent->prev;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | if (sibling->flags & RB_RED) {
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
parent->flags |= RB_RED;
sibling->flags &= ~RB_RED;
rot_right (parent);
|
eed89d | 2001-12-10 | Martin Stjernholm | | top = RBSTACK_PEEK (rbstack);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | if (top)
SET_PTR_TO_CHILD (top, parent, sibling, sibling);
else
top = sibling;
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (keep_rbstack) rbstack_insert (&rbstack_top, &rbstack, sibling);
else RBSTACK_PUSH (rbstack, sibling);
|
5dc193 | 2001-05-01 | Martin Stjernholm | | #ifdef PIKE_DEBUG
if (parent->flags & RB_THREAD_PREV)
rb_fatal (parent, "Sibling in prev is null; tree was unbalanced.\n");
#endif
|
c550c2 | 2001-04-30 | Martin Stjernholm | | sibling = parent->prev;
goto next_node_red_parent;
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | else if (!(parent->flags & RB_RED)) {
|
5dc193 | 2001-05-01 | Martin Stjernholm | | if ((sibling->flags & RB_THREAD_PREV || !(sibling->prev->flags & RB_RED)) &&
(sibling->flags & RB_THREAD_NEXT || !(sibling->next->flags & RB_RED))) {
|
c550c2 | 2001-04-30 | Martin Stjernholm | | sibling->flags |= RB_RED;
node = parent;
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (keep_rbstack) RBSTACK_UP (rbstack, parent);
else RBSTACK_POP (rbstack, parent);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | continue;
}
}
else {
next_node_red_parent:
|
5dc193 | 2001-05-01 | Martin Stjernholm | | if ((sibling->flags & RB_THREAD_PREV || !(sibling->prev->flags & RB_RED)) &&
(sibling->flags & RB_THREAD_NEXT || !(sibling->next->flags & RB_RED))) {
|
c550c2 | 2001-04-30 | Martin Stjernholm | | parent->flags &= ~RB_RED;
sibling->flags |= RB_RED;
break;
}
}
if (sibling->flags & RB_THREAD_PREV || !(sibling->prev->flags & RB_RED)) {
|
5dc193 | 2001-05-01 | Martin Stjernholm | |
|
c550c2 | 2001-04-30 | Martin Stjernholm | | sibling->flags |= RB_RED;
sibling = parent->prev = rot_left (sibling);
sibling->flags &= ~RB_RED;
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | assert (!(sibling->flags & RB_RED));
|
c550c2 | 2001-04-30 | Martin Stjernholm | | rot_right (parent);
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (keep_rbstack) top = RBSTACK_PEEK (rbstack);
else RBSTACK_POP (rbstack, top);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | if (top) {
SET_PTR_TO_CHILD (top, parent, sibling, sibling);
if (parent->flags & RB_RED) {
sibling->flags |= RB_RED;
parent->flags &= ~RB_RED;
}
}
else {
top = sibling;
|
eed89d | 2001-12-10 | Martin Stjernholm | | assert (!(parent->flags & RB_RED));
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
sibling->prev->flags &= ~RB_RED;
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (keep_rbstack) {
struct rbstack_ptr tmp = rbstack;
rbstack_insert (&rbstack_top, &tmp, sibling);
}
|
c550c2 | 2001-04-30 | Martin Stjernholm | | break;
}
} while (parent);
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (keep_rbstack) {
RBSTACK_UP_TO_ROOT (rbstack, top);
*rbstack_ptr = rbstack_top;
}
else {
RBSTACK_FREE_SET_ROOT (rbstack, top);
*rbstack_ptr = rbstack;
}
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #ifdef PIKE_DEBUG
if (top->flags & RB_RED) rb_fatal (top, "Root node not black.\n");
#endif
return top;
}
void low_rb_init_root (struct rb_node_hdr *node)
{
|
881484 | 2001-05-01 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (!node) Pike_fatal ("New node is null.\n");
|
eed89d | 2001-12-10 | Martin Stjernholm | | #endif
#ifdef RB_STATS
rb_num_adds++;
|
881484 | 2001-05-01 | Martin Stjernholm | | #endif
node->flags = (node->flags & ~RB_RED) | RB_THREAD_PREV | RB_THREAD_NEXT;
|
eed89d | 2001-12-10 | Martin Stjernholm | | node->prev = node->next = NULL;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | void low_rb_link_at_prev (struct rb_node_hdr **root, struct rbstack_ptr rbstack,
|
c550c2 | 2001-04-30 | Martin Stjernholm | | struct rb_node_hdr *new)
{
|
5dc193 | 2001-05-01 | Martin Stjernholm | | struct rb_node_hdr *parent = RBSTACK_PEEK (rbstack);
|
eed89d | 2001-12-10 | Martin Stjernholm | |
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (!new) Pike_fatal ("New node is null.\n");
if (!parent) Pike_fatal ("Cannot link in root node.\n");
|
c550c2 | 2001-04-30 | Martin Stjernholm | | if (!(parent->flags & RB_THREAD_PREV))
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal ("Cannot link in node at interior prev link.\n");
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #endif
|
eed89d | 2001-12-10 | Martin Stjernholm | | #ifdef RB_STATS
rb_num_adds++;
#endif
|
c550c2 | 2001-04-30 | Martin Stjernholm | | new->flags |= RB_RED | RB_THREAD_PREV | RB_THREAD_NEXT;
new->prev = parent->prev;
new->next = parent;
parent->flags &= ~RB_THREAD_PREV;
parent->prev = new;
|
eed89d | 2001-12-10 | Martin Stjernholm | | *root = rebalance_after_add (new, rbstack);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | void low_rb_link_at_next (struct rb_node_hdr **root, struct rbstack_ptr rbstack,
|
c550c2 | 2001-04-30 | Martin Stjernholm | | struct rb_node_hdr *new)
{
|
5dc193 | 2001-05-01 | Martin Stjernholm | | struct rb_node_hdr *parent = RBSTACK_PEEK (rbstack);
|
eed89d | 2001-12-10 | Martin Stjernholm | |
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (!new) Pike_fatal ("New node is null.\n");
if (!parent) Pike_fatal ("Cannot link in root node.\n");
|
c550c2 | 2001-04-30 | Martin Stjernholm | | if (!(parent->flags & RB_THREAD_NEXT))
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal ("Cannot link in node at interior next link.\n");
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #endif
|
eed89d | 2001-12-10 | Martin Stjernholm | | #ifdef RB_STATS
rb_num_adds++;
#endif
|
c550c2 | 2001-04-30 | Martin Stjernholm | | new->flags |= RB_RED | RB_THREAD_PREV | RB_THREAD_NEXT;
new->prev = parent;
new->next = parent->next;
parent->flags &= ~RB_THREAD_NEXT;
parent->next = new;
|
eed89d | 2001-12-10 | Martin Stjernholm | | *root = rebalance_after_add (new, rbstack);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
10be3f | 2002-12-23 | Henrik Grubbström (Grubba) | | #define DO_SIMPLE_UNLINK(UNLINK, PARENT, NODE) \
do { \
|
eed89d | 2001-12-10 | Martin Stjernholm | | PARENT = RBSTACK_PEEK (rbstack); \
\
if (UNLINK->flags & RB_THREAD_PREV) { \
if (UNLINK->flags & RB_THREAD_NEXT) { \
if (PARENT) \
SET_PTR_TO_CHILD ( \
PARENT, UNLINK, \
(PARENT->flags |= RB_THREAD_PREV, NODE = UNLINK->prev), \
(PARENT->flags |= RB_THREAD_NEXT, NODE = UNLINK->next)); \
else \
NODE = NULL; \
|
10be3f | 2002-12-23 | Henrik Grubbström (Grubba) | | break; /* We're done. */ \
|
eed89d | 2001-12-10 | Martin Stjernholm | | } \
\
else { /* prev is null. */ \
NODE = UNLINK->next; \
DO_IF_DEBUG ( \
/* Since UNLINK->prev is null, UNLINK->next must be red */ \
/* and can't have children, or else the tree is */ \
/* unbalanced. */ \
if (!(NODE->flags & RB_THREAD_PREV)) \
rb_fatal (PARENT, "Expected thread prev pointer in %p; " \
"tree is unbalanced.\n", NODE); \
); \
NODE->prev = UNLINK->prev; \
} \
} \
\
else { /* next is null. */ \
NODE = UNLINK->prev; \
DO_IF_DEBUG ( \
if (!(NODE->flags & RB_THREAD_NEXT)) \
rb_fatal (PARENT, "Expected thread next pointer in %p; " \
"tree is unbalanced.\n", NODE); \
); \
NODE->next = UNLINK->next; \
} \
\
if (PARENT) SET_PTR_TO_CHILD (PARENT, UNLINK, NODE, NODE); \
} while (0)
#define ADJUST_STACK_TO_NEXT(RBSTACK, NEXT) do { \
struct rb_node_hdr *node = RBSTACK_PEEK (RBSTACK); \
if (NEXT && (!node || \
(!(node->flags & RB_THREAD_PREV) && node->prev == NEXT) || \
(!(node->flags & RB_THREAD_NEXT) && node->next == NEXT))) { \
RBSTACK_PUSH (RBSTACK, NEXT); \
while (!(NEXT->flags & RB_THREAD_PREV)) \
RBSTACK_PUSH (RBSTACK, NEXT = NEXT->prev); \
} \
else \
while (node != NEXT) { \
RBSTACK_POP (RBSTACK, node); \
assert (!NEXT || node != NULL); \
node = RBSTACK_PEEK (RBSTACK); \
} \
} while (0)
struct rb_node_hdr *low_rb_unlink_with_move (struct rb_node_hdr **root,
struct rbstack_ptr *rbstack_ptr,
int keep_rbstack,
size_t node_size)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *node, *parent, *unlink, *next;
struct rbstack_ptr rbstack = *rbstack_ptr;
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_POP (rbstack, node);
#ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (!node) Pike_fatal ("No node to delete on stack.\n");
|
5dc193 | 2001-05-01 | Martin Stjernholm | | #endif
|
eed89d | 2001-12-10 | Martin Stjernholm | | #ifdef RB_STATS
rb_num_deletes++;
#endif
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (node->flags & (RB_THREAD_PREV|RB_THREAD_NEXT)) {
next = node->next;
|
4a705a | 2001-05-02 | Martin Stjernholm | | unlink = node;
|
eed89d | 2001-12-10 | Martin Stjernholm | | DO_SIMPLE_UNLINK (unlink, parent, node);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | |
|
c550c2 | 2001-04-30 | Martin Stjernholm | | else {
|
4a705a | 2001-05-02 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | next = parent = node;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_PUSH (rbstack, node);
|
4a705a | 2001-05-02 | Martin Stjernholm | | for (unlink = node->next; !(unlink->flags & RB_THREAD_PREV); unlink = unlink->prev) {
parent = unlink;
RBSTACK_PUSH (rbstack, unlink);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
4a705a | 2001-05-02 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | keep_flags (node,
MEMCPY ((char *) node + OFFSETOF (rb_node_hdr, flags),
(char *) unlink + OFFSETOF (rb_node_hdr, flags),
node_size - OFFSETOF (rb_node_hdr, flags)));
|
4a705a | 2001-05-02 | Martin Stjernholm | |
if (parent == node) {
node = unlink->next;
if (unlink->flags & RB_THREAD_NEXT)
parent->flags |= RB_THREAD_NEXT;
else {
#ifdef PIKE_DEBUG
if (!(node->flags & RB_THREAD_PREV))
rb_fatal (parent, "Expected thread prev pointer in %p; "
"tree is unbalanced.\n", node);
#endif
node->prev = unlink->prev;
}
parent->next = node;
}
|
eed89d | 2001-12-10 | Martin Stjernholm | |
|
4a705a | 2001-05-02 | Martin Stjernholm | | else
if (unlink->flags & RB_THREAD_NEXT) {
parent->flags |= RB_THREAD_PREV;
parent->prev = node = unlink->prev;
}
else {
node = unlink->next;
#ifdef PIKE_DEBUG
if (!(node->flags & RB_THREAD_PREV))
rb_fatal (parent, "Expected thread prev pointer in %p; "
"tree is unbalanced.\n", node);
#endif
node->prev = unlink->prev;
parent->prev = node;
}
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (unlink->flags & RB_RED) {
if (!keep_rbstack) RBSTACK_FREE (rbstack);
}
|
c550c2 | 2001-04-30 | Martin Stjernholm | | else
|
eed89d | 2001-12-10 | Martin Stjernholm | | *root = rebalance_after_delete (node, &rbstack, keep_rbstack);
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (keep_rbstack) ADJUST_STACK_TO_NEXT (rbstack, next);
*rbstack_ptr = rbstack;
|
4a705a | 2001-05-02 | Martin Stjernholm | | return unlink;
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | #if 0
struct rb_node_hdr *low_rb_unlink_with_move (struct rb_node_hdr **root,
struct rbstack_ptr *rbstack_ptr,
int keep_rbstack,
size_t node_size)
|
4a705a | 2001-05-02 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *node = RBSTACK_PEEK (*rbstack_ptr), *next = rb_next (node);
struct rb_node_hdr *unlink =
real_low_rb_unlink_with_move (root, rbstack_ptr, 1, node_size);
debug_check_rbstack (*root, *rbstack_ptr);
if (node != unlink) next = node;
if (RBSTACK_PEEK (*rbstack_ptr) != next)
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal ("Stack got %p on top, but next node is %p.\n",
|
9a0e5a | 2002-12-08 | Martin Stjernholm | | RBSTACK_PEEK (*rbstack_ptr), next);
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (!keep_rbstack) RBSTACK_FREE (*rbstack_ptr);
return unlink;
}
#endif
void low_rb_unlink_without_move (struct rb_node_hdr **root,
struct rbstack_ptr *rbstack_ptr,
int keep_rbstack)
{
struct rb_node_hdr *node, *parent, *unlink, *next;
struct rbstack_ptr rbstack = *rbstack_ptr;
int unlink_flags;
|
4a705a | 2001-05-02 | Martin Stjernholm | |
RBSTACK_POP (rbstack, node);
#ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (!node) Pike_fatal ("No node to delete on stack.\n");
|
4a705a | 2001-05-02 | Martin Stjernholm | | #endif
|
eed89d | 2001-12-10 | Martin Stjernholm | | #ifdef RB_STATS
rb_num_deletes++;
#endif
|
4a705a | 2001-05-02 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (node->flags & (RB_THREAD_PREV|RB_THREAD_NEXT)) {
next = node->next;
|
4a705a | 2001-05-02 | Martin Stjernholm | | unlink = node;
|
eed89d | 2001-12-10 | Martin Stjernholm | | DO_SIMPLE_UNLINK (unlink, parent, node);
unlink_flags = unlink->flags;
|
4a705a | 2001-05-02 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | |
|
4a705a | 2001-05-02 | Martin Stjernholm | | else {
struct rb_node_hdr *orig_parent = RBSTACK_PEEK (rbstack), *tmp;
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rbstack_ptr pos;
|
4a705a | 2001-05-02 | Martin Stjernholm | | parent = unlink = node;
|
eed89d | 2001-12-10 | Martin Stjernholm | | RBSTACK_PUSH (rbstack, NULL);
pos = rbstack;
|
4a705a | 2001-05-02 | Martin Stjernholm | | for (node = node->next; !(node->flags & RB_THREAD_PREV); node = node->prev) {
parent = node;
RBSTACK_PUSH (rbstack, node);
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | RBSTACK_POKE (pos, next = node);
|
4a705a | 2001-05-02 | Martin Stjernholm | | unlink_flags = node->flags;
if (orig_parent) SET_PTR_TO_CHILD (orig_parent, unlink, node, node);
|
eed89d | 2001-12-10 | Martin Stjernholm | | else *root = node;
|
4a705a | 2001-05-02 | Martin Stjernholm | | for (tmp = unlink->prev; !(tmp->flags & RB_THREAD_NEXT); tmp = tmp->next) {}
tmp->next = node;
node->prev = unlink->prev;
|
eed89d | 2001-12-10 | Martin Stjernholm | |
|
4a705a | 2001-05-02 | Martin Stjernholm | | if (parent == unlink) {
node->flags =
(node->flags & ~(RB_FLAG_MASK & ~RB_THREAD_NEXT)) |
(unlink->flags & (RB_FLAG_MASK & ~RB_THREAD_NEXT));
parent = node;
node = parent->next;
}
|
eed89d | 2001-12-10 | Martin Stjernholm | |
|
4a705a | 2001-05-02 | Martin Stjernholm | | else {
if (node->flags & RB_THREAD_NEXT) {
parent->flags |= RB_THREAD_PREV;
parent->prev = node;
}
else parent->prev = node->next;
node->flags = (node->flags & ~RB_FLAG_MASK) | (unlink->flags & RB_FLAG_MASK);
node->next = unlink->next;
node = parent->prev;
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | }
|
4a705a | 2001-05-02 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (unlink_flags & RB_RED) {
if (!keep_rbstack) RBSTACK_FREE (rbstack);
|
4a705a | 2001-05-02 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | else
*root = rebalance_after_delete (node, &rbstack, keep_rbstack);
|
4a705a | 2001-05-02 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (keep_rbstack) ADJUST_STACK_TO_NEXT (rbstack, next);
*rbstack_ptr = rbstack;
}
|
4a705a | 2001-05-02 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | #if 0
void low_rb_unlink_without_move (struct rb_node_hdr **root,
struct rbstack_ptr *rbstack_ptr,
int keep_rbstack)
{
struct rb_node_hdr *node = RBSTACK_PEEK (*rbstack_ptr), *next = rb_next (node);
real_low_rb_unlink_without_move (root, rbstack_ptr, 1);
debug_check_rbstack (*root, *rbstack_ptr);
if (RBSTACK_PEEK (*rbstack_ptr) != next)
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal ("Stack got %p on top, but next node is %p.\n",
|
9a0e5a | 2002-12-08 | Martin Stjernholm | | RBSTACK_PEEK (*rbstack_ptr), next);
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (!keep_rbstack) RBSTACK_FREE (*rbstack_ptr);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | #endif
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
66b53d | 2009-04-07 | Peter Bortas | |
void low_rb_build_stack (struct rb_node_hdr *root, struct rb_node_hdr *node,
struct rbstack_ptr *rbstack_ptr)
{
struct rb_node_hdr *thr_ptr_prev, *thr_ptr_next;
if (root == node) {
RBSTACK_PUSH (*rbstack_ptr, node);
return;
}
thr_ptr_prev = node;
while (1) {
if (thr_ptr_prev->flags & RB_THREAD_PREV) {
thr_ptr_prev = thr_ptr_prev->prev;
break;
}
thr_ptr_prev = thr_ptr_prev->prev;
}
thr_ptr_next = node;
while (1) {
if (thr_ptr_next->flags & RB_THREAD_NEXT) {
thr_ptr_next = thr_ptr_next->next;
break;
}
thr_ptr_next = thr_ptr_next->next;
}
if (thr_ptr_prev && thr_ptr_prev->next == node) {
struct rb_node_hdr *p;
if (thr_ptr_next) {
low_rb_build_stack (root, thr_ptr_next, rbstack_ptr);
p = thr_ptr_next->prev;
}
else
p = root;
RBSTACK_PUSH (*rbstack_ptr, p);
do {
p = p->next;
#ifdef PIKE_DEBUG
if (!p) rb_fatal (root, "Got corrupt thread pointers from %p, "
"or the tree doesn't contain it.\n", node);
#endif
RBSTACK_PUSH (*rbstack_ptr, p);
} while (p != node);
}
else {
struct rb_node_hdr *p;
#ifdef PIKE_DEBUG
if (!thr_ptr_next || thr_ptr_next->prev != node)
rb_fatal (root, "Got corrupt thread pointers from %p.\n", node);
#endif
if (thr_ptr_prev) {
low_rb_build_stack (root, thr_ptr_prev, rbstack_ptr);
p = thr_ptr_prev->next;
}
else
p = root;
RBSTACK_PUSH (*rbstack_ptr, p);
do {
p = p->prev;
#ifdef PIKE_DEBUG
if (!p) rb_fatal (root, "Got corrupt thread pointers from %p, "
"or the tree doesn't contain it.\n", node);
#endif
RBSTACK_PUSH (*rbstack_ptr, p);
} while (p != node);
}
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | #ifdef ENABLE_UNUSED_RB_FUNCTIONS
struct rb_node_hdr *rb_insert (struct rb_node_hdr **root,
rb_find_fn *find_fn, void *key,
struct rb_node_hdr *new)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (*root) {
struct rb_node_hdr *node = *root;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_INIT (rbstack);
|
eed89d | 2001-12-10 | Martin Stjernholm | | LOW_RB_TRACK (
rbstack, node,
cmp_res = find_fn (key, node),
{
low_rb_link_at_next (root, rbstack, new);
}, {
RBSTACK_FREE (rbstack);
return node;
}, {
low_rb_link_at_prev (root, rbstack, new);
});
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
else {
low_rb_init_root (new);
|
eed89d | 2001-12-10 | Martin Stjernholm | | *root = new;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
return new;
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | void rb_add (struct rb_node_hdr **root,
rb_find_fn *find_fn, void *key,
struct rb_node_hdr *new)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (*root) {
struct rb_node_hdr *node = *root;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_INIT (rbstack);
|
eed89d | 2001-12-10 | Martin Stjernholm | | LOW_RB_TRACK_NEQ (
rbstack, node, cmp_res = find_fn (key, node) >= 0 ? 1 : -1,
low_rb_link_at_next (root, rbstack, new),
low_rb_link_at_prev (root, rbstack, new)
);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
else {
low_rb_init_root (new);
|
eed89d | 2001-12-10 | Martin Stjernholm | | *root = new;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | 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)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (*root) {
struct rb_node_hdr *node = *root;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_INIT (rbstack);
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
if (existing) {
|
eed89d | 2001-12-10 | Martin Stjernholm | | LOW_RB_TRACK_NEQ (
rbstack, node, cmp_res = find_fn (key, node) >= 0 ? 1 : -1, ;, ;);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | while (node != existing) {
|
eed89d | 2001-12-10 | Martin Stjernholm | | LOW_RB_TRACK_PREV (rbstack, node);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (!node) Pike_fatal ("Tree doesn't contain the existing node.\n");
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #endif
}
if (node->flags & RB_THREAD_NEXT) {
|
eed89d | 2001-12-10 | Martin Stjernholm | | low_rb_link_at_next (root, rbstack, new);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | return;
}
else node = node->next;
}
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_PUSH (rbstack, node);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | while (!(node->flags & RB_THREAD_PREV)) {
node = node->prev;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_PUSH (rbstack, node);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | low_rb_link_at_prev (root, rbstack, new);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
else {
#ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (existing) Pike_fatal ("Tree doesn't contain the existing node.\n");
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #endif
low_rb_init_root (new);
|
eed89d | 2001-12-10 | Martin Stjernholm | | *root = new;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
}
|
eed89d | 2001-12-10 | Martin Stjernholm | |
struct rb_node_hdr *rb_remove (struct rb_node_hdr **root,
rb_find_fn *find_fn, void *key)
|
4a705a | 2001-05-02 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *node = *root;
|
4a705a | 2001-05-02 | Martin Stjernholm | | if (node) {
RBSTACK_INIT (rbstack);
|
eed89d | 2001-12-10 | Martin Stjernholm | | LOW_RB_TRACK (
rbstack, node,
cmp_res = find_fn (key, node),
{
}, {
low_rb_unlink_without_move (root, rbstack);
return node;
}, {
});
|
4a705a | 2001-05-02 | Martin Stjernholm | | RBSTACK_FREE (rbstack);
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | return NULL;
|
4a705a | 2001-05-02 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | void rb_remove_node (struct rb_node_hdr **root,
rb_find_fn *find_fn, void *key,
struct rb_node_hdr *to_delete)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *node = *root;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_INIT (rbstack);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (!node) Pike_fatal ("Tree is empty.\n");
|
eed89d | 2001-12-10 | Martin Stjernholm | | #if 0
if (find_fn (key, to_delete))
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal ("Given key doesn't match the node to delete.\n");
|
eed89d | 2001-12-10 | Martin Stjernholm | | #endif
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #endif
|
eed89d | 2001-12-10 | Martin Stjernholm | | LOW_RB_TRACK_NEQ (rbstack, node, cmp_res = find_fn (key, node) >= 0 ? 1 : -1, ;, ;);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | while (node != to_delete) {
|
eed89d | 2001-12-10 | Martin Stjernholm | | LOW_RB_TRACK_PREV (rbstack, node);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (!node) Pike_fatal ("Tree doesn't contain the node to delete.\n");
|
c550c2 | 2001-04-30 | Martin Stjernholm | | #endif
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | low_rb_unlink_without_move (root, rbstack);
}
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 *node = *root;
if (node) {
RBSTACK_INIT (rbstack);
LOW_RB_TRACK (
rbstack, node,
cmp_res = find_fn (key, node),
{
}, {
if (cleanup_fn) cleanup_fn (node, cleanup_fn_extra);
return low_rb_unlink_with_move (root, rbstack, node_size);
}, {
});
RBSTACK_FREE (rbstack);
}
return NULL;
|
4a705a | 2001-05-02 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | |
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 *to_delete,
size_t node_size)
|
4a705a | 2001-05-02 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *node = *root;
|
4a705a | 2001-05-02 | Martin Stjernholm | | RBSTACK_INIT (rbstack);
#ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (!node) Pike_fatal ("Tree is empty.\n");
|
eed89d | 2001-12-10 | Martin Stjernholm | | #if 0
if (find_fn (key, to_delete))
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal ("Given key doesn't match the node to delete.\n");
|
eed89d | 2001-12-10 | Martin Stjernholm | | #endif
|
4a705a | 2001-05-02 | Martin Stjernholm | | #endif
|
eed89d | 2001-12-10 | Martin Stjernholm | | LOW_RB_TRACK_NEQ (rbstack, node, cmp_res = find_fn (key, node) >= 0 ? 1 : -1, ;, ;);
|
4a705a | 2001-05-02 | Martin Stjernholm | | while (node != to_delete) {
|
eed89d | 2001-12-10 | Martin Stjernholm | | LOW_RB_TRACK_PREV (rbstack, node);
|
4a705a | 2001-05-02 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (!node) Pike_fatal ("Tree doesn't contain the node to delete.\n");
|
4a705a | 2001-05-02 | Martin Stjernholm | | #endif
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | return low_rb_unlink_with_move (root, rbstack, node_size);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *rb_find_eq (struct rb_node_hdr *root,
rb_find_fn *find_fn, void *key)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (root)
LOW_RB_FIND (root, cmp_res = find_fn (key, root), ;, return root, ;);
return NULL;
}
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *rb_find_lt (struct rb_node_hdr *root,
rb_find_fn *find_fn, void *key)
{
if (root)
LOW_RB_FIND_NEQ (root, cmp_res = find_fn (key, root) <= 0 ? -1 : 1,
return root, return root->prev);
return NULL;
}
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *rb_find_gt (struct rb_node_hdr *root,
rb_find_fn *find_fn, void *key)
{
if (root)
LOW_RB_FIND_NEQ (root, cmp_res = find_fn (key, root) >= 0 ? 1 : -1,
return root->next, return root);
return NULL;
}
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *rb_find_le (struct rb_node_hdr *root,
rb_find_fn *find_fn, void *key)
{
if (root)
LOW_RB_FIND_NEQ (root, cmp_res = find_fn (key, root) >= 0 ? 1 : -1,
return root, return root->prev);
return NULL;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *rb_find_ge (struct rb_node_hdr *root,
rb_find_fn *find_fn, void *key)
|
5dc193 | 2001-05-01 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (root)
LOW_RB_FIND_NEQ (root, cmp_res = find_fn (key, root) <= 0 ? -1 : 1,
return root->next, return root);
return NULL;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | #endif /* ENABLE_UNUSED_RB_FUNCTIONS */
struct rb_node_hdr *rb_get_nth (struct rb_node_hdr *root, size_t n)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | #ifdef PIKE_DEBUG
size_t index = n;
#endif
if ((root = rb_first (root))) {
while (n) {
n--;
root = rb_next (root);
#ifdef PIKE_DEBUG
if (!root) goto tree_too_small;
#endif
}
return root;
}
#ifdef PIKE_DEBUG
|
62b6f1 | 2002-10-28 | Martin Nilsson | | tree_too_small:
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal ("Tree too small for index %"PRINTSIZET"u.\n", index);
|
eed89d | 2001-12-10 | Martin Stjernholm | | #endif
return (struct rb_node_hdr *) (ptrdiff_t) -1;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | size_t rb_sizeof (struct rb_node_hdr *root)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | size_t size = 0;
if ((root = rb_first (root))) {
do {
size++;
} while ((root = rb_next (root)));
}
return size;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | #ifdef ENABLE_UNUSED_RB_FUNCTIONS
void rb_free (struct rb_node_hdr *root, rb_free_fn *free_node_fn, void *extra)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | if ((root = rb_first (root))) {
struct rb_node_hdr *next;
do {
next = rb_next (root);
free_node_fn (root, extra);
root = next;
} while (root);
}
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | int rb_equal (struct rb_node_hdr *a, struct rb_node_hdr *b,
rb_equal_fn *node_equal_fn, void *extra)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | a = rb_first (a);
b = rb_first (b);
while (a && b) {
if (!node_equal_fn (a, b, extra)) return 0;
a = rb_next (a);
b = rb_next (b);
}
return !(a || b);
}
struct rb_node_hdr *rb_copy (struct rb_node_hdr *source,
rb_copy_fn *copy_node_fn, void *extra)
{
if (source) {
struct rb_node_hdr *copy, *target, *new, *t_prev_tgt = NULL, *t_next_src = NULL;
RBSTACK_INIT (s_stack);
RBSTACK_INIT (t_stack);
copy = target = copy_node_fn (source, extra);
copy->flags = (copy->flags & ~RB_FLAG_MASK) | (source->flags & RB_FLAG_MASK);
LOW_RB_TRAVERSE (
1, s_stack, source,
{
}, {
target->prev = t_prev_tgt;
}, {
new = target->prev = copy_node_fn (source->prev, extra);
new->flags = (new->flags & ~RB_FLAG_MASK) | (source->prev->flags & RB_FLAG_MASK);
RBSTACK_PUSH (t_stack, target);
target = new;
}, {
t_prev_tgt = target;
if (t_next_src) {
t_next_src->next = target;
t_next_src = NULL;
}
}, {
t_next_src = target;
}, {
new = target->next = copy_node_fn (source->next, extra);
new->flags = (new->flags & ~RB_FLAG_MASK) | (source->next->flags & RB_FLAG_MASK);
RBSTACK_PUSH (t_stack, target);
target = new;
}, {
RBSTACK_POP (t_stack, target);
});
if (t_next_src) t_next_src->next = NULL;
return copy;
}
else return NULL;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | #endif /* ENABLE_UNUSED_RB_FUNCTIONS */
struct rb_node_hdr *rb_make_list (struct rb_node_hdr *tree)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *list = tree = rb_first (tree);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | if (tree)
|
eed89d | 2001-12-10 | Martin Stjernholm | | while ((tree = tree->next = rb_next (tree))) {}
return list;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | |
struct rb_node_hdr *rb_make_tree (struct rb_node_hdr *list, size_t length)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *root = NULL;
if (length > 1) {
unsigned depth, *top_idx;
size_t deep_end, count = 0, start = 0, idx = 1;
struct rb_node_hdr **stack, *prev_tgt = NULL, *next_src = NULL;
int stack_malloced = 0;
{
unsigned l = 0, h = sizeof (length) * CHAR_BIT;
do {
depth = (l + h) >> 1;
|
3441e2 | 2002-12-07 | Martin Stjernholm | | if ((size_t) 1 << depth <= length)
l = depth + 1;
else
h = depth;
|
eed89d | 2001-12-10 | Martin Stjernholm | | } while (l < h);
|
3441e2 | 2002-12-07 | Martin Stjernholm | | if ((size_t) 1 << depth <= length) depth++;
|
eed89d | 2001-12-10 | Martin Stjernholm | | }
|
cc1706 | 2002-12-07 | Martin Stjernholm | | deep_end = (length - ((size_t) 1 << (depth - 1))) << 1;
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (!(length & 1)) deep_end |= 1;
{
size_t stack_size =
depth * sizeof (struct rb_node_hdr *) +
(depth + 1) * sizeof (unsigned);
#ifdef HAVE_ALLOCA
stack = alloca (stack_size);
if (!stack)
#endif
{
stack = xalloc (stack_size);
stack_malloced = 1;
}
|
8b2ad8 | 2002-12-08 | Henrik Grubbström (Grubba) | | top_idx = (unsigned *) (stack + depth);
|
eed89d | 2001-12-10 | Martin Stjernholm | | memset (top_idx, 0, (depth + 1) * sizeof (unsigned));
depth--;
}
while (count < length) {
struct rb_node_hdr *next;
#ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (!list) Pike_fatal ("Premature end of list at %"PRINTSIZET"u, "
|
9a0e5a | 2002-12-08 | Martin Stjernholm | | "expected %"PRINTSIZET"u.\n", count, length);
|
eed89d | 2001-12-10 | Martin Stjernholm | | #endif
next = list->next;
if (idx > start) {
idx = start;
list->flags |= RB_THREAD_PREV|RB_THREAD_NEXT;
next_src = stack[idx] = list;
list->prev = prev_tgt;
}
else {
idx = top_idx[idx];
list->flags &= ~(RB_THREAD_PREV|RB_THREAD_NEXT);
prev_tgt = next_src->next = stack[idx] = list;
list->prev = stack[idx - 1];
if (idx == depth) {
assert (!root);
root = list;
}
}
|
9a0e5a | 2002-12-08 | Martin Stjernholm | | assert (idx <= depth);
|
eed89d | 2001-12-10 | Martin Stjernholm | |
if (count++ == deep_end) {
if (idx) {
next_src = list;
list->flags |= RB_THREAD_NEXT;
}
start = 1;
}
if (idx & 1) list->flags &= ~RB_RED;
else list->flags |= RB_RED;
if (top_idx[idx] == top_idx[idx + 1])
top_idx[idx] = idx + 1;
else {
top_idx[idx] = top_idx[idx + 1];
stack[idx + 1]->next = list;
}
list = next;
}
|
9a0e5a | 2002-12-08 | Martin Stjernholm | | assert (deep_end == length - 1 && (length & 1) ? idx == 0 : idx == start);
#ifdef PIKE_DEBUG
for (; idx <= depth; idx++)
assert (top_idx[idx] == depth + 1);
#endif
|
d08166 | 2002-12-07 | Henrik Grubbström (Grubba) | | assert(root);
|
eed89d | 2001-12-10 | Martin Stjernholm | | next_src->next = NULL;
root->flags &= ~RB_RED;
if (stack_malloced) xfree (stack);
}
else if (length) {
root = list;
#ifdef PIKE_DEBUG
list = list->next;
#endif
low_rb_init_root (root);
}
|
881484 | 2001-05-01 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (list) Pike_fatal ("List longer than expected %d.\n", length);
|
881484 | 2001-05-01 | Martin Stjernholm | | #endif
|
eed89d | 2001-12-10 | Martin Stjernholm | | return root;
}
#ifdef ENABLE_UNUSED_RB_FUNCTIONS
struct linear_merge_cleanup
{
int operation;
struct rb_node_hdr *a, *b, *res;
rb_merge_free_fn *free_node_fn;
void *extra;
};
static void do_linear_merge_cleanup (struct linear_merge_cleanup *s)
{
struct rb_node_hdr *node, *next;
rb_merge_free_fn *free_node_fn = s->free_node_fn;
void *extra = s->extra;
for (node = s->res; node; node = next) {
next = node->next;
free_node_fn (node, extra, MERGE_TREE_RES);
}
if (s->operation & PIKE_MERGE_DESTR_A)
for (node = s->a; node; node = next) {
next = rb_prev (node);
free_node_fn (node, extra, MERGE_TREE_A);
}
if (s->operation & PIKE_MERGE_DESTR_B)
for (node = s->b; node; node = next) {
next = rb_prev (node);
free_node_fn (node, extra, MERGE_TREE_B);
}
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | |
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)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *n;
size_t len = 0;
int cmp_res, op;
struct linear_merge_cleanup s;
ONERROR uwp;
s.operation = operation;
s.free_node_fn = free_node_fn;
s.extra = free_fn_extra;
SET_ONERROR (uwp, do_linear_merge_cleanup, &s);
LOW_RB_MERGE (
x, s.a, s.b, s.res, len, operation, ;, ;,
{
cmp_res = cmp_fn (s.a, s.b, cmp_fn_extra);
}, {
new_node = operation & PIKE_MERGE_DESTR_A ? s.a :
copy_node_fn (s.a, copy_fn_extra, MERGE_TREE_A);
}, {
if (operation & PIKE_MERGE_DESTR_A)
free_node_fn (s.a, free_fn_extra, MERGE_TREE_A);
}, {
new_node = operation & PIKE_MERGE_DESTR_B ? s.b :
copy_node_fn (s.b, copy_fn_extra, MERGE_TREE_B);
}, {
if (operation & PIKE_MERGE_DESTR_B)
free_node_fn (s.b, free_fn_extra, MERGE_TREE_B);
});
UNSET_ONERROR (uwp);
if (length) *length = len;
return s.res;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | #endif /* ENABLE_UNUSED_RB_FUNCTIONS */
#ifdef RB_STATS
size_t rb_num_finds = 0, rb_find_depth = 0;
size_t rb_num_sidesteps = 0, rb_num_sidestep_ops = 0;
size_t rb_num_tracks = 0, rb_track_depth = 0;
size_t rb_num_sidetracks = 0, rb_num_sidetrack_ops = 0;
size_t rb_max_depth = 0;
size_t rb_num_traverses = 0, rb_num_traverse_ops = 0;
size_t rbstack_slice_allocs = 0;
size_t rb_num_adds = 0, rb_add_rebalance_cnt = 0;
size_t rb_num_deletes = 0, rb_del_rebalance_cnt = 0;
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | void reset_rb_stats()
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | rb_num_sidesteps = rb_num_sidestep_ops = 0;
rb_num_finds = rb_find_depth = 0;
rb_num_tracks = rb_track_depth = 0;
rb_num_sidetracks = rb_num_sidetrack_ops = 0;
rb_max_depth = 0;
rb_num_traverses = rb_num_traverse_ops = 0;
rbstack_slice_allocs = 0;
rb_num_adds = rb_add_rebalance_cnt = 0;
rb_num_deletes = rb_del_rebalance_cnt = 0;
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | void print_rb_stats (int reset)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | fprintf (stderr,
"rbtree stats:\n"
" number of finds . . . . . . %10"PRINTSIZET"u\n"
" avg find depth . . . . . . . %10.2f\n"
" number of sidesteps . . . . %10"PRINTSIZET"u\n"
" avg ops per sidestep . . . . %10.2f\n"
" number of tracks . . . . . . %10"PRINTSIZET"u\n"
" avg track depth . . . . . . %10.2f\n"
" number of sidetracks . . . . %10"PRINTSIZET"u\n"
" avg ops per sidetrack . . . %10.2f\n"
" maximum depth . . . . . . . %10"PRINTSIZET"u\n"
" number of traverses . . . . %10"PRINTSIZET"u\n"
" avg ops per traverse . . . . %10.2f\n"
" allocated stack slices . . . %10"PRINTSIZET"u\n"
" number of adds . . . . . . . %10"PRINTSIZET"u\n"
" avg add rebalance count . . %10.2f\n"
" number of deletes . . . . . %10"PRINTSIZET"u\n"
" avg delete rebalance count . %10.2f\n",
rb_num_finds,
(double) rb_find_depth / rb_num_finds,
rb_num_sidesteps,
(double) rb_num_sidestep_ops / rb_num_sidesteps,
rb_num_tracks,
(double) rb_track_depth / rb_num_tracks,
rb_num_sidetracks,
(double) rb_num_sidetrack_ops / rb_num_sidetracks,
rb_max_depth,
rb_num_traverses,
(double) rb_num_traverse_ops / rb_num_traverses,
rbstack_slice_allocs,
rb_num_adds,
(double) rb_add_rebalance_cnt / rb_num_adds,
rb_num_deletes,
(double) rb_del_rebalance_cnt / rb_num_deletes);
if (reset) reset_rb_stats();
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | #endif /* RB_STATS */
#if defined (PIKE_DEBUG) || defined (TEST_MULTISET)
void debug_dump_rb_tree (struct rb_node_hdr *root, dump_data_fn *dump_data,
void *extra)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (root) {
struct rb_node_hdr *node = root;
struct rb_node_hdr *n, *n2;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | struct rbstack_ptr p;
|
eed89d | 2001-12-10 | Martin Stjernholm | | size_t depth = 0;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_INIT (rbstack);
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | LOW_RB_TRAVERSE (
1, rbstack, node,
{
depth++;
p = rbstack;
RBSTACK_UP (p, n);
while (n) {
if (n == node) {
fprintf (stderr, "[Circular %p]", node);
goto skip_node;
}
RBSTACK_UP (p, n);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | fputc ('(', stderr);
}, {
p = rbstack;
n2 = node;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_UP (p, n);
|
eed89d | 2001-12-10 | Martin Stjernholm | | while (n && (n->flags & RB_THREAD_NEXT || n->next != n2)) {
n2 = n;
RBSTACK_UP (p, n);
}
if (node->prev != n)
|
9a0e5a | 2002-12-08 | Martin Stjernholm | | fprintf (stderr, "[Thread ptr is %p, expected %p]\n%*s",
node->prev, n, depth, "");
|
eed89d | 2001-12-10 | Martin Stjernholm | | }, {
if (!node->prev) {
fputs ("[Zero subtree]", stderr);
goto between_1;
}
}, {
if (!(node->flags & RB_THREAD_PREV))
fprintf (stderr, "\n%*s", depth, "");
if (node == root) fputs ("root=", stderr);
fprintf (stderr, "%p/%c",
node, node->flags & RB_RED ? 'R' : 'B');
if (dump_data) {
fputs (": ", stderr);
dump_data (node, extra);
}
|
04dd6e | 2002-12-19 | Martin Stjernholm | | if (node->prev && node->prev == node->next)
fputs (" [prev == next]", stderr);
|
eed89d | 2001-12-10 | Martin Stjernholm | | }, {
p = rbstack;
n2 = node;
RBSTACK_UP (p, n);
while (n && (n->flags & RB_THREAD_PREV || n->prev != n2)) {
n2 = n;
RBSTACK_UP (p, n);
}
if (node->next != n)
|
9a0e5a | 2002-12-08 | Martin Stjernholm | | fprintf (stderr, "\n%*s[Thread ptr is %p, expected %p]",
depth, "", node->next, n);
|
eed89d | 2001-12-10 | Martin Stjernholm | | }, {
|
9a0e5a | 2002-12-08 | Martin Stjernholm | | fprintf (stderr, "\n%*s", depth, "");
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (!node->next) {
|
9a0e5a | 2002-12-08 | Martin Stjernholm | | fputs ("[Zero subtree]", stderr);
|
eed89d | 2001-12-10 | Martin Stjernholm | | goto leave_1;
}
}, {
fputc (')', stderr);
skip_node:
|
9a0e5a | 2002-12-08 | Martin Stjernholm | | depth--;
|
eed89d | 2001-12-10 | Martin Stjernholm | | });
|
c550c2 | 2001-04-30 | Martin Stjernholm | | fputc ('\n', stderr);
}
else
fprintf (stderr, "(empty tree)\n");
}
|
eed89d | 2001-12-10 | Martin Stjernholm | |
void debug_dump_rbstack (struct rbstack_ptr rbstack, struct rbstack_ptr *pos)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rb_node_hdr *node, *ptr_node = (void *) (ptrdiff_t) -1;
RBSTACK_INIT (reversed);
while (1) {
int here = pos ? pos->ssp == rbstack.ssp && pos->slice == rbstack.slice : 0;
RBSTACK_UP (rbstack, node);
if (here) ptr_node = node;
if (!node) break;
RBSTACK_PUSH (reversed, node);
}
if (pos && !ptr_node) fputs ("* ", stderr);
while (1) {
RBSTACK_POP (reversed, node);
if (!node) break;
fprintf (stderr, "%p ", node);
if (pos && ptr_node == node) fputs ("* ", stderr);
}
if (pos && ptr_node == (void *) (ptrdiff_t) -1)
fputs ("(pos outside stack)", stderr);
fputc ('\n', stderr);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | static void debug_rb_fatal (struct rb_node_hdr *tree, const char *fmt, ...)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
va_list args;
va_start (args, fmt);
(void) VFPRINTF (stderr, fmt, args);
|
eed89d | 2001-12-10 | Martin Stjernholm | | fputs ("Dumping tree:\n", stderr);
debug_dump_rb_tree (tree, NULL, NULL);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | debug_fatal ("\r");
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | static void debug_custom_rb_fatal (struct rb_node_hdr *tree, dump_data_fn *dump_data,
void *extra, const char *fmt, ...)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
va_list args;
va_start (args, fmt);
(void) VFPRINTF (stderr, fmt, args);
|
eed89d | 2001-12-10 | Martin Stjernholm | | fputs ("Dumping tree:\n", stderr);
debug_dump_rb_tree (tree, dump_data, extra);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | debug_fatal ("\r");
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | void debug_check_rb_tree (struct rb_node_hdr *root, dump_data_fn *dump_data, void *extra)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (root) {
struct rb_node_hdr *node = root, *n, *n2;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | struct rbstack_ptr p;
size_t blacks = 1, max_blacks = 0, depth = 0;
RBSTACK_INIT (rbstack);
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (root->flags & RB_RED) custom_rb_fatal (root, dump_data, extra,
"Root node not black.\n");
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | LOW_RB_TRAVERSE (
1, rbstack, node,
{
depth++;
p = rbstack;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_UP (p, n);
|
eed89d | 2001-12-10 | Martin Stjernholm | | while (n) {
if (n == node) custom_rb_fatal (root, dump_data, extra,
"Circular subtrees @ %p.\n", node);
RBSTACK_UP (p, n);
}
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | if (!(node->flags & RB_RED)) blacks++;
}, {
if (max_blacks) {
if (blacks != max_blacks)
custom_rb_fatal (root, dump_data, extra,
"Unbalanced tree - leftmost branch is %d, "
"prev @ %p is %d.\n", max_blacks, node, blacks);
}
else max_blacks = blacks;
|
c550c2 | 2001-04-30 | Martin Stjernholm | |
|
eed89d | 2001-12-10 | Martin Stjernholm | | p = rbstack;
n2 = node;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_UP (p, n);
|
eed89d | 2001-12-10 | Martin Stjernholm | | while (n && (n->flags & RB_THREAD_NEXT || n->next != n2)) {
n2 = n;
RBSTACK_UP (p, n);
}
if (node->prev != n)
custom_rb_fatal (root, dump_data, extra,
"Thread prev pointer @ %p is %p, expected %p.\n",
node, node->prev, n);
}, {
if (!node->prev) custom_rb_fatal (root, dump_data, extra,
"Subtree prev is null @ %p.\n", node);
if (node->flags & RB_RED && node->prev->flags & RB_RED)
custom_rb_fatal (root, dump_data, extra,
"Red node got red subtree prev node @ %p.\n", node);
}, {
}, {
if (blacks != max_blacks)
custom_rb_fatal (root, dump_data, extra,
"Unbalanced tree - leftmost branch is %d, "
"next @ %p is %d.\n", max_blacks, node, blacks);
p = rbstack;
n2 = node;
|
5dc193 | 2001-05-01 | Martin Stjernholm | | RBSTACK_UP (p, n);
|
eed89d | 2001-12-10 | Martin Stjernholm | | while (n && (n->flags & RB_THREAD_PREV || n->prev != n2)) {
n2 = n;
RBSTACK_UP (p, n);
}
if (node->next != n)
custom_rb_fatal (root, dump_data, extra,
"Thread next pointer @ %p is %p, expected %p.\n",
node, node->next, n);
}, {
if (!node->next) custom_rb_fatal (root, dump_data, extra,
"Subtree next is null @ %p.\n", node);
if (node->flags & RB_RED && node->next->flags & RB_RED)
custom_rb_fatal (root, dump_data, extra,
"Red node got red subtree next node @ %p.\n", node);
}, {
if (!(node->flags & RB_RED)) blacks--;
depth--;
});
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
}
|
eed89d | 2001-12-10 | Martin Stjernholm | | void debug_check_rbstack (struct rb_node_hdr *root, struct rbstack_ptr rbstack)
|
c550c2 | 2001-04-30 | Martin Stjernholm | | {
|
eed89d | 2001-12-10 | Martin Stjernholm | | struct rbstack_ptr rbstack_top = rbstack;
struct rb_node_hdr *snode, *tnode = root;
RBSTACK_INIT (reversed);
while (1) {
RBSTACK_UP (rbstack, snode);
if (!snode) break;
RBSTACK_PUSH (reversed, snode);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | RBSTACK_POP (reversed, snode);
if (!snode) return;
if (snode != tnode) {
fputs ("rbstack: ", stderr);
debug_dump_rbstack (rbstack_top, NULL);
rb_fatal (root, "rbstack root %p != tree root.\n", snode);
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | while (1) {
RBSTACK_POP (reversed, snode);
if (!snode) break;
if (!(tnode->flags & RB_THREAD_PREV) && snode == tnode->prev)
{tnode = snode; continue;}
if (!(tnode->flags & RB_THREAD_NEXT) && snode == tnode->next)
{tnode = snode; continue;}
rb_fatal (root, "rbstack differs from tree: Node %p got no child %p.\n",
tnode, snode);
}
|
c550c2 | 2001-04-30 | Martin Stjernholm | | }
|
eed89d | 2001-12-10 | Martin Stjernholm | | #endif /* PIKE_DEBUG || TEST_MULTISET */
|