mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-29 06:51:10 +00:00
rbtree: Access node->parent only via accessors
This also adds a set_parent() function that automatically takes care of updating tree->root for root nodes.
This commit is contained in:
parent
7ff949ea30
commit
a33ff4c6ab
226
gtk/gtkrbtree.c
226
gtk/gtkrbtree.c
@ -50,6 +50,23 @@ struct _GtkRbNode
|
|||||||
#define NODE_TO_POINTER(node) ((gpointer) ((node) ? (((guchar *) (node)) + sizeof (GtkRbNode)) : NULL))
|
#define NODE_TO_POINTER(node) ((gpointer) ((node) ? (((guchar *) (node)) + sizeof (GtkRbNode)) : NULL))
|
||||||
#define NODE_TO_AUG_POINTER(tree, node) ((gpointer) ((node) ? (((guchar *) (node)) + sizeof (GtkRbNode) + (tree)->element_size) : NULL))
|
#define NODE_TO_AUG_POINTER(tree, node) ((gpointer) ((node) ? (((guchar *) (node)) + sizeof (GtkRbNode) + (tree)->element_size) : NULL))
|
||||||
|
|
||||||
|
static inline GtkRbNode *
|
||||||
|
parent (GtkRbNode *node)
|
||||||
|
{
|
||||||
|
return node->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_parent (GtkRbTree *tree,
|
||||||
|
GtkRbNode *node,
|
||||||
|
GtkRbNode *new_parent)
|
||||||
|
{
|
||||||
|
node->parent = new_parent;
|
||||||
|
|
||||||
|
if (new_parent == NULL)
|
||||||
|
tree->root = node;
|
||||||
|
}
|
||||||
|
|
||||||
static inline gsize
|
static inline gsize
|
||||||
gtk_rb_node_get_size (GtkRbTree *tree)
|
gtk_rb_node_get_size (GtkRbTree *tree)
|
||||||
{
|
{
|
||||||
@ -105,8 +122,8 @@ gtk_rb_node_mark_dirty (GtkRbNode *node,
|
|||||||
|
|
||||||
node->dirty = TRUE;
|
node->dirty = TRUE;
|
||||||
|
|
||||||
if (mark_parent && node->parent)
|
if (mark_parent && parent (node))
|
||||||
gtk_rb_node_mark_dirty (node->parent, TRUE);
|
gtk_rb_node_mark_dirty (parent (node), TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -146,17 +163,17 @@ gtk_rb_node_get_last (GtkRbNode *node)
|
|||||||
static GtkRbNode *
|
static GtkRbNode *
|
||||||
gtk_rb_node_get_previous (GtkRbNode *node)
|
gtk_rb_node_get_previous (GtkRbNode *node)
|
||||||
{
|
{
|
||||||
GtkRbNode *parent;
|
GtkRbNode *p;
|
||||||
|
|
||||||
if (node->left)
|
if (node->left)
|
||||||
return gtk_rb_node_get_last (node->left);
|
return gtk_rb_node_get_last (node->left);
|
||||||
|
|
||||||
for (parent = node->parent; parent != NULL; parent = node->parent)
|
for (p = parent (node); p != NULL; p = parent (node))
|
||||||
{
|
{
|
||||||
if (parent->right == node)
|
if (p->right == node)
|
||||||
return parent;
|
return p;
|
||||||
|
|
||||||
node = parent;
|
node = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -165,17 +182,17 @@ gtk_rb_node_get_previous (GtkRbNode *node)
|
|||||||
static GtkRbNode *
|
static GtkRbNode *
|
||||||
gtk_rb_node_get_next (GtkRbNode *node)
|
gtk_rb_node_get_next (GtkRbNode *node)
|
||||||
{
|
{
|
||||||
GtkRbNode *parent;
|
GtkRbNode *p;
|
||||||
|
|
||||||
if (node->right)
|
if (node->right)
|
||||||
return gtk_rb_node_get_first (node->right);
|
return gtk_rb_node_get_first (node->right);
|
||||||
|
|
||||||
for (parent = node->parent; parent != NULL; parent = node->parent)
|
for (p = parent (node); p != NULL; p = parent (node))
|
||||||
{
|
{
|
||||||
if (parent->left == node)
|
if (p->left == node)
|
||||||
return parent;
|
return p;
|
||||||
|
|
||||||
node = parent;
|
node = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -185,29 +202,26 @@ static void
|
|||||||
gtk_rb_node_rotate_left (GtkRbTree *tree,
|
gtk_rb_node_rotate_left (GtkRbTree *tree,
|
||||||
GtkRbNode *node)
|
GtkRbNode *node)
|
||||||
{
|
{
|
||||||
GtkRbNode *right;
|
GtkRbNode *right, *p;
|
||||||
|
|
||||||
right = node->right;
|
right = node->right;
|
||||||
|
p = parent (node);
|
||||||
|
|
||||||
node->right = right->left;
|
node->right = right->left;
|
||||||
if (right->left)
|
if (right->left)
|
||||||
right->left->parent = node;
|
set_parent (tree, right->left, node);
|
||||||
|
|
||||||
right->parent = node->parent;
|
set_parent (tree, right, p);
|
||||||
if (node->parent)
|
if (p)
|
||||||
{
|
{
|
||||||
if (node == node->parent->left)
|
if (node == p->left)
|
||||||
node->parent->left = right;
|
p->left = right;
|
||||||
else
|
else
|
||||||
node->parent->right = right;
|
p->right = right;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tree->root = right;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
right->left = node;
|
right->left = node;
|
||||||
node->parent = right;
|
set_parent (tree, node, right);
|
||||||
|
|
||||||
gtk_rb_node_mark_dirty (node, FALSE);
|
gtk_rb_node_mark_dirty (node, FALSE);
|
||||||
gtk_rb_node_mark_dirty (right, FALSE);
|
gtk_rb_node_mark_dirty (right, FALSE);
|
||||||
@ -217,30 +231,27 @@ static void
|
|||||||
gtk_rb_node_rotate_right (GtkRbTree *tree,
|
gtk_rb_node_rotate_right (GtkRbTree *tree,
|
||||||
GtkRbNode *node)
|
GtkRbNode *node)
|
||||||
{
|
{
|
||||||
GtkRbNode *left;
|
GtkRbNode *left, *p;
|
||||||
|
|
||||||
left = node->left;
|
left = node->left;
|
||||||
|
p = parent (node);
|
||||||
|
|
||||||
node->left = left->right;
|
node->left = left->right;
|
||||||
if (left->right)
|
if (left->right)
|
||||||
left->right->parent = node;
|
set_parent (tree, left->right, node);
|
||||||
|
|
||||||
left->parent = node->parent;
|
set_parent (tree, left, p);
|
||||||
if (node->parent)
|
if (p)
|
||||||
{
|
{
|
||||||
if (node == node->parent->right)
|
if (node == p->right)
|
||||||
node->parent->right = left;
|
p->right = left;
|
||||||
else
|
else
|
||||||
node->parent->left = left;
|
p->left = left;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tree->root = left;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* link node and left */
|
/* link node and left */
|
||||||
left->right = node;
|
left->right = node;
|
||||||
node->parent = left;
|
set_parent (tree, node, left);
|
||||||
|
|
||||||
gtk_rb_node_mark_dirty (node, FALSE);
|
gtk_rb_node_mark_dirty (node, FALSE);
|
||||||
gtk_rb_node_mark_dirty (left, FALSE);
|
gtk_rb_node_mark_dirty (left, FALSE);
|
||||||
@ -283,64 +294,73 @@ static void
|
|||||||
gtk_rb_tree_insert_fixup (GtkRbTree *tree,
|
gtk_rb_tree_insert_fixup (GtkRbTree *tree,
|
||||||
GtkRbNode *node)
|
GtkRbNode *node)
|
||||||
{
|
{
|
||||||
|
GtkRbNode *p;
|
||||||
|
|
||||||
/* check Red-Black properties */
|
/* check Red-Black properties */
|
||||||
while (node->parent && is_red (node->parent))
|
for (p = parent (node);
|
||||||
|
p && is_red (p);
|
||||||
|
p = parent (node))
|
||||||
{
|
{
|
||||||
/* we have a violation */
|
GtkRbNode *pp = parent (p);
|
||||||
g_assert (node->parent->parent);
|
|
||||||
|
|
||||||
if (node->parent == node->parent->parent->left)
|
/* we have a violation */
|
||||||
|
g_assert (pp);
|
||||||
|
|
||||||
|
if (p == pp->left)
|
||||||
{
|
{
|
||||||
GtkRbNode *uncle = node->parent->parent->right;
|
GtkRbNode *uncle = pp->right;
|
||||||
|
|
||||||
if (is_red (uncle))
|
if (is_red (uncle))
|
||||||
{
|
{
|
||||||
/* uncle is red */
|
/* uncle is red */
|
||||||
set_black (node->parent);
|
set_black (p);
|
||||||
set_black (uncle);
|
set_black (uncle);
|
||||||
set_red (node->parent->parent);
|
set_red (pp);
|
||||||
node = node->parent->parent;
|
node = pp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* uncle is black */
|
/* uncle is black */
|
||||||
if (node == node->parent->right)
|
if (node == p->right)
|
||||||
{
|
{
|
||||||
/* make node a left child */
|
/* make node a left child */
|
||||||
node = node->parent;
|
node = p;
|
||||||
|
p = parent (node);
|
||||||
|
pp = parent (p);
|
||||||
gtk_rb_node_rotate_left (tree, node);
|
gtk_rb_node_rotate_left (tree, node);
|
||||||
}
|
}
|
||||||
/* recolor and rotate */
|
/* recolor and rotate */
|
||||||
set_black (node->parent);
|
set_black (p);
|
||||||
set_red (node->parent->parent);
|
set_red (pp);
|
||||||
gtk_rb_node_rotate_right (tree, node->parent->parent);
|
gtk_rb_node_rotate_right (tree, pp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* mirror image of above code */
|
/* mirror image of above code */
|
||||||
GtkRbNode *uncle = node->parent->parent->left;
|
GtkRbNode *uncle = pp->left;
|
||||||
|
|
||||||
if (is_red (uncle))
|
if (is_red (uncle))
|
||||||
{
|
{
|
||||||
/* uncle is red */
|
/* uncle is red */
|
||||||
set_black (node->parent);
|
set_black (p);
|
||||||
set_black (uncle);
|
set_black (uncle);
|
||||||
set_red (node->parent->parent);
|
set_red (pp);
|
||||||
node = node->parent->parent;
|
node = pp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* uncle is black */
|
/* uncle is black */
|
||||||
if (node == node->parent->left)
|
if (node == p->left)
|
||||||
{
|
{
|
||||||
node = node->parent;
|
node = p;
|
||||||
|
p = parent (node);
|
||||||
|
pp = parent (p);
|
||||||
gtk_rb_node_rotate_right (tree, node);
|
gtk_rb_node_rotate_right (tree, node);
|
||||||
}
|
}
|
||||||
set_black (node->parent);
|
set_black (p);
|
||||||
set_red (node->parent->parent);
|
set_red (pp);
|
||||||
gtk_rb_node_rotate_left (tree, node->parent->parent);
|
gtk_rb_node_rotate_left (tree, pp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -351,25 +371,25 @@ gtk_rb_tree_insert_fixup (GtkRbTree *tree,
|
|||||||
static void
|
static void
|
||||||
gtk_rb_tree_remove_node_fixup (GtkRbTree *tree,
|
gtk_rb_tree_remove_node_fixup (GtkRbTree *tree,
|
||||||
GtkRbNode *node,
|
GtkRbNode *node,
|
||||||
GtkRbNode *parent)
|
GtkRbNode *p)
|
||||||
{
|
{
|
||||||
while (node != tree->root && is_black (node))
|
while (node != tree->root && is_black (node))
|
||||||
{
|
{
|
||||||
if (node == parent->left)
|
if (node == p->left)
|
||||||
{
|
{
|
||||||
GtkRbNode *w = parent->right;
|
GtkRbNode *w = p->right;
|
||||||
|
|
||||||
if (is_red (w))
|
if (is_red (w))
|
||||||
{
|
{
|
||||||
set_black (w);
|
set_black (w);
|
||||||
set_red (parent);
|
set_red (p);
|
||||||
gtk_rb_node_rotate_left (tree, parent);
|
gtk_rb_node_rotate_left (tree, p);
|
||||||
w = parent->right;
|
w = p->right;
|
||||||
}
|
}
|
||||||
if (is_black (w->left) && is_black (w->right))
|
if (is_black (w->left) && is_black (w->right))
|
||||||
{
|
{
|
||||||
set_red (w);
|
set_red (w);
|
||||||
node = parent;
|
node = p;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -378,29 +398,29 @@ gtk_rb_tree_remove_node_fixup (GtkRbTree *tree,
|
|||||||
set_black (w->left);
|
set_black (w->left);
|
||||||
set_red (w);
|
set_red (w);
|
||||||
gtk_rb_node_rotate_right (tree, w);
|
gtk_rb_node_rotate_right (tree, w);
|
||||||
w = parent->right;
|
w = p->right;
|
||||||
}
|
}
|
||||||
w->red = parent->red;
|
w->red = p->red;
|
||||||
set_black (parent);
|
set_black (p);
|
||||||
set_black (w->right);
|
set_black (w->right);
|
||||||
gtk_rb_node_rotate_left (tree, parent);
|
gtk_rb_node_rotate_left (tree, p);
|
||||||
node = tree->root;
|
node = tree->root;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GtkRbNode *w = parent->left;
|
GtkRbNode *w = p->left;
|
||||||
if (is_red (w))
|
if (is_red (w))
|
||||||
{
|
{
|
||||||
set_black (w);
|
set_black (w);
|
||||||
set_red (parent);
|
set_red (p);
|
||||||
gtk_rb_node_rotate_right (tree, parent);
|
gtk_rb_node_rotate_right (tree, p);
|
||||||
w = parent->left;
|
w = p->left;
|
||||||
}
|
}
|
||||||
if (is_black (w->right) && is_black (w->left))
|
if (is_black (w->right) && is_black (w->left))
|
||||||
{
|
{
|
||||||
set_red (w);
|
set_red (w);
|
||||||
node = parent;
|
node = p;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -409,17 +429,17 @@ gtk_rb_tree_remove_node_fixup (GtkRbTree *tree,
|
|||||||
set_black (w->right);
|
set_black (w->right);
|
||||||
set_red (w);
|
set_red (w);
|
||||||
gtk_rb_node_rotate_left (tree, w);
|
gtk_rb_node_rotate_left (tree, w);
|
||||||
w = parent->left;
|
w = p->left;
|
||||||
}
|
}
|
||||||
w->red = parent->red;
|
w->red = p->red;
|
||||||
set_black (parent);
|
set_black (p);
|
||||||
set_black (w->left);
|
set_black (w->left);
|
||||||
gtk_rb_node_rotate_right (tree, parent);
|
gtk_rb_node_rotate_right (tree, p);
|
||||||
node = tree->root;
|
node = tree->root;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parent = node->parent;
|
p = parent (node);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_black (node);
|
set_black (node);
|
||||||
@ -509,7 +529,7 @@ gpointer
|
|||||||
gtk_rb_tree_get_parent (GtkRbTree *tree,
|
gtk_rb_tree_get_parent (GtkRbTree *tree,
|
||||||
gpointer node)
|
gpointer node)
|
||||||
{
|
{
|
||||||
return NODE_TO_POINTER (NODE_FROM_POINTER (node)->parent);
|
return NODE_TO_POINTER (parent (NODE_FROM_POINTER (node)));
|
||||||
}
|
}
|
||||||
|
|
||||||
gpointer
|
gpointer
|
||||||
@ -575,7 +595,7 @@ gtk_rb_tree_insert_before (GtkRbTree *tree,
|
|||||||
{
|
{
|
||||||
current->left = result;
|
current->left = result;
|
||||||
}
|
}
|
||||||
result->parent = current;
|
set_parent (tree, result, current);
|
||||||
gtk_rb_node_mark_dirty (current, TRUE);
|
gtk_rb_node_mark_dirty (current, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -615,7 +635,7 @@ gtk_rb_tree_insert_after (GtkRbTree *tree,
|
|||||||
{
|
{
|
||||||
current->right = result;
|
current->right = result;
|
||||||
}
|
}
|
||||||
result->parent = current;
|
set_parent (tree, result, current);
|
||||||
gtk_rb_node_mark_dirty (current, TRUE);
|
gtk_rb_node_mark_dirty (current, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,7 +648,7 @@ void
|
|||||||
gtk_rb_tree_remove (GtkRbTree *tree,
|
gtk_rb_tree_remove (GtkRbTree *tree,
|
||||||
gpointer node)
|
gpointer node)
|
||||||
{
|
{
|
||||||
GtkRbNode *x, *y, *real_node;
|
GtkRbNode *x, *y, *p, *real_node;
|
||||||
|
|
||||||
real_node = NODE_FROM_POINTER (node);
|
real_node = NODE_FROM_POINTER (node);
|
||||||
y = real_node;
|
y = real_node;
|
||||||
@ -647,25 +667,22 @@ gtk_rb_tree_remove (GtkRbTree *tree,
|
|||||||
x = y->right;
|
x = y->right;
|
||||||
|
|
||||||
/* remove y from the parent chain */
|
/* remove y from the parent chain */
|
||||||
|
p = parent (y);
|
||||||
if (x != NULL)
|
if (x != NULL)
|
||||||
x->parent = y->parent;
|
set_parent (tree, x, p);
|
||||||
if (y->parent)
|
if (p)
|
||||||
{
|
{
|
||||||
if (y == y->parent->left)
|
if (y == p->left)
|
||||||
y->parent->left = x;
|
p->left = x;
|
||||||
else
|
else
|
||||||
y->parent->right = x;
|
p->right = x;
|
||||||
gtk_rb_node_mark_dirty (y->parent, TRUE);
|
gtk_rb_node_mark_dirty (p, TRUE);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tree->root = x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to clean up the validity of the tree.
|
/* We need to clean up the validity of the tree.
|
||||||
*/
|
*/
|
||||||
if (is_black (y))
|
if (is_black (y))
|
||||||
gtk_rb_tree_remove_node_fixup (tree, x, y->parent);
|
gtk_rb_tree_remove_node_fixup (tree, x, p);
|
||||||
|
|
||||||
if (y != real_node)
|
if (y != real_node)
|
||||||
{
|
{
|
||||||
@ -675,22 +692,19 @@ gtk_rb_tree_remove (GtkRbTree *tree,
|
|||||||
|
|
||||||
y->left = real_node->left;
|
y->left = real_node->left;
|
||||||
if (y->left)
|
if (y->left)
|
||||||
y->left->parent = y;
|
set_parent (tree, y->left, y);
|
||||||
y->right = real_node->right;
|
y->right = real_node->right;
|
||||||
if (y->right)
|
if (y->right)
|
||||||
y->right->parent = y;
|
set_parent (tree, y->right, y);
|
||||||
y->parent = real_node->parent;
|
p = parent (real_node);
|
||||||
if (y->parent)
|
set_parent (tree, y, p);
|
||||||
|
if (p)
|
||||||
{
|
{
|
||||||
if (y->parent->left == real_node)
|
if (p->left == real_node)
|
||||||
y->parent->left = y;
|
p->left = y;
|
||||||
else
|
else
|
||||||
y->parent->right = y;
|
p->right = y;
|
||||||
gtk_rb_node_mark_dirty (y->parent, TRUE);
|
gtk_rb_node_mark_dirty (p, TRUE);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tree->root = y;
|
|
||||||
}
|
}
|
||||||
gtk_rb_node_mark_dirty (y, TRUE);
|
gtk_rb_node_mark_dirty (y, TRUE);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user