[glib] Add fundamental type and pspec for GVariant



commit 4708b8ecc3f00e49aa98cb5989b5474a3257906c
Author: Christian Persch <chpe gnome org>
Date:   Thu Jun 17 18:03:51 2010 +0200

    Add fundamental type and pspec for GVariant
    
    Make G_TYPE_VARIANT a fundamental type instead of boxed, and add
    g_variant_{set,get,dup}_variant.
    
    Add GParamSpecVariant.
    
    Bug #610863.

 NEWS                                        |    4 +
 docs/reference/gobject/gobject-sections.txt |   13 ++-
 gobject/gboxed.c                            |   15 ++--
 gobject/gboxed.h                            |   13 +--
 gobject/glib-genmarshal.c                   |    4 +
 gobject/gmarshal.list                       |    2 +
 gobject/gobject.symbols                     |    6 +-
 gobject/gparamspecs.c                       |  127 +++++++++++++++++++++++-
 gobject/gparamspecs.h                       |   52 ++++++++++
 gobject/gtype.h                             |   13 ++-
 gobject/gvaluetypes.c                       |  148 +++++++++++++++++++++++++++
 gobject/gvaluetypes.h                       |   15 +++
 tests/gobject/gvalue-test.c                 |   38 ++++++--
 tests/gobject/paramspec-test.c              |   46 +++++++--
 14 files changed, 461 insertions(+), 35 deletions(-)
---
diff --git a/NEWS b/NEWS
index 0ba9da1..f2e1d54 100644
--- a/NEWS
+++ b/NEWS
@@ -28,6 +28,10 @@ and GApplication. Users of these APIs will need to be adapted.
 * GObject
  - Introduce g_object_notify_by_pspec
  - Add GBinding
+ - The GVariant gtype G_TYPE_VARIANT was changed from boxed
+   to fundamental. We believe there were no existing users
+   of the boxed type, so this should not cause any applications
+   to break.
 
 * Test framework
  - Add package and version to the test report XML
diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt
index 4b1bf0f..483c785 100644
--- a/docs/reference/gobject/gobject-sections.txt
+++ b/docs/reference/gobject/gobject-sections.txt
@@ -147,6 +147,7 @@ G_TYPE_BOXED
 G_TYPE_PARAM
 G_TYPE_OBJECT
 G_TYPE_GTYPE
+G_TYPE_VARIANT
 
 <SUBSECTION>
 G_TYPE_RESERVED_GLIB_FIRST
@@ -351,7 +352,6 @@ G_TYPE_REGEX
 G_TYPE_ARRAY
 G_TYPE_BYTE_ARRAY
 G_TYPE_PTR_ARRAY
-G_TYPE_VARIANT
 G_TYPE_VARIANT_TYPE
 G_TYPE_ERROR
 GStrv
@@ -698,6 +698,17 @@ g_param_spec_gtype
 g_value_get_gtype
 g_value_set_gtype
 
+<SUBSECTION GVariant>
+G_IS_PARAM_SPEC_VARIANT
+G_PARAM_SPEC_VARIANT
+G_VALUE_HOLDS_VARIANT
+G_TYPE_PARAM_VARIANT
+GParamSpecVariant
+g_param_spec_variant
+g_value_get_variant
+g_value_dup_variant
+g_value_set_variant
+
 <SUBSECTION Private>
 g_value_set_instance
 g_param_spec_types
diff --git a/gobject/gboxed.c b/gobject/gboxed.c
index f18ffb5..0685093 100644
--- a/gobject/gboxed.c
+++ b/gobject/gboxed.c
@@ -286,17 +286,16 @@ g_variant_type_get_gtype (void)
   return type_id;
 }
 
+/**
+ * g_variant_get_gtype:
+ *
+ * Since: 2.24
+ * Deprecated: 2.26
+ */
 GType
 g_variant_get_gtype (void)
 {
-  static GType type_id = 0;
-
-  if (!type_id)
-    type_id = g_boxed_type_register_static (g_intern_static_string ("GVariant"),
-                                            (GBoxedCopyFunc) g_variant_ref,
-                                            (GBoxedFreeFunc) g_variant_unref);
-
-  return type_id;
+  return G_TYPE_VARIANT;
 }
 
 GType
