summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-07-16 18:05:43 +0000
committerMatthias Clasen <mclasen@redhat.com>2020-07-16 18:05:43 +0000
commit6b89148487463ffb05779a82287a4304e8622413 (patch)
treef79d11f6ca5ea8ae2236feef55b41266b354b91c
parentddb9e428ece38dc48bd965d661c629df41d92282 (diff)
parent60a09e59e86152e1064f9e345e0ed8bbf5b063e0 (diff)
downloadgtk+-6b89148487463ffb05779a82287a4304e8622413.tar.gz
Merge branch 'wip/otte/vector' into 'master'
Arrays See merge request GNOME/gtk!2197
-rw-r--r--gdk/gdkarrayimpl.c283
-rw-r--r--gtk/gtkarrayimplprivate.h137
-rw-r--r--gtk/gtkcssprovider.c28
-rw-r--r--gtk/gtkcssselector.c37
-rw-r--r--gtk/gtkcssselectorprivate.h11
-rw-r--r--gtk/gtkicontheme.c55
-rw-r--r--gtk/gtkmain.c44
-rw-r--r--gtk/gtksnapshot.c147
-rw-r--r--gtk/gtksnapshotprivate.h70
-rw-r--r--gtk/gtkstringlist.c99
-rw-r--r--testsuite/gdk/array.c105
-rw-r--r--testsuite/gdk/arrayimpl.c117
-rw-r--r--testsuite/gdk/meson.build1
13 files changed, 746 insertions, 388 deletions
diff --git a/gdk/gdkarrayimpl.c b/gdk/gdkarrayimpl.c
new file mode 100644
index 0000000000..b08b43b2c2
--- /dev/null
+++ b/gdk/gdkarrayimpl.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright © 2020 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#ifndef GDK_ARRAY_TYPE_NAME
+#define GDK_ARRAY_TYPE_NAME GdkArray
+#endif
+
+#ifndef GDK_ARRAY_NAME
+#define GDK_ARRAY_NAME gdk_array
+#endif
+
+#ifndef GDK_ARRAY_ELEMENT_TYPE
+#define GDK_ARRAY_ELEMENT_TYPE gpointer
+#endif
+
+#ifdef GDK_ARRAY_PREALLOC
+#if GDK_ARRAY_PREALLOC == 0
+#undef GDK_ARRAY_PREALLOC
+#endif
+#endif
+
+#ifdef GDK_ARRAY_NULL_TERMINATED
+#define GDK_ARRAY_REAL_SIZE(_size) ((_size) + 1)
+#else
+#define GDK_ARRAY_REAL_SIZE(_size) (_size)
+#endif
+
+/* make this readable */
+#define _T_ GDK_ARRAY_ELEMENT_TYPE
+#define GdkArray GDK_ARRAY_TYPE_NAME
+#define gdk_array_paste_more(GDK_ARRAY_NAME, func_name) GDK_ARRAY_NAME ## _ ## func_name
+#define gdk_array_paste(GDK_ARRAY_NAME, func_name) gdk_array_paste_more (GDK_ARRAY_NAME, func_name)
+#define gdk_array(func_name) gdk_array_paste (GDK_ARRAY_NAME, func_name)
+
+typedef struct GdkArray GdkArray;
+
+struct GdkArray
+{
+ _T_ *start;
+ _T_ *end;
+ _T_ *end_allocation;
+#ifdef GDK_ARRAY_PREALLOC
+ _T_ preallocated[GDK_ARRAY_REAL_SIZE(GDK_ARRAY_PREALLOC)];
+#endif
+};
+
+/* no G_GNUC_UNUSED here, if you don't use an array type, remove it. */
+static inline void
+gdk_array(init) (GdkArray *self)
+{
+#ifdef GDK_ARRAY_PREALLOC
+ self->start = self->preallocated;
+ self->end = self->start;
+ self->end_allocation = self->start + GDK_ARRAY_PREALLOC;
+#ifdef GDK_ARRAY_NULL_TERMINATED
+ *self->start = *(_T_[1]) {};
+#endif
+#else
+ self->start = NULL;
+ self->end = NULL;
+ self->end_allocation = NULL;
+#endif
+}
+
+static inline void
+gdk_array(free_elements) (_T_ *start,
+ _T_ *end)
+{
+#ifdef GDK_ARRAY_FREE_FUNC
+ _T_ *e;
+ for (e = start; e < end; e++)
+#ifdef GDK_ARRAY_BY_VALUE
+ GDK_ARRAY_FREE_FUNC (e);
+#else
+ GDK_ARRAY_FREE_FUNC (*e);
+#endif
+#endif
+}
+
+/* no G_GNUC_UNUSED here */
+static inline void
+gdk_array(clear) (GdkArray *self)
+{
+ gdk_array(free_elements) (self->start, self->end);
+
+#ifdef GDK_ARRAY_PREALLOC
+ if (self->start != self->preallocated)
+#endif
+ g_free (self->start);
+ gdk_array(init) (self);
+}
+
+G_GNUC_UNUSED static inline _T_ *
+gdk_array(get_data) (const GdkArray *self)
+{
+ return self->start;
+}
+
+G_GNUC_UNUSED static inline _T_ *
+gdk_array(index) (const GdkArray *self,
+ gsize pos)
+{
+ return self->start + pos;
+}
+
+G_GNUC_UNUSED static inline gsize
+gdk_array(get_capacity) (const GdkArray *self)
+{
+ return self->end_allocation - self->start;
+}
+
+G_GNUC_UNUSED static inline gsize
+gdk_array(get_size) (const GdkArray *self)
+{
+ return self->end - self->start;
+}
+
+G_GNUC_UNUSED static inline gboolean
+gdk_array(is_empty) (const GdkArray *self)
+{
+ return self->end == self->start;
+}
+
+G_GNUC_UNUSED static void
+gdk_array(reserve) (GdkArray *self,
+ gsize n)
+{
+ gsize new_size, size;
+
+ if (n <= gdk_array(get_capacity) (self))
+ return;
+
+ size = gdk_array(get_size) (self);
+ new_size = 1 << g_bit_storage (MAX (GDK_ARRAY_REAL_SIZE (n), 16) - 1);
+
+#ifdef GDK_ARRAY_PREALLOC
+ if (self->start == self->preallocated)
+ {
+ self->start = g_new (_T_, new_size);
+ memcpy (self->start, self->preallocated, sizeof (_T_) * GDK_ARRAY_REAL_SIZE (size));
+ }
+ else
+#endif
+#ifdef GDK_ARRAY_NULL_TERMINATED
+ if (self->start == NULL)
+ {
+ self->start = g_new (_T_, new_size);
+ *self->start = *(_T_[1]) {};
+ }
+ else
+#endif
+ self->start = g_renew (_T_, self->start, new_size);
+
+ self->end = self->start + size;
+ self->end_allocation = self->start + new_size;
+#ifdef GDK_ARRAY_NULL_TERMINATED
+ self->end_allocation--;
+#endif
+}
+
+G_GNUC_UNUSED static void
+gdk_array(splice) (GdkArray *self,
+ gsize pos,
+ gsize removed,
+ _T_ *additions,
+ gsize added)
+{
+ gsize size;
+ gsize remaining;
+
+ size = gdk_array(get_size) (self);
+ g_assert (pos + removed <= size);
+ remaining = size - pos - removed;
+
+ gdk_array(free_elements) (gdk_array(index) (self, pos),
+ gdk_array(index) (self, pos + removed));
+
+ gdk_array(reserve) (self, size - removed + added);
+
+ if (GDK_ARRAY_REAL_SIZE (remaining) && removed != added)
+ memmove (gdk_array(index) (self, pos + added),
+ gdk_array(index) (self, pos + removed),
+ GDK_ARRAY_REAL_SIZE (remaining) * sizeof (_T_));
+
+ if (added)
+ {
+ if (additions)
+ memcpy (gdk_array(index) (self, pos),
+ additions,
+ added * sizeof (_T_));
+ else
+ memset (gdk_array(index) (self, pos), 0, added * sizeof (_T_));
+ }
+
+
+ /* might overflow, but does the right thing */
+ self->end += added - removed;
+}
+
+G_GNUC_UNUSED static void
+gdk_array(set_size) (GdkArray *self,
+ gsize new_size)
+{
+ gsize old_size = gdk_array(get_size) (self);
+ if (new_size > old_size)
+ gdk_array(splice) (self, old_size, 0, NULL, new_size - old_size);
+ else
+ gdk_array(splice) (self, new_size, old_size - new_size, NULL, 0);
+}
+
+G_GNUC_UNUSED static void
+gdk_array(append) (GdkArray *self,
+#ifdef GDK_ARRAY_BY_VALUE
+ _T_ *value)
+#else
+ _T_ value)
+#endif
+{
+ gdk_array(splice) (self,
+ gdk_array(get_size) (self),
+ 0,
+#ifdef GDK_ARRAY_BY_VALUE
+ value,
+#else
+ &value,
+#endif
+ 1);
+}
+
+#ifdef GDK_ARRAY_BY_VALUE
+G_GNUC_UNUSED static _T_ *
+gdk_array(get) (const GdkArray *self,
+ gsize pos)
+{
+ return gdk_array(index) (self, pos);
+}
+#else
+G_GNUC_UNUSED static _T_
+gdk_array(get) (const GdkArray *self,
+ gsize pos)
+ {
+ return *gdk_array(index) (self, pos);
+ }
+#endif
+
+#ifndef GDK_ARRAY_NO_UNDEF
+
+#undef _T_
+#undef GdkArray
+#undef gdk_array_paste_more
+#undef gdk_array_paste
+#undef gdk_array
+#undef GDK_ARRAY_REAL_SIZE
+
+#undef GDK_ARRAY_BY_VALUE
+#undef GDK_ARRAY_ELEMENT_TYPE
+#undef GDK_ARRAY_FREE_FUNC
+#undef GDK_ARRAY_NAME
+#undef GDK_ARRAY_NULL_TERMINATED
+#undef GDK_ARRAY_PREALLOC
+#undef GDK_ARRAY_TYPE_NAME
+
+#endif
diff --git a/gtk/gtkarrayimplprivate.h b/gtk/gtkarrayimplprivate.h
deleted file mode 100644
index cd8051373d..0000000000
--- a/gtk/gtkarrayimplprivate.h
+++ /dev/null
@@ -1,137 +0,0 @@
-#ifndef __GTK_ARRAY_IMPL_PRIVATE_H__
-#define __GTK_ARRAY_IMPL_PRIVATE_H__
-
-
-/* This is a dumbed-down GPtrArray, which takes some stack
- * space to use. When using this, the general case should always
- * be that the number of elements is lower than reserved_size.
- * The GPtrArray should only be used in extreme cases.
- */
-
-typedef struct
-{
- guint reserved_size;
- guint len;
- void **stack_space;
- GPtrArray *ptr_array;
-
-} GtkArray;
-
-
-static inline void
-gtk_array_init (GtkArray *self,
- void **stack_space,
- guint reserved_size)
-{
- self->reserved_size = reserved_size;
- self->len = 0;
- self->stack_space = stack_space;
- self->ptr_array = NULL;
-}
-
-static inline void *
-gtk_array_index (const GtkArray *self,
- guint index)
-{
- g_assert (index < self->len);
-
- if (G_LIKELY (!self->ptr_array))
- return self->stack_space[index];
-
- return g_ptr_array_index (self->ptr_array, index);
-}
-
-static inline void
-gtk_array_add (GtkArray *self,
- void *element)
-{
- if (G_LIKELY (self->len < self->reserved_size))
- {
- self->stack_space[self->len] = element;
- self->len++;
- return;
- }
-
- /* Need to fall back to the GPtrArray */
- if (G_UNLIKELY (!self->ptr_array))
- {
- self->ptr_array = g_ptr_array_new_full (self->len + 1, NULL);
- memcpy (self->ptr_array->pdata, self->stack_space, sizeof (void *) * self->len);
- self->ptr_array->len = self->len;
- }
-
- g_ptr_array_add (self->ptr_array, element);
- self->len++; /* We still count self->len */
-}
-
-static inline void
-gtk_array_insert (GtkArray *self,
- guint index,
- void *element)
-{
- if (index >= self->len)
- {
- gtk_array_add (self, element);
- return;
- }
-
- if (G_LIKELY (self->len < self->reserved_size))
- {
- memmove (self->stack_space + index + 1, self->stack_space + index,
- sizeof (void *) * (self->len - index));
- self->stack_space[index] = element;
- self->len++;
- return;
- }
-
- if (G_UNLIKELY (!self->ptr_array))
- {
- self->ptr_array = g_ptr_array_new_full (self->len + 1, NULL);
- memcpy (self->ptr_array->pdata, self->stack_space, sizeof (void *) * self->len);
- self->ptr_array->len = self->len;
- }
-
- g_assert (self->ptr_array);
- g_ptr_array_insert (self->ptr_array, index, element);
- self->len++;
-}
-
-static inline void
-gtk_array_free (GtkArray *self,
- GDestroyNotify element_free_func)
-{
- guint i;
-
- if (G_LIKELY (!self->ptr_array))
- {
- if (element_free_func)
- {
- for (i = 0; i < self->len; i++)
- element_free_func (self->stack_space[i]);
- }
-
- return;
- }
-
- g_assert (self->ptr_array);
-
- if (element_free_func)
- {
- for (i = 0; i < self->ptr_array->len; i++)
- element_free_func (g_ptr_array_index (self->ptr_array, i));
- }
-
- g_ptr_array_free (self->ptr_array, TRUE);
-}
-
-static inline void **
-gtk_array_get_data (GtkArray *self)
-{
- if (G_LIKELY (!self->ptr_array))
- return self->stack_space;
-
- return self->ptr_array->pdata;
-}
-
-
-#endif
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index 7dbc6924f5..04b3a1d152 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -391,9 +391,9 @@ gtk_css_provider_init (GtkCssProvider *css_provider)
}
static void
-verify_tree_match_results (GtkCssProvider *provider,
- GtkCssNode *node,
- GtkArray *tree_rules)
+verify_tree_match_results (GtkCssProvider *provider,
+ GtkCssNode *node,
+ GtkCssSelectorMatches *tree_rules)
{
#ifdef VERIFY_TREE
GtkCssProviderPrivate *priv = gtk_css_provider_get_instance_private (provider);
@@ -407,9 +407,9 @@ verify_tree_match_results (GtkCssProvider *provider,
ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
- for (j = 0; j < tree_rules->len; j++)
+ for (j = 0; j < gtk_css_selector_matches_get_size (tree_rules); j++)
{
- if (ruleset == gtk_array_index (tree_rules, j))
+ if (ruleset == gtk_css_selector_matches_get (tree_rules, j))
{
found = TRUE;
break;
@@ -459,22 +459,21 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider,
GtkCssRuleset *ruleset;
guint j;
int i;
- GtkArray tree_rules_array;
- GtkCssRuleset *rules_stack[32];
+ GtkCssSelectorMatches tree_rules;
if (_gtk_css_selector_tree_is_empty (priv->tree))
return;
- gtk_array_init (&tree_rules_array, (void**)rules_stack, 32);
- _gtk_css_selector_tree_match_all (priv->tree, filter, node, &tree_rules_array);
+ gtk_css_selector_matches_init (&tree_rules);
+ _gtk_css_selector_tree_match_all (priv->tree, filter, node, &tree_rules);
- if (tree_rules_array.len > 0)
+ if (!gtk_css_selector_matches_is_empty (&tree_rules))
{
- verify_tree_match_results (css_provider, node, &tree_rules_array);
+ verify_tree_match_results (css_provider, node, &tree_rules);
- for (i = tree_rules_array.len - 1; i >= 0; i--)
+ for (i = gtk_css_selector_matches_get_size (&tree_rules) - 1; i >= 0; i--)
{
- ruleset = gtk_array_index (&tree_rules_array, i);
+ ruleset = gtk_css_selector_matches_get (&tree_rules, i);
if (ruleset->styles == NULL)
continue;
@@ -493,9 +492,8 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider,
ruleset->styles[j].value);
}
}
-
- gtk_array_free (&tree_rules_array, NULL);
}
+ gtk_css_selector_matches_clear (&tree_rules);
if (change)
*change = gtk_css_selector_tree_get_change_all (priv->tree, filter, node);
diff --git a/gtk/gtkcssselector.c b/gtk/gtkcssselector.c
index 75c64898c5..7c7c0f8740 100644
--- a/gtk/gtkcssselector.c
+++ b/gtk/gtkcssselector.c
@@ -24,7 +24,6 @@
#include "gtkcssprovider.h"
#include "gtkstylecontextprivate.h"
-#include "gtkarrayimplprivate.h"
#include <errno.h>
#if defined(_MSC_VER) && _MSC_VER >= 1500
@@ -152,14 +151,14 @@ gtk_css_selector_tree_get_matches (const GtkCssSelectorTree *tree)
}
static void
-gtk_array_insert_sorted (GtkArray *array,
- gpointer data)
+gtk_css_selector_matches_insert_sorted (GtkCssSelectorMatches *matches,
+ gpointer data)
{
guint i;
- for (i = 0; i < array->len; i++)
+ for (i = 0; i < gtk_css_selector_matches_get_size (matches); i++)
{
- gpointer elem = gtk_array_index (array, i);
+ gpointer elem = gtk_css_selector_matches_get (matches, i);
if (data == elem)
return;
@@ -168,7 +167,7 @@ gtk_array_insert_sorted (GtkArray *array,
break;
}
- gtk_array_insert (array, i, data);
+ gtk_css_selector_matches_splice (matches, i, 0, (gpointer[1]) { data }, 1);
}
static inline gboolean
@@ -1877,7 +1876,7 @@ gtk_css_selector_tree_get_change (const GtkCssSelectorTree *tree,
static void
gtk_css_selector_tree_found_match (const GtkCssSelectorTree *tree,
- GtkArray *results)
+ GtkCssSelectorMatches *results)
{
int i;
gpointer *matches;
@@ -1887,7 +1886,7 @@ gtk_css_selector_tree_found_match (const GtkCssSelectorTree *tree,
return;
for (i = 0; matches[i] != NULL; i++)
- gtk_array_insert_sorted (results, matches[i]);
+ gtk_css_selector_matches_insert_sorted (results, matches[i]);
}
static gboolean
@@ -1895,7 +1894,7 @@ gtk_css_selector_tree_match (const GtkCssSelectorTree *tree,
const GtkCountingBloomFilter *filter,
gboolean match_filter,
GtkCssNode *node,
- GtkArray *results)
+ GtkCssSelectorMatches *results)
{
const GtkCssSelectorTree *prev;
GtkCssNode *child;
@@ -1932,7 +1931,7 @@ void
_gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
const GtkCountingBloomFilter *filter,
GtkCssNode *node,
- GtkArray *out_tree_rules)
+ GtkCssSelectorMatches *out_tree_rules)
{
const GtkCssSelectorTree *iter;
@@ -2117,8 +2116,7 @@ subdivide_infos (GByteArray *array,
GHashTableIter iter;
guint max_count;
gpointer key, value;
- void *exact_matches_stack[8];
- GtkArray exact_matches_array;
+ GtkCssSelectorMatches exact_matches;
gint32 res;
guint i;
@@ -2160,7 +2158,7 @@ subdivide_infos (GByteArray *array,
matched_infos = g_alloca (sizeof (GtkCssSelectorRuleSetInfo *) * n_infos);
remaining_infos = g_alloca (sizeof (GtkCssSelectorRuleSetInfo *) * n_infos);
- gtk_array_init (&exact_matches_array, (void**)exact_matches_stack, 8);
+ gtk_css_selector_matches_init (&exact_matches);
for (i = 0; i < n_infos; i++)
{
GtkCssSelectorRuleSetInfo *info = infos[i];
@@ -2171,7 +2169,7 @@ subdivide_infos (GByteArray *array,
if (info->current_selector == NULL)
{
/* Matches current node */
- gtk_array_add (&exact_matches_array, info->match);
+ gtk_css_selector_matches_append (&exact_matches, info->match);
if (info->selector_match != NULL)
*info->selector_match = GUINT_TO_POINTER (tree_offset);
}
@@ -2188,17 +2186,16 @@ subdivide_infos (GByteArray *array,
}
}
- if (exact_matches_array.len > 0)
+ if (!gtk_css_selector_matches_is_empty (&exact_matches))
{
- gtk_array_add (&exact_matches_array, NULL); /* Null terminate */
+ gtk_css_selector_matches_append (&exact_matches, NULL); /* Null terminate */
res = array->len;
- g_byte_array_append (array, (guint8 *)gtk_array_get_data (&exact_matches_array),
- exact_matches_array.len * sizeof (gpointer));
-
- gtk_array_free (&exact_matches_array, NULL);
+ g_byte_array_append (array, (guint8 *) gtk_css_selector_matches_get_data (&exact_matches),
+ gtk_css_selector_matches_get_size (&exact_matches) * sizeof (gpointer));
}
else
res = GTK_CSS_SELECTOR_TREE_EMPTY_OFFSET;
+ gtk_css_selector_matches_clear (&exact_matches);
get_tree (array, tree_offset)->matches_offset = res;
res = subdivide_infos (array, matched_infos, n_matched, tree_offset);
diff --git a/gtk/gtkcssselectorprivate.h b/gtk/gtkcssselectorprivate.h
index f635066435..9cff8e90a8 100644
--- a/gtk/gtkcssselectorprivate.h
+++ b/gtk/gtkcssselectorprivate.h
@@ -21,7 +21,12 @@
#include "gtk/gtkcountingbloomfilterprivate.h"
#include "gtk/gtkcsstypesprivate.h"
#include "gtk/gtkcssparserprivate.h"
-#include "gtk/gtkarrayimplprivate.h"
+
+#define GDK_ARRAY_ELEMENT_TYPE gpointer
+#define GDK_ARRAY_TYPE_NAME GtkCssSelectorMatches
+#define GDK_ARRAY_NAME gtk_css_selector_matches
+#define GDK_ARRAY_PREALLOC 32
+#include "gdk/gdkarrayimpl.c"
G_BEGIN_DECLS
@@ -45,8 +50,8 @@ int _gtk_css_selector_compare (const GtkCssSelector *a,
void _gtk_css_selector_tree_free (GtkCssSelectorTree *tree);
void _gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
const GtkCountingBloomFilter *filter,
- GtkCssNode *node,
- GtkArray *out_tree_rules);
+ GtkCssNode *node,
+ GtkCssSelectorMatches *out_tree_rules);
GtkCssChange gtk_css_selector_tree_get_change_all (const GtkCssSelectorTree *tree,
const GtkCountingBloomFilter *filter,
GtkCssNode *node);
diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c
index 7c46cb3267..ea73167f31 100644
--- a/gtk/gtkicontheme.c
+++ b/gtk/gtkicontheme.c
@@ -55,6 +55,14 @@
#include "gdk/gdktextureprivate.h"
#include "gdk/gdkprofilerprivate.h"
+#define GDK_ARRAY_ELEMENT_TYPE char *
+#define GDK_ARRAY_NULL_TERMINATED 1
+#define GDK_ARRAY_FREE_FUNC g_free
+#define GDK_ARRAY_TYPE_NAME GtkStrvBuilder
+#define GDK_ARRAY_NAME gtk_strv_builder
+#define GDK_ARRAY_PREALLOC 16
+#include "gdk/gdkarrayimpl.c"
+
/**
* SECTION:gtkicontheme
* @Short_description: Looking up icons by name
@@ -2276,13 +2284,13 @@ real_choose_icon (GtkIconTheme *self,
}
static void
-icon_name_list_add_icon (GPtrArray *icons,
- const gchar *dir_suffix,
- gchar *icon_name)
+icon_name_list_add_icon (GtkStrvBuilder *icons,
+ const gchar *dir_suffix,
+ gchar *icon_name)
{
if (dir_suffix)
- g_ptr_array_add (icons, g_strconcat (icon_name, dir_suffix, NULL));
- g_ptr_array_add (icons, icon_name);
+ gtk_strv_builder_append (icons, g_strconcat (icon_name, dir_suffix, NULL));
+ gtk_strv_builder_append (icons, icon_name);
}
static GtkIconPaintable *
@@ -2296,7 +2304,7 @@ choose_icon (GtkIconTheme *self,
{
gboolean has_regular = FALSE, has_symbolic = FALSE;
GtkIconPaintable *icon;
- GPtrArray *new_names;
+ GtkStrvBuilder new_names;
const gchar *dir_suffix;
guint i;
@@ -2327,73 +2335,70 @@ choose_icon (GtkIconTheme *self,
if ((flags & GTK_ICON_LOOKUP_FORCE_REGULAR) && has_symbolic)
{
- new_names = g_ptr_array_new_with_free_func (g_free);
+ gtk_strv_builder_init (&new_names);
for (i = 0; icon_names[i]; i++)
{
if (icon_name_is_symbolic (icon_names[i], -1))
- icon_name_list_add_icon (new_names, dir_suffix, g_strndup (icon_names[i], strlen (icon_names[i]) - strlen ("-symbolic")));
+ icon_name_list_add_icon (&new_names, dir_suffix, g_strndup (icon_names[i], strlen (icon_names[i]) - strlen ("-symbolic")));
else
- icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i]));
+ icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
}
for (i = 0; icon_names[i]; i++)
{
if (icon_name_is_symbolic (icon_names[i], -1))
- icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i]));
+ icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
}
- g_ptr_array_add (new_names, NULL);
icon = real_choose_icon (self,
- (const gchar **) new_names->pdata,
+ (const char **) gtk_strv_builder_get_data (&new_names),
size,
scale,
flags & ~(GTK_ICON_LOOKUP_FORCE_REGULAR | GTK_ICON_LOOKUP_FORCE_SYMBOLIC),
non_blocking);
- g_ptr_array_free (new_names, TRUE);
+ gtk_strv_builder_clear (&new_names);
}
else if ((flags & GTK_ICON_LOOKUP_FORCE_SYMBOLIC) && has_regular)
{
- new_names = g_ptr_array_new_with_free_func (g_free);
+ gtk_strv_builder_init (&new_names);
for (i = 0; icon_names[i]; i++)
{
if (!icon_name_is_symbolic (icon_names[i], -1))
- icon_name_list_add_icon (new_names, dir_suffix, g_strconcat (icon_names[i], "-symbolic", NULL));
+ icon_name_list_add_icon (&new_names, dir_suffix, g_strconcat (icon_names[i], "-symbolic", NULL));
else
- icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i]));
+ icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
}
for (i = 0; icon_names[i]; i++)
{
if (!icon_name_is_symbolic (icon_names[i], -1))
- icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i]));
+ icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
}
- g_ptr_array_add (new_names, NULL);
icon = real_choose_icon (self,
- (const gchar **) new_names->pdata,
+ (const char **) gtk_strv_builder_get_data (&new_names),
size,
scale,
flags & ~(GTK_ICON_LOOKUP_FORCE_REGULAR | GTK_ICON_LOOKUP_FORCE_SYMBOLIC),
non_blocking);
- g_ptr_array_free (new_names, TRUE);
+ gtk_strv_builder_clear (&new_names);
}
else if (dir_suffix)
{
- new_names = g_ptr_array_new_with_free_func (g_free);
+ gtk_strv_builder_init (&new_names);
for (i = 0; icon_names[i]; i++)
{
- icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i]));
+ icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
}
- g_ptr_array_add (new_names, NULL);
icon = real_choose_icon (self,
- (const gchar **) new_names->pdata,
+ (const char **) gtk_strv_builder_get_data (&new_names),
size,
scale,
flags & ~(GTK_ICON_LOOKUP_FORCE_REGULAR | GTK_ICON_LOOKUP_FORCE_SYMBOLIC),
non_blocking);
- g_ptr_array_free (new_names, TRUE);
+ gtk_strv_builder_clear (&new_names);
}
else
{
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index e1dd5bd6fc..4ce05ced76 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -95,7 +95,6 @@
#include "gdk/gdk-private.h"
#include "gsk/gskprivate.h"
#include "gsk/gskrendernodeprivate.h"
-#include "gtkarrayimplprivate.h"
#include "gtknative.h"
#include <locale.h>
@@ -138,6 +137,13 @@
#include "a11y/gtkaccessibility.h"
#include "inspector/window.h"
+#define GDK_ARRAY_ELEMENT_TYPE GtkWidget *
+#define GDK_ARRAY_TYPE_NAME GtkWidgetStack
+#define GDK_ARRAY_NAME gtk_widget_stack
+#define GDK_ARRAY_FREE_FUNC g_object_unref
+#define GDK_ARRAY_PREALLOC 16
+#include "gdk/gdkarrayimpl.c"
+
static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
static gint pre_initialized = FALSE;
@@ -1321,8 +1327,7 @@ gtk_synthesize_crossing_events (GtkRoot *toplevel,
double x, y;
GtkWidget *prev;
gboolean seen_ancestor;
- GtkArray target_array;
- GtkWidget *stack_targets[16];
+ GtkWidgetStack target_array;
int i;
if (old_target == new_target)
@@ -1376,19 +1381,19 @@ gtk_synthesize_crossing_events (GtkRoot *toplevel,
widget = _gtk_widget_get_parent (widget);
}
- gtk_array_init (&target_array, (void**)stack_targets, 16);
+ gtk_widget_stack_init (&target_array);
for (widget = new_target; widget; widget = _gtk_widget_get_parent (widget))
- gtk_array_add (&target_array, widget);
+ gtk_widget_stack_append (&target_array, g_object_ref (widget));
crossing.direction = GTK_CROSSING_IN;
seen_ancestor = FALSE;
- for (i = (int)target_array.len - 1; i >= 0; i--)
+ for (i = gtk_widget_stack_get_size (&target_array) - 1; i >= 0; i--)
{
- widget = gtk_array_index (&target_array, i);
+ widget = gtk_widget_stack_get (&target_array, i);
- if (i < (int)target_array.len - 1)
- crossing.new_descendent = gtk_array_index (&target_array, i + 1);
+ if (i < gtk_widget_stack_get_size (&target_array) - 1)
+ crossing.new_descendent = gtk_widget_stack_get (&target_array, i + 1);
else
crossing.new_descendent = NULL;
@@ -1417,7 +1422,7 @@ gtk_synthesize_crossing_events (GtkRoot *toplevel,
gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE);
}
- gtk_array_free (&target_array, NULL);
+ gtk_widget_stack_clear (&target_array);
}
static GtkWidget *
@@ -1994,13 +1999,12 @@ gtk_propagate_event_internal (GtkWidget *widget,
{
gint handled_event = FALSE;
GtkWidget *target = widget;
- GtkArray widget_array;
- GtkWidget *stack_widgets[16];
+ GtkWidgetStack widget_array;
int i;
/* First, propagate event down */
- gtk_array_init (&widget_array, (void**)stack_widgets, 16);
- gtk_array_add (&widget_array, g_object_ref (widget));
+ gtk_widget_stack_init (&widget_array);
+ gtk_widget_stack_append (&widget_array, g_object_ref (widget));
for (;;)
{
@@ -2008,16 +2012,16 @@ gtk_propagate_event_internal (GtkWidget *widget,
if (!widget)
break;
- gtk_array_add (&widget_array, g_object_ref (widget));
+ gtk_widget_stack_append (&widget_array, g_object_ref (widget));
if (widget == topmost)
break;
}
- i = widget_array.len - 1;
+ i = gtk_widget_stack_get_size (&widget_array) - 1;
for (;;)
{
- widget = gtk_array_index (&widget_array, i);
+ widget = gtk_widget_stack_get (&widget_array, i);
if (!_gtk_widget_is_sensitive (widget))
{
@@ -2050,9 +2054,9 @@ gtk_propagate_event_internal (GtkWidget *widget,
* parents can see the button and motion
* events of the children.
*/
- for (i = 0; i < widget_array.len; i++)
+ for (i = 0; i < gtk_widget_stack_get_size (&widget_array); i++)
{
- widget = gtk_array_index (&widget_array, i);
+ widget = gtk_widget_stack_get (&widget_array, i);
/* Scroll events are special cased here because it
* feels wrong when scrolling a GtkViewport, say,
@@ -2071,7 +2075,7 @@ gtk_propagate_event_internal (GtkWidget *widget,
}
}
- gtk_array_free (&widget_array, g_object_unref);
+ gtk_widget_stack_clear (&widget_array);
return handled_event;
}
diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c
index ef47909750..5c80b694eb 100644
--- a/gtk/gtksnapshot.c
+++ b/gtk/gtksnapshot.c
@@ -34,6 +34,11 @@
#include "gtk/gskpango.h"
+#define GDK_ARRAY_NAME gtk_snapshot_nodes
+#define GDK_ARRAY_TYPE_NAME GtkSnapshotNodes
+#define GDK_ARRAY_ELEMENT_TYPE GskRenderNode *
+#define GDK_ARRAY_FREE_FUNC gsk_render_node_unref
+#include "gdk/gdkarrayimpl.c"
/**
* SECTION:gtksnapshot
@@ -54,6 +59,85 @@
* use gtk_snapshot_new().
*/
+typedef struct _GtkSnapshotState GtkSnapshotState;
+
+typedef GskRenderNode * (* GtkSnapshotCollectFunc) (GtkSnapshot *snapshot,
+ GtkSnapshotState *state,
+ GskRenderNode **nodes,
+ guint n_nodes);
+
+struct _GtkSnapshotState {
+ guint start_node_index;
+ guint n_nodes;
+
+ GskTransform * transform;
+
+ GtkSnapshotCollectFunc collect_func;
+ union {
+ struct {
+ double opacity;
+ } opacity;
+ struct {
+ double radius;
+ } blur;
+ struct {
+ graphene_matrix_t matrix;
+ graphene_vec4_t offset;
+ } color_matrix;
+ struct {
+ graphene_rect_t bounds;
+ graphene_rect_t child_bounds;
+ } repeat;
+ struct {
+ graphene_rect_t bounds;
+ } clip;
+ struct {
+ GskRoundedRect bounds;
+ } rounded_clip;
+ struct {
+ gsize n_shadows;
+ GskShadow *shadows;
+ GskShadow a_shadow; /* Used if n_shadows == 1 */
+ } shadow;
+ struct {
+ GskBlendMode blend_mode;
+ GskRenderNode *bottom_node;
+ } blend;
+ struct {
+ double progress;
+ GskRenderNode *start_node;
+ } cross_fade;
+ struct {
+ char *message;
+ } debug;
+ } data;
+};
+
+static void gtk_snapshot_state_clear (GtkSnapshotState *state);
+
+#define GDK_ARRAY_NAME gtk_snapshot_states
+#define GDK_ARRAY_TYPE_NAME GtkSnapshotStates
+#define GDK_ARRAY_ELEMENT_TYPE GtkSnapshotState
+#define GDK_ARRAY_FREE_FUNC gtk_snapshot_state_clear
+#define GDK_ARRAY_BY_VALUE 1
+#include "gdk/gdkarrayimpl.c"
+
+/* This is a nasty little hack. We typedef GtkSnapshot to the fake object GdkSnapshot
+ * so that we don't need to typecast between them.
+ * After all, the GdkSnapshot only exist so poor language bindings don't trip. Hardcore
+ * C code can just blatantly ignore such layering violations with a typedef.
+ */
+struct _GdkSnapshot {
+ GObject parent_instance; /* it's really GdkSnapshot, but don't tell anyone! */
+
+ GtkSnapshotStates state_stack;
+ GtkSnapshotNodes nodes;
+};
+
+struct _GtkSnapshotClass {
+ GObjectClass parent_class; /* it's really GdkSnapshotClass, but don't tell anyone! */
+};
+
G_DEFINE_TYPE (GtkSnapshot, gtk_snapshot, GDK_TYPE_SNAPSHOT)
static void
@@ -61,11 +145,11 @@ gtk_snapshot_dispose (GObject *object)
{
GtkSnapshot *snapshot = GTK_SNAPSHOT (object);
- if (snapshot->state_stack)
+ if (!gtk_snapshot_states_is_empty (&snapshot->state_stack))
gsk_render_node_unref (gtk_snapshot_to_node (snapshot));
- g_assert (snapshot->state_stack == NULL);
- g_assert (snapshot->nodes == NULL);
+ g_assert (gtk_snapshot_states_is_empty (&snapshot->state_stack));
+ g_assert (gtk_snapshot_nodes_is_empty (&snapshot->nodes));
G_OBJECT_CLASS (gtk_snapshot_parent_class)->dispose (object);
}
@@ -112,15 +196,15 @@ gtk_snapshot_push_state (GtkSnapshot *snapshot,
GskTransform *transform,
GtkSnapshotCollectFunc collect_func)
{
- const gsize n_states = snapshot->state_stack->len;
+ const gsize n_states = gtk_snapshot_states_get_size (&snapshot->state_stack);
GtkSnapshotState *state;
- g_array_set_size (snapshot->state_stack, n_states + 1);
- state = &g_array_index (snapshot->state_stack, GtkSnapshotState, n_states);
+ gtk_snapshot_states_set_size (&snapshot->state_stack, n_states + 1);
+ state = gtk_snapshot_states_get (&snapshot->state_stack, n_states);
state->transform = gsk_transform_ref (transform);
state->collect_func = collect_func;
- state->start_node_index = snapshot->nodes->len;
+ state->start_node_index = gtk_snapshot_nodes_get_size (&snapshot->nodes);
state->n_nodes = 0;
return state;
@@ -129,17 +213,21 @@ gtk_snapshot_push_state (GtkSnapshot *snapshot,
static GtkSnapshotState *
gtk_snapshot_get_current_state (const GtkSnapshot *snapshot)
{
- g_assert (snapshot->state_stack->len > 0);
+ gsize size = gtk_snapshot_states_get_size (&snapshot->state_stack);
- return &g_array_index (snapshot->state_stack, GtkSnapshotState, snapshot->state_stack->len - 1);
+ g_assert (size > 0);
+
+ return gtk_snapshot_states_get (&snapshot->state_stack, size - 1);
}
static GtkSnapshotState *
gtk_snapshot_get_previous_state (const GtkSnapshot *snapshot)
{
- g_assert (snapshot->state_stack->len > 1);
+ gsize size = gtk_snapshot_states_get_size (&snapshot->state_stack);
+
+ g_assert (size > 1);
- return &g_array_index (snapshot->state_stack, GtkSnapshotState, snapshot->state_stack->len - 2);
+ return gtk_snapshot_states_get (&snapshot->state_stack, size - 2);
}
static void
@@ -162,9 +250,8 @@ gtk_snapshot_new (void)
snapshot = g_object_new (GTK_TYPE_SNAPSHOT, NULL);
- snapshot->state_stack = g_array_new (FALSE, TRUE, sizeof (GtkSnapshotState));
- g_array_set_clear_func (snapshot->state_stack, (GDestroyNotify)gtk_snapshot_state_clear);
- snapshot->nodes = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_render_node_unref);
+ gtk_snapshot_states_init (&snapshot->state_stack);
+ gtk_snapshot_nodes_init (&snapshot->nodes);
gtk_snapshot_push_state (snapshot,
NULL,
@@ -1029,30 +1116,28 @@ gtk_snapshot_pop_one (GtkSnapshot *snapshot)
guint state_index;
GskRenderNode *node;
- if (snapshot->state_stack->len == 0)
+ if (gtk_snapshot_states_is_empty (&snapshot->state_stack))
{
g_warning ("Too many gtk_snapshot_pop() calls.");
return NULL;
}
state = gtk_snapshot_get_current_state (snapshot);
- state_index = snapshot->state_stack->len - 1;
+ state_index = gtk_snapshot_states_get_size (&snapshot->state_stack) - 1;
if (state->collect_func)
{
node = state->collect_func (snapshot,
state,
- (GskRenderNode **) snapshot->nodes->pdata + state->start_node_index,
+ (GskRenderNode **) gtk_snapshot_nodes_index (&snapshot->nodes, state->start_node_index),
state->n_nodes);
/* The collect func may not modify the state stack... */
- g_assert (state_index == snapshot->state_stack->len - 1);
+ g_assert (state_index == gtk_snapshot_states_get_size (&snapshot->state_stack) - 1);
/* Remove all the state's nodes from the list of nodes */
- g_assert (state->start_node_index + state->n_nodes == snapshot->nodes->len);
- g_ptr_array_remove_range (snapshot->nodes,
- snapshot->nodes->len - state->n_nodes,
- state->n_nodes);
+ g_assert (state->start_node_index + state->n_nodes == gtk_snapshot_nodes_get_size (&snapshot->nodes));
+ gtk_snapshot_nodes_splice (&snapshot->nodes, state->start_node_index, state->n_nodes, NULL, 0);
}
else
{
@@ -1063,10 +1148,10 @@ gtk_snapshot_pop_one (GtkSnapshot *snapshot)
/* move the nodes to the parent */
previous_state = gtk_snapshot_get_previous_state (snapshot);
previous_state->n_nodes += state->n_nodes;
- g_assert (previous_state->start_node_index + previous_state->n_nodes == snapshot->nodes->len);
+ g_assert (previous_state->start_node_index + previous_state->n_nodes == gtk_snapshot_nodes_get_size (&snapshot->nodes));
}
- g_array_remove_index (snapshot->state_stack, state_index);
+ gtk_snapshot_states_splice (&snapshot->state_stack, state_index, 1, NULL, 0);
return node;
}
@@ -1081,7 +1166,7 @@ gtk_snapshot_append_node_internal (GtkSnapshot *snapshot,
if (current_state)
{
- g_ptr_array_add (snapshot->nodes, node);
+ gtk_snapshot_nodes_append (&snapshot->nodes, node);
current_state->n_nodes ++;
}
else
@@ -1162,16 +1247,14 @@ gtk_snapshot_to_node (GtkSnapshot *snapshot)
result = gtk_snapshot_pop_internal (snapshot);
/* We should have exactly our initial state */
- if (snapshot->state_stack->len > 0)
+ if (!gtk_snapshot_states_is_empty (&snapshot->state_stack))
{
- g_warning ("Too many gtk_snapshot_push() calls. %u states remaining.", snapshot->state_stack->len);
+ g_warning ("Too many gtk_snapshot_push() calls. %zu states remaining.",
+ gtk_snapshot_states_get_size (&snapshot->state_stack));
}
- g_array_free (snapshot->state_stack, TRUE);
- g_ptr_array_free (snapshot->nodes, TRUE);
-
- snapshot->state_stack = NULL;
- snapshot->nodes = NULL;
+ gtk_snapshot_states_clear (&snapshot->state_stack);
+ gtk_snapshot_nodes_clear (&snapshot->nodes);
return result;
}
diff --git a/gtk/gtksnapshotprivate.h b/gtk/gtksnapshotprivate.h
index aebf5c3840..99714c5a99 100644
--- a/gtk/gtksnapshotprivate.h
+++ b/gtk/gtksnapshotprivate.h
@@ -24,76 +24,6 @@
G_BEGIN_DECLS
-typedef struct _GtkSnapshotState GtkSnapshotState;
-
-typedef GskRenderNode * (* GtkSnapshotCollectFunc) (GtkSnapshot *snapshot,
- GtkSnapshotState *state,
- GskRenderNode **nodes,
- guint n_nodes);
-
-struct _GtkSnapshotState {
- guint start_node_index;
- guint n_nodes;
-
- GskTransform * transform;
-
- GtkSnapshotCollectFunc collect_func;
- union {
- struct {
- double opacity;
- } opacity;
- struct {
- double radius;
- } blur;
- struct {
- graphene_matrix_t matrix;
- graphene_vec4_t offset;
- } color_matrix;
- struct {
- graphene_rect_t bounds;
- graphene_rect_t child_bounds;
- } repeat;
- struct {
- graphene_rect_t bounds;
- } clip;
- struct {
- GskRoundedRect bounds;
- } rounded_clip;
- struct {
- gsize n_shadows;
- GskShadow *shadows;
- GskShadow a_shadow; /* Used if n_shadows == 1 */
- } shadow;
- struct {
- GskBlendMode blend_mode;
- GskRenderNode *bottom_node;
- } blend;
- struct {
- double progress;
- GskRenderNode *start_node;
- } cross_fade;
- struct {
- char *message;
- } debug;
- } data;
-};
-
-/* This is a nasty little hack. We typedef GtkSnapshot to the fake object GdkSnapshot
- * so that we don't need to typecast between them.
- * After all, the GdkSnapshot only exist so poor language bindings don't trip. Hardcore
- * C code can just blatantly ignore such layering violations with a typedef.
- */
-struct _GdkSnapshot {
- GObject parent_instance; /* it's really GdkSnapshot, but don't tell anyone! */
-
- GArray *state_stack;
- GPtrArray *nodes;
-};
-
-struct _GtkSnapshotClass {
- GObjectClass parent_class; /* it's really GdkSnapshotClass, but don't tell anyone! */
-};
-
void gtk_snapshot_append_text (GtkSnapshot *snapshot,
PangoFont *font,
PangoGlyphString *glyphs,
diff --git a/gtk/gtkstringlist.c b/gtk/gtkstringlist.c
index a88c719e1d..b92c2ab9b2 100644
--- a/gtk/gtkstringlist.c
+++ b/gtk/gtkstringlist.c
@@ -57,6 +57,12 @@
*/
+#define GDK_ARRAY_ELEMENT_TYPE GtkStringObject *
+#define GDK_ARRAY_NAME objects
+#define GDK_ARRAY_TYPE_NAME Objects
+#define GDK_ARRAY_FREE_FUNC g_object_unref
+#include "gdk/gdkarrayimpl.c"
+
struct _GtkStringObject
{
GObject parent_instance;
@@ -190,7 +196,7 @@ struct _GtkStringList
{
GObject parent_instance;
- GSequence *items;
+ Objects items;
};
struct _GtkStringListClass
@@ -209,7 +215,7 @@ gtk_string_list_get_n_items (GListModel *list)
{
GtkStringList *self = GTK_STRING_LIST (list);
- return g_sequence_get_length (self->items);
+ return objects_get_size (&self->items);
}
static gpointer
@@ -217,14 +223,11 @@ gtk_string_list_get_item (GListModel *list,
guint position)
{
GtkStringList *self = GTK_STRING_LIST (list);
- GSequenceIter *iter;
-
- iter = g_sequence_get_iter_at_pos (self->items, position);
- if (g_sequence_iter_is_end (iter))
+ if (position >= objects_get_size (&self->items))
return NULL;
- else
- return g_object_ref (g_sequence_get (iter));
+
+ return g_object_ref (objects_get (&self->items, position));
}
static void
@@ -331,7 +334,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));
+ gtk_string_list_append (data->list, data->string->str);
}
data->translatable = FALSE;
@@ -411,7 +414,7 @@ gtk_string_list_dispose (GObject *object)
{
GtkStringList *self = GTK_STRING_LIST (object);
- g_clear_pointer (&self->items, g_sequence_free);
+ objects_clear (&self->items);
G_OBJECT_CLASS (gtk_string_list_parent_class)->dispose (object);
}
@@ -427,7 +430,7 @@ gtk_string_list_class_init (GtkStringListClass *class)
static void
gtk_string_list_init (GtkStringList *self)
{
- self->items = g_sequence_new (g_object_unref);
+ objects_init (&self->items);
}
/**
@@ -476,39 +479,26 @@ gtk_string_list_splice (GtkStringList *self,
guint n_removals,
const char * const *additions)
{
- GSequenceIter *it;
- guint add, n_items;
+ guint i, n_additions;
g_return_if_fail (GTK_IS_STRING_LIST (self));
g_return_if_fail (position + n_removals >= position); /* overflow */
+ g_return_if_fail (position + n_removals <= objects_get_size (&self->items));
- n_items = g_sequence_get_length (self->items);
- 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);
+ if (additions)
+ n_additions = g_strv_length ((char **) additions);
+ else
+ n_additions = 0;
- it = end;
- }
+ objects_splice (&self->items, position, n_removals, NULL, n_additions);
- if (additions)
+ for (i = 0; i < n_additions; i++)
{
- for (add = 0; additions[add]; add++)
- {
- g_sequence_insert_before (it, gtk_string_object_new (additions[add]));
- }
+ *objects_index (&self->items, position + i) = gtk_string_object_new (additions[i]);
}
- else
- add = 0;
- if (n_removals || add)
- g_list_model_items_changed (G_LIST_MODEL (self), position, n_removals, add);
+ if (n_removals || n_additions)
+ g_list_model_items_changed (G_LIST_MODEL (self), position, n_removals, n_additions);
}
/**
@@ -525,14 +515,11 @@ void
gtk_string_list_append (GtkStringList *self,
const char *string)
{
- guint n_items;
-
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));
+ objects_append (&self->items, gtk_string_object_new (string));
- g_list_model_items_changed (G_LIST_MODEL (self), n_items, 0, 1);
+ g_list_model_items_changed (G_LIST_MODEL (self), objects_get_size (&self->items) - 1, 0, 1);
}
/**
@@ -554,14 +541,11 @@ void
gtk_string_list_take (GtkStringList *self,
char *string)
{
- guint n_items;
-
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));
+ objects_append (&self->items, gtk_string_object_new_take (string));
- g_list_model_items_changed (G_LIST_MODEL (self), n_items, 0, 1);
+ g_list_model_items_changed (G_LIST_MODEL (self), objects_get_size (&self->items) - 1, 0, 1);
}
/**
@@ -576,16 +560,9 @@ 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));
-
- g_sequence_remove (iter);
-
- g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 0);
+ gtk_string_list_splice (self, position, 1, NULL);
}
/**
@@ -605,20 +582,10 @@ const char *
gtk_string_list_get_string (GtkStringList *self,
guint position)
{
- GSequenceIter *iter;
-
g_return_val_if_fail (GTK_IS_STRING_LIST (self), NULL);
- iter = g_sequence_get_iter_at_pos (self->items, position);
-
- if (g_sequence_iter_is_end (iter))
- {
- return NULL;
- }
- else
- {
- GtkStringObject *obj = g_sequence_get (iter);
+ if (position >= objects_get_size (&self->items))
+ return NULL;
- return obj->string;
- }
+ return objects_get (&self->items, position)->string;
}
diff --git a/testsuite/gdk/array.c b/testsuite/gdk/array.c
new file mode 100644
index 0000000000..f9d5677b2c
--- /dev/null
+++ b/testsuite/gdk/array.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright © 2020 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#include <locale.h>
+
+#include <gtk/gtk.h>
+
+static void
+int_free_func (int data)
+{
+}
+
+#define GDK_ARRAY_ELEMENT_TYPE int
+#define GDK_ARRAY_NAME int_array
+#define GDK_ARRAY_TYPE_NAME IntVector
+#include "arrayimpl.c"
+
+#define GDK_ARRAY_ELEMENT_TYPE int
+#define GDK_ARRAY_NAME pre_int_array
+#define GDK_ARRAY_TYPE_NAME PreIntVector
+#define GDK_ARRAY_PREALLOC 100
+#include "arrayimpl.c"
+
+#define GDK_ARRAY_ELEMENT_TYPE int
+#define GDK_ARRAY_NAME free_int_array
+#define GDK_ARRAY_TYPE_NAME FreeIntVector
+#define GDK_ARRAY_FREE_FUNC int_free_func
+#include "arrayimpl.c"
+
+#define GDK_ARRAY_ELEMENT_TYPE int
+#define GDK_ARRAY_NAME pre_free_int_array
+#define GDK_ARRAY_TYPE_NAME PreFreeIntVector
+#define GDK_ARRAY_PREALLOC 100
+#define GDK_ARRAY_FREE_FUNC int_free_func
+#include "arrayimpl.c"
+
+#define GDK_ARRAY_ELEMENT_TYPE int
+#define GDK_ARRAY_NAME null_int_array
+#define GDK_ARRAY_TYPE_NAME NullIntVector
+#define GDK_ARRAY_NULL_TERMINATED 1
+#include "arrayimpl.c"
+
+#define GDK_ARRAY_ELEMENT_TYPE int
+#define GDK_ARRAY_NAME null_pre_int_array
+#define GDK_ARRAY_TYPE_NAME NullPreIntVector
+#define GDK_ARRAY_PREALLOC 100
+#define GDK_ARRAY_NULL_TERMINATED 1
+#include "arrayimpl.c"
+
+#define GDK_ARRAY_ELEMENT_TYPE int
+#define GDK_ARRAY_NAME null_free_int_array
+#define GDK_ARRAY_TYPE_NAME NullFreeIntVector
+#define GDK_ARRAY_FREE_FUNC int_free_func
+#define GDK_ARRAY_NULL_TERMINATED 1
+#include "arrayimpl.c"
+
+#define GDK_ARRAY_ELEMENT_TYPE int
+#define GDK_ARRAY_NAME null_pre_free_int_array
+#define GDK_ARRAY_TYPE_NAME NullPreFreeIntVector
+#define GDK_ARRAY_PREALLOC 100
+#define GDK_ARRAY_FREE_FUNC int_free_func
+#define GDK_ARRAY_NULL_TERMINATED 1
+#include "arrayimpl.c"
+
+int
+main (int argc, char *argv[])
+{
+ g_test_init (&argc, &argv, NULL);
+ setlocale (LC_ALL, "C");
+
+ g_test_add_func ("/intarray/simple", int_array_test_simple);
+ g_test_add_func ("/intarray/prealloc/simple", pre_int_array_test_simple);
+ g_test_add_func ("/intarray/freefunc/simple", free_int_array_test_simple);
+ g_test_add_func ("/intarray/prealloc/freefunc/simple", pre_free_int_array_test_simple);
+ g_test_add_func ("/intarray/null/simple", null_int_array_test_simple);
+ g_test_add_func ("/intarray/null/prealloc/simple", null_pre_int_array_test_simple);
+ g_test_add_func ("/intarray/null/freefunc/simple", null_free_int_array_test_simple);
+ g_test_add_func ("/intarray/null/prealloc/freefunc/simple", null_pre_free_int_array_test_simple);
+ g_test_add_func ("/intarray/splice", int_array_test_splice);
+ g_test_add_func ("/intarray/prealloc/splice", pre_int_array_test_splice);
+ g_test_add_func ("/intarray/freefunc/splice", free_int_array_test_splice);
+ g_test_add_func ("/intarray/prealloc/freefunc/splice", pre_free_int_array_test_splice);
+ g_test_add_func ("/intarray/null/splice", null_int_array_test_splice);
+ g_test_add_func ("/intarray/null/prealloc/splice", null_pre_int_array_test_splice);
+ g_test_add_func ("/intarray/null/freefunc/splice", null_free_int_array_test_splice);
+ g_test_add_func ("/intarray/null/prealloc/freefunc/splice", null_pre_free_int_array_test_splice);
+
+ return g_test_run ();
+}
diff --git a/testsuite/gdk/arrayimpl.c b/testsuite/gdk/arrayimpl.c
new file mode 100644
index 0000000000..286f64d678
--- /dev/null
+++ b/testsuite/gdk/arrayimpl.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2020 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#include <gtk/gtk.h>
+
+#define GDK_ARRAY_NO_UNDEF
+
+#include "../../gdk/gdkarrayimpl.c"
+
+static void
+gdk_array(test_simple) (void)
+{
+ GdkArray v;
+ gsize i;
+
+ gdk_array(init) (&v);
+
+ for (i = 0; i < 1000; i++)
+ {
+ g_assert_cmpint (gdk_array(get_size) (&v), ==, i);
+ g_assert_cmpint (gdk_array(get_size) (&v), <=, gdk_array(get_capacity) (&v));
+ gdk_array(append) (&v, i);
+#ifdef GDK_ARRAY_NULL_TERMINATED
+ g_assert_cmpint (*gdk_array(index) (&v, gdk_array(get_size) (&v)), ==, 0);
+#endif
+ }
+ g_assert_cmpint (gdk_array(get_size) (&v), ==, i);
+ g_assert_cmpint (gdk_array(get_size) (&v), <=, gdk_array(get_capacity) (&v));
+
+ for (i = 0; i < 1000; i++)
+ {
+ g_assert_cmpint (gdk_array(get) (&v, i), ==, i);
+ }
+
+ gdk_array(clear) (&v);
+}
+
+static void
+gdk_array(test_splice) (void)
+{
+ GdkArray v;
+ gsize i, j, sum;
+ gsize pos, add, remove;
+ int additions[4] = { 0, 1, 2, 3 };
+
+ gdk_array(init) (&v);
+ sum = 0;
+
+ for (i = 0; i < 1000; i++)
+ {
+ gsize old_size = gdk_array(get_size) (&v);
+
+ pos = g_random_int_range (0, old_size + 1);
+ g_assert (pos <= old_size);
+ remove = g_random_int_range (0, 4);
+ remove = MIN (remove, old_size - pos);
+ add = g_random_int_range (0, 4);
+
+ for (j = 0; j < remove; j++)
+ sum -= gdk_array(get) (&v, pos + j);
+ for (j = 0; j < add; j++)
+ sum += ++additions[j];
+
+ gdk_array(splice) (&v, pos, remove, additions, add);
+ {
+ gsize total = 0;
+ for (j = 0; j < gdk_array(get_size) (&v); j++)
+ total += gdk_array(get) (&v, j);
+ g_assert_cmpint (total, ==, sum);
+ }
+
+ g_assert_cmpint (gdk_array(get_size) (&v), ==, old_size + add - remove);
+ g_assert_cmpint (gdk_array(get_size) (&v), <=, gdk_array(get_capacity) (&v));
+#ifdef GDK_ARRAY_NULL_TERMINATED
+ if (gdk_array(get_size) (&v))
+ g_assert_cmpint (*gdk_array(index) (&v, gdk_array(get_size) (&v)), ==, 0);
+#endif
+ for (j = 0; j < add; j++)
+ g_assert_cmpint (gdk_array(get) (&v, pos + j), ==, additions[j]);
+ }
+
+ for (i = 0; i < gdk_array(get_size) (&v); i++)
+ {
+ sum -= gdk_array(get) (&v, i);
+ }
+ g_assert_cmpint (sum, ==, 0);
+}
+
+#undef _T_
+#undef GdkArray
+#undef gdk_array_paste_more
+#undef gdk_array_paste
+#undef gdk_array
+#undef GDK_ARRAY_REAL_SIZE
+
+#undef GDK_ARRAY_ELEMENT_TYPE
+#undef GDK_ARRAY_NAME
+#undef GDK_ARRAY_TYPE_NAME
+#undef GDK_ARRAY_PREALLOC
+#undef GDK_ARRAY_NULL_TERMINATED
+
diff --git a/testsuite/gdk/meson.build b/testsuite/gdk/meson.build
index 003e77172b..bd7744ee0e 100644
--- a/testsuite/gdk/meson.build
+++ b/testsuite/gdk/meson.build
@@ -2,6 +2,7 @@ testexecdir = join_paths(installed_test_bindir, 'gdk')
testdatadir = join_paths(installed_test_datadir, 'gdk')
tests = [
+ 'array',
'cairo',
'clipboard',
'display',