1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-gvalue.c GValue to-from DBusMessageIter
4 * Copyright (C) 2004 Ximian, Inc.
5 * Copyright (C) 2005 Red Hat, Inc.
7 * Licensed under the Academic Free License version 2.1
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "dbus-gtest.h"
27 #include "dbus-gvalue.h"
28 #include "dbus-gsignature.h"
29 #include "dbus-gobject.h"
30 #include "dbus-gvalue-utils.h"
31 #include "dbus/dbus-glib.h"
34 #include "dbus/dbus-signature.h"
36 /* Seems reasonable, but this should probably be part of the standard protocol */
37 #define DBUS_GLIB_MAX_VARIANT_RECURSION 32
39 static gboolean demarshal_static_variant (DBusGValueMarshalCtx *context,
40 DBusMessageIter *iter,
45 static gboolean marshal_basic (DBusMessageIter *iter,
47 static gboolean demarshal_basic (DBusGValueMarshalCtx *context,
48 DBusMessageIter *iter,
51 static gboolean marshal_strv (DBusMessageIter *iter,
53 static gboolean demarshal_strv (DBusGValueMarshalCtx *context,
54 DBusMessageIter *iter,
57 static gboolean marshal_valuearray (DBusMessageIter *iter,
59 static gboolean demarshal_valuearray (DBusGValueMarshalCtx *context,
60 DBusMessageIter *iter,
63 static gboolean marshal_variant (DBusMessageIter *iter,
65 static gboolean demarshal_variant (DBusGValueMarshalCtx *context,
66 DBusMessageIter *iter,
69 static gboolean marshal_proxy (DBusMessageIter *iter,
71 static gboolean demarshal_proxy (DBusGValueMarshalCtx *context,
72 DBusMessageIter *iter,
75 static gboolean marshal_object_path (DBusMessageIter *iter,
77 static gboolean demarshal_object_path (DBusGValueMarshalCtx *context,
78 DBusMessageIter *iter,
81 static gboolean marshal_object (DBusMessageIter *iter,
83 static gboolean demarshal_object (DBusGValueMarshalCtx *context,
84 DBusMessageIter *iter,
87 static gboolean marshal_signature (DBusMessageIter *iter,
89 static gboolean demarshal_signature (DBusGValueMarshalCtx *context,
90 DBusMessageIter *iter,
93 static gboolean marshal_map (DBusMessageIter *iter,
95 static gboolean demarshal_map (DBusGValueMarshalCtx *context,
96 DBusMessageIter *iter,
100 static gboolean marshal_collection (DBusMessageIter *iter,
101 const GValue *value);
102 static gboolean marshal_collection_ptrarray (DBusMessageIter *iter,
103 const GValue *value);
104 static gboolean marshal_collection_array (DBusMessageIter *iter,
105 const GValue *value);
106 static gboolean demarshal_collection (DBusGValueMarshalCtx *context,
107 DBusMessageIter *iter,
110 static gboolean demarshal_collection_ptrarray (DBusGValueMarshalCtx *context,
111 DBusMessageIter *iter,
114 static gboolean demarshal_collection_array (DBusGValueMarshalCtx *context,
115 DBusMessageIter *iter,
118 static gboolean marshal_struct (DBusMessageIter *iter,
119 const GValue *value);
120 static gboolean demarshal_struct (DBusGValueMarshalCtx *context,
121 DBusMessageIter *iter,
126 typedef gboolean (*DBusGValueMarshalFunc) (DBusMessageIter *iter,
127 const GValue *value);
128 typedef gboolean (*DBusGValueDemarshalFunc) (DBusGValueMarshalCtx *context,
129 DBusMessageIter *iter,
134 DBusGValueMarshalFunc marshaller;
135 DBusGValueDemarshalFunc demarshaller;
136 } DBusGTypeMarshalVtable;
140 const DBusGTypeMarshalVtable *vtable;
141 } DBusGTypeMarshalData;
144 dbus_g_type_metadata_data_quark ()
148 quark = g_quark_from_static_string ("DBusGTypeMetaData");
154 set_type_metadata (GType type, const DBusGTypeMarshalData *data)
156 g_type_set_qdata (type, dbus_g_type_metadata_data_quark (), (gpointer) data);
160 register_basic (int typecode, const DBusGTypeMarshalData *typedata)
162 set_type_metadata (_dbus_gtype_from_basic_typecode (typecode), typedata);
166 _dbus_g_value_types_init (void)
168 static gboolean types_initialized;
170 static const DBusGTypeMarshalVtable basic_vtable = {
175 if (types_initialized)
178 dbus_g_type_specialized_init ();
180 /* Register basic types */
182 static const DBusGTypeMarshalData typedata = {
183 DBUS_TYPE_BOOLEAN_AS_STRING,
186 register_basic (DBUS_TYPE_BOOLEAN, &typedata);
189 static const DBusGTypeMarshalData typedata = {
190 DBUS_TYPE_BYTE_AS_STRING,
193 register_basic (DBUS_TYPE_BYTE, &typedata);
196 static const DBusGTypeMarshalData typedata = {
197 DBUS_TYPE_INT16_AS_STRING,
200 register_basic (DBUS_TYPE_INT16, &typedata);
203 static const DBusGTypeMarshalData typedata = {
204 DBUS_TYPE_UINT16_AS_STRING,
207 register_basic (DBUS_TYPE_UINT16, &typedata);
210 static const DBusGTypeMarshalData typedata = {
211 DBUS_TYPE_UINT32_AS_STRING,
214 register_basic (DBUS_TYPE_UINT32, &typedata);
217 static const DBusGTypeMarshalData typedata = {
218 DBUS_TYPE_INT32_AS_STRING,
221 register_basic (DBUS_TYPE_INT32, &typedata);
224 static const DBusGTypeMarshalData typedata = {
225 DBUS_TYPE_UINT64_AS_STRING,
228 register_basic (DBUS_TYPE_UINT64, &typedata);
231 static const DBusGTypeMarshalData typedata = {
232 DBUS_TYPE_INT64_AS_STRING,
235 register_basic (DBUS_TYPE_INT64, &typedata);
238 static const DBusGTypeMarshalData typedata = {
239 DBUS_TYPE_DOUBLE_AS_STRING,
242 register_basic (DBUS_TYPE_DOUBLE, &typedata);
245 static const DBusGTypeMarshalData typedata = {
246 DBUS_TYPE_STRING_AS_STRING,
249 register_basic (DBUS_TYPE_STRING, &typedata);
251 /* fundamental GTypes that don't map 1:1 with D-BUS types */
253 static const DBusGTypeMarshalData typedata = {
254 DBUS_TYPE_BYTE_AS_STRING,
257 set_type_metadata (G_TYPE_CHAR, &typedata);
260 static const DBusGTypeMarshalData typedata = {
261 DBUS_TYPE_INT32_AS_STRING,
264 set_type_metadata (G_TYPE_LONG, &typedata);
267 static const DBusGTypeMarshalData typedata = {
268 DBUS_TYPE_UINT32_AS_STRING,
271 set_type_metadata (G_TYPE_ULONG, &typedata);
274 static const DBusGTypeMarshalData typedata = {
275 DBUS_TYPE_DOUBLE_AS_STRING,
278 set_type_metadata (G_TYPE_FLOAT, &typedata);
281 /* Register complex types with builtin GType mappings */
283 static const DBusGTypeMarshalVtable vtable = {
287 static const DBusGTypeMarshalData typedata = {
288 DBUS_TYPE_VARIANT_AS_STRING,
291 set_type_metadata (G_TYPE_VALUE, &typedata);
294 static const DBusGTypeMarshalVtable vtable = {
298 static const DBusGTypeMarshalData typedata = {
299 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
302 set_type_metadata (G_TYPE_STRV, &typedata);
306 /* Register some types specific to the D-BUS GLib bindings */
308 static const DBusGTypeMarshalVtable vtable = {
312 static const DBusGTypeMarshalData typedata = {
313 DBUS_TYPE_OBJECT_PATH_AS_STRING,
316 set_type_metadata (DBUS_TYPE_G_PROXY, &typedata);
320 static const DBusGTypeMarshalVtable vtable = {
322 demarshal_object_path
324 static const DBusGTypeMarshalData typedata = {
325 DBUS_TYPE_OBJECT_PATH_AS_STRING,
328 set_type_metadata (DBUS_TYPE_G_OBJECT_PATH, &typedata);
332 static const DBusGTypeMarshalVtable vtable = {
336 static const DBusGTypeMarshalData typedata = {
337 DBUS_TYPE_OBJECT_PATH_AS_STRING,
340 set_type_metadata (G_TYPE_OBJECT, &typedata);
344 static const DBusGTypeMarshalVtable vtable = {
348 static const DBusGTypeMarshalData typedata = {
349 DBUS_TYPE_SIGNATURE_AS_STRING,
352 set_type_metadata (DBUS_TYPE_G_SIGNATURE, &typedata);
355 types_initialized = TRUE;
361 * A typedef for a string used to represent D-Bus object paths.
362 * Its GType is %DBUS_TYPE_G_OBJECT_PATH, derived from %G_TYPE_BOXED.
364 * Prior to version 0.FIXME this was used as the type name of
365 * %DBUS_TYPE_G_OBJECT_PATH, but did not actually exist as a typedef.
371 * DBUS_TYPE_G_OBJECT_PATH:
373 * The #GType of a #DBusGObjectPath, which is a boxed type containing a
374 * D-Bus object path as a zero-terminated string. Object paths can be
375 * copied with g_strdup() and freed with g_free(), just like %G_TYPE_STRING,
376 * but have a distinct boxed type to allow them to be distinguished when
377 * stored in a #GValue.
379 * Returns: a type derived from %G_TYPE_BOXED
382 dbus_g_object_path_get_g_type (void)
384 static GType type_id = 0;
387 type_id = g_boxed_type_register_static ("DBusGObjectPath",
388 (GBoxedCopyFunc) g_strdup,
389 (GBoxedFreeFunc) g_free);
396 * A typedef for a string used to represent D-Bus signatures.
397 * Its GType is %DBUS_TYPE_G_SIGNATURE, derived from %G_TYPE_BOXED.
399 * Prior to version 0.FIXME this was used as the type name of
400 * %DBUS_TYPE_G_SIGNATURE, but did not actually exist as a typedef.
406 * DBUS_TYPE_G_SIGNATURE:
408 * The #GType of a #DBusGSignature, which is a boxed type containing a
409 * D-Bus signature as a zero-terminated string. Signatures can be
410 * copied with g_strdup() and freed with g_free(), just like %G_TYPE_STRING,
411 * but have a distinct boxed type to allow them to be distinguished when
412 * stored in a #GValue.
414 * Returns: a type derived from %G_TYPE_BOXED
417 dbus_g_signature_get_g_type (void)
419 static GType type_id = 0;
421 if (G_UNLIKELY (type_id == 0))
422 type_id = g_boxed_type_register_static ("DBusGSignature",
423 (GBoxedCopyFunc) g_strdup,
424 (GBoxedFreeFunc) g_free);
431 _dbus_gtype_to_signature (GType gtype)
434 DBusGTypeMarshalData *typedata;
436 if (dbus_g_type_is_collection (gtype))
441 elt_gtype = dbus_g_type_get_collection_specialization (gtype);
442 subsig = _dbus_gtype_to_signature (elt_gtype);
443 ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING, subsig, NULL);
446 else if (dbus_g_type_is_map (gtype))
453 key_gtype = dbus_g_type_get_map_key_specialization (gtype);
454 val_gtype = dbus_g_type_get_map_value_specialization (gtype);
455 key_subsig = _dbus_gtype_to_signature (key_gtype);
456 val_subsig = _dbus_gtype_to_signature (val_gtype);
457 ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING, key_subsig, val_subsig, DBUS_DICT_ENTRY_END_CHAR_AS_STRING, NULL);
461 else if (dbus_g_type_is_struct (gtype))
465 size = dbus_g_type_get_struct_size (gtype);
466 sig = g_string_sized_new (size+2); /*some sensible starting size*/
467 g_string_assign (sig, DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
468 for (i = 0; i < size; i++)
471 subsig = _dbus_gtype_to_signature (
472 dbus_g_type_get_struct_member_type (gtype, i));
473 g_string_append (sig, subsig);
476 g_string_append (sig, DBUS_STRUCT_END_CHAR_AS_STRING);
477 ret = g_string_free (sig, FALSE);
481 typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ());
482 if (typedata == NULL)
484 ret = g_strdup (typedata->sig);
490 _dbus_gvalue_to_signature (const GValue *val)
494 gtype = G_VALUE_TYPE (val);
495 if (g_type_is_a (gtype, G_TYPE_VALUE_ARRAY))
501 array = g_value_get_boxed (val);
503 str = g_string_new (DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
504 for (i = 0; i < array->n_values; i++)
507 sig = _dbus_gvalue_to_signature (g_value_array_get_nth (array, i));
508 g_string_append (str, sig);
511 g_string_append (str, DBUS_STRUCT_END_CHAR_AS_STRING);
513 return g_string_free (str, FALSE);
516 return _dbus_gtype_to_signature (gtype);
520 demarshal_basic (DBusGValueMarshalCtx *context,
521 DBusMessageIter *iter,
527 current_type = dbus_message_iter_get_arg_type (iter);
528 g_assert (dbus_type_is_basic (current_type));
530 switch (current_type)
532 case DBUS_TYPE_BOOLEAN:
535 if (!G_VALUE_HOLDS (value, G_TYPE_BOOLEAN))
537 dbus_message_iter_get_basic (iter, &bool);
538 g_value_set_boolean (value, bool);
544 if (!G_VALUE_HOLDS (value, G_TYPE_UCHAR))
546 dbus_message_iter_get_basic (iter, &byte);
547 g_value_set_uchar (value, byte);
550 case DBUS_TYPE_INT32:
553 if (!G_VALUE_HOLDS (value, G_TYPE_INT))
555 dbus_message_iter_get_basic (iter, &intval);
556 g_value_set_int (value, intval);
559 case DBUS_TYPE_UINT32:
561 dbus_uint32_t intval;
562 if (!G_VALUE_HOLDS (value, G_TYPE_UINT))
564 dbus_message_iter_get_basic (iter, &intval);
565 g_value_set_uint (value, intval);
568 case DBUS_TYPE_INT64:
571 if (!G_VALUE_HOLDS (value, G_TYPE_INT64))
573 dbus_message_iter_get_basic (iter, &intval);
574 g_value_set_int64 (value, intval);
577 case DBUS_TYPE_UINT64:
579 dbus_uint64_t intval;
580 if (!G_VALUE_HOLDS (value, G_TYPE_UINT64))
582 dbus_message_iter_get_basic (iter, &intval);
583 g_value_set_uint64 (value, intval);
586 case DBUS_TYPE_DOUBLE:
589 if (!G_VALUE_HOLDS (value, G_TYPE_DOUBLE))
591 dbus_message_iter_get_basic (iter, &dval);
592 g_value_set_double (value, dval);
595 case DBUS_TYPE_INT16:
598 if (!G_VALUE_HOLDS (value, G_TYPE_INT))
600 dbus_message_iter_get_basic (iter, &v);
601 g_value_set_int (value, v);
604 case DBUS_TYPE_UINT16:
607 if (!G_VALUE_HOLDS (value, G_TYPE_UINT))
609 dbus_message_iter_get_basic (iter, &v);
610 g_value_set_uint (value, v);
613 case DBUS_TYPE_STRING:
616 if (!G_VALUE_HOLDS (value, G_TYPE_STRING))
618 dbus_message_iter_get_basic (iter, &s);
619 g_value_set_string (value, s);
623 /* fall through to invalid_type */
629 DBUS_GERROR_INVALID_ARGS,
630 "Expected type %s, got type code \'%c\'",
631 g_type_name (G_VALUE_TYPE (value)),
632 (guchar) current_type);
637 demarshal_static_variant (DBusGValueMarshalCtx *context,
638 DBusMessageIter *iter,
643 DBusMessageIter subiter;
646 dbus_message_iter_recurse (iter, &subiter);
647 sig = dbus_message_iter_get_signature (&subiter);
649 variant_type = _dbus_gtype_from_signature (sig, context->proxy != NULL);
650 if (variant_type != G_TYPE_INVALID)
652 g_value_init (value, variant_type);
654 if (!_dbus_gvalue_demarshal (context, &subiter, value, error))
665 demarshal_variant (DBusGValueMarshalCtx *context,
666 DBusMessageIter *iter,
672 variant_val = g_new0 (GValue, 1);
674 if (!demarshal_static_variant (context, iter, variant_val, error))
677 g_value_take_boxed (value, variant_val);
682 demarshal_proxy (DBusGValueMarshalCtx *context,
683 DBusMessageIter *iter,
687 DBusGProxy *new_proxy;
691 current_type = dbus_message_iter_get_arg_type (iter);
692 if (current_type != DBUS_TYPE_OBJECT_PATH)
696 DBUS_GERROR_INVALID_ARGS,
697 "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
701 g_assert (context->proxy != NULL);
703 dbus_message_iter_get_basic (iter, &objpath);
705 new_proxy = dbus_g_proxy_new_from_proxy (context->proxy, NULL, objpath);
706 g_value_take_object (value, new_proxy);
712 demarshal_object_path (DBusGValueMarshalCtx *context,
713 DBusMessageIter *iter,
720 current_type = dbus_message_iter_get_arg_type (iter);
721 if (current_type != DBUS_TYPE_OBJECT_PATH)
725 DBUS_GERROR_INVALID_ARGS,
726 "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
730 dbus_message_iter_get_basic (iter, &objpath);
732 g_value_set_boxed (value, objpath);
738 demarshal_object (DBusGValueMarshalCtx *context,
739 DBusMessageIter *iter,
747 current_type = dbus_message_iter_get_arg_type (iter);
748 if (current_type != DBUS_TYPE_OBJECT_PATH)
752 DBUS_GERROR_INVALID_ARGS,
753 "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
756 g_assert (context->proxy == NULL);
758 dbus_message_iter_get_basic (iter, &objpath);
760 obj = dbus_g_connection_lookup_g_object (context->gconnection, objpath);
765 DBUS_GERROR_INVALID_ARGS,
766 "Unregistered object at path '%s'",
770 g_value_set_object (value, obj);
776 demarshal_signature (DBusGValueMarshalCtx *context,
777 DBusMessageIter *iter,
784 current_type = dbus_message_iter_get_arg_type (iter);
785 if (current_type != DBUS_TYPE_SIGNATURE)
789 DBUS_GERROR_INVALID_ARGS,
790 "Expected D-BUS signature, got type code \'%c\'", (guchar) current_type);
794 dbus_message_iter_get_basic (iter, &sig);
796 g_value_set_boxed (value, sig);
802 demarshal_strv (DBusGValueMarshalCtx *context,
803 DBusMessageIter *iter,
807 DBusMessageIter subiter;
811 current_type = dbus_message_iter_get_arg_type (iter);
812 if (current_type != DBUS_TYPE_ARRAY)
816 DBUS_GERROR_INVALID_ARGS,
817 "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
821 dbus_message_iter_recurse (iter, &subiter);
823 current_type = dbus_message_iter_get_arg_type (&subiter);
824 if (current_type != DBUS_TYPE_INVALID
825 && current_type != DBUS_TYPE_STRING)
829 DBUS_GERROR_INVALID_ARGS,
830 "Expected D-BUS string, got type code \'%c\'", (guchar) current_type);
834 arr = g_array_new (TRUE, FALSE, sizeof (char *));
836 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
838 g_assert (current_type == DBUS_TYPE_STRING);
842 dbus_message_iter_get_basic (&subiter, &str);
843 copy = g_strdup (str);
844 g_array_append_val (arr, copy);
846 dbus_message_iter_next (&subiter);
849 g_value_take_boxed (value, arr->data);
850 g_array_free (arr, FALSE);
856 demarshal_valuearray (DBusGValueMarshalCtx *context,
857 DBusMessageIter *iter,
863 DBusMessageIter subiter;
865 current_type = dbus_message_iter_get_arg_type (iter);
866 if (current_type != DBUS_TYPE_STRUCT)
870 DBUS_GERROR_INVALID_ARGS,
871 "Expected D-BUS struct, got type code \'%c\'", (guchar) current_type);
875 dbus_message_iter_recurse (iter, &subiter);
877 ret = g_value_array_new (12);
879 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
885 g_value_array_append (ret, NULL);
886 val = g_value_array_get_nth (ret, ret->n_values - 1);
888 current_sig = dbus_message_iter_get_signature (&subiter);
889 elt_type = _dbus_gtype_from_signature (current_sig, TRUE);
891 if (elt_type == G_TYPE_INVALID)
893 g_value_array_free (ret);
896 DBUS_GERROR_INVALID_ARGS,
897 "Couldn't demarshal argument with signature \"%s\"", current_sig);
898 dbus_free (current_sig);
901 dbus_free (current_sig);
903 g_value_init (val, elt_type);
905 if (!_dbus_gvalue_demarshal (context, &subiter, val, error))
907 g_value_array_free (ret);
911 dbus_message_iter_next (&subiter);
914 g_value_take_boxed (value, ret);
920 demarshal_map (DBusGValueMarshalCtx *context,
921 DBusMessageIter *iter,
926 DBusMessageIter subiter;
931 DBusGTypeSpecializedAppendContext appendctx;
933 current_type = dbus_message_iter_get_arg_type (iter);
934 if (current_type != DBUS_TYPE_ARRAY)
938 DBUS_GERROR_INVALID_ARGS,
939 "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
943 gtype = G_VALUE_TYPE (value);
945 dbus_message_iter_recurse (iter, &subiter);
947 current_type = dbus_message_iter_get_arg_type (&subiter);
948 if (current_type != DBUS_TYPE_INVALID
949 && current_type != DBUS_TYPE_DICT_ENTRY)
953 DBUS_GERROR_INVALID_ARGS,
954 "Expected D-BUS dict entry, got type code \'%c\'", (guchar) current_type);
958 key_gtype = dbus_g_type_get_map_key_specialization (gtype);
959 value_gtype = dbus_g_type_get_map_value_specialization (gtype);
961 ret = dbus_g_type_specialized_construct (gtype);
962 g_value_take_boxed (value, ret);
964 dbus_g_type_specialized_init_append (value, &appendctx);
966 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
968 DBusMessageIter entry_iter;
969 GValue key_value = {0,};
970 GValue value_value = {0,};
972 current_type = dbus_message_iter_get_arg_type (&subiter);
973 g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
975 dbus_message_iter_recurse (&subiter, &entry_iter);
977 g_value_init (&key_value, key_gtype);
978 if (!_dbus_gvalue_demarshal (context,
984 dbus_message_iter_next (&entry_iter);
986 g_value_init (&value_value, value_gtype);
987 if (!_dbus_gvalue_demarshal (context,
993 dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
994 /* Ownership of values passes to map, don't unset */
996 dbus_message_iter_next (&subiter);
1003 demarshal_struct (DBusGValueMarshalCtx *context,
1004 DBusMessageIter *iter,
1009 DBusMessageIter subiter;
1014 current_type = dbus_message_iter_get_arg_type (iter);
1015 if (current_type != DBUS_TYPE_STRUCT)
1019 DBUS_GERROR_INVALID_ARGS,
1020 "Expected D-BUS struct, got type code \'%c\'", (guchar) current_type);
1024 dbus_message_iter_recurse (iter, &subiter);
1026 g_value_take_boxed (value,
1027 dbus_g_type_specialized_construct (G_VALUE_TYPE (value)));
1029 size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value));
1031 for (i=0; i < size; i++)
1034 elt_type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE(value), i);
1035 if (elt_type == G_TYPE_INVALID)
1037 g_value_unset (value);
1040 DBUS_GERROR_INVALID_ARGS,
1041 "Couldn't demarshal argument, "
1042 "struct type %s has no member %d",
1043 g_type_name (G_VALUE_TYPE(value)), i);
1047 g_value_init (&val, elt_type);
1049 if (!_dbus_gvalue_demarshal (context, &subiter, &val, error))
1051 g_value_unset (&val);
1052 g_value_unset (value);
1055 if (!dbus_g_type_struct_set_member (value, i, &val))
1057 g_value_unset (&val);
1058 g_value_unset (value);
1062 dbus_message_iter_next (&subiter);
1063 g_value_unset (&val);
1066 g_assert (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_INVALID);
1072 static DBusGValueDemarshalFunc
1073 get_type_demarshaller (GType type)
1075 DBusGTypeMarshalData *typedata;
1077 typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
1078 if (typedata == NULL)
1080 if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
1081 return demarshal_valuearray;
1082 if (dbus_g_type_is_collection (type))
1083 return demarshal_collection;
1084 if (dbus_g_type_is_map (type))
1085 return demarshal_map;
1086 if (dbus_g_type_is_struct (type))
1087 return demarshal_struct;
1089 g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
1092 g_assert (typedata->vtable);
1093 return typedata->vtable->demarshaller;
1097 demarshal_collection (DBusGValueMarshalCtx *context,
1098 DBusMessageIter *iter,
1105 coltype = G_VALUE_TYPE (value);
1106 subtype = dbus_g_type_get_collection_specialization (coltype);
1108 if (_dbus_g_type_is_fixed (subtype))
1109 return demarshal_collection_array (context, iter, value, error);
1111 return demarshal_collection_ptrarray (context, iter, value, error);
1115 demarshal_collection_ptrarray (DBusGValueMarshalCtx *context,
1116 DBusMessageIter *iter,
1123 DBusGTypeSpecializedAppendContext ctx;
1124 DBusGValueDemarshalFunc demarshaller;
1125 DBusMessageIter subiter;
1128 current_type = dbus_message_iter_get_arg_type (iter);
1130 if (current_type != DBUS_TYPE_ARRAY)
1134 DBUS_GERROR_INVALID_ARGS,
1135 "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
1139 dbus_message_iter_recurse (iter, &subiter);
1141 coltype = G_VALUE_TYPE (value);
1142 subtype = dbus_g_type_get_collection_specialization (coltype);
1144 demarshaller = get_type_demarshaller (subtype);
1150 DBUS_GERROR_INVALID_ARGS,
1151 "No demarshaller registered for type \"%s\" of collection \"%s\"",
1152 g_type_name (coltype),
1153 g_type_name (subtype));
1157 instance = dbus_g_type_specialized_construct (coltype);
1158 g_value_take_boxed (value, instance);
1160 dbus_g_type_specialized_init_append (value, &ctx);
1162 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
1164 GValue eltval = {0, };
1166 g_value_init (&eltval, subtype);
1168 if (!demarshaller (context, &subiter, &eltval, error))
1170 dbus_g_type_specialized_collection_end_append (&ctx);
1171 g_value_unset (value);
1174 dbus_g_type_specialized_collection_append (&ctx, &eltval);
1176 dbus_message_iter_next (&subiter);
1178 dbus_g_type_specialized_collection_end_append (&ctx);
1184 demarshal_collection_array (DBusGValueMarshalCtx *context,
1185 DBusMessageIter *iter,
1189 DBusMessageIter subiter;
1196 dbus_message_iter_recurse (iter, &subiter);
1198 elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
1199 g_assert (elt_gtype != G_TYPE_INVALID);
1200 g_assert (_dbus_g_type_is_fixed (elt_gtype));
1202 elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
1204 ret = g_array_new (FALSE, TRUE, elt_size);
1207 dbus_message_iter_get_fixed_array (&subiter,
1210 g_assert (msgarray != NULL || msgarray_len == 0);
1213 g_array_append_vals (ret, msgarray, (guint) msgarray_len);
1215 g_value_take_boxed (value, ret);
1221 _dbus_gvalue_demarshal (DBusGValueMarshalCtx *context,
1222 DBusMessageIter *iter,
1227 DBusGValueDemarshalFunc demarshaller;
1228 gboolean retcode = FALSE;
1230 if (context->recursion_depth > DBUS_GLIB_MAX_VARIANT_RECURSION)
1232 g_set_error (error, DBUS_GERROR,
1233 DBUS_GERROR_NO_MEMORY,
1234 "Variant recursion limit exceeded");
1237 context->recursion_depth++;
1239 gtype = G_VALUE_TYPE (value);
1241 demarshaller = get_type_demarshaller (gtype);
1243 if (demarshaller == NULL)
1247 DBUS_GERROR_INVALID_ARGS,
1248 "No demarshaller registered for type \"%s\"",
1249 g_type_name (gtype));
1254 retcode = demarshaller (context, iter, value, error);
1256 context->recursion_depth--;
1261 _dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx *context,
1262 DBusMessageIter *iter,
1266 return demarshal_static_variant (context, iter, value, error);
1270 _dbus_gvalue_demarshal_message (DBusGValueMarshalCtx *context,
1271 DBusMessage *message,
1277 DBusMessageIter iter;
1281 ret = g_value_array_new (6); /* 6 is a typical maximum for arguments */
1283 dbus_message_iter_init (message, &iter);
1285 while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
1290 if (index_ >= n_types)
1292 g_set_error (error, DBUS_GERROR,
1293 DBUS_GERROR_INVALID_ARGS,
1294 "Too many arguments in message");
1298 g_value_array_append (ret, NULL);
1299 value = g_value_array_get_nth (ret, index_);
1301 gtype = types[index_];
1302 g_value_init (value, gtype);
1304 if (!_dbus_gvalue_demarshal (context, &iter, value, error))
1306 dbus_message_iter_next (&iter);
1309 if (index_ < n_types)
1311 g_set_error (error, DBUS_GERROR,
1312 DBUS_GERROR_INVALID_ARGS,
1313 "Too few arguments in message");
1319 g_value_array_free (ret);
1323 static void oom (void) G_GNUC_NORETURN;
1327 g_error ("no memory");
1331 marshal_basic (DBusMessageIter *iter, const GValue *value)
1335 value_type = G_VALUE_TYPE (value);
1341 char b = g_value_get_char (value);
1342 if (!dbus_message_iter_append_basic (iter,
1350 unsigned char b = g_value_get_uchar (value);
1351 if (!dbus_message_iter_append_basic (iter,
1357 case G_TYPE_BOOLEAN:
1359 dbus_bool_t b = g_value_get_boolean (value);
1361 g_return_val_if_fail (b == TRUE || b == FALSE, FALSE);
1363 if (!dbus_message_iter_append_basic (iter,
1371 dbus_int32_t v = g_value_get_int (value);
1372 if (!dbus_message_iter_append_basic (iter,
1380 dbus_uint32_t v = g_value_get_uint (value);
1381 if (!dbus_message_iter_append_basic (iter,
1389 dbus_int32_t v = g_value_get_long (value);
1390 if (!dbus_message_iter_append_basic (iter,
1398 dbus_uint32_t v = g_value_get_ulong (value);
1399 if (!dbus_message_iter_append_basic (iter,
1407 gint64 v = g_value_get_int64 (value);
1408 if (!dbus_message_iter_append_basic (iter,
1416 guint64 v = g_value_get_uint64 (value);
1417 if (!dbus_message_iter_append_basic (iter,
1425 double v = g_value_get_float (value);
1427 if (!dbus_message_iter_append_basic (iter,
1435 double v = g_value_get_double (value);
1437 if (!dbus_message_iter_append_basic (iter,
1445 const char *v = g_value_get_string (value);
1449 /* FIXME: fd.o #16320: consider using g_return_if_fail to check UTF-8
1452 if (!dbus_message_iter_append_basic (iter,
1456 gchar *s = g_strdup_value_contents (value);
1458 g_critical ("Unable to marshal string (not UTF-8 or OOM?): %s",
1468 g_assert_not_reached ();
1475 marshal_strv (DBusMessageIter *iter,
1476 const GValue *value)
1478 DBusMessageIter subiter;
1481 gboolean ret = FALSE;
1483 g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
1485 array = g_value_get_boxed (value);
1487 if (!dbus_message_iter_open_container (iter,
1495 for (elt = array; *elt; elt++)
1497 if (!dbus_message_iter_append_basic (&subiter,
1504 if (!dbus_message_iter_close_container (iter, &subiter))
1512 marshal_valuearray (DBusMessageIter *iter,
1513 const GValue *value)
1517 DBusMessageIter subiter;
1519 g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
1521 array = g_value_get_boxed (value);
1523 if (!dbus_message_iter_open_container (iter,
1531 for (i = 0; i < array->n_values; i++)
1533 if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
1535 dbus_message_iter_abandon_container (iter, &subiter);
1541 return dbus_message_iter_close_container (iter, &subiter);
1545 marshal_proxy (DBusMessageIter *iter,
1546 const GValue *value)
1551 g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
1553 proxy = g_value_get_object (value);
1554 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
1555 path = dbus_g_proxy_get_path (proxy);
1556 g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
1558 if (!dbus_message_iter_append_basic (iter,
1559 DBUS_TYPE_OBJECT_PATH,
1567 marshal_object_path (DBusMessageIter *iter,
1568 const GValue *value)
1572 g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
1574 path = g_value_get_boxed (value);
1575 g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
1577 if (!dbus_message_iter_append_basic (iter,
1578 DBUS_TYPE_OBJECT_PATH,
1586 marshal_object (DBusMessageIter *iter,
1587 const GValue *value)
1592 obj = g_value_get_object (value);
1593 g_return_val_if_fail (G_IS_OBJECT (obj), FALSE);
1595 path = _dbus_gobject_get_path (obj);
1596 g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
1598 if (!dbus_message_iter_append_basic (iter,
1599 DBUS_TYPE_OBJECT_PATH,
1607 marshal_signature (DBusMessageIter *iter,
1608 const GValue *value)
1612 g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_SIGNATURE);
1614 sig = g_value_get_boxed (value);
1615 g_return_val_if_fail (g_variant_is_signature (sig), FALSE);
1617 /* failure here isn't strictly *guaranteed* to be OOM, since GDBus might
1618 * understand more type-codes than our libdbus */
1619 if (!dbus_message_iter_append_basic (iter,
1620 DBUS_TYPE_SIGNATURE,
1627 struct DBusGLibHashMarshalData
1629 const char *entry_sig;
1630 DBusMessageIter *iter;
1635 marshal_map_entry (const GValue *key,
1636 const GValue *value,
1639 struct DBusGLibHashMarshalData *hashdata = data;
1640 DBusMessageIter subiter;
1645 if (!dbus_message_iter_open_container (hashdata->iter,
1646 DBUS_TYPE_DICT_ENTRY,
1651 if (!_dbus_gvalue_marshal (&subiter, key))
1654 if (!_dbus_gvalue_marshal (&subiter, value))
1657 if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
1662 hashdata->err = TRUE;
1666 marshal_map (DBusMessageIter *iter,
1667 const GValue *value)
1670 DBusMessageIter arr_iter;
1671 struct DBusGLibHashMarshalData hashdata;
1679 gtype = G_VALUE_TYPE (value);
1681 key_type = dbus_g_type_get_map_key_specialization (gtype);
1682 g_assert (_dbus_gtype_is_valid_hash_key (key_type));
1683 value_type = dbus_g_type_get_map_value_specialization (gtype);
1684 g_assert (_dbus_gtype_is_valid_hash_value (value_type));
1686 key_sig = _dbus_gtype_to_signature (key_type);
1689 g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
1692 value_sig = _dbus_gtype_to_signature (value_type);
1696 g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
1699 entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
1702 array_sig = g_strdup_printf ("%c%s%c",
1703 DBUS_DICT_ENTRY_BEGIN_CHAR,
1705 DBUS_DICT_ENTRY_END_CHAR);
1706 if (!dbus_message_iter_open_container (iter,
1712 hashdata.iter = &arr_iter;
1713 hashdata.err = FALSE;
1714 hashdata.entry_sig = entry_sig;
1716 dbus_g_type_map_value_iterate (value,
1722 dbus_message_iter_abandon_container (iter, &arr_iter);
1725 else if (!dbus_message_iter_close_container (iter, &arr_iter))
1733 return !hashdata.err;
1735 hashdata.err = TRUE;
1740 marshal_struct (DBusMessageIter *iter,
1741 const GValue *value)
1744 DBusMessageIter subiter;
1748 gtype = G_VALUE_TYPE (value);
1750 size = dbus_g_type_get_struct_size (gtype);
1752 if (!dbus_message_iter_open_container (iter,
1758 for (i = 0; i < size; i++)
1760 g_value_init (&val, dbus_g_type_get_struct_member_type
1761 (G_VALUE_TYPE(value), i));
1763 if (!dbus_g_type_struct_get_member (value, i, &val))
1766 if (!_dbus_gvalue_marshal (&subiter, &val))
1769 g_value_unset(&val);
1772 return dbus_message_iter_close_container (iter, &subiter);
1775 dbus_message_iter_abandon_container (iter, &subiter);
1780 marshal_variant (DBusMessageIter *iter,
1781 const GValue *value)
1784 DBusMessageIter subiter;
1787 gboolean ret = FALSE;
1789 real_value = g_value_get_boxed (value);
1790 value_gtype = G_VALUE_TYPE (real_value);
1792 variant_sig = _dbus_gvalue_to_signature (real_value);
1793 if (variant_sig == NULL)
1795 g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
1799 if (!dbus_message_iter_open_container (iter,
1805 if (!_dbus_gvalue_marshal (&subiter, real_value))
1807 dbus_message_iter_abandon_container (iter, &subiter);
1811 if (!dbus_message_iter_close_container (iter, &subiter))
1816 g_free (variant_sig);
1820 static DBusGValueMarshalFunc
1821 get_type_marshaller (GType type)
1823 DBusGTypeMarshalData *typedata;
1825 typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
1826 if (typedata == NULL)
1828 if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
1829 return marshal_valuearray;
1830 if (dbus_g_type_is_collection (type))
1831 return marshal_collection;
1832 if (dbus_g_type_is_map (type))
1834 if (dbus_g_type_is_struct (type))
1835 return marshal_struct;
1837 g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
1840 g_assert (typedata->vtable);
1841 return typedata->vtable->marshaller;
1846 DBusMessageIter *iter;
1847 DBusGValueMarshalFunc marshaller;
1849 } DBusGValueCollectionMarshalData;
1852 collection_marshal_iterator (const GValue *eltval,
1855 DBusGValueCollectionMarshalData *data = user_data;
1860 if (!data->marshaller (data->iter, eltval))
1865 marshal_collection (DBusMessageIter *iter,
1866 const GValue *value)
1871 coltype = G_VALUE_TYPE (value);
1872 subtype = dbus_g_type_get_collection_specialization (coltype);
1874 if (_dbus_g_type_is_fixed (subtype))
1875 return marshal_collection_array (iter, value);
1877 return marshal_collection_ptrarray (iter, value);
1881 marshal_collection_ptrarray (DBusMessageIter *iter,
1882 const GValue *value)
1886 DBusGValueCollectionMarshalData data;
1887 DBusMessageIter subiter;
1890 coltype = G_VALUE_TYPE (value);
1891 elt_gtype = dbus_g_type_get_collection_specialization (coltype);
1892 data.marshaller = get_type_marshaller (elt_gtype);
1893 if (!data.marshaller)
1896 elt_sig = _dbus_gtype_to_signature (elt_gtype);
1899 g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
1902 g_assert (g_variant_is_signature (elt_sig));
1904 if (!dbus_message_iter_open_container (iter,
1912 data.iter = &subiter;
1915 dbus_g_type_collection_value_iterate (value,
1916 collection_marshal_iterator,
1921 dbus_message_iter_abandon_container (iter, &subiter);
1925 return dbus_message_iter_close_container (iter, &subiter);
1928 /* If any of these assertions are violated, then marshal_collection_array
1929 * is buggy for that type. dbus_g_value_basic_array_parse_variant() has
1930 * general size-conversion code, if needed. */
1931 G_STATIC_ASSERT (sizeof (dbus_bool_t) == sizeof (gboolean));
1932 G_STATIC_ASSERT (sizeof (dbus_int32_t) == sizeof (gint));
1933 G_STATIC_ASSERT (sizeof (dbus_uint32_t) == sizeof (guint));
1934 /* These should be true regardless, but just for completeness... */
1935 G_STATIC_ASSERT (sizeof (dbus_int64_t) == sizeof (gint64));
1936 G_STATIC_ASSERT (sizeof (dbus_uint64_t) == sizeof (guint64));
1937 G_STATIC_ASSERT (sizeof (double) == sizeof (gdouble));
1940 marshal_collection_array (DBusMessageIter *iter,
1941 const GValue *value)
1944 DBusMessageIter subiter;
1946 char *subsignature_str;
1948 array = g_value_get_boxed (value);
1949 g_return_val_if_fail (array != NULL, FALSE);
1951 elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
1952 g_assert (_dbus_g_type_is_fixed (elt_gtype));
1953 subsignature_str = _dbus_gtype_to_signature (elt_gtype);
1954 if (!subsignature_str)
1956 g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
1959 g_assert (g_variant_is_signature (subsignature_str));
1961 if (!dbus_message_iter_open_container (iter,
1967 /* TODO - This assumes that basic values are the same size
1968 * is this always true? If it is we can probably avoid
1969 * a lot of the overhead in _marshal_basic_instance...
1971 if (!dbus_message_iter_append_fixed_array (&subiter,
1972 subsignature_str[0],
1976 g_critical ("Unable to serialize %u GArray members as signature %s "
1977 "(OOM or invalid boolean value?)", array->len, subsignature_str);
1979 g_free (subsignature_str);
1980 dbus_message_iter_abandon_container (iter, &subiter);
1984 g_free (subsignature_str);
1985 return dbus_message_iter_close_container (iter, &subiter);
1989 _dbus_gvalue_marshal (DBusMessageIter *iter,
1990 const GValue *value)
1993 DBusGValueMarshalFunc marshaller;
1995 gtype = G_VALUE_TYPE (value);
1997 marshaller = get_type_marshaller (gtype);
1998 if (marshaller == NULL)
2000 return marshaller (iter, value);
2003 #ifdef DBUS_BUILD_TESTS
2006 assert_type_maps_to (GType gtype, const char *expected_sig)
2009 sig = _dbus_gtype_to_signature (gtype);
2010 g_assert (sig != NULL);
2011 g_assert (!strcmp (expected_sig, sig));
2016 assert_signature_maps_to (const char *sig, GType expected_gtype)
2018 g_assert (_dbus_gtype_from_signature (sig, TRUE) == expected_gtype);
2022 assert_bidirectional_mapping (GType gtype, const char *expected_sig)
2024 assert_type_maps_to (gtype, expected_sig);
2025 assert_signature_maps_to (expected_sig, gtype);
2029 * Unit test for general glib stuff
2030 * Returns: %TRUE on success.
2033 _dbus_gvalue_test (const char *test_data_dir)
2035 _dbus_g_value_types_init ();
2037 assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
2038 assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
2039 assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
2041 assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
2042 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);
2043 assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
2044 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
2045 assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
2046 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
2048 assert_bidirectional_mapping (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID),
2049 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 );
2053 #endif /* DBUS_BUILD_TESTS */