From 21a4fd1a5f8d21dff606b4c9d0fc7b1aa37223a5 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 13 Feb 2020 18:47:08 -0500 Subject: [PATCH] Make GtkCssLookupValue refcounted --- gtk/gtkcsslookup.c | 58 ++++++++++++++++++++++++++----- gtk/gtkcsslookupprivate.h | 10 +++++- gtk/gtkcssprovider.c | 72 +++++++++++++-------------------------- 3 files changed, 83 insertions(+), 57 deletions(-) diff --git a/gtk/gtkcsslookup.c b/gtk/gtkcsslookup.c index 65d8e6d844..e7ae35c52c 100644 --- a/gtk/gtkcsslookup.c +++ b/gtk/gtkcsslookup.c @@ -24,6 +24,47 @@ #include "gtkprivatetypebuiltins.h" #include "gtkprivate.h" +GtkCssLookupValue * +gtk_css_lookup_value_new (guint id, + GtkCssValue *value, + GtkCssSection *section) +{ + GtkCssLookupValue *v; + + v = g_new0 (GtkCssLookupValue, 1); + v->ref_count = 1; + + v->id = id; + v->value = _gtk_css_value_ref (value); + if (section) + v->section = gtk_css_section_ref (section); + + return v; +} + +static void +gtk_css_lookup_value_free (GtkCssLookupValue *value) +{ + _gtk_css_value_unref (value->value); + if (value->section) + gtk_css_section_unref (value->section); + g_free (value); +} + +GtkCssLookupValue * +gtk_css_lookup_value_ref (GtkCssLookupValue *value) +{ + value->ref_count++; + return value; +} + +void +gtk_css_lookup_value_unref (GtkCssLookupValue *value) +{ + value->ref_count--; + if (value->ref_count == 0) + gtk_css_lookup_value_free (value); +} GtkCssLookup * gtk_css_lookup_new (void) @@ -78,9 +119,9 @@ gtk_css_lookup_unref (GtkCssLookup *lookup) * @lookup does not have a value yet. */ void -gtk_css_lookup_fill (GtkCssLookup *lookup, - GtkCssLookupValue *values, - guint n_values) +gtk_css_lookup_fill (GtkCssLookup *lookup, + GtkCssLookupValue **values, + guint n_values) { int i, j; @@ -88,7 +129,8 @@ gtk_css_lookup_fill (GtkCssLookup *lookup, gtk_internal_return_if_fail (values != NULL); if (!lookup->values) - lookup->values = g_ptr_array_sized_new (MAX (16, n_values)); + lookup->values = g_ptr_array_new_full (MAX (16, n_values), + (GDestroyNotify)gtk_css_lookup_value_unref); for (i = 0, j = 0; j < n_values; j++, i++) { @@ -97,14 +139,14 @@ gtk_css_lookup_fill (GtkCssLookup *lookup, for (; i < lookup->values->len; i++) { v = g_ptr_array_index (lookup->values, i); - if (v->id >= values[j].id) + if (v->id >= values[j]->id) break; } - if (i == lookup->values->len || v->id > values[j].id) + if (i == lookup->values->len || v->id > values[j]->id) { - g_ptr_array_insert (lookup->values, i, &values[j]); - lookup->set_values = _gtk_bitmask_set (lookup->set_values, values[j].id, TRUE); + g_ptr_array_insert (lookup->values, i, gtk_css_lookup_value_ref (values[j])); + lookup->set_values = _gtk_bitmask_set (lookup->set_values, values[j]->id, TRUE); } } } diff --git a/gtk/gtkcsslookupprivate.h b/gtk/gtkcsslookupprivate.h index b7113076a4..2b585e3a90 100644 --- a/gtk/gtkcsslookupprivate.h +++ b/gtk/gtkcsslookupprivate.h @@ -31,11 +31,19 @@ G_BEGIN_DECLS typedef struct _GtkCssLookup GtkCssLookup; typedef struct { + int ref_count; guint id; GtkCssValue *value; GtkCssSection *section; } GtkCssLookupValue; +GtkCssLookupValue * gtk_css_lookup_value_new (guint id, + GtkCssValue *value, + GtkCssSection *section); +GtkCssLookupValue * gtk_css_lookup_value_ref (GtkCssLookupValue *value); +void gtk_css_lookup_value_unref (GtkCssLookupValue *value); + + struct _GtkCssLookup { int ref_count; GtkBitmask *set_values; @@ -47,7 +55,7 @@ GtkCssLookup * gtk_css_lookup_ref (GtkCssLookup *lookup); void gtk_css_lookup_unref (GtkCssLookup *lookup); void gtk_css_lookup_fill (GtkCssLookup *lookup, - GtkCssLookupValue *values, + GtkCssLookupValue **values, guint n_values); GtkCssSection * gtk_css_lookup_get_section (GtkCssLookup *lookup, guint id); diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c index ac8ffcabe4..474adcd8cd 100644 --- a/gtk/gtkcssprovider.c +++ b/gtk/gtkcssprovider.c @@ -86,7 +86,6 @@ struct _GtkCssProviderClass typedef struct GtkCssRuleset GtkCssRuleset; typedef struct _GtkCssScanner GtkCssScanner; -typedef GtkCssLookupValue PropertyValue; typedef enum ParserScope ParserScope; typedef enum ParserSymbol ParserSymbol; @@ -95,9 +94,8 @@ struct GtkCssRuleset { GtkCssSelector *selector; GtkCssSelectorTree *selector_match; - PropertyValue *styles; + GtkCssLookupValue **styles; guint n_styles; - guint owns_styles : 1; }; struct _GtkCssScanner @@ -226,30 +224,23 @@ gtk_css_ruleset_init_copy (GtkCssRuleset *new, GtkCssRuleset *ruleset, GtkCssSelector *selector) { + int i; + memcpy (new, ruleset, sizeof (GtkCssRuleset)); new->selector = selector; - /* First copy takes over ownership */ - if (ruleset->owns_styles) - ruleset->owns_styles = FALSE; + for (i = 0; i < new->n_styles; i++) + gtk_css_lookup_value_ref (new->styles[i]); } static void gtk_css_ruleset_clear (GtkCssRuleset *ruleset) { - if (ruleset->owns_styles) - { - guint i; + int i; + + for (i = 0; i < ruleset->n_styles; i++) + gtk_css_lookup_value_unref (ruleset->styles[i]); - for (i = 0; i < ruleset->n_styles; i++) - { - _gtk_css_value_unref (ruleset->styles[i].value); - ruleset->styles[i].value = NULL; - if (ruleset->styles[i].section) - gtk_css_section_unref (ruleset->styles[i].section); - } - g_free (ruleset->styles); - } if (ruleset->selector) _gtk_css_selector_free (ruleset->selector); @@ -265,43 +256,28 @@ gtk_css_ruleset_add (GtkCssRuleset *ruleset, guint i; guint id; - g_return_if_fail (ruleset->owns_styles || ruleset->n_styles == 0); - - ruleset->owns_styles = TRUE; - id = _gtk_css_style_property_get_id (property); for (i = 0; i < ruleset->n_styles; i++) { - if (ruleset->styles[i].id > id) + if (ruleset->styles[i]->id > id) break; - if (ruleset->styles[i].id == id) + if (ruleset->styles[i]->id == id) { - _gtk_css_value_unref (ruleset->styles[i].value); - ruleset->styles[i].value = NULL; - if (ruleset->styles[i].section) - gtk_css_section_unref (ruleset->styles[i].section); - break; + gtk_css_lookup_value_unref (ruleset->styles[i]); + ruleset->styles[i] = gtk_css_lookup_value_new (id, value, section); + return; } } - if (i == ruleset->n_styles || ruleset->styles[i].id != id) - { - ruleset->styles = g_realloc (ruleset->styles, (ruleset->n_styles + 1) * sizeof (PropertyValue)); - if (i < ruleset->n_styles) - memmove (&ruleset->styles[i + 1], &ruleset->styles[i], (ruleset->n_styles - i) * sizeof (PropertyValue)); + ruleset->styles = g_realloc (ruleset->styles, (ruleset->n_styles + 1) * sizeof (GtkCssLookupValue *)); - ruleset->n_styles++; + if (i < ruleset->n_styles) + memmove (&ruleset->styles[i + 1], &ruleset->styles[i], (ruleset->n_styles - i) * sizeof (GtkCssLookupValue *)); - ruleset->styles[i].value = NULL; - ruleset->styles[i].id = id; - } + ruleset->n_styles++; - ruleset->styles[i].value = value; - if (gtk_keep_css_sections) - ruleset->styles[i].section = gtk_css_section_ref (section); - else - ruleset->styles[i].section = NULL; + ruleset->styles[i] = gtk_css_lookup_value_new (id, value, section); } static void @@ -483,7 +459,7 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider, if (ruleset->styles == NULL) continue; - gtk_css_lookup_fill (lookup, (GtkCssLookupValue *)ruleset->styles, ruleset->n_styles); + gtk_css_lookup_fill (lookup, ruleset->styles, ruleset->n_styles); } gtk_array_free (&tree_rules_array, NULL); @@ -1390,10 +1366,10 @@ compare_properties (gconstpointer a, gconstpointer b, gpointer style) { const guint *ua = a; const guint *ub = b; - PropertyValue *styles = style; + GtkCssLookupValue **styles = style; - return strcmp (_gtk_style_property_get_name (GTK_STYLE_PROPERTY (_gtk_css_style_property_lookup_by_id (styles[*ua].id))), - _gtk_style_property_get_name (GTK_STYLE_PROPERTY (_gtk_css_style_property_lookup_by_id (styles[*ub].id)))); + return strcmp (_gtk_style_property_get_name (GTK_STYLE_PROPERTY (_gtk_css_style_property_lookup_by_id (styles[*ua]->id))), + _gtk_style_property_get_name (GTK_STYLE_PROPERTY (_gtk_css_style_property_lookup_by_id (styles[*ub]->id)))); } static void @@ -1418,7 +1394,7 @@ gtk_css_ruleset_print (const GtkCssRuleset *ruleset, for (i = 0; i < ruleset->n_styles; i++) { - PropertyValue *prop = &ruleset->styles[sorted[i]]; + GtkCssLookupValue *prop = ruleset->styles[sorted[i]]; g_string_append (str, " "); g_string_append (str, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (_gtk_css_style_property_lookup_by_id (prop->id)))); g_string_append (str, ": ");