[gtk+/wip/cssvalue] Don't use GValue in GtkCssValue



commit 1ceed037b24c78b48a5319f465e4c489eb373413
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Mar 8 16:20:03 2012 +0100

    Don't use GValue in GtkCssValue
    
    We now have complete coverage in the GtkCssValue API for type
    handling, so drop the GValue from internal storage and just create
    new ones when needed.

 gtk/gtkcssvalue.c |  254 ++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 163 insertions(+), 91 deletions(-)
---
diff --git a/gtk/gtkcssvalue.c b/gtk/gtkcssvalue.c
index a3ea6d2..3678181 100644
--- a/gtk/gtkcssvalue.c
+++ b/gtk/gtkcssvalue.c
@@ -28,19 +28,25 @@
 struct _GtkCssValue
 {
   volatile gint ref_count;
-  GValue g_value;
+  GType type;
+  union {
+    gpointer ptr;
+    gint gint;
+    double dbl;
+  } u;
 };
 
 G_DEFINE_BOXED_TYPE (GtkCssValue, _gtk_css_value, _gtk_css_value_ref, _gtk_css_value_unref)
 
 static GtkCssValue *
-_gtk_css_value_new (void)
+_gtk_css_value_new (GType type)
 {
   GtkCssValue *value;
 
   value = g_slice_new0 (GtkCssValue);
 
   value->ref_count = 1;
+  value->type = type;
 
   return value;
 }
@@ -62,9 +68,24 @@ _gtk_css_value_new_from_gvalue (const GValue *g_value)
     value = _gtk_css_value_new_from_number (g_value_get_boxed (g_value));
   else
     {
-      value = _gtk_css_value_new ();
-      g_value_init (&value->g_value, type);
-      g_value_copy (g_value, &value->g_value);
+      value = _gtk_css_value_new (type);
+
+      if (g_type_is_a (type, G_TYPE_OBJECT))
+	value->u.ptr = g_value_dup_object (g_value);
+      else if (g_type_is_a (type, G_TYPE_BOXED))
+	value->u.ptr = g_value_dup_boxed (g_value);
+      else if (g_type_is_a (type, G_TYPE_INT))
+	value->u.gint = g_value_get_int (g_value);
+      else if (g_type_is_a (type, G_TYPE_BOOLEAN))
+	value->u.gint = g_value_get_boolean (g_value);
+      else if (g_type_is_a (type, G_TYPE_ENUM))
+	value->u.gint = g_value_get_enum (g_value);
+      else if (g_type_is_a (type, G_TYPE_STRING))
+	value->u.ptr = g_value_dup_string (g_value);
+      else if (g_type_is_a (type, G_TYPE_DOUBLE))
+	value->u.dbl = g_value_get_double (g_value);
+      else
+	g_assert_not_reached ();
     }
 
   return value;
@@ -93,8 +114,24 @@ _gtk_css_value_new_take_gvalue (GValue *g_value)
     }
   else
     {
-      value = _gtk_css_value_new ();
-      value->g_value = *g_value;
+      value = _gtk_css_value_new (type);
+
+      if (g_type_is_a (type, G_TYPE_OBJECT))
+	value->u.ptr = g_value_get_object (g_value);
+      else if (g_type_is_a (type, G_TYPE_BOXED))
+	value->u.ptr = g_value_get_boxed (g_value);
+      else if (g_type_is_a (type, G_TYPE_INT))
+	value->u.gint = g_value_get_int (g_value);
+      else if (g_type_is_a (type, G_TYPE_BOOLEAN))
+	value->u.gint = g_value_get_boolean (g_value);
+      else if (g_type_is_a (type, G_TYPE_ENUM))
+	value->u.gint = g_value_get_enum (g_value);
+      else if (g_type_is_a (type, G_TYPE_STRING))
+	value->u.ptr = g_value_dup_string (g_value);
+      else if (g_type_is_a (type, G_TYPE_DOUBLE))
+	value->u.dbl = g_value_get_double (g_value);
+      else
+	g_assert_not_reached ();
     }
 
   return value;
@@ -110,17 +147,15 @@ _gtk_css_value_new_from_int (gint val)
     {
       if (singletons[val] == NULL)
 	{
-	  value = _gtk_css_value_new ();
-	  g_value_init (&value->g_value, G_TYPE_INT);
-	  g_value_set_int (&value->g_value, val);
+	  value = _gtk_css_value_new (G_TYPE_INT);
+	  value->u.gint = val;
 	  singletons[val] = value;
 	}
       return _gtk_css_value_ref (singletons[val]);
     }
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, G_TYPE_INT);
-  g_value_set_int (&value->g_value, val);
+  value = _gtk_css_value_new (G_TYPE_INT);
+  value->u.gint = val;
 
   return value;
 }