diff --git a/gobject/gboxed.h b/gobject/gboxed.h
index f46728b..baac62c 100644
--- a/gobject/gboxed.h
+++ b/gobject/gboxed.h
@@ -195,14 +195,6 @@ GType	g_boxed_type_register_static		(const gchar	*name,
  */
 #define	G_TYPE_VARIANT_TYPE (g_variant_type_get_gtype ())
 /**
- * G_TYPE_VARIANT:
- * 
- * The #GType for a boxed type holding a #GVariant reference.
- * 
- * Since: 2.24
- */
-#define	G_TYPE_VARIANT (g_variant_get_gtype ())
-/**
  * G_TYPE_ERROR:
  * 
  * The #GType for a boxed type holding a #GError.
@@ -229,10 +221,13 @@ GType   g_array_get_type        (void)  G_GNUC_CONST;
 GType   g_byte_array_get_type   (void)  G_GNUC_CONST;
 GType   g_ptr_array_get_type    (void)  G_GNUC_CONST;
 GType   g_variant_type_get_gtype(void)  G_GNUC_CONST;
-GType   g_variant_get_gtype     (void)  G_GNUC_CONST;
 GType   g_regex_get_type        (void)  G_GNUC_CONST;
 GType   g_error_get_type        (void)  G_GNUC_CONST;
 
+#ifndef G_DISABLE_DEPRECATED
+GType   g_variant_get_gtype     (void)  G_GNUC_CONST;
+#endif
+
 /**
  * GStrv:
  * 
diff --git a/gobject/glib-genmarshal.c b/gobject/glib-genmarshal.c
index f96f466..e382fdc 100644
--- a/gobject/glib-genmarshal.c
+++ b/gobject/glib-genmarshal.c
@@ -151,6 +151,7 @@ put_marshal_value_getters (void)
   fputs ("#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)\n", fout);
   fputs ("#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)\n", fout);
   fputs ("#define g_marshal_value_peek_object(v)   g_value_get_object (v)\n", fout);
+  fputs ("#define g_marshal_value_peek_variant(v)  g_value_get_variant (v)\n", fout);
   fputs ("#else /* !G_ENABLE_DEBUG */\n", fout);
   fputs ("/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.\n", fout);
   fputs (" *          Do not access GValues directly in your code. Instead, use the\n", fout);
@@ -174,6 +175,7 @@ put_marshal_value_getters (void)
   fputs ("#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer\n", fout);
   fputs ("#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer\n", fout);
   fputs ("#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer\n", fout);
+  fputs ("#define g_marshal_value_peek_variant(v)  (v)->data[0].v_pointer\n", fout);
   fputs ("#endif /* !G_ENABLE_DEBUG */\n", fout);
   fputs ("\n", fout);
 }
@@ -202,6 +204,7 @@ complete_in_arg (InArgument *iarg)
     { "BOXED",		"BOXED",	"gpointer",	"g_marshal_value_peek_boxed",	},
     { "POINTER",	"POINTER",	"gpointer",	"g_marshal_value_peek_pointer",	},
     { "OBJECT",		"OBJECT",	"gpointer",	"g_marshal_value_peek_object",	},
+    { "VARIANT",	"VARIANT",	"gpointer",	"g_marshal_value_peek_variant",	},
     /* deprecated: */
     { "NONE",		"VOID",		"void",		NULL,			},
     { "BOOL",		"BOOLEAN",	"gboolean",	"g_marshal_value_peek_boolean",	},
@@ -246,6 +249,7 @@ complete_out_arg (OutArgument *oarg)
     { "BOXED",		"BOXED",	"gpointer",	"g_value_take_boxed",			     },
     { "POINTER",	"POINTER",	"gpointer",	"g_value_set_pointer",			     },
     { "OBJECT",		"OBJECT",	"GObject*",	"g_value_take_object",			     },
