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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 <glib/gi18n.h>
35 #include "dbus/dbus-signature.h"
37 static gboolean demarshal_static_variant (DBusGValueMarshalCtx *context,
38 DBusMessageIter *iter,
43 static gboolean marshal_basic (DBusMessageIter *iter,
45 static gboolean demarshal_basic (DBusGValueMarshalCtx *context,
46 DBusMessageIter *iter,
49 static gboolean marshal_strv (DBusMessageIter *iter,
51 static gboolean demarshal_strv (DBusGValueMarshalCtx *context,
52 DBusMessageIter *iter,
55 static gboolean marshal_valuearray (DBusMessageIter *iter,
57 static gboolean demarshal_valuearray (DBusGValueMarshalCtx *context,
58 DBusMessageIter *iter,
61 static gboolean marshal_variant (DBusMessageIter *iter,
63 static gboolean demarshal_variant (DBusGValueMarshalCtx *context,
64 DBusMessageIter *iter,
67 static gboolean marshal_proxy (DBusMessageIter *iter,
69 static gboolean demarshal_proxy (DBusGValueMarshalCtx *context,
70 DBusMessageIter *iter,
73 static gboolean marshal_object_path (DBusMessageIter *iter,
75 static gboolean demarshal_object_path (DBusGValueMarshalCtx *context,
76 DBusMessageIter *iter,
79 static gboolean marshal_object (DBusMessageIter *iter,
81 static gboolean demarshal_object (DBusGValueMarshalCtx *context,
82 DBusMessageIter *iter,
85 static gboolean marshal_map (DBusMessageIter *iter,
87 static gboolean demarshal_map (DBusGValueMarshalCtx *context,
88 DBusMessageIter *iter,
92 static gboolean marshal_collection (DBusMessageIter *iter,
94 static gboolean marshal_collection_ptrarray (DBusMessageIter *iter,
96 static gboolean marshal_collection_array (DBusMessageIter *iter,
98 static gboolean demarshal_collection (DBusGValueMarshalCtx *context,
99 DBusMessageIter *iter,
102 static gboolean demarshal_collection_ptrarray (DBusGValueMarshalCtx *context,
103 DBusMessageIter *iter,
106 static gboolean demarshal_collection_array (DBusGValueMarshalCtx *context,
107 DBusMessageIter *iter,
111 typedef gboolean (*DBusGValueMarshalFunc) (DBusMessageIter *iter,
112 const GValue *value);
113 typedef gboolean (*DBusGValueDemarshalFunc) (DBusGValueMarshalCtx *context,
114 DBusMessageIter *iter,
119 DBusGValueMarshalFunc marshaller;
120 DBusGValueDemarshalFunc demarshaller;
121 } DBusGTypeMarshalVtable;
125 const DBusGTypeMarshalVtable *vtable;
126 } DBusGTypeMarshalData;
129 dbus_g_type_metadata_data_quark ()
133 quark = g_quark_from_static_string ("DBusGTypeMetaData");
139 set_type_metadata (GType type, const DBusGTypeMarshalData *data)
141 g_type_set_qdata (type, dbus_g_type_metadata_data_quark (), (gpointer) data);
145 register_basic (int typecode, const DBusGTypeMarshalData *typedata)
147 set_type_metadata (_dbus_gtype_from_basic_typecode (typecode), typedata);
151 _dbus_g_value_types_init (void)
153 static gboolean types_initialized;
155 static const DBusGTypeMarshalVtable basic_vtable = {
160 if (types_initialized)
163 dbus_g_type_specialized_init ();
164 _dbus_g_type_specialized_builtins_init ();
166 /* Register basic types */
168 static const DBusGTypeMarshalData typedata = {
169 DBUS_TYPE_BOOLEAN_AS_STRING,
172 register_basic (DBUS_TYPE_BOOLEAN, &typedata);
175 static const DBusGTypeMarshalData typedata = {
176 DBUS_TYPE_BYTE_AS_STRING,
179 register_basic (DBUS_TYPE_BYTE, &typedata);
182 static const DBusGTypeMarshalData typedata = {
183 DBUS_TYPE_INT16_AS_STRING,
186 register_basic (DBUS_TYPE_INT16, &typedata);
189 static const DBusGTypeMarshalData typedata = {
190 DBUS_TYPE_UINT16_AS_STRING,
193 register_basic (DBUS_TYPE_UINT16, &typedata);
196 static const DBusGTypeMarshalData typedata = {
197 DBUS_TYPE_UINT32_AS_STRING,
200 register_basic (DBUS_TYPE_UINT32, &typedata);
203 static const DBusGTypeMarshalData typedata = {
204 DBUS_TYPE_INT32_AS_STRING,
207 register_basic (DBUS_TYPE_INT32, &typedata);
210 static const DBusGTypeMarshalData typedata = {
211 DBUS_TYPE_UINT64_AS_STRING,
214 register_basic (DBUS_TYPE_UINT64, &typedata);
217 static const DBusGTypeMarshalData typedata = {
218 DBUS_TYPE_INT64_AS_STRING,
221 register_basic (DBUS_TYPE_INT64, &typedata);
224 static const DBusGTypeMarshalData typedata = {
225 DBUS_TYPE_DOUBLE_AS_STRING,
228 register_basic (DBUS_TYPE_DOUBLE, &typedata);
231 static const DBusGTypeMarshalData typedata = {
232 DBUS_TYPE_STRING_AS_STRING,
235 register_basic (DBUS_TYPE_STRING, &typedata);
237 /* fundamental GTypes that don't map 1:1 with D-BUS types */
239 static const DBusGTypeMarshalData typedata = {
240 DBUS_TYPE_BYTE_AS_STRING,
243 set_type_metadata (G_TYPE_CHAR, &typedata);
246 static const DBusGTypeMarshalData typedata = {
247 DBUS_TYPE_INT32_AS_STRING,
250 set_type_metadata (G_TYPE_LONG, &typedata);
253 static const DBusGTypeMarshalData typedata = {
254 DBUS_TYPE_UINT32_AS_STRING,
257 set_type_metadata (G_TYPE_ULONG, &typedata);
260 static const DBusGTypeMarshalData typedata = {
261 DBUS_TYPE_DOUBLE_AS_STRING,
264 set_type_metadata (G_TYPE_FLOAT, &typedata);
267 /* Register complex types with builtin GType mappings */
269 static const DBusGTypeMarshalVtable vtable = {
273 static const DBusGTypeMarshalData typedata = {
274 DBUS_TYPE_VARIANT_AS_STRING,
277 set_type_metadata (G_TYPE_VALUE, &typedata);
280 static const DBusGTypeMarshalVtable vtable = {
284 static const DBusGTypeMarshalData typedata = {
285 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
288 set_type_metadata (G_TYPE_STRV, &typedata);
292 /* Register some types specific to the D-BUS GLib bindings */
294 static const DBusGTypeMarshalVtable vtable = {
298 static const DBusGTypeMarshalData typedata = {
299 DBUS_TYPE_OBJECT_PATH_AS_STRING,
302 set_type_metadata (DBUS_TYPE_G_PROXY, &typedata);
306 static const DBusGTypeMarshalVtable vtable = {
308 demarshal_object_path
310 static const DBusGTypeMarshalData typedata = {
311 DBUS_TYPE_OBJECT_PATH_AS_STRING,
314 set_type_metadata (DBUS_TYPE_G_OBJECT_PATH, &typedata);
318 static const DBusGTypeMarshalVtable vtable = {
322 static const DBusGTypeMarshalData typedata = {
323 DBUS_TYPE_OBJECT_PATH_AS_STRING,
326 set_type_metadata (G_TYPE_OBJECT, &typedata);
329 types_initialized = TRUE;
333 * Get the GLib type ID for a DBusGObjectPath boxed type.
338 dbus_g_object_path_get_g_type (void)
340 static GType type_id = 0;
343 type_id = g_boxed_type_register_static ("DBusGObjectPath",
344 (GBoxedCopyFunc) g_strdup,
345 (GBoxedFreeFunc) g_free);
350 _dbus_gtype_to_signature (GType gtype)
353 DBusGTypeMarshalData *typedata;
355 if (dbus_g_type_is_collection (gtype))
360 elt_gtype = dbus_g_type_get_collection_specialization (gtype);
361 subsig = _dbus_gtype_to_signature (elt_gtype);
362 ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING, subsig, NULL);
365 else if (dbus_g_type_is_map (gtype))
372 key_gtype = dbus_g_type_get_map_key_specialization (gtype);
373 val_gtype = dbus_g_type_get_map_value_specialization (gtype);
374 key_subsig = _dbus_gtype_to_signature (key_gtype);
375 val_subsig = _dbus_gtype_to_signature (val_gtype);
376 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);
382 typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ());
383 if (typedata == NULL)
385 ret = g_strdup (typedata->sig);
392 dbus_gvalue_to_signature (const GValue *val)
396 gtype = G_VALUE_TYPE (val);
397 if (g_type_is_a (gtype, G_TYPE_VALUE_ARRAY))
403 array = g_value_get_boxed (val);
405 str = g_string_new ("");
406 for (i = 0; i < array->n_values; i++)
409 sig = dbus_gvalue_to_signature (g_value_array_get_nth (array, i));
410 g_string_append (str, sig);
413 return g_string_free (str, FALSE);
416 return _dbus_gtype_to_signature (gtype);
420 demarshal_basic (DBusGValueMarshalCtx *context,
421 DBusMessageIter *iter,
427 current_type = dbus_message_iter_get_arg_type (iter);
428 g_assert (dbus_type_is_basic (current_type));
430 switch (current_type)
432 case DBUS_TYPE_BOOLEAN:
435 dbus_message_iter_get_basic (iter, &bool);
436 g_value_set_boolean (value, bool);
442 dbus_message_iter_get_basic (iter, &byte);
443 g_value_set_uchar (value, byte);
446 case DBUS_TYPE_INT32:
449 dbus_message_iter_get_basic (iter, &intval);
450 g_value_set_int (value, intval);
453 case DBUS_TYPE_UINT32:
455 dbus_uint32_t intval;
456 dbus_message_iter_get_basic (iter, &intval);
457 g_value_set_uint (value, intval);
460 case DBUS_TYPE_INT64:
463 dbus_message_iter_get_basic (iter, &intval);
464 g_value_set_int64 (value, intval);
467 case DBUS_TYPE_UINT64:
469 dbus_uint64_t intval;
470 dbus_message_iter_get_basic (iter, &intval);
471 g_value_set_uint64 (value, intval);
474 case DBUS_TYPE_DOUBLE:
477 dbus_message_iter_get_basic (iter, &dval);
478 g_value_set_double (value, dval);
481 case DBUS_TYPE_INT16:
484 dbus_message_iter_get_basic (iter, &v);
485 g_value_set_int (value, v);
488 case DBUS_TYPE_UINT16:
491 dbus_message_iter_get_basic (iter, &v);
492 g_value_set_uint (value, v);
495 case DBUS_TYPE_STRING:
498 dbus_message_iter_get_basic (iter, &s);
499 g_value_set_string (value, s);
503 g_assert_not_reached ();
509 demarshal_static_variant (DBusGValueMarshalCtx *context,
510 DBusMessageIter *iter,
516 DBusMessageIter subiter;
519 current_type = dbus_message_iter_get_arg_type (iter);
520 dbus_message_iter_recurse (iter, &subiter);
521 sig = dbus_message_iter_get_signature (&subiter);
523 variant_type = _dbus_gtype_from_signature (sig, context->proxy != NULL);
524 if (variant_type != G_TYPE_INVALID)
526 g_value_init (value, variant_type);
528 if (!_dbus_gvalue_demarshal (context, &subiter, value, error))
539 demarshal_variant (DBusGValueMarshalCtx *context,
540 DBusMessageIter *iter,
546 variant_val = g_new0 (GValue, 1);
548 if (!demarshal_static_variant (context, iter, variant_val, error))
551 g_value_set_boxed_take_ownership (value, variant_val);
556 demarshal_proxy (DBusGValueMarshalCtx *context,
557 DBusMessageIter *iter,
561 DBusGProxy *new_proxy;
565 current_type = dbus_message_iter_get_arg_type (iter);
566 if (current_type != DBUS_TYPE_OBJECT_PATH)
570 DBUS_GERROR_INVALID_ARGS,
571 _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
575 g_assert (context->proxy != NULL);
577 dbus_message_iter_get_basic (iter, &objpath);
579 new_proxy = dbus_g_proxy_new_from_proxy (context->proxy, NULL, objpath);
580 g_value_set_object_take_ownership (value, new_proxy);
586 demarshal_object_path (DBusGValueMarshalCtx *context,
587 DBusMessageIter *iter,
594 current_type = dbus_message_iter_get_arg_type (iter);
595 if (current_type != DBUS_TYPE_OBJECT_PATH)
599 DBUS_GERROR_INVALID_ARGS,
600 _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
604 dbus_message_iter_get_basic (iter, &objpath);
606 g_value_set_boxed_take_ownership (value, g_strdup (objpath));
612 demarshal_object (DBusGValueMarshalCtx *context,
613 DBusMessageIter *iter,
621 current_type = dbus_message_iter_get_arg_type (iter);
622 if (current_type != DBUS_TYPE_OBJECT_PATH)
626 DBUS_GERROR_INVALID_ARGS,
627 _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
630 g_assert (context->proxy == NULL);
632 dbus_message_iter_get_basic (iter, &objpath);
634 obj = dbus_g_connection_lookup_g_object (context->gconnection, objpath);
639 DBUS_GERROR_INVALID_ARGS,
640 _("Unregistered object at path '%s'"),
644 g_value_set_object (value, obj);
650 demarshal_strv (DBusGValueMarshalCtx *context,
651 DBusMessageIter *iter,
655 DBusMessageIter subiter;
661 current_type = dbus_message_iter_get_arg_type (iter);
662 if (current_type != DBUS_TYPE_ARRAY)
666 DBUS_GERROR_INVALID_ARGS,
667 _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
671 dbus_message_iter_recurse (iter, &subiter);
673 current_type = dbus_message_iter_get_arg_type (&subiter);
674 if (current_type != DBUS_TYPE_INVALID
675 && current_type != DBUS_TYPE_STRING)
679 DBUS_GERROR_INVALID_ARGS,
680 _("Expected D-BUS string, got type code \'%c\'"), (guchar) current_type);
684 len = dbus_message_iter_get_array_len (&subiter);
686 ret = g_malloc (sizeof (char *) * (len + 1));
689 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
692 g_assert (current_type == DBUS_TYPE_STRING);
694 dbus_message_iter_get_basic (&subiter, &(ret[i]));
695 ret[i] = g_strdup (ret[i]);
697 dbus_message_iter_next (&subiter);
701 g_value_set_boxed_take_ownership (value, ret);
707 demarshal_valuearray (DBusGValueMarshalCtx *context,
708 DBusMessageIter *iter,
714 DBusMessageIter subiter;
716 current_type = dbus_message_iter_get_arg_type (iter);
717 if (current_type != DBUS_TYPE_STRUCT)
721 DBUS_GERROR_INVALID_ARGS,
722 _("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type);
726 dbus_message_iter_recurse (iter, &subiter);
728 ret = g_value_array_new (12);
730 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
736 g_value_array_append (ret, NULL);
737 val = g_value_array_get_nth (ret, ret->n_values - 1);
739 current_sig = dbus_message_iter_get_signature (&subiter);
740 elt_type = _dbus_gtype_from_signature (current_sig, TRUE);
742 g_free (current_sig);
743 if (elt_type == G_TYPE_INVALID)
745 g_value_array_free (ret);
748 DBUS_GERROR_INVALID_ARGS,
749 _("Couldn't demarshal argument with signature \"%s\""), current_sig);
753 g_value_init (val, elt_type);
755 if (!_dbus_gvalue_demarshal (context, &subiter, val, error))
757 g_value_array_free (ret);
761 dbus_message_iter_next (&subiter);
764 g_value_set_boxed_take_ownership (value, ret);
770 demarshal_map (DBusGValueMarshalCtx *context,
771 DBusMessageIter *iter,
776 DBusMessageIter subiter;
781 DBusGTypeSpecializedAppendContext appendctx;
783 current_type = dbus_message_iter_get_arg_type (iter);
784 if (current_type != DBUS_TYPE_ARRAY)
788 DBUS_GERROR_INVALID_ARGS,
789 _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
793 gtype = G_VALUE_TYPE (value);
795 dbus_message_iter_recurse (iter, &subiter);
797 current_type = dbus_message_iter_get_arg_type (&subiter);
798 if (current_type != DBUS_TYPE_INVALID
799 && current_type != DBUS_TYPE_DICT_ENTRY)
803 DBUS_GERROR_INVALID_ARGS,
804 _("Expected D-BUS dict entry, got type code \'%c\'"), (guchar) current_type);
808 key_gtype = dbus_g_type_get_map_key_specialization (gtype);
809 value_gtype = dbus_g_type_get_map_value_specialization (gtype);
811 ret = dbus_g_type_specialized_construct (gtype);
812 g_value_set_boxed_take_ownership (value, ret);
814 dbus_g_type_specialized_init_append (value, &appendctx);
816 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
818 DBusMessageIter entry_iter;
819 GValue key_value = {0,};
820 GValue value_value = {0,};
822 current_type = dbus_message_iter_get_arg_type (&subiter);
823 g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
825 dbus_message_iter_recurse (&subiter, &entry_iter);
827 g_value_init (&key_value, key_gtype);
828 if (!_dbus_gvalue_demarshal (context,
834 dbus_message_iter_next (&entry_iter);
836 g_value_init (&value_value, value_gtype);
837 if (!_dbus_gvalue_demarshal (context,
843 dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
844 /* Ownership of values passes to map, don't unset */
846 dbus_message_iter_next (&subiter);
852 static DBusGValueDemarshalFunc
853 get_type_demarshaller (GType type)
855 DBusGTypeMarshalData *typedata;
857 typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
858 if (typedata == NULL)
860 if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
861 return demarshal_valuearray;
862 if (dbus_g_type_is_collection (type))
863 return demarshal_collection;
864 if (dbus_g_type_is_map (type))
865 return demarshal_map;
867 g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
870 g_assert (typedata->vtable);
871 return typedata->vtable->demarshaller;
875 demarshal_collection (DBusGValueMarshalCtx *context,
876 DBusMessageIter *iter,
883 coltype = G_VALUE_TYPE (value);
884 subtype = dbus_g_type_get_collection_specialization (coltype);
886 if (_dbus_g_type_is_fixed (subtype))
887 return demarshal_collection_array (context, iter, value, error);
889 return demarshal_collection_ptrarray (context, iter, value, error);
893 demarshal_collection_ptrarray (DBusGValueMarshalCtx *context,
894 DBusMessageIter *iter,
901 DBusGTypeSpecializedAppendContext ctx;
902 DBusGValueDemarshalFunc demarshaller;
903 DBusMessageIter subiter;
906 current_type = dbus_message_iter_get_arg_type (iter);
908 if (current_type != DBUS_TYPE_ARRAY)
912 DBUS_GERROR_INVALID_ARGS,
913 _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
917 dbus_message_iter_recurse (iter, &subiter);
919 coltype = G_VALUE_TYPE (value);
920 subtype = dbus_g_type_get_collection_specialization (coltype);
922 demarshaller = get_type_demarshaller (subtype);
928 DBUS_GERROR_INVALID_ARGS,
929 _("No demarshaller registered for type \"%s\" of collection \"%s\""),
930 g_type_name (coltype),
931 g_type_name (subtype));
935 instance = dbus_g_type_specialized_construct (coltype);
936 g_value_set_boxed_take_ownership (value, instance);
938 dbus_g_type_specialized_init_append (value, &ctx);
940 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
942 GValue eltval = {0, };
944 g_value_init (&eltval, subtype);
946 if (!demarshaller (context, &subiter, &eltval, error))
948 dbus_g_type_specialized_collection_end_append (&ctx);
949 g_value_unset (value);
952 dbus_g_type_specialized_collection_append (&ctx, &eltval);
954 dbus_message_iter_next (&subiter);
956 dbus_g_type_specialized_collection_end_append (&ctx);
962 demarshal_collection_array (DBusGValueMarshalCtx *context,
963 DBusMessageIter *iter,
967 DBusMessageIter subiter;
974 dbus_message_iter_recurse (iter, &subiter);
976 elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
977 g_assert (elt_gtype != G_TYPE_INVALID);
978 g_assert (_dbus_g_type_is_fixed (elt_gtype));
980 elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
982 ret = g_array_new (FALSE, TRUE, elt_size);
985 dbus_message_iter_get_fixed_array (&subiter,
988 g_assert (msgarray != NULL);
989 g_assert (msgarray_len >= 0);
990 g_array_append_vals (ret, msgarray, (guint) msgarray_len);
992 g_value_set_boxed_take_ownership (value, ret);
998 _dbus_gvalue_demarshal (DBusGValueMarshalCtx *context,
999 DBusMessageIter *iter,
1004 DBusGValueDemarshalFunc demarshaller;
1006 gtype = G_VALUE_TYPE (value);
1008 demarshaller = get_type_demarshaller (gtype);
1010 if (demarshaller == NULL)
1014 DBUS_GERROR_INVALID_ARGS,
1015 _("No demarshaller registered for type \"%s\""),
1016 g_type_name (gtype));
1020 return demarshaller (context, iter, value, error);
1024 _dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx *context,
1025 DBusMessageIter *iter,
1029 return demarshal_static_variant (context, iter, value, error);
1033 _dbus_gvalue_demarshal_message (DBusGValueMarshalCtx *context,
1034 DBusMessage *message,
1040 DBusMessageIter iter;
1044 ret = g_value_array_new (6); /* 6 is a typical maximum for arguments */
1046 dbus_message_iter_init (message, &iter);
1048 while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
1053 if (index >= n_types)
1055 g_set_error (error, DBUS_GERROR,
1056 DBUS_GERROR_INVALID_ARGS,
1057 _("Too many arguments in message"));
1061 g_value_array_append (ret, NULL);
1062 value = g_value_array_get_nth (ret, index);
1064 gtype = types[index];
1065 g_value_init (value, gtype);
1067 if (!_dbus_gvalue_demarshal (context, &iter, value, error))
1069 dbus_message_iter_next (&iter);
1072 if (index < n_types)
1074 g_set_error (error, DBUS_GERROR,
1075 DBUS_GERROR_INVALID_ARGS,
1076 _("Too few arguments in message"));
1082 g_value_array_free (ret);
1087 marshal_basic (DBusMessageIter *iter, const GValue *value)
1091 value_type = G_VALUE_TYPE (value);
1097 char b = g_value_get_char (value);
1098 if (!dbus_message_iter_append_basic (iter,
1106 unsigned char b = g_value_get_uchar (value);
1107 if (!dbus_message_iter_append_basic (iter,
1113 case G_TYPE_BOOLEAN:
1115 dbus_bool_t b = g_value_get_boolean (value);
1116 if (!dbus_message_iter_append_basic (iter,
1124 dbus_int32_t v = g_value_get_int (value);
1125 if (!dbus_message_iter_append_basic (iter,
1133 dbus_uint32_t v = g_value_get_uint (value);
1134 if (!dbus_message_iter_append_basic (iter,
1142 dbus_int32_t v = g_value_get_long (value);
1143 if (!dbus_message_iter_append_basic (iter,
1151 dbus_uint32_t v = g_value_get_ulong (value);
1152 if (!dbus_message_iter_append_basic (iter,
1160 gint64 v = g_value_get_int64 (value);
1161 if (!dbus_message_iter_append_basic (iter,
1169 guint64 v = g_value_get_uint64 (value);
1170 if (!dbus_message_iter_append_basic (iter,
1178 double v = g_value_get_float (value);
1180 if (!dbus_message_iter_append_basic (iter,
1188 double v = g_value_get_double (value);
1190 if (!dbus_message_iter_append_basic (iter,
1197 /* FIXME, the GValue string may not be valid UTF-8 */
1199 const char *v = g_value_get_string (value);
1202 if (!dbus_message_iter_append_basic (iter,
1211 g_assert_not_reached ();
1217 g_error ("no memory");
1222 marshal_strv (DBusMessageIter *iter,
1223 const GValue *value)
1225 DBusMessageIter subiter;
1228 gboolean ret = FALSE;
1230 g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
1232 array = g_value_get_boxed (value);
1234 if (!dbus_message_iter_open_container (iter,
1240 for (elt = array; *elt; elt++)
1242 if (!dbus_message_iter_append_basic (&subiter,
1248 if (!dbus_message_iter_close_container (iter, &subiter))
1256 marshal_valuearray (DBusMessageIter *iter,
1257 const GValue *value)
1261 DBusMessageIter subiter;
1263 g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
1265 array = g_value_get_boxed (value);
1267 if (!dbus_message_iter_open_container (iter,
1273 for (i = 0; i < array->n_values; i++)
1275 if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
1279 if (!dbus_message_iter_close_container (iter, &subiter))
1284 g_error ("out of memory");
1289 marshal_proxy (DBusMessageIter *iter,
1290 const GValue *value)
1295 g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
1297 proxy = g_value_get_object (value);
1298 path = dbus_g_proxy_get_path (proxy);
1300 if (!dbus_message_iter_append_basic (iter,
1301 DBUS_TYPE_OBJECT_PATH,
1308 marshal_object_path (DBusMessageIter *iter,
1309 const GValue *value)
1313 g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
1315 path = (const char*) g_value_get_boxed (value);
1317 if (!dbus_message_iter_append_basic (iter,
1318 DBUS_TYPE_OBJECT_PATH,
1325 marshal_object (DBusMessageIter *iter,
1326 const GValue *value)
1331 obj = g_value_get_object (value);
1332 path = _dbus_gobject_get_path (obj);
1335 /* FIXME should throw error */
1338 if (!dbus_message_iter_append_basic (iter,
1339 DBUS_TYPE_OBJECT_PATH,
1345 struct DBusGLibHashMarshalData
1347 const char *entry_sig;
1348 DBusMessageIter *iter;
1353 marshal_map_entry (const GValue *key,
1354 const GValue *value,
1357 struct DBusGLibHashMarshalData *hashdata = data;
1358 DBusMessageIter subiter;
1363 if (!dbus_message_iter_open_container (hashdata->iter,
1364 DBUS_TYPE_DICT_ENTRY,
1369 if (!_dbus_gvalue_marshal (&subiter, key))
1372 if (!_dbus_gvalue_marshal (&subiter, value))
1375 if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
1380 hashdata->err = TRUE;
1384 marshal_map (DBusMessageIter *iter,
1385 const GValue *value)
1388 DBusMessageIter arr_iter;
1390 struct DBusGLibHashMarshalData hashdata;
1398 gtype = G_VALUE_TYPE (value);
1402 key_type = dbus_g_type_get_map_key_specialization (gtype);
1403 g_assert (_dbus_gtype_is_valid_hash_key (key_type));
1404 value_type = dbus_g_type_get_map_value_specialization (gtype);
1405 g_assert (_dbus_gtype_is_valid_hash_value (value_type));
1407 key_sig = _dbus_gtype_to_signature (key_type);
1410 g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
1413 value_sig = _dbus_gtype_to_signature (value_type);
1417 g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
1420 entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
1423 array_sig = g_strdup_printf ("%c%s%c",
1424 DBUS_DICT_ENTRY_BEGIN_CHAR,
1426 DBUS_DICT_ENTRY_END_CHAR);
1427 if (!dbus_message_iter_open_container (iter,
1433 hashdata.iter = &arr_iter;
1434 hashdata.err = FALSE;
1435 hashdata.entry_sig = entry_sig;
1437 dbus_g_type_map_value_iterate (value,
1441 if (!dbus_message_iter_close_container (iter, &arr_iter))
1447 return !hashdata.err;
1449 hashdata.err = TRUE;
1454 marshal_variant (DBusMessageIter *iter,
1455 const GValue *value)
1458 DBusMessageIter subiter;
1461 gboolean ret = FALSE;
1463 real_value = g_value_get_boxed (value);
1464 value_gtype = G_VALUE_TYPE (real_value);
1466 variant_sig = dbus_gvalue_to_signature (real_value);
1467 if (variant_sig == NULL)
1469 g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
1473 if (!dbus_message_iter_open_container (iter,
1479 if (!marshal_basic (&subiter, real_value))
1482 if (!dbus_message_iter_close_container (iter, &subiter))
1487 g_free (variant_sig);
1491 static DBusGValueMarshalFunc
1492 get_type_marshaller (GType type)
1494 DBusGTypeMarshalData *typedata;
1496 typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
1497 if (typedata == NULL)
1499 if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
1500 return marshal_valuearray;
1501 if (dbus_g_type_is_collection (type))
1502 return marshal_collection;
1503 if (dbus_g_type_is_map (type))
1506 g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
1509 g_assert (typedata->vtable);
1510 return typedata->vtable->marshaller;
1515 DBusMessageIter *iter;
1516 DBusGValueMarshalFunc marshaller;
1518 } DBusGValueCollectionMarshalData;
1521 collection_marshal_iterator (const GValue *eltval,
1524 DBusGValueCollectionMarshalData *data = user_data;
1529 if (!data->marshaller (data->iter, eltval))
1534 marshal_collection (DBusMessageIter *iter,
1535 const GValue *value)
1540 coltype = G_VALUE_TYPE (value);
1541 subtype = dbus_g_type_get_collection_specialization (coltype);
1543 if (_dbus_g_type_is_fixed (subtype))
1544 return marshal_collection_array (iter, value);
1546 return marshal_collection_ptrarray (iter, value);
1550 marshal_collection_ptrarray (DBusMessageIter *iter,
1551 const GValue *value)
1555 DBusGValueCollectionMarshalData data;
1556 DBusMessageIter subiter;
1559 coltype = G_VALUE_TYPE (value);
1560 elt_gtype = dbus_g_type_get_collection_specialization (coltype);
1561 data.marshaller = get_type_marshaller (elt_gtype);
1562 if (!data.marshaller)
1565 elt_sig = _dbus_gtype_to_signature (elt_gtype);
1568 g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
1572 if (!dbus_message_iter_open_container (iter,
1579 data.iter = &subiter;
1582 dbus_g_type_collection_value_iterate (value,
1583 collection_marshal_iterator,
1586 if (!dbus_message_iter_close_container (iter, &subiter))
1591 g_error ("out of memory");
1597 marshal_collection_array (DBusMessageIter *iter,
1598 const GValue *value)
1601 DBusMessageIter subiter;
1604 char *subsignature_str;
1606 elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
1607 g_assert (_dbus_g_type_is_fixed (elt_gtype));
1608 subsignature_str = _dbus_gtype_to_signature (elt_gtype);
1609 if (!subsignature_str)
1611 g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
1615 elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
1617 array = g_value_get_boxed (value);
1619 if (!dbus_message_iter_open_container (iter,
1625 /* TODO - This assumes that basic values are the same size
1626 * is this always true? If it is we can probably avoid
1627 * a lot of the overhead in _marshal_basic_instance...
1629 if (!dbus_message_iter_append_fixed_array (&subiter,
1630 subsignature_str[0],
1635 if (!dbus_message_iter_close_container (iter, &subiter))
1637 g_free (subsignature_str);
1640 g_error ("out of memory");
1645 _dbus_gvalue_marshal (DBusMessageIter *iter,
1646 const GValue *value)
1649 DBusGValueMarshalFunc marshaller;
1651 gtype = G_VALUE_TYPE (value);
1653 marshaller = get_type_marshaller (gtype);
1654 if (marshaller == NULL)
1656 return marshaller (iter, value);
1659 #ifdef DBUS_BUILD_TESTS
1662 assert_type_maps_to (GType gtype, const char *expected_sig)
1665 sig = _dbus_gtype_to_signature (gtype);
1666 g_assert (sig != NULL);
1667 g_assert (!strcmp (expected_sig, sig));
1672 assert_signature_maps_to (const char *sig, GType expected_gtype)
1674 g_assert (_dbus_gtype_from_signature (sig, TRUE) == expected_gtype);
1678 assert_bidirectional_mapping (GType gtype, const char *expected_sig)
1680 assert_type_maps_to (gtype, expected_sig);
1681 assert_signature_maps_to (expected_sig, gtype);
1685 * @ingroup DBusGLibInternals
1686 * Unit test for general glib stuff
1687 * @returns #TRUE on success.
1690 _dbus_gvalue_test (const char *test_data_dir)
1692 _dbus_g_value_types_init ();
1694 assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
1695 assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
1696 assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
1698 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);
1699 assert_signature_maps_to (DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING, G_TYPE_VALUE_ARRAY);
1700 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);
1702 assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
1703 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);
1704 assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
1705 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
1706 assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
1707 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
1712 #endif /* DBUS_BUILD_TESTS */