@@ -130,9 +165,8 @@ _gtk_css_value_new_take_string (char *string)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, G_TYPE_STRING);
-  g_value_take_string (&value->g_value, string);
+  value = _gtk_css_value_new (G_TYPE_STRING);
+  value->u.ptr = string;
 
   return value;
 }
@@ -142,21 +176,28 @@ _gtk_css_value_new_from_string (const char *string)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, G_TYPE_STRING);
-  g_value_set_string (&value->g_value, string);
+  value = _gtk_css_value_new (G_TYPE_STRING);
+  value->u.ptr = g_strdup (string);
 
   return value;
 }
 
+static gpointer
+g_boxed_copy0 (GType         boxed_type,
+	       gconstpointer src_boxed)
+{
+  if (src_boxed == NULL)
+    return NULL;
+  return g_boxed_copy (boxed_type, src_boxed);
+}
+
 GtkCssValue *
 _gtk_css_value_new_from_border (const GtkBorder *border)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GTK_TYPE_BORDER);
-  g_value_set_boxed (&value->g_value, border);
+  value = _gtk_css_value_new (GTK_TYPE_BORDER);
+  value->u.ptr = g_boxed_copy0 (GTK_TYPE_BORDER, border);
 
   return value;
 }
@@ -166,9 +207,8 @@ _gtk_css_value_new_take_pattern (cairo_pattern_t *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, CAIRO_GOBJECT_TYPE_PATTERN);
-  g_value_take_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (CAIRO_GOBJECT_TYPE_PATTERN);
+  value->u.ptr = v;
 
   return value;
 }
@@ -178,9 +218,8 @@ _gtk_css_value_new_from_pattern (const cairo_pattern_t *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, CAIRO_GOBJECT_TYPE_PATTERN);
-  g_value_set_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (CAIRO_GOBJECT_TYPE_PATTERN);
+  value->u.ptr = g_boxed_copy0 (CAIRO_GOBJECT_TYPE_PATTERN, v);
 
   return value;
 }
@@ -190,9 +229,8 @@ _gtk_css_value_new_take_shadow (GtkShadow *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GTK_TYPE_SHADOW);
-  g_value_take_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (GTK_TYPE_SHADOW);
+  value->u.ptr = v;
 
   return value;
 }
@@ -202,9 +240,8 @@ _gtk_css_value_new_take_font_description (PangoFontDescription *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, PANGO_TYPE_FONT_DESCRIPTION);
-  g_value_take_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (PANGO_TYPE_FONT_DESCRIPTION);
+  value->u.ptr = v;
 
   return value;
 }
@@ -214,9 +251,8 @@ _gtk_css_value_new_take_image (GtkCssImage *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GTK_TYPE_CSS_IMAGE);
-  g_value_take_object (&value->g_value, v);
+  value = _gtk_css_value_new (GTK_TYPE_CSS_IMAGE);
+  value->u.ptr = v;
 
   return value;
 }
@@ -233,9 +269,8 @@ _gtk_css_value_new_from_number (const GtkCssNumber *v)
     {
       if (zero_singleton == NULL)
 	{
-	  value = _gtk_css_value_new ();
-	  g_value_init (&value->g_value, GTK_TYPE_CSS_NUMBER);
-	  g_value_set_boxed (&value->g_value, v);
+	  value = _gtk_css_value_new (GTK_TYPE_CSS_NUMBER);
+	  value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_NUMBER, v);
 	  zero_singleton = value;
 	}
       return _gtk_css_value_ref (zero_singleton);
@@ -251,18 +286,16 @@ _gtk_css_value_new_from_number (const GtkCssNumber *v)
       int i = round (v->value);
       if (px_singletons[i] == NULL)
 	{
-	  value = _gtk_css_value_new ();
-	  g_value_init (&value->g_value, GTK_TYPE_CSS_NUMBER);
-	  g_value_set_boxed (&value->g_value, v);
+	  value = _gtk_css_value_new (GTK_TYPE_CSS_NUMBER);
+	  value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_NUMBER, v);
 	  px_singletons[i] = value;
 	}
 
       return _gtk_css_value_ref (px_singletons[i]);
     }
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GTK_TYPE_CSS_NUMBER);
-  g_value_set_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (GTK_TYPE_CSS_NUMBER);
+  value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_NUMBER, v);
 
   return value;
 }