+    { "VARIANT",	"VARIANT",	"GVariant*",	"g_value_take_variant",			     },
     /* deprecated: */
     { "NONE",		"VOID",		"void",		NULL,					     },
     { "BOOL",		"BOOLEAN",	"gboolean",	"g_value_set_boolean",			     },
diff --git a/gobject/gmarshal.list b/gobject/gmarshal.list
index f3844a1..533307b 100644
--- a/gobject/gmarshal.list
+++ b/gobject/gmarshal.list
@@ -19,6 +19,7 @@
 #   BOXED       for boxed (anonymous but reference counted) types (GBoxed*)
 #   POINTER     for anonymous pointer types (gpointer)
 #   OBJECT      for GObject or derived types (GObject*)
+#   VARIANT     for variants (GVariant*)
 #   NONE        deprecated alias for VOID
 #   BOOL        deprecated alias for BOOLEAN
 
@@ -40,6 +41,7 @@ VOID:PARAM
 VOID:BOXED
 VOID:POINTER
 VOID:OBJECT
+VOID:VARIANT
 
 # GRuntime specific marshallers
 VOID:UINT,POINTER
diff --git a/gobject/gobject.symbols b/gobject/gobject.symbols
index f47f9e6..0c3dd5b 100644
--- a/gobject/gobject.symbols
+++ b/gobject/gobject.symbols
@@ -41,7 +41,6 @@ g_error_get_type G_GNUC_CONST
 g_ptr_array_get_type G_GNUC_CONST
 g_regex_get_type G_GNUC_CONST
 g_variant_type_get_gtype G_GNUC_CONST
-g_variant_get_gtype G_GNUC_CONST
 g_closure_get_type G_GNUC_CONST
 g_value_get_type G_GNUC_CONST
 g_value_array_get_type G_GNUC_CONST
@@ -52,6 +51,7 @@ g_value_get_boxed
 g_value_set_static_boxed
 #ifndef G_DISABLE_DEPRECATED
 g_value_set_boxed_take_ownership
+g_variant_get_gtype G_GNUC_CONST
 #endif
 #endif
 #endif
@@ -215,6 +215,7 @@ g_param_spec_uint64
 g_param_spec_ulong
 g_param_spec_unichar
 g_param_spec_value_array
+g_param_spec_variant
 #endif
 #endif
 
@@ -294,6 +295,9 @@ g_value_take_string
 g_gtype_get_type
 g_value_set_gtype
 g_value_get_gtype
+g_value_get_variant
+g_value_dup_variant
+g_value_set_variant
 #endif
 #endif
 
