X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkrbtree.c;h=d3e1fef7a61b37624aac786e780daa1db567e56d;hb=HEAD;hp=6304ee875cfc8b0a74636112fab886c312e6fcfa;hpb=a4630d0e7b233479825b059e0df0e6d65b0e6734;p=~andy%2Fgtk diff --git a/gtk/gtkrbtree.c b/gtk/gtkrbtree.c index 6304ee875..d3e1fef7a 100644 --- a/gtk/gtkrbtree.c +++ b/gtk/gtkrbtree.c @@ -12,9 +12,7 @@ * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #include "config.h" @@ -61,9 +59,9 @@ _gtk_rbnode_new (GtkRBTree *tree, { GtkRBNode *node = g_slice_new (GtkRBNode); - node->left = tree->nil; - node->right = tree->nil; - node->parent = tree->nil; + node->left = (GtkRBNode *) &nil; + node->right = (GtkRBNode *) &nil; + node->parent = (GtkRBNode *) &nil; node->flags = GTK_RBNODE_RED; node->total_count = 1; node->count = 1; @@ -95,24 +93,20 @@ _gtk_rbnode_rotate_left (GtkRBTree *tree, GtkRBNode *node) { gint node_height, right_height; - GtkRBNode *right = node->right; + GtkRBNode *right; g_return_if_fail (!_gtk_rbtree_is_nil (node)); + g_return_if_fail (!_gtk_rbtree_is_nil (node->right)); - node_height = node->offset - - (node->left?node->left->offset:0) - - (node->right?node->right->offset:0) - - (node->children?node->children->root->offset:0); - right_height = right->offset - - (right->left?right->left->offset:0) - - (right->right?right->right->offset:0) - - (right->children?right->children->root->offset:0); + right = node->right; + + node_height = GTK_RBNODE_GET_HEIGHT (node); + right_height = GTK_RBNODE_GET_HEIGHT (right); node->right = right->left; if (!_gtk_rbtree_is_nil (right->left)) right->left->parent = node; - if (!_gtk_rbtree_is_nil (right)) - right->parent = node->parent; + right->parent = node->parent; if (!_gtk_rbtree_is_nil (node->parent)) { if (node == node->parent->left) @@ -124,22 +118,15 @@ _gtk_rbnode_rotate_left (GtkRBTree *tree, } right->left = node; - if (!_gtk_rbtree_is_nil (node)) - node->parent = right; - - node->count = 1 + (node->left?node->left->count:0) + - (node->right?node->right->count:0); - right->count = 1 + (right->left?right->left->count:0) + - (right->right?right->right->count:0); - - node->offset = node_height + - (node->left?node->left->offset:0) + - (node->right?node->right->offset:0) + - (node->children?node->children->root->offset:0); - right->offset = right_height + - (right->left?right->left->offset:0) + - (right->right?right->right->offset:0) + - (right->children?right->children->root->offset:0); + node->parent = right; + + node->count = 1 + node->left->count + node->right->count; + right->count = 1 + right->left->count + right->right->count; + + node->offset = node_height + node->left->offset + node->right->offset + + (node->children ? node->children->root->offset : 0); + right->offset = right_height + right->left->offset + right->right->offset + + (right->children ? right->children->root->offset : 0); _fixup_validation (tree, node); _fixup_validation (tree, right); @@ -152,25 +139,21 @@ _gtk_rbnode_rotate_right (GtkRBTree *tree, GtkRBNode *node) { gint node_height, left_height; - GtkRBNode *left = node->left; + GtkRBNode *left; g_return_if_fail (!_gtk_rbtree_is_nil (node)); + g_return_if_fail (!_gtk_rbtree_is_nil (node->left)); + + left = node->left; - node_height = node->offset - - (node->left?node->left->offset:0) - - (node->right?node->right->offset:0) - - (node->children?node->children->root->offset:0); - left_height = left->offset - - (left->left?left->left->offset:0) - - (left->right?left->right->offset:0) - - (left->children?left->children->root->offset:0); + node_height = GTK_RBNODE_GET_HEIGHT (node); + left_height = GTK_RBNODE_GET_HEIGHT (left); node->left = left->right; if (!_gtk_rbtree_is_nil (left->right)) left->right->parent = node; - if (!_gtk_rbtree_is_nil (left)) - left->parent = node->parent; + left->parent = node->parent; if (!_gtk_rbtree_is_nil (node->parent)) { if (node == node->parent->right) @@ -185,22 +168,15 @@ _gtk_rbnode_rotate_right (GtkRBTree *tree, /* link node and left */ left->right = node; - if (!_gtk_rbtree_is_nil (node)) - node->parent = left; - - node->count = 1 + (node->left?node->left->count:0) + - (node->right?node->right->count:0); - left->count = 1 + (left->left?left->left->count:0) + - (left->right?left->right->count:0); - - node->offset = node_height + - (node->left?node->left->offset:0) + - (node->right?node->right->offset:0) + - (node->children?node->children->root->offset:0); - left->offset = left_height + - (left->left?left->left->offset:0) + - (left->right?left->right->offset:0) + - (left->children?left->children->root->offset:0); + node->parent = left; + + node->count = 1 + node->left->count + node->right->count; + left->count = 1 + left->left->count + left->right->count; + + node->offset = node_height + node->left->offset + node->right->offset + + (node->children ? node->children->root->offset : 0); + left->offset = left_height + left->left->offset + left->right->offset + + (left->children?left->children->root->offset:0); _fixup_validation (tree, node); _fixup_validation (tree, left); @@ -357,9 +333,8 @@ _gtk_rbtree_new (void) retval->parent_tree = NULL; retval->parent_node = NULL; - retval->nil = (GtkRBNode *) &nil; + retval->root = (GtkRBNode *) &nil; - retval->root = retval->nil; return retval; } @@ -473,11 +448,11 @@ _gtk_rbtree_insert_after (GtkRBTree *tree, } /* setup new node */ node = _gtk_rbnode_new (tree, height); - node->parent = (current?current:tree->nil); /* insert node in tree */ if (current) { + node->parent = current; if (right) current->right = node; else @@ -541,11 +516,11 @@ _gtk_rbtree_insert_before (GtkRBTree *tree, /* setup new node */ node = _gtk_rbnode_new (tree, height); - node->parent = (current?current:tree->nil); /* insert node in tree */ if (current) { + node->parent = current; if (left) current->left = node; else @@ -681,8 +656,8 @@ _gtk_rbtree_node_mark_valid (GtkRBTree *tree, if ((GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID)) || (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID)) || (node->children && GTK_RBNODE_FLAG_SET (node->children->root, GTK_RBNODE_DESCENDANTS_INVALID)) || - (!_gtk_rbtree_is_nil (node->left) && GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID)) || - (!_gtk_rbtree_is_nil (node->right) && GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID))) + (GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID)) || + (GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID))) return; GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID); @@ -790,65 +765,48 @@ _gtk_rbtree_set_fixed_height (GtkRBTree *tree, while ((node = _gtk_rbtree_next (tree, node)) != NULL); } -typedef struct _GtkRBReorder -{ - GtkRBTree *children; - gint height; - gint flags; - gint order; - gint invert_order; - guint total_count; -} GtkRBReorder; - -static int -gtk_rbtree_reorder_sort_func (gconstpointer a, - gconstpointer b) +static void +reorder_prepare (GtkRBTree *tree, + GtkRBNode *node, + gpointer data) { - return ((GtkRBReorder *) a)->order - ((GtkRBReorder *) b)->order; + node->offset -= node->left->offset + node->right->offset; + GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID); } -static int -gtk_rbtree_reorder_invert_func (gconstpointer a, - gconstpointer b) +static void +reorder_fixup (GtkRBTree *tree, + GtkRBNode *node, + gpointer data) { - return ((GtkRBReorder *) a)->invert_order - ((GtkRBReorder *) b)->invert_order; + node->offset += node->left->offset + node->right->offset; + node->count = 1 + node->left->count + node->right->count; + _fixup_validation (tree, node); + _fixup_total_count (tree, node); } static void -gtk_rbtree_reorder_fixup (GtkRBTree *tree, - GtkRBNode *node) +reorder_copy_node (GtkRBTree *tree, + GtkRBNode *to, + GtkRBNode *from) { - if (_gtk_rbtree_is_nil (node)) - return; - - node->total_count = 1; - - if (!_gtk_rbtree_is_nil (node->left)) - { - gtk_rbtree_reorder_fixup (tree, node->left); - node->offset += node->left->offset; - node->total_count += node->left->total_count; - } - if (!_gtk_rbtree_is_nil (node->right)) - { - gtk_rbtree_reorder_fixup (tree, node->right); - node->offset += node->right->offset; - node->total_count += node->right->total_count; - } - - if (node->children) - { - node->offset += node->children->root->offset; - node->total_count += node->children->root->total_count; - } - - if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) || - (!_gtk_rbtree_is_nil (node->right) && GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID)) || - (!_gtk_rbtree_is_nil (node->left) && GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID)) || - (node->children && GTK_RBNODE_FLAG_SET (node->children->root, GTK_RBNODE_DESCENDANTS_INVALID))) - GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID); - else - GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID); + to->flags = (to->flags & GTK_RBNODE_NON_COLORS) | GTK_RBNODE_GET_COLOR (from); + + to->left = from->left; + if (!_gtk_rbtree_is_nil (to->left)) + to->left->parent = to; + + to->right = from->right; + if (!_gtk_rbtree_is_nil (to->right)) + to->right->parent = to; + + to->parent = from->parent; + if (_gtk_rbtree_is_nil (to->parent)) + tree->root = to; + else if (to->parent->left == from) + to->parent->left = to; + else if (to->parent->right == from) + to->parent->right = to; } /* It basically pulls everything out of the tree, rearranges it, and puts it @@ -862,61 +820,89 @@ _gtk_rbtree_reorder (GtkRBTree *tree, gint *new_order, gint length) { - GtkRBReorder reorder = { NULL }; - GArray *array; + GtkRBNode **nodes; GtkRBNode *node; - gint i; + gint i, j; g_return_if_fail (tree != NULL); g_return_if_fail (length > 0); g_return_if_fail (tree->root->count == length); - /* Sort the trees values in the new tree. */ - array = g_array_sized_new (FALSE, FALSE, sizeof (GtkRBReorder), length); - for (i = 0; i < length; i++) - { - reorder.order = new_order[i]; - reorder.invert_order = i; - g_array_append_val (array, reorder); - } + nodes = g_new (GtkRBNode *, length); - g_array_sort(array, gtk_rbtree_reorder_sort_func); + _gtk_rbtree_traverse (tree, tree->root, G_PRE_ORDER, reorder_prepare, NULL); - /* rewind node*/ - node = _gtk_rbtree_first (tree); + for (node = _gtk_rbtree_first (tree), i = 0; + node; + node = _gtk_rbtree_next (tree, node), i++) + { + nodes[i] = node; + } for (i = 0; i < length; i++) { - g_assert (!_gtk_rbtree_is_nil (node)); - g_array_index (array, GtkRBReorder, i).children = node->children; - g_array_index (array, GtkRBReorder, i).flags = GTK_RBNODE_NON_COLORS & node->flags; - g_array_index (array, GtkRBReorder, i).height = GTK_RBNODE_GET_HEIGHT (node); + GtkRBNode tmp = { 0, }; + GSList *l, *cycle = NULL; - node = _gtk_rbtree_next (tree, node); - } + tmp.offset = -1; - g_array_sort (array, gtk_rbtree_reorder_invert_func); - - /* rewind node*/ - node = _gtk_rbtree_first (tree); + /* already swapped */ + if (nodes[i] == NULL) + continue; + /* no need to swap */ + if (new_order[i] == i) + continue; - /* Go through the tree and change the values to the new ones. */ - for (i = 0; i < length; i++) - { - reorder = g_array_index (array, GtkRBReorder, i); - node->children = reorder.children; - if (node->children) - node->children->parent_node = node; - node->flags = GTK_RBNODE_GET_COLOR (node) | reorder.flags; - /* We temporarily set the height to this. */ - node->offset = reorder.height; - node = _gtk_rbtree_next (tree, node); + /* make a list out of the pending nodes */ + for (j = i; new_order[j] != i; j = new_order[j]) + { + cycle = g_slist_prepend (cycle, nodes[j]); + nodes[j] = NULL; + } + + node = nodes[j]; + reorder_copy_node (tree, &tmp, node); + for (l = cycle; l; l = l->next) + { + reorder_copy_node (tree, node, l->data); + node = l->data; + } + + reorder_copy_node (tree, node, &tmp); + nodes[j] = NULL; + g_slist_free (cycle); } - gtk_rbtree_reorder_fixup (tree, tree->root); - g_array_free (array, TRUE); + _gtk_rbtree_traverse (tree, tree->root, G_POST_ORDER, reorder_fixup, NULL); + + g_free (nodes); } +/** + * _gtk_rbtree_contains: + * @tree: a tree + * @potential_child: a potential child of @tree + * + * Checks if @potential_child is a child (direct or via intermediate + * trees) of @tree. + * + * Returns: %TRUE if @potentitial_child is a child of @tree. + **/ +gboolean +_gtk_rbtree_contains (GtkRBTree *tree, + GtkRBTree *potential_child) +{ + g_return_val_if_fail (tree != NULL, FALSE); + g_return_val_if_fail (potential_child != NULL, FALSE); + + do { + potential_child = potential_child->parent_tree; + if (potential_child == tree) + return TRUE; + } while (potential_child != NULL); + + return FALSE; +} gint _gtk_rbtree_node_find_offset (GtkRBTree *tree, @@ -987,11 +973,11 @@ _gtk_rbtree_node_get_index (GtkRBTree *tree, return retval; } -gint -_gtk_rbtree_real_find_offset (GtkRBTree *tree, - gint height, - GtkRBTree **new_tree, - GtkRBNode **new_node) +static gint +gtk_rbtree_real_find_offset (GtkRBTree *tree, + gint height, + GtkRBTree **new_tree, + GtkRBNode **new_node) { GtkRBNode *tmp_node; @@ -1035,14 +1021,14 @@ _gtk_rbtree_real_find_offset (GtkRBTree *tree, *new_node = tmp_node; return (height - tmp_node->left->offset); } - return _gtk_rbtree_real_find_offset (tmp_node->children, - height - tmp_node->left->offset - - (tmp_node->offset - - tmp_node->left->offset - - tmp_node->right->offset - - tmp_node->children->root->offset), - new_tree, - new_node); + return gtk_rbtree_real_find_offset (tmp_node->children, + height - tmp_node->left->offset - + (tmp_node->offset - + tmp_node->left->offset - + tmp_node->right->offset - + tmp_node->children->root->offset), + new_tree, + new_node); } *new_tree = tree; *new_node = tmp_node; @@ -1051,9 +1037,9 @@ _gtk_rbtree_real_find_offset (GtkRBTree *tree, gint _gtk_rbtree_find_offset (GtkRBTree *tree, - gint height, - GtkRBTree **new_tree, - GtkRBNode **new_node) + gint height, + GtkRBTree **new_tree, + GtkRBNode **new_node) { g_assert (tree); @@ -1065,7 +1051,7 @@ _gtk_rbtree_find_offset (GtkRBTree *tree, return 0; } - return _gtk_rbtree_real_find_offset (tree, height, new_tree, new_node); + return gtk_rbtree_real_find_offset (tree, height, new_tree, new_node); } gboolean @@ -1467,8 +1453,8 @@ void _fixup_validation (GtkRBTree *tree, { if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) || GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID) || - (!_gtk_rbtree_is_nil (node->left) && GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID)) || - (!_gtk_rbtree_is_nil (node->right) && GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID)) || + GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID) || + GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID) || (node->children != NULL && GTK_RBNODE_FLAG_SET (node->children->root, GTK_RBNODE_DESCENDANTS_INVALID))) { GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID); @@ -1586,8 +1572,8 @@ _gtk_rbtree_test_dirty (GtkRBTree *tree, { g_assert (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID) || GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) || - (!_gtk_rbtree_is_nil (node->left) && GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID)) || - (!_gtk_rbtree_is_nil (node->right) && GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID)) || + GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID) || + GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID) || (node->children && GTK_RBNODE_FLAG_SET (node->children->root, GTK_RBNODE_DESCENDANTS_INVALID))); } else @@ -1666,8 +1652,6 @@ _gtk_rbtree_test (const gchar *where, while (tmp_tree->parent_tree) tmp_tree = tmp_tree->parent_tree; - g_assert (tmp_tree->nil != NULL); - if (_gtk_rbtree_is_nil (tmp_tree->root)) return;