@@ -272,9 +305,8 @@ _gtk_css_value_new_from_rgba (const GdkRGBA *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GDK_TYPE_RGBA);
-  g_value_set_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (GDK_TYPE_RGBA);
+  value->u.ptr = g_boxed_copy0 (GDK_TYPE_RGBA, v);
 
   return value;
 }
@@ -284,9 +316,8 @@ _gtk_css_value_new_from_color (const GdkColor *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GDK_TYPE_COLOR);
-  g_value_set_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (GDK_TYPE_COLOR);
+  value->u.ptr = g_boxed_copy0 (GDK_TYPE_COLOR, v);
 
   return value;
 }
@@ -296,9 +327,8 @@ _gtk_css_value_new_from_background_size (const GtkCssBackgroundSize *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GTK_TYPE_CSS_BACKGROUND_SIZE);
-  g_value_set_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (GTK_TYPE_CSS_BACKGROUND_SIZE);
+  value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_BACKGROUND_SIZE, v);
 
   return value;
 }
@@ -308,9 +338,8 @@ _gtk_css_value_new_take_symbolic_color (GtkSymbolicColor *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GTK_TYPE_SYMBOLIC_COLOR);
-  g_value_take_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (GTK_TYPE_SYMBOLIC_COLOR);
+  value->u.ptr = v;
 
   return value;
 }
@@ -328,26 +357,62 @@ _gtk_css_value_ref (GtkCssValue *value)
 void
 _gtk_css_value_unref (GtkCssValue *value)
 {
+  GType type;
+
   if (value == NULL)
     return;
 
   if (!g_atomic_int_dec_and_test (&value->ref_count))
     return;
 
-  g_value_unset (&value->g_value);
+  type = value->type;
+
+  if (g_type_is_a (type, G_TYPE_OBJECT) && value->u.ptr != NULL)
+    g_object_unref (value->u.ptr);
+  else if (g_type_is_a (type, G_TYPE_BOXED) && value->u.ptr != NULL)
+    g_boxed_free (type, value->u.ptr);
+  else if (g_type_is_a (type, G_TYPE_STRING))
+    g_free (value->u.ptr);
+
   g_slice_free (GtkCssValue, value);
 }
 
 GType
 _gtk_css_value_get_content_type (GtkCssValue *value)
 {
-  return G_VALUE_TYPE (&value->g_value);
+  return value->type;
 }
 
 gboolean
 _gtk_css_value_holds (GtkCssValue *value, GType type)
 {
-  return G_VALUE_HOLDS (&value->g_value, type);
+  return g_type_is_a (value->type, type);
+}
+
+static void
+fill_gvalue (GtkCssValue *value,
+	     GValue      *g_value)
+{
+  GType type;
+
+  type = value->type;
+
+  if (g_type_is_a (type, G_TYPE_OBJECT))
+    g_value_set_object (g_value, value->u.ptr);
+  else if (g_type_is_a (type, G_TYPE_BOXED))
+    g_value_set_boxed (g_value, value->u.ptr);
+  else if (g_type_is_a (type, G_TYPE_INT))
+    g_value_set_int (g_value, value->u.gint);
+  else if (g_type_is_a (type, G_TYPE_BOOLEAN))
+    g_value_set_boolean (g_value, value->u.gint);
+  else if (g_type_is_a (type, G_TYPE_ENUM))
+    g_value_set_enum (g_value, value->u.gint);
+  else if (g_type_is_a (type, G_TYPE_STRING))
+    g_value_set_string (g_value, value->u.ptr);
+  else if (g_type_is_a (type, G_TYPE_DOUBLE))
+    g_value_set_double (g_value, value->u.dbl);
+  else
+    g_assert_not_reached ();
 }
 
 void
