diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-07-16 18:05:43 +0000 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-07-16 18:05:43 +0000 |
commit | 6b89148487463ffb05779a82287a4304e8622413 (patch) | |
tree | f79d11f6ca5ea8ae2236feef55b41266b354b91c | |
parent | ddb9e428ece38dc48bd965d661c629df41d92282 (diff) | |
parent | 60a09e59e86152e1064f9e345e0ed8bbf5b063e0 (diff) | |
download | gtk+-6b89148487463ffb05779a82287a4304e8622413.tar.gz |
Merge branch 'wip/otte/vector' into 'master'
Arrays
See merge request GNOME/gtk!2197
-rw-r--r-- | gdk/gdkarrayimpl.c | 283 | ||||
-rw-r--r-- | gtk/gtkarrayimplprivate.h | 137 | ||||
-rw-r--r-- | gtk/gtkcssprovider.c | 28 | ||||
-rw-r--r-- | gtk/gtkcssselector.c | 37 | ||||
-rw-r--r-- | gtk/gtkcssselectorprivate.h | 11 | ||||
-rw-r--r-- | gtk/gtkicontheme.c | 55 | ||||
-rw-r--r-- | gtk/gtkmain.c | 44 | ||||
-rw-r--r-- | gtk/gtksnapshot.c | 147 | ||||
-rw-r--r-- | gtk/gtksnapshotprivate.h | 70 | ||||
-rw-r--r-- | gtk/gtkstringlist.c | 99 | ||||
-rw-r--r-- | testsuite/gdk/array.c | 105 | ||||
-rw-r--r-- | testsuite/gdk/arrayimpl.c | 117 | ||||
-rw-r--r-- | testsuite/gdk/meson.build | 1 |
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', |