From b9ebe8c2269d2040d50448fb72f72c344d459625 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 3 Apr 2012 09:49:37 +0200 Subject: [PATCH] cssarrayvalue: Redo parsing arrays Does 3 things: 1) Introduce a "none" array signleton 2) Get rid of memleaks in error paths 3) Reduce code in parse funcs --- gtk/gtkcssarrayvalue.c | 56 ++++++++-- gtk/gtkcssarrayvalueprivate.h | 7 +- gtk/gtkcssshorthandproperty.c | 2 +- gtk/gtkcssshorthandpropertyimpl.c | 3 +- gtk/gtkcssstylepropertyimpl.c | 173 +++++++++++------------------- 5 files changed, 118 insertions(+), 123 deletions(-) diff --git a/gtk/gtkcssarrayvalue.c b/gtk/gtkcssarrayvalue.c index 5260eaf653..baab5fa820 100644 --- a/gtk/gtkcssarrayvalue.c +++ b/gtk/gtkcssarrayvalue.c @@ -94,18 +94,62 @@ static const GtkCssValueClass GTK_CSS_VALUE_ARRAY = { gtk_css_value_array_print }; +static GtkCssValue none_singleton = { >K_CSS_VALUE_ARRAY, 1, 0, { NULL } }; + GtkCssValue * -_gtk_css_array_value_new (GtkCssValue **values, - guint n_values) +_gtk_css_array_value_new (GtkCssValue *content) +{ + if (content == NULL) + return _gtk_css_value_ref (&none_singleton); + + return _gtk_css_array_value_new_from_array (&content, 1); +} + +GtkCssValue * +_gtk_css_array_value_new_from_array (GtkCssValue **values, + guint n_values) { GtkCssValue *result; - - g_return_val_if_fail (values != NULL || n_values == 0, NULL); - - result = _gtk_css_value_alloc (>K_CSS_VALUE_ARRAY, sizeof (GtkCssValue) + sizeof (GtkCssValue *) * (MAX (1, n_values) - 1)); + + g_return_val_if_fail (values != NULL, NULL); + g_return_val_if_fail (n_values > 0, NULL); + + result = _gtk_css_value_alloc (>K_CSS_VALUE_ARRAY, sizeof (GtkCssValue) + sizeof (GtkCssValue *) * (n_values - 1)); result->n_values = n_values; memcpy (&result->values[0], values, sizeof (GtkCssValue *) * n_values); + + return result; +} +GtkCssValue * +_gtk_css_array_value_parse (GtkCssParser *parser, + GtkCssValue *(* parse_func) (GtkCssParser *parser), + gboolean allow_none) +{ + GtkCssValue *value, *result; + GPtrArray *values; + + if (allow_none && + _gtk_css_parser_try (parser, "none", TRUE)) + return _gtk_css_value_ref (&none_singleton); + + values = g_ptr_array_new (); + + do { + value = parse_func (parser); + + if (value == NULL) + { + g_ptr_array_set_free_func (values, (GDestroyNotify) _gtk_css_value_unref); + g_ptr_array_free (values, TRUE); + return NULL; + } + + g_ptr_array_add (values, value); + } while (_gtk_css_parser_try (parser, ",", TRUE)); + + result = _gtk_css_array_value_new_from_array ((GtkCssValue **) values->pdata, values->len); + g_ptr_array_free (values, TRUE); return result; } diff --git a/gtk/gtkcssarrayvalueprivate.h b/gtk/gtkcssarrayvalueprivate.h index 08b6e4a84d..38443b512c 100644 --- a/gtk/gtkcssarrayvalueprivate.h +++ b/gtk/gtkcssarrayvalueprivate.h @@ -20,12 +20,17 @@ #ifndef __GTK_CSS_ARRAY_VALUE_PRIVATE_H__ #define __GTK_CSS_ARRAY_VALUE_PRIVATE_H__ +#include "gtkcssparserprivate.h" #include "gtkcssvalueprivate.h" G_BEGIN_DECLS -GtkCssValue * _gtk_css_array_value_new (GtkCssValue **values, +GtkCssValue * _gtk_css_array_value_new (GtkCssValue *content); +GtkCssValue * _gtk_css_array_value_new_from_array (GtkCssValue **values, guint n_values); +GtkCssValue * _gtk_css_array_value_parse (GtkCssParser *parser, + GtkCssValue * (* parse_func) (GtkCssParser *parser), + gboolean allow_none); GtkCssValue * _gtk_css_array_value_get_nth (const GtkCssValue *value, guint i); diff --git a/gtk/gtkcssshorthandproperty.c b/gtk/gtkcssshorthandproperty.c index f10201d31c..f63d3a51de 100644 --- a/gtk/gtkcssshorthandproperty.c +++ b/gtk/gtkcssshorthandproperty.c @@ -139,7 +139,7 @@ gtk_css_shorthand_property_parse_value (GtkStyleProperty *property, data[i] = _gtk_css_initial_value_new (); } - result = _gtk_css_array_value_new (data, shorthand->subproperties->len); + result = _gtk_css_array_value_new_from_array (data, shorthand->subproperties->len); g_free (data); return result; diff --git a/gtk/gtkcssshorthandpropertyimpl.c b/gtk/gtkcssshorthandpropertyimpl.c index 7bba8786c7..3b467f7b5c 100644 --- a/gtk/gtkcssshorthandpropertyimpl.c +++ b/gtk/gtkcssshorthandpropertyimpl.c @@ -434,8 +434,7 @@ parse_font (GtkCssShorthandProperty *shorthand, if (mask & PANGO_FONT_MASK_FAMILY) { - GtkCssValue *value = _gtk_css_string_value_new (pango_font_description_get_family (desc)); - values[0] = _gtk_css_array_value_new (&value, 1); + values[0] = _gtk_css_array_value_new (_gtk_css_string_value_new (pango_font_description_get_family (desc))); } if (mask & PANGO_FONT_MASK_STYLE) { diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c index 7871076714..73a3b98206 100644 --- a/gtk/gtkcssstylepropertyimpl.c +++ b/gtk/gtkcssstylepropertyimpl.c @@ -217,50 +217,40 @@ color_assign (GtkCssStyleProperty *property, return _gtk_css_rgba_value_new_from_rgba (g_value_get_boxed (value)); } +static GtkCssValue * +font_family_parse_one (GtkCssParser *parser) +{ + char *name; + + name = _gtk_css_parser_try_ident (parser, TRUE); + if (name) + { + GString *string = g_string_new (name); + g_free (name); + while ((name = _gtk_css_parser_try_ident (parser, TRUE))) + { + g_string_append_c (string, ' '); + g_string_append (string, name); + g_free (name); + } + name = g_string_free (string, FALSE); + } + else + { + name = _gtk_css_parser_read_string (parser); + if (name == NULL) + return NULL; + } + + return _gtk_css_string_value_new_take (name); +} + static GtkCssValue * font_family_parse (GtkCssStyleProperty *property, GtkCssParser *parser, GFile *base) { - GPtrArray *names; - GtkCssValue *result; - char *name; - - /* We don't special case generic families. Pango should do - * that for us */ - - names = g_ptr_array_new (); - - do { - name = _gtk_css_parser_try_ident (parser, TRUE); - if (name) - { - GString *string = g_string_new (name); - g_free (name); - while ((name = _gtk_css_parser_try_ident (parser, TRUE))) - { - g_string_append_c (string, ' '); - g_string_append (string, name); - g_free (name); - } - name = g_string_free (string, FALSE); - } - else - { - name = _gtk_css_parser_read_string (parser); - if (name == NULL) - { - g_ptr_array_free (names, TRUE); - return FALSE; - } - } - - g_ptr_array_add (names, _gtk_css_string_value_new_take (name)); - } while (_gtk_css_parser_try (parser, ",", TRUE)); - - result = _gtk_css_array_value_new ((GtkCssValue **) names->pdata, names->len); - g_ptr_array_free (names, TRUE); - return result; + return _gtk_css_array_value_parse (parser, font_family_parse_one, FALSE); } static void @@ -300,7 +290,7 @@ font_family_assign (GtkCssStyleProperty *property, g_ptr_array_add (array, _gtk_css_string_value_new (*names)); } - result = _gtk_css_array_value_new ((GtkCssValue **) array->pdata, array->len); + result = _gtk_css_array_value_new_from_array ((GtkCssValue **) array->pdata, array->len); g_ptr_array_free (array, TRUE); return result; } @@ -735,35 +725,34 @@ border_image_width_parse (GtkCssStyleProperty *property, return result; } +static GtkCssValue * +transition_property_parse_one (GtkCssParser *parser) +{ + GtkCssValue *value; + + value = _gtk_css_ident_value_try_parse (parser); + + if (value == NULL) + { + _gtk_css_parser_error (parser, "Expected an identifier"); + return NULL; + } + + return value; +} + static GtkCssValue * transition_property_parse (GtkCssStyleProperty *property, GtkCssParser *parser, GFile *base) { - GPtrArray *names; - GtkCssValue *result, *value; + return _gtk_css_array_value_parse (parser, transition_property_parse_one, FALSE); +} - if (_gtk_css_parser_try (parser, "none", TRUE)) - return _gtk_css_array_value_new (NULL, 0); - - names = g_ptr_array_new (); - - do { - value = _gtk_css_ident_value_try_parse (parser); - - if (value == NULL) - { - _gtk_css_parser_error (parser, "Expected an identifier"); - g_ptr_array_free (names, TRUE); - return NULL; - } - - g_ptr_array_add (names, value); - } while (_gtk_css_parser_try (parser, ",", TRUE)); - - result = _gtk_css_array_value_new ((GtkCssValue **) names->pdata, names->len); - g_ptr_array_free (names, TRUE); - return result; +static GtkCssValue * +transition_time_parse_one (GtkCssParser *parser) +{ + return _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_TIME); } static GtkCssValue * @@ -771,26 +760,7 @@ transition_time_parse (GtkCssStyleProperty *property, GtkCssParser *parser, GFile *base) { - GPtrArray *times; - GtkCssValue *result, *next; - - times = g_ptr_array_new (); - - do { - next = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_TIME); - - if (next == NULL) - { - g_ptr_array_free (times, TRUE); - return NULL; - } - - g_ptr_array_add (times, next); - } while (_gtk_css_parser_try (parser, ",", TRUE)); - - result = _gtk_css_array_value_new ((GtkCssValue **) times->pdata, times->len); - g_ptr_array_free (times, TRUE); - return result; + return _gtk_css_array_value_parse (parser, transition_time_parse_one, FALSE); } static GtkCssValue * @@ -798,26 +768,7 @@ transition_timing_function_parse (GtkCssStyleProperty *property, GtkCssParser *parser, GFile *base) { - GPtrArray *funcs; - GtkCssValue *result, *next; - - funcs = g_ptr_array_new (); - - do { - next = _gtk_css_ease_value_parse (parser); - - if (next == NULL) - { - g_ptr_array_free (funcs, TRUE); - return NULL; - } - - g_ptr_array_add (funcs, next); - } while (_gtk_css_parser_try (parser, ",", TRUE)); - - result = _gtk_css_array_value_new ((GtkCssValue **) funcs->pdata, funcs->len); - g_ptr_array_free (funcs, TRUE); - return result; + return _gtk_css_array_value_parse (parser, _gtk_css_ease_value_parse, FALSE); } static GtkCssValue * @@ -1281,7 +1232,6 @@ gtk_symbolic_color_new_rgba (double red, void _gtk_css_style_property_init_properties (void) { - GtkCssValue *value; GtkCssBackgroundSize default_background_size = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), FALSE, FALSE }; GtkCssBackgroundPosition default_background_position = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PERCENT), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PERCENT)}; GtkCssBorderCornerRadius no_corner_radius = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX) }; @@ -1332,7 +1282,6 @@ _gtk_css_style_property_init_properties (void) _gtk_css_value_new_take_symbolic_color ( gtk_symbolic_color_new_rgba (0, 0, 0, 0))); - value = _gtk_css_string_value_new ("Sans"); gtk_css_style_property_register ("font-family", GTK_CSS_PROPERTY_FONT_FAMILY, G_TYPE_STRV, @@ -1343,7 +1292,7 @@ _gtk_css_style_property_init_properties (void) font_family_query, font_family_assign, NULL, - _gtk_css_array_value_new (&value, 1)); + _gtk_css_array_value_new (_gtk_css_string_value_new ("Sans"))); gtk_css_style_property_register ("font-style", GTK_CSS_PROPERTY_FONT_STYLE, PANGO_TYPE_STYLE, @@ -1856,7 +1805,6 @@ _gtk_css_style_property_init_properties (void) NULL, _gtk_css_value_new_from_boxed (GTK_TYPE_BORDER, NULL)); - value = _gtk_css_ident_value_new ("all"); gtk_css_style_property_register ("transition-property", GTK_CSS_PROPERTY_TRANSITION_PROPERTY, G_TYPE_NONE, @@ -1867,8 +1815,7 @@ _gtk_css_style_property_init_properties (void) NULL, NULL, NULL, - _gtk_css_array_value_new (&value, 1)); - value = _gtk_css_number_value_new (0, GTK_CSS_S); + _gtk_css_array_value_new (_gtk_css_ident_value_new ("all"))); gtk_css_style_property_register ("transition-duration", GTK_CSS_PROPERTY_TRANSITION_DURATION, G_TYPE_NONE, @@ -1879,8 +1826,7 @@ _gtk_css_style_property_init_properties (void) NULL, NULL, NULL, - _gtk_css_array_value_new (&value, 1)); - value = _gtk_css_ease_value_new_cubic_bezier (0.25, 0.1, 0.25, 1.0); + _gtk_css_array_value_new (_gtk_css_number_value_new (0, GTK_CSS_S))); gtk_css_style_property_register ("transition-timing-function", GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION, G_TYPE_NONE, @@ -1891,7 +1837,8 @@ _gtk_css_style_property_init_properties (void) NULL, NULL, NULL, - _gtk_css_array_value_new (&value, 1)); + _gtk_css_array_value_new ( + _gtk_css_ease_value_new_cubic_bezier (0.25, 0.1, 0.25, 1.0))); gtk_css_style_property_register ("transition-delay", GTK_CSS_PROPERTY_TRANSITION_DELAY, G_TYPE_NONE, @@ -1902,7 +1849,7 @@ _gtk_css_style_property_init_properties (void) NULL, NULL, NULL, - _gtk_css_array_value_new (&value, 1)); + _gtk_css_array_value_new (_gtk_css_number_value_new (0, GTK_CSS_S))); gtk_css_style_property_register ("engine", GTK_CSS_PROPERTY_ENGINE,