[gtk] cssprovider: Parse selectors without a GList
- From: Timm Bäder <baedert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk] cssprovider: Parse selectors without a GList
- Date: Sun, 26 Jan 2020 17:29:54 +0000 (UTC)
commit 36e3f4d9028bdd514b8a6996229afb0de0e93cde
Author: Timm Bäder <mail baedert org>
Date: Sat Jan 25 08:33:51 2020 +0100
cssprovider: Parse selectors without a GList
The maximum length of this list in Adwaita is 18, so use a generous
maximum length of 64 for the selector list of a ruleset.
gtk/gtkcssprovider.c | 58 ++++++++++++++++++++++++++++++++--------------------
1 file changed, 36 insertions(+), 22 deletions(-)
---
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index 6c25afae67..d32328c034 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -74,6 +74,8 @@
* way back to 4.0.
*/
+#define MAX_SELECTOR_LIST_LENGTH 64
+
struct _GtkCssProviderClass
{
GObjectClass parent_class;
@@ -550,29 +552,28 @@ gtk_css_provider_new (void)
}
static void
-css_provider_commit (GtkCssProvider *css_provider,
- GSList *selectors,
- GtkCssRuleset *ruleset)
+css_provider_commit (GtkCssProvider *css_provider,
+ GtkCssSelector **selectors,
+ guint n_selectors,
+ GtkCssRuleset *ruleset)
{
GtkCssProviderPrivate *priv = gtk_css_provider_get_instance_private (css_provider);
- GSList *l;
+ guint i;
if (ruleset->styles == NULL)
{
- g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free);
return;
}
- for (l = selectors; l; l = l->next)
+ for (i = 0; i < n_selectors; i ++)
{
- GtkCssRuleset new;
+ GtkCssRuleset *new;
- gtk_css_ruleset_init_copy (&new, ruleset, l->data);
+ g_array_set_size (priv->rulesets, priv->rulesets->len + 1);
- g_array_append_val (priv->rulesets, new);
+ new = &g_array_index (priv->rulesets, GtkCssRuleset, priv->rulesets->len - 1);
+ gtk_css_ruleset_init_copy (new, ruleset, selectors[i]);
}
-
- g_slist_free (selectors);
}
static void
@@ -757,22 +758,32 @@ parse_at_keyword (GtkCssScanner *scanner)
gtk_css_parser_end_block (scanner->parser);
}
-static GSList *
-parse_selector_list (GtkCssScanner *scanner)
+static guint
+parse_selector_list (GtkCssScanner *scanner,
+ GtkCssSelector *out_selectors[MAX_SELECTOR_LIST_LENGTH])
{
- GSList *selectors = NULL;
+ guint n_selectors = 0;
do {
GtkCssSelector *select = _gtk_css_selector_parse (scanner->parser);
if (select == NULL)
- return NULL;
+ return 0;
+
+ out_selectors[n_selectors] = select;
+ n_selectors++;
- selectors = g_slist_prepend (selectors, select);
+ if (G_UNLIKELY (n_selectors > MAX_SELECTOR_LIST_LENGTH))
+ {
+ gtk_css_parser_error_syntax (scanner->parser,
+ "Only %u selectors per ruleset allowed",
+ MAX_SELECTOR_LIST_LENGTH);
+ return 0;
+ }
}
while (gtk_css_parser_try_token (scanner->parser, GTK_CSS_TOKEN_COMMA));
- return selectors;
+ return n_selectors;
}
static void
@@ -891,11 +902,12 @@ parse_declarations (GtkCssScanner *scanner,
static void
parse_ruleset (GtkCssScanner *scanner)
{
- GSList *selectors;
+ GtkCssSelector *selectors[MAX_SELECTOR_LIST_LENGTH];
+ guint n_selectors;
GtkCssRuleset ruleset = { 0, };
- selectors = parse_selector_list (scanner);
- if (selectors == NULL)
+ n_selectors = parse_selector_list (scanner, selectors);
+ if (n_selectors == 0)
{
gtk_css_parser_skip_until (scanner->parser, GTK_CSS_TOKEN_OPEN_CURLY);
gtk_css_parser_skip (scanner->parser);
@@ -904,8 +916,10 @@ parse_ruleset (GtkCssScanner *scanner)
if (!gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_OPEN_CURLY))
{
+ guint i;
gtk_css_parser_error_syntax (scanner->parser, "Expected '{' after selectors");
- g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free);
+ for (i = 0; i < n_selectors; i ++)
+ _gtk_css_selector_free (selectors[i]);
gtk_css_parser_skip_until (scanner->parser, GTK_CSS_TOKEN_OPEN_CURLY);
gtk_css_parser_skip (scanner->parser);
return;
@@ -917,7 +931,7 @@ parse_ruleset (GtkCssScanner *scanner)
gtk_css_parser_end_block (scanner->parser);
- css_provider_commit (scanner->provider, selectors, &ruleset);
+ css_provider_commit (scanner->provider, selectors, n_selectors, &ruleset);
gtk_css_ruleset_clear (&ruleset);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]