summaryrefslogtreecommitdiffstats
path: root/glib/dbus-gvalue.c
diff options
context:
space:
mode:
Diffstat (limited to 'glib/dbus-gvalue.c')
-rw-r--r--glib/dbus-gvalue.c148
1 files changed, 142 insertions, 6 deletions
diff --git a/glib/dbus-gvalue.c b/glib/dbus-gvalue.c
index e332e71a..3e8cf1e7 100644
--- a/glib/dbus-gvalue.c
+++ b/glib/dbus-gvalue.c
@@ -107,6 +107,13 @@ static gboolean demarshal_collection_array (DBusGValueMarshalCtx *cont
DBusMessageIter *iter,
GValue *value,
GError **error);
+static gboolean marshal_struct (DBusMessageIter *iter,
+ const GValue *value);
+static gboolean demarshal_struct (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error);
+
typedef gboolean (*DBusGValueMarshalFunc) (DBusMessageIter *iter,
const GValue *value);
@@ -346,6 +353,7 @@ dbus_g_object_path_get_g_type (void)
return type_id;
}
+
char *
_dbus_gtype_to_signature (GType gtype)
{
@@ -377,6 +385,21 @@ _dbus_gtype_to_signature (GType gtype)
g_free (key_subsig);
g_free (val_subsig);
}
+ else if (dbus_g_type_is_struct (gtype))
+ {
+ guint i, size;
+ GString *sig;
+ size = dbus_g_type_get_struct_size (gtype);
+ sig = g_string_sized_new (size+2); /*some sensible starting size*/
+ g_string_assign (sig, DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
+ for (i=0; i < size; i++)
+ {
+ g_string_append (sig, _dbus_gtype_to_signature (
+ dbus_g_type_get_struct_member_type (gtype, i)));
+ }
+ g_string_append (sig, DBUS_STRUCT_END_CHAR_AS_STRING);
+ ret = g_string_free (sig, FALSE);
+ }
else
{
typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ());
@@ -384,7 +407,6 @@ _dbus_gtype_to_signature (GType gtype)
return NULL;
ret = g_strdup (typedata->sig);
}
-
return ret;
}
@@ -851,6 +873,76 @@ demarshal_map (DBusGValueMarshalCtx *context,
return TRUE;
}
+static gboolean
+demarshal_struct (DBusGValueMarshalCtx *context,
+ DBusMessageIter *iter,
+ GValue *value,
+ GError **error)
+{
+ int current_type;
+ DBusMessageIter subiter;
+ guint i, size;
+ GValue val = {0,};
+ GType elt_type;
+
+ current_type = dbus_message_iter_get_arg_type (iter);
+ if (current_type != DBUS_TYPE_STRUCT)
+ {
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ _("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type);
+ return FALSE;
+ }
+
+ dbus_message_iter_recurse (iter, &subiter);
+
+ g_value_set_boxed_take_ownership (value,
+ dbus_g_type_specialized_construct (G_VALUE_TYPE (value)));
+
+ size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value));
+
+ for (i=0; i < size; i++)
+ {
+
+ elt_type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE(value), i);
+ if (elt_type == G_TYPE_INVALID)
+ {
+ g_value_unset (value);
+ g_set_error (error,
+ DBUS_GERROR,
+ DBUS_GERROR_INVALID_ARGS,
+ _("Couldn't demarshal argument, "
+ "struct type %s has no member %d"),
+ g_type_name (G_VALUE_TYPE(value)), i);
+ return FALSE;
+ }
+
+ g_value_init (&val, elt_type);
+
+ if (!_dbus_gvalue_demarshal (context, &subiter, &val, error))
+ {
+ g_value_unset (&val);
+ g_value_unset (value);
+ return FALSE;
+ }
+ if (!dbus_g_type_struct_set_member (value, i, &val))
+ {
+ g_value_unset (&val);
+ g_value_unset (value);
+ return FALSE;
+ }
+
+ dbus_message_iter_next (&subiter);
+ g_value_unset (&val);
+ }
+
+ g_assert (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_INVALID);
+
+ return TRUE;
+}
+
+
static DBusGValueDemarshalFunc
get_type_demarshaller (GType type)
{
@@ -865,6 +957,8 @@ get_type_demarshaller (GType type)
return demarshal_collection;
if (dbus_g_type_is_map (type))
return demarshal_map;
+ if (dbus_g_type_is_struct (type))
+ return demarshal_struct;
g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
return NULL;
@@ -1453,6 +1547,48 @@ marshal_map (DBusMessageIter *iter,
}
static gboolean
+marshal_struct (DBusMessageIter *iter,
+ const GValue *value)
+{
+ GType gtype;
+ DBusMessageIter subiter;
+ gboolean ret;
+ guint size, i;
+ GValue val = {0,};
+
+ gtype = G_VALUE_TYPE (value);
+
+ ret = FALSE;
+
+ size = dbus_g_type_get_struct_size (gtype);
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &subiter))
+ goto oom;
+
+ for (i = 0; i < size; i++)
+ {
+ g_value_init (&val, dbus_g_type_get_struct_member_type
+ (G_VALUE_TYPE(value), i));
+ if (!dbus_g_type_struct_get_member (value, i, &val))
+ return FALSE;
+ if (!_dbus_gvalue_marshal (&subiter, &val))
+ return FALSE;
+ g_value_unset(&val);
+ }
+
+ if (!dbus_message_iter_close_container (iter, &subiter))
+ goto oom;
+
+ return TRUE;
+ oom:
+ g_error ("out of memory");
+ return FALSE;
+}
+
+static gboolean
marshal_variant (DBusMessageIter *iter,
const GValue *value)
{
@@ -1504,6 +1640,8 @@ get_type_marshaller (GType type)
return marshal_collection;
if (dbus_g_type_is_map (type))
return marshal_map;
+ if (dbus_g_type_is_struct (type))
+ return marshal_struct;
g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
return NULL;
@@ -1697,17 +1835,15 @@ _dbus_gvalue_test (const char *test_data_dir)
assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
- assert_signature_maps_to (DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING, G_TYPE_VALUE_ARRAY);
- assert_signature_maps_to (DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING, G_TYPE_VALUE_ARRAY);
- assert_signature_maps_to (DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_TYPE_UINT32_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING, G_TYPE_VALUE_ARRAY);
-
assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
- DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
+ assert_bidirectional_mapping (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID),
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING );
return TRUE;
}