diff --git a/gobject/gparamspecs.c b/gobject/gparamspecs.c
index 2f49824..3bdfaf7 100644
--- a/gobject/gparamspecs.c
+++ b/gobject/gparamspecs.c
@@ -1,5 +1,6 @@
 /* GObject - GLib Type, Object, Parameter and Signal Library
  * Copyright (C) 1997-1999, 2000-2001 Tim Janik and Red Hat, Inc.
+ * Copyright (C) 2010 Christian Persch
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -1098,13 +1099,71 @@ param_gtype_values_cmp (GParamSpec   *pspec,
   return p1 < p2 ? -1 : p1 > p2;
 }
 
+static void
+param_variant_init (GParamSpec *pspec)
+{
+  GParamSpecVariant *vspec = G_PARAM_SPEC_VARIANT (pspec);
+
+  vspec->type = NULL;
+  vspec->default_value = NULL;
+}
+
+static void
+param_variant_finalize (GParamSpec *pspec)
+{
+  GParamSpecVariant *vspec = G_PARAM_SPEC_VARIANT (pspec);
+  GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_VARIANT));
+
+  if (vspec->default_value)
+    g_variant_unref (vspec->default_value);
+  g_variant_type_free (vspec->type);
+
+  parent_class->finalize (pspec);
+}
+
+static void
+param_variant_set_default (GParamSpec *pspec,
+                           GValue     *value)
+{
+  value->data[0].v_pointer = G_PARAM_SPEC_VARIANT (pspec)->default_value;
+  value->data[1].v_uint |= G_VALUE_NOCOPY_CONTENTS;
+}
+
+static gboolean
+param_variant_validate (GParamSpec *pspec,
+                        GValue     *value)
+{
+  GParamSpecVariant *vspec = G_PARAM_SPEC_VARIANT (pspec);
+  GVariant *variant = value->data[0].v_pointer;
+
+  if ((variant == NULL && vspec->default_value != NULL) ||
+      (variant != NULL && !g_variant_is_of_type (variant, vspec->type)))
+    {
+      g_param_value_set_default (pspec, value);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gint
+param_variant_values_cmp (GParamSpec   *pspec,
+                          const GValue *value1,
+                          const GValue *value2)
+{
+  GVariant *v1 = value1->data[0].v_pointer;
+  GVariant *v2 = value2->data[0].v_pointer;
+
+  return v1 < v2 ? -1 : v2 > v1;
+}
+
 /* --- type initialization --- */
 GType *g_param_spec_types = NULL;
 
 void
 g_param_spec_types_init (void)	
 {
-  const guint n_types = 22;
+  const guint n_types = 23;
   GType type, *spec_types, *spec_types_bound;
 
   g_param_spec_types = g_new0 (GType, n_types);
@@ -1509,6 +1568,24 @@ g_param_spec_types_init (void)
     g_assert (type == G_TYPE_PARAM_GTYPE);
   }
 
+  /* G_TYPE_PARAM_VARIANT
+   */
+  {
+    const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecVariant), /* instance_size */
+      0,                          /* n_preallocs */
+      param_variant_init,         /* instance_init */
+      G_TYPE_VARIANT,             /* value_type */
+      param_variant_finalize,     /* finalize */
+      param_variant_set_default,  /* value_set_default */
+      param_variant_validate,     /* value_validate */
+      param_variant_values_cmp,   /* values_cmp */
+    };
+    type = g_param_type_register_static (g_intern_static_string ("GParamVariant"), &pspec_info);
+    *spec_types++ = type;
+    g_assert (type == G_TYPE_PARAM_VARIANT);
+  }
+
   g_assert (spec_types == spec_types_bound);
 }
 
@@ -2393,5 +2470,53 @@ g_param_spec_override (const gchar *name,
   return pspec;
 }
 
+/**
+ * g_param_spec_variant:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @type: a #GVariantType
+ * @default_value: (allow-none): a #GVariant of type @type to use as the
+ *                 default value, or %NULL
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecVariant instance specifying a #GVariant
+ * property.
+ *
+ * If @default_value is floating, it is consumed.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: the newly created #GParamSpec
+ *
+ * Since: 2.26
+ */
+GParamSpec*
+g_param_spec_variant (const gchar        *name,
+                      const gchar        *nick,
+                      const gchar        *blurb,
+                      const GVariantType *type,
+                      GVariant           *default_value,
+                      GParamFlags         flags)
+{
+  GParamSpecVariant *vspec;
+
+  g_return_val_if_fail (type != NULL, NULL);
+  g_return_val_if_fail (default_value == NULL ||
+                        g_variant_is_of_type (default_value, type), NULL);
+
+  vspec = g_param_spec_internal (G_TYPE_PARAM_VARIANT,
+                                 name,
+                                 nick,
+                                 blurb,
+                                 flags);
+
+  vspec->type = g_variant_type_copy (type);
+  if (default_value)
+    vspec->default_value = g_variant_ref_sink (default_value);
+
+  return G_PARAM_SPEC (vspec);
+}
+
 #define __G_PARAMSPECS_C__
 #include "gobjectaliasdef.c"
