summaryrefslogtreecommitdiff
path: root/gtk/gtktreemodel.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2011-05-31 22:10:58 -0400
committerMatthias Clasen <mclasen@redhat.com>2011-05-31 22:10:58 -0400
commit2833cc2327d10fb7c0670f0284a9ff0dc6ba4790 (patch)
tree9c7d8ef74209519af75b18f4ef69509785c009b7 /gtk/gtktreemodel.c
parent906292541a985d783221b6b73fd8d45d320f567a (diff)
downloadgtk+-2833cc2327d10fb7c0670f0284a9ff0dc6ba4790.tar.gz
Change GtkTreePath to grow exponentially
To avoid quadratic behaviour when building up paths by repeated appending indices. Bug 634491.
Diffstat (limited to 'gtk/gtktreemodel.c')
-rw-r--r--gtk/gtktreemodel.c49
1 files changed, 31 insertions, 18 deletions
diff --git a/gtk/gtktreemodel.c b/gtk/gtktreemodel.c
index b4c342461a..f0043005fe 100644
--- a/gtk/gtktreemodel.c
+++ b/gtk/gtktreemodel.c
@@ -222,7 +222,8 @@ static guint tree_model_signals[LAST_SIGNAL] = { 0 };
struct _GtkTreePath
{
- gint depth;
+ gint depth; /* Number of elements */
+ gint alloc; /* Number of allocated elements */
gint *indices;
};
@@ -559,6 +560,7 @@ gtk_tree_path_new (void)
GtkTreePath *retval;
retval = g_slice_new (GtkTreePath);
retval->depth = 0;
+ retval->alloc = 0;
retval->indices = NULL;
return retval;
@@ -724,14 +726,23 @@ gtk_tree_path_new_first (void)
*/
void
gtk_tree_path_append_index (GtkTreePath *path,
- gint index)
+ gint index_)
{
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->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,
gint index)
{
- gint *new_indices;
-
- (path->depth)++;
- new_indices = g_new (gint, path->depth);
-
- if (path->indices == NULL)
+ if (path->depth == path->alloc)
{
- path->indices = new_indices;
- path->indices[0] = index;
- return;
+ gint *indices;
+ path->alloc = MAX (path->alloc * 2, 1);
+ indices = g_new (gint, path->alloc);
+ memcpy (indices + 1, path->indices, path->depth * sizeof (gint));
+ g_free (path->indices);
+ path->indices = indices;
}
- memcpy (new_indices + 1, path->indices, (path->depth - 1)*sizeof (gint));
- g_free (path->indices);
- path->indices = new_indices;
+ else if (path->depth > 0)
+ memmove (path->indices + 1, path->indices, path->depth * sizeof (gint));
+
+ path->depth += 1;
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 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
*/
gint *
@@ -863,7 +875,8 @@ gtk_tree_path_copy (const GtkTreePath *path)
retval = g_slice_new (GtkTreePath);
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));
return retval;
}