summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.co.uk>2012-09-12 12:57:43 +0200
committerXavier Claessens <xavier.claessens@collabora.co.uk>2012-09-15 15:37:26 +0200
commitd1d2203333f47701b5887dde18a910c0ffaed7f9 (patch)
treec09c2a6b2ea0437daed700cb878cbfbc9624ec0f
parent51115c42577150c400a9785b77714efd442117a8 (diff)
downloadtelepathy-glib-d1d2203333f47701b5887dde18a910c0ffaed7f9.tar.gz
GVariant: Add tp_vardict_get_foo() similar to tp_asv_get_foo()
-rw-r--r--docs/reference/telepathy-glib-docs.sgml2
-rw-r--r--docs/reference/telepathy-glib-sections.txt22
-rw-r--r--telepathy-glib/variant-util.c507
-rw-r--r--telepathy-glib/variant-util.h27
4 files changed, 556 insertions, 2 deletions
diff --git a/docs/reference/telepathy-glib-docs.sgml b/docs/reference/telepathy-glib-docs.sgml
index a59c1e20d..fe4bb9090 100644
--- a/docs/reference/telepathy-glib-docs.sgml
+++ b/docs/reference/telepathy-glib-docs.sgml
@@ -20,6 +20,8 @@
<xi:include href="xml/proxy-tp-properties.xml"/>
<xi:include href="xml/dbus.xml"/>
<xi:include href="xml/asv.xml"/>
+ <xi:include href="xml/variant-util.xml"/>
+ <xi:include href="xml/vardict.xml"/>
<xi:include href="xml/proxy-subclass.xml"/>
</chapter>
<chapter id="ch-protocol">
diff --git a/docs/reference/telepathy-glib-sections.txt b/docs/reference/telepathy-glib-sections.txt
index a9456221d..d277555a7 100644
--- a/docs/reference/telepathy-glib-sections.txt
+++ b/docs/reference/telepathy-glib-sections.txt
@@ -2468,6 +2468,28 @@ tp_asv_dump
</SECTION>
<SECTION>
+<FILE>variant-util</FILE>
+<TITLE>variant-util</TITLE>
+<INCLUDE>telepathy-glib/telepathy-glib.h</INCLUDE>
+tp_variant_type_classify
+tp_variant_convert
+</SECTION>
+
+<SECTION>
+<FILE>vardict</FILE>
+<TITLE>vardict</TITLE>
+<INCLUDE>telepathy-glib/telepathy-glib.h</INCLUDE>
+tp_vardict_get_boolean
+tp_vardict_get_double
+tp_vardict_get_int32
+tp_vardict_get_int64
+tp_vardict_get_object_path
+tp_vardict_get_string
+tp_vardict_get_uint32
+tp_vardict_get_uint64
+</SECTION>
+
+<SECTION>
<FILE>dbus</FILE>
<TITLE>dbus</TITLE>
<INCLUDE>telepathy-glib/telepathy-glib.h</INCLUDE>
diff --git a/telepathy-glib/variant-util.c b/telepathy-glib/variant-util.c
index fce3ee17f..c9ae69992 100644
--- a/telepathy-glib/variant-util.c
+++ b/telepathy-glib/variant-util.c
@@ -27,10 +27,10 @@
*/
/**
- * SECTION:vardic
+ * SECTION:vardict
* @title: Manipulating a{sv} mappings
* @short_description: Functions to manipulate mappings from string to
- * variant, as represented in GDBus by a %G_VARIANT_TYPE_VARDICT
+ * variant, as represented in GVariant by a %G_VARIANT_TYPE_VARDICT
*
* These functions provide convenient access to the values in such
* a mapping.
@@ -106,3 +106,506 @@ _tp_asv_from_vardict (GVariant *variant)
g_value_unset (&v);
return result;
}
+
+/**
+ * tp_variant_type_classify:
+ * @type: a #GVariantType
+ *
+ * Classifies @type according to its top-level type.
+ *
+ * Returns: the #GVariantClass of @type
+ * Since: 0.UNRELEASED
+ **/
+GVariantClass
+tp_variant_type_classify (const GVariantType *type)
+{
+ /* Same as g_variant_classify() but for a GVariantType. This returns the first
+ * letter of the dbus type and cast it to an enum where elements have the
+ * ascii value of the type letters. */
+ return g_variant_type_peek_string (type)[0];
+}
+
+static gdouble
+_tp_variant_convert_double (GVariant *variant,
+ gboolean *valid)
+{
+ *valid = TRUE;
+
+ switch (g_variant_classify (variant))
+ {
+ case G_VARIANT_CLASS_DOUBLE:
+ return g_variant_get_double (variant);
+
+ case G_VARIANT_CLASS_BYTE:
+ return g_variant_get_byte (variant);
+
+ case G_VARIANT_CLASS_UINT32:
+ return g_variant_get_uint32 (variant);
+
+ case G_VARIANT_CLASS_INT32:
+ return g_variant_get_int32 (variant);
+
+ case G_VARIANT_CLASS_INT64:
+ return g_variant_get_int64 (variant);
+
+ case G_VARIANT_CLASS_UINT64:
+ return g_variant_get_uint64 (variant);
+
+ default:
+ break;
+ }
+
+ *valid = FALSE;
+ return 0.0;
+}
+
+static gint32
+_tp_variant_convert_int32 (GVariant *variant,
+ gboolean *valid)
+{
+ gint64 i;
+ guint64 u;
+
+ *valid = TRUE;
+
+ switch (g_variant_classify (variant))
+ {
+ case G_VARIANT_CLASS_BYTE:
+ return g_variant_get_byte (variant);
+
+ case G_VARIANT_CLASS_UINT32:
+ u = g_variant_get_uint32 (variant);
+ if (G_LIKELY (u <= G_MAXINT32))
+ return u;
+ break;
+
+ case G_VARIANT_CLASS_INT32:
+ return g_variant_get_int32 (variant);
+
+ case G_VARIANT_CLASS_INT64:
+ i = g_variant_get_int64 (variant);
+ if (G_LIKELY (i >= G_MININT32 && i <= G_MAXINT32))
+ return i;
+ break;
+
+ case G_VARIANT_CLASS_UINT64:
+ u = g_variant_get_uint64 (variant);
+ if (G_LIKELY (u <= G_MAXINT32))
+ return u;
+ break;
+
+ default:
+ break;
+ }
+
+ *valid = FALSE;
+ return 0;
+}
+
+static gint64
+_tp_variant_convert_int64 (GVariant *variant,
+ gboolean *valid)
+{
+ guint64 u;
+
+ *valid = TRUE;
+
+ switch (g_variant_classify (variant))
+ {
+ case G_VARIANT_CLASS_BYTE:
+ return g_variant_get_byte (variant);
+
+ case G_VARIANT_CLASS_UINT32:
+ return g_variant_get_uint32 (variant);
+
+ case G_VARIANT_CLASS_INT32:
+ return g_variant_get_int32 (variant);
+
+ case G_VARIANT_CLASS_INT64:
+ return g_variant_get_int64 (variant);
+
+ case G_VARIANT_CLASS_UINT64:
+ u = g_variant_get_uint64 (variant);
+ if (G_LIKELY (u <= G_MAXINT64))
+ return u;
+ break;
+
+ default:
+ break;
+ }
+
+ *valid = FALSE;
+ return 0;
+}
+
+static guint32
+_tp_variant_convert_uint32 (GVariant *variant,
+ gboolean *valid)
+{
+ gint64 i;
+ guint64 u;
+
+ *valid = TRUE;
+
+ switch (g_variant_classify (variant))
+ {
+ case G_VARIANT_CLASS_BYTE:
+ return g_variant_get_byte (variant);
+
+ case G_VARIANT_CLASS_UINT32:
+ return g_variant_get_uint32 (variant);
+
+ case G_VARIANT_CLASS_INT32:
+ i = g_variant_get_int32 (variant);
+ if (G_LIKELY (i >= 0))
+ return i;
+ break;
+
+ case G_VARIANT_CLASS_INT64:
+ i = g_variant_get_int64 (variant);
+ if (G_LIKELY (i >= 0 && i <= G_MAXUINT32))
+ return i;
+ break;
+
+ case G_VARIANT_CLASS_UINT64:
+ u = g_variant_get_uint64 (variant);
+ if (G_LIKELY (u <= G_MAXUINT32))
+ return u;
+ break;
+
+ default:
+ break;
+ }
+
+ *valid = FALSE;
+ return 0;
+}
+
+static guint64
+_tp_variant_convert_uint64 (GVariant *variant,
+ gboolean *valid)
+{
+ gint64 tmp;
+
+ *valid = TRUE;
+
+ switch (g_variant_classify (variant))
+ {
+ case G_VARIANT_CLASS_BYTE:
+ return g_variant_get_byte (variant);
+
+ case G_VARIANT_CLASS_UINT32:
+ return g_variant_get_uint32 (variant);
+
+ case G_VARIANT_CLASS_INT32:
+ tmp = g_variant_get_int32 (variant);
+ if (G_LIKELY (tmp >= 0))
+ return tmp;
+ break;
+
+ case G_VARIANT_CLASS_INT64:
+ tmp = g_variant_get_int64 (variant);
+ if (G_LIKELY (tmp >= 0))
+ return tmp;
+ break;
+
+ case G_VARIANT_CLASS_UINT64:
+ return g_variant_get_uint64 (variant);
+
+ default:
+ break;
+ }
+
+ *valid = FALSE;
+ return 0;
+}
+
+/**
+ * tp_variant_convert:
+ * @variant: (transfer full): a #GVariant to convert
+ * @type: a #GVariantType @variant must be converted to
+ *
+ * Convert the type of @variant to @type if possible. This takes ownership of
+ * @variant. If no conversion is needed, simply return @variant. If conversion
+ * is not possible, %NULL is returned.
+ *
+ * Returns: (transfer full): a new #GVariant owned by the caller.
+ * Since: 0.UNRELEASED
+ **/
+GVariant *
+tp_variant_convert (GVariant *variant,
+ const GVariantType *type)
+{
+ GVariant *ret = NULL;
+ gboolean valid;
+
+ if (variant == NULL)
+ return NULL;
+
+ g_variant_ref_sink (variant);
+
+ if (g_variant_is_of_type (variant, type))
+ return variant;
+
+ switch (tp_variant_type_classify (type))
+ {
+ #define CASE(type) \
+ { \
+ g##type tmp = _tp_variant_convert_##type (variant, &valid); \
+ if (valid) \
+ ret = g_variant_new_##type (tmp); \
+ }
+ case G_VARIANT_CLASS_DOUBLE:
+ CASE (double);
+ break;
+
+ case G_VARIANT_CLASS_INT32:
+ CASE (int32);
+ break;
+
+ case G_VARIANT_CLASS_INT64:
+ CASE (int64);
+ break;
+
+ case G_VARIANT_CLASS_UINT32:
+ CASE (uint32);
+ break;
+
+ case G_VARIANT_CLASS_UINT64:
+ CASE (uint64);
+ break;
+
+ default:
+ break;
+ #undef CASE
+ }
+
+ g_variant_unref (variant);
+
+ return (ret != NULL) ? g_variant_ref_sink (ret) : NULL;
+}
+
+/**
+ * tp_vardict_get_string:
+ * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
+ * @key: The key to look up
+ *
+ * If a value for @key in @variant is present and is a string, return it.
+ *
+ * Otherwise return %NULL.
+ *
+ * The returned value is not copied, and is only valid as long as @variant is
+ * kept. Copy it with g_strdup() if you need to keep it for longer.
+ *
+ * Returns: (transfer none) (allow-none): the string value of @key, or %NULL
+ * Since: 0.UNRELEASED
+ */
+const gchar *
+tp_vardict_get_string (GVariant *variant,
+ const gchar *key)
+{
+ const gchar *ret;
+
+ g_return_val_if_fail (variant != NULL, NULL);
+ g_return_val_if_fail (key != NULL, NULL);
+ g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), NULL);
+
+ if (!g_variant_lookup (variant, key, "&s", &ret))
+ return NULL;
+
+ return ret;
+}
+
+/**
+ * tp_vardict_get_object_path:
+ * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
+ * @key: The key to look up
+ *
+ * If a value for @key in @variant is present and is an object path, return it.
+ *
+ * Otherwise return %NULL.
+ *
+ * The returned value is not copied, and is only valid as long as @variant is
+ * kept. Copy it with g_strdup() if you need to keep it for longer.
+ *
+ * Returns: (transfer none) (allow-none): the object path value of @key, or
+ * %NULL
+ * Since: 0.UNRELEASED
+ */
+const gchar *
+tp_vardict_get_object_path (GVariant *variant,
+ const gchar *key)
+{
+ const gchar *ret;
+
+ g_return_val_if_fail (variant != NULL, NULL);
+ g_return_val_if_fail (key != NULL, NULL);
+ g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), NULL);
+
+ if (!g_variant_lookup (variant, key, "&o", &ret))
+ return NULL;
+
+ return ret;
+}
+
+/**
+ * tp_vardict_get_boolean:
+ * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
+ * @key: The key to look up
+ * @valid: (out): Either %NULL, or a location to store %TRUE if the key actually
+ * exists and has a boolean value
+ *
+ * If a value for @key in @variant is present and boolean, return it,
+ * and set *@valid to %TRUE if @valid is not %NULL.
+ *
+ * Otherwise return %FALSE, and set *@valid to %FALSE if @valid is not %NULL.
+ *
+ * Returns: a boolean value for @key
+ * Since: 0.UNRELEASED
+ */
+gboolean
+tp_vardict_get_boolean (GVariant *variant,
+ const gchar *key,
+ gboolean *valid)
+{
+ gboolean ret;
+
+ g_return_val_if_fail (variant != NULL, FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+ g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), FALSE);
+
+ if (!g_variant_lookup (variant, key, "b", &ret))
+ {
+ if (valid != NULL)
+ *valid = FALSE;
+
+ return FALSE;
+ }
+
+ if (valid != NULL)
+ *valid = TRUE;
+
+ return ret;
+}
+
+#define IMPLEMENT(type) \
+ g##type \
+ tp_vardict_get_##type (GVariant *variant, \
+ const gchar *key, \
+ gboolean *valid) \
+ { \
+ g##type ret = 0; \
+ gboolean ret_valid = FALSE; \
+ GVariant *value; \
+ \
+ g_return_val_if_fail (variant != NULL, 0); \
+ g_return_val_if_fail (key != NULL, 0); \
+ g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), 0); \
+ \
+ value = g_variant_lookup_value (variant, key, NULL); \
+ if (value != NULL) \
+ { \
+ ret = _tp_variant_convert_##type (value, &ret_valid); \
+ g_variant_unref (value); \
+ } \
+ \
+ if (valid != NULL) \
+ *valid = ret_valid; \
+ \
+ return ret; \
+ }
+
+/**
+ * tp_vardict_get_double:
+ * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
+ * @key: The key to look up
+ * @valid: (out): Either %NULL, or a location in which to store %TRUE on success
+ * or %FALSE on failure
+ *
+ * If a value for @key in @variant is present and has any numeric type used by
+ * GVariant (gint32, guint32, gint64, guint64 or gdouble),
+ * return it as a double, and if @valid is not %NULL, set *@valid to %TRUE.
+ *
+ * Otherwise, return 0.0, and if @valid is not %NULL, set *@valid to %FALSE.
+ *
+ * Returns: the double precision floating-point value of @key, or 0.0
+ * Since: 0.UNRELEASED
+ */
+IMPLEMENT (double)
+
+/**
+ * tp_vardict_get_int32:
+ * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
+ * @key: The key to look up
+ * @valid: (out): Either %NULL, or a location in which to store %TRUE on success
+ * or %FALSE on failure
+ *
+ * If a value for @key in @variant is present, has an integer type used by
+ * GVariant (gint32, guint32, gint64 or guint64) and fits in the
+ * range of a gint32, return it, and if @valid is not %NULL, set *@valid to
+ * %TRUE.
+ *
+ * Otherwise, return 0, and if @valid is not %NULL, set *@valid to %FALSE.
+ *
+ * Returns: the 32-bit signed integer value of @key, or 0
+ * Since: 0.UNRELEASED
+ */
+IMPLEMENT (int32)
+
+/**
+ * tp_vardict_get_int64:
+ * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
+ * @key: The key to look up
+ * @valid: (out): Either %NULL, or a location in which to store %TRUE on success
+ * or %FALSE on failure
+ *
+ * If a value for @key in @variant is present, has an integer type used by
+ * GVariant (gint32, guint32, gint64 or guint64) and fits in the
+ * range of a gint64, return it, and if @valid is not %NULL, set *@valid to
+ * %TRUE.
+ *
+ * Otherwise, return 0, and if @valid is not %NULL, set *@valid to %FALSE.
+ *
+ * Returns: the 64-bit signed integer value of @key, or 0
+ * Since: 0.UNRELEASED
+ */
+IMPLEMENT (int64)
+
+/**
+ * tp_vardict_get_uint32:
+ * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
+ * @key: The key to look up
+ * @valid: (out): Either %NULL, or a location in which to store %TRUE on success
+ * or %FALSE on failure
+ *
+ * If a value for @key in @variant is present, has an integer type used by
+ * GVariant (gint32, guint32, gint64 or guint64) and fits in the
+ * range of a guint32, return it, and if @valid is not %NULL, set *@valid to
+ * %TRUE.
+ *
+ * Otherwise, return 0, and if @valid is not %NULL, set *@valid to %FALSE.
+ *
+ * Returns: the 32-bit unsigned integer value of @key, or 0
+ * Since: 0.UNRELEASED
+ */
+IMPLEMENT (uint32)
+
+/**
+ * tp_vardict_get_uint64:
+ * @variant: a #GVariant of type %G_VARIANT_TYPE_VARDICT
+ * @key: The key to look up
+ * @valid: (out): Either %NULL, or a location in which to store %TRUE on success
+ * or %FALSE on failure
+ *
+ * If a value for @key in @variant is present, has an integer type used by
+ * GVariant (gint32, guint32, gint64 or guint64) and is non-negative,
+ * return it, and if @valid is not %NULL, set *@valid to %TRUE.
+ *
+ * Otherwise, return 0, and if @valid is not %NULL, set *@valid to %FALSE.
+ *
+ * Returns: the 64-bit unsigned integer value of @key, or 0
+ * Since: 0.UNRELEASED
+ */
+IMPLEMENT (uint64)
+
+#undef IMPLEMENT
diff --git a/telepathy-glib/variant-util.h b/telepathy-glib/variant-util.h
index 6f1321874..55124d444 100644
--- a/telepathy-glib/variant-util.h
+++ b/telepathy-glib/variant-util.h
@@ -30,6 +30,33 @@
G_BEGIN_DECLS
+GVariantClass tp_variant_type_classify (const GVariantType *type);
+
+GVariant *tp_variant_convert (GVariant *variant,
+ const GVariantType *type);
+
+const gchar *tp_vardict_get_string (GVariant *variant,
+ const gchar *key);
+const gchar *tp_vardict_get_object_path (GVariant *variant,
+ const gchar *key);
+gboolean tp_vardict_get_boolean (GVariant *variant,
+ const gchar *key,
+ gboolean *valid);
+gdouble tp_vardict_get_double (GVariant *variant,
+ const gchar *key,
+ gboolean *valid);
+gint32 tp_vardict_get_int32 (GVariant *variant,
+ const gchar *key,
+ gboolean *valid);
+gint64 tp_vardict_get_int64 (GVariant *variant,
+ const gchar *key,
+ gboolean *valid);
+guint32 tp_vardict_get_uint32 (GVariant *variant,
+ const gchar *key,
+ gboolean *valid);
+guint64 tp_vardict_get_uint64 (GVariant *variant,
+ const gchar *key,
+ gboolean *valid);
G_END_DECLS