* 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
G_TYPE_PARAM
G_TYPE_OBJECT
G_TYPE_GTYPE
+G_TYPE_VARIANT
<SUBSECTION>
G_TYPE_RESERVED_GLIB_FIRST
G_TYPE_ARRAY
G_TYPE_BYTE_ARRAY
G_TYPE_PTR_ARRAY
-G_TYPE_VARIANT
G_TYPE_VARIANT_TYPE
G_TYPE_ERROR
GStrv
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
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
*/
#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.
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:
*
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);
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);
}
{ "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", },
{ "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", },
# 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
VOID:BOXED
VOID:POINTER
VOID:OBJECT
+VOID:VARIANT
# GRuntime specific marshallers
VOID:UINT,POINTER
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
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
g_param_spec_ulong
g_param_spec_unichar
g_param_spec_value_array
+g_param_spec_variant
#endif
#endif
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
/* 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
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);
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);
}
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"
*/
#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;
typedef struct _GParamSpecObject GParamSpecObject;
typedef struct _GParamSpecOverride GParamSpecOverride;
typedef struct _GParamSpecGType GParamSpecGType;
+typedef struct _GParamSpecVariant GParamSpecVariant;
/**
* GParamSpecChar:
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,
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
* 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
* 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:
*
/* 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
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
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);
+ }
}
}
/**
+ * 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.
*
* 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 --- */
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 */
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
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 ();
}
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 ();
}