diff --git a/gobject/gparamspecs.h b/gobject/gparamspecs.h
index 345db03..a61d608 100644
--- a/gobject/gparamspecs.h
+++ b/gobject/gparamspecs.h
@@ -549,6 +549,34 @@ G_BEGIN_DECLS
  */
 #define G_PARAM_SPEC_GTYPE(pspec)          (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_GTYPE, GParamSpecGType))
 
+/**
+ * G_TYPE_PARAM_VARIANT:
+ *
+ * The #GType of #GParamSpecVariant.
+ *
+ * Since: 2.26
+ */
+#define G_TYPE_PARAM_VARIANT                (g_param_spec_types[22])
+/**
+ * G_IS_PARAM_SPEC_VARIANT:
+ * @pspec: a #GParamSpec
+ *
+ * Checks whether the given #GParamSpec is of type %G_TYPE_PARAM_VARIANT.
+ *
+ * Returns: %TRUE on success
+ *
+ * Since: 2.26
+ */
+#define G_IS_PARAM_SPEC_VARIANT(pspec)      (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_VARIANT))
+/**
+ * G_PARAM_SPEC_VARIANT:
+ * @pspec: a #GParamSpec
+ *
+ * Casts a #GParamSpec into a #GParamSpecVariant.
+ *
+ * Since: 2.26
+ */
+#define G_PARAM_SPEC_VARIANT(pspec)         (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_VARIANT, GParamSpecVariant))
 
 /* --- typedefs & structures --- */
 typedef struct _GParamSpecChar       GParamSpecChar;
@@ -573,6 +601,7 @@ typedef struct _GParamSpecValueArray GParamSpecValueArray;
 typedef struct _GParamSpecObject     GParamSpecObject;
 typedef struct _GParamSpecOverride   GParamSpecOverride;
 typedef struct _GParamSpecGType      GParamSpecGType;
