[gtk+] css: Move selector parsing code into a custom function



commit 67d0b8195d3659e1080b52457826c105b8200939
Author: Benjamin Otte <otte redhat com>
Date:   Wed Feb 15 15:42:00 2012 +0100

    css: Move selector parsing code into a custom function

 gtk/gtkcssprovider.c        |  279 +------------------------------------------
 gtk/gtkcssselector.c        |  269 ++++++++++++++++++++++++++++++++++++++++--
 gtk/gtkcssselectorprivate.h |   14 +--
 3 files changed, 264 insertions(+), 298 deletions(-)
---
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index 4811c01..2da4073 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -2075,283 +2075,6 @@ parse_at_keyword (GtkCssScanner *scanner)
     }
 }
 
-static gboolean
-parse_selector_class (GtkCssScanner *scanner, GArray *classes)
-{
-  GQuark qname;
-  char *name;
-    
-  name = _gtk_css_parser_try_name (scanner->parser, FALSE);
-
-  if (name == NULL)
-    {
-      gtk_css_provider_error_literal (scanner->provider,
-                                      scanner,
-                                      GTK_CSS_PROVIDER_ERROR,
-                                      GTK_CSS_PROVIDER_ERROR_SYNTAX,
-                                      "Expected a valid name for class");
-      return FALSE;
-    }
-
-  qname = g_quark_from_string (name);
-  g_array_append_val (classes, qname);
-  g_free (name);
-  return TRUE;
-}
-
-static gboolean
-parse_selector_name (GtkCssScanner *scanner, GArray *names)
-{
-  GQuark qname;
-  char *name;
-    
-  name = _gtk_css_parser_try_name (scanner->parser, FALSE);
-
-  if (name == NULL)
-    {
-      gtk_css_provider_error_literal (scanner->provider,
-                                      scanner,
-                                      GTK_CSS_PROVIDER_ERROR,
-                                      GTK_CSS_PROVIDER_ERROR_SYNTAX,
-                                      "Expected a valid name for id");
-      return FALSE;
-    }
-
-  qname = g_quark_from_string (name);
-  g_array_append_val (names, qname);
-  g_free (name);
-  return TRUE;
-}
-
-static gboolean
-parse_selector_pseudo_class (GtkCssScanner  *scanner,
-                             GtkRegionFlags *region_to_modify,
-                             GtkStateFlags  *state_to_modify)
-{
-  struct {
-    const char *name;
-    GtkRegionFlags region_flag;
-    GtkStateFlags state_flag;
-  } pseudo_classes[] = {
-    { "first-child",  GTK_REGION_FIRST, 0 },
-    { "last-child",   GTK_REGION_LAST, 0 },
-    { "only-child",   GTK_REGION_ONLY, 0 },
-    { "sorted",       GTK_REGION_SORTED, 0 },
-    { "active",       0, GTK_STATE_FLAG_ACTIVE },
-    { "prelight",     0, GTK_STATE_FLAG_PRELIGHT },
-    { "hover",        0, GTK_STATE_FLAG_PRELIGHT },
-    { "selected",     0, GTK_STATE_FLAG_SELECTED },
-    { "insensitive",  0, GTK_STATE_FLAG_INSENSITIVE },
-    { "inconsistent", 0, GTK_STATE_FLAG_INCONSISTENT },
-    { "focused",      0, GTK_STATE_FLAG_FOCUSED },
-    { "focus",        0, GTK_STATE_FLAG_FOCUSED },
-    { "backdrop",     0, GTK_STATE_FLAG_BACKDROP },
-    { NULL, }
-  }, nth_child_classes[] = {
-    { "first",        GTK_REGION_FIRST, 0 },
-    { "last",         GTK_REGION_LAST, 0 },
-    { "even",         GTK_REGION_EVEN, 0 },
-    { "odd",          GTK_REGION_ODD, 0 },
-    { NULL, }
-  }, *classes;
-  guint i;
-  char *name;
-
-  name = _gtk_css_parser_try_ident (scanner->parser, FALSE);
-  if (name == NULL)
-    {
-      gtk_css_provider_error_literal (scanner->provider,
-                                      scanner,
-                                      GTK_CSS_PROVIDER_ERROR,
-                                      GTK_CSS_PROVIDER_ERROR_SYNTAX,
-                                      "Missing name of pseudo-class");
-      return FALSE;
-    }
-
-  if (_gtk_css_parser_try (scanner->parser, "(", TRUE))
-    {
-      char *function = name;
-
-      name = _gtk_css_parser_try_ident (scanner->parser, TRUE);
-      if (!_gtk_css_parser_try (scanner->parser, ")", FALSE))
-        {
-          gtk_css_provider_error_literal (scanner->provider,
-                                          scanner,
-                                          GTK_CSS_PROVIDER_ERROR,
-                                          GTK_CSS_PROVIDER_ERROR_SYNTAX,
-                                          "Missing closing bracket for pseudo-class");
-          return FALSE;
-        }
-
-      if (g_ascii_strcasecmp (function, "nth-child") != 0)
-        {
-          gtk_css_provider_error (scanner->provider,
-                                  scanner,
-                                  GTK_CSS_PROVIDER_ERROR,
-                                  GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
-                                  "Unknown pseudo-class '%s(%s)'", function, name ? name : "");
-          g_free (function);
-          g_free (name);
-          return FALSE;
-        }
-      
-      g_free (function);
-    
-      if (name == NULL)
-        {
-          gtk_css_provider_error (scanner->provider,
-                                  scanner,
-                                  GTK_CSS_PROVIDER_ERROR,
-                                  GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
-                                  "nth-child() requires an argument");
-          return FALSE;
-        }
-
-      classes = nth_child_classes;
-    }
-  else
-    classes = pseudo_classes;
-
-  for (i = 0; classes[i].name != NULL; i++)
-    {
-      if (g_ascii_strcasecmp (name, classes[i].name) == 0)
-        {
-          if ((*region_to_modify & classes[i].region_flag) ||
-              (*state_to_modify & classes[i].state_flag))
-            {
-              if (classes == nth_child_classes)
-                gtk_css_provider_error (scanner->provider,
-                                        scanner,
-                                        GTK_CSS_PROVIDER_ERROR,
-                                        GTK_CSS_PROVIDER_ERROR_SYNTAX,
-                                        "Duplicate pseudo-class 'nth-child(%s)'", name);
-              else
-                gtk_css_provider_error (scanner->provider,
-                                        scanner,
-                                        GTK_CSS_PROVIDER_ERROR,
-                                        GTK_CSS_PROVIDER_ERROR_SYNTAX,
-                                        "Duplicate pseudo-class '%s'", name);
-            }
-          *region_to_modify |= classes[i].region_flag;
-          *state_to_modify |= classes[i].state_flag;
-
-          g_free (name);
-          return TRUE;
-        }
-    }
-
-  if (classes == nth_child_classes)
-    gtk_css_provider_error (scanner->provider,
-                            scanner,
-                            GTK_CSS_PROVIDER_ERROR,
-                            GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
-                            "Unknown pseudo-class 'nth-child(%s)'", name);
-  else
-    gtk_css_provider_error (scanner->provider,
-                            scanner,
-                            GTK_CSS_PROVIDER_ERROR,
-                            GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
-                            "Unknown pseudo-class '%s'", name);
-  g_free (name);
-  return FALSE;
-}
-
-static gboolean
-parse_simple_selector (GtkCssScanner *scanner,
-                       char **name,
-                       GArray *ids,
-                       GArray *classes,
-                       GtkRegionFlags *pseudo_classes,
-                       GtkStateFlags *state)
-{
-  gboolean parsed_something;
-  
-  *name = _gtk_css_parser_try_ident (scanner->parser, FALSE);
-  if (*name)
-    parsed_something = TRUE;
-  else
-    parsed_something = _gtk_css_parser_try (scanner->parser, "*", FALSE);
-
-  do {
-      if (_gtk_css_parser_try (scanner->parser, "#", FALSE))
-        {
-          if (!parse_selector_name (scanner, ids))
-            return FALSE;
-        }
-      else if (_gtk_css_parser_try (scanner->parser, ".", FALSE))
-        {
-          if (!parse_selector_class (scanner, classes))
-            return FALSE;
-        }
-      else if (_gtk_css_parser_try (scanner->parser, ":", FALSE))
-        {
-          if (!parse_selector_pseudo_class (scanner, pseudo_classes, state))
-            return FALSE;
-        }
-      else if (!parsed_something)
-        {
-          gtk_css_provider_error_literal (scanner->provider,
-                                          scanner,
-                                          GTK_CSS_PROVIDER_ERROR,
-                                          GTK_CSS_PROVIDER_ERROR_SYNTAX,
-                                          "Expected a valid selector");
-          return FALSE;
-        }
-      else
-        break;
-
-      parsed_something = TRUE;
-    }
-  while (!_gtk_css_parser_is_eof (scanner->parser));
-
-  _gtk_css_parser_skip_whitespace (scanner->parser);
-  return TRUE;
-}
-
-static GtkCssSelector *
-parse_selector (GtkCssScanner *scanner)
-{
-  GtkCssSelector *selector = NULL;
-
-  do {
-      char *name = NULL;
-      GArray *ids = g_array_new (TRUE, FALSE, sizeof (GQuark));
-      GArray *classes = g_array_new (TRUE, FALSE, sizeof (GQuark));
-      GtkRegionFlags pseudo_classes = 0;
-      GtkStateFlags state = 0;
-      GtkCssCombinator combine = GTK_CSS_COMBINE_DESCANDANT;
-
-      if (selector)
-        {
-          if (_gtk_css_parser_try (scanner->parser, ">", TRUE))
-            combine = GTK_CSS_COMBINE_CHILD;
-        }
-
-      if (!parse_simple_selector (scanner, &name, ids, classes, &pseudo_classes, &state))
-        {
-          g_array_free (ids, TRUE);
-          g_array_free (classes, TRUE);
-          if (selector)
-            _gtk_css_selector_free (selector);
-          return NULL;
-        }
-
-      selector = _gtk_css_selector_new (selector,
-                                        combine,
-                                        name,
-                                        (GQuark *) g_array_free (ids, ids->len == 0),
-                                        (GQuark *) g_array_free (classes, classes->len == 0),
-                                        pseudo_classes,
-                                        state);
-      g_free (name);
-    }
-  while (!_gtk_css_parser_is_eof (scanner->parser) &&
-         !_gtk_css_parser_begins_with (scanner->parser, ',') &&
-         !_gtk_css_parser_begins_with (scanner->parser, '{'));
-
-  return selector;
-}
-
 static GSList *
 parse_selector_list (GtkCssScanner *scanner)
 {
@@ -2360,7 +2083,7 @@ parse_selector_list (GtkCssScanner *scanner)
   gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_SELECTOR);
 
   do {
-      GtkCssSelector *select = parse_selector (scanner);
+      GtkCssSelector *select = _gtk_css_selector_parse (scanner->parser);
 
       if (select == NULL)
         {
diff --git a/gtk/gtkcssselector.c b/gtk/gtkcssselector.c
index d67880f..71247c0 100644
--- a/gtk/gtkcssselector.c
+++ b/gtk/gtkcssselector.c
@@ -19,8 +19,14 @@
 
 #include "gtkcssselectorprivate.h"
 
+#include "gtkcssprovider.h"
 #include "gtkstylecontextprivate.h"
 
+typedef enum {
+  GTK_CSS_COMBINE_DESCANDANT,
+  GTK_CSS_COMBINE_CHILD
+} GtkCssCombinator;
+
 struct _GtkCssSelector
 {
   GtkCssSelector *  previous;        /* link to next element in selector or NULL if last */
@@ -33,14 +39,14 @@ struct _GtkCssSelector
   GtkStateFlags     state;           /* required state flags (currently not checked when matching) */
 };
 
-GtkCssSelector *
-_gtk_css_selector_new (GtkCssSelector         *previous,
-                       GtkCssCombinator        combine,
-                       const char *            name,
-                       GQuark *                ids,
-                       GQuark *                classes,
-                       GtkRegionFlags          pseudo_classes,
-                       GtkStateFlags           state)
+static GtkCssSelector *
+gtk_css_selector_new (GtkCssSelector         *previous,
+                      GtkCssCombinator        combine,
+                      const char *            name,
+                      GQuark *                ids,
+                      GQuark *                classes,
+                      GtkRegionFlags          pseudo_classes,
+                      GtkStateFlags           state)
 {
   GtkCssSelector *selector;
 
@@ -57,6 +63,253 @@ _gtk_css_selector_new (GtkCssSelector         *previous,
   return selector;
 }
 
+static gboolean
+parse_selector_class (GtkCssParser *parser, GArray *classes)
+{
+  GQuark qname;
+  char *name;
+    
+  name = _gtk_css_parser_try_name (parser, FALSE);
+
+  if (name == NULL)
+    {
+      _gtk_css_parser_error (parser, "Expected a valid name for class");
+      return FALSE;
+    }
+
+  qname = g_quark_from_string (name);
+  g_array_append_val (classes, qname);
+  g_free (name);
+  return TRUE;
+}
+
+static gboolean
+parse_selector_name (GtkCssParser *parser, GArray *names)
+{
+  GQuark qname;
+  char *name;
+    
+  name = _gtk_css_parser_try_name (parser, FALSE);
+
+  if (name == NULL)
+    {
+      _gtk_css_parser_error (parser, "Expected a valid name for id");
+      return FALSE;
+    }
+
+  qname = g_quark_from_string (name);
+  g_array_append_val (names, qname);
+  g_free (name);
+  return TRUE;
+}
+
+static gboolean
+parse_selector_pseudo_class (GtkCssParser   *parser,
+                             GtkRegionFlags *region_to_modify,
+                             GtkStateFlags  *state_to_modify)
+{
+  struct {
+    const char *name;
+    GtkRegionFlags region_flag;
+    GtkStateFlags state_flag;
+  } pseudo_classes[] = {
+    { "first-child",  GTK_REGION_FIRST, 0 },
+    { "last-child",   GTK_REGION_LAST, 0 },
+    { "only-child",   GTK_REGION_ONLY, 0 },
+    { "sorted",       GTK_REGION_SORTED, 0 },
+    { "active",       0, GTK_STATE_FLAG_ACTIVE },
+    { "prelight",     0, GTK_STATE_FLAG_PRELIGHT },
+    { "hover",        0, GTK_STATE_FLAG_PRELIGHT },
+    { "selected",     0, GTK_STATE_FLAG_SELECTED },
+    { "insensitive",  0, GTK_STATE_FLAG_INSENSITIVE },
+    { "inconsistent", 0, GTK_STATE_FLAG_INCONSISTENT },
+    { "focused",      0, GTK_STATE_FLAG_FOCUSED },
+    { "focus",        0, GTK_STATE_FLAG_FOCUSED },
+    { "backdrop",     0, GTK_STATE_FLAG_BACKDROP },
+    { NULL, }
+  }, nth_child_classes[] = {
+    { "first",        GTK_REGION_FIRST, 0 },
+    { "last",         GTK_REGION_LAST, 0 },
+    { "even",         GTK_REGION_EVEN, 0 },
+    { "odd",          GTK_REGION_ODD, 0 },
+    { NULL, }
+  }, *classes;
+  guint i;
+  char *name;
+  GError *error;
+
+  name = _gtk_css_parser_try_ident (parser, FALSE);
+  if (name == NULL)
+    {
+      _gtk_css_parser_error (parser, "Missing name of pseudo-class");
+      return FALSE;
+    }
+
+  if (_gtk_css_parser_try (parser, "(", TRUE))
+    {
+      char *function = name;
+
+      name = _gtk_css_parser_try_ident (parser, TRUE);
+      if (!_gtk_css_parser_try (parser, ")", FALSE))
+        {
+          _gtk_css_parser_error (parser, "Missing closing bracket for pseudo-class");
+          return FALSE;
+        }
+
+      if (g_ascii_strcasecmp (function, "nth-child") != 0)
+        {
+          error = g_error_new (GTK_CSS_PROVIDER_ERROR,
+                               GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
+                               "Unknown pseudo-class '%s(%s)'", function, name ? name : "");
+          _gtk_css_parser_take_error (parser, error);
+          g_free (function);
+          g_free (name);
+          return FALSE;
+        }
+      
+      g_free (function);
+    
+      if (name == NULL)
+        {
+          error = g_error_new (GTK_CSS_PROVIDER_ERROR,
+                               GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
+                               "Unknown pseudo-class 'nth-child(%s)'", name);
+          _gtk_css_parser_take_error (parser, error);
+          return FALSE;
+        }
+
+      classes = nth_child_classes;
+    }
+  else
+    classes = pseudo_classes;
+
+  for (i = 0; classes[i].name != NULL; i++)
+    {
+      if (g_ascii_strcasecmp (name, classes[i].name) == 0)
+        {
+          if ((*region_to_modify & classes[i].region_flag) ||
+              (*state_to_modify & classes[i].state_flag))
+            {
+              if (classes == nth_child_classes)
+                _gtk_css_parser_error (parser, "Duplicate pseudo-class 'nth-child(%s)'", name);
+              else
+                _gtk_css_parser_error (parser, "Duplicate pseudo-class '%s'", name);
+            }
+          *region_to_modify |= classes[i].region_flag;
+          *state_to_modify |= classes[i].state_flag;
+
+          g_free (name);
+          return TRUE;
+        }
+    }
+
+  if (classes == nth_child_classes)
+    error = g_error_new (GTK_CSS_PROVIDER_ERROR,
+                         GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
+                         "Unknown pseudo-class 'nth-child(%s)'", name);
+  else
+    error = g_error_new (GTK_CSS_PROVIDER_ERROR,
+                         GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE,
+                         "Unknown pseudo-class '%s'", name);
+
+  g_free (name);
+  _gtk_css_parser_take_error (parser, error);
+
+  return FALSE;
+}
+
+static gboolean
+parse_simple_selector (GtkCssParser *parser,
+                       char **name,
+                       GArray *ids,
+                       GArray *classes,
+                       GtkRegionFlags *pseudo_classes,
+                       GtkStateFlags *state)
+{
+  gboolean parsed_something;
+  
+  *name = _gtk_css_parser_try_ident (parser, FALSE);
+  if (*name)
+    parsed_something = TRUE;
+  else
+    parsed_something = _gtk_css_parser_try (parser, "*", FALSE);
+
+  do {
+      if (_gtk_css_parser_try (parser, "#", FALSE))
+        {
+          if (!parse_selector_name (parser, ids))
+            return FALSE;
+        }
+      else if (_gtk_css_parser_try (parser, ".", FALSE))
+        {
+          if (!parse_selector_class (parser, classes))
+            return FALSE;
+        }
+      else if (_gtk_css_parser_try (parser, ":", FALSE))
+        {
+          if (!parse_selector_pseudo_class (parser, pseudo_classes, state))
+            return FALSE;
+        }
+      else if (!parsed_something)
+        {
+          _gtk_css_parser_error (parser, "Expected a valid selector");
+          return FALSE;
+        }
+      else
+        break;
+
+      parsed_something = TRUE;
+    }
+  while (!_gtk_css_parser_is_eof (parser));
+
+  _gtk_css_parser_skip_whitespace (parser);
+  return TRUE;
+}
+
+GtkCssSelector *
+_gtk_css_selector_parse (GtkCssParser *parser)
+{
+  GtkCssSelector *selector = NULL;
+
+  do {
+      char *name = NULL;
+      GArray *ids = g_array_new (TRUE, FALSE, sizeof (GQuark));
+      GArray *classes = g_array_new (TRUE, FALSE, sizeof (GQuark));
+      GtkRegionFlags pseudo_classes = 0;
+      GtkStateFlags state = 0;
+      GtkCssCombinator combine = GTK_CSS_COMBINE_DESCANDANT;
+
+      if (selector)
+        {
+          if (_gtk_css_parser_try (parser, ">", TRUE))
+            combine = GTK_CSS_COMBINE_CHILD;
+        }
+
+      if (!parse_simple_selector (parser, &name, ids, classes, &pseudo_classes, &state))
+        {
+          g_array_free (ids, TRUE);
+          g_array_free (classes, TRUE);
+          if (selector)
+            _gtk_css_selector_free (selector);
+          return NULL;
+        }
+
+      selector = gtk_css_selector_new (selector,
+                                       combine,
+                                       name,
+                                       (GQuark *) g_array_free (ids, ids->len == 0),
+                                       (GQuark *) g_array_free (classes, classes->len == 0),
+                                       pseudo_classes,
+                                       state);
+      g_free (name);
+    }
+  while (!_gtk_css_parser_is_eof (parser) &&
+         !_gtk_css_parser_begins_with (parser, ',') &&
+         !_gtk_css_parser_begins_with (parser, '{'));
+
+  return selector;
+}
+
 void
 _gtk_css_selector_free (GtkCssSelector *selector)
 {
diff --git a/gtk/gtkcssselectorprivate.h b/gtk/gtkcssselectorprivate.h
index 8601381..b74dfc5 100644
--- a/gtk/gtkcssselectorprivate.h
+++ b/gtk/gtkcssselectorprivate.h
@@ -20,23 +20,13 @@
 
 #include <gtk/gtkenums.h>
 #include <gtk/gtkwidgetpath.h>
+#include "gtk/gtkcssparserprivate.h"
 
 G_BEGIN_DECLS
 
-typedef enum {
-  GTK_CSS_COMBINE_DESCANDANT,
-  GTK_CSS_COMBINE_CHILD
-} GtkCssCombinator;
-
 typedef struct _GtkCssSelector GtkCssSelector;
 
-GtkCssSelector *  _gtk_css_selector_new             (GtkCssSelector         *previous,
-                                                     GtkCssCombinator        combine,
-                                                     const char *            name,
-                                                     GQuark *                ids,
-                                                     GQuark *                classes,
-                                                     GtkRegionFlags          pseudo_classes,
-                                                     GtkStateFlags           state);
+GtkCssSelector *  _gtk_css_selector_parse           (GtkCssParser           *parser);
 void              _gtk_css_selector_free            (GtkCssSelector         *selector);
 
 char *            _gtk_css_selector_to_string       (const GtkCssSelector   *selector);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]