From bf367b219bfc2bbaa9b326dec224f2b5941182da Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 30 Jun 2020 23:37:21 -0400 Subject: [PATCH] stringlist: Use an array A version of GtkStringList that uses a GPtrArray to hold the strings / objects. We avoid a second array by marking strings using a low bit of the pointer. --- gtk/gtkstringlist.c | 148 +++++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 71 deletions(-) diff --git a/gtk/gtkstringlist.c b/gtk/gtkstringlist.c index 608081d500..45ee337992 100644 --- a/gtk/gtkstringlist.c +++ b/gtk/gtkstringlist.c @@ -145,23 +145,6 @@ gtk_string_object_class_init (GtkStringObjectClass *class) } -static GtkStringObject * -gtk_string_object_new_take (char *string) -{ - GtkStringObject *obj; - - obj = g_object_new (GTK_TYPE_STRING_OBJECT, NULL); - obj->string = string; - - return obj; -} - -static GtkStringObject * -gtk_string_object_new (const char *string) -{ - return gtk_string_object_new_take (g_strdup (string)); -} - /** * gtk_string_object_get_string: * @self: a #GtkStringObject @@ -182,7 +165,7 @@ struct _GtkStringList { GObject parent_instance; - GSequence *items; + GPtrArray *items; }; struct _GtkStringListClass @@ -201,7 +184,25 @@ gtk_string_list_get_n_items (GListModel *list) { GtkStringList *self = GTK_STRING_LIST (list); - return g_sequence_get_length (self->items); + return self->items->len; +} + +static inline gboolean +IS_STRING (gpointer item) +{ + return GPOINTER_TO_INT (item) & 0x1; +} + +static inline gpointer +TO_STRING (gpointer item) +{ + return GINT_TO_POINTER (GPOINTER_TO_INT (item) & ~0x1); +} + +static inline gpointer +MAKE_STRING (const char *str) +{ + return GINT_TO_POINTER (GPOINTER_TO_INT (str) | 0x1); } static gpointer @@ -209,14 +210,23 @@ gtk_string_list_get_item (GListModel *list, guint position) { GtkStringList *self = GTK_STRING_LIST (list); - GSequenceIter *iter; + gpointer item; - iter = g_sequence_get_iter_at_pos (self->items, position); - - if (g_sequence_iter_is_end (iter)) + if (position >= self->items->len) return NULL; - else - return g_object_ref (g_sequence_get (iter)); + + item = g_ptr_array_index (self->items, position); + + if (IS_STRING (item)) + { + GtkStringObject *obj = g_object_new (GTK_TYPE_STRING_OBJECT, NULL); + obj->string = (char *)TO_STRING (item); + g_assert (!IS_STRING (obj)); + g_ptr_array_index (self->items, position) = obj; + item = obj; + } + + return g_object_ref (item); } static void @@ -323,7 +333,7 @@ item_end_element (GtkBuildableParseContext *context, g_string_assign (data->string, translated); } - g_sequence_append (data->list->items, gtk_string_object_new (data->string->str)); + g_ptr_array_add (data->list->items, MAKE_STRING (g_strdup (data->string->str))); } data->translatable = FALSE; @@ -403,7 +413,7 @@ gtk_string_list_dispose (GObject *object) { GtkStringList *self = GTK_STRING_LIST (object); - g_clear_pointer (&self->items, g_sequence_free); + g_clear_pointer (&self->items, g_ptr_array_unref); G_OBJECT_CLASS (gtk_string_list_parent_class)->dispose (object); } @@ -416,10 +426,19 @@ gtk_string_list_class_init (GtkStringListClass *class) gobject_class->dispose = gtk_string_list_dispose; } +static void +free_string_or_object (gpointer data) +{ + if (IS_STRING (data)) + g_free (TO_STRING (data)); + else + g_object_unref (data); +} + static void gtk_string_list_init (GtkStringList *self) { - self->items = g_sequence_new (g_object_unref); + self->items = g_ptr_array_new_full (32, free_string_or_object); } /** @@ -468,39 +487,30 @@ gtk_string_list_splice (GtkStringList *self, guint n_removals, const char * const *additions) { - GSequenceIter *it; - guint add, n_items; + guint n_items; + guint i; + gpointer item; g_return_if_fail (GTK_IS_STRING_LIST (self)); g_return_if_fail (position + n_removals >= position); /* overflow */ - n_items = g_sequence_get_length (self->items); + n_items = self->items->len; g_return_if_fail (position + n_removals <= n_items); - it = g_sequence_get_iter_at_pos (self->items, position); - - if (n_removals) - { - GSequenceIter *end; - - end = g_sequence_iter_move (it, n_removals); - g_sequence_remove_range (it, end); - - it = end; - } + for (i = 0; i < n_removals; i++) + g_ptr_array_remove_index (self->items, position); if (additions) - { - for (add = 0; additions[add]; add++) - { - g_sequence_insert_before (it, gtk_string_object_new (additions[add])); - } - } + for (i = 0; additions[i]; i++) + { + item = MAKE_STRING (g_strdup (additions[i])); + g_ptr_array_insert (self->items, position + i, item); + } else - add = 0; + i = 0; - if (n_removals || add) - g_list_model_items_changed (G_LIST_MODEL (self), position, n_removals, add); + if (n_removals || i) + g_list_model_items_changed (G_LIST_MODEL (self), position, n_removals, i); } /** @@ -518,11 +528,13 @@ gtk_string_list_append (GtkStringList *self, const char *string) { guint n_items; + gpointer item; g_return_if_fail (GTK_IS_STRING_LIST (self)); - n_items = g_sequence_get_length (self->items); - g_sequence_append (self->items, gtk_string_object_new (string)); + n_items = self->items->len; + item = MAKE_STRING (g_strdup (string)); + g_ptr_array_add (self->items, item); g_list_model_items_changed (G_LIST_MODEL (self), n_items, 0, 1); } @@ -547,11 +559,13 @@ gtk_string_list_take (GtkStringList *self, char *string) { guint n_items; + gpointer item; g_return_if_fail (GTK_IS_STRING_LIST (self)); - n_items = g_sequence_get_length (self->items); - g_sequence_append (self->items, gtk_string_object_new_take (string)); + n_items = self->items->len; + item = MAKE_STRING (string); + g_ptr_array_add (self->items, item); g_list_model_items_changed (G_LIST_MODEL (self), n_items, 0, 1); } @@ -568,14 +582,12 @@ void gtk_string_list_remove (GtkStringList *self, guint position) { - GSequenceIter *iter; - g_return_if_fail (GTK_IS_STRING_LIST (self)); - iter = g_sequence_get_iter_at_pos (self->items, position); - g_return_if_fail (!g_sequence_iter_is_end (iter)); + if (position >= self->items->len) + return; - g_sequence_remove (iter); + g_ptr_array_remove_index (self->items, position); g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 0); } @@ -597,20 +609,14 @@ const char * gtk_string_list_get_string (GtkStringList *self, guint position) { - GSequenceIter *iter; + gpointer item; g_return_val_if_fail (GTK_IS_STRING_LIST (self), NULL); - iter = g_sequence_get_iter_at_pos (self->items, position); + item = g_ptr_array_index (self->items, position); - if (g_sequence_iter_is_end (iter)) - { - return NULL; - } + if (IS_STRING (item)) + return (const char *)TO_STRING (item); else - { - GtkStringObject *obj = g_sequence_get (iter); - - return obj->string; - } + return GTK_STRING_OBJECT (item)->string; }