summaryrefslogtreecommitdiff
path: root/gtk/gtkcssselector.c
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2012-12-10 12:57:10 +0100
committerAlexander Larsson <alexl@redhat.com>2012-12-10 12:57:10 +0100
commita1ee2b7b82154a506f6dee546975ed97a5fc9e2a (patch)
tree90a3962d58e8474e092be859d86166c974e68c2c /gtk/gtkcssselector.c
parent089eafb468ac1a49dfd839421346d1ad9b9c3263 (diff)
downloadgtk+-a1ee2b7b82154a506f6dee546975ed97a5fc9e2a.tar.gz
css: Speed up name matching
We use the new g_type_get_type_registration_serial() so that we can cache and properly invalidate the result of g_type_from_name(). This bumps the glib requirement to 2.35.3 to get the new function. https://bugzilla.gnome.org/show_bug.cgi?id=689847
Diffstat (limited to 'gtk/gtkcssselector.c')
-rw-r--r--gtk/gtkcssselector.c86
1 files changed, 76 insertions, 10 deletions
diff --git a/gtk/gtkcssselector.c b/gtk/gtkcssselector.c
index 718131be03..fcf0ac6cdf 100644
--- a/gtk/gtkcssselector.c
+++ b/gtk/gtkcssselector.c
@@ -682,18 +682,74 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_ANY = {
/* NAME */
+typedef struct {
+ GType type;
+ const char *name;
+} TypeReference;
+
+static GHashTable *type_refs_ht = NULL;
+static guint type_refs_last_serial = 0;
+
+static TypeReference *
+get_type_reference (const char *name)
+{
+ TypeReference *ref;
+
+
+ if (type_refs_ht == NULL)
+ type_refs_ht = g_hash_table_new (g_str_hash, g_str_equal);
+
+ ref = g_hash_table_lookup (type_refs_ht, name);
+
+ if (ref != NULL)
+ return ref;
+
+ ref = g_slice_new (TypeReference);
+ ref->name = g_intern_string (name);
+ ref->type = g_type_from_name (ref->name);
+
+ g_hash_table_insert (type_refs_ht,
+ (gpointer)ref->name, ref);
+
+ return ref;
+}
+
+static void
+update_type_references (void)
+{
+ GHashTableIter iter;
+ guint serial;
+ gpointer value;
+
+ serial = g_type_get_type_registration_serial ();
+
+ if (serial == type_refs_last_serial)
+ return;
+
+ type_refs_last_serial = serial;
+
+ g_hash_table_iter_init (&iter, type_refs_ht);
+ while (g_hash_table_iter_next (&iter,
+ NULL, &value))
+ {
+ TypeReference *ref = value;
+ if (ref->type == G_TYPE_INVALID)
+ ref->type = g_type_from_name (ref->name);
+ }
+}
+
static void
gtk_css_selector_name_print (const GtkCssSelector *selector,
GString *string)
{
- g_string_append (string, selector->data);
+ g_string_append (string, ((TypeReference *)selector->data)->name);
}
static gboolean
gtk_css_selector_name_match (const GtkCssSelector *selector,
const GtkCssMatcher *matcher)
{
- if (!_gtk_css_matcher_has_name (matcher, selector->data))
+ if (!_gtk_css_matcher_has_type (matcher, ((TypeReference *)selector->data)->type))
return FALSE;
return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher);
@@ -704,7 +760,7 @@ gtk_css_selector_name_tree_match (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher,
GHashTable *res)
{
- if (!_gtk_css_matcher_has_name (matcher, tree->selector.data))
+ if (!_gtk_css_matcher_has_type (matcher, ((TypeReference *)tree->selector.data)->type))
return;
gtk_css_selector_tree_found_match (tree, res);
@@ -718,7 +774,7 @@ gtk_css_selector_name_tree_get_change (const GtkCssSelectorTree *tree,
{
GtkCssChange change, previous_change;
- if (!_gtk_css_matcher_has_name (matcher, tree->selector.data))
+ if (!_gtk_css_matcher_has_type (matcher, ((TypeReference *)tree->selector.data)->type))
return 0;
change = 0;
@@ -745,7 +801,8 @@ static int
gtk_css_selector_name_compare_one (const GtkCssSelector *a,
const GtkCssSelector *b)
{
- return strcmp (a->data, b->data);
+ return strcmp (((TypeReference *)a->data)->name,
+ ((TypeReference *)b->data)->name);
}
static const GtkCssSelectorClass GTK_CSS_SELECTOR_NAME = {
@@ -1805,11 +1862,14 @@ try_parse_name (GtkCssParser *parser,
name = _gtk_css_parser_try_ident (parser, FALSE);
if (name)
{
- selector = gtk_css_selector_new (_gtk_style_context_check_region_name (name)
- ? &GTK_CSS_SELECTOR_REGION
- : &GTK_CSS_SELECTOR_NAME,
- selector,
- g_intern_string (name));
+ if (_gtk_style_context_check_region_name (name))
+ selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_REGION,
+ selector,
+ g_intern_string (name));
+ else
+ selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_NAME,
+ selector,
+ get_type_reference (name));
g_free (name);
}
else if (_gtk_css_parser_try (parser, "*", FALSE))
@@ -1916,6 +1976,8 @@ _gtk_css_selector_tree_match_get_change (const GtkCssSelectorTree *tree)
{
GtkCssChange change = 0;
+ update_type_references ();
+
while (tree)
{
change = tree->selector.class->get_change (&tree->selector, change);
@@ -1947,6 +2009,8 @@ _gtk_css_selector_matches (const GtkCssSelector *selector,
g_return_val_if_fail (selector != NULL, FALSE);
g_return_val_if_fail (matcher != NULL, FALSE);
+ update_type_references ();
+
return gtk_css_selector_match (selector, matcher);
}
@@ -2085,6 +2149,8 @@ _gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
GHashTableIter iter;
gpointer key;
+ update_type_references ();
+
res = g_hash_table_new (g_direct_hash, g_direct_equal);
for (; tree != NULL;