[glib/gdbus] Work some more on C object mapping
- From: David Zeuthen <davidz src gnome org>
- To: svn-commits-list gnome org
- Subject: [glib/gdbus] Work some more on C object mapping
- Date: Sat, 25 Apr 2009 23:21:27 -0400 (EDT)
commit 909821bd1c5475ffcf5c9123f97fc7b88bdbb3aa
Author: David Zeuthen <davidz redhat com>
Date: Sat Apr 25 23:16:05 2009 -0400
Work some more on C object mapping
---
docs/reference/gdbus/gdbus-docs.xml | 2 +
docs/reference/gdbus/gdbus-sections.txt | 122 ++
docs/reference/gdbus/gdbus.types | 2 +
gdbus/Makefile.am | 4 +
gdbus/gdbus.h | 2 +
gdbus/gdbus.symbols | 108 ++-
gdbus/gdbusprivate.c | 504 +++++++++
gdbus/gdbusprivate.h | 59 +-
gdbus/gdbusproxy.c | 1871 +++++++++++++++++++++++++++----
gdbus/gdbusproxy.h | 81 +-
gdbus/gdbusstructure.c | 457 ++++++++
gdbus/gdbusstructure.h | 101 ++
gdbus/gdbustypes.h | 2 +
gdbus/gdbusvariant.c | 1575 ++++++++++++++++++++++++++
gdbus/gdbusvariant.h | 201 ++++
gdbus/tests/proxy.c | 784 +++++++++++++-
gdbus/tests/sessionbus.c | 7 +
gdbus/tests/testserver.py | 366 ++-----
18 files changed, 5705 insertions(+), 543 deletions(-)
diff --git a/docs/reference/gdbus/gdbus-docs.xml b/docs/reference/gdbus/gdbus-docs.xml
index 0d31e06..860073f 100644
--- a/docs/reference/gdbus/gdbus-docs.xml
+++ b/docs/reference/gdbus/gdbus-docs.xml
@@ -32,6 +32,8 @@
<chapter id="cmapping">
<title>C Object Mapping</title>
<xi:include href="xml/gdbusproxy.xml"/>
+ <xi:include href="xml/gdbusvariant.xml"/>
+ <xi:include href="xml/gdbusstructure.xml"/>
</chapter>
</part>
diff --git a/docs/reference/gdbus/gdbus-sections.txt b/docs/reference/gdbus/gdbus-sections.txt
index 18fbc4b..a4b9ead 100644
--- a/docs/reference/gdbus/gdbus-sections.txt
+++ b/docs/reference/gdbus/gdbus-sections.txt
@@ -118,13 +118,18 @@ g_bus_unown_name
GDBusProxy
GDBusProxyClass
g_dbus_proxy_new
+g_dbus_proxy_new_finish
g_dbus_proxy_get_connection
g_dbus_proxy_get_interface_name
g_dbus_proxy_get_name
g_dbus_proxy_get_object_path
+g_dbus_proxy_get_cached_property
+g_dbus_proxy_set_cached_property
g_dbus_proxy_invoke_method
g_dbus_proxy_invoke_method_finish
g_dbus_proxy_invoke_method_sync
+g_dbus_proxy_get_properties_loaded
+g_dbus_proxy_block_for_properties
<SUBSECTION Standard>
G_DBUS_PROXY
G_IS_DBUS_PROXY
@@ -135,3 +140,120 @@ G_IS_DBUS_PROXY_CLASS
G_DBUS_PROXY_GET_CLASS
</SECTION>
+<SECTION>
+<FILE>gdbusstructure</FILE>
+<TITLE>GDBusStructure</TITLE>
+GDBusStructure
+GDBusStructureClass
+g_dbus_structure_new
+g_dbus_structure_equal
+g_dbus_structure_get_element
+g_dbus_structure_set_element
+g_dbus_structure_get_num_elements
+g_dbus_structure_get_signature
+g_dbus_structure_get_signature_for_element
+<SUBSECTION Standard>
+G_DBUS_STRUCTURE
+G_IS_DBUS_STRUCTURE
+G_TYPE_DBUS_STRUCTURE
+g_dbus_structure_get_type
+G_DBUS_STRUCTURE_CLASS
+G_IS_DBUS_STRUCTURE_CLASS
+G_DBUS_STRUCTURE_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gdbusvariant</FILE>
+<TITLE>GDBusVariant</TITLE>
+GDBusVariant
+GDBusVariantClass
+g_dbus_variant_new
+g_dbus_variant_equal
+g_dbus_variant_get_variant_signature
+g_dbus_variant_new_for_string
+g_dbus_variant_new_for_byte
+g_dbus_variant_new_for_boolean
+g_dbus_variant_new_for_int16
+g_dbus_variant_new_for_uint16
+g_dbus_variant_new_for_int
+g_dbus_variant_new_for_uint
+g_dbus_variant_new_for_int64
+g_dbus_variant_new_for_uint64
+g_dbus_variant_new_for_double
+g_dbus_variant_new_for_array
+g_dbus_variant_new_for_ptr_array
+g_dbus_variant_new_for_hash_table
+g_dbus_variant_new_for_structure
+g_dbus_variant_new_for_string_array
+g_dbus_variant_new_for_object_path
+g_dbus_variant_new_for_object_path_array
+g_dbus_variant_new_for_signature
+g_dbus_variant_new_for_signature_array
+g_dbus_variant_get_string
+g_dbus_variant_get_byte
+g_dbus_variant_get_boolean
+g_dbus_variant_get_int16
+g_dbus_variant_get_int
+g_dbus_variant_get_uint
+g_dbus_variant_get_uint16
+g_dbus_variant_get_int64
+g_dbus_variant_get_uint64
+g_dbus_variant_get_double
+g_dbus_variant_get_array
+g_dbus_variant_get_ptr_array
+g_dbus_variant_get_hash_table
+g_dbus_variant_get_structure
+g_dbus_variant_get_string_array
+g_dbus_variant_get_object_path
+g_dbus_variant_get_object_path_array
+g_dbus_variant_get_signature
+g_dbus_variant_get_signature_array
+g_dbus_variant_set_string
+g_dbus_variant_set_byte
+g_dbus_variant_set_boolean
+g_dbus_variant_set_int16
+g_dbus_variant_set_uint16
+g_dbus_variant_set_int
+g_dbus_variant_set_uint
+g_dbus_variant_set_int64
+g_dbus_variant_set_uint64
+g_dbus_variant_set_double
+g_dbus_variant_set_array
+g_dbus_variant_set_ptr_array
+g_dbus_variant_set_hash_table
+g_dbus_variant_set_structure
+g_dbus_variant_set_string_array
+g_dbus_variant_set_object_path
+g_dbus_variant_set_object_path_array
+g_dbus_variant_set_signature
+g_dbus_variant_set_signature_array
+g_dbus_variant_is_unset
+g_dbus_variant_is_string
+g_dbus_variant_is_byte
+g_dbus_variant_is_boolean
+g_dbus_variant_is_int16
+g_dbus_variant_is_uint16
+g_dbus_variant_is_int
+g_dbus_variant_is_uint
+g_dbus_variant_is_int64
+g_dbus_variant_is_uint64
+g_dbus_variant_is_double
+g_dbus_variant_is_array
+g_dbus_variant_is_ptr_array
+g_dbus_variant_is_hash_table
+g_dbus_variant_is_structure
+g_dbus_variant_is_string_array
+g_dbus_variant_is_object_path
+g_dbus_variant_is_object_path_array
+g_dbus_variant_is_signature
+g_dbus_variant_is_signature_array
+<SUBSECTION Standard>
+G_DBUS_VARIANT
+G_IS_DBUS_VARIANT
+G_TYPE_DBUS_VARIANT
+g_dbus_variant_get_type
+G_DBUS_VARIANT_CLASS
+G_IS_DBUS_VARIANT_CLASS
+G_DBUS_VARIANT_GET_CLASS
+</SECTION>
+
diff --git a/docs/reference/gdbus/gdbus.types b/docs/reference/gdbus/gdbus.types
index d4f00a6..0545a3a 100644
--- a/docs/reference/gdbus/gdbus.types
+++ b/docs/reference/gdbus/gdbus.types
@@ -5,3 +5,5 @@ g_bus_type_get_type
g_bus_name_owner_flags_get_type
g_dbus_error_get_type
g_dbus_proxy_get_type
+g_dbus_structure_get_type
+g_dbus_variant_get_type
diff --git a/gdbus/Makefile.am b/gdbus/Makefile.am
index bb246f1..5b5964c 100644
--- a/gdbus/Makefile.am
+++ b/gdbus/Makefile.am
@@ -84,6 +84,8 @@ gdbus_headers = \
gdbusnamewatching.h \
gdbusnameowning.h \
gdbusproxy.h \
+ gdbusstructure.h \
+ gdbusvariant.h \
$(NULL)
libgdbus_2_0_la_SOURCES = \
@@ -101,6 +103,8 @@ libgdbus_2_0_la_SOURCES = \
gdbusnameowning.h gdbusnameowning.c \
gdbusprivate.h gdbusprivate.c \
gdbusproxy.h gdbusproxy.c \
+ gdbusstructure.h gdbusstructure.c \
+ gdbusvariant.h gdbusvariant.c \
gdbusalias.h \
gdbusaliasdef.c \
$(NULL)
diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
index d4c2926..65595e4 100644
--- a/gdbus/gdbus.h
+++ b/gdbus/gdbus.h
@@ -35,6 +35,8 @@
#include <gdbus/gdbusnamewatching.h>
#include <gdbus/gdbusnameowning.h>
#include <gdbus/gdbusproxy.h>
+#include <gdbus/gdbusstructure.h>
+#include <gdbus/gdbusvariant.h>
#undef __G_DBUS_D_DBUS_H_INSIDE__
diff --git a/gdbus/gdbus.symbols b/gdbus/gdbus.symbols
index 90835c7..19c6d3b 100644
--- a/gdbus/gdbus.symbols
+++ b/gdbus/gdbus.symbols
@@ -37,6 +37,7 @@ g_dbus_connection_send_dbus_1_message_cancel
#if IN_HEADER(__G_BUS_NAME_OWNER_H__)
#if IN_FILE(__G_BUS_NAME_OWNER_C__)
+g_bus_name_owner_get_type G_GNUC_CONST
g_bus_name_owner_new
g_bus_name_owner_new_finish
g_bus_name_owner_new_for_connection
@@ -45,12 +46,12 @@ g_bus_name_owner_get_connection
g_bus_name_owner_get_flags
g_bus_name_owner_get_name
g_bus_name_owner_get_owns_name
-g_bus_name_owner_get_type
#endif
#endif
#if IN_HEADER(__G_BUS_NAME_WATCHER_H__)
#if IN_FILE(__G_BUS_NAME_WATCHER_C__)
+g_bus_name_watcher_get_type G_GNUC_CONST
g_bus_name_watcher_new
g_bus_name_watcher_new_finish
g_bus_name_watcher_new_for_connection
@@ -58,7 +59,6 @@ g_bus_name_watcher_new_for_connection_finish
g_bus_name_watcher_get_connection
g_bus_name_watcher_get_name
g_bus_name_watcher_get_name_owner
-g_bus_name_watcher_get_type
#endif
#endif
@@ -116,5 +116,109 @@ g_dbus_proxy_get_object_path
g_dbus_proxy_invoke_method
g_dbus_proxy_invoke_method_finish
g_dbus_proxy_invoke_method_sync
+g_dbus_proxy_block_for_properties
+g_dbus_proxy_get_cached_property
+g_dbus_proxy_get_properties_loaded
+g_dbus_proxy_new_finish
+g_dbus_proxy_set_cached_property
+#endif
+#endif
+
+#if IN_HEADER(__G_DBUS_STRUCTURE_H__)
+#if IN_FILE(__G_DBUS_STRUCTURE_C__)
+g_dbus_structure_get_type G_GNUC_CONST
+g_dbus_structure_equal
+g_dbus_structure_get_element
+g_dbus_structure_get_num_elements
+g_dbus_structure_get_signature
+g_dbus_structure_get_signature_for_element
+g_dbus_structure_new
+g_dbus_structure_set_element
+#endif
+#endif
+
+#if IN_HEADER(__G_DBUS_VARIANT_H__)
+#if IN_FILE(__G_DBUS_VARIANT_C__)
+g_dbus_variant_get_type G_GNUC_CONST
+g_dbus_variant_equal
+g_dbus_variant_get_array
+g_dbus_variant_get_boolean
+g_dbus_variant_get_byte
+g_dbus_variant_get_double
+g_dbus_variant_get_hash_table
+g_dbus_variant_get_int
+g_dbus_variant_get_int16
+g_dbus_variant_get_int64
+g_dbus_variant_get_object_path
+g_dbus_variant_get_object_path_array
+g_dbus_variant_get_ptr_array
+g_dbus_variant_get_signature
+g_dbus_variant_get_signature_array
+g_dbus_variant_get_string
+g_dbus_variant_get_string_array
+g_dbus_variant_get_structure
+g_dbus_variant_get_uint
+g_dbus_variant_get_uint16
+g_dbus_variant_get_uint64
+g_dbus_variant_get_variant_signature
+g_dbus_variant_is_array
+g_dbus_variant_is_boolean
+g_dbus_variant_is_byte
+g_dbus_variant_is_double
+g_dbus_variant_is_hash_table
+g_dbus_variant_is_int
+g_dbus_variant_is_int16
+g_dbus_variant_is_int64
+g_dbus_variant_is_object_path
+g_dbus_variant_is_object_path_array
+g_dbus_variant_is_ptr_array
+g_dbus_variant_is_signature
+g_dbus_variant_is_signature_array
+g_dbus_variant_is_string
+g_dbus_variant_is_string_array
+g_dbus_variant_is_structure
+g_dbus_variant_is_uint
+g_dbus_variant_is_uint16
+g_dbus_variant_is_uint64
+g_dbus_variant_is_unset
+g_dbus_variant_new
+g_dbus_variant_new_for_array
+g_dbus_variant_new_for_boolean
+g_dbus_variant_new_for_byte
+g_dbus_variant_new_for_double
+g_dbus_variant_new_for_hash_table
+g_dbus_variant_new_for_int
+g_dbus_variant_new_for_int16
+g_dbus_variant_new_for_int64
+g_dbus_variant_new_for_object_path
+g_dbus_variant_new_for_object_path_array
+g_dbus_variant_new_for_ptr_array
+g_dbus_variant_new_for_signature
+g_dbus_variant_new_for_signature_array
+g_dbus_variant_new_for_string
+g_dbus_variant_new_for_string_array
+g_dbus_variant_new_for_structure
+g_dbus_variant_new_for_uint
+g_dbus_variant_new_for_uint16
+g_dbus_variant_new_for_uint64
+g_dbus_variant_set_array
+g_dbus_variant_set_boolean
+g_dbus_variant_set_byte
+g_dbus_variant_set_double
+g_dbus_variant_set_hash_table
+g_dbus_variant_set_int
+g_dbus_variant_set_int16
+g_dbus_variant_set_int64
+g_dbus_variant_set_object_path
+g_dbus_variant_set_object_path_array
+g_dbus_variant_set_ptr_array
+g_dbus_variant_set_signature
+g_dbus_variant_set_signature_array
+g_dbus_variant_set_string
+g_dbus_variant_set_string_array
+g_dbus_variant_set_structure
+g_dbus_variant_set_uint
+g_dbus_variant_set_uint16
+g_dbus_variant_set_uint64
#endif
#endif
diff --git a/gdbus/gdbusprivate.c b/gdbus/gdbusprivate.c
index f6e7d75..411e0fd 100644
--- a/gdbus/gdbusprivate.c
+++ b/gdbus/gdbusprivate.c
@@ -23,10 +23,14 @@
#include "config.h"
#include <stdlib.h>
+#include <string.h>
#include <glib/gi18n.h>
#include "gdbustypes.h"
+#include "gdbusprivate.h"
+#include "gdbusvariant.h"
+#include "gdbusstructure.h"
void
_g_dbus_oom (void)
@@ -35,3 +39,503 @@ _g_dbus_oom (void)
g_error ("OOM from libdbus");
abort ();
}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * _gdbus_signature_vararg_foreach:
+ * @signature: A D-Bus signature of zero or more single complete types.
+ * @first_type: First #GType to match up.
+ * @va_args: The value of the first in argument, followed by zero or more (type, value) pairs, followed
+ * by #G_TYPE_INVALID.
+ * @callback: Callback function.
+ * @user_data: User data to pass to @callback.
+ *
+ * Splits up @signature into single complete types, matches each single complete type with
+ * the #GType<!-- -->s and values from @first_type, @va_args and invokes @callback for each
+ * matching pair.
+ *
+ * Returns: %TRUE if @callback short-circuited the matching, %FALSE otherwise.
+ */
+gboolean
+_gdbus_signature_vararg_foreach (const gchar *signature,
+ GType first_type,
+ va_list va_args,
+ _GDBusSignatureVarargForeachCallback callback,
+ gpointer user_data)
+{
+ DBusSignatureIter iter;
+ gchar *element_signature;
+ gboolean ret;
+ GType gtype;
+ guint arg_num;
+
+ g_assert (dbus_signature_validate (signature, NULL));
+
+ ret = FALSE;
+
+ if (strlen (signature) == 0)
+ goto out;
+
+ g_assert (first_type != G_TYPE_INVALID);
+
+ dbus_signature_iter_init (&iter, signature);
+
+ gtype = first_type;
+ arg_num = 0;
+ do
+ {
+ if (arg_num > 0)
+ gtype = va_arg (va_args, GType);
+
+ element_signature = dbus_signature_iter_get_signature (&iter);
+
+ ret = callback (arg_num,
+ element_signature,
+ gtype,
+ va_args,
+ user_data);
+ dbus_free (element_signature);
+
+ if (ret)
+ goto out;
+
+ arg_num++;
+ }
+ while (dbus_signature_iter_next (&iter));
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+gboolean
+_g_strv_equal (gchar **strv1,
+ gchar **strv2)
+{
+ guint n;
+
+ if (strv1 == NULL && strv2 == NULL)
+ return TRUE;
+ if (strv1 == NULL || strv2 == NULL)
+ return FALSE;
+
+ for (n = 0; strv1[n] != NULL && strv2[n] != NULL; n++)
+ {
+ if (g_strcmp0 (strv1[n], strv2[n]) != 0)
+ return FALSE;
+ }
+ if (strv1[n] != NULL || strv2[n] != NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+_g_array_equal (GArray *array1,
+ GArray *array2)
+{
+ if (array1 == NULL && array2 == NULL)
+ return TRUE;
+ if (array1 == NULL || array2 == NULL)
+ return FALSE;
+
+ if (array1->len != array2->len)
+ return FALSE;
+
+ if (array1->len == 0)
+ return TRUE;
+
+ if (g_array_get_element_size (array1) != g_array_get_element_size (array2))
+ return FALSE;
+
+ return memcmp (array1->data, array2->data, g_array_get_element_size (array1) * array1->len) == 0;
+}
+
+static gboolean
+values_equal (gpointer value1,
+ gpointer value2,
+ const gchar *signature)
+{
+ gboolean ret;
+
+ ret = FALSE;
+ switch (signature[0])
+ {
+ case DBUS_TYPE_BYTE:
+ case DBUS_TYPE_BOOLEAN:
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT16:
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT32:
+ ret = (value1 == value2);
+ break;
+
+ case DBUS_TYPE_OBJECT_PATH:
+ case DBUS_TYPE_SIGNATURE:
+ case DBUS_TYPE_STRING:
+ ret = (strcmp (value1, value2) == 0);
+ break;
+
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ ret = (*((const gint64*) value1) == *((const gint64*) value2));
+ break;
+
+ case DBUS_TYPE_DOUBLE:
+ ret = (*((const gdouble*) value1) == *((const gdouble*) value2));
+ break;
+
+ case DBUS_TYPE_VARIANT:
+ ret = g_dbus_variant_equal (value1, value2);
+ break;
+
+ case DBUS_STRUCT_BEGIN_CHAR:
+ ret = g_dbus_structure_equal (value1, value2);
+ break;
+
+ case DBUS_TYPE_ARRAY:
+ switch (signature[1])
+ {
+ case DBUS_TYPE_BYTE:
+ case DBUS_TYPE_BOOLEAN:
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT16:
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT32:
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ case DBUS_TYPE_DOUBLE:
+ ret = _g_array_equal (value1, value2);
+ break;
+
+ case DBUS_TYPE_OBJECT_PATH:
+ case DBUS_TYPE_SIGNATURE:
+ case DBUS_TYPE_STRING:
+ ret = _g_strv_equal (value1, value2);
+ break;
+
+ case DBUS_STRUCT_BEGIN_CHAR:
+ case DBUS_TYPE_VARIANT:
+ ret = _g_ptr_array_equal (value1, value2, signature + 1);
+ break;
+
+ case DBUS_DICT_ENTRY_BEGIN_CHAR:
+ {
+ char key_sig[2];
+ char *val_sig;
+
+ /* keys are guaranteed by the D-Bus spec to be primitive types */
+ key_sig[0] = signature[2];
+ key_sig[1] = '\0';
+ val_sig = g_strdup (signature + 3);
+ val_sig[strlen (val_sig) - 1] = '\0';
+
+ ret = _g_hash_table_equal (value1, value2, key_sig, val_sig);
+ g_free (val_sig);
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return ret;
+}
+
+gboolean
+_g_ptr_array_equal (GPtrArray *array1,
+ GPtrArray *array2,
+ const gchar *element_signature)
+{
+ gboolean ret;
+ guint n;
+
+ if (array1 == NULL && array2 == NULL)
+ return TRUE;
+ if (array1 == NULL || array2 == NULL)
+ return FALSE;
+
+ if (array1->len != array2->len)
+ return FALSE;
+
+ if (array1->len == 0)
+ return TRUE;
+
+ ret = FALSE;
+
+ for (n = 0; n < array1->len; n++)
+ {
+ gpointer value1 = array1->pdata[n];
+ gpointer value2 = array2->pdata[n];
+
+ if (!values_equal (value1, value2, element_signature))
+ goto out;
+
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+gboolean
+_g_hash_table_equal (GHashTable *hash1,
+ GHashTable *hash2,
+ const gchar *key_signature,
+ const gchar *value_signature)
+{
+ gboolean ret;
+ GHashTableIter iter;
+ gpointer key1;
+ gpointer value1;
+ gpointer value2;
+
+ if (hash1 == NULL && hash2 == NULL)
+ return TRUE;
+ if (hash1 == NULL || hash2 == NULL)
+ return FALSE;
+
+ if (g_hash_table_size (hash1) != g_hash_table_size (hash2))
+ return FALSE;
+
+ if (g_hash_table_size (hash1) == 0)
+ return TRUE;
+
+ ret = FALSE;
+
+ g_hash_table_iter_init (&iter, hash1);
+ while (g_hash_table_iter_next (&iter, &key1, &value1))
+ {
+ /* this takes care of comparing the keys (relying on the hashes being set up correctly) */
+ if (!g_hash_table_lookup_extended (hash2, key1, NULL, &value2))
+ goto out;
+
+ if (!values_equal (value1, value2, value_signature))
+ goto out;
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* this equal func only works for GValue instances used by GDBus */
+gboolean
+_g_dbus_gvalue_equal (const GValue *value1,
+ const GValue *value2,
+ const gchar *signature)
+{
+ GType type;
+ gboolean ret;
+
+ if (value1 == NULL && value2 == NULL)
+ return TRUE;
+ if (value1 == NULL || value2 == NULL)
+ return FALSE;
+
+ if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
+ return FALSE;
+
+ ret = FALSE;
+ type = G_VALUE_TYPE (value1);
+ switch (type)
+ {
+ case G_TYPE_UCHAR:
+ ret = (g_value_get_uchar (value1) == g_value_get_uchar (value2));
+ break;
+
+ case G_TYPE_BOOLEAN:
+ ret = (g_value_get_boolean (value1) == g_value_get_boolean (value2));
+ break;
+
+ case G_TYPE_INT: // TODO:16
+ ret = (g_value_get_int (value1) == g_value_get_int (value2));
+ break;
+
+ case G_TYPE_UINT:
+ ret = (g_value_get_uint (value1) == g_value_get_uint (value2));
+ break;
+
+ case G_TYPE_INT64:
+ ret = (g_value_get_int64 (value1) == g_value_get_int64 (value2));
+ break;
+
+ case G_TYPE_UINT64:
+ ret = (g_value_get_uint64 (value1) == g_value_get_uint64 (value2));
+ break;
+
+ case G_TYPE_DOUBLE:
+ ret = (g_value_get_double (value1) == g_value_get_double (value2));
+ break;
+
+ case G_TYPE_STRING: // TODO:o TODO:g
+ ret = (g_strcmp0 (g_value_get_string (value1), g_value_get_string (value2)) == 0);
+ break;
+
+ default:
+ if (type == G_TYPE_STRV) // TODO:ao TODO:ag
+ ret = _g_strv_equal (g_value_get_boxed (value1),
+ g_value_get_boxed (value2));
+ else if (type == G_TYPE_ARRAY)
+ ret = _g_array_equal (g_value_get_boxed (value1),
+ g_value_get_boxed (value2));
+ else if (type == G_TYPE_PTR_ARRAY)
+ ret = _g_ptr_array_equal (g_value_get_boxed (value1),
+ g_value_get_boxed (value2),
+ signature + 1);
+ else if (type == G_TYPE_HASH_TABLE)
+ {
+ char key_sig[2];
+ char *val_sig;
+
+ /* keys are guaranteed by the D-Bus spec to be primitive types */
+ key_sig[0] = signature[2];
+ key_sig[1] = '\0';
+ val_sig = g_strdup (signature + 3);
+ val_sig[strlen (val_sig) - 1] = '\0';
+
+ ret = _g_hash_table_equal (g_value_get_boxed (value1),
+ g_value_get_boxed (value2),
+ key_sig,
+ val_sig);
+ g_free (val_sig);
+ }
+ else if (type == G_TYPE_DBUS_STRUCTURE)
+ {
+ ret = g_dbus_structure_equal (g_value_get_object (value1),
+ g_value_get_object (value2));
+ }
+ else
+ g_assert_not_reached ();
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * _g_dbus_signature_get_gtype:
+ * @signature: A D-Bus signature
+ *
+ * Returns the #GType to use for @signature.
+ *
+ * Returns: A #GType.
+ **/
+GType
+_g_dbus_signature_get_gtype (const gchar *signature)
+{
+ GType ret;
+
+ ret = G_TYPE_INVALID;
+
+ switch (signature[0])
+ {
+ case DBUS_TYPE_BYTE:
+ ret = G_TYPE_UCHAR;
+ break;
+
+ case DBUS_TYPE_BOOLEAN:
+ ret = G_TYPE_BOOLEAN;
+ break;
+
+ case DBUS_TYPE_INT16:
+ ret = G_TYPE_INT; // TODO:16
+ break;
+
+ case DBUS_TYPE_UINT16:
+ ret = G_TYPE_UINT; // TODO:16
+ break;
+
+ case DBUS_TYPE_INT32:
+ ret = G_TYPE_INT;
+ break;
+
+ case DBUS_TYPE_UINT32:
+ ret = G_TYPE_UINT;
+ break;
+
+ case DBUS_TYPE_INT64:
+ ret = G_TYPE_INT64;
+ break;
+
+ case DBUS_TYPE_UINT64:
+ ret = G_TYPE_UINT64;
+ break;
+
+ case DBUS_TYPE_DOUBLE:
+ ret = G_TYPE_DOUBLE;
+ break;
+
+ case DBUS_TYPE_VARIANT:
+ ret = G_TYPE_DBUS_VARIANT;
+ break;
+
+ case DBUS_STRUCT_BEGIN_CHAR:
+ ret = G_TYPE_DBUS_STRUCTURE;
+ break;
+
+ case DBUS_TYPE_OBJECT_PATH: // TODO:o
+ case DBUS_TYPE_SIGNATURE: // TODO:g
+ case DBUS_TYPE_STRING:
+ ret = G_TYPE_STRING;
+ break;
+
+ case DBUS_TYPE_ARRAY:
+ switch (signature[1])
+ {
+ case DBUS_TYPE_BYTE:
+ case DBUS_TYPE_BOOLEAN:
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT16:
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT32:
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ case DBUS_TYPE_DOUBLE:
+ ret = G_TYPE_ARRAY;
+ break;
+
+ case DBUS_TYPE_OBJECT_PATH: // TODO:ao
+ case DBUS_TYPE_SIGNATURE: // TODO:ag
+ case DBUS_TYPE_STRING:
+ ret = G_TYPE_STRV;
+ break;
+
+ case DBUS_STRUCT_BEGIN_CHAR:
+ case DBUS_TYPE_VARIANT:
+ case DBUS_TYPE_ARRAY:
+ ret = G_TYPE_PTR_ARRAY;
+ break;
+
+ case DBUS_DICT_ENTRY_BEGIN_CHAR:
+ ret = G_TYPE_HASH_TABLE;
+ break;
+
+ default:
+ g_warning ("Failed determining GType for D-Bus array with signature '%s'", signature);
+ g_assert_not_reached ();
+ break;
+ }
+ break;
+
+ default:
+ g_warning ("Failed determining GType for D-Bus signature '%s'", signature);
+ g_assert_not_reached ();
+ break;
+ }
+
+ return ret;
+}
diff --git a/gdbus/gdbusprivate.h b/gdbus/gdbusprivate.h
index 90d1278..e3bb462 100644
--- a/gdbus/gdbusprivate.h
+++ b/gdbus/gdbusprivate.h
@@ -28,11 +28,68 @@
#define __G_DBUS_PRIVATE_H__
#include <gdbus/gdbustypes.h>
+#include <stdarg.h>
G_BEGIN_DECLS
void _g_dbus_oom (void);
+/**
+ * _GDBusSignatureVarargForeachCallback:
+ * @arg_num: The argument number currently being processed.
+ * @signature: Signature for single complete D-Bus type.
+ * @type: The #GType corresponding to @signature.
+ * @va_args: A #va_list you can use va_arg() on to extract the value.
+ * @user_data: User data passed to _gdbus_signature_vararg_foreach().
+ *
+ * Callback function used in _gdbus_signature_vararg_foreach().
+ *
+ * Returns: %TRUE to short-circuit iteration, %FALSE to continue iterating.
+ */
+typedef gboolean (*_GDBusSignatureVarargForeachCallback) (guint arg_num,
+ const gchar *signature,
+ GType type,
+ va_list va_args,
+ gpointer user_data);
+
+gboolean _gdbus_signature_vararg_foreach (const gchar *signature,
+ GType first_type,
+ va_list va_args,
+ _GDBusSignatureVarargForeachCallback callback,
+ gpointer user_data);
+
+GDBusStructure *_g_dbus_structure_new_for_values (const gchar *signature,
+ guint num_elements,
+ GValue *elements);
+
+const GValue *_g_dbus_structure_get_gvalue_for_element (GDBusStructure *structure,
+ guint element);
+
+const GValue *_g_dbus_variant_get_gvalue (GDBusVariant *variant);
+
+GDBusVariant *_g_dbus_variant_new_for_gvalue (const GValue *value, const gchar *signature);
+
+gboolean _g_strv_equal (gchar **strv1,
+ gchar **strv2);
+
+gboolean _g_array_equal (GArray *array1,
+ GArray *array2);
+
+gboolean _g_ptr_array_equal (GPtrArray *array1,
+ GPtrArray *array2,
+ const gchar *element_signature);
+
+gboolean _g_hash_table_equal (GHashTable *hash1,
+ GHashTable *hash2,
+ const gchar *key_signature,
+ const gchar *value_signature);
+
+gboolean _g_dbus_gvalue_equal (const GValue *value1,
+ const GValue *value2,
+ const gchar *signature);
+
+GType _g_dbus_signature_get_gtype (const gchar *signature);
+
G_END_DECLS
-#endif /* __G_DBUS_TYPES_H__ */
+#endif /* __G_DBUS_PRIVATE_H__ */
diff --git a/gdbus/gdbusproxy.c b/gdbus/gdbusproxy.c
index fd1d092..4f043c9 100644
--- a/gdbus/gdbusproxy.c
+++ b/gdbus/gdbusproxy.c
@@ -23,23 +23,26 @@
#include "config.h"
#include <stdlib.h>
-
#include <glib/gi18n.h>
+#include <gobject/gvaluecollector.h>
#include "gdbusproxy.h"
#include "gdbusenumtypes.h"
#include "gdbusconnection.h"
#include "gdbuserror.h"
+#include "gdbusstructure.h"
+#include "gdbusvariant.h"
#include "gdbusprivate.h"
#include "gdbusalias.h"
/**
* SECTION:gdbusproxy
- * @short_description: Proxy Class
+ * @short_description: Base class for proxies
* @include: gdbus/gdbus.h
*
- * #GDBusProxy is a...
+ * #GDBusProxy is a base class used for proxies to access a D-Bus
+ * interface on a remote object.
*/
struct _GDBusProxyPrivate
@@ -48,6 +51,9 @@ struct _GDBusProxyPrivate
gchar *name;
gchar *object_path;
gchar *interface_name;
+ gboolean properties_loaded;
+ guint property_loading_pending_call_id;
+ GHashTable *properties;
};
enum
@@ -57,6 +63,7 @@ enum
PROP_G_DBUS_PROXY_NAME,
PROP_G_DBUS_PROXY_OBJECT_PATH,
PROP_G_DBUS_PROXY_INTERFACE_NAME,
+ PROP_G_DBUS_PROXY_PROPERTIES_LOADED,
};
G_DEFINE_TYPE (GDBusProxy, g_dbus_proxy, G_TYPE_OBJECT);
@@ -70,6 +77,8 @@ g_dbus_proxy_finalize (GObject *object)
g_free (proxy->priv->name);
g_free (proxy->priv->object_path);
g_free (proxy->priv->interface_name);
+ if (proxy->priv->properties != NULL)
+ g_hash_table_unref (proxy->priv->properties);
if (G_OBJECT_CLASS (g_dbus_proxy_parent_class)->finalize != NULL)
G_OBJECT_CLASS (g_dbus_proxy_parent_class)->finalize (object);
@@ -101,6 +110,10 @@ g_dbus_proxy_get_property (GObject *object,
g_value_set_string (value, proxy->priv->interface_name);
break;
+ case PROP_G_DBUS_PROXY_PROPERTIES_LOADED:
+ g_value_set_boolean (value, proxy->priv->properties_loaded);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -234,6 +247,22 @@ g_dbus_proxy_class_init (GDBusProxyClass *klass)
G_PARAM_STATIC_BLURB |
G_PARAM_STATIC_NICK));
+ /**
+ * GDBusProxy:g-dbus-proxy-properties-loaded:
+ *
+ * Whether D-Bus properties has been acquired.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_G_DBUS_PROXY_PROPERTIES_LOADED,
+ g_param_spec_boolean ("g-dbus-proxy-properties-loaded",
+ _("g-dbus-proxy-properties-loaded"),
+ _("Whether D-Bus properties has been acquired"),
+ FALSE,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+
g_type_class_add_private (klass, sizeof (GDBusProxyPrivate));
}
@@ -246,14 +275,193 @@ g_dbus_proxy_init (GDBusProxy *proxy)
/* ---------------------------------------------------------------------------------------------------- */
/**
+ * g_dbus_proxy_get_cached_property:
+ * @proxy: A #GDBusProxy.
+ * @property_name: Property name.
+ * @error: Return location for error.
+ *
+ * Looks up the value for a property from the cache. This call does no
+ * blocking IO.
+ *
+ * Returns: A #GDBusVariant that holds the value for @property_name or
+ * %NULL if @error is set. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_proxy_get_cached_property (GDBusProxy *proxy,
+ const gchar *property_name,
+ GError **error)
+{
+ GDBusVariant *variant;
+
+ g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
+ g_return_val_if_fail (property_name != NULL, NULL);
+
+ variant = NULL;
+
+ if (!proxy->priv->properties_loaded)
+ {
+ g_set_error (error,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ _("Properties are not loaded"));
+ goto out;
+ }
+
+ if (proxy->priv->properties == NULL)
+ {
+ g_set_error (error,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ _("Failed loading properties"));
+ goto out;
+ }
+
+ variant = g_hash_table_lookup (proxy->priv->properties, property_name);
+ if (variant == NULL)
+ {
+ g_set_error (error,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ _("No property with name %s"),
+ property_name);
+ goto out;
+ }
+
+ g_object_ref (variant);
+
+ out:
+
+ return variant;
+}
+
+/**
+ * g_dbus_proxy_set_cached_property:
+ * @proxy: A #GDBusProxy.
+ * @property_name: Property name.
+ * @variant: The value to set.
+ * @error: Return location for error.
+ *
+ * Updates the local cache with the value for @property_name. This
+ * call does no blocking IO.
+ *
+ * Returns: %TRUE if the property was updated, %FALSE if @error is set.
+ **/
+gboolean
+g_dbus_proxy_set_cached_property (GDBusProxy *proxy,
+ const gchar *property_name,
+ GDBusVariant *variant,
+ GError **error)
+{
+ GDBusVariant *existing_variant;
+ gboolean ret;
+
+ g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), FALSE);
+ g_return_val_if_fail (property_name != NULL, FALSE);
+ g_return_val_if_fail (variant != NULL, FALSE);
+
+ ret = FALSE;
+
+ if (!proxy->priv->properties_loaded)
+ {
+ g_set_error (error,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ _("Cannot set property %s (properties are not loaded)"),
+ property_name);
+ goto out;
+ }
+
+ if (proxy->priv->properties == NULL)
+ {
+ g_set_error (error,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ _("Cannot set property %s (properties are not loaded and the attempt to load them failed)"),
+ property_name);
+ goto out;
+ }
+
+ existing_variant = g_hash_table_lookup (proxy->priv->properties, property_name);
+ if (existing_variant == NULL)
+ {
+ g_set_error (error,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ _("There is no existing property with name %s"),
+ property_name);
+ goto out;
+ }
+
+ if (g_strcmp0 (g_dbus_variant_get_variant_signature (existing_variant),
+ g_dbus_variant_get_variant_signature (variant)) != 0)
+ {
+ g_set_error (error,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ _("Existing value for property %s has signature %s and value to set has signature %s"),
+ property_name,
+ g_dbus_variant_get_variant_signature (existing_variant),
+ g_dbus_variant_get_variant_signature (variant));
+ goto out;
+ }
+
+ g_hash_table_insert (proxy->priv->properties,
+ g_strdup (property_name),
+ g_object_ref (variant));
+
+ ret = TRUE;
+
+ out:
+
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+get_all_cb (GDBusProxy *proxy,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ GError *error;
+
+ error = NULL;
+ if (!g_dbus_proxy_invoke_method_finish (proxy,
+ "a{sv}",
+ res,
+ &error,
+ G_TYPE_HASH_TABLE, &proxy->priv->properties,
+ G_TYPE_INVALID))
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_error_free (error);
+ proxy->priv->properties = NULL;
+ }
+
+ proxy->priv->properties_loaded = TRUE;
+ proxy->priv->property_loading_pending_call_id = 0;
+ g_object_notify (G_OBJECT (proxy), "g-dbus-proxy-properties-loaded");
+
+ g_simple_async_result_complete (simple);
+}
+
+/**
* g_dbus_proxy_new:
* @connection: A #GDBusConnection.
* @name: A bus name.
* @object_path: An object path.
* @interface_name: A D-Bus interface name.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: The callback function to invoke when finished attempting to load properties or %NULL.
+ * @user_data: User data to pass to @callback.
*
* Creates a proxy for accessing @interface_name on the remote at
- * @object_path owned by @name at @connection.
+ * @object_path owned by @name at @connection and starts loading
+ * the D-Bus properties for the remote object.
+ *
+ * Once the D-Bus properties are loaded, @callback will be invoked
+ * and you can call g_dbus_proxy_new_finish() to check the result.
*
* Returns: A #GDBusProxy. Free with g_object_unref().
**/
@@ -261,11 +469,13 @@ GDBusProxy *
g_dbus_proxy_new (GDBusConnection *connection,
const gchar *name,
const gchar *object_path,
- const gchar *interface_name)
+ const gchar *interface_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
GDBusProxy *proxy;
-
- /* TODO: need to take a GAsyncReadyCallback for when properties are loaded */
+ GSimpleAsyncResult *simple;
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
g_return_val_if_fail (name != NULL, NULL);
@@ -279,8 +489,49 @@ g_dbus_proxy_new (GDBusConnection *connection,
"g-dbus-proxy-interface-name", interface_name,
NULL));
+ simple = g_simple_async_result_new (G_OBJECT (connection),
+ callback,
+ user_data,
+ g_dbus_proxy_new_finish);
+
+ proxy->priv->property_loading_pending_call_id = g_dbus_proxy_invoke_method (proxy,
+ "org.freedesktop.DBus.Properties.GetAll",
+ "s",
+ -1,
+ cancellable,
+ (GAsyncReadyCallback) get_all_cb,
+ simple,
+ G_TYPE_STRING,
+ proxy->priv->interface_name,
+ G_TYPE_INVALID);
+
return proxy;
}
+
+/**
+ * g_dbus_proxy_new_finish:
+ * @proxy: A #GDBusProxy.
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to g_dbus_proxy_new().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes loading properties for @proxy.
+ *
+ * Returns: %TRUE if properties was successfully loaded, otherwise %FALSE with @error set.
+ **/
+gboolean
+g_dbus_proxy_new_finish (GDBusProxy *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), FALSE);
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_dbus_proxy_new_finish);
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+ else
+ return proxy->priv->properties_loaded;
+}
+
/* ---------------------------------------------------------------------------------------------------- */
/**
@@ -343,289 +594,1448 @@ g_dbus_proxy_get_interface_name (GDBusProxy *proxy)
return proxy->priv->interface_name;
}
-/* ---------------------------------------------------------------------------------------------------- */
-
/**
- * ForeachCallback:
- * @signature: Signature for single complete D-Bus type.
- * @type: The #GType corresponding to @signature.
- * @va_args: A #va_list you can use va_arg() on to extract the value.
+ * g_dbus_proxy_get_properties_loaded:
+ * @proxy: A #GDBusProxy.
*
- * Callback function used in foreach_signature_and_gtype().
+ * Gets whether properties has been loaded.
*
- * Returns: %TRUE to short-circuit iteration, %FALSE to continue iterating.
- */
-typedef gboolean (*ForeachCallback) (guint arg_num,
- const gchar *signature,
- GType type,
- va_list va_args,
- gpointer user_data);
+ * To track changes, listen for notifications on the
+ * #GDBusProxy:g-dbus-proxy-properties-loaded property.
+ *
+ * Returns: %TRUE if properties are available, %FALSE otherwise.
+ **/
+gboolean
+g_dbus_proxy_get_properties_loaded (GDBusProxy *proxy)
+{
+ g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), FALSE);
+ return proxy->priv->properties_loaded;
+}
/**
- * foreach_signature_and_gtype:
- * @signature: A D-Bus signature of zero or more single complete types.
- * @first_type: First #GType to match up.
- * @va_args: The value of the first in argument, followed by zero or more (type, value) pairs, followed
- * by #G_TYPE_INVALID.
- * @callback: Callback function.
- * @user_data: User data to pass to @callback.
- *
- * Splits up @signature into single complete types, matches each single complete type with
- * the #GType<!-- -->s and values from @first_type, @va_args and invokes @callback for each
- * matching pair.
+ * g_dbus_proxy_block_for_properties:
+ * @proxy: A #GDBusProxy.
*
- * Returns: %TRUE if @callback short-circuited the matching, %FALSE otherwise.
- */
-static gboolean
-foreach_signature_and_gtype (const gchar *signature,
- GType first_type,
- va_list va_args,
- ForeachCallback callback,
- gpointer user_data)
+ * If the attempt to load properties is done, does nothing. Otherwise blocks (not
+ * in the mainloop), until the attempt to load properties is done.
+ **/
+void
+g_dbus_proxy_block_for_properties (GDBusProxy *proxy)
{
- DBusSignatureIter iter;
- gchar *element_signature;
- gboolean ret;
- GType gtype;
- guint arg_num;
-
- g_assert (dbus_signature_validate (signature, NULL));
+ g_return_if_fail (G_IS_DBUS_PROXY (proxy));
- ret = FALSE;
+ if (G_LIKELY (proxy->priv->properties_loaded))
+ return;
- if (strlen (signature) == 0)
- goto out;
-
- g_assert (first_type != G_TYPE_INVALID);
-
- dbus_signature_iter_init (&iter, signature);
-
- gtype = first_type;
- arg_num = 0;
- do
+ if (proxy->priv->property_loading_pending_call_id != 0)
{
- if (arg_num > 0)
- gtype = va_arg (va_args, GType);
-
- element_signature = dbus_signature_iter_get_signature (&iter);
+ g_dbus_connection_send_dbus_1_message_block (proxy->priv->connection,
+ proxy->priv->property_loading_pending_call_id);
+ }
+}
- ret = callback (arg_num,
- element_signature,
- gtype,
- va_args,
- user_data);
- dbus_free (element_signature);
+/* ---------------------------------------------------------------------------------------------------- */
- if (ret)
- goto out;
+static guint
+get_element_size (gchar dbus_type_code)
+{
+ guint ret;
- arg_num++;
+ switch (dbus_type_code)
+ {
+ case DBUS_TYPE_BYTE:
+ ret = 1;
+ break;
+ case DBUS_TYPE_BOOLEAN:
+ ret = sizeof (gboolean);
+ break;
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT16:
+ ret = sizeof (gint16);
+ break;
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT32:
+ ret = sizeof (gint);
+ break;
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ ret = sizeof (gint64);
+ break;
+ case DBUS_TYPE_DOUBLE:
+ ret = sizeof (gdouble);
+ break;
+ default:
+ g_assert_not_reached ();
}
- while (dbus_signature_iter_next (&iter));
- out:
return ret;
}
-/* ---------------------------------------------------------------------------------------------------- */
-
static gboolean
-append_values_cb (guint arg_num,
- const gchar *signature,
- GType type,
- va_list va_args,
- gpointer user_data)
+get_value_from_iter (DBusMessageIter *iter,
+ GValue *out_value,
+ GError **error)
{
- DBusMessageIter *iter = user_data;
- guchar v_byte;
- dbus_uint16_t v_uint16;
- dbus_uint32_t v_uint32;
- dbus_uint64_t v_uint64;
- gdouble v_double;
- dbus_bool_t v_boolean;
- const gchar *v_string;
+ int arg_type;
+ int array_arg_type;
+ dbus_bool_t bool_val;
+ const char *str_val;
+ guchar uint8_val;
+ dbus_int16_t int16_val;
+ dbus_uint16_t uint16_val;
+ dbus_int32_t int32_val;
+ dbus_uint32_t uint32_val;
+ dbus_int64_t int64_val;
+ dbus_uint64_t uint64_val;
+ double double_val;
+ gboolean ret;
- switch (signature[0])
+ /* TODO: - fill in @error instead of using g_assert_not_reached() */
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (out_value != NULL, FALSE);
+
+ ret = FALSE;
+
+ arg_type = dbus_message_iter_get_arg_type (iter);
+
+ switch (arg_type)
{
- case DBUS_TYPE_BYTE:
- if (type == G_TYPE_UCHAR || type == G_TYPE_CHAR)
- v_byte = va_arg (va_args, guint);
- else
- goto mismatch;
- dbus_message_iter_append_basic (iter, signature[0], &v_byte);
+ case DBUS_TYPE_STRING:
+ g_value_init (out_value, G_TYPE_STRING);
+ dbus_message_iter_get_basic (iter, &str_val);
+ g_value_set_string (out_value, str_val);
+ break;
+
+ case DBUS_TYPE_OBJECT_PATH:
+ g_value_init (out_value, G_TYPE_STRING); // TODO:o
+ dbus_message_iter_get_basic (iter, &str_val);
+ g_value_set_string (out_value, str_val);
+ break;
+
+ case DBUS_TYPE_SIGNATURE:
+ g_value_init (out_value, G_TYPE_STRING); // TODO:g
+ dbus_message_iter_get_basic (iter, &str_val);
+ g_value_set_string (out_value, str_val);
break;
case DBUS_TYPE_BOOLEAN:
- if (type == G_TYPE_BOOLEAN)
- v_boolean = va_arg (va_args, gboolean);
- else
- goto mismatch;
- dbus_message_iter_append_basic (iter, signature[0], &v_boolean);
+ g_value_init (out_value, G_TYPE_BOOLEAN);
+ dbus_message_iter_get_basic (iter, &bool_val);
+ g_value_set_boolean (out_value, bool_val);
+ break;
+
+ case DBUS_TYPE_BYTE:
+ g_value_init (out_value, G_TYPE_UCHAR);
+ dbus_message_iter_get_basic (iter, &uint8_val);
+ g_value_set_uchar (out_value, uint8_val);
break;
case DBUS_TYPE_INT16:
+ g_value_init (out_value, G_TYPE_INT); // TODO:16
+ dbus_message_iter_get_basic (iter, &int16_val);
+ g_value_set_int (out_value, int16_val);
+ break;
+
case DBUS_TYPE_UINT16:
- if (type == G_TYPE_INT || type == G_TYPE_UINT)
- v_uint16 = va_arg (va_args, guint);
- else
- goto mismatch;
- dbus_message_iter_append_basic (iter, signature[0], &v_uint16);
+ g_value_init (out_value, G_TYPE_UINT); // TODO:16
+ dbus_message_iter_get_basic (iter, &uint16_val);
+ g_value_set_uint (out_value, uint16_val);
break;
case DBUS_TYPE_INT32:
+ g_value_init (out_value, G_TYPE_INT);
+ dbus_message_iter_get_basic (iter, &int32_val);
+ g_value_set_int (out_value, int32_val);
+ break;
+
case DBUS_TYPE_UINT32:
- if (type == G_TYPE_INT || type == G_TYPE_UINT)
- v_uint32 = va_arg (va_args, guint);
- else
- goto mismatch;
- dbus_message_iter_append_basic (iter, signature[0], &v_uint32);
+ g_value_init (out_value, G_TYPE_UINT);
+ dbus_message_iter_get_basic (iter, &uint32_val);
+ g_value_set_uint (out_value, uint32_val);
break;
case DBUS_TYPE_INT64:
+ g_value_init (out_value, G_TYPE_INT64);
+ dbus_message_iter_get_basic (iter, &int64_val);
+ g_value_set_int64 (out_value, int64_val);
+ break;
+
case DBUS_TYPE_UINT64:
- if (type == G_TYPE_INT64 || type == G_TYPE_UINT64)
- v_uint64 = va_arg (va_args, guint64);
- else
- goto mismatch;
- dbus_message_iter_append_basic (iter, signature[0], &v_uint64);
+ g_value_init (out_value, G_TYPE_UINT64);
+ dbus_message_iter_get_basic (iter, &uint64_val);
+ g_value_set_uint64 (out_value, uint64_val);
break;
case DBUS_TYPE_DOUBLE:
- if (type == G_TYPE_DOUBLE)
- v_double = va_arg (va_args, gdouble);
- else
- goto mismatch;
- dbus_message_iter_append_basic (iter, signature[0], &v_double);
+ g_value_init (out_value, G_TYPE_DOUBLE);
+ dbus_message_iter_get_basic (iter, &double_val);
+ g_value_set_double (out_value, double_val);
break;
- case DBUS_TYPE_STRING:
- case DBUS_TYPE_OBJECT_PATH:
- case DBUS_TYPE_SIGNATURE:
- if (type == G_TYPE_STRING)
- v_string = (gchar *) va_arg (va_args, gchar*);
+ case DBUS_TYPE_STRUCT:
+ {
+ DBusMessageIter struct_iter;
+ char *struct_signature;
+ GDBusStructure *structure;
+ GArray *a;
+
+ struct_signature = dbus_message_iter_get_signature (iter);
+
+ a = g_array_new (FALSE,
+ TRUE,
+ sizeof (GValue));
+
+ dbus_message_iter_recurse (iter, &struct_iter);
+
+ /* now collect all the elements in the structure as GValue objects */
+ while (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_INVALID)
+ {
+ GValue *value;
+
+ g_array_set_size (a, a->len + 1);
+ value = &g_array_index (a, GValue, a->len - 1);
+
+ /* doing the recursive dance! */
+ if (!get_value_from_iter (&struct_iter, value, error))
+ goto out;
+
+ dbus_message_iter_next (&struct_iter);
+ }
+
+ /* takes ownership of elems */
+ structure = _g_dbus_structure_new_for_values (struct_signature,
+ a->len,
+ (GValue *) a->data);
+ g_assert (structure != NULL);
+
+ g_array_free (a, FALSE);
+
+ g_value_init (out_value, G_TYPE_DBUS_STRUCTURE);
+ g_value_take_object (out_value, structure);
+
+ dbus_free (struct_signature);
+ }
+ break;
+
+ case DBUS_TYPE_ARRAY:
+ array_arg_type = dbus_message_iter_get_element_type (iter);
+ if (array_arg_type == DBUS_TYPE_STRING ||
+ array_arg_type == DBUS_TYPE_OBJECT_PATH ||
+ array_arg_type == DBUS_TYPE_SIGNATURE)
+ {
+ GPtrArray *p;
+ DBusMessageIter array_iter;
+ GType boxed_type;
+
+ if (array_arg_type == DBUS_TYPE_STRING)
+ boxed_type = G_TYPE_STRV;
+ else if (array_arg_type == DBUS_TYPE_OBJECT_PATH)
+ boxed_type = G_TYPE_STRV; // TODO:o EGG_DBUS_TYPE_OBJECT_PATH_ARRAY;
+ else if (array_arg_type == DBUS_TYPE_SIGNATURE)
+ boxed_type = G_TYPE_STRV; // TODO:g EGG_DBUS_TYPE_SIGNATURE_ARRAY;
+ else
+ g_assert_not_reached ();
+
+ dbus_message_iter_recurse (iter, &array_iter);
+ p = g_ptr_array_new ();
+ while (dbus_message_iter_get_arg_type (&array_iter) != DBUS_TYPE_INVALID)
+ {
+ dbus_message_iter_get_basic (&array_iter, &str_val);
+ g_ptr_array_add (p, (void *) g_strdup (str_val));
+ dbus_message_iter_next (&array_iter);
+ }
+ g_ptr_array_add (p, NULL);
+ g_value_init (out_value, boxed_type);
+ g_value_take_boxed (out_value, p->pdata);
+ g_ptr_array_free (p, FALSE);
+ }
+ else if (array_arg_type == DBUS_TYPE_BYTE ||
+ array_arg_type == DBUS_TYPE_INT16 ||
+ array_arg_type == DBUS_TYPE_UINT16 ||
+ array_arg_type == DBUS_TYPE_INT32 ||
+ array_arg_type == DBUS_TYPE_UINT32 ||
+ array_arg_type == DBUS_TYPE_INT64 ||
+ array_arg_type == DBUS_TYPE_UINT64 ||
+ array_arg_type == DBUS_TYPE_BOOLEAN ||
+ array_arg_type == DBUS_TYPE_DOUBLE)
+ {
+ GArray *a;
+ DBusMessageIter array_iter;
+ gconstpointer data;
+ gint num_items;
+
+ dbus_message_iter_recurse (iter, &array_iter);
+ dbus_message_iter_get_fixed_array (&array_iter,
+ &data,
+ (int*) &num_items);
+ a = g_array_sized_new (FALSE, FALSE, get_element_size (array_arg_type), num_items);
+ g_array_append_vals (a, data, num_items);
+ g_value_init (out_value, G_TYPE_ARRAY);
+ g_value_take_boxed (out_value, a);
+ }
+ else if (array_arg_type == DBUS_TYPE_STRUCT)
+ {
+ DBusMessageIter array_iter;
+ char *struct_signature;
+ GPtrArray *p;
+
+ p = g_ptr_array_new_with_free_func (g_object_unref);
+
+ dbus_message_iter_recurse (iter, &array_iter);
+
+ struct_signature = dbus_message_iter_get_signature (&array_iter);
+
+ /* now collect all the elements in the structure.
+ */
+ while (dbus_message_iter_get_arg_type (&array_iter) != DBUS_TYPE_INVALID)
+ {
+ GValue elem_value = {0};
+
+ /* recurse */
+ if (!get_value_from_iter (&array_iter, &elem_value, error))
+ {
+ dbus_free (struct_signature);
+ g_ptr_array_unref (p);
+ goto out;
+ }
+
+ g_ptr_array_add (p, g_value_get_object (&elem_value));
+
+ dbus_message_iter_next (&array_iter);
+ }
+
+ g_value_init (out_value, G_TYPE_PTR_ARRAY);
+ g_value_take_boxed (out_value, p);
+
+ dbus_free (struct_signature);
+ }
+ else if (array_arg_type == DBUS_TYPE_DICT_ENTRY)
+ {
+ DBusMessageIter array_iter;
+ GHashTable *hash;
+ char key_sig[2];
+ char *val_sig;
+ char *array_sig;
+ GHashFunc hash_func;
+ GEqualFunc equal_func;
+ GDestroyNotify key_free_func;
+ GDestroyNotify val_free_func;
+
+ dbus_message_iter_recurse (iter, &array_iter);
+
+ array_sig = dbus_message_iter_get_signature (&array_iter);
+
+ /* keys are guaranteed by the D-Bus spec to be primitive types */
+ key_sig[0] = array_sig[1];
+ key_sig[1] = '\0';
+ val_sig = g_strdup (array_sig + 2);
+ val_sig[strlen (val_sig) - 1] = '\0';
+
+ /* set up the hash table */
+
+ switch (key_sig[0])
+ {
+ case DBUS_TYPE_BOOLEAN:
+ case DBUS_TYPE_BYTE:
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT16:
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT32:
+ key_free_func = NULL;
+ hash_func = g_direct_hash;
+ equal_func = g_direct_equal;
+ break;
+
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ hash_func = g_int64_hash;
+ equal_func = g_int64_equal;
+ key_free_func = g_free;
+ break;
+
+ case DBUS_TYPE_DOUBLE:
+ hash_func = g_double_hash;
+ equal_func = g_double_equal;
+ key_free_func = g_free;
+ break;
+
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH:
+ case DBUS_TYPE_SIGNATURE:
+ hash_func = g_str_hash;
+ equal_func = g_str_equal;
+ key_free_func = g_free;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ switch (val_sig[0])
+ {
+ case DBUS_TYPE_BOOLEAN:
+ case DBUS_TYPE_BYTE:
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT16:
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT32:
+ val_free_func = NULL;
+ break;
+
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ case DBUS_TYPE_DOUBLE:
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH:
+ case DBUS_TYPE_SIGNATURE:
+ val_free_func = g_free;
+ break;
+
+ case DBUS_TYPE_ARRAY:
+ switch (val_sig[1])
+ {
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH:
+ case DBUS_TYPE_SIGNATURE:
+ val_free_func = (GDestroyNotify) g_strfreev;
+ break;
+
+ case DBUS_TYPE_BOOLEAN:
+ case DBUS_TYPE_BYTE:
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT16:
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT32:
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ case DBUS_TYPE_DOUBLE:
+ val_free_func = (GDestroyNotify) g_array_unref;
+ break;
+
+ case DBUS_STRUCT_BEGIN_CHAR:
+ case DBUS_DICT_ENTRY_BEGIN_CHAR:
+ val_free_func = (GDestroyNotify) g_ptr_array_unref;
+ break;
+
+ case DBUS_TYPE_VARIANT:
+ val_free_func = (GDestroyNotify) g_ptr_array_unref;
+ break;
+
+ case DBUS_TYPE_ARRAY:
+ val_free_func = (GDestroyNotify) g_ptr_array_unref;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ break;
+
+ case DBUS_STRUCT_BEGIN_CHAR:
+ val_free_func = g_object_unref;
+ break;
+
+ case DBUS_TYPE_VARIANT:
+ val_free_func = g_object_unref;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ hash = g_hash_table_new_full (hash_func,
+ equal_func,
+ key_free_func,
+ val_free_func);
+
+ while (dbus_message_iter_get_arg_type (&array_iter) != DBUS_TYPE_INVALID)
+ {
+ DBusMessageIter hash_iter;
+ gpointer key, value;
+ const char *str_val;
+
+ dbus_message_iter_recurse (&array_iter, &hash_iter);
+
+ switch (key_sig[0])
+ {
+ case DBUS_TYPE_BOOLEAN:
+ dbus_message_iter_get_basic (&hash_iter, &bool_val);
+ key = GINT_TO_POINTER (bool_val);
+ break;
+
+ case DBUS_TYPE_BYTE:
+ dbus_message_iter_get_basic (&hash_iter, &uint8_val);
+ key = GINT_TO_POINTER (uint8_val);
+ break;
+
+ case DBUS_TYPE_INT16:
+ dbus_message_iter_get_basic (&hash_iter, &int16_val);
+ key = GINT_TO_POINTER (int16_val);
+ break;
+
+ case DBUS_TYPE_UINT16:
+ dbus_message_iter_get_basic (&hash_iter, &uint16_val);
+ key = GINT_TO_POINTER (uint16_val);
+ break;
+
+ case DBUS_TYPE_INT32:
+ dbus_message_iter_get_basic (&hash_iter, &int32_val);
+ key = GINT_TO_POINTER (int32_val);
+ break;
+
+ case DBUS_TYPE_UINT32:
+ dbus_message_iter_get_basic (&hash_iter, &uint32_val);
+ key = GINT_TO_POINTER (uint32_val);
+ break;
+
+ case DBUS_TYPE_INT64:
+ dbus_message_iter_get_basic (&hash_iter, &int64_val);
+ key = g_memdup (&int64_val, sizeof (gint64));
+ break;
+
+ case DBUS_TYPE_UINT64:
+ dbus_message_iter_get_basic (&hash_iter, &uint64_val);
+ key = g_memdup (&uint64_val, sizeof (guint64));
+ break;
+
+ case DBUS_TYPE_DOUBLE:
+ dbus_message_iter_get_basic (&hash_iter, &double_val);
+ key = g_memdup (&double_val, sizeof (gdouble));
+ break;
+
+ case DBUS_TYPE_STRING:
+ dbus_message_iter_get_basic (&hash_iter, &str_val);
+ key = g_strdup (str_val);
+ break;
+
+ case DBUS_TYPE_OBJECT_PATH:
+ dbus_message_iter_get_basic (&hash_iter, &str_val);
+ key = g_strdup (str_val);
+ break;
+
+ case DBUS_TYPE_SIGNATURE:
+ dbus_message_iter_get_basic (&hash_iter, &str_val);
+ key = g_strdup (str_val);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ dbus_message_iter_next (&hash_iter);
+
+ switch (val_sig[0])
+ {
+ case DBUS_TYPE_BOOLEAN:
+ dbus_message_iter_get_basic (&hash_iter, &bool_val);
+ value = GINT_TO_POINTER (bool_val);
+ break;
+
+ case DBUS_TYPE_BYTE:
+ dbus_message_iter_get_basic (&hash_iter, &uint8_val);
+ value = GINT_TO_POINTER (uint8_val);
+ break;
+
+ case DBUS_TYPE_INT16:
+ dbus_message_iter_get_basic (&hash_iter, &int16_val);
+ value = GINT_TO_POINTER (int16_val);
+ break;
+
+ case DBUS_TYPE_UINT16:
+ dbus_message_iter_get_basic (&hash_iter, &uint16_val);
+ value = GINT_TO_POINTER (uint16_val);
+ break;
+
+ case DBUS_TYPE_INT32:
+ dbus_message_iter_get_basic (&hash_iter, &int32_val);
+ value = GINT_TO_POINTER (int32_val);
+ break;
+
+ case DBUS_TYPE_INT64:
+ dbus_message_iter_get_basic (&hash_iter, &int64_val);
+ value = g_memdup (&int64_val, sizeof (gint64));
+ break;
+
+ case DBUS_TYPE_UINT64:
+ dbus_message_iter_get_basic (&hash_iter, &uint64_val);
+ value = g_memdup (&uint64_val, sizeof (guint64));
+ break;
+
+ case DBUS_TYPE_DOUBLE:
+ dbus_message_iter_get_basic (&hash_iter, &double_val);
+ value = g_memdup (&double_val, sizeof (gdouble));
+ break;
+
+ case DBUS_TYPE_UINT32:
+ dbus_message_iter_get_basic (&hash_iter, &uint32_val);
+ value = GINT_TO_POINTER (uint32_val);
+ break;
+
+ case DBUS_TYPE_STRING:
+ dbus_message_iter_get_basic (&hash_iter, &str_val);
+ value = g_strdup (str_val);
+ break;
+
+ case DBUS_TYPE_OBJECT_PATH:
+ dbus_message_iter_get_basic (&hash_iter, &str_val);
+ value = g_strdup (str_val);
+ break;
+
+ case DBUS_TYPE_SIGNATURE:
+ dbus_message_iter_get_basic (&hash_iter, &str_val);
+ value = g_strdup (str_val);
+ break;
+
+ case DBUS_TYPE_ARRAY:
+ {
+ GValue array_val = {0};
+ /* recurse */
+ if (!get_value_from_iter (&hash_iter, &array_val, error))
+ goto out;
+ switch (val_sig[1])
+ {
+ case DBUS_TYPE_BOOLEAN:
+ case DBUS_TYPE_BYTE:
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT16:
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT32:
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ case DBUS_TYPE_DOUBLE:
+ case DBUS_STRUCT_BEGIN_CHAR:
+ case DBUS_DICT_ENTRY_BEGIN_CHAR:
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH:
+ case DBUS_TYPE_SIGNATURE:
+ case DBUS_TYPE_VARIANT:
+ case DBUS_TYPE_ARRAY:
+ value = g_value_get_boxed (&array_val);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case DBUS_STRUCT_BEGIN_CHAR:
+ {
+ GValue object_val = {0};
+ /* recurse */
+ if (!get_value_from_iter (&hash_iter, &object_val, error))
+ goto out;
+ value = g_value_get_object (&object_val);
+ }
+ break;
+
+ case DBUS_TYPE_VARIANT:
+ {
+ GValue object_val = {0};
+ /* recurse */
+ if (!get_value_from_iter (&hash_iter, &object_val, error))
+ goto out;
+ value = g_value_get_object (&object_val);
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ g_hash_table_insert (hash, key, value);
+ dbus_message_iter_next (&array_iter);
+ }
+
+ g_value_init (out_value, G_TYPE_HASH_TABLE);
+ g_value_take_boxed (out_value, hash);
+
+ dbus_free (array_sig);
+ g_free (val_sig);
+
+ }
+ else if (array_arg_type == DBUS_TYPE_ARRAY)
+ {
+ GPtrArray *p;
+ DBusMessageIter array_iter;
+ GDestroyNotify elem_free_func;
+
+ /* handling array of arrays, e.g.
+ *
+ * - aas: GPtrArray of GStrv (gchar **)
+ * - aao: GPtrArray of GStrv (gchar **) TODO:o
+ * - aao: GPtrArray of GStrv (gchar **) TODO:g
+ * - aa{ss}: GPtrArray of GHashTable
+ * - aai: GPtrArray of GArray
+ * - aa(ii): GPtrArray of GPtrArray containg GObject-derived type
+ * - aaas: GPtrArray of GPtrArray of GStrv (gchar **)
+ *
+ */
+
+ dbus_message_iter_recurse (iter, &array_iter);
+
+ elem_free_func = NULL;
+
+ p = g_ptr_array_new ();
+ while (dbus_message_iter_get_arg_type (&array_iter) != DBUS_TYPE_INVALID)
+ {
+ GValue elem_val = {0};
+
+ /* recurse */
+ if (!get_value_from_iter (&array_iter, &elem_val, error))
+ goto out;
+
+ if (G_VALUE_TYPE (&elem_val) == G_TYPE_STRV)
+ {
+ g_ptr_array_add (p, g_value_get_boxed (&elem_val));
+ elem_free_func = (GDestroyNotify) g_strfreev;
+ }
+ else if (G_VALUE_TYPE (&elem_val) == G_TYPE_ARRAY)
+ {
+ g_ptr_array_add (p, g_value_get_boxed (&elem_val));
+ elem_free_func = (GDestroyNotify) g_array_unref;
+ }
+ else if (G_VALUE_TYPE (&elem_val) == G_TYPE_PTR_ARRAY)
+ {
+ g_ptr_array_add (p, g_value_get_boxed (&elem_val));
+ elem_free_func = (GDestroyNotify) g_ptr_array_unref;
+ }
+ else if (G_VALUE_TYPE (&elem_val) == G_TYPE_HASH_TABLE)
+ {
+ g_ptr_array_add (p, g_value_get_boxed (&elem_val));
+ elem_free_func = (GDestroyNotify) g_hash_table_unref;
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+
+ dbus_message_iter_next (&array_iter);
+ } /* for all elements in array */
+ g_ptr_array_set_free_func (p, elem_free_func);
+ g_value_init (out_value, G_TYPE_PTR_ARRAY);
+ g_value_take_boxed (out_value, p);
+ }
+ else if (array_arg_type == DBUS_TYPE_VARIANT)
+ {
+ GPtrArray *p;
+ DBusMessageIter array_iter;
+ char *elem_signature;
+
+ /* array of variants */
+
+ dbus_message_iter_recurse (iter, &array_iter);
+
+ elem_signature = dbus_message_iter_get_signature (&array_iter);
+
+ p = g_ptr_array_new_with_free_func (g_object_unref);
+ while (dbus_message_iter_get_arg_type (&array_iter) != DBUS_TYPE_INVALID)
+ {
+ GValue elem_val = {0};
+
+ /* recurse */
+ if (!get_value_from_iter (&array_iter, &elem_val, error))
+ goto out;
+
+ g_ptr_array_add (p, g_value_get_object (&elem_val));
+
+ dbus_message_iter_next (&array_iter);
+ } /* for all elements in array */
+
+ g_value_init (out_value, G_TYPE_PTR_ARRAY);
+ g_value_take_boxed (out_value, p);
+
+ dbus_free (elem_signature);
+ }
else
- goto mismatch;
- dbus_message_iter_append_basic (iter, signature[0], &v_string);
+ {
+ char *signature;
+ signature = dbus_message_iter_get_signature (iter);
+ g_set_error (error,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ "Cannot decode message with array of signature %s", signature);
+ g_free (signature);
+ goto out;
+ }
+ break;
+
+ case DBUS_TYPE_VARIANT:
+ {
+ GValue variant_val = {0};
+ GDBusVariant *variant;
+ DBusMessageIter variant_iter;
+ gchar *variant_signature;
+
+ dbus_message_iter_recurse (iter, &variant_iter);
+
+ variant_signature = dbus_message_iter_get_signature (&variant_iter);
+
+ /* recurse */
+ if (!get_value_from_iter (&variant_iter, &variant_val, error))
+ goto out;
+
+ variant = _g_dbus_variant_new_for_gvalue (&variant_val, variant_signature);
+
+ g_value_init (out_value, G_TYPE_DBUS_VARIANT);
+ g_value_take_object (out_value, variant);
+
+ dbus_free (variant_signature);
+ }
break;
default:
- g_warning ("Don't know how to append D-Bus type-code %c while processing in-arg %d",
- signature[0],
- arg_num);
- goto error;
+ {
+ char *signature;
+ signature = dbus_message_iter_get_signature (iter);
+ g_set_error (error,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ "Cannot decode message with signature %s", signature);
+ dbus_free (signature);
+ goto out;
+ }
+ break;
}
- return FALSE;
+ ret = TRUE;
+
+ out:
- mismatch:
- g_warning ("D-Bus signature %s and GType %s are not compatible for in-arg %d",
- signature,
- g_type_name (type),
- arg_num);
- error:
- return TRUE;
+ return ret;
}
/* ---------------------------------------------------------------------------------------------------- */
static gboolean
-extract_values_cb (guint arg_num,
- const gchar *signature,
- GType type,
- va_list va_args,
- gpointer user_data)
+append_value_to_iter (DBusMessageIter *iter,
+ const gchar *signature,
+ const GValue *value,
+ GError **error)
{
- DBusMessageIter *iter = user_data;
- guchar v_byte;
- dbus_uint16_t v_uint16;
- dbus_uint32_t v_uint32;
- dbus_uint64_t v_uint64;
- gdouble v_double;
- dbus_bool_t v_boolean;
- const gchar *v_string;
- gpointer p;
+ gboolean ret;
+
+ /* TODO: - fill in @error instead of using g_assert_not_reached()
+ * - validate object paths and signatures (to shield app developers
+ * from getting disconnected from the bus)
+ * - perhaps access GValue directly (trading off safety for performance)
+ */
+
+ //g_debug ("_append_value_to_iter: signature=%s -> value=%s", signature, g_strdup_value_contents (value));
+ ret = FALSE;
+
+ /* TODO: we could probably speed this up by accessing the GValue directly */
switch (signature[0])
{
+ case DBUS_TYPE_STRING:
+ {
+ const char *val = g_value_get_string (value);
+ dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &val);
+ }
+ break;
+
+ case DBUS_TYPE_OBJECT_PATH:
+ {
+ const char *val = g_value_get_string (value); // TODO:o
+ dbus_message_iter_append_basic (iter, DBUS_TYPE_OBJECT_PATH, &val);
+ }
+ break;
+
+ case DBUS_TYPE_SIGNATURE:
+ {
+ const char *val = g_value_get_string (value); // TODO:g
+ dbus_message_iter_append_basic (iter, DBUS_TYPE_SIGNATURE, &val);
+ }
+ break;
+
case DBUS_TYPE_BYTE:
- if (type != G_TYPE_UCHAR && type != G_TYPE_CHAR)
- goto mismatch;
- dbus_message_iter_get_basic (iter, &v_byte);
- p = va_arg (va_args, gpointer);
- *((guchar *) p) = v_byte;
+ {
+ guchar val = g_value_get_uchar (value);
+ dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &val);
+ }
break;
case DBUS_TYPE_BOOLEAN:
- if (type != G_TYPE_BOOLEAN)
- goto mismatch;
- dbus_message_iter_get_basic (iter, &v_boolean);
- p = va_arg (va_args, gpointer);
- *((gboolean *) p) = v_boolean;
+ {
+ dbus_bool_t val = g_value_get_boolean (value);
+ dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &val);
+ }
break;
case DBUS_TYPE_INT16:
+ {
+ dbus_int16_t val = g_value_get_int (value); // TODO:16
+ dbus_message_iter_append_basic (iter, DBUS_TYPE_INT16, &val);
+ }
+ break;
+
case DBUS_TYPE_UINT16:
- if (type != G_TYPE_INT && type != G_TYPE_UINT)
- goto mismatch;
- dbus_message_iter_get_basic (iter, &v_uint16);
- p = va_arg (va_args, gpointer);
- *((guint *) p) = v_uint16;
+ {
+ dbus_uint16_t val = g_value_get_uint (value); // TODO:16
+ dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT16, &val);
+ }
break;
case DBUS_TYPE_INT32:
+ {
+ dbus_int32_t val = g_value_get_int (value);
+ dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &val);
+ }
+ break;
+
case DBUS_TYPE_UINT32:
- if (type != G_TYPE_INT && type != G_TYPE_UINT)
- goto mismatch;
- dbus_message_iter_get_basic (iter, &v_uint32);
- p = va_arg (va_args, gpointer);
- *((guint *) p) = v_uint32;
+ {
+ dbus_uint32_t val;
+ if (value->g_type == G_TYPE_UINT)
+ {
+ val = g_value_get_uint (value);
+ }
+ else if (G_TYPE_IS_ENUM (value->g_type))
+ {
+ val = g_value_get_enum (value);
+ }
+ else if (G_TYPE_IS_FLAGS (value->g_type))
+ {
+ val = g_value_get_flags (value);
+ }
+ dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &val);
+ }
break;
case DBUS_TYPE_INT64:
+ {
+ dbus_int64_t val = g_value_get_int64 (value);
+ dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &val);
+ }
+ break;
+
case DBUS_TYPE_UINT64:
- if (type != G_TYPE_INT64 && type != G_TYPE_UINT64)
- goto mismatch;
- dbus_message_iter_get_basic (iter, &v_uint64);
- p = va_arg (va_args, gpointer);
- *((guint64 *) p) = v_uint64;
+ {
+ dbus_uint64_t val = g_value_get_uint64 (value);
+ dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &val);
+ }
break;
case DBUS_TYPE_DOUBLE:
- if (type != G_TYPE_DOUBLE)
- goto mismatch;
- dbus_message_iter_get_basic (iter, &v_double);
- p = va_arg (va_args, gpointer);
- *((gdouble *) p) = v_double;
+ {
+ double val = g_value_get_double (value);
+ dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &val);
+ }
break;
- case DBUS_TYPE_STRING:
- case DBUS_TYPE_OBJECT_PATH:
- case DBUS_TYPE_SIGNATURE:
- if (type != G_TYPE_STRING)
- goto mismatch;
- dbus_message_iter_get_basic (iter, &v_string);
- p = va_arg (va_args, gpointer);
- *((gchar **) p) = g_strdup (v_string);
+ /* ---------------------------------------------------------------------------------------------------- */
+ case DBUS_TYPE_ARRAY:
+ if (signature[1] == DBUS_TYPE_BYTE ||
+ signature[1] == DBUS_TYPE_INT16 ||
+ signature[1] == DBUS_TYPE_UINT16 ||
+ signature[1] == DBUS_TYPE_INT32 ||
+ signature[1] == DBUS_TYPE_UINT32 ||
+ signature[1] == DBUS_TYPE_INT64 ||
+ signature[1] == DBUS_TYPE_UINT64 ||
+ signature[1] == DBUS_TYPE_DOUBLE ||
+ signature[1] == DBUS_TYPE_BOOLEAN)
+ {
+ DBusMessageIter array_iter;
+ GArray *a;
+
+ a = (GArray *) g_value_get_boxed (value);
+
+ if (a != NULL && a->len > 0 && get_element_size (signature[1]) != g_array_get_element_size (a))
+ {
+ g_set_error (error,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ "GArray has element size %d but element size %d was expected",
+ get_element_size (signature[1]),
+ g_array_get_element_size (a));
+ goto out;
+ }
+
+ dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, signature + 1, &array_iter);
+ dbus_message_iter_append_fixed_array (&array_iter, signature[1], &(a->data), a->len);
+ dbus_message_iter_close_container (iter, &array_iter);
+ }
+ else if (signature[1] == DBUS_TYPE_STRING ||
+ signature[1] == DBUS_TYPE_OBJECT_PATH ||
+ signature[1] == DBUS_TYPE_SIGNATURE)
+ {
+ DBusMessageIter array_iter;
+ gchar **strv;
+ guint n;
+
+ strv = (gchar **) g_value_get_boxed (value);
+ dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, signature + 1, &array_iter);
+ for (n = 0; strv[n] != NULL; n++)
+ dbus_message_iter_append_basic (&array_iter, signature[1], &(strv[n]));
+ dbus_message_iter_close_container (iter, &array_iter);
+ }
+ else if (signature[1] == DBUS_STRUCT_BEGIN_CHAR)
+ {
+ DBusMessageIter array_iter;
+ GPtrArray *p;
+ guint n;
+
+ p = g_value_get_boxed (value);
+ dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, signature + 1, &array_iter);
+ for (n = 0; n < p->len; n++)
+ {
+ GValue val = {0};
+ g_value_init (&val, G_TYPE_DBUS_STRUCTURE);
+ g_value_take_object (&val, G_DBUS_STRUCTURE (p->pdata[n]));
+ /* recursive dance */
+ if (!append_value_to_iter (&array_iter, signature + 1, &val, error))
+ goto out;
+ }
+ dbus_message_iter_close_container (iter, &array_iter);
+ }
+ else if (signature[1] == DBUS_DICT_ENTRY_BEGIN_CHAR)
+ {
+ DBusMessageIter array_iter;
+ GHashTable *hash_table;
+ GHashTableIter hash_iter;
+ gpointer hash_key;
+ gpointer hash_value;
+ char *value_signature;
+
+ value_signature = g_strdup (signature + 3);
+ value_signature[strlen (value_signature) - 1] = '\0';
+
+ hash_table = g_value_get_boxed (value);
+
+ //g_debug ("signature='%s' value_signature='%s'", signature, value_signature);
+
+ dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, signature + 1, &array_iter);
+ g_hash_table_iter_init (&hash_iter, hash_table);
+ while (g_hash_table_iter_next (&hash_iter, &hash_key, &hash_value))
+ {
+ GValue val = {0};
+ DBusMessageIter dict_iter;
+
+ dbus_message_iter_open_container (&array_iter,
+ DBUS_TYPE_DICT_ENTRY,
+ NULL,
+ &dict_iter);
+ switch (signature[2])
+ {
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH:
+ case DBUS_TYPE_SIGNATURE:
+ case DBUS_TYPE_BYTE:
+ case DBUS_TYPE_BOOLEAN:
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT16:
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT32:
+ dbus_message_iter_append_basic (&dict_iter, signature[2], &hash_key);
+ break;
+
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ case DBUS_TYPE_DOUBLE:
+ dbus_message_iter_append_basic (&dict_iter, signature[2], hash_key);
+ break;
+
+ default:
+ /* the D-Bus spec says the hash_key must be a basic type */
+ g_assert_not_reached ();
+ break;
+ }
+
+ //g_debug ("value_signature='%s'", value_signature);
+ switch (value_signature[0])
+ {
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH:
+ case DBUS_TYPE_SIGNATURE:
+ case DBUS_TYPE_BYTE:
+ case DBUS_TYPE_BOOLEAN:
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT16:
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT32:
+ dbus_message_iter_append_basic (&dict_iter, signature[2], &hash_value);
+ break;
+
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ case DBUS_TYPE_DOUBLE:
+ dbus_message_iter_append_basic (&dict_iter, signature[2], hash_value);
+ break;
+
+ case DBUS_STRUCT_BEGIN_CHAR:
+ g_value_init (&val, G_TYPE_DBUS_STRUCTURE);
+ g_value_take_object (&val, G_DBUS_STRUCTURE (hash_value));
+ /* recursive dance */
+ if (!append_value_to_iter (&dict_iter, value_signature, &val, error))
+ goto out;
+ break;
+
+ case DBUS_TYPE_ARRAY:
+ if (value_signature[1] == DBUS_TYPE_BYTE ||
+ value_signature[1] == DBUS_TYPE_INT16 ||
+ value_signature[1] == DBUS_TYPE_UINT16 ||
+ value_signature[1] == DBUS_TYPE_INT32 ||
+ value_signature[1] == DBUS_TYPE_UINT32 ||
+ value_signature[1] == DBUS_TYPE_INT64 ||
+ value_signature[1] == DBUS_TYPE_UINT64 ||
+ value_signature[1] == DBUS_TYPE_BOOLEAN ||
+ value_signature[1] == DBUS_TYPE_DOUBLE)
+ {
+ g_value_init (&val, G_TYPE_ARRAY);
+ g_value_take_boxed (&val, hash_value);
+ /* recurse */
+ if (!append_value_to_iter (&dict_iter, value_signature, &val, error))
+ goto out;
+ }
+ else if (value_signature[1] == DBUS_TYPE_STRING ||
+ value_signature[1] == DBUS_TYPE_OBJECT_PATH ||
+ value_signature[1] == DBUS_TYPE_SIGNATURE)
+ {
+ GType boxed_type;
+
+ if (value_signature[1] == DBUS_TYPE_STRING)
+ boxed_type = G_TYPE_STRV;
+ else if (value_signature[1] == DBUS_TYPE_OBJECT_PATH)
+ boxed_type = G_TYPE_STRV; // TODO:o EGG_DBUS_TYPE_OBJECT_PATH_ARRAY;
+ else if (value_signature[1] == DBUS_TYPE_SIGNATURE)
+ boxed_type = G_TYPE_STRV; // TODO:o EGG_DBUS_TYPE_SIGNATURE_ARRAY;
+ else
+ g_assert_not_reached ();
+
+ g_value_init (&val, boxed_type);
+ g_value_set_static_boxed (&val, hash_value);
+ /* recurse */
+ if (!append_value_to_iter (&dict_iter, value_signature, &val, error))
+ goto out;
+ }
+ else if (value_signature[1] == DBUS_STRUCT_BEGIN_CHAR)
+ {
+ g_value_init (&val, G_TYPE_PTR_ARRAY);
+ g_value_take_boxed (&val, hash_value);
+ /* recurse */
+ if (!append_value_to_iter (&dict_iter, value_signature, &val, error))
+ goto out;
+ }
+ else if (value_signature[1] == DBUS_DICT_ENTRY_BEGIN_CHAR)
+ {
+ g_value_init (&val, G_TYPE_HASH_TABLE);
+ g_value_take_boxed (&val, hash_value);
+ /* recurse */
+ if (!append_value_to_iter (&dict_iter, value_signature, &val, error))
+ goto out;
+ }
+ else if (value_signature[1] == DBUS_TYPE_VARIANT)
+ {
+ g_value_init (&val, G_TYPE_PTR_ARRAY);
+ g_value_take_boxed (&val, hash_value);
+ /* recurse */
+ if (!append_value_to_iter (&dict_iter, value_signature, &val, error))
+ goto out;
+ }
+ else if (value_signature[1] == DBUS_TYPE_ARRAY)
+ {
+ g_value_init (&val, G_TYPE_PTR_ARRAY);
+ g_value_take_boxed (&val, hash_value);
+ /* recurse */
+ if (!append_value_to_iter (&dict_iter, value_signature, &val, error))
+ goto out;
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+ break;
+
+ case DBUS_TYPE_VARIANT:
+ g_value_init (&val, G_TYPE_DBUS_VARIANT);
+ g_value_take_object (&val, hash_value);
+ /* recurse */
+ if (!append_value_to_iter (&dict_iter, value_signature, &val, error))
+ goto out;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ dbus_message_iter_close_container (&array_iter, &dict_iter);
+ }
+ dbus_message_iter_close_container (iter, &array_iter);
+
+ g_free (value_signature);
+ }
+ else if (signature[1] == DBUS_TYPE_ARRAY) /* array of an array */
+ {
+ DBusMessageIter array_iter;
+ GPtrArray *p;
+ guint n;
+
+ p = g_value_get_boxed (value);
+ dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, signature + 1, &array_iter);
+ for (n = 0; n < p->len; n++)
+ {
+ GValue val = {0};
+
+ g_value_init (&val, _g_dbus_signature_get_gtype (signature + 1));
+
+ /* this can either be boxed (for GStrv, GArray) or an object (for e.g. structs, variants) */
+ if (g_type_is_a (G_VALUE_TYPE (&val), G_TYPE_BOXED))
+ g_value_take_boxed (&val, p->pdata[n]);
+ else if (g_type_is_a (G_VALUE_TYPE (&val), G_TYPE_OBJECT))
+ g_value_take_object (&val, p->pdata[n]);
+ else
+ g_assert_not_reached ();
+
+ /* recursive dance */
+ if (!append_value_to_iter (&array_iter, signature + 1, &val, error))
+ goto out;
+ }
+
+ dbus_message_iter_close_container (iter, &array_iter);
+ }
+ else if (signature[1] == DBUS_TYPE_VARIANT ) /* array of variants */
+ {
+ DBusMessageIter array_iter;
+ GPtrArray *p;
+ guint n;
+
+ p = g_value_get_boxed (value);
+ dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, signature + 1, &array_iter);
+ for (n = 0; n < p->len; n++)
+ {
+ GValue val = {0};
+
+ g_value_init (&val, G_TYPE_DBUS_VARIANT);
+ g_value_take_object (&val, p->pdata[n]);
+
+ /* recursive dance */
+ if (!append_value_to_iter (&array_iter, signature + 1, &val, error))
+ goto out;
+ }
+
+ dbus_message_iter_close_container (iter, &array_iter);
+ }
+ else
+ {
+ g_warning ("Don't know append an array with elements with with signature %s", signature + 1);
+ g_assert_not_reached ();
+ }
+ break;
+
+ /* ---------------------------------------------------------------------------------------------------- */
+ case DBUS_STRUCT_BEGIN_CHAR:
+ {
+ DBusMessageIter struct_iter;
+ GDBusStructure *structure;
+ guint n;
+ guint num_elems;
+
+ structure = G_DBUS_STRUCTURE (g_value_get_object (value));
+
+ num_elems = g_dbus_structure_get_num_elements (structure);
+
+ dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, &struct_iter);
+ for (n = 0; n < num_elems; n++)
+ {
+ const GValue *val;
+ const gchar *sig_for_elem;
+
+ val = _g_dbus_structure_get_gvalue_for_element (structure, n);
+ sig_for_elem = g_dbus_structure_get_signature_for_element (structure, n);
+ /* recurse */
+ if (!append_value_to_iter (&struct_iter, sig_for_elem, val, error))
+ goto out;
+ }
+ dbus_message_iter_close_container (iter, &struct_iter);
+ }
+ break;
+
+ /* ---------------------------------------------------------------------------------------------------- */
+ case DBUS_TYPE_VARIANT:
+ {
+ GDBusVariant *variant;
+ DBusMessageIter variant_iter;
+ const gchar *variant_signature;
+ GValue val = {0};
+
+ g_value_init (&val, G_TYPE_DBUS_VARIANT);
+ variant = g_value_get_object (value);
+
+ variant_signature = g_dbus_variant_get_variant_signature (variant);
+
+ dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, variant_signature, &variant_iter);
+ /* recurse */
+ if (!append_value_to_iter (&variant_iter,
+ variant_signature,
+ _g_dbus_variant_get_gvalue (variant),
+ error))
+ goto out;
+ dbus_message_iter_close_container (iter, &variant_iter);
+ }
break;
default:
- g_warning ("Don't know how to extract D-Bus type-code %c for out-arg %d",
- signature[0],
- arg_num);
- goto error;
+ g_warning ("Don't know append a value with signature %s", signature);
+ g_assert_not_reached ();
+ break;
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+extract_values_cb (guint arg_num,
+ const gchar *signature,
+ GType type,
+ va_list va_args,
+ gpointer user_data)
+{
+ DBusMessageIter *iter = user_data;
+ GValue value = {0};
+ GValue value2 = {0};
+ GValue *value_to_extract;
+ GError *error;
+ gboolean ret;
+ gchar *error_str;
+
+ ret = TRUE;
+
+ //g_debug ("arg %d: %s", arg_num, g_type_name (type));
+
+ error = NULL;
+ if (!get_value_from_iter (iter, &value, &error))
+ {
+ g_warning ("Error extracting value for arg %d: %s",
+ arg_num,
+ error->message);
+ g_error_free (error);
+ goto out;
+ }
+ value_to_extract = &value;
+
+ /* coerce if needed */
+ if (!g_type_is_a (type, G_VALUE_TYPE (&value)))
+ {
+ /* try and see if a transformation routine is available */
+ g_value_init (&value2, type);
+ if (!g_value_transform (&value, &value2))
+ {
+ g_warning ("GType '%s' is incompatible with D-Bus signature '%s' (expected GType '%s') "
+ "and no transformation is available",
+ g_type_name (type),
+ signature,
+ g_type_name (G_VALUE_TYPE (&value)));
+ g_value_unset (&value);
+ goto out;
+ }
+ //g_debug ("Transformed from %s to %s", g_type_name (G_VALUE_TYPE (&value)), g_type_name (type));
+ value_to_extract = &value2;
+ g_value_unset (&value);
+ }
+
+ error_str = NULL;
+ G_VALUE_LCOPY (value_to_extract, va_args, G_VALUE_NOCOPY_CONTENTS, &error_str);
+ if (error != NULL)
+ {
+ g_warning ("Error copying value: %s", error_str);
+ g_free (error_str);
+ g_value_unset (value_to_extract);
+ goto out;
}
dbus_message_iter_next (iter);
- return FALSE;
+ ret = FALSE;
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
- mismatch:
- g_warning ("D-Bus signature %s and GType %s are not compatible for out-arg %d",
- signature,
- g_type_name (type),
- arg_num);
- error:
- return TRUE;
+static gboolean
+append_values_cb (guint arg_num,
+ const gchar *signature,
+ GType type,
+ va_list va_args,
+ gpointer user_data)
+{
+ DBusMessageIter *iter = user_data;
+ GValue value = {0};
+ GValue value2 = {0};
+ GValue *value_to_append;
+ GError *error;
+ gboolean ret;
+ gchar *error_str;
+ GType expected_type;
+
+ ret = TRUE;
+
+ //g_debug ("arg %d: %s", arg_num, g_type_name (type));
+
+ g_value_init (&value, type);
+ error_str = NULL;
+ G_VALUE_COLLECT (&value, va_args, G_VALUE_NOCOPY_CONTENTS, &error_str);
+ if (error_str != NULL)
+ {
+ g_warning ("Error collecting value: %s", error_str);
+ g_free (error_str);
+ g_value_unset (&value);
+ goto out;
+ }
+ value_to_append = &value;
+
+ /* coerce if needed */
+ expected_type = _g_dbus_signature_get_gtype (signature);
+ if (!g_type_is_a (type, expected_type))
+ {
+ /* try and see if a transformation routine is available */
+ g_value_init (&value2, expected_type);
+ if (!g_value_transform (&value, &value2))
+ {
+ g_warning ("GType '%s' is incompatible with D-Bus signature '%s' (expected GType '%s') "
+ "and no transformation is available",
+ g_type_name (type),
+ signature,
+ g_type_name (expected_type));
+ g_value_unset (&value);
+ goto out;
+ }
+ //g_debug ("Transformed from %s to %s", g_type_name (type), g_type_name (expected_type));
+ value_to_append = &value2;
+ g_value_unset (&value);
+ }
+
+ error = NULL;
+ if (!append_value_to_iter (iter, signature, value_to_append, &error))
+ {
+ g_warning ("Error appending value for arg %d: %s",
+ arg_num,
+ error->message);
+ g_error_free (error);
+ g_value_unset (value_to_append);
+ goto out;
+ }
+
+ g_value_unset (value_to_append);
+
+ ret = FALSE;
+
+ out:
+ return ret;
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -683,19 +2093,36 @@ g_dbus_proxy_invoke_method_valist (GDBusProxy *proxy,
user_data,
g_dbus_proxy_invoke_method);
- if ((message = dbus_message_new_method_call (proxy->priv->name,
- proxy->priv->object_path,
- proxy->priv->interface_name,
- name)) == NULL)
- _g_dbus_oom ();
+ if (strchr (name, '.'))
+ {
+ gchar *buf;
+ gchar *p;
+ buf = g_strdup (name);
+ p = strrchr (buf, '.');
+ *p = '\0';
+ if ((message = dbus_message_new_method_call (proxy->priv->name,
+ proxy->priv->object_path,
+ buf,
+ p + 1)) == NULL)
+ _g_dbus_oom ();
+ g_free (buf);
+ }
+ else
+ {
+ if ((message = dbus_message_new_method_call (proxy->priv->name,
+ proxy->priv->object_path,
+ proxy->priv->interface_name,
+ name)) == NULL)
+ _g_dbus_oom ();
+ }
/* append args to message */
dbus_message_iter_init_append (message, &iter);
- if (foreach_signature_and_gtype (signature,
- first_in_arg_type,
- va_args,
- append_values_cb,
- &iter))
+ if (_gdbus_signature_vararg_foreach (signature,
+ first_in_arg_type,
+ va_args,
+ append_values_cb,
+ &iter))
goto out;
pending_call_id = g_dbus_connection_send_dbus_1_message_with_reply (proxy->priv->connection,
@@ -747,11 +2174,11 @@ g_dbus_proxy_invoke_method_finish_valist (GDBusProxy *proxy,
/* extract values from message */
dbus_message_iter_init (reply, &reply_iter);
- if (foreach_signature_and_gtype (signature,
- first_out_arg_type,
- va_args,
- extract_values_cb,
- &reply_iter))
+ if (_gdbus_signature_vararg_foreach (signature,
+ first_out_arg_type,
+ va_args,
+ extract_values_cb,
+ &reply_iter))
{
g_set_error (error,
G_DBUS_ERROR,
@@ -783,6 +2210,10 @@ g_dbus_proxy_invoke_method_finish_valist (GDBusProxy *proxy,
* is an asynchronous operation and when the reply is ready @callback will be invoked (on
* the main thread) and you can get the result by calling g_dbus_proxy_invoke_method_finish().
*
+ * If @name contains any dots, then @name is split into interface and
+ * method name parts. This allows using @proxy for invoking methods on
+ * other interfaces.
+ *
* Note that @signature and and the supplied (type, value) pairs must match as described in
* chapter TODO_SECTION_EXPLAINING_DBUS_TO_GTYPE_OBJECT_MAPPING.
*
@@ -885,6 +2316,10 @@ invoke_method_sync_cb (GDBusConnection *connection,
* Synchronously invokes the method @name on the interface and remote
* object represented by @proxy.
*
+ * If @name contains any dots, then @name is split into interface and
+ * method name parts. This allows using @proxy for invoking methods on
+ * other interfaces.
+ *
* Returns: %TRUE if the call succeeded, %FALSE if @error is set.
**/
gboolean
diff --git a/gdbus/gdbusproxy.h b/gdbus/gdbusproxy.h
index 7a56db4..ebe2630 100644
--- a/gdbus/gdbusproxy.h
+++ b/gdbus/gdbusproxy.h
@@ -79,39 +79,54 @@ struct _GDBusProxyClass
void (*_g_reserved8) (void);
};
-GType g_dbus_proxy_get_type (void) G_GNUC_CONST;
-GDBusProxy *g_dbus_proxy_new (GDBusConnection *connection,
- const gchar *name,
- const gchar *object_path,
- const gchar *interface_name);
-GDBusConnection *g_dbus_proxy_get_connection (GDBusProxy *proxy);
-const gchar *g_dbus_proxy_get_name (GDBusProxy *proxy);
-const gchar *g_dbus_proxy_get_object_path (GDBusProxy *proxy);
-const gchar *g_dbus_proxy_get_interface_name (GDBusProxy *proxy);
-guint g_dbus_proxy_invoke_method (GDBusProxy *proxy,
- const gchar *name,
- const gchar *signature,
- guint timeout_msec,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data,
- GType first_in_arg_type,
- ...);
-gboolean g_dbus_proxy_invoke_method_finish (GDBusProxy *proxy,
- const gchar *signature,
- GAsyncResult *res,
- GError **error,
- GType first_out_arg_type,
- ...);
-gboolean g_dbus_proxy_invoke_method_sync (GDBusProxy *proxy,
- const gchar *name,
- const gchar *in_signature,
- const gchar *out_signature,
- guint timeout_msec,
- GCancellable *cancellable,
- GError **error,
- GType first_in_arg_type,
- ...);
+GType g_dbus_proxy_get_type (void) G_GNUC_CONST;
+GDBusProxy *g_dbus_proxy_new (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean g_dbus_proxy_new_finish (GDBusProxy *proxy,
+ GAsyncResult *res,
+ GError **error);
+GDBusConnection *g_dbus_proxy_get_connection (GDBusProxy *proxy);
+const gchar *g_dbus_proxy_get_name (GDBusProxy *proxy);
+const gchar *g_dbus_proxy_get_object_path (GDBusProxy *proxy);
+const gchar *g_dbus_proxy_get_interface_name (GDBusProxy *proxy);
+gboolean g_dbus_proxy_get_properties_loaded (GDBusProxy *proxy);
+void g_dbus_proxy_block_for_properties (GDBusProxy *proxy);
+guint g_dbus_proxy_invoke_method (GDBusProxy *proxy,
+ const gchar *name,
+ const gchar *signature,
+ guint timeout_msec,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ GType first_in_arg_type,
+ ...);
+gboolean g_dbus_proxy_invoke_method_finish (GDBusProxy *proxy,
+ const gchar *signature,
+ GAsyncResult *res,
+ GError **error,
+ GType first_out_arg_type,
+ ...);
+gboolean g_dbus_proxy_invoke_method_sync (GDBusProxy *proxy,
+ const gchar *name,
+ const gchar *in_signature,
+ const gchar *out_signature,
+ guint timeout_msec,
+ GCancellable *cancellable,
+ GError **error,
+ GType first_in_arg_type,
+ ...);
+GDBusVariant *g_dbus_proxy_get_cached_property (GDBusProxy *proxy,
+ const gchar *property_name,
+ GError **error);
+gboolean g_dbus_proxy_set_cached_property (GDBusProxy *proxy,
+ const gchar *property_name,
+ GDBusVariant *variant,
+ GError **error);
G_END_DECLS
diff --git a/gdbus/gdbusstructure.c b/gdbus/gdbusstructure.c
new file mode 100644
index 0000000..02c7dcb
--- /dev/null
+++ b/gdbus/gdbusstructure.c
@@ -0,0 +1,457 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <glib/gi18n.h>
+#include <gobject/gvaluecollector.h>
+
+#include "gdbusstructure.h"
+#include "gdbusenumtypes.h"
+#include "gdbusconnection.h"
+#include "gdbuserror.h"
+#include "gdbusprivate.h"
+
+#include "gdbusalias.h"
+
+/**
+ * SECTION:gdbusstructure
+ * @short_description: Holds a set of values
+ * @include: gdbus/gdbus.h
+ *
+ * #GDBusStructure is a type that holds a D-Bus structure.
+ */
+
+struct _GDBusStructurePrivate
+{
+ gchar *signature;
+ guint num_elements;
+ GValue *elements;
+ gchar **element_signatures;
+};
+
+static gboolean construct_cb (guint arg_num,
+ const gchar *signature,
+ GType type,
+ va_list va_args,
+ gpointer user_data);
+
+G_DEFINE_TYPE (GDBusStructure, g_dbus_structure, G_TYPE_OBJECT);
+
+static void
+g_dbus_structure_finalize (GObject *object)
+{
+ GDBusStructure *structure = G_DBUS_STRUCTURE (object);
+ guint n;
+
+ g_free (structure->priv->signature);
+ for (n = 0; n < structure->priv->num_elements; n++)
+ {
+ g_value_unset (&structure->priv->elements[n]);
+ dbus_free (structure->priv->element_signatures[n]); /* allocated by libdbus */
+ }
+ g_free (structure->priv->element_signatures);
+
+ if (G_OBJECT_CLASS (g_dbus_structure_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (g_dbus_structure_parent_class)->finalize (object);
+}
+
+static void
+g_dbus_structure_class_init (GDBusStructureClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_dbus_structure_finalize;
+
+ /* We avoid using GObject properties since
+ *
+ * - performance is a concern
+ * - this is for the C object mapping only
+ */
+
+ g_type_class_add_private (klass, sizeof (GDBusStructurePrivate));
+}
+
+static void
+g_dbus_structure_init (GDBusStructure *structure)
+{
+ structure->priv = G_TYPE_INSTANCE_GET_PRIVATE (structure, G_TYPE_DBUS_STRUCTURE, GDBusStructurePrivate);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * g_dbus_structure_get_num_elements:
+ * @structure: A #GDBusStructure.
+ *
+ * Gets number of elements in @structure.
+ *
+ * Returns: Number of elements in @structure.
+ **/
+guint
+g_dbus_structure_get_num_elements (GDBusStructure *structure)
+{
+ g_return_val_if_fail (G_IS_DBUS_STRUCTURE (structure), 0);
+ return structure->priv->num_elements;
+}
+
+/**
+ * g_dbus_structure_get_signature:
+ * @structure: A #GDBusStructure.
+ *
+ * Gets the signature for @structure.
+ *
+ * Returns: A D-Bus signature. Do not free this string, it
+ * is owned by @structure.
+ **/
+const gchar *
+g_dbus_structure_get_signature (GDBusStructure *structure)
+{
+ g_return_val_if_fail (G_IS_DBUS_STRUCTURE (structure), NULL);
+ return structure->priv->signature;
+}
+
+/**
+ * g_dbus_structure_get_signature_for_element:
+ * @structure: A #GDBusStructure.
+ * @element: Element number.
+ *
+ * Gets the signature for an @element in @structure.
+ *
+ * Returns: A D-Bus signature. Do not free this string, it
+ * is owned by @structure.
+ **/
+const gchar *
+g_dbus_structure_get_signature_for_element (GDBusStructure *structure,
+ guint element)
+{
+ g_return_val_if_fail (G_IS_DBUS_STRUCTURE (structure), NULL);
+ g_return_val_if_fail (element < structure->priv->num_elements, NULL);
+ return structure->priv->element_signatures[element];
+}
+
+const GValue *
+_g_dbus_structure_get_gvalue_for_element (GDBusStructure *structure,
+ guint element)
+{
+ g_return_val_if_fail (G_IS_DBUS_STRUCTURE (structure), NULL);
+ g_return_val_if_fail (element < structure->priv->num_elements, NULL);
+ return &structure->priv->elements[element];
+}
+
+/**
+ * g_dbus_structure_equal:
+ * @structure1: The first #GDBusStructure.
+ * @structure2: The second #GDBusStructure.
+ *
+ * Checks if @structure1 holds the same types and values as @structure2.
+ *
+ * Returns: %TRUE if @structure1 and @structure2 are equal, %FALSE otherwise.
+ **/
+gboolean
+g_dbus_structure_equal (GDBusStructure *structure1,
+ GDBusStructure *structure2)
+{
+ gboolean ret;
+ guint n;
+
+ g_return_val_if_fail (G_IS_DBUS_STRUCTURE (structure1), FALSE);
+ g_return_val_if_fail (G_IS_DBUS_STRUCTURE (structure2), FALSE);
+
+ if (g_strcmp0 (structure1->priv->signature, structure2->priv->signature) != 0)
+ return FALSE;
+
+ ret = FALSE;
+ for (n = 0; n < structure1->priv->num_elements; n++)
+ {
+ if (!_g_dbus_gvalue_equal (&structure1->priv->elements[n],
+ &structure2->priv->elements[n],
+ structure1->priv->element_signatures[n]))
+ goto out;
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * g_dbus_structure_new:
+ * @signature: The signature of the structure.
+ * @first_element_type: The #GType of the element.
+ * @...: The value of the first element, followed by zero or more (type, value) pairs, followed by #G_TYPE_INVALID.
+ *
+ * Creates a new D-Bus structure with @signature.
+ *
+ * Note that @signature and and the supplied (type, value) pairs must match as described in
+ * chapter TODO_SECTION_EXPLAINING_DBUS_TO_GTYPE_OBJECT_MAPPING.
+ *
+ * Returns: A new #GDBusStructure, free with g_object_unref().
+ **/
+GDBusStructure *
+g_dbus_structure_new (const gchar *signature,
+ GType first_element_type,
+ ...)
+{
+ GDBusStructure *s;
+ va_list va_args;
+ GArray *a;
+ guint n;
+ gchar *signature_with_parenthesis;
+
+ s = NULL;
+ a = g_array_new (FALSE,
+ TRUE,
+ sizeof (GValue));
+
+ signature_with_parenthesis = g_strdup (signature + 1);
+ signature_with_parenthesis[strlen (signature_with_parenthesis) - 1] = '\0';
+
+ va_start (va_args, first_element_type);
+ if (_gdbus_signature_vararg_foreach (signature_with_parenthesis,
+ first_element_type,
+ va_args,
+ construct_cb,
+ a))
+ {
+ for (n = 0; n < a->len; n++)
+ g_value_unset (&(g_array_index (a, GValue, n)));
+ g_array_free (a, TRUE);
+ goto out;
+ }
+
+ s = _g_dbus_structure_new_for_values (signature,
+ a->len,
+ (GValue *) a->data);
+
+ g_array_free (a, FALSE);
+
+ out:
+ va_end (va_args);
+ g_free (signature_with_parenthesis);
+ return s;
+}
+
+static gboolean
+construct_cb (guint arg_num,
+ const gchar *signature,
+ GType type,
+ va_list va_args,
+ gpointer user_data)
+{
+ GArray *a = user_data;
+ GValue *value;
+ gboolean ret;
+ gchar *error_str;
+
+ ret = TRUE;
+
+ g_array_set_size (a, a->len + 1);
+ value = &g_array_index (a, GValue, a->len - 1);
+
+ g_value_init (value, type);
+
+ error_str = NULL;
+ G_VALUE_COLLECT (value, va_args, 0, &error_str);
+ if (error_str != NULL)
+ {
+ g_warning ("Error collecting value: %s", error_str);
+ g_free (error_str);
+ goto error;
+ }
+
+ /* TODO: check if value is compatible with signature */
+
+ //g_debug ("arg_num %d: %s", arg_num, g_strdup_value_contents (value));
+
+ ret = FALSE;
+
+ error:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+GDBusStructure *
+_g_dbus_structure_new_for_values (const gchar *signature,
+ guint num_elements,
+ GValue *elements)
+{
+ GDBusStructure *s;
+ DBusSignatureIter iter;
+ GPtrArray *p;
+ gchar *signature_with_parenthesis;
+
+ s = G_DBUS_STRUCTURE (g_object_new (G_TYPE_DBUS_STRUCTURE, NULL));
+
+ signature_with_parenthesis = g_strdup (signature + 1);
+ signature_with_parenthesis[strlen (signature_with_parenthesis) - 1] = '\0';
+
+ s->priv->signature = g_strdup (signature);
+ s->priv->num_elements = num_elements;
+ s->priv->elements = elements; /* we steal the elements */
+
+ /* TODO: when constructing structures we already parse the signature so maybe use
+ * that to avoid the overhead of parsing it again
+ */
+ p = g_ptr_array_new ();
+ dbus_signature_iter_init (&iter, signature_with_parenthesis);
+ do
+ {
+ g_ptr_array_add (p, dbus_signature_iter_get_signature (&iter));
+ }
+ while (dbus_signature_iter_next (&iter));
+
+ g_assert (num_elements == p->len);
+
+ s->priv->element_signatures = (gchar **) p->pdata;
+
+ g_ptr_array_free (p, FALSE);
+
+ g_free (signature_with_parenthesis);
+
+ return s;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+g_dbus_structure_set_element_valist (GDBusStructure *structure,
+ guint first_element_number,
+ va_list var_args)
+{
+ guint elem_number;
+
+ g_return_if_fail (G_IS_DBUS_STRUCTURE (structure));
+
+ elem_number = first_element_number;
+ while (elem_number != (guint) -1)
+ {
+ gchar *error;
+
+ if (elem_number >= structure->priv->num_elements)
+ {
+ g_warning ("%s: elem number %u is out of bounds", G_STRFUNC, elem_number);
+ break;
+ }
+
+ G_VALUE_COLLECT (&(structure->priv->elements[elem_number]), var_args, 0, &error);
+ if (error != NULL)
+ {
+ g_warning ("%s: %s", G_STRFUNC, error);
+ g_free (error);
+ break;
+ }
+
+ elem_number = va_arg (var_args, guint);
+ }
+}
+
+/**
+ * g_dbus_structure_set_element:
+ * @structure: A #GDBusStructure.
+ * @first_element_number: Element number to set.
+ * @...: First element to set, followed optionally by
+ * more element number / return location pairs, followed by -1.
+ *
+ * Sets element values in a #GDBusStructure. Similar to g_object_set().
+ **/
+void
+g_dbus_structure_set_element (GDBusStructure *structure,
+ guint first_element_number,
+ ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (G_IS_DBUS_STRUCTURE (structure));
+
+ va_start (var_args, first_element_number);
+ g_dbus_structure_set_element_valist (structure, first_element_number, var_args);
+ va_end (var_args);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+g_dbus_structure_get_element_valist (GDBusStructure *structure,
+ guint first_element_number,
+ va_list var_args)
+{
+ guint elem_number;
+
+ g_return_if_fail (G_IS_DBUS_STRUCTURE (structure));
+
+ elem_number = first_element_number;
+ while (elem_number != (guint) -1)
+ {
+ gchar *error;
+
+ if (elem_number >= structure->priv->num_elements)
+ {
+ g_warning ("%s: elem number %u is out of bounds", G_STRFUNC, elem_number);
+ break;
+ }
+
+ G_VALUE_LCOPY (&(structure->priv->elements[elem_number]), var_args, G_VALUE_NOCOPY_CONTENTS, &error);
+ if (error != NULL)
+ {
+ g_warning ("%s: %s", G_STRFUNC, error);
+ g_free (error);
+ break;
+ }
+
+ elem_number = va_arg (var_args, guint);
+ }
+}
+
+/**
+ * g_dbus_structure_get_element:
+ * @structure: A #GDBusStructure.
+ * @first_element_number: Element number to get.
+ * @...: Return location for the first element, followed optionally by
+ * more element number / return location pairs, followed by -1.
+ *
+ * Gets element values in a #GDBusStructure, similar to g_object_get(). The returned
+ * values should not be freed; @structure owns the reference.
+ **/
+void
+g_dbus_structure_get_element (GDBusStructure *structure,
+ guint first_element_number,
+ ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (G_IS_DBUS_STRUCTURE (structure));
+
+ va_start (var_args, first_element_number);
+ g_dbus_structure_get_element_valist (structure, first_element_number, var_args);
+ va_end (var_args);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+#define __G_DBUS_STRUCTURE_C__
+#include "gdbusaliasdef.c"
diff --git a/gdbus/gdbusstructure.h b/gdbus/gdbusstructure.h
new file mode 100644
index 0000000..2978e52
--- /dev/null
+++ b/gdbus/gdbusstructure.h
@@ -0,0 +1,101 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#if !defined (__G_DBUS_G_DBUS_H_INSIDE__) && !defined (G_DBUS_COMPILATION)
+#error "Only <gdbus/gdbus.h> can be included directly."
+#endif
+
+#ifndef __G_DBUS_STRUCTURE_H__
+#define __G_DBUS_STRUCTURE_H__
+
+#include <gdbus/gdbustypes.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_DBUS_STRUCTURE (g_dbus_structure_get_type ())
+#define G_DBUS_STRUCTURE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DBUS_STRUCTURE, GDBusStructure))
+#define G_DBUS_STRUCTURE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DBUS_STRUCTURE, GDBusStructureClass))
+#define G_DBUS_STRUCTURE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DBUS_STRUCTURE, GDBusStructureClass))
+#define G_IS_DBUS_STRUCTURE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DBUS_STRUCTURE))
+#define G_IS_DBUS_STRUCTURE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DBUS_STRUCTURE))
+
+typedef struct _GDBusStructureClass GDBusStructureClass;
+typedef struct _GDBusStructurePrivate GDBusStructurePrivate;
+
+/**
+ * GDBusStructure:
+ *
+ * The #GDBusStructure structure contains only private data and
+ * should only be accessed using the provided API.
+ */
+struct _GDBusStructure
+{
+ /*< private >*/
+ GObject parent_instance;
+ GDBusStructurePrivate *priv;
+};
+
+/**
+ * GDBusStructureClass:
+ *
+ * Class structure for #GDBusStructure.
+ */
+struct _GDBusStructureClass
+{
+ /*< private >*/
+ GObjectClass parent_class;
+
+ /*< public >*/
+
+ /*< private >*/
+ /* Padding for future expansion */
+ void (*_g_reserved1) (void);
+ void (*_g_reserved2) (void);
+ void (*_g_reserved3) (void);
+ void (*_g_reserved4) (void);
+ void (*_g_reserved5) (void);
+ void (*_g_reserved6) (void);
+ void (*_g_reserved7) (void);
+ void (*_g_reserved8) (void);
+};
+
+GType g_dbus_structure_get_type (void) G_GNUC_CONST;
+gboolean g_dbus_structure_equal (GDBusStructure *structure1,
+ GDBusStructure *structure2);
+GDBusStructure *g_dbus_structure_new (const gchar *signature,
+ GType first_element_type,
+ ...);
+const gchar *g_dbus_structure_get_signature (GDBusStructure *structure);
+guint g_dbus_structure_get_num_elements (GDBusStructure *structure);
+const gchar *g_dbus_structure_get_signature_for_element (GDBusStructure *structure,
+ guint element);
+void g_dbus_structure_get_element (GDBusStructure *structure,
+ guint first_element_number,
+ ...);
+void g_dbus_structure_set_element (GDBusStructure *structure,
+ guint first_element_number,
+ ...);
+
+G_END_DECLS
+
+#endif /* __G_DBUS_STRUCTURE_H__ */
diff --git a/gdbus/gdbustypes.h b/gdbus/gdbustypes.h
index f1a4451..8a6d31b 100644
--- a/gdbus/gdbustypes.h
+++ b/gdbus/gdbustypes.h
@@ -35,6 +35,8 @@ typedef struct _GDBusConnection GDBusConnection;
typedef struct _GBusNameOwner GBusNameOwner;
typedef struct _GBusNameWatcher GBusNameWatcher;
typedef struct _GDBusProxy GDBusProxy;
+typedef struct _GDBusStructure GDBusStructure;
+typedef struct _GDBusVariant GDBusVariant;
G_END_DECLS
diff --git a/gdbus/gdbusvariant.c b/gdbus/gdbusvariant.c
new file mode 100644
index 0000000..278a63e
--- /dev/null
+++ b/gdbus/gdbusvariant.c
@@ -0,0 +1,1575 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <glib/gi18n.h>
+#include <gobject/gvaluecollector.h>
+
+#include "gdbusvariant.h"
+#include "gdbusenumtypes.h"
+#include "gdbusconnection.h"
+#include "gdbuserror.h"
+#include "gdbusstructure.h"
+#include "gdbusprivate.h"
+
+#include "gdbusalias.h"
+
+/**
+ * SECTION:gdbusvariant
+ * @short_description: Holds a D-Bus signature and a value
+ * @include: gdbus/gdbus.h
+ *
+ * #GDBusVariant is a polymorphic type that holds a D-Bus signature and a value.
+ */
+
+struct _GDBusVariantPrivate
+{
+ gchar *signature;
+ GValue value;
+};
+
+G_DEFINE_TYPE (GDBusVariant, g_dbus_variant, G_TYPE_OBJECT);
+
+static void
+g_dbus_variant_finalize (GObject *object)
+{
+ GDBusVariant *variant = G_DBUS_VARIANT (object);
+
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_free (variant->priv->signature);
+
+ if (G_OBJECT_CLASS (g_dbus_variant_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (g_dbus_variant_parent_class)->finalize (object);
+}
+
+static void
+g_dbus_variant_class_init (GDBusVariantClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_dbus_variant_finalize;
+
+ /* We avoid using GObject properties since
+ *
+ * - performance is a concern
+ * - this is for the C object mapping only
+ */
+
+ g_type_class_add_private (klass, sizeof (GDBusVariantPrivate));
+}
+
+static void
+g_dbus_variant_init (GDBusVariant *variant)
+{
+ variant->priv = G_TYPE_INSTANCE_GET_PRIVATE (variant, G_TYPE_DBUS_VARIANT, GDBusVariantPrivate);
+}
+
+const GValue *
+_g_dbus_variant_get_gvalue (GDBusVariant *variant)
+{
+ return &variant->priv->value;
+}
+
+/**
+ * g_dbus_variant_get_variant_signature:
+ * @variant: A #GDBusVariant
+ *
+ * Gets the signature for @variant.
+ *
+ * Returns: The signature for @variant or %NULL if @variant is
+ * unset. Do not free this string, it is owned by @variant.
+ **/
+const gchar *
+g_dbus_variant_get_variant_signature (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), NULL);
+ return variant->priv->signature;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * g_dbus_variant_equal:
+ * @variant1: The first #GDBusVariant.
+ * @variant2: The second #GDBusVariant.
+ *
+ * Checks if @variant1 holds the same type and value as @variant2.
+ *
+ * Returns: %TRUE if @variant1 and @variant2 are equal, %FALSE otherwise.
+ **/
+gboolean
+g_dbus_variant_equal (GDBusVariant *variant1,
+ GDBusVariant *variant2)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant1), FALSE);
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant2), FALSE);
+
+ if (g_strcmp0 (variant1->priv->signature, variant2->priv->signature) != 0)
+ return FALSE;
+
+ if (variant1->priv->signature == NULL)
+ return TRUE;
+
+ return _g_dbus_gvalue_equal (&variant1->priv->value,
+ &variant2->priv->value,
+ variant1->priv->signature);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+set_signature (GDBusVariant *variant,
+ const gchar *signature)
+{
+ if (signature == NULL)
+ {
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ variant->priv->signature = NULL;
+ g_free (variant->priv->signature);
+ }
+ else
+ {
+ g_free (variant->priv->signature);
+ variant->priv->signature = g_strdup (signature);
+ }
+}
+
+static void
+set_signature_for_array (GDBusVariant *variant,
+ const gchar *elem_signature)
+{
+ if (elem_signature == NULL)
+ {
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ variant->priv->signature = NULL;
+ g_free (variant->priv->signature);
+ }
+ else
+ {
+ g_free (variant->priv->signature);
+ variant->priv->signature = g_strdup_printf ("a%s", elem_signature);
+ }
+}
+
+static void
+set_signature_for_hash_table (GDBusVariant *variant,
+ const gchar *key_signature,
+ const gchar *value_signature)
+{
+ if (key_signature == NULL || value_signature == NULL)
+ {
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ variant->priv->signature = NULL;
+ g_free (variant->priv->signature);
+ }
+ else
+ {
+ g_free (variant->priv->signature);
+ variant->priv->signature = g_strdup_printf ("a{%s%s}", key_signature, value_signature);
+ }
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * g_dbus_variant_new:
+ *
+ * Creates a new unset variant.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new (void)
+{
+ GDBusVariant *variant;
+ variant = G_DBUS_VARIANT (g_object_new (G_TYPE_DBUS_VARIANT, NULL));
+ return variant;
+}
+
+GDBusVariant *
+_g_dbus_variant_new_for_gvalue (const GValue *value, const gchar *signature)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_value_init (&variant->priv->value, G_VALUE_TYPE (value));
+ g_value_copy (value, &variant->priv->value);
+ set_signature (variant, signature);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_string:
+ * @value: A string.
+ *
+ * Creates a new variant that holds a copy of @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_string (const gchar *value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_string (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_object_path:
+ * @value: An object path.
+ *
+ * Creates a new variant that holds a copy of @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_object_path (const gchar *value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_object_path (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_signature:
+ * @value: A D-Bus signature.
+ *
+ * Creates a new variant that holds a copy of @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_signature (const gchar *value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_signature (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_string_array:
+ * @value: A string array.
+ *
+ * Creates a new variant that holds a copy of @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_string_array (gchar **value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_string_array (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_object_path_array:
+ * @value: An object path array.
+ *
+ * Creates a new variant that holds a copy of @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_object_path_array (gchar **value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_object_path_array (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_signature_array:
+ * @value: A signature array.
+ *
+ * Creates a new variant that holds a copy of @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_signature_array (gchar **value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_signature_array (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_byte:
+ * @value: A #guchar.
+ *
+ * Creates a new variant that holds a #guchar equal to @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_byte (guchar value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_byte (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_int16:
+ * @value: A #gint16.
+ *
+ * Creates a new variant that holds a #gint16 equal to @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_int16 (gint16 value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_int16 (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_uint16:
+ * @value: A #guint16.
+ *
+ * Creates a new variant that holds a #guint16 equal to @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_uint16 (guint16 value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_uint16 (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_int:
+ * @value: A #gint.
+ *
+ * Creates a new variant that holds a #gint equal to @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_int (gint value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_int (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_uint:
+ * @value: A #guint.
+ *
+ * Creates a new variant that holds a #guint equal to @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_uint (guint value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_uint (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_int64:
+ * @value: A #gint64.
+ *
+ * Creates a new variant that holds a #gint64 equal to @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_int64 (gint64 value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_int64 (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_uint64:
+ * @value: A #guint64.
+ *
+ * Creates a new variant that holds a #guint64 equal to @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_uint64 (guint64 value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_uint64 (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_boolean:
+ * @value: A #gboolean.
+ *
+ * Creates a new variant that holds a #gboolean equal to @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_boolean (gboolean value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_boolean (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_double:
+ * @value: A #gdouble.
+ *
+ * Creates a new variant that holds a #gdouble equal to @value.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_double (gdouble value)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_double (variant, value);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_array:
+ * @array: A #GArray.
+ * @element_signature: D-Bus signature of the elements stored in @array.
+ *
+ * Creates a new variant that holds a reference to @array.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_array (GArray *array,
+ const gchar *element_signature)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_array (variant, array, element_signature);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_ptr_array:
+ * @array: A #GPtrArray.
+ * @element_signature: D-Bus signature of the elements stored in @array.
+ *
+ * Creates a new variant that holds a reference to @array.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_ptr_array (GPtrArray *array,
+ const gchar *element_signature)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_ptr_array (variant, array, element_signature);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_hash_table:
+ * @hash_table: A #GHashTable.
+ * @key_signature: D-Bus signature of the keys stored in @hash_table.
+ * @value_signature: D-Bus signature of the values stored in @hash_table.
+ *
+ * Creates a new variant that holds a reference to @hash_table.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_hash_table (GHashTable *hash_table,
+ const gchar *key_signature,
+ const gchar *value_signature)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_hash_table (variant, hash_table, key_signature, value_signature);
+ return variant;
+}
+
+/**
+ * g_dbus_variant_new_for_structure:
+ * @structure: A #GDBusStructure.
+ *
+ * Creates a new variant that holds a reference to @structure.
+ *
+ * Returns: A new #GDBusVariant. Free with g_object_unref().
+ **/
+GDBusVariant *
+g_dbus_variant_new_for_structure (GDBusStructure *structure)
+{
+ GDBusVariant *variant;
+ variant = g_dbus_variant_new ();
+ g_dbus_variant_set_structure (variant, structure);
+ return variant;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * g_dbus_variant_set_string:
+ * @variant: A #GDBusVariant.
+ * @value: A string.
+ *
+ * Makes @variant hold a copy of @value.
+ **/
+void
+g_dbus_variant_set_string (GDBusVariant *variant,
+ const gchar *value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_STRING);
+ g_value_set_string (&variant->priv->value, value);
+ set_signature (variant, "s");
+}
+
+/**
+ * g_dbus_variant_set_object_path:
+ * @variant: A #GDBusVariant.
+ * @value: An object path.
+ *
+ * Makes @variant hold a copy of @value.
+ **/
+void
+g_dbus_variant_set_object_path (GDBusVariant *variant,
+ const gchar *value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_STRING); //TODO:o G_DBUS_TYPE_OBJECT_PATH);
+ g_value_set_string (&variant->priv->value, value);
+ set_signature (variant, "o");
+}
+
+/**
+ * g_dbus_variant_set_signature:
+ * @variant: A #GDBusVariant.
+ * @value: A signature.
+ *
+ * Makes @variant hold a copy of @value.
+ **/
+void
+g_dbus_variant_set_signature (GDBusVariant *variant,
+ const gchar *value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_STRING); //TODO:g G_DBUS_TYPE_OBJECT_PATH);
+ g_value_set_string (&variant->priv->value, value);
+ set_signature (variant, "g");
+}
+
+/**
+ * g_dbus_variant_set_string_array:
+ * @variant: A #GDBusVariant.
+ * @value: A %NULL-terminated string array.
+ *
+ * Makes @variant hold a copy of @value.
+ **/
+void
+g_dbus_variant_set_string_array (GDBusVariant *variant,
+ gchar **value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_STRV);
+ g_value_set_boxed (&variant->priv->value, value);
+ set_signature (variant, "as");
+}
+
+/**
+ * g_dbus_variant_set_object_path_array:
+ * @variant: A #GDBusVariant.
+ * @value: A %NULL-terminated object path array.
+ *
+ * Makes @variant hold a copy of @value.
+ **/
+void
+g_dbus_variant_set_object_path_array (GDBusVariant *variant,
+ gchar **value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_STRV); //TODO:o G_DBUS_TYPE_OBJECT_PATH);
+ g_value_set_boxed (&variant->priv->value, value);
+ set_signature (variant, "ao");
+}
+
+/**
+ * g_dbus_variant_set_signature_array:
+ * @variant: A #GDBusVariant.
+ * @value: A %NULL-terminated signature array.
+ *
+ * Makes @variant hold a copy of @value.
+ **/
+void
+g_dbus_variant_set_signature_array (GDBusVariant *variant,
+ gchar **value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_STRV); //TODO:g G_DBUS_TYPE_SIGNATURE);
+ g_value_set_boxed (&variant->priv->value, value);
+ set_signature (variant, "ag");
+}
+
+/**
+ * g_dbus_variant_set_byte:
+ * @variant: A #GDBusVariant.
+ * @value: A #guchar.
+ *
+ * Makes @variant hold a #guchar equal to @value.
+ **/
+void
+g_dbus_variant_set_byte (GDBusVariant *variant,
+ guchar value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_UCHAR);
+ g_value_set_uchar (&variant->priv->value, value);
+ set_signature (variant, "y");
+}
+
+/**
+ * g_dbus_variant_set_int16:
+ * @variant: A #GDBusVariant.
+ * @value: A #gint16.
+ *
+ * Makes @variant hold a #gint16 equal to @value.
+ **/
+void
+g_dbus_variant_set_int16 (GDBusVariant *variant,
+ gint16 value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_INT); //TODO:16 DBUS_TYPE_INT16);
+ g_value_set_int (&variant->priv->value, value);
+ set_signature (variant, "n");
+}
+
+/**
+ * g_dbus_variant_set_uint16:
+ * @variant: A #GDBusVariant.
+ * @value: A #guint16.
+ *
+ * Makes @variant hold a #guint64 equal to @value.
+ **/
+void
+g_dbus_variant_set_uint16 (GDBusVariant *variant,
+ guint16 value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_UINT); //TODO:16 G_DBUS_TYPE_UINT16);
+ g_value_set_uint (&variant->priv->value, value);
+ set_signature (variant, "q");
+}
+
+/**
+ * g_dbus_variant_set_int:
+ * @variant: A #GDBusVariant.
+ * @value: A #gint.
+ *
+ * Makes @variant hold a #gint equal to @value.
+ **/
+void
+g_dbus_variant_set_int (GDBusVariant *variant,
+ gint value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_INT);
+ g_value_set_int (&variant->priv->value, value);
+ set_signature (variant, "i");
+}
+
+/**
+ * g_dbus_variant_set_uint:
+ * @variant: A #GDBusVariant.
+ * @value: A #guint.
+ *
+ * Makes @variant hold a #guint equal to @value.
+ **/
+void
+g_dbus_variant_set_uint (GDBusVariant *variant,
+ guint value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_UINT);
+ g_value_set_uint (&variant->priv->value, value);
+ set_signature (variant, "u");
+}
+
+/**
+ * g_dbus_variant_set_int64:
+ * @variant: A #GDBusVariant.
+ * @value: A #gint64.
+ *
+ * Makes @variant hold a #gint64 equal to @value.
+ **/
+void
+g_dbus_variant_set_int64 (GDBusVariant *variant,
+ gint64 value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_INT64);
+ g_value_set_int64 (&variant->priv->value, value);
+ set_signature (variant, "x");
+}
+
+/**
+ * g_dbus_variant_set_uint64:
+ * @variant: A #GDBusVariant.
+ * @value: A #guint64.
+ *
+ * Makes @variant hold a #guint64 equal to @value.
+ **/
+void
+g_dbus_variant_set_uint64 (GDBusVariant *variant,
+ guint64 value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_UINT64);
+ g_value_set_uint64 (&variant->priv->value, value);
+ set_signature (variant, "t");
+}
+
+/**
+ * g_dbus_variant_set_boolean:
+ * @variant: A #GDBusVariant.
+ * @value: A #gboolean.
+ *
+ * Makes @variant hold a #gboolean equal to @value.
+ **/
+void
+g_dbus_variant_set_boolean (GDBusVariant *variant,
+ gboolean value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (&variant->priv->value, value);
+ set_signature (variant, "b");
+}
+
+/**
+ * g_dbus_variant_set_double:
+ * @variant: A #GDBusVariant.
+ * @value: A #gdouble.
+ *
+ * Makes @variant hold a #gdouble equal to @value.
+ **/
+void
+g_dbus_variant_set_double (GDBusVariant *variant,
+ gdouble value)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_DOUBLE);
+ g_value_set_double (&variant->priv->value, value);
+ set_signature (variant, "d");
+}
+
+/**
+ * g_dbus_variant_set_array:
+ * @variant: A #GDBusVariant.
+ * @array: A #GArray.
+ * @element_signature: D-Bus signature of the elements stored in @array.
+ *
+ * Makes @variant hold a reference to @array.
+ **/
+void
+g_dbus_variant_set_array (GDBusVariant *variant,
+ GArray *array,
+ const gchar *element_signature)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_ARRAY);
+ g_value_set_boxed (&variant->priv->value, array);
+ set_signature_for_array (variant, element_signature);
+}
+
+/**
+ * g_dbus_variant_set_ptr_array:
+ * @variant: A #GDBusVariant.
+ * @array: A #GPtrArray.
+ * @element_signature: D-Bus signature of the elements stored in @array.
+ *
+ * Makes @variant hold a reference to @array.
+ **/
+void
+g_dbus_variant_set_ptr_array (GDBusVariant *variant,
+ GPtrArray *array,
+ const gchar *element_signature)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_PTR_ARRAY);
+ g_value_set_boxed (&variant->priv->value, array);
+ set_signature_for_array (variant, element_signature);
+}
+
+/**
+ * g_dbus_variant_set_hash_table:
+ * @variant: A #GDBusVariant.
+ * @hash_table: A #GHashTable.
+ * @key_signature: D-Bus signature of the keys stored in @hash_table.
+ * @value_signature: D-Bus signature of the values stored in @hash_table.
+ *
+ * Makes @variant hold a reference to @hash_table.
+ **/
+void
+g_dbus_variant_set_hash_table (GDBusVariant *variant,
+ GHashTable *hash_table,
+ const gchar *key_signature,
+ const gchar *value_signature)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_HASH_TABLE);
+ g_value_set_boxed (&variant->priv->value, hash_table);
+ set_signature_for_hash_table (variant,
+ key_signature,
+ value_signature);
+}
+
+/**
+ * g_dbus_variant_set_structure:
+ * @variant: A #GDBusVariant.
+ * @structure: A #GDBusStructure.
+ *
+ * Makes @variant hold a reference to @structure.
+ **/
+void
+g_dbus_variant_set_structure (GDBusVariant *variant,
+ GDBusStructure *structure)
+{
+ g_return_if_fail (G_IS_DBUS_VARIANT (variant));
+ if (variant->priv->signature != NULL)
+ g_value_unset (&variant->priv->value);
+ g_value_init (&variant->priv->value, G_TYPE_DBUS_STRUCTURE);
+ g_value_set_object (&variant->priv->value, structure);
+ set_signature (variant, g_dbus_structure_get_signature (structure));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * g_dbus_variant_get_string:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the string stored in @variant.
+ *
+ * Returns: A string owned by @variant. Do not free.
+ **/
+const gchar *
+g_dbus_variant_get_string (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_string (variant), NULL);
+ return g_value_get_string (&variant->priv->value);
+}
+
+/**
+ * g_dbus_variant_get_object_path:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the object path stored in @variant.
+ *
+ * Returns: An object path owned by @variant. Do not free.
+ **/
+const gchar *
+g_dbus_variant_get_object_path (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_object_path (variant), NULL);
+ return g_value_get_string (&variant->priv->value); // TODO:o
+}
+
+/**
+ * g_dbus_variant_get_signature:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the signature stored in @variant.
+ *
+ * Returns: A signature owned by @variant. Do not free.
+ **/
+const gchar *
+g_dbus_variant_get_signature (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_signature (variant), NULL);
+ return g_value_get_string (&variant->priv->value); // TODO:g
+}
+
+/**
+ * g_dbus_variant_get_string_array:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the string array stored in @variant.
+ *
+ * Returns: A %NULL-terminated string array signature owned by @variant. Do not free.
+ **/
+gchar **
+g_dbus_variant_get_string_array (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_string_array (variant), NULL);
+ return g_value_get_boxed (&variant->priv->value);
+}
+
+/**
+ * g_dbus_variant_get_object_path_array:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the object path array stored in @variant.
+ *
+ * Returns: A %NULL-terminated object path array owned by @variant. Do not free.
+ **/
+gchar **
+g_dbus_variant_get_object_path_array (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_object_path_array (variant), NULL);
+ return g_value_get_boxed (&variant->priv->value);
+}
+
+/**
+ * g_dbus_variant_get_signature_array:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the signature array stored in @variant.
+ *
+ * Returns: A %NULL-terminated signature array owned by @variant. Do not free.
+ **/
+gchar **
+g_dbus_variant_get_signature_array (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_signature_array (variant), NULL);
+ return g_value_get_boxed (&variant->priv->value);
+}
+
+/**
+ * g_dbus_variant_get_byte:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the #guchar stored in @variant.
+ *
+ * Returns: A #guchar.
+ **/
+guchar
+g_dbus_variant_get_byte (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_byte (variant), 0);
+ return g_value_get_uchar (&variant->priv->value);
+}
+
+/**
+ * g_dbus_variant_get_int16:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the #gint16 stored in @variant.
+ *
+ * Returns: A #gint16.
+ **/
+gint16
+g_dbus_variant_get_int16 (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_int16 (variant), 0);
+ return g_value_get_int (&variant->priv->value); // TODO:16
+}
+
+/**
+ * g_dbus_variant_get_uint16:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the #guint16 stored in @variant.
+ *
+ * Returns: A #guint16.
+ **/
+guint16
+g_dbus_variant_get_uint16 (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_uint16 (variant), 0);
+ return g_value_get_uint (&variant->priv->value); // TODO:16
+}
+
+/**
+ * g_dbus_variant_get_int:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the #gint stored in @variant.
+ *
+ * Returns: A #gint.
+ **/
+gint
+g_dbus_variant_get_int (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_int (variant), 0);
+ return g_value_get_int (&variant->priv->value);
+}
+
+/**
+ * g_dbus_variant_get_uint:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the #guint stored in @variant.
+ *
+ * Returns: A #guint.
+ **/
+guint
+g_dbus_variant_get_uint (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_uint (variant), 0);
+ return g_value_get_uint (&variant->priv->value);
+}
+
+/**
+ * g_dbus_variant_get_int64:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the #gint64 stored in @variant.
+ *
+ * Returns: A #gint64.
+ **/
+gint64
+g_dbus_variant_get_int64 (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_int64 (variant), 0);
+ return g_value_get_int64 (&variant->priv->value);
+}
+
+/**
+ * g_dbus_variant_get_uint64:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the #guint64 stored in @variant.
+ *
+ * Returns: A #guint64.
+ **/
+guint64
+g_dbus_variant_get_uint64 (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_uint64 (variant), 0);
+ return g_value_get_uint64 (&variant->priv->value);
+}
+
+/**
+ * g_dbus_variant_get_boolean:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the #gboolean stored in @variant.
+ *
+ * Returns: A #gboolean.
+ **/
+gboolean
+g_dbus_variant_get_boolean (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_boolean (variant), FALSE);
+ return g_value_get_boolean (&variant->priv->value);
+}
+
+/**
+ * g_dbus_variant_get_double:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the #gdouble stored in @variant.
+ *
+ * Returns: A #gdouble.
+ **/
+gdouble
+g_dbus_variant_get_double (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_double (variant), 0.0);
+ return g_value_get_double (&variant->priv->value);
+}
+
+/**
+ * g_dbus_variant_get_array:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the array stored in @variant.
+ *
+ * Returns: A #GArray owned by @variant. Do not free.
+ **/
+GArray *
+g_dbus_variant_get_array (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_array (variant), NULL);
+ return g_value_get_boxed (&variant->priv->value);
+}
+
+/**
+ * g_dbus_variant_get_ptr_array:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the pointer array stored in @variant.
+ *
+ * Returns: A #GPtrArray owned by @variant. Do not free.
+ **/
+GPtrArray *
+g_dbus_variant_get_ptr_array (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_ptr_array (variant), NULL);
+ return g_value_get_boxed (&variant->priv->value);
+}
+
+/**
+ * g_dbus_variant_get_hash_table:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the hash table stored in @variant.
+ *
+ * Returns: A #GHashTable owned by @variant. Do not free.
+ **/
+GHashTable *
+g_dbus_variant_get_hash_table (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_hash_table (variant), NULL);
+ return g_value_get_boxed (&variant->priv->value);
+}
+
+/**
+ * g_dbus_variant_get_structure:
+ * @variant: A #GDBusVariant.
+ *
+ * Gets the structure stored in @variant.
+ *
+ * Returns: A #GDBusStructure owned by @variant. Do not free.
+ **/
+GDBusStructure *
+g_dbus_variant_get_structure (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant) && g_dbus_variant_is_structure (variant), NULL);
+ return g_value_get_object (&variant->priv->value);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * g_dbus_variant_is_unset:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a value.
+ *
+ * Returns: %TRUE if @variant does not hold a value, %FALSE is @variant holds a value.
+ **/
+gboolean
+g_dbus_variant_is_unset (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return variant->priv->signature != NULL;
+}
+
+/**
+ * g_dbus_variant_is_string:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a string.
+ *
+ * Returns: %TRUE only if @variant holds a string.
+ **/
+gboolean
+g_dbus_variant_is_string (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 's';
+}
+
+/**
+ * g_dbus_variant_is_object_path:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds an object path.
+ *
+ * Returns: %TRUE only if @variant holds an object path.
+ **/
+gboolean
+g_dbus_variant_is_object_path (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'o';
+}
+
+/**
+ * g_dbus_variant_is_signature
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds an signature.
+ *
+ * Returns: %TRUE only if @variant holds an signature.
+ **/
+gboolean
+g_dbus_variant_is_signature (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'g';
+}
+
+/**
+ * g_dbus_variant_is_string_array:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a string array.
+ *
+ * Returns: %TRUE only if @variant holds a string array.
+ **/
+gboolean
+g_dbus_variant_is_string_array (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'a' &&
+ variant->priv->signature[1] == 's';
+}
+
+/**
+ * g_dbus_variant_is_object_path_array:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds an object path array.
+ *
+ * Returns: %TRUE only if @variant holds an object path array.
+ **/
+gboolean
+g_dbus_variant_is_object_path_array (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'a' &&
+ variant->priv->signature[1] == 'o';
+}
+
+/**
+ * g_dbus_variant_is_signature_array:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a signature array.
+ *
+ * Returns: %TRUE only if @variant holds a signature array.
+ **/
+gboolean
+g_dbus_variant_is_signature_array (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'a' &&
+ variant->priv->signature[1] == 'g';
+}
+
+/**
+ * g_dbus_variant_is_byte:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a #guchar.
+ *
+ * Returns: %TRUE only if @variant holds a #guchar.
+ **/
+gboolean
+g_dbus_variant_is_byte (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'y';
+}
+
+/**
+ * g_dbus_variant_is_int16:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a #gint16.
+ *
+ * Returns: %TRUE only if @variant holds a #gint16.
+ **/
+gboolean
+g_dbus_variant_is_int16 (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'n';
+}
+
+/**
+ * g_dbus_variant_is_uint16:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a #guint16.
+ *
+ * Returns: %TRUE only if @variant holds a #guint16.
+ **/
+gboolean
+g_dbus_variant_is_uint16 (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'q';
+}
+
+/**
+ * g_dbus_variant_is_int:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a #gint.
+ *
+ * Returns: %TRUE only if @variant holds a #gint.
+ **/
+gboolean
+g_dbus_variant_is_int (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'i';
+}
+
+/**
+ * g_dbus_variant_is_uint:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a #guint.
+ *
+ * Returns: %TRUE only if @variant holds a #guint.
+ **/
+gboolean
+g_dbus_variant_is_uint (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'u';
+}
+
+/**
+ * g_dbus_variant_is_int64:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a #gint64.
+ *
+ * Returns: %TRUE only if @variant holds a #gint64.
+ **/
+gboolean
+g_dbus_variant_is_int64 (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'x';
+}
+
+/**
+ * g_dbus_variant_is_uint64:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a #guint64.
+ *
+ * Returns: %TRUE only if @variant holds a #guint64.
+ **/
+gboolean
+g_dbus_variant_is_uint64 (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 't';
+}
+
+/**
+ * g_dbus_variant_is_boolean:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a #gboolean.
+ *
+ * Returns: %TRUE only if @variant holds a #gboolean.
+ **/
+gboolean
+g_dbus_variant_is_boolean (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'b';
+}
+
+/**
+ * g_dbus_variant_is_double:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a #gdouble.
+ *
+ * Returns: %TRUE only if @variant holds a #gdouble.
+ **/
+gboolean
+g_dbus_variant_is_double (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'd';
+}
+
+/**
+ * g_dbus_variant_is_array:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds an array.
+ *
+ * Returns: %TRUE only if @variant holds an array.
+ **/
+gboolean
+g_dbus_variant_is_array (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'a' &&
+ (variant->priv->signature[1] == 'y' ||
+ variant->priv->signature[1] == 'n' ||
+ variant->priv->signature[1] == 'q' ||
+ variant->priv->signature[1] == 'i' ||
+ variant->priv->signature[1] == 'x' ||
+ variant->priv->signature[1] == 't' ||
+ variant->priv->signature[1] == 'd' ||
+ variant->priv->signature[1] == 'b');
+}
+
+/**
+ * g_dbus_variant_is_ptr_array:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a pointer array.
+ *
+ * Returns: %TRUE only if @variant holds a pointer array.
+ **/
+gboolean
+g_dbus_variant_is_ptr_array (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'a' &&
+ (variant->priv->signature[1] == 'a' ||
+ variant->priv->signature[1] == 'v' ||
+ variant->priv->signature[1] == '(');
+}
+
+/**
+ * g_dbus_variant_is_hash_table:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a hash table.
+ *
+ * Returns: %TRUE only if @variant holds a hash table.
+ **/
+gboolean
+g_dbus_variant_is_hash_table (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == 'a' &&
+ variant->priv->signature[1] == '{';
+}
+
+/**
+ * g_dbus_variant_is_structure:
+ * @variant: A #GDBusVariant.
+ *
+ * Checks if @variant holds a structure.
+ *
+ * Returns: %TRUE only if @variant holds a structure.
+ **/
+gboolean
+g_dbus_variant_is_structure (GDBusVariant *variant)
+{
+ g_return_val_if_fail (G_IS_DBUS_VARIANT (variant), FALSE);
+ return
+ variant->priv->signature != NULL &&
+ variant->priv->signature[0] == '(';
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+#define __G_DBUS_VARIANT_C__
+#include "gdbusaliasdef.c"
diff --git a/gdbus/gdbusvariant.h b/gdbus/gdbusvariant.h
new file mode 100644
index 0000000..d455642
--- /dev/null
+++ b/gdbus/gdbusvariant.h
@@ -0,0 +1,201 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#if !defined (__G_DBUS_G_DBUS_H_INSIDE__) && !defined (G_DBUS_COMPILATION)
+#error "Only <gdbus/gdbus.h> can be included directly."
+#endif
+
+#ifndef __G_DBUS_VARIANT_H__
+#define __G_DBUS_VARIANT_H__
+
+#include <gdbus/gdbustypes.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_DBUS_VARIANT (g_dbus_variant_get_type ())
+#define G_DBUS_VARIANT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DBUS_VARIANT, GDBusVariant))
+#define G_DBUS_VARIANT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DBUS_VARIANT, GDBusVariantClass))
+#define G_DBUS_VARIANT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DBUS_VARIANT, GDBusVariantClass))
+#define G_IS_DBUS_VARIANT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DBUS_VARIANT))
+#define G_IS_DBUS_VARIANT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DBUS_VARIANT))
+
+typedef struct _GDBusVariantClass GDBusVariantClass;
+typedef struct _GDBusVariantPrivate GDBusVariantPrivate;
+
+/**
+ * GDBusVariant:
+ *
+ * The #GDBusVariant structure contains only private data and
+ * should only be accessed using the provided API.
+ */
+struct _GDBusVariant
+{
+ /*< private >*/
+ GObject parent_instance;
+ GDBusVariantPrivate *priv;
+};
+
+/**
+ * GDBusVariantClass:
+ *
+ * Class structure for #GDBusVariant.
+ */
+struct _GDBusVariantClass
+{
+ /*< private >*/
+ GObjectClass parent_class;
+
+ /*< public >*/
+
+ /*< private >*/
+ /* Padding for future expansion */
+ void (*_g_reserved1) (void);
+ void (*_g_reserved2) (void);
+ void (*_g_reserved3) (void);
+ void (*_g_reserved4) (void);
+ void (*_g_reserved5) (void);
+ void (*_g_reserved6) (void);
+ void (*_g_reserved7) (void);
+ void (*_g_reserved8) (void);
+};
+
+GType g_dbus_variant_get_type (void) G_GNUC_CONST;
+const gchar *g_dbus_variant_get_variant_signature (GDBusVariant *variant);
+gboolean g_dbus_variant_equal (GDBusVariant *variant1,
+ GDBusVariant *variant2);
+/* constructors */
+GDBusVariant *g_dbus_variant_new (void);
+GDBusVariant *g_dbus_variant_new_for_string (const gchar *value);
+GDBusVariant *g_dbus_variant_new_for_object_path (const gchar *value);
+GDBusVariant *g_dbus_variant_new_for_signature (const gchar *value);
+GDBusVariant *g_dbus_variant_new_for_string_array (gchar **value);
+GDBusVariant *g_dbus_variant_new_for_object_path_array (gchar **value);
+GDBusVariant *g_dbus_variant_new_for_signature_array (gchar **value);
+GDBusVariant *g_dbus_variant_new_for_byte (guchar value);
+GDBusVariant *g_dbus_variant_new_for_int16 (gint16 value);
+GDBusVariant *g_dbus_variant_new_for_uint16 (guint16 value);
+GDBusVariant *g_dbus_variant_new_for_int (gint value);
+GDBusVariant *g_dbus_variant_new_for_uint (guint value);
+GDBusVariant *g_dbus_variant_new_for_int64 (gint64 value);
+GDBusVariant *g_dbus_variant_new_for_uint64 (guint64 value);
+GDBusVariant *g_dbus_variant_new_for_boolean (gboolean value);
+GDBusVariant *g_dbus_variant_new_for_double (gdouble value);
+GDBusVariant *g_dbus_variant_new_for_array (GArray *array,
+ const gchar *element_signature);
+GDBusVariant *g_dbus_variant_new_for_ptr_array (GPtrArray *array,
+ const gchar *element_signature);
+GDBusVariant *g_dbus_variant_new_for_hash_table (GHashTable *hash_table,
+ const gchar *key_signature,
+ const gchar *value_signature);
+GDBusVariant *g_dbus_variant_new_for_structure (GDBusStructure *structure);
+
+/* getters */
+const gchar *g_dbus_variant_get_string (GDBusVariant *variant);
+const gchar *g_dbus_variant_get_object_path (GDBusVariant *variant);
+const gchar *g_dbus_variant_get_signature (GDBusVariant *variant);
+gchar **g_dbus_variant_get_string_array (GDBusVariant *variant);
+gchar **g_dbus_variant_get_object_path_array (GDBusVariant *variant);
+gchar **g_dbus_variant_get_signature_array (GDBusVariant *variant);
+guchar g_dbus_variant_get_byte (GDBusVariant *variant);
+gint16 g_dbus_variant_get_int16 (GDBusVariant *variant);
+guint16 g_dbus_variant_get_uint16 (GDBusVariant *variant);
+gint g_dbus_variant_get_int (GDBusVariant *variant);
+guint g_dbus_variant_get_uint (GDBusVariant *variant);
+gint64 g_dbus_variant_get_int64 (GDBusVariant *variant);
+guint64 g_dbus_variant_get_uint64 (GDBusVariant *variant);
+gboolean g_dbus_variant_get_boolean (GDBusVariant *variant);
+gdouble g_dbus_variant_get_double (GDBusVariant *variant);
+GArray *g_dbus_variant_get_array (GDBusVariant *variant);
+GPtrArray *g_dbus_variant_get_ptr_array (GDBusVariant *variant);
+GHashTable *g_dbus_variant_get_hash_table (GDBusVariant *variant);
+GDBusStructure *g_dbus_variant_get_structure (GDBusVariant *variant);
+
+/* setters */
+void g_dbus_variant_set_string (GDBusVariant *variant,
+ const gchar *value);
+void g_dbus_variant_set_object_path (GDBusVariant *variant,
+ const gchar *value);
+void g_dbus_variant_set_signature (GDBusVariant *variant,
+ const gchar *value);
+void g_dbus_variant_set_string_array (GDBusVariant *variant,
+ gchar **value);
+void g_dbus_variant_set_object_path_array (GDBusVariant *variant,
+ gchar **value);
+void g_dbus_variant_set_signature_array (GDBusVariant *variant,
+ gchar **value);
+void g_dbus_variant_set_byte (GDBusVariant *variant,
+ guchar value);
+void g_dbus_variant_set_int16 (GDBusVariant *variant,
+ gint16 value);
+void g_dbus_variant_set_uint16 (GDBusVariant *variant,
+ guint16 value);
+void g_dbus_variant_set_int (GDBusVariant *variant,
+ gint value);
+void g_dbus_variant_set_uint (GDBusVariant *variant,
+ guint value);
+void g_dbus_variant_set_int64 (GDBusVariant *variant,
+ gint64 value);
+void g_dbus_variant_set_uint64 (GDBusVariant *variant,
+ guint64 value);
+void g_dbus_variant_set_boolean (GDBusVariant *variant,
+ gboolean value);
+void g_dbus_variant_set_double (GDBusVariant *variant,
+ gdouble value);
+void g_dbus_variant_set_array (GDBusVariant *variant,
+ GArray *array,
+ const gchar *element_signature);
+void g_dbus_variant_set_ptr_array (GDBusVariant *variant,
+ GPtrArray *array,
+ const gchar *element_signature);
+void g_dbus_variant_set_hash_table (GDBusVariant *variant,
+ GHashTable *hash_table,
+ const gchar *key_signature,
+ const gchar *value_signature);
+void g_dbus_variant_set_structure (GDBusVariant *variant,
+ GDBusStructure *structure);
+
+/* identification */
+gboolean g_dbus_variant_is_unset (GDBusVariant *variant);
+gboolean g_dbus_variant_is_string (GDBusVariant *variant);
+gboolean g_dbus_variant_is_object_path (GDBusVariant *variant);
+gboolean g_dbus_variant_is_signature (GDBusVariant *variant);
+gboolean g_dbus_variant_is_string_array (GDBusVariant *variant);
+gboolean g_dbus_variant_is_object_path_array (GDBusVariant *variant);
+gboolean g_dbus_variant_is_signature_array (GDBusVariant *variant);
+gboolean g_dbus_variant_is_byte (GDBusVariant *variant);
+gboolean g_dbus_variant_is_int16 (GDBusVariant *variant);
+gboolean g_dbus_variant_is_uint16 (GDBusVariant *variant);
+gboolean g_dbus_variant_is_int (GDBusVariant *variant);
+gboolean g_dbus_variant_is_uint (GDBusVariant *variant);
+gboolean g_dbus_variant_is_int64 (GDBusVariant *variant);
+gboolean g_dbus_variant_is_uint64 (GDBusVariant *variant);
+gboolean g_dbus_variant_is_boolean (GDBusVariant *variant);
+gboolean g_dbus_variant_is_double (GDBusVariant *variant);
+gboolean g_dbus_variant_is_array (GDBusVariant *variant);
+gboolean g_dbus_variant_is_ptr_array (GDBusVariant *variant);
+gboolean g_dbus_variant_is_hash_table (GDBusVariant *variant);
+gboolean g_dbus_variant_is_structure (GDBusVariant *variant);
+
+G_END_DECLS
+
+#endif /* __G_DBUS_VARIANT_H__ */
diff --git a/gdbus/tests/proxy.c b/gdbus/tests/proxy.c
index d24d4df..2618824 100644
--- a/gdbus/tests/proxy.c
+++ b/gdbus/tests/proxy.c
@@ -32,6 +32,7 @@ static GMainLoop *loop = NULL;
/* Test GDBusProxy */
/* ---------------------------------------------------------------------------------------------------- */
+
static void
proxy_on_name_appeared (GDBusConnection *connection,
const gchar *name,
@@ -41,6 +42,7 @@ proxy_on_name_appeared (GDBusConnection *connection,
GDBusProxy *frob;
GError *error;
gboolean ret;
+ guint n;
gchar v_byte;
gboolean v_boolean;
gint v_int16;
@@ -53,13 +55,89 @@ proxy_on_name_appeared (GDBusConnection *connection,
gchar *v_string;
gchar *v_object_path;
gchar *v_signature;
+ GArray *ay;
+ GArray *ab;
+ GArray *an;
+ GArray *aq;
+ GArray *ai;
+ GArray *au;
+ GArray *ax;
+ GArray *at;
+ GArray *ad;
+ GArray *v_ay;
+ GArray *v_ab;
+ GArray *v_an;
+ GArray *v_aq;
+ GArray *v_ai;
+ GArray *v_au;
+ GArray *v_ax;
+ GArray *v_at;
+ GArray *v_ad;
+ gchar *as[] = {"bla", "baz", NULL};
+ gchar *ao[] = {"/foo", "/bar", NULL};
+ gchar *ag[] = {"ass", "git", NULL};
+ gchar **v_as;
+ gchar **v_ao;
+ gchar **v_ag;
+ GHashTable *hyy;
+ GHashTable *hbb;
+ GHashTable *hnn;
+ GHashTable *hqq;
+ GHashTable *hii;
+ GHashTable *huu;
+ GHashTable *hxx;
+ GHashTable *htt;
+ GHashTable *hdd;
+ GHashTable *hss;
+ GHashTable *hoo;
+ GHashTable *hgg;
+ gint64 v_int64_a = 16;
+ gint64 v_int64_b = 17;
+ guint64 v_uint64_a = 32;
+ guint64 v_uint64_b = 33;
+ gdouble v_double_a = 1.2;
+ gdouble v_double_b = 2.1;
+ GHashTable *v_hyy;
+ GHashTable *v_hbb;
+ GHashTable *v_hnn;
+ GHashTable *v_hqq;
+ GHashTable *v_hii;
+ GHashTable *v_huu;
+ GHashTable *v_hxx;
+ GHashTable *v_htt;
+ GHashTable *v_hdd;
+ GHashTable *v_hss;
+ GHashTable *v_hoo;
+ GHashTable *v_hgg;
+ GDBusStructure *pair;
+ GDBusStructure *complex_struct;
+ GDBusStructure *v_pair;
+ GDBusStructure *v_complex_struct;
+ GDBusStructure *other_struct;
+ GPtrArray *array_of_pairs;
+ GPtrArray *v_array_of_pairs;
+ GDBusVariant *variant;
+ GDBusVariant *v_variant;
+ gchar *v_str0;
+ gchar *v_str1;
+ gchar *v_str2;
+ gchar *v_str3;
+ gchar *v_str4;
+ gchar *v_str5;
+ gchar *v_str6;
+ gchar *v_str7;
+ gchar *v_str8;
error = NULL;
frob = g_dbus_proxy_new (connection,
name,
"/com/example/TestObject",
- "com.example.Frob");
+ "com.example.Frob",
+ NULL,
+ NULL,
+ NULL);
+ g_dbus_proxy_block_for_properties (frob);
ret = g_dbus_proxy_invoke_method_sync (frob,
"HelloWorld",
@@ -72,12 +150,13 @@ proxy_on_name_appeared (GDBusConnection *connection,
g_assert_cmpstr (v_string, ==, "You greeted me with 'Hello World!'. Thanks!");
g_free (v_string);
+ /* test marshalling/demarshalling of primitive types */
ret = g_dbus_proxy_invoke_method_sync (frob,
"TestPrimitiveTypes",
"ybnqiuxtdsog", "ybnqiuxtdsog",
-1, NULL, &error,
/* in values */
- G_TYPE_CHAR, 1,
+ G_TYPE_UCHAR, 1,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_INT, 2, /* gint16 */
G_TYPE_UINT, 3, /* guint16 */
@@ -91,7 +170,7 @@ proxy_on_name_appeared (GDBusConnection *connection,
G_TYPE_STRING, "ass", /* a signature */
G_TYPE_INVALID,
/* out values */
- G_TYPE_CHAR, &v_byte,
+ G_TYPE_UCHAR, &v_byte,
G_TYPE_BOOLEAN, &v_boolean,
G_TYPE_INT, &v_int16, /* gint16 */
G_TYPE_UINT, &v_uint16, /* guint16 */
@@ -122,9 +201,706 @@ proxy_on_name_appeared (GDBusConnection *connection,
g_free (v_object_path);
g_free (v_signature);
- g_object_unref (frob);
+ /* same test, but check that type coercion works */
+ ret = g_dbus_proxy_invoke_method_sync (frob,
+ "TestPrimitiveTypes",
+ "ybnqiuxtdsog", "ybnqiuxtdsog",
+ -1, NULL, &error,
+ /* in values */
+ G_TYPE_INT, 1,
+ G_TYPE_INT, TRUE,
+ G_TYPE_INT, 2, /* gint16 */
+ G_TYPE_INT, 3, /* guint16 */
+ G_TYPE_INT, 4,
+ G_TYPE_INT, 5,
+ G_TYPE_INT, 6,
+ G_TYPE_INT, 7,
+ G_TYPE_INT, 8,
+ G_TYPE_STRING, "a string",
+ G_TYPE_STRING, "/foo", /* an object path */
+ G_TYPE_STRING, "ass", /* a signature */
+ G_TYPE_INVALID,
+ /* out values */
+ G_TYPE_STRING, &v_str0,
+ G_TYPE_STRING, &v_str1,
+ G_TYPE_STRING, &v_str2,
+ G_TYPE_STRING, &v_str3,
+ G_TYPE_STRING, &v_str4,
+ G_TYPE_STRING, &v_str5,
+ G_TYPE_STRING, &v_str6,
+ G_TYPE_STRING, &v_str7,
+ G_TYPE_STRING, &v_str8,
+ G_TYPE_STRING, &v_string,
+ G_TYPE_STRING, &v_object_path, /* an object path */
+ G_TYPE_STRING, &v_signature, /* a signature */
+ G_TYPE_INVALID);
+ g_assert_no_error (error);
+ g_assert (ret);
+ g_assert_cmpstr (v_str0, ==, "2");
+ g_assert_cmpstr (v_str1, ==, "FALSE");
+ g_assert_cmpstr (v_str2, ==, "3");
+ g_assert_cmpstr (v_str3, ==, "4");
+ g_assert_cmpstr (v_str4, ==, "5");
+ g_assert_cmpstr (v_str5, ==, "6");
+ g_assert_cmpstr (v_str6, ==, "7");
+ g_assert_cmpstr (v_str7, ==, "8");
+ g_assert_cmpstr (v_str8, ==, "-7.877000");
+ g_assert_cmpstr (v_string, ==, "a stringa string");
+ g_assert_cmpstr (v_object_path, ==, "/foo/modified");
+ g_assert_cmpstr (v_signature, ==, "assass");
+ g_free (v_str0);
+ g_free (v_str1);
+ g_free (v_str2);
+ g_free (v_str3);
+ g_free (v_str4);
+ g_free (v_str5);
+ g_free (v_str6);
+ g_free (v_str7);
+ g_free (v_str8);
+ g_free (v_string);
+ g_free (v_object_path);
+ g_free (v_signature);
+
+ /* test marshalling/demarhalling of arrays of primitive types */
+ ay = g_array_new (FALSE, FALSE, sizeof (guchar)); g_array_set_size (ay, 1); ((guchar *) ay->data)[0] = 1;
+ ab = g_array_new (FALSE, FALSE, sizeof (gboolean)); g_array_set_size (ab, 1); ((gboolean *) ab->data)[0] = TRUE;
+ an = g_array_new (FALSE, FALSE, sizeof (gint16)); g_array_set_size (an, 1); ((gint16 *) an->data)[0] = 3;
+ aq = g_array_new (FALSE, FALSE, sizeof (guint16)); g_array_set_size (aq, 1); ((guint16 *) aq->data)[0] = 4;
+ ai = g_array_new (FALSE, FALSE, sizeof (gint)); g_array_set_size (ai, 1); ((gint *) ai->data)[0] = 5;
+ au = g_array_new (FALSE, FALSE, sizeof (guint)); g_array_set_size (au, 1); ((guint *) au->data)[0] = 6;
+ ax = g_array_new (FALSE, FALSE, sizeof (gint64)); g_array_set_size (ax, 1); ((gint64 *) ax->data)[0] = 7;
+ at = g_array_new (FALSE, FALSE, sizeof (guint64)); g_array_set_size (at, 1); ((guint64 *) at->data)[0] = 8;
+ ad = g_array_new (FALSE, FALSE, sizeof (gdouble)); g_array_set_size (ad, 1); ((gdouble *) ad->data)[0] = 8.2;
+ ret = g_dbus_proxy_invoke_method_sync (frob,
+ "TestArrayOfPrimitiveTypes",
+ "ayabanaqaiauaxatad", "ayabanaqaiauaxatad",
+ -1, NULL, &error,
+ /* in values */
+ G_TYPE_ARRAY, ay,
+ G_TYPE_ARRAY, ab,
+ G_TYPE_ARRAY, an,
+ G_TYPE_ARRAY, aq,
+ G_TYPE_ARRAY, ai,
+ G_TYPE_ARRAY, au,
+ G_TYPE_ARRAY, ax,
+ G_TYPE_ARRAY, at,
+ G_TYPE_ARRAY, ad,
+ G_TYPE_INVALID,
+ /* out values */
+ G_TYPE_ARRAY, &v_ay,
+ G_TYPE_ARRAY, &v_ab,
+ G_TYPE_ARRAY, &v_an,
+ G_TYPE_ARRAY, &v_aq,
+ G_TYPE_ARRAY, &v_ai,
+ G_TYPE_ARRAY, &v_au,
+ G_TYPE_ARRAY, &v_ax,
+ G_TYPE_ARRAY, &v_at,
+ G_TYPE_ARRAY, &v_ad,
+ G_TYPE_INVALID);
+ g_assert_no_error (error);
+ g_assert (ret);
+#define CHECK_ARRAY(array, type, val) do {g_assert (array->len == 2 && g_array_get_element_size (array) == sizeof (type) && g_array_index (array, type, 0) == val && g_array_index (array, type, 1) == val);} while (FALSE)
+ CHECK_ARRAY (v_ay, guchar, 1);
+ CHECK_ARRAY (v_ab, gboolean, TRUE);
+ CHECK_ARRAY (v_an, guint16, 3);
+ CHECK_ARRAY (v_aq, gint16, 4);
+ CHECK_ARRAY (v_ai, gint, 5);
+ CHECK_ARRAY (v_au, guint, 6);
+ CHECK_ARRAY (v_ax, gint64, 7);
+ CHECK_ARRAY (v_at, guint64, 8);
+ CHECK_ARRAY (v_ad, gdouble, 8.2);
+ g_array_unref (v_ay);
+ g_array_unref (v_ab);
+ g_array_unref (v_an);
+ g_array_unref (v_aq);
+ g_array_unref (v_ai);
+ g_array_unref (v_au);
+ g_array_unref (v_ax);
+ g_array_unref (v_at);
+ g_array_unref (v_ad);
+
+ /* test marshalling/demarshalling of array of string(ish) types */
+ ret = g_dbus_proxy_invoke_method_sync (frob,
+ "TestArrayOfStringTypes",
+ "asaoag", "asaoag",
+ -1, NULL, &error,
+ /* in values */
+ G_TYPE_STRV, as,
+ G_TYPE_STRV, ao,
+ G_TYPE_STRV, ag,
+ G_TYPE_INVALID,
+ /* out values */
+ G_TYPE_STRV, &v_as,
+ G_TYPE_STRV, &v_ao,
+ G_TYPE_STRV, &v_ag,
+ G_TYPE_INVALID);
+ g_assert_no_error (error);
+ g_assert (ret);
+ g_assert_cmpint (g_strv_length (v_as), ==, 4);
+ g_assert_cmpint (g_strv_length (v_ao), ==, 4);
+ g_assert_cmpint (g_strv_length (v_ag), ==, 4);
+ g_assert_cmpstr (v_as[0], ==, "bla");
+ g_assert_cmpstr (v_as[2], ==, "bla");
+ g_assert_cmpstr (v_as[1], ==, "baz");
+ g_assert_cmpstr (v_as[3], ==, "baz");
+ g_assert_cmpstr (v_ao[0], ==, "/foo");
+ g_assert_cmpstr (v_ao[2], ==, "/foo");
+ g_assert_cmpstr (v_ao[1], ==, "/bar");
+ g_assert_cmpstr (v_ao[3], ==, "/bar");
+ g_assert_cmpstr (v_ag[0], ==, "ass");
+ g_assert_cmpstr (v_ag[2], ==, "ass");
+ g_assert_cmpstr (v_ag[1], ==, "git");
+ g_assert_cmpstr (v_ag[3], ==, "git");
+ g_strfreev (v_as);
+ g_strfreev (v_ao);
+ g_strfreev (v_ag);
+
+ /* test marshalling/demarshalling of hash tables with primitive types */
+ hyy = g_hash_table_new (g_direct_hash, g_direct_equal);
+ hbb = g_hash_table_new (g_direct_hash, g_direct_equal);
+ hnn = g_hash_table_new (g_direct_hash, g_direct_equal);
+ hqq = g_hash_table_new (g_direct_hash, g_direct_equal);
+ hii = g_hash_table_new (g_direct_hash, g_direct_equal);
+ huu = g_hash_table_new (g_direct_hash, g_direct_equal);
+ hxx = g_hash_table_new (g_int64_hash, g_int64_equal);
+ htt = g_hash_table_new (g_int64_hash, g_int64_equal);
+ hdd = g_hash_table_new (g_double_hash, g_double_equal);
+ hss = g_hash_table_new (g_str_hash, g_str_equal);
+ hoo = g_hash_table_new (g_str_hash, g_str_equal);
+ hgg = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (hyy, GINT_TO_POINTER (1), GINT_TO_POINTER (1));
+ g_hash_table_insert (hbb, GINT_TO_POINTER (TRUE), GINT_TO_POINTER (FALSE));
+ g_hash_table_insert (hnn, GINT_TO_POINTER (2), GINT_TO_POINTER (2));
+ g_hash_table_insert (hqq, GINT_TO_POINTER (3), GINT_TO_POINTER (3));
+ g_hash_table_insert (hii, GINT_TO_POINTER (4), GINT_TO_POINTER (4));
+ g_hash_table_insert (huu, GINT_TO_POINTER (5), GINT_TO_POINTER (5));
+ g_hash_table_insert (hxx, &v_int64_a, &v_int64_b);
+ g_hash_table_insert (htt, &v_uint64_a, &v_uint64_b);
+ g_hash_table_insert (hdd, &v_double_a, &v_double_b);
+ g_hash_table_insert (hss, "foo", "bar");
+ g_hash_table_insert (hss, "frak", "frack");
+ g_hash_table_insert (hoo, "/foo", "/bar");
+ g_hash_table_insert (hgg, "g", "sad");
+ ret = g_dbus_proxy_invoke_method_sync (frob,
+ "TestHashTables",
+ "a{yy}a{bb}a{nn}a{qq}a{ii}a{uu}a{xx}a{tt}a{dd}a{ss}a{oo}a{gg}",
+ "a{yy}a{bb}a{nn}a{qq}a{ii}a{uu}a{xx}a{tt}a{dd}a{ss}a{oo}a{gg}",
+ -1, NULL, &error,
+ /* in values */
+ G_TYPE_HASH_TABLE, hyy,
+ G_TYPE_HASH_TABLE, hbb,
+ G_TYPE_HASH_TABLE, hnn,
+ G_TYPE_HASH_TABLE, hqq,
+ G_TYPE_HASH_TABLE, hii,
+ G_TYPE_HASH_TABLE, huu,
+ G_TYPE_HASH_TABLE, hxx,
+ G_TYPE_HASH_TABLE, htt,
+ G_TYPE_HASH_TABLE, hdd,
+ G_TYPE_HASH_TABLE, hss,
+ G_TYPE_HASH_TABLE, hoo,
+ G_TYPE_HASH_TABLE, hgg,
+ G_TYPE_INVALID,
+ /* out values */
+ G_TYPE_HASH_TABLE, &v_hyy,
+ G_TYPE_HASH_TABLE, &v_hbb,
+ G_TYPE_HASH_TABLE, &v_hnn,
+ G_TYPE_HASH_TABLE, &v_hqq,
+ G_TYPE_HASH_TABLE, &v_hii,
+ G_TYPE_HASH_TABLE, &v_huu,
+ G_TYPE_HASH_TABLE, &v_hxx,
+ G_TYPE_HASH_TABLE, &v_htt,
+ G_TYPE_HASH_TABLE, &v_hdd,
+ G_TYPE_HASH_TABLE, &v_hss,
+ G_TYPE_HASH_TABLE, &v_hoo,
+ G_TYPE_HASH_TABLE, &v_hgg,
+ G_TYPE_INVALID);
+ g_assert_no_error (error);
+ g_assert (ret);
+ g_assert_cmpint (GPOINTER_TO_INT (g_hash_table_lookup (v_hyy, GINT_TO_POINTER (1 * 2))), ==, 1 * 3);
+ g_assert_cmpint (GPOINTER_TO_INT (g_hash_table_lookup (v_hbb, GINT_TO_POINTER (TRUE))), ==, TRUE);
+ g_assert_cmpint (GPOINTER_TO_INT (g_hash_table_lookup (v_hnn, GINT_TO_POINTER (2 * 2))), ==, 2 * 3);
+ g_assert_cmpint (GPOINTER_TO_INT (g_hash_table_lookup (v_hqq, GINT_TO_POINTER (3 * 2))), ==, 3 * 3);
+ g_assert_cmpint (GPOINTER_TO_INT (g_hash_table_lookup (v_hii, GINT_TO_POINTER (4 * 2))), ==, 4 * 3);
+ g_assert_cmpint (GPOINTER_TO_INT (g_hash_table_lookup (v_huu, GINT_TO_POINTER (5 * 2))), ==, 5 * 3);
+ v_int64_a += 2; v_int64_b += 1;
+ g_assert_cmpint (*((gint64 *) g_hash_table_lookup (v_hxx, &v_int64_a)), ==, v_int64_b);
+ v_uint64_a += 2; v_uint64_b += 1;
+ g_assert_cmpint (*((guint64 *) g_hash_table_lookup (v_htt, &v_uint64_a)), ==, v_uint64_b);
+ v_double_a += 2.5; v_double_b += 5.0;
+ g_assert_cmpint (*((gdouble *) g_hash_table_lookup (v_hdd, &v_double_a)), ==, v_double_b);
+ g_assert_cmpstr (g_hash_table_lookup (v_hss, "foomod"), ==, "barbar");
+ g_assert_cmpstr (g_hash_table_lookup (v_hss, "frakmod"), ==, "frackfrack");
+ g_assert_cmpstr (g_hash_table_lookup (v_hoo, "/foo/mod"), ==, "/bar/mod2");
+ g_assert_cmpstr (g_hash_table_lookup (v_hgg, "gassgit"), ==, "sadsad");
+ g_hash_table_unref (v_hyy);
+ g_hash_table_unref (v_hbb);
+ g_hash_table_unref (v_hnn);
+ g_hash_table_unref (v_hqq);
+ g_hash_table_unref (v_hii);
+ g_hash_table_unref (v_huu);
+ g_hash_table_unref (v_hxx);
+ g_hash_table_unref (v_htt);
+ g_hash_table_unref (v_hdd);
+ g_hash_table_unref (v_hss);
+ g_hash_table_unref (v_hoo);
+ g_hash_table_unref (v_hgg);
+
+ /* test marshalling/demarshalling of structs */
+ pair = g_dbus_structure_new ("(ii)",
+ G_TYPE_INT, 42,
+ G_TYPE_INT, 43,
+ G_TYPE_INVALID);
+ complex_struct = g_dbus_structure_new ("(s(ii)aya{ss})",
+ G_TYPE_STRING, "The time is right to make new friends",
+ G_TYPE_DBUS_STRUCTURE, pair,
+ G_TYPE_ARRAY, ay,
+ G_TYPE_HASH_TABLE, hss,
+ G_TYPE_INVALID);
+ ret = g_dbus_proxy_invoke_method_sync (frob,
+ "TestStructureTypes",
+ "(ii)(s(ii)aya{ss})", "(ii)(s(ii)aya{ss})",
+ -1, NULL, &error,
+ /* in values */
+ G_TYPE_DBUS_STRUCTURE, pair,
+ G_TYPE_DBUS_STRUCTURE, complex_struct,
+ G_TYPE_INVALID,
+ /* out values */
+ G_TYPE_DBUS_STRUCTURE, &v_pair,
+ G_TYPE_DBUS_STRUCTURE, &v_complex_struct,
+ G_TYPE_INVALID);
+ g_assert_no_error (error);
+ g_assert (ret);
+ g_dbus_structure_get_element (v_pair,
+ 0, &v_int32,
+ 1, &v_uint32,
+ -1);
+ g_assert_cmpint (v_int32, ==, 42 + 1);
+ g_assert_cmpint (v_uint32, ==, 43 + 1);
+ g_dbus_structure_get_element (v_complex_struct,
+ 0, &v_string,
+ 1, &other_struct,
+ 2, &v_ay,
+ 3, &v_hss,
+ -1);
+ g_assert_cmpstr (v_string, ==, "The time is right to make new friends ... in bed!"); /* lame chinese fortune joke */
+ g_dbus_structure_get_element (other_struct,
+ 0, &v_int32,
+ 1, &v_uint32,
+ -1);
+ g_assert_cmpint (v_int32, ==, 42 + 2);
+ g_assert_cmpint (v_uint32, ==, 43 + 2);
+ CHECK_ARRAY (v_ay, guchar, 1);
+ g_assert_cmpstr (g_hash_table_lookup (v_hss, "foo"), ==, "bar ... in bed!");
+ g_assert_cmpstr (g_hash_table_lookup (v_hss, "frak"), ==, "frack ... in bed!");
+ g_assert (ret);
+ g_object_unref (v_pair);
+ g_object_unref (v_complex_struct);
+
+ /* test marshalling/demarshalling of complex arrays */
+ GPtrArray *array_of_array_of_pairs;
+ GPtrArray *v_array_of_array_of_pairs;
+ GPtrArray *array_of_array_of_strings;
+ GPtrArray *v_array_of_array_of_strings;
+ GPtrArray *array_of_hashes;
+ GPtrArray *v_array_of_hashes;
+ GPtrArray *array_of_ay;
+ GPtrArray *v_array_of_ay;
+ GPtrArray *av;
+ GPtrArray *v_av;
+ GPtrArray *aav;
+ GPtrArray *v_aav;
+ array_of_pairs = g_ptr_array_new ();
+ g_ptr_array_add (array_of_pairs, pair);
+ g_ptr_array_add (array_of_pairs, pair);
+ array_of_array_of_pairs = g_ptr_array_new ();
+ g_ptr_array_add (array_of_array_of_pairs, array_of_pairs);
+ g_ptr_array_add (array_of_array_of_pairs, array_of_pairs);
+ g_ptr_array_add (array_of_array_of_pairs, array_of_pairs);
+ array_of_array_of_strings = g_ptr_array_new ();
+ g_ptr_array_add (array_of_array_of_strings, as);
+ array_of_hashes = g_ptr_array_new ();
+ g_ptr_array_add (array_of_hashes, hss);
+ g_ptr_array_add (array_of_hashes, hss);
+ g_ptr_array_add (array_of_hashes, hss);
+ g_ptr_array_add (array_of_hashes, hss);
+ array_of_ay = g_ptr_array_new ();
+ g_ptr_array_add (array_of_ay, ay);
+ g_ptr_array_add (array_of_ay, ay);
+ g_ptr_array_add (array_of_ay, ay);
+ GDBusVariant *variant1;
+ GDBusVariant *variant2;
+ variant1 = g_dbus_variant_new_for_signature ("assgit");
+ variant2 = g_dbus_variant_new_for_structure (pair);
+ av = g_ptr_array_new ();
+ g_ptr_array_add (av, variant1);
+ g_ptr_array_add (av, variant2);
+ g_ptr_array_add (av, variant1);
+ aav = g_ptr_array_new ();
+ g_ptr_array_add (aav, av);
+ g_ptr_array_add (aav, av);
+ g_ptr_array_add (aav, av);
+ g_ptr_array_add (aav, av);
+ g_ptr_array_add (aav, av);
+ ret = g_dbus_proxy_invoke_method_sync (frob,
+ "TestComplexArrays",
+ "a(ii)aa(ii)aasaa{ss}aayavaav", "a(ii)aa(ii)aasaa{ss}aayavaav",
+ -1, NULL, &error,
+ /* in values */
+ G_TYPE_PTR_ARRAY, array_of_pairs,
+ G_TYPE_PTR_ARRAY, array_of_array_of_pairs,
+ G_TYPE_PTR_ARRAY, array_of_array_of_strings,
+ G_TYPE_PTR_ARRAY, array_of_hashes,
+ G_TYPE_PTR_ARRAY, array_of_ay,
+ G_TYPE_PTR_ARRAY, av,
+ G_TYPE_PTR_ARRAY, aav,
+ G_TYPE_INVALID,
+ /* out values */
+ G_TYPE_PTR_ARRAY, &v_array_of_pairs,
+ G_TYPE_PTR_ARRAY, &v_array_of_array_of_pairs,
+ G_TYPE_PTR_ARRAY, &v_array_of_array_of_strings,
+ G_TYPE_PTR_ARRAY, &v_array_of_hashes,
+ G_TYPE_PTR_ARRAY, &v_array_of_ay,
+ G_TYPE_PTR_ARRAY, &v_av,
+ G_TYPE_PTR_ARRAY, &v_aav,
+ G_TYPE_INVALID);
+ g_assert_no_error (error);
+ g_assert (ret);
+ g_assert_cmpint (v_array_of_pairs->len, ==, 4);
+ g_assert_cmpint (v_array_of_array_of_pairs->len, ==, 6);
+ g_assert_cmpint (v_array_of_array_of_strings->len, ==, 2);
+ g_assert_cmpint (v_array_of_hashes->len, ==, 8);
+ g_assert_cmpint (v_array_of_ay->len, ==, 6);
+ g_assert_cmpint (v_av->len, ==, 6);
+ g_assert_cmpint (v_aav->len, ==, 10);
+ g_ptr_array_unref (v_array_of_pairs);
+ g_ptr_array_unref (v_array_of_array_of_pairs);
+ g_ptr_array_unref (v_array_of_array_of_strings);
+ g_ptr_array_unref (v_array_of_hashes);
+ g_ptr_array_unref (v_array_of_ay);
+ g_ptr_array_unref (v_av);
+ g_ptr_array_unref (v_aav);
+ /* test hash tables with non-primitive types */
+ GHashTable *h_str_to_pair;
+ GHashTable *v_h_str_to_pair;
+ GHashTable *h_str_to_variant;
+ GHashTable *v_h_str_to_variant;
+ GHashTable *h_str_to_av;
+ GHashTable *v_h_str_to_av;
+ GHashTable *h_str_to_aav;
+ GHashTable *v_h_str_to_aav;
+ GHashTable *h_str_to_array_of_pairs;
+ GHashTable *v_h_str_to_array_of_pairs;
+ GHashTable *hash_of_hashes;
+ GHashTable *v_hash_of_hashes;
+ h_str_to_pair = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (h_str_to_pair, "first", pair);
+ g_hash_table_insert (h_str_to_pair, "second", pair);
+ h_str_to_variant = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (h_str_to_variant, "1st", variant1);
+ g_hash_table_insert (h_str_to_variant, "2nd", variant2);
+ h_str_to_av = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (h_str_to_av, "1", av);
+ g_hash_table_insert (h_str_to_av, "2", av);
+ h_str_to_aav = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (h_str_to_aav, "1", aav);
+ g_hash_table_insert (h_str_to_aav, "2", aav);
+ h_str_to_array_of_pairs = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (h_str_to_array_of_pairs, "1", array_of_pairs);
+ g_hash_table_insert (h_str_to_array_of_pairs, "2", array_of_pairs);
+ hash_of_hashes = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (hash_of_hashes, "1", hss);
+ g_hash_table_insert (hash_of_hashes, "2", hss);
+ ret = g_dbus_proxy_invoke_method_sync (frob,
+ "TestComplexHashTables",
+ "a{s(ii)}a{sv}a{sav}a{saav}a{sa(ii)}a{sa{ss}}",
+ "a{s(ii)}a{sv}a{sav}a{saav}a{sa(ii)}a{sa{ss}}",
+ -1, NULL, &error,
+ /* in values */
+ G_TYPE_HASH_TABLE, h_str_to_pair,
+ G_TYPE_HASH_TABLE, h_str_to_variant,
+ G_TYPE_HASH_TABLE, h_str_to_av,
+ G_TYPE_HASH_TABLE, h_str_to_aav,
+ G_TYPE_HASH_TABLE, h_str_to_array_of_pairs,
+ G_TYPE_HASH_TABLE, hash_of_hashes,
+ G_TYPE_INVALID,
+ /* out values */
+ G_TYPE_HASH_TABLE, &v_h_str_to_pair,
+ G_TYPE_HASH_TABLE, &v_h_str_to_variant,
+ G_TYPE_HASH_TABLE, &v_h_str_to_av,
+ G_TYPE_HASH_TABLE, &v_h_str_to_aav,
+ G_TYPE_HASH_TABLE, &v_h_str_to_array_of_pairs,
+ G_TYPE_HASH_TABLE, &v_hash_of_hashes,
+ G_TYPE_INVALID);
+ g_assert_no_error (error);
+ g_assert (ret);
+ g_assert ((v_pair = g_hash_table_lookup (v_h_str_to_pair, "first_baz")) != NULL);
+ g_assert (g_dbus_structure_equal (pair, v_pair));
+ g_assert ((v_pair = g_hash_table_lookup (v_h_str_to_pair, "second_baz")) != NULL);
+ g_assert (g_dbus_structure_equal (pair, v_pair));
+ g_hash_table_unref (v_h_str_to_pair);
+ g_assert ((v_variant = g_hash_table_lookup (v_h_str_to_variant, "1st_baz")) != NULL);
+ g_assert_cmpstr (g_dbus_variant_get_signature (v_variant), ==, "assgit");
+ g_assert ((v_variant = g_hash_table_lookup (v_h_str_to_variant, "2nd_baz")) != NULL);
+ g_assert (g_dbus_structure_equal (pair, g_dbus_variant_get_structure (v_variant)));
+ g_hash_table_unref (v_h_str_to_variant);
+ g_assert_cmpint (g_hash_table_size (h_str_to_av), ==, g_hash_table_size (v_h_str_to_av));
+ g_hash_table_unref (v_h_str_to_av);
+ g_assert_cmpint (g_hash_table_size (h_str_to_aav), ==, g_hash_table_size (v_h_str_to_aav));
+ g_hash_table_unref (v_h_str_to_aav);
+ g_assert_cmpint (g_hash_table_size (h_str_to_array_of_pairs), ==, g_hash_table_size (v_h_str_to_array_of_pairs));
+ g_hash_table_unref (v_h_str_to_array_of_pairs);
+ g_assert_cmpint (g_hash_table_size (hash_of_hashes), ==, g_hash_table_size (v_hash_of_hashes));
+ g_hash_table_unref (v_hash_of_hashes);
+
+ g_hash_table_unref (h_str_to_av);
+ g_hash_table_unref (h_str_to_aav);
+ g_hash_table_unref (h_str_to_array_of_pairs);
+ g_hash_table_unref (hash_of_hashes);
+
+ /* test marshalling/demarshalling of variants (this also tests various _equal() funcs) */
+ for (n = 0; ; n++)
+ {
+ variant = NULL;
+ switch (n)
+ {
+ case 0:
+ variant = g_dbus_variant_new_for_string ("frak");
+ break;
+ case 1:
+ variant = g_dbus_variant_new_for_object_path ("/blah");
+ break;
+ case 2:
+ variant = g_dbus_variant_new_for_signature ("assgit");
+ break;
+ case 3:
+ variant = g_dbus_variant_new_for_string_array (as);
+ break;
+ case 4:
+ variant = g_dbus_variant_new_for_object_path_array (ao);
+ break;
+ case 5:
+ variant = g_dbus_variant_new_for_signature_array (ag);
+ break;
+ case 6:
+ variant = g_dbus_variant_new_for_byte (1);
+ break;
+ case 7:
+ variant = g_dbus_variant_new_for_int16 (2);
+ break;
+ case 8:
+ variant = g_dbus_variant_new_for_uint16 (3);
+ break;
+ case 9:
+ variant = g_dbus_variant_new_for_int (4);
+ break;
+ case 10:
+ variant = g_dbus_variant_new_for_uint (5);
+ break;
+ case 11:
+ variant = g_dbus_variant_new_for_int64 (6);
+ break;
+ case 12:
+ variant = g_dbus_variant_new_for_uint64 (7);
+ break;
+ case 13:
+ variant = g_dbus_variant_new_for_boolean (TRUE);
+ break;
+ case 14:
+ variant = g_dbus_variant_new_for_double (8.1);
+ break;
+ case 15:
+ variant = g_dbus_variant_new_for_array (ai, "i");
+ break;
+ case 16:
+ variant = g_dbus_variant_new_for_hash_table (hii, "i", "i");
+ break;
+ case 17:
+ variant = g_dbus_variant_new_for_hash_table (hoo, "o", "o");
+ break;
+ case 18:
+ variant = g_dbus_variant_new_for_structure (complex_struct);
+ break;
+ case 19:
+ variant = g_dbus_variant_new_for_ptr_array (array_of_pairs, "(ii)");
+ break;
+
+ default:
+ break;
+ }
+
+ if (variant == NULL)
+ break;
+
+ /* first make the service returns the identical variant - this also tests
+ * that all the _equal() functions work as intended
+ */
+ ret = g_dbus_proxy_invoke_method_sync (frob,
+ "TestVariant",
+ "vb", "v",
+ -1, NULL, &error,
+ /* in values */
+ G_TYPE_DBUS_VARIANT, variant,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_INVALID,
+ /* out values */
+ G_TYPE_DBUS_VARIANT, &v_variant,
+ G_TYPE_INVALID);
+ g_assert_no_error (error);
+ g_assert (ret);
+ g_assert (g_dbus_variant_equal (variant, v_variant));
+ g_object_unref (v_variant);
+
+ /* this make the service modify the variant */
+ ret = g_dbus_proxy_invoke_method_sync (frob,
+ "TestVariant",
+ "vb", "v",
+ -1, NULL, &error,
+ /* in values */
+ G_TYPE_DBUS_VARIANT, variant,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_INVALID,
+ /* out values */
+ G_TYPE_DBUS_VARIANT, &v_variant,
+ G_TYPE_INVALID);
+ g_assert (!g_dbus_variant_equal (variant, v_variant));
+ g_assert_no_error (error);
+ g_assert (ret);
+ switch (n)
+ {
+ case 0:
+ g_assert_cmpstr (g_dbus_variant_get_string (v_variant), ==, "frakfrak");
+ break;
+ case 1:
+ g_assert_cmpstr (g_dbus_variant_get_object_path (v_variant), ==, "/blah/blah");
+ break;
+ case 2:
+ g_assert_cmpstr (g_dbus_variant_get_signature (v_variant), ==, "assgitassgit");
+ break;
+ case 3:
+ v_as = g_dbus_variant_get_string_array (v_variant);
+ g_assert_cmpint (g_strv_length (v_as), ==, 4);
+ g_assert_cmpstr (v_as[0], ==, "bla");
+ g_assert_cmpstr (v_as[2], ==, "bla");
+ g_assert_cmpstr (v_as[1], ==, "baz");
+ g_assert_cmpstr (v_as[3], ==, "baz");
+ break;
+ case 4:
+ v_ao = g_dbus_variant_get_object_path_array (v_variant);
+ g_assert_cmpint (g_strv_length (v_ao), ==, 4);
+ g_assert_cmpstr (v_ao[0], ==, "/foo");
+ g_assert_cmpstr (v_ao[2], ==, "/foo");
+ g_assert_cmpstr (v_ao[1], ==, "/bar");
+ g_assert_cmpstr (v_ao[3], ==, "/bar");
+ break;
+ case 5:
+ v_ag = g_dbus_variant_get_signature_array (v_variant);
+ g_assert_cmpint (g_strv_length (v_ag), ==, 4);
+ g_assert_cmpstr (v_ag[0], ==, "ass");
+ g_assert_cmpstr (v_ag[2], ==, "ass");
+ g_assert_cmpstr (v_ag[1], ==, "git");
+ g_assert_cmpstr (v_ag[3], ==, "git");
+ break;
+ case 6:
+ g_assert_cmpint (g_dbus_variant_get_byte (v_variant), ==, g_dbus_variant_get_byte (variant) * 2);
+ break;
+ case 7:
+ g_assert_cmpint (g_dbus_variant_get_int16 (v_variant), ==, g_dbus_variant_get_int16 (variant) * 2);
+ break;
+ case 8:
+ g_assert_cmpint (g_dbus_variant_get_uint16 (v_variant), ==, g_dbus_variant_get_uint16 (variant) * 2);
+ break;
+ case 9:
+ g_assert_cmpint (g_dbus_variant_get_int (v_variant), ==, g_dbus_variant_get_int (variant) * 2);
+ break;
+ case 10:
+ g_assert_cmpint (g_dbus_variant_get_uint (v_variant), ==, g_dbus_variant_get_uint (variant) * 2);
+ break;
+ case 11:
+ g_assert_cmpint (g_dbus_variant_get_int64 (v_variant), ==, g_dbus_variant_get_int64 (variant) * 2);
+ break;
+ case 12:
+ g_assert_cmpint (g_dbus_variant_get_uint64 (v_variant), ==, g_dbus_variant_get_uint64 (variant) * 2);
+ break;
+ case 13:
+ g_assert (!g_dbus_variant_get_boolean (v_variant));
+ break;
+ case 14:
+ g_assert_cmpfloat (g_dbus_variant_get_double (v_variant), ==, g_dbus_variant_get_double (variant) * 2);
+ break;
+ case 15:
+ v_ai = g_dbus_variant_get_array (v_variant);
+ CHECK_ARRAY (v_ai, gint, 5);
+ break;
+ case 16:
+ v_hii = g_dbus_variant_get_hash_table (v_variant);
+ g_assert_cmpint (GPOINTER_TO_INT (g_hash_table_lookup (v_hii, GINT_TO_POINTER (4))), ==, 4 * 2);
+ break;
+ case 17:
+ v_hoo = g_dbus_variant_get_hash_table (v_variant);
+ g_assert_cmpstr (g_hash_table_lookup (v_hoo, "/foo"), ==, "/bar/bar");
+ break;
+ case 18:
+ other_struct = g_dbus_variant_get_structure (v_variant);
+ g_dbus_structure_get_element (other_struct,
+ 0, &v_string,
+ 1, &v_int16,
+ -1);
+ g_assert_cmpstr (v_string, ==, "other struct");
+ g_assert_cmpint (v_int16, ==, 100);
+ break;
+ case 19:
+ g_assert_cmpint (g_dbus_variant_get_ptr_array (v_variant)->len, ==, array_of_pairs->len * 2);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ g_object_unref (v_variant);
+
+ g_object_unref (variant);
+ }
+
+ /* free all objects constructed for testing */
+ g_array_unref (ay);
+ g_array_unref (ab);
+ g_array_unref (an);
+ g_array_unref (aq);
+ g_array_unref (ai);
+ g_array_unref (au);
+ g_array_unref (ax);
+ g_array_unref (at);
+ g_array_unref (ad);
+ g_hash_table_unref (hyy);
+ g_hash_table_unref (hbb);
+ g_hash_table_unref (hnn);
+ g_hash_table_unref (hqq);
+ g_hash_table_unref (hii);
+ g_hash_table_unref (huu);
+ g_hash_table_unref (hxx);
+ g_hash_table_unref (htt);
+ g_hash_table_unref (hdd);
+ g_hash_table_unref (hss);
+ g_hash_table_unref (hoo);
+ g_hash_table_unref (hgg);
+ g_object_unref (pair);
+ g_object_unref (complex_struct);
+ g_ptr_array_unref (array_of_pairs);
+ g_ptr_array_unref (array_of_array_of_pairs);
+ g_hash_table_unref (h_str_to_pair);
+ g_hash_table_unref (h_str_to_variant);
+ g_object_unref (variant1);
+ g_object_unref (variant2);
+ g_ptr_array_unref (array_of_array_of_strings);
+ g_ptr_array_unref (array_of_hashes);
+ g_ptr_array_unref (array_of_ay);
+ g_ptr_array_unref (av);
+ g_ptr_array_unref (aav);
+
+ g_object_unref (frob);
g_main_loop_quit (loop);
+
+#undef CHECK_ARRAY
}
static void
diff --git a/gdbus/tests/sessionbus.c b/gdbus/tests/sessionbus.c
index b4a466e..57ffc20 100644
--- a/gdbus/tests/sessionbus.c
+++ b/gdbus/tests/sessionbus.c
@@ -245,6 +245,13 @@ session_bus_up_with_address (const gchar *given_address)
g_snprintf (buf, sizeof buf, "add %d\n", (guint) pid);
write (pipe_fds[1], buf, strlen (buf));
+ /* start dbus-monitor */
+ if (g_getenv ("GDBUS_MONITOR") != NULL)
+ {
+ g_spawn_command_line_async ("dbus-monitor --session", NULL);
+ usleep (500 * 1000);
+ }
+
g_hash_table_insert (session_bus_address_to_pid, address, GUINT_TO_POINTER (pid));
out:
diff --git a/gdbus/tests/testserver.py b/gdbus/tests/testserver.py
index 9c30999..5ce3dfd 100755
--- a/gdbus/tests/testserver.py
+++ b/gdbus/tests/testserver.py
@@ -12,7 +12,8 @@ class TestException(dbus.DBusException):
class TestService(dbus.service.Object):
- # $ dbus-send --session --print-reply --dest=com.example.TestService /com/example/TestService com.example.TestService.HelloWorld string:Hi!
+ # ----------------------------------------------------------------------------------------------------
+
@dbus.service.method("com.example.Frob",
in_signature='s', out_signature='s')
def HelloWorld(self, hello_message):
@@ -21,60 +22,42 @@ class TestService(dbus.service.Object):
else:
return "You greeted me with '%s'. Thanks!"%(str(hello_message))
- # $ dbus-send --session --print-reply --dest=com.example.TestService /com/example/TestService com.example.TestService.TestPrimitiveTypes byte:1 boolean:false int16:160 uint16:161 int32:320 uint32:321 int64:640 uint64:641 double:4.5 string:foo objpath:/foo
+ # ----------------------------------------------------------------------------------------------------
+
@dbus.service.method("com.example.Frob",
in_signature='ybnqiuxtdsog', out_signature='ybnqiuxtdsog')
def TestPrimitiveTypes(self, val_byte, val_boolean, val_int16, val_uint16, val_int32, val_uint32, val_int64, val_uint64, val_double, val_string, val_objpath, val_signature):
return val_byte + 1, not val_boolean, val_int16 + 1, val_uint16 + 1, val_int32 + 1, val_uint32 + 1, val_int64 + 1, val_uint64 + 1, -val_double + 0.123, val_string * 2, val_objpath + "/modified", val_signature * 2
- # $ dbus-send --session --print-reply --dest=com.example.TestService /com/example/TestService com.example.TestService.TestArrayOfPrimitiveTypes array:byte:1,2 array:boolean:false,true array:int16:160,170 array:uint16:161,171 array:int32:320,330 array:uint32:321,331 array:int64:640,650 array:uint64:641,651 array:double:4.5,5.5 array:string:foo,foo2 array:objpath:/foo,/foo2
- @dbus.service.method("com.example.Frob",
- in_signature='ayabanaqaiauaxatadasao', out_signature='ayabanaqaiauaxatadasao')
- def TestArrayOfPrimitiveTypes(self, val_byte, val_boolean, val_int16, val_uint16, val_int32, val_uint32, val_int64, val_uint64, val_double, val_string, val_objpath):
- return val_byte*2, val_boolean*2, val_int16*2, val_uint16*2, val_int32*2, val_uint32*2, val_int64*2, val_uint64*2, val_double*2, val_string*2, val_objpath*2
+ # ----------------------------------------------------------------------------------------------------
- # no support in dbus-send
@dbus.service.method("com.example.Frob",
- in_signature='(ii)(s(ii))', out_signature='(ii)(s(ii))')
- def TestStructureTypes(self, s1, s2):
- (x, y) = s1;
- (desc, (x1, y1)) = s2;
- return (x + 1, y + 1), ("replaced desc", (x1 + 2, y1 + 2))
+ in_signature='ayabanaqaiauaxatad', out_signature='ayabanaqaiauaxatad')
+ def TestArrayOfPrimitiveTypes(self, val_byte, val_boolean, val_int16, val_uint16, val_int32, val_uint32, val_int64, val_uint64, val_double):
+ return val_byte*2, val_boolean*2, val_int16*2, val_uint16*2, val_int32*2, val_uint32*2, val_int64*2, val_uint64*2, val_double*2
- # no support in dbus-send
- @dbus.service.method("com.example.Frob",
- in_signature='a(s(ii)s)', out_signature='a(s(ii)s)')
- def TestArrayOfStructureTypes(self, a):
- r = []
- n = 0
- for i in a:
- (d, (x, y), e) = i;
- r.append(("%s_%d"%(d,n), (x + 1, y + 1), "%s_%d"%(e,n)))
- n+=1
- return r
-
- # no support in dbus-send
- @dbus.service.method("com.example.Frob",
- in_signature = 'a{ss}a{oo}a{ii}a{yy}a{nn}a{qq}a{uu}a{bb}a{xx}a{tt}a{dd}',
- out_signature = 'a{ss}a{oo}a{ii}a{yy}a{nn}a{qq}a{uu}a{bb}a{xx}a{tt}a{dd}')
- def TestHashTables(self, hss, hoo, hii, hyy, hnn, hqq, huu, hbb, hxx, htt, hdd):
+ # ----------------------------------------------------------------------------------------------------
- ret_hss = {}
- for i in hss:
- ret_hss[i + "mod"] = hss[i]*2
+ @dbus.service.method("com.example.Frob",
+ in_signature='asaoag', out_signature='asaoag')
+ def TestArrayOfStringTypes(self, val_string, val_objpath, val_signature):
+ return val_string * 2, val_objpath * 2, val_signature * 2
- ret_hoo = {}
- for i in hoo:
- ret_hoo[i + "/mod"] = hoo[i] + "/mod2"
+ # ----------------------------------------------------------------------------------------------------
- ret_hii = {}
- for i in hii:
- ret_hii[i*2] = hii[i]*3
+ @dbus.service.method("com.example.Frob",
+ in_signature = 'a{yy}a{bb}a{nn}a{qq}a{ii}a{uu}a{xx}a{tt}a{dd}a{ss}a{oo}a{gg}',
+ out_signature = 'a{yy}a{bb}a{nn}a{qq}a{ii}a{uu}a{xx}a{tt}a{dd}a{ss}a{oo}a{gg}')
+ def TestHashTables(self, hyy, hbb, hnn, hqq, hii, huu, hxx, htt, hdd, hss, hoo, hgg):
ret_hyy = {}
for i in hyy:
ret_hyy[i*2] = (hyy[i]*3) & 255
+ ret_hbb = {}
+ for i in hbb:
+ ret_hbb[i] = True
+
ret_hnn = {}
for i in hnn:
ret_hnn[i*2] = hnn[i]*3
@@ -83,14 +66,14 @@ class TestService(dbus.service.Object):
for i in hqq:
ret_hqq[i*2] = hqq[i]*3
+ ret_hii = {}
+ for i in hii:
+ ret_hii[i*2] = hii[i]*3
+
ret_huu = {}
for i in huu:
ret_huu[i*2] = huu[i]*3
- ret_hbb = {}
- for i in hbb:
- ret_hbb[i] = True
-
ret_hxx = {}
for i in hxx:
ret_hxx[i + 2] = hxx[i] + 1
@@ -103,218 +86,77 @@ class TestService(dbus.service.Object):
for i in hdd:
ret_hdd[i + 2.5] = hdd[i] + 5.0
- return ret_hss, ret_hoo, ret_hii, ret_hyy, ret_hnn, ret_hqq, ret_huu, ret_hbb, ret_hxx, ret_htt, ret_hdd
+ ret_hss = {}
+ for i in hss:
+ ret_hss[i + "mod"] = hss[i]*2
+
+ ret_hoo = {}
+ for i in hoo:
+ ret_hoo[i + "/mod"] = hoo[i] + "/mod2"
- # no support in dbus-send
- @dbus.service.method("com.example.Frob",
- in_signature = 'a{s(ii)}',
- out_signature = 'a{s(s(ii))}')
- def TestHashTableOfStructures(self, hash_of_points):
- ret = {}
- for s in hash_of_points:
- (x, y) = hash_of_points[s]
- ret[s + "_new"] = (s, (x + 100, y + 200))
- return ret
-
- # no support in dbus-send
- @dbus.service.method("com.example.Frob",
- in_signature = 'a{sas}a{sao}a{sai}a{say}a{san}a{saq}a{sau}a{sab}a{sax}a{sat}a{sad}a{sa(ii)}',
- out_signature = 'a{sas}a{sao}a{sai}a{say}a{san}a{saq}a{sau}a{sab}a{sax}a{sat}a{sad}a{sa(ii)}')
- def TestHashTablesOfArrays(self, hsas, hsao, hsai, hsay, hsan, hsaq, hsau, hsab, hsax, hsat, hsad, hash_of_point_arrays):
-
- ret_hsas = {}
- for i in hsas:
- ret_hsas[i] = hsas[i]*2
-
- ret_hsao = {}
- for i in hsao:
- ret_hsao[i] = hsao[i]*2
-
- ret_hsai = {"k" : [1, 2]}
- ret_hsay = {"k" : [3, 4]}
- ret_hsan = {"k" : [5, 6]}
- ret_hsaq = {"k" : [7, 8]}
- ret_hsau = {"k" : [9, 10]}
- ret_hsab = {"k" : [True, False, True]}
- ret_hsax = {"k" : [11, 12]}
- ret_hsat = {"k" : [13, 14]}
- ret_hsad = {"k" : [15.5, 16.5]}
-
- ret_hash_of_point_arrays = {}
- for s in hash_of_point_arrays:
- point_array = hash_of_point_arrays[s]
- new_point_array = []
- for point in point_array:
- (x, y) = point
- new_point_array.append ((x + 100, y + 200))
- ret_hash_of_point_arrays[s + "_new"] = new_point_array
-
- return ret_hsas, ret_hsao, ret_hsai, ret_hsay, ret_hsan, ret_hsaq, ret_hsau, ret_hsab, ret_hsax, ret_hsat, ret_hsad, ret_hash_of_point_arrays
-
- # no support in dbus-send
- @dbus.service.method("com.example.Frob",
- in_signature = 'a{sa{s(ii)}}',
- out_signature = 'a{sa{s(ii)}}')
- def TestHashTableOfHashTablesOfStructures(self, hash_of_hash_of_points):
-
- ret = {}
- for h in hash_of_hash_of_points:
- hash_of_points = hash_of_hash_of_points[h]
- newh = {}
- for s in hash_of_points:
- (x, y) = hash_of_points[s]
- newh[s + "_new_new"] = (x + 100, y + 200)
- ret[h + "_new"] = newh
-
- return ret
-
- # no support in dbus-send
- @dbus.service.method("com.example.Frob",
- in_signature = 'aa{s(ii)}',
- out_signature = 'aa{s(ii)}')
- def TestArrayOfHashTablesOfStructures(self, list_of_hash_of_points):
+ ret_hgg = {}
+ for i in hgg:
+ ret_hgg[i + "assgit"] = hgg[i]*2
- ret = []
- for hash_of_points in list_of_hash_of_points:
- newh = {}
- for s in hash_of_points:
- (x, y) = hash_of_points[s]
- newh[s + "_new_new"] = (x + 100, y + 200)
- ret.append(newh)
+ return ret_hyy, ret_hbb, ret_hnn, ret_hqq, ret_hii, ret_huu, ret_hxx, ret_htt, ret_hdd, ret_hss, ret_hoo, ret_hgg
- return ret
+ # ----------------------------------------------------------------------------------------------------
- # no support in dbus-send
- @dbus.service.method("com.example.Frob",
- in_signature = 'aasaa(ii)aaoaaiaayaanaaqaauaabaaxaataadaaas',
- out_signature = 'aasaa(ii)aaoaaiaayaanaaqaauaabaaxaataadaaas')
- def TestArrayOfArrays(self, aas, aastruct, aao, aai, aay, aan, aaq, aau, aab, aax, aat, aad, aaas):
-
- ret_aas = aas*2;
- ret_aastruct = aastruct*2;
- ret_aao = aao*2;
- ret_aai = aai*2;
- ret_aay = aay*2;
- ret_aan = aan*2;
- ret_aaq = aaq*2;
- ret_aau = aau*2;
- ret_aab = aab*2;
- ret_aax = aax*2;
- ret_aat = aat*2;
- ret_aad = aad*2;
- ret_aaas = aaas*2
-
- return ret_aas, ret_aastruct, ret_aao, ret_aai, ret_aay, ret_aan, ret_aaq, ret_aau, ret_aab, ret_aax, ret_aat, ret_aad, ret_aaas
-
- # dbus-send --print-reply --session --dest=com.example.TestService /com/example/TestService com.example.TestService.TestVariantReturn string:o
@dbus.service.method("com.example.Frob",
- in_signature = 's',
- out_signature = 'v')
- def TestVariantReturn(self, desired_variant):
-
- if desired_variant == "y":
- ret = dbus.Byte(1)
- elif desired_variant == "b":
- ret = True
- elif desired_variant == "n":
- ret = dbus.Int16(2)
- elif desired_variant == "q":
- ret = dbus.UInt16(3)
- elif desired_variant == "i":
- ret = dbus.Int32(4)
- elif desired_variant == "u":
- ret = dbus.UInt32(5)
- elif desired_variant == "x":
- ret = dbus.Int64(6)
- elif desired_variant == "t":
- ret = dbus.UInt64(7)
- elif desired_variant == "d":
- ret = 7.5
- elif desired_variant == "s":
- ret = "a string"
- elif desired_variant == "o":
- ret = dbus.ObjectPath("/some/object/path")
- elif desired_variant == "ai":
- ret = []
- ret.append(dbus.Int32(4))
- ret.append(dbus.Int32(5))
- elif desired_variant == "as":
- ret = []
- ret.append("a string")
- ret.append("another string")
- elif desired_variant == "point":
- ret = (1, 2)
- elif desired_variant == "dpoint":
- ret = ("the desc", (3, 4))
- elif desired_variant == "hash_of_points":
- ret = {}
- ret["key0"] = (1, 2)
- ret["key1"] = (3, 4)
- ret["key2"] = (5, 6)
- ret["key3"] = (7, 8)
- elif desired_variant == "unregistered_struct":
- ret = ("string",
- dbus.Byte(2),
- dbus.Int16(3),
- 4,
- [0, 1, 2, 3],
- {"rip" : 2, "rap" : 4, "rup" : 6},
- [(1, 2), (1, 2), (1, 2)],
- [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
- [True, False, False],
- [[True, True], [False, True]],
- [dbus.Byte(0xca), dbus.Byte(0xfe), dbus.Byte(0xba), dbus.Byte(0xbe), dbus.Byte(0x00), dbus.Byte(0xde), dbus.Byte(0xad), dbus.Byte(0xbe), dbus.Byte(0xef)],
- {"huey" : (2, 1), "dewey" : (4, 2), "louie" : (6, 3)},
- {"innie" : [10, 11], "minnie" : [12, 13], "minie" : [14, 15], "moe" : [16, 17]},
- {dbus.Byte(0xa0) : [10, 11], dbus.Byte(0xa1) : [12, 13], dbus.Byte(0xa2) : [14, 15]})
- else:
- raise TestException("unknown desired variant '%s'"%desired_variant)
+ in_signature='(ii)(s(ii)aya{ss})', out_signature='(ii)(s(ii)aya{ss})')
+ def TestStructureTypes(self, s1, s2):
+ (x, y) = s1;
+ (desc, (x1, y1), ay, hss) = s2;
+ ret_hss = {}
+ for i in hss:
+ ret_hss[i] = hss[i] + " ... in bed!"
+ return (x + 1, y + 1), (desc + " ... in bed!", (x1 + 2, y1 + 2), ay * 2, ret_hss)
- return ret
+ # ----------------------------------------------------------------------------------------------------
- # $ dbus-send --print-reply --session --dest=com.example.TestService /com/example/TestService com.example.TestService.TestVariantReturn2 string:one
@dbus.service.method("com.example.Frob",
- in_signature = 's',
- out_signature = 'ava{sv}(siivx)')
- def TestVariantReturn2(self, desired_variant):
-
- ret_av = []
- ret_hsv = {}
-
- if desired_variant == "one":
- ret_av.append (dbus.Byte(1))
- ret_av.append ("a string")
- ret_av.append ((1, 2))
- ret_av.append ([dbus.Int16(100), dbus.Int16(100), dbus.Int16(100)])
- ret_av.append ({"rip" : 2, "rap" : 4, "rup" : 6})
- ret_struct = ("ok, steady", 10, 11, "one", 2)
- elif desired_variant == "two":
- ret_hsv["1st"] = dbus.Byte(1)
- ret_hsv["2nd"] = "a string"
- ret_hsv["3rd"] = (1, 2)
- ret_hsv["4th"] = [dbus.Int16(100), dbus.Int16(100), dbus.Int16(100)]
- ret_hsv["5th"] = {"rip" : 2, "rap" : 4, "rup" : 6}
- ret_struct = ("anger. fear. acceptance. CA$H!!", 10, 11, {"foo": 42, "bar": 43}, 2)
+ in_signature='vb', out_signature='v')
+ def TestVariant(self, v, modify):
+
+ if modify:
+ if type(v)==dbus.Boolean:
+ ret = False
+ elif type(v)==dbus.Dictionary:
+ ret = {}
+ for i in v:
+ ret[i] = v[i] * 2
+ elif type(v)==dbus.Struct:
+ ret = ["other struct", dbus.Int16(100)]
+ else:
+ ret = v * 2
else:
- raise TestException("unknown desired variant '%s'"%desired_variant)
+ ret = v
+ return (type(v))(ret)
- return ret_av, ret_hsv, ret_struct
+ # ----------------------------------------------------------------------------------------------------
- # $ dbus-send --print-reply --session --dest=com.example.TestService /com/example/TestService com.example.TestService.TestPassVariant variant:string:dbus-rocks
@dbus.service.method("com.example.Frob",
- in_signature = 'v',
- out_signature = 's')
- def TestPassVariant(self, variant):
+ in_signature='a(ii)aa(ii)aasaa{ss}aayavaav', out_signature='a(ii)aa(ii)aasaa{ss}aayavaav')
+ def TestComplexArrays(self, aii, aaii, aas, ahashes, aay, av, aav):
+ return aii * 2, aaii * 2, aas * 2, ahashes * 2, aay * 2, av *2, aav * 2
- return dbus.String(variant) + "-and-a-bag-of-chips"
+ # ----------------------------------------------------------------------------------------------------
- # $ dbus-send --print-reply --session --dest=com.example.TestService /com/example/TestService com.example.TestService.TestPassVariant variant:string:dbus-rocks
@dbus.service.method("com.example.Frob",
- in_signature = 'ava{sv}a{sav}(siivx)',
- out_signature = 's')
- def TestPassVariant2(self, array_of_variants, dict_of_string_to_variants, dict_of_string_to_array_of_variants, struct_with_variant):
+ in_signature='a{s(ii)}a{sv}a{sav}a{saav}a{sa(ii)}a{sa{ss}}',
+ out_signature='a{s(ii)}a{sv}a{sav}a{saav}a{sa(ii)}a{sa{ss}}')
+ def TestComplexHashTables(self, h_str_to_pair, h_str_to_variant, h_str_to_av, h_str_to_aav,
+ h_str_to_array_of_pairs, hash_of_hashes):
- return dbus.String(array_of_variants) + dbus.String(dict_of_string_to_variants) + dbus.String(dict_of_string_to_array_of_variants) + dbus.String(struct_with_variant)
+ ret_h_str_to_pair = {}
+ for i in h_str_to_pair:
+ ret_h_str_to_pair[i + "_baz"] = h_str_to_pair[i]
+
+ ret_h_str_to_variant = {}
+ for i in h_str_to_variant:
+ ret_h_str_to_variant[i + "_baz"] = h_str_to_variant[i]
+
+ return ret_h_str_to_pair, ret_h_str_to_variant, h_str_to_av, h_str_to_aav, h_str_to_array_of_pairs, hash_of_hashes
@dbus.service.method("org.freedesktop.DBus.Properties",
in_signature = 'ss',
@@ -323,8 +165,6 @@ class TestService(dbus.service.Object):
if interface_name == "com.example.Frob":
return self.frob_props[property_name]
- elif interface_name == "com.example.Tweak":
- return self.tweak_props[property_name]
else:
raise TestException("No such interface " + interface_name)
@@ -334,48 +174,9 @@ class TestService(dbus.service.Object):
def GetAll(self, interface_name):
if interface_name == "com.example.Frob":
return self.frob_props
- elif interface_name == "com.example.Tweak":
- return self.tweak_props
else:
raise TestException("No such interface " + interface_name)
- @dbus.service.method("com.example.Tweak",
- in_signature='s', out_signature='s')
- def ICanHazGreetingz(self, hello_message):
- return "Word. You haz greetz '%s'. KTHXBYE!"%(str(hello_message))
-
- @dbus.service.method("com.example.Tweak",
- out_signature='s')
- def GetServerUniqueName(self):
- return session_bus.get_unique_name()
-
-
-
-
-
- @dbus.service.signal("com.example.Tweak")
- def NewzNotifz(self, newz):
- pass
-
- @dbus.service.method("com.example.Tweak",
- in_signature='s')
- def BroadcastzNewz(self, newz_to_pass):
- self.NewzNotifz("Word. Broadcastz '%s'. KTHXBYE!"%(str(newz_to_pass)))
-
-
- @dbus.service.method("com.example.Twiddle",
- in_signature='s')
- def BroadcastzNewzOnTwiddle(self, newz_to_pass):
- string = "Sez '%s'. KTHXBYE!"%(str(newz_to_pass))
- # manually construct the message since dbus-python doesn't appear
- # to support identical signal names on different interfaces...
- #
- message = dbus.lowlevel.SignalMessage("/com/example/TestObject", "com.example.Twiddle", "NewzNotifz")
- message.append(string)
- session_bus.send_message(message)
-
-
-
if __name__ == '__main__':
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
@@ -411,10 +212,5 @@ if __name__ == '__main__':
obj.frob_props["ao"] = [dbus.ObjectPath("/some/path"), dbus.ObjectPath("/another/path")]
obj.frob_props["foo"] = "a frobbed string"
- obj.tweak_props = {}
- obj.tweak_props["foo"] = "a tweaked string"
- obj.tweak_props["bar"] = [1, 2]
- obj.tweak_props["baz"] = (3, 4)
-
mainloop = gobject.MainLoop()
mainloop.run()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]