+typedef struct _GParamSpecVariant    GParamSpecVariant;
 
 /**
  * GParamSpecChar:
@@ -921,6 +950,23 @@ struct _GParamSpecGType
   GParamSpec    parent_instance;
   GType         is_a_type;
 };
+/**
+ * GParamSpecVariant:
+ * @parent_instance: private #GParamSpec portion
+ * @type: a #GVariantType, or %NULL
+ * @default_value: a #GVariant, or %NULL
+ *
+ * A #GParamSpec derived structure that contains the meta data for #GVariant properties.
+ *
+ * Since: 2.26
+ */
+struct _GParamSpecVariant
+{
+  GParamSpec    parent_instance;
+  GVariantType *type;
+  GVariant     *default_value;
+  gpointer      padding[4];
+};
 
 /* --- GParamSpec prototypes --- */
 GParamSpec*	g_param_spec_char	 (const gchar	 *name,
@@ -1051,6 +1097,12 @@ GParamSpec*	g_param_spec_gtype	 (const gchar	 *name,
 					  const gchar	 *blurb,
 					  GType           is_a_type,
 					  GParamFlags	  flags);
+GParamSpec*	g_param_spec_variant	 (const gchar        *name,
+					  const gchar        *nick,
+					  const gchar	     *blurb,
+					  const GVariantType *type,
+					  GVariant           *default_value,
+					  GParamFlags         flags);
 
 /* --- internal --- */
 /* We prefix variable declarations so they can
diff --git a/gobject/gtype.h b/gobject/gtype.h
index 33a4a8b..d94249d 100644
--- a/gobject/gtype.h
+++ b/gobject/gtype.h
@@ -179,6 +179,17 @@ G_BEGIN_DECLS
  * The fundamental type for #GObject.
  */
 #define G_TYPE_OBJECT			G_TYPE_MAKE_FUNDAMENTAL (20)
+/**
+ * G_TYPE_VARIANT:
+ *
+ * The fundamental type corresponding to #GVariant.
+ *
+ * Note: GLib 2.24 did include a boxed type with this name. It was replaced
+ * with this fundamental type in 2.26.
+ *
+ * Since: 2.26
+ */
+#define	G_TYPE_VARIANT                  G_TYPE_MAKE_FUNDAMENTAL (21)
 
 
 /* Reserved fundamental type numbers to create new fundamental
@@ -208,7 +219,7 @@ G_BEGIN_DECLS
  * First fundamental type number to create a new fundamental type id with
  * G_TYPE_MAKE_FUNDAMENTAL() reserved for GLib.
  */
-#define G_TYPE_RESERVED_GLIB_FIRST	(21)
+#define G_TYPE_RESERVED_GLIB_FIRST	(22)
 /**
  * G_TYPE_RESERVED_GLIB_LAST:
  * 
diff --git a/gobject/gvaluetypes.c b/gobject/gvaluetypes.c
index 5713e48..925a503 100644
--- a/gobject/gvaluetypes.c
+++ b/gobject/gvaluetypes.c
@@ -1,5 +1,6 @@
 /* GObject - GLib Type, Object, Parameter and Signal Library
  * Copyright (C) 1997-1999, 2000-2001 Tim Janik and Red Hat, Inc.
+ * Copyright © 2010 Christian Persch
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -361,6 +362,63 @@ value_lcopy_pointer (const GValue *value,
   return NULL;
 }
 
+static void
+value_free_variant (GValue *value)
+{
+  if (!(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) &&
+      value->data[0].v_pointer)
+    g_variant_unref (value->data[0].v_pointer);
+}
+
+static void
+value_copy_variant (const GValue *src_value,
+		   GValue	*dest_value)
+{
+  if (src_value->data[0].v_pointer)
+    dest_value->data[0].v_pointer = g_variant_ref_sink (src_value->data[0].v_pointer);
+  else
+    dest_value->data[0].v_pointer = NULL;
+}
+
+static gchar*
+value_collect_variant (GValue	  *value,
+		      guint        n_collect_values,
+		      GTypeCValue *collect_values,
+		      guint        collect_flags)
+{
+  if (!collect_values[0].v_pointer)
+    value->data[0].v_pointer = NULL;
+  else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
+    {
+      value->data[0].v_pointer = collect_values[0].v_pointer;
+      value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
+    }
+  else
+    value->data[0].v_pointer = g_variant_ref_sink (collect_values[0].v_pointer);
+
+  return NULL;
+}
+
+static gchar*
+value_lcopy_variant (const GValue *value,
+		    guint         n_collect_values,
+		    GTypeCValue  *collect_values,
+		    guint         collect_flags)
+{
+  GVariant **variant_p = collect_values[0].v_pointer;
+
+  if (!variant_p)
+    return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
+
+  if (!value->data[0].v_pointer)
+    *variant_p = NULL;
+  else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
+    *variant_p = value->data[0].v_pointer;
+  else
+    *variant_p = g_variant_ref_sink (value->data[0].v_pointer);
+
+  return NULL;
+}
 
 /* --- type initialization --- */
 void
@@ -550,6 +608,24 @@ g_value_types_init (void)
     type = g_type_register_fundamental (G_TYPE_POINTER, g_intern_static_string ("gpointer"), &info, &finfo, 0);
     g_assert (type == G_TYPE_POINTER);
   }
+
+  /* G_TYPE_VARIANT
+   */
+  {
+    static const GTypeValueTable value_table = {
+      value_init_pointer,	/* value_init */
+      value_free_variant,	/* value_free */
+      value_copy_variant,	/* value_copy */
+      value_peek_pointer0,	/* value_peek_pointer */
+      "p",			/* collect_format */
+      value_collect_variant,	/* collect_value */
+      "p",			/* lcopy_format */
+      value_lcopy_variant,	/* lcopy_value */
+    };
+    info.value_table = &value_table;
+    type = g_type_register_fundamental (G_TYPE_VARIANT, g_intern_static_string ("GVariant"), &info, &finfo, 0);
+    g_assert (type == G_TYPE_VARIANT);
+  }
 }
 
 