@@ -356,8 +421,8 @@ _gtk_css_value_init_gvalue (GtkCssValue *value,
 {
   if (value != NULL)
     {
-      g_value_init (g_value, G_VALUE_TYPE (&value->g_value));
-      g_value_copy (&value->g_value, g_value);
+      g_value_init (g_value, value->type);
+      fill_gvalue (value, g_value);
     }
 }
 
@@ -365,13 +430,18 @@ void
 _gtk_css_value_to_gvalue (GtkCssValue *value,
 			  GValue      *g_value)
 {
-  if (G_VALUE_TYPE (&value->g_value) == G_VALUE_TYPE (g_value))
-    g_value_copy (&value->g_value, g_value);
-  else if (g_value_type_transformable (G_VALUE_TYPE (&value->g_value), G_VALUE_TYPE (g_value)))
-    g_value_transform (&value->g_value, g_value);
+  if (value->type == G_VALUE_TYPE (g_value))
+    fill_gvalue (value, g_value);
+  else if (g_value_type_transformable (value->type, G_VALUE_TYPE (g_value)))
+    {
+      GValue v = G_VALUE_INIT;
+      _gtk_css_value_init_gvalue (value, &v);
+      g_value_transform (&v, g_value);
+      g_value_unset (&v);
+    }
   else
     g_warning ("can't convert css value of type `%s' as value of type `%s'",
-	       G_VALUE_TYPE_NAME (&value->g_value),
+	       g_type_name (value->type),
 	       G_VALUE_TYPE_NAME (g_value));
 }
 
@@ -385,159 +455,161 @@ GtkCssSpecialValue
 _gtk_css_value_get_special_kind  (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_SPECIAL_VALUE), 0);
-  return g_value_get_enum (&value->g_value);
+  return value->u.gint;
 }
 
 GtkCssNumber *
 _gtk_css_value_get_number  (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_NUMBER), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 GtkSymbolicColor *
 _gtk_css_value_get_symbolic_color  (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_SYMBOLIC_COLOR), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 int
 _gtk_css_value_get_int (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_INT), 0);
-  return g_value_get_int (&value->g_value);
+  return value->u.gint;
 }
 
 double
 _gtk_css_value_get_double (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_DOUBLE), 0);
-  return g_value_get_double (&value->g_value);
+  return value->u.dbl;
 }
 
 const char *
 _gtk_css_value_get_string (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_STRING), 0);
-  return g_value_get_string (&value->g_value);
+  return value->u.ptr;
 }
 
 gpointer
 _gtk_css_value_dup_object (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_OBJECT), NULL);
-  return g_value_dup_object (&value->g_value);
+  if (value->u.ptr)
+    return g_object_ref (value->u.ptr);
+  return NULL;
 }
 
 gpointer
 _gtk_css_value_get_object (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_OBJECT), NULL);
-  return g_value_get_object (&value->g_value);
+  return value->u.ptr;
 }
 
 gpointer
 _gtk_css_value_get_boxed (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_BOXED), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 const char **
 _gtk_css_value_get_strv (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_STRV), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 GtkCssImage *
 _gtk_css_value_get_image (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_IMAGE), NULL);
-  return g_value_get_object (&value->g_value);
+  return value->u.ptr;
 }
 
 GtkBorderStyle
 _gtk_css_value_get_border_style (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_BORDER_STYLE), 0);
-  return g_value_get_enum (&value->g_value);
+  return value->u.gint;
 }
 
 GtkCssBackgroundSize *
 _gtk_css_value_get_background_size (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BACKGROUND_SIZE), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 GtkCssBorderImageRepeat *
 _gtk_css_value_get_border_image_repeat (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 GtkCssBorderCornerRadius *
 _gtk_css_value_get_border_corner_radius (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 PangoFontDescription *
 _gtk_css_value_get_font_description (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_FONT_DESCRIPTION), 0);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 PangoStyle
 _gtk_css_value_get_pango_style (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_STYLE), 0);
-  return g_value_get_enum (&value->g_value);
+  return value->u.gint;
 }
 
 PangoVariant
 _gtk_css_value_get_pango_variant (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_VARIANT), 0);
-  return g_value_get_enum (&value->g_value);
+  return value->u.gint;
 }
 
 PangoWeight
 _gtk_css_value_get_pango_weight (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_WEIGHT), 0);
-  return g_value_get_enum (&value->g_value);
+  return value->u.gint;
 }
 
 GdkRGBA *
 _gtk_css_value_get_rgba (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GDK_TYPE_RGBA), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 cairo_pattern_t *
 _gtk_css_value_get_pattern (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, CAIRO_GOBJECT_TYPE_PATTERN), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 GtkGradient *
 _gtk_css_value_get_gradient (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_GRADIENT), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 GtkShadow *
 _gtk_css_value_get_shadow (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_SHADOW), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }



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