Change GtkTreePath to grow exponentially

To avoid quadratic behaviour when building up
paths by repeated appending indices. Bug 634491.
This commit is contained in:
Matthias Clasen 2011-05-31 22:10:58 -04:00
parent 906292541a
commit 2833cc2327

View File

@ -222,7 +222,8 @@ static guint tree_model_signals[LAST_SIGNAL] = { 0 };
struct _GtkTreePath struct _GtkTreePath
{ {
gint depth; gint depth; /* Number of elements */
gint alloc; /* Number of allocated elements */
gint *indices; gint *indices;
}; };
@ -559,6 +560,7 @@ gtk_tree_path_new (void)
GtkTreePath *retval; GtkTreePath *retval;
retval = g_slice_new (GtkTreePath); retval = g_slice_new (GtkTreePath);
retval->depth = 0; retval->depth = 0;
retval->alloc = 0;
retval->indices = NULL; retval->indices = NULL;
return retval; return retval;
@ -724,14 +726,23 @@ gtk_tree_path_new_first (void)
*/ */
void void
gtk_tree_path_append_index (GtkTreePath *path, gtk_tree_path_append_index (GtkTreePath *path,
gint index) gint index_)
{ {
g_return_if_fail (path != NULL); g_return_if_fail (path != NULL);
g_return_if_fail (index >= 0); g_return_if_fail (index_ >= 0);
if (path->depth == path->alloc)
{
gint *indices;
path->alloc = MAX (path->alloc * 2, 1);
indices = g_new (gint, path->alloc);
memcpy (indices, path->indices, path->depth * sizeof (gint));
g_free (path->indices);
path->indices = indices;
}
path->depth += 1; path->depth += 1;
path->indices = g_realloc (path->indices, path->depth * sizeof(gint)); path->indices[path->depth - 1] = index_;
path->indices[path->depth - 1] = index;
} }
/** /**
@ -747,20 +758,19 @@ void
gtk_tree_path_prepend_index (GtkTreePath *path, gtk_tree_path_prepend_index (GtkTreePath *path,
gint index) gint index)
{ {
gint *new_indices; if (path->depth == path->alloc)
(path->depth)++;
new_indices = g_new (gint, path->depth);
if (path->indices == NULL)
{ {
path->indices = new_indices; gint *indices;
path->indices[0] = index; path->alloc = MAX (path->alloc * 2, 1);
return; indices = g_new (gint, path->alloc);
} memcpy (indices + 1, path->indices, path->depth * sizeof (gint));
memcpy (new_indices + 1, path->indices, (path->depth - 1)*sizeof (gint));
g_free (path->indices); g_free (path->indices);
path->indices = new_indices; path->indices = indices;
}
else if (path->depth > 0)
memmove (path->indices + 1, path->indices, path->depth * sizeof (gint));
path->depth += 1;
path->indices[0] = index; path->indices[0] = index;
} }
@ -789,6 +799,8 @@ gtk_tree_path_get_depth (GtkTreePath *path)
* This is an array of integers, each representing a node in a tree. * This is an array of integers, each representing a node in a tree.
* This value should not be freed. * This value should not be freed.
* *
* The length of the array can be obtained with gtk_tree_path_get_depth().
*
* Return value: The current indices, or %NULL * Return value: The current indices, or %NULL
*/ */
gint * gint *
@ -863,7 +875,8 @@ gtk_tree_path_copy (const GtkTreePath *path)
retval = g_slice_new (GtkTreePath); retval = g_slice_new (GtkTreePath);
retval->depth = path->depth; retval->depth = path->depth;
retval->indices = g_new (gint, path->depth); retval->alloc = retval->depth;
retval->indices = g_new (gint, path->alloc);
memcpy (retval->indices, path->indices, path->depth * sizeof (gint)); memcpy (retval->indices, path->indices, path->depth * sizeof (gint));
return retval; return retval;
} }