@@ -1102,6 +1178,78 @@ g_value_get_gtype (const GValue *value)
 }
 
 /**
+ * g_value_set_variant:
+ * @value: a valid #GValue of %G_TYPE_VARIANT
+ * @variant: a #GVariant, or %NULL
+ *
+ * Set the contents of a variant #GValue to @variant.
+ * If the variant is floating, it is consumed.
+ *
+ * Since: 2.26
+ */
+void
+g_value_set_variant (GValue   *value,
+                     GVariant *variant)
+{
+  GVariant *old_variant;
+
+  g_return_if_fail (G_VALUE_HOLDS_VARIANT (value));
+
+  old_variant = value->data[0].v_pointer;
+
+  if (variant)
+    value->data[0].v_pointer = g_variant_ref_sink (variant);
+  else
+    value->data[0].v_pointer = NULL;
+
+  if (old_variant)
+    g_variant_unref (old_variant);
+}
+
+/**
+ * g_value_get_variant:
+ * @value: a valid #GValue of %G_TYPE_VARIANT
+ *
+ * Get the contents of a variant #GValue.
+ *
+ * Returns: variant contents of @value
+ *
+ * Since: 2.26
+ */
+GVariant*
+g_value_get_variant (const GValue *value)
+{
+  g_return_val_if_fail (G_VALUE_HOLDS_VARIANT (value), NULL);
+
+  return value->data[0].v_pointer;
+}
+
+/**
+ * g_value_get_variant:
+ * @value: a valid #GValue of %G_TYPE_VARIANT
+ *
+ * Get the contents of a variant #GValue, increasing its refcount.
+ *
+ * Returns: variant contents of @value, should be unrefed using
+ *   g_variant_unref() when no longer needed
+ *
+ * Since: 2.26
+ */
+GVariant*
+g_value_dup_variant (const GValue *value)
+{
+  GVariant *variant;
+
+  g_return_val_if_fail (G_VALUE_HOLDS_VARIANT (value), NULL);
+
+  variant = value->data[0].v_pointer;
+  if (variant)
+    g_variant_ref_sink (variant);
+
+  return variant;
+}
+
+/**
  * g_strdup_value_contents:
  * @value: #GValue which contents are to be described.
  *
diff --git a/gobject/gvaluetypes.h b/gobject/gvaluetypes.h
index 6385783..d5e27c9 100644
--- a/gobject/gvaluetypes.h
+++ b/gobject/gvaluetypes.h
@@ -163,6 +163,17 @@ G_BEGIN_DECLS
  * Returns: %TRUE on success.
  */
 #define G_VALUE_HOLDS_GTYPE(value)	 (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_GTYPE))
+/**
+ * G_VALUE_HOLDS_VARIANT:
+ * @value: a valid #GValue structure
+ *
+ * Checks whether the given #GValue can hold values of type %G_TYPE_VARIANT.
+ *
+ * Returns: %TRUE on success.
+ *
+ * Since: 2.26
+ */
+#define G_VALUE_HOLDS_VARIANT(value)     (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_VARIANT))
 
 
 /* --- prototypes --- */
@@ -212,6 +223,10 @@ GType		      g_gtype_get_type		(void);
 void		      g_value_set_gtype	        (GValue	      *value,
 						 GType         v_gtype);
 GType	              g_value_get_gtype	        (const GValue *value);
+void		      g_value_set_variant	(GValue	      *value,
+						 GVariant     *variant);
+GVariant*	      g_value_get_variant	(const GValue *value);
+GVariant*	      g_value_dup_variant	(const GValue *value);
 
 
 /* Convenience for registering new pointer types */
diff --git a/tests/gobject/gvalue-test.c b/tests/gobject/gvalue-test.c
index 2d721e0..516a484 100644
--- a/tests/gobject/gvalue-test.c
+++ b/tests/gobject/gvalue-test.c
@@ -219,6 +219,15 @@ test_collection (void)
   error = collect (&value, G_TYPE_BOXED);
   g_assert (error == NULL);
   g_assert (g_value_get_gtype (&value) == G_TYPE_BOXED);
+
+  g_value_unset (&value);
+  g_value_init (&value, G_TYPE_VARIANT);
+  error = collect (&value, g_variant_new_uint32 (42));
+  g_assert (error == NULL);
+  g_assert (g_variant_is_of_type (g_value_get_variant (&value), G_VARIANT_TYPE ("u")));
+  g_assert_cmpuint (g_variant_get_uint32 (g_value_get_variant (&value)), ==, 42);
+
+  g_value_unset (&value);
 }
 
 static void
@@ -357,18 +366,33 @@ test_copying (void)
     g_assert (error == NULL);
     g_assert (c == G_TYPE_BOXED);
   }  
+
+  {
+    GVariant *c = NULL;
+
+    g_value_unset (&value);
+    g_value_init (&value, G_TYPE_VARIANT);
+    g_value_set_variant (&value, g_variant_new_uint32 (42));
+    error = lcopy (&value, &c);
+    g_assert (error == NULL);
+    g_assert (c != NULL);
+    g_assert (g_variant_is_of_type (c, G_VARIANT_TYPE ("u")));
+    g_assert_cmpuint (g_variant_get_uint32 (c), ==, 42);
+    g_variant_unref (c);
+  }
 }
 
 
 int
 main (int argc, char *argv[])
 {
-  g_type_init (); 
-  
-  test_enum_transformation ();
-  test_gtype_value ();
-  test_collection ();
-  test_copying ();
+  g_test_init (&argc, &argv, NULL);
+  g_type_init ();
+
+  g_test_add_func ("/gvalue/enum-transformation", test_enum_transformation);
+  g_test_add_func ("/gvalue/gtype", test_gtype_value);
+  g_test_add_func ("/gvalue/collection", test_collection);
+  g_test_add_func ("/gvalue/copying", test_copying);
 
-  return 0;
+  return g_test_run ();
 }
diff --git a/tests/gobject/paramspec-test.c b/tests/gobject/paramspec-test.c
index 498aed0..6de850f 100644
--- a/tests/gobject/paramspec-test.c
+++ b/tests/gobject/paramspec-test.c
@@ -206,15 +206,47 @@ test_param_spec_gtype (void)
   g_assert (!modified && g_value_get_gtype (&value) == G_TYPE_PARAM_INT);
 }
 
+static void
+test_param_spec_variant (void)
+{
+  GParamSpec *pspec;
+  GValue value = { 0, };
+  gboolean modified;
+
+  pspec = g_param_spec_variant ("variant", "nick", "blurb",
+                                G_VARIANT_TYPE ("i"),
+                                g_variant_new_int32 (42),
+                                G_PARAM_READWRITE);
+
+  g_value_init (&value, G_TYPE_VARIANT);
+  g_value_set_variant (&value, g_variant_new_int32 (42));
+
+  g_assert (g_param_value_defaults (pspec, &value));
+
+  modified = g_param_value_validate (pspec, &value);
+  g_assert (!modified);
+
+  g_value_reset (&value);
+  g_value_set_variant (&value, g_variant_new_uint32 (41));
+  modified = g_param_value_validate (pspec, &value);
+  g_assert (modified);
+  g_assert_cmpint (g_variant_get_int32 (g_value_get_variant (&value)), ==, 42);
+  g_value_unset (&value);
+
+  g_param_spec_unref (pspec);
+}
+
 int
 main (int argc, char *argv[])
 {
-  g_type_init (); 
-  
-  test_param_spec_char ();
-  test_param_spec_string ();
-  test_param_spec_override ();
-  test_param_spec_gtype ();
+  g_test_init (&argc, &argv, NULL);
+  g_type_init ();
+
+  g_test_add_func ("/paramspec/char", test_param_spec_char);
+  g_test_add_func ("/paramspec/string", test_param_spec_string);
+  g_test_add_func ("/paramspec/override", test_param_spec_override);
+  g_test_add_func ("/paramspec/gtype", test_param_spec_gtype);
+  g_test_add_func ("/paramspec/variant", test_param_spec_variant);
 
-  return 0;
+  return g_test_run ();
 }



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