1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-gvalue.c GValue to-from DBusMessageIter
3 *
4 * Copyright (C) 2004 Ximian, Inc.
5 * Copyright (C) 2005 Red Hat, Inc.
6 *
7 * SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
8 *
9 * Licensed under the Academic Free License version 2.1
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 #include "config.h"
28 #include "dbus-gtest.h"
29 #include "dbus-gvalue.h"
30 #include "dbus-gsignature.h"
31 #include "dbus-gobject.h"
32 #include "dbus-gvalue-utils.h"
33 #include "dbus/dbus-glib.h"
34 #include <string.h>
35 #include <glib.h>
36 #include "dbus/dbus-signature.h"
37
38 /* Seems reasonable, but this should probably be part of the standard protocol */
39 #define DBUS_GLIB_MAX_VARIANT_RECURSION 32
40
41 static gboolean demarshal_static_variant (DBusGValueMarshalCtx *context,
42 DBusMessageIter *iter,
43 GValue *value,
44 GError **error);
45
46
47 static gboolean marshal_basic (DBusMessageIter *iter,
48 const GValue *value);
49 static gboolean demarshal_basic (DBusGValueMarshalCtx *context,
50 DBusMessageIter *iter,
51 GValue *value,
52 GError **error);
53 static gboolean marshal_strv (DBusMessageIter *iter,
54 const GValue *value);
55 static gboolean demarshal_strv (DBusGValueMarshalCtx *context,
56 DBusMessageIter *iter,
57 GValue *value,
58 GError **error);
59 static gboolean marshal_valuearray (DBusMessageIter *iter,
60 const GValue *value);
61 static gboolean demarshal_valuearray (DBusGValueMarshalCtx *context,
62 DBusMessageIter *iter,
63 GValue *value,
64 GError **error);
65 static gboolean marshal_variant (DBusMessageIter *iter,
66 const GValue *value);
67 static gboolean demarshal_variant (DBusGValueMarshalCtx *context,
68 DBusMessageIter *iter,
69 GValue *value,
70 GError **error);
71 static gboolean marshal_proxy (DBusMessageIter *iter,
72 const GValue *value);
73 static gboolean demarshal_proxy (DBusGValueMarshalCtx *context,
74 DBusMessageIter *iter,
75 GValue *value,
76 GError **error);
77 static gboolean marshal_object_path (DBusMessageIter *iter,
78 const GValue *value);
79 static gboolean demarshal_object_path (DBusGValueMarshalCtx *context,
80 DBusMessageIter *iter,
81 GValue *value,
82 GError **error);
83 static gboolean marshal_object (DBusMessageIter *iter,
84 const GValue *value);
85 static gboolean demarshal_object (DBusGValueMarshalCtx *context,
86 DBusMessageIter *iter,
87 GValue *value,
88 GError **error);
89 static gboolean marshal_signature (DBusMessageIter *iter,
90 const GValue *value);
91 static gboolean demarshal_signature (DBusGValueMarshalCtx *context,
92 DBusMessageIter *iter,
93 GValue *value,
94 GError **error);
95 static gboolean marshal_map (DBusMessageIter *iter,
96 const GValue *value);
97 static gboolean demarshal_map (DBusGValueMarshalCtx *context,
98 DBusMessageIter *iter,
99 GValue *value,
100 GError **error);
101
102 static gboolean marshal_collection (DBusMessageIter *iter,
103 const GValue *value);
104 static gboolean marshal_collection_ptrarray (DBusMessageIter *iter,
105 const GValue *value);
106 static gboolean marshal_collection_array (DBusMessageIter *iter,
107 const GValue *value);
108 static gboolean demarshal_collection (DBusGValueMarshalCtx *context,
109 DBusMessageIter *iter,
110 GValue *value,
111 GError **error);
112 static gboolean demarshal_collection_ptrarray (DBusGValueMarshalCtx *context,
113 DBusMessageIter *iter,
114 GValue *value,
115 GError **error);
116 static gboolean demarshal_collection_array (DBusGValueMarshalCtx *context,
117 DBusMessageIter *iter,
118 GValue *value,
119 GError **error);
120 static gboolean marshal_struct (DBusMessageIter *iter,
121 const GValue *value);
122 static gboolean demarshal_struct (DBusGValueMarshalCtx *context,
123 DBusMessageIter *iter,
124 GValue *value,
125 GError **error);
126
127
128 typedef gboolean (*DBusGValueMarshalFunc) (DBusMessageIter *iter,
129 const GValue *value);
130 typedef gboolean (*DBusGValueDemarshalFunc) (DBusGValueMarshalCtx *context,
131 DBusMessageIter *iter,
132 GValue *value,
133 GError **error);
134
135 typedef struct {
136 DBusGValueMarshalFunc marshaller;
137 DBusGValueDemarshalFunc demarshaller;
138 } DBusGTypeMarshalVtable;
139
140 typedef struct {
141 const char *sig;
142 const DBusGTypeMarshalVtable *vtable;
143 } DBusGTypeMarshalData;
144
145 static GQuark
dbus_g_type_metadata_data_quark()146 dbus_g_type_metadata_data_quark ()
147 {
148 static GQuark quark;
149 if (!quark)
150 quark = g_quark_from_static_string ("DBusGTypeMetaData");
151
152 return quark;
153 }
154
155 static void
set_type_metadata(GType type,const DBusGTypeMarshalData * data)156 set_type_metadata (GType type, const DBusGTypeMarshalData *data)
157 {
158 g_type_set_qdata (type, dbus_g_type_metadata_data_quark (), (gpointer) data);
159 }
160
161 static void
register_basic(int typecode,const DBusGTypeMarshalData * typedata)162 register_basic (int typecode, const DBusGTypeMarshalData *typedata)
163 {
164 set_type_metadata (_dbus_gtype_from_basic_typecode (typecode), typedata);
165 }
166
167 void
_dbus_g_value_types_init(void)168 _dbus_g_value_types_init (void)
169 {
170 static gboolean types_initialized;
171
172 static const DBusGTypeMarshalVtable basic_vtable = {
173 marshal_basic,
174 demarshal_basic
175 };
176
177 if (types_initialized)
178 return;
179
180 dbus_g_type_specialized_init ();
181
182 /* Register basic types */
183 {
184 static const DBusGTypeMarshalData typedata = {
185 DBUS_TYPE_BOOLEAN_AS_STRING,
186 &basic_vtable,
187 };
188 register_basic (DBUS_TYPE_BOOLEAN, &typedata);
189 }
190 {
191 static const DBusGTypeMarshalData typedata = {
192 DBUS_TYPE_BYTE_AS_STRING,
193 &basic_vtable,
194 };
195 register_basic (DBUS_TYPE_BYTE, &typedata);
196 }
197 {
198 static const DBusGTypeMarshalData typedata = {
199 DBUS_TYPE_INT16_AS_STRING,
200 &basic_vtable,
201 };
202 register_basic (DBUS_TYPE_INT16, &typedata);
203 }
204 {
205 static const DBusGTypeMarshalData typedata = {
206 DBUS_TYPE_UINT16_AS_STRING,
207 &basic_vtable,
208 };
209 register_basic (DBUS_TYPE_UINT16, &typedata);
210 }
211 {
212 static const DBusGTypeMarshalData typedata = {
213 DBUS_TYPE_UINT32_AS_STRING,
214 &basic_vtable,
215 };
216 register_basic (DBUS_TYPE_UINT32, &typedata);
217 }
218 {
219 static const DBusGTypeMarshalData typedata = {
220 DBUS_TYPE_INT32_AS_STRING,
221 &basic_vtable,
222 };
223 register_basic (DBUS_TYPE_INT32, &typedata);
224 }
225 {
226 static const DBusGTypeMarshalData typedata = {
227 DBUS_TYPE_UINT64_AS_STRING,
228 &basic_vtable,
229 };
230 register_basic (DBUS_TYPE_UINT64, &typedata);
231 }
232 {
233 static const DBusGTypeMarshalData typedata = {
234 DBUS_TYPE_INT64_AS_STRING,
235 &basic_vtable,
236 };
237 register_basic (DBUS_TYPE_INT64, &typedata);
238 }
239 {
240 static const DBusGTypeMarshalData typedata = {
241 DBUS_TYPE_DOUBLE_AS_STRING,
242 &basic_vtable,
243 };
244 register_basic (DBUS_TYPE_DOUBLE, &typedata);
245 }
246 {
247 static const DBusGTypeMarshalData typedata = {
248 DBUS_TYPE_STRING_AS_STRING,
249 &basic_vtable,
250 };
251 register_basic (DBUS_TYPE_STRING, &typedata);
252 }
253 /* fundamental GTypes that don't map 1:1 with D-BUS types */
254 {
255 static const DBusGTypeMarshalData typedata = {
256 DBUS_TYPE_BYTE_AS_STRING,
257 &basic_vtable,
258 };
259 set_type_metadata (G_TYPE_CHAR, &typedata);
260 }
261 {
262 static const DBusGTypeMarshalData typedata = {
263 DBUS_TYPE_INT32_AS_STRING,
264 &basic_vtable,
265 };
266 set_type_metadata (G_TYPE_LONG, &typedata);
267 }
268 {
269 static const DBusGTypeMarshalData typedata = {
270 DBUS_TYPE_UINT32_AS_STRING,
271 &basic_vtable,
272 };
273 set_type_metadata (G_TYPE_ULONG, &typedata);
274 }
275 {
276 static const DBusGTypeMarshalData typedata = {
277 DBUS_TYPE_DOUBLE_AS_STRING,
278 &basic_vtable,
279 };
280 set_type_metadata (G_TYPE_FLOAT, &typedata);
281 }
282
283 /* Register complex types with builtin GType mappings */
284 {
285 static const DBusGTypeMarshalVtable vtable = {
286 marshal_variant,
287 demarshal_variant
288 };
289 static const DBusGTypeMarshalData typedata = {
290 DBUS_TYPE_VARIANT_AS_STRING,
291 &vtable
292 };
293 set_type_metadata (G_TYPE_VALUE, &typedata);
294 };
295 {
296 static const DBusGTypeMarshalVtable vtable = {
297 marshal_strv,
298 demarshal_strv
299 };
300 static const DBusGTypeMarshalData typedata = {
301 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
302 &vtable
303 };
304 set_type_metadata (G_TYPE_STRV, &typedata);
305 };
306
307
308 /* Register some types specific to the D-BUS GLib bindings */
309 {
310 static const DBusGTypeMarshalVtable vtable = {
311 marshal_proxy,
312 demarshal_proxy
313 };
314 static const DBusGTypeMarshalData typedata = {
315 DBUS_TYPE_OBJECT_PATH_AS_STRING,
316 &vtable
317 };
318 set_type_metadata (DBUS_TYPE_G_PROXY, &typedata);
319 }
320
321 {
322 static const DBusGTypeMarshalVtable vtable = {
323 marshal_object_path,
324 demarshal_object_path
325 };
326 static const DBusGTypeMarshalData typedata = {
327 DBUS_TYPE_OBJECT_PATH_AS_STRING,
328 &vtable
329 };
330 set_type_metadata (DBUS_TYPE_G_OBJECT_PATH, &typedata);
331 }
332
333 {
334 static const DBusGTypeMarshalVtable vtable = {
335 marshal_object,
336 demarshal_object
337 };
338 static const DBusGTypeMarshalData typedata = {
339 DBUS_TYPE_OBJECT_PATH_AS_STRING,
340 &vtable
341 };
342 set_type_metadata (G_TYPE_OBJECT, &typedata);
343 }
344
345 {
346 static const DBusGTypeMarshalVtable vtable = {
347 marshal_signature,
348 demarshal_signature
349 };
350 static const DBusGTypeMarshalData typedata = {
351 DBUS_TYPE_SIGNATURE_AS_STRING,
352 &vtable
353 };
354 set_type_metadata (DBUS_TYPE_G_SIGNATURE, &typedata);
355 }
356
357 types_initialized = TRUE;
358 }
359
360 /**
361 * DBusGObjectPath:
362 *
363 * A typedef for a string used to represent D-Bus object paths.
364 * Its GType is %DBUS_TYPE_G_OBJECT_PATH, derived from %G_TYPE_BOXED.
365 *
366 * Prior to version 0.FIXME this was used as the type name of
367 * %DBUS_TYPE_G_OBJECT_PATH, but did not actually exist as a typedef.
368 *
369 * Since: 0.FIXME
370 *
371 * Deprecated: New code should use GDBus instead. The closest equivalent
372 * is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_OBJECT_PATH.
373 */
374
375 /**
376 * DBUS_TYPE_G_OBJECT_PATH:
377 *
378 * The #GType of a #DBusGObjectPath, which is a boxed type containing a
379 * D-Bus object path as a zero-terminated string. Object paths can be
380 * copied with g_strdup() and freed with g_free(), just like %G_TYPE_STRING,
381 * but have a distinct boxed type to allow them to be distinguished when
382 * stored in a #GValue.
383 *
384 * Returns: a type derived from %G_TYPE_BOXED
385 *
386 * Deprecated: New code should use GDBus instead. The closest equivalent
387 * is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_OBJECT_PATH.
388 */
389 GType
dbus_g_object_path_get_g_type(void)390 dbus_g_object_path_get_g_type (void)
391 {
392 static GType type_id = 0;
393
394 if (!type_id)
395 type_id = g_boxed_type_register_static ("DBusGObjectPath",
396 (GBoxedCopyFunc) g_strdup,
397 (GBoxedFreeFunc) g_free);
398 return type_id;
399 }
400
401 /**
402 * DBusGSignature:
403 *
404 * A typedef for a string used to represent D-Bus signatures.
405 * Its GType is %DBUS_TYPE_G_SIGNATURE, derived from %G_TYPE_BOXED.
406 *
407 * Prior to version 0.FIXME this was used as the type name of
408 * %DBUS_TYPE_G_SIGNATURE, but did not actually exist as a typedef.
409 *
410 * Since: 0.FIXME
411 *
412 * Deprecated: New code should use GDBus instead. The closest equivalent
413 * is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_SIGNATURE.
414 */
415
416 /**
417 * DBUS_TYPE_G_SIGNATURE:
418 *
419 * The #GType of a #DBusGSignature, which is a boxed type containing a
420 * D-Bus signature as a zero-terminated string. Signatures can be
421 * copied with g_strdup() and freed with g_free(), just like %G_TYPE_STRING,
422 * but have a distinct boxed type to allow them to be distinguished when
423 * stored in a #GValue.
424 *
425 * Returns: a type derived from %G_TYPE_BOXED
426 *
427 * Deprecated: New code should use GDBus instead. The closest equivalent
428 * is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_SIGNATURE.
429 */
430 GType
dbus_g_signature_get_g_type(void)431 dbus_g_signature_get_g_type (void)
432 {
433 static GType type_id = 0;
434
435 if (G_UNLIKELY (type_id == 0))
436 type_id = g_boxed_type_register_static ("DBusGSignature",
437 (GBoxedCopyFunc) g_strdup,
438 (GBoxedFreeFunc) g_free);
439
440 return type_id;
441 }
442
443
444 char *
_dbus_gtype_to_signature(GType gtype)445 _dbus_gtype_to_signature (GType gtype)
446 {
447 char *ret;
448 DBusGTypeMarshalData *typedata;
449
450 if (dbus_g_type_is_collection (gtype))
451 {
452 GType elt_gtype;
453 char *subsig;
454
455 elt_gtype = dbus_g_type_get_collection_specialization (gtype);
456 subsig = _dbus_gtype_to_signature (elt_gtype);
457 ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING, subsig, NULL);
458 g_free (subsig);
459 }
460 else if (dbus_g_type_is_map (gtype))
461 {
462 GType key_gtype;
463 GType val_gtype;
464 char *key_subsig;
465 char *val_subsig;
466
467 key_gtype = dbus_g_type_get_map_key_specialization (gtype);
468 val_gtype = dbus_g_type_get_map_value_specialization (gtype);
469 key_subsig = _dbus_gtype_to_signature (key_gtype);
470 val_subsig = _dbus_gtype_to_signature (val_gtype);
471 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);
472 g_free (key_subsig);
473 g_free (val_subsig);
474 }
475 else if (dbus_g_type_is_struct (gtype))
476 {
477 guint i, size;
478 GString *sig;
479 size = dbus_g_type_get_struct_size (gtype);
480 sig = g_string_sized_new (size+2); /*some sensible starting size*/
481 g_string_assign (sig, DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
482 for (i = 0; i < size; i++)
483 {
484 gchar *subsig;
485 subsig = _dbus_gtype_to_signature (
486 dbus_g_type_get_struct_member_type (gtype, i));
487 g_string_append (sig, subsig);
488 g_free (subsig);
489 }
490 g_string_append (sig, DBUS_STRUCT_END_CHAR_AS_STRING);
491 ret = g_string_free (sig, FALSE);
492 }
493 else
494 {
495 typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ());
496 if (typedata == NULL)
497 return NULL;
498 ret = g_strdup (typedata->sig);
499 }
500 return ret;
501 }
502
503 char *
_dbus_gvalue_to_signature(const GValue * val)504 _dbus_gvalue_to_signature (const GValue *val)
505 {
506 GType gtype;
507
508 gtype = G_VALUE_TYPE (val);
509 if (g_type_is_a (gtype, G_TYPE_VALUE_ARRAY))
510 {
511 GString *str;
512 guint i;
513 GValueArray *array;
514
515 array = g_value_get_boxed (val);
516
517 str = g_string_new (DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
518 for (i = 0; i < array->n_values; i++)
519 {
520 char *sig;
521 sig = _dbus_gvalue_to_signature (g_value_array_get_nth (array, i));
522 g_string_append (str, sig);
523 g_free (sig);
524 }
525 g_string_append (str, DBUS_STRUCT_END_CHAR_AS_STRING);
526
527 return g_string_free (str, FALSE);
528 }
529 else
530 return _dbus_gtype_to_signature (gtype);
531 }
532
533 static gboolean
demarshal_basic(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)534 demarshal_basic (DBusGValueMarshalCtx *context,
535 DBusMessageIter *iter,
536 GValue *value,
537 GError **error)
538 {
539 int current_type;
540
541 current_type = dbus_message_iter_get_arg_type (iter);
542 g_assert (dbus_type_is_basic (current_type));
543
544 switch (current_type)
545 {
546 case DBUS_TYPE_BOOLEAN:
547 {
548 dbus_bool_t bool;
549 if (!G_VALUE_HOLDS (value, G_TYPE_BOOLEAN))
550 goto invalid_type;
551 dbus_message_iter_get_basic (iter, &bool);
552 g_value_set_boolean (value, bool);
553 return TRUE;
554 }
555 case DBUS_TYPE_BYTE:
556 {
557 unsigned char byte;
558 if (!G_VALUE_HOLDS (value, G_TYPE_UCHAR))
559 goto invalid_type;
560 dbus_message_iter_get_basic (iter, &byte);
561 g_value_set_uchar (value, byte);
562 return TRUE;
563 }
564 case DBUS_TYPE_INT32:
565 {
566 dbus_int32_t intval;
567 if (!G_VALUE_HOLDS (value, G_TYPE_INT))
568 goto invalid_type;
569 dbus_message_iter_get_basic (iter, &intval);
570 g_value_set_int (value, intval);
571 return TRUE;
572 }
573 case DBUS_TYPE_UINT32:
574 {
575 dbus_uint32_t intval;
576 if (!G_VALUE_HOLDS (value, G_TYPE_UINT))
577 goto invalid_type;
578 dbus_message_iter_get_basic (iter, &intval);
579 g_value_set_uint (value, intval);
580 return TRUE;
581 }
582 case DBUS_TYPE_INT64:
583 {
584 dbus_int64_t intval;
585 if (!G_VALUE_HOLDS (value, G_TYPE_INT64))
586 goto invalid_type;
587 dbus_message_iter_get_basic (iter, &intval);
588 g_value_set_int64 (value, intval);
589 return TRUE;
590 }
591 case DBUS_TYPE_UINT64:
592 {
593 dbus_uint64_t intval;
594 if (!G_VALUE_HOLDS (value, G_TYPE_UINT64))
595 goto invalid_type;
596 dbus_message_iter_get_basic (iter, &intval);
597 g_value_set_uint64 (value, intval);
598 return TRUE;
599 }
600 case DBUS_TYPE_DOUBLE:
601 {
602 double dval;
603 if (!G_VALUE_HOLDS (value, G_TYPE_DOUBLE))
604 goto invalid_type;
605 dbus_message_iter_get_basic (iter, &dval);
606 g_value_set_double (value, dval);
607 return TRUE;
608 }
609 case DBUS_TYPE_INT16:
610 {
611 dbus_int16_t v;
612 if (!G_VALUE_HOLDS (value, G_TYPE_INT))
613 goto invalid_type;
614 dbus_message_iter_get_basic (iter, &v);
615 g_value_set_int (value, v);
616 return TRUE;
617 }
618 case DBUS_TYPE_UINT16:
619 {
620 dbus_uint16_t v;
621 if (!G_VALUE_HOLDS (value, G_TYPE_UINT))
622 goto invalid_type;
623 dbus_message_iter_get_basic (iter, &v);
624 g_value_set_uint (value, v);
625 return TRUE;
626 }
627 case DBUS_TYPE_STRING:
628 {
629 const char *s;
630 if (!G_VALUE_HOLDS (value, G_TYPE_STRING))
631 goto invalid_type;
632 dbus_message_iter_get_basic (iter, &s);
633 g_value_set_string (value, s);
634 return TRUE;
635 }
636 default:
637 /* fall through to invalid_type */
638 break;
639 }
640 invalid_type:
641 g_set_error (error,
642 DBUS_GERROR,
643 DBUS_GERROR_INVALID_ARGS,
644 "Expected type %s, got type code \'%c\'",
645 g_type_name (G_VALUE_TYPE (value)),
646 (guchar) current_type);
647 return FALSE;
648 }
649
650 static gboolean
demarshal_static_variant(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)651 demarshal_static_variant (DBusGValueMarshalCtx *context,
652 DBusMessageIter *iter,
653 GValue *value,
654 GError **error)
655 {
656 char *sig;
657 DBusMessageIter subiter;
658 GType variant_type;
659
660 dbus_message_iter_recurse (iter, &subiter);
661 sig = dbus_message_iter_get_signature (&subiter);
662
663 variant_type = _dbus_gtype_from_signature (sig, context->proxy != NULL);
664 if (variant_type == G_TYPE_INVALID)
665 {
666 /* It can happen if we received an unknown type such as
667 * DBUS_TYPE_UNIX_FD or DBUS_TYPE_MAYBE. */
668 g_set_error (error, DBUS_GERROR,
669 DBUS_GERROR_INVALID_SIGNATURE,
670 "Variant contains unknown signature \'%s\'", sig);
671 dbus_free (sig);
672 return FALSE;
673 }
674
675 dbus_free (sig);
676
677 g_value_init (value, variant_type);
678
679 if (!_dbus_gvalue_demarshal (context, &subiter, value, error))
680 return FALSE;
681
682 return TRUE;
683 }
684
685 static gboolean
demarshal_variant(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)686 demarshal_variant (DBusGValueMarshalCtx *context,
687 DBusMessageIter *iter,
688 GValue *value,
689 GError **error)
690
691 {
692 GValue *variant_val;
693 variant_val = g_new0 (GValue, 1);
694
695 if (!demarshal_static_variant (context, iter, variant_val, error))
696 return FALSE;
697
698 g_value_take_boxed (value, variant_val);
699 return TRUE;
700 }
701
702 static gboolean
demarshal_proxy(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)703 demarshal_proxy (DBusGValueMarshalCtx *context,
704 DBusMessageIter *iter,
705 GValue *value,
706 GError **error)
707 {
708 DBusGProxy *new_proxy;
709 const char *objpath;
710 int current_type;
711
712 current_type = dbus_message_iter_get_arg_type (iter);
713 if (current_type != DBUS_TYPE_OBJECT_PATH)
714 {
715 g_set_error (error,
716 DBUS_GERROR,
717 DBUS_GERROR_INVALID_ARGS,
718 "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
719 return FALSE;
720 }
721
722 g_assert (context->proxy != NULL);
723
724 dbus_message_iter_get_basic (iter, &objpath);
725
726 new_proxy = dbus_g_proxy_new_from_proxy (context->proxy, NULL, objpath);
727 g_value_take_object (value, new_proxy);
728
729 return TRUE;
730 }
731
732 static gboolean
demarshal_object_path(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)733 demarshal_object_path (DBusGValueMarshalCtx *context,
734 DBusMessageIter *iter,
735 GValue *value,
736 GError **error)
737 {
738 const char *objpath;
739 int current_type;
740
741 current_type = dbus_message_iter_get_arg_type (iter);
742 if (current_type != DBUS_TYPE_OBJECT_PATH)
743 {
744 g_set_error (error,
745 DBUS_GERROR,
746 DBUS_GERROR_INVALID_ARGS,
747 "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
748 return FALSE;
749 }
750
751 dbus_message_iter_get_basic (iter, &objpath);
752
753 g_value_set_boxed (value, objpath);
754
755 return TRUE;
756 }
757
758 static gboolean
demarshal_object(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)759 demarshal_object (DBusGValueMarshalCtx *context,
760 DBusMessageIter *iter,
761 GValue *value,
762 GError **error)
763 {
764 const char *objpath;
765 int current_type;
766 GObject *obj;
767
768 current_type = dbus_message_iter_get_arg_type (iter);
769 if (current_type != DBUS_TYPE_OBJECT_PATH)
770 {
771 g_set_error (error,
772 DBUS_GERROR,
773 DBUS_GERROR_INVALID_ARGS,
774 "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
775 return FALSE;
776 }
777 g_assert (context->proxy == NULL);
778
779 dbus_message_iter_get_basic (iter, &objpath);
780
781 obj = dbus_g_connection_lookup_g_object (context->gconnection, objpath);
782 if (obj == NULL)
783 {
784 g_set_error (error,
785 DBUS_GERROR,
786 DBUS_GERROR_INVALID_ARGS,
787 "Unregistered object at path '%s'",
788 objpath);
789 return FALSE;
790 }
791 g_value_set_object (value, obj);
792
793 return TRUE;
794 }
795
796 static gboolean
demarshal_signature(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)797 demarshal_signature (DBusGValueMarshalCtx *context,
798 DBusMessageIter *iter,
799 GValue *value,
800 GError **error)
801 {
802 const char *sig;
803 int current_type;
804
805 current_type = dbus_message_iter_get_arg_type (iter);
806 if (current_type != DBUS_TYPE_SIGNATURE)
807 {
808 g_set_error (error,
809 DBUS_GERROR,
810 DBUS_GERROR_INVALID_ARGS,
811 "Expected D-BUS signature, got type code \'%c\'", (guchar) current_type);
812 return FALSE;
813 }
814
815 dbus_message_iter_get_basic (iter, &sig);
816
817 g_value_set_boxed (value, sig);
818
819 return TRUE;
820 }
821
822 static gboolean
demarshal_strv(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)823 demarshal_strv (DBusGValueMarshalCtx *context,
824 DBusMessageIter *iter,
825 GValue *value,
826 GError **error)
827 {
828 DBusMessageIter subiter;
829 int current_type;
830 GArray *arr;
831
832 current_type = dbus_message_iter_get_arg_type (iter);
833 if (current_type != DBUS_TYPE_ARRAY)
834 {
835 g_set_error (error,
836 DBUS_GERROR,
837 DBUS_GERROR_INVALID_ARGS,
838 "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
839 return FALSE;
840 }
841
842 dbus_message_iter_recurse (iter, &subiter);
843
844 current_type = dbus_message_iter_get_arg_type (&subiter);
845 if (current_type != DBUS_TYPE_INVALID
846 && current_type != DBUS_TYPE_STRING)
847 {
848 g_set_error (error,
849 DBUS_GERROR,
850 DBUS_GERROR_INVALID_ARGS,
851 "Expected D-BUS string, got type code \'%c\'", (guchar) current_type);
852 return FALSE;
853 }
854
855 arr = g_array_new (TRUE, FALSE, sizeof (char *));
856
857 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
858 {
859 g_assert (current_type == DBUS_TYPE_STRING);
860 const char *str;
861 char *copy;
862
863 dbus_message_iter_get_basic (&subiter, &str);
864 copy = g_strdup (str);
865 g_array_append_val (arr, copy);
866
867 dbus_message_iter_next (&subiter);
868 }
869
870 g_value_take_boxed (value, arr->data);
871 g_array_free (arr, FALSE);
872
873 return TRUE;
874 }
875
876 static gboolean
demarshal_valuearray(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)877 demarshal_valuearray (DBusGValueMarshalCtx *context,
878 DBusMessageIter *iter,
879 GValue *value,
880 GError **error)
881 {
882 int current_type;
883 GValueArray *ret;
884 DBusMessageIter subiter;
885
886 current_type = dbus_message_iter_get_arg_type (iter);
887 if (current_type != DBUS_TYPE_STRUCT)
888 {
889 g_set_error (error,
890 DBUS_GERROR,
891 DBUS_GERROR_INVALID_ARGS,
892 "Expected D-BUS struct, got type code \'%c\'", (guchar) current_type);
893 return FALSE;
894 }
895
896 dbus_message_iter_recurse (iter, &subiter);
897
898 ret = g_value_array_new (12);
899
900 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
901 {
902 GValue *val;
903 GType elt_type;
904 char *current_sig;
905
906 g_value_array_append (ret, NULL);
907 val = g_value_array_get_nth (ret, ret->n_values - 1);
908
909 current_sig = dbus_message_iter_get_signature (&subiter);
910 elt_type = _dbus_gtype_from_signature (current_sig, TRUE);
911
912 if (elt_type == G_TYPE_INVALID)
913 {
914 g_value_array_free (ret);
915 g_set_error (error,
916 DBUS_GERROR,
917 DBUS_GERROR_INVALID_ARGS,
918 "Couldn't demarshal argument with signature \"%s\"", current_sig);
919 dbus_free (current_sig);
920 return FALSE;
921 }
922 dbus_free (current_sig);
923
924 g_value_init (val, elt_type);
925
926 if (!_dbus_gvalue_demarshal (context, &subiter, val, error))
927 {
928 g_value_array_free (ret);
929 return FALSE;
930 }
931
932 dbus_message_iter_next (&subiter);
933 }
934
935 g_value_take_boxed (value, ret);
936
937 return TRUE;
938 }
939
940 static gboolean
demarshal_map(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)941 demarshal_map (DBusGValueMarshalCtx *context,
942 DBusMessageIter *iter,
943 GValue *value,
944 GError **error)
945 {
946 GType gtype;
947 DBusMessageIter subiter;
948 int current_type;
949 gpointer ret;
950 GType key_gtype;
951 GType value_gtype;
952 DBusGTypeSpecializedAppendContext appendctx;
953
954 current_type = dbus_message_iter_get_arg_type (iter);
955 if (current_type != DBUS_TYPE_ARRAY)
956 {
957 g_set_error (error,
958 DBUS_GERROR,
959 DBUS_GERROR_INVALID_ARGS,
960 "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
961 return FALSE;
962 }
963
964 gtype = G_VALUE_TYPE (value);
965
966 dbus_message_iter_recurse (iter, &subiter);
967
968 current_type = dbus_message_iter_get_arg_type (&subiter);
969 if (current_type != DBUS_TYPE_INVALID
970 && current_type != DBUS_TYPE_DICT_ENTRY)
971 {
972 g_set_error (error,
973 DBUS_GERROR,
974 DBUS_GERROR_INVALID_ARGS,
975 "Expected D-BUS dict entry, got type code \'%c\'", (guchar) current_type);
976 return FALSE;
977 }
978
979 key_gtype = dbus_g_type_get_map_key_specialization (gtype);
980 value_gtype = dbus_g_type_get_map_value_specialization (gtype);
981
982 ret = dbus_g_type_specialized_construct (gtype);
983 g_value_take_boxed (value, ret);
984
985 dbus_g_type_specialized_init_append (value, &appendctx);
986
987 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
988 {
989 DBusMessageIter entry_iter;
990 GValue key_value = {0,};
991 GValue value_value = {0,};
992
993 current_type = dbus_message_iter_get_arg_type (&subiter);
994 g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
995
996 dbus_message_iter_recurse (&subiter, &entry_iter);
997
998 g_value_init (&key_value, key_gtype);
999 if (!_dbus_gvalue_demarshal (context,
1000 &entry_iter,
1001 &key_value,
1002 error))
1003 return FALSE;
1004
1005 dbus_message_iter_next (&entry_iter);
1006
1007 g_value_init (&value_value, value_gtype);
1008 if (!_dbus_gvalue_demarshal (context,
1009 &entry_iter,
1010 &value_value,
1011 error))
1012 return FALSE;
1013
1014 dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
1015 /* Ownership of values passes to map, don't unset */
1016
1017 dbus_message_iter_next (&subiter);
1018 }
1019
1020 return TRUE;
1021 }
1022
1023 static gboolean
demarshal_struct(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)1024 demarshal_struct (DBusGValueMarshalCtx *context,
1025 DBusMessageIter *iter,
1026 GValue *value,
1027 GError **error)
1028 {
1029 int current_type;
1030 DBusMessageIter subiter;
1031 guint i, size;
1032 GValue val = {0,};
1033 GType elt_type;
1034
1035 current_type = dbus_message_iter_get_arg_type (iter);
1036 if (current_type != DBUS_TYPE_STRUCT)
1037 {
1038 g_set_error (error,
1039 DBUS_GERROR,
1040 DBUS_GERROR_INVALID_ARGS,
1041 "Expected D-BUS struct, got type code \'%c\'", (guchar) current_type);
1042 return FALSE;
1043 }
1044
1045 dbus_message_iter_recurse (iter, &subiter);
1046
1047 g_value_take_boxed (value,
1048 dbus_g_type_specialized_construct (G_VALUE_TYPE (value)));
1049
1050 size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value));
1051
1052 for (i=0; i < size; i++)
1053 {
1054
1055 elt_type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE(value), i);
1056 if (elt_type == G_TYPE_INVALID)
1057 {
1058 g_value_unset (value);
1059 g_set_error (error,
1060 DBUS_GERROR,
1061 DBUS_GERROR_INVALID_ARGS,
1062 "Couldn't demarshal argument, "
1063 "struct type %s has no member %d",
1064 g_type_name (G_VALUE_TYPE(value)), i);
1065 return FALSE;
1066 }
1067
1068 g_value_init (&val, elt_type);
1069
1070 if (!_dbus_gvalue_demarshal (context, &subiter, &val, error))
1071 {
1072 g_value_unset (&val);
1073 g_value_unset (value);
1074 return FALSE;
1075 }
1076 if (!dbus_g_type_struct_set_member (value, i, &val))
1077 {
1078 g_value_unset (&val);
1079 g_value_unset (value);
1080 return FALSE;
1081 }
1082
1083 dbus_message_iter_next (&subiter);
1084 g_value_unset (&val);
1085 }
1086
1087 g_assert (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_INVALID);
1088
1089 return TRUE;
1090 }
1091
1092
1093 static DBusGValueDemarshalFunc
get_type_demarshaller(GType type)1094 get_type_demarshaller (GType type)
1095 {
1096 DBusGTypeMarshalData *typedata;
1097
1098 typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
1099 if (typedata == NULL)
1100 {
1101 if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
1102 return demarshal_valuearray;
1103 if (dbus_g_type_is_collection (type))
1104 return demarshal_collection;
1105 if (dbus_g_type_is_map (type))
1106 return demarshal_map;
1107 if (dbus_g_type_is_struct (type))
1108 return demarshal_struct;
1109
1110 g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
1111 return NULL;
1112 }
1113 g_assert (typedata->vtable);
1114 return typedata->vtable->demarshaller;
1115 }
1116
1117 static gboolean
demarshal_collection(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)1118 demarshal_collection (DBusGValueMarshalCtx *context,
1119 DBusMessageIter *iter,
1120 GValue *value,
1121 GError **error)
1122 {
1123 GType coltype;
1124 GType subtype;
1125
1126 coltype = G_VALUE_TYPE (value);
1127 subtype = dbus_g_type_get_collection_specialization (coltype);
1128
1129 if (_dbus_g_type_is_fixed (subtype))
1130 return demarshal_collection_array (context, iter, value, error);
1131 else
1132 return demarshal_collection_ptrarray (context, iter, value, error);
1133 }
1134
1135 static gboolean
demarshal_collection_ptrarray(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)1136 demarshal_collection_ptrarray (DBusGValueMarshalCtx *context,
1137 DBusMessageIter *iter,
1138 GValue *value,
1139 GError **error)
1140 {
1141 GType coltype;
1142 GType subtype;
1143 gpointer instance;
1144 DBusGTypeSpecializedAppendContext ctx;
1145 DBusGValueDemarshalFunc demarshaller;
1146 DBusMessageIter subiter;
1147 int current_type;
1148
1149 current_type = dbus_message_iter_get_arg_type (iter);
1150
1151 if (current_type != DBUS_TYPE_ARRAY)
1152 {
1153 g_set_error (error,
1154 DBUS_GERROR,
1155 DBUS_GERROR_INVALID_ARGS,
1156 "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
1157 return FALSE;
1158 }
1159
1160 dbus_message_iter_recurse (iter, &subiter);
1161
1162 coltype = G_VALUE_TYPE (value);
1163 subtype = dbus_g_type_get_collection_specialization (coltype);
1164
1165 demarshaller = get_type_demarshaller (subtype);
1166
1167 if (!demarshaller)
1168 {
1169 g_set_error (error,
1170 DBUS_GERROR,
1171 DBUS_GERROR_INVALID_ARGS,
1172 "No demarshaller registered for type \"%s\" of collection \"%s\"",
1173 g_type_name (coltype),
1174 g_type_name (subtype));
1175 return FALSE;
1176 }
1177
1178 instance = dbus_g_type_specialized_construct (coltype);
1179 g_value_take_boxed (value, instance);
1180
1181 dbus_g_type_specialized_init_append (value, &ctx);
1182
1183 while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
1184 {
1185 GValue eltval = {0, };
1186
1187 g_value_init (&eltval, subtype);
1188
1189 if (!demarshaller (context, &subiter, &eltval, error))
1190 {
1191 dbus_g_type_specialized_collection_end_append (&ctx);
1192 g_value_unset (value);
1193 return FALSE;
1194 }
1195 dbus_g_type_specialized_collection_append (&ctx, &eltval);
1196
1197 dbus_message_iter_next (&subiter);
1198 }
1199 dbus_g_type_specialized_collection_end_append (&ctx);
1200
1201 return TRUE;
1202 }
1203
1204 static gboolean
demarshal_collection_array(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)1205 demarshal_collection_array (DBusGValueMarshalCtx *context,
1206 DBusMessageIter *iter,
1207 GValue *value,
1208 GError **error)
1209 {
1210 DBusMessageIter subiter;
1211 GArray *ret;
1212 GType elt_gtype;
1213 int elt_size;
1214 void *msgarray;
1215 int msgarray_len;
1216
1217 dbus_message_iter_recurse (iter, &subiter);
1218
1219 elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
1220 g_assert (elt_gtype != G_TYPE_INVALID);
1221 g_assert (_dbus_g_type_is_fixed (elt_gtype));
1222
1223 elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
1224
1225 ret = g_array_new (FALSE, TRUE, elt_size);
1226
1227 msgarray = NULL;
1228 dbus_message_iter_get_fixed_array (&subiter,
1229 &msgarray,
1230 &msgarray_len);
1231 g_assert (msgarray != NULL || msgarray_len == 0);
1232
1233 if (msgarray_len)
1234 g_array_append_vals (ret, msgarray, (guint) msgarray_len);
1235
1236 g_value_take_boxed (value, ret);
1237
1238 return TRUE;
1239 }
1240
1241 gboolean
_dbus_gvalue_demarshal(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)1242 _dbus_gvalue_demarshal (DBusGValueMarshalCtx *context,
1243 DBusMessageIter *iter,
1244 GValue *value,
1245 GError **error)
1246 {
1247 GType gtype;
1248 DBusGValueDemarshalFunc demarshaller;
1249 gboolean retcode = FALSE;
1250
1251 if (context->recursion_depth > DBUS_GLIB_MAX_VARIANT_RECURSION)
1252 {
1253 g_set_error (error, DBUS_GERROR,
1254 DBUS_GERROR_NO_MEMORY,
1255 "Variant recursion limit exceeded");
1256 return FALSE;
1257 }
1258 context->recursion_depth++;
1259
1260 gtype = G_VALUE_TYPE (value);
1261
1262 demarshaller = get_type_demarshaller (gtype);
1263
1264 if (demarshaller == NULL)
1265 {
1266 g_set_error (error,
1267 DBUS_GERROR,
1268 DBUS_GERROR_INVALID_ARGS,
1269 "No demarshaller registered for type \"%s\"",
1270 g_type_name (gtype));
1271
1272 goto out;
1273 }
1274
1275 retcode = demarshaller (context, iter, value, error);
1276 out:
1277 context->recursion_depth--;
1278 return retcode;
1279 }
1280
1281 gboolean
_dbus_gvalue_demarshal_variant(DBusGValueMarshalCtx * context,DBusMessageIter * iter,GValue * value,GError ** error)1282 _dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx *context,
1283 DBusMessageIter *iter,
1284 GValue *value,
1285 GError **error)
1286 {
1287 return demarshal_static_variant (context, iter, value, error);
1288 }
1289
1290 GValueArray *
_dbus_gvalue_demarshal_message(DBusGValueMarshalCtx * context,DBusMessage * message,guint n_types,const GType * types,GError ** error)1291 _dbus_gvalue_demarshal_message (DBusGValueMarshalCtx *context,
1292 DBusMessage *message,
1293 guint n_types,
1294 const GType *types,
1295 GError **error)
1296 {
1297 GValueArray *ret;
1298 DBusMessageIter iter;
1299 int current_type;
1300 guint index_;
1301
1302 ret = g_value_array_new (6); /* 6 is a typical maximum for arguments */
1303
1304 dbus_message_iter_init (message, &iter);
1305 index_ = 0;
1306 while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
1307 {
1308 GValue *value;
1309 GType gtype;
1310
1311 if (index_ >= n_types)
1312 {
1313 g_set_error (error, DBUS_GERROR,
1314 DBUS_GERROR_INVALID_ARGS,
1315 "Too many arguments in message");
1316 goto lose;
1317 }
1318
1319 g_value_array_append (ret, NULL);
1320 value = g_value_array_get_nth (ret, index_);
1321
1322 gtype = types[index_];
1323 g_value_init (value, gtype);
1324
1325 if (!_dbus_gvalue_demarshal (context, &iter, value, error))
1326 goto lose;
1327 dbus_message_iter_next (&iter);
1328 index_++;
1329 }
1330 if (index_ < n_types)
1331 {
1332 g_set_error (error, DBUS_GERROR,
1333 DBUS_GERROR_INVALID_ARGS,
1334 "Too few arguments in message");
1335 goto lose;
1336 }
1337
1338 return ret;
1339 lose:
1340 g_value_array_free (ret);
1341 return NULL;
1342 }
1343
1344 static void oom (void) G_GNUC_NORETURN;
1345 static void
oom(void)1346 oom (void)
1347 {
1348 g_error ("no memory");
1349 }
1350
1351 static gboolean
marshal_basic(DBusMessageIter * iter,const GValue * value)1352 marshal_basic (DBusMessageIter *iter, const GValue *value)
1353 {
1354 GType value_type;
1355
1356 value_type = G_VALUE_TYPE (value);
1357
1358 switch (value_type)
1359 {
1360 case G_TYPE_CHAR:
1361 {
1362 char b = g_value_get_char (value);
1363 if (!dbus_message_iter_append_basic (iter,
1364 DBUS_TYPE_BYTE,
1365 &b))
1366 oom ();
1367 }
1368 return TRUE;
1369 case G_TYPE_UCHAR:
1370 {
1371 unsigned char b = g_value_get_uchar (value);
1372 if (!dbus_message_iter_append_basic (iter,
1373 DBUS_TYPE_BYTE,
1374 &b))
1375 oom ();
1376 }
1377 return TRUE;
1378 case G_TYPE_BOOLEAN:
1379 {
1380 dbus_bool_t b = g_value_get_boolean (value);
1381
1382 g_return_val_if_fail (b == TRUE || b == FALSE, FALSE);
1383
1384 if (!dbus_message_iter_append_basic (iter,
1385 DBUS_TYPE_BOOLEAN,
1386 &b))
1387 oom ();
1388 }
1389 return TRUE;
1390 case G_TYPE_INT:
1391 {
1392 dbus_int32_t v = g_value_get_int (value);
1393 if (!dbus_message_iter_append_basic (iter,
1394 DBUS_TYPE_INT32,
1395 &v))
1396 oom ();
1397 }
1398 return TRUE;
1399 case G_TYPE_UINT:
1400 {
1401 dbus_uint32_t v = g_value_get_uint (value);
1402 if (!dbus_message_iter_append_basic (iter,
1403 DBUS_TYPE_UINT32,
1404 &v))
1405 oom ();
1406 }
1407 return TRUE;
1408 case G_TYPE_LONG:
1409 {
1410 dbus_int32_t v = g_value_get_long (value);
1411 if (!dbus_message_iter_append_basic (iter,
1412 DBUS_TYPE_INT32,
1413 &v))
1414 oom ();
1415 }
1416 return TRUE;
1417 case G_TYPE_ULONG:
1418 {
1419 dbus_uint32_t v = g_value_get_ulong (value);
1420 if (!dbus_message_iter_append_basic (iter,
1421 DBUS_TYPE_UINT32,
1422 &v))
1423 oom ();
1424 }
1425 return TRUE;
1426 case G_TYPE_INT64:
1427 {
1428 gint64 v = g_value_get_int64 (value);
1429 if (!dbus_message_iter_append_basic (iter,
1430 DBUS_TYPE_INT64,
1431 &v))
1432 oom ();
1433 }
1434 return TRUE;
1435 case G_TYPE_UINT64:
1436 {
1437 guint64 v = g_value_get_uint64 (value);
1438 if (!dbus_message_iter_append_basic (iter,
1439 DBUS_TYPE_UINT64,
1440 &v))
1441 oom ();
1442 }
1443 return TRUE;
1444 case G_TYPE_FLOAT:
1445 {
1446 double v = g_value_get_float (value);
1447
1448 if (!dbus_message_iter_append_basic (iter,
1449 DBUS_TYPE_DOUBLE,
1450 &v))
1451 oom ();
1452 }
1453 return TRUE;
1454 case G_TYPE_DOUBLE:
1455 {
1456 double v = g_value_get_double (value);
1457
1458 if (!dbus_message_iter_append_basic (iter,
1459 DBUS_TYPE_DOUBLE,
1460 &v))
1461 oom ();
1462 }
1463 return TRUE;
1464 case G_TYPE_STRING:
1465 {
1466 const char *v = g_value_get_string (value);
1467 if (!v)
1468 v = "";
1469
1470 /* FIXME: fd.o #16320: consider using g_return_if_fail to check UTF-8
1471 * validity */
1472
1473 if (!dbus_message_iter_append_basic (iter,
1474 DBUS_TYPE_STRING,
1475 &v))
1476 {
1477 gchar *s = g_strdup_value_contents (value);
1478
1479 g_critical ("Unable to marshal string (not UTF-8 or OOM?): %s",
1480 s);
1481 g_free (s);
1482 return FALSE;
1483 }
1484 }
1485 return TRUE;
1486
1487 default:
1488 {
1489 g_assert_not_reached ();
1490 return FALSE;
1491 }
1492 }
1493 }
1494
1495 static gboolean
marshal_strv(DBusMessageIter * iter,const GValue * value)1496 marshal_strv (DBusMessageIter *iter,
1497 const GValue *value)
1498 {
1499 DBusMessageIter subiter;
1500 char **array;
1501 char **elt;
1502 gboolean ret = FALSE;
1503
1504 g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
1505
1506 array = g_value_get_boxed (value);
1507
1508 if (!dbus_message_iter_open_container (iter,
1509 DBUS_TYPE_ARRAY,
1510 "s",
1511 &subiter))
1512 goto out;
1513
1514 if (array)
1515 {
1516 for (elt = array; *elt; elt++)
1517 {
1518 if (!dbus_message_iter_append_basic (&subiter,
1519 DBUS_TYPE_STRING,
1520 elt))
1521 goto out;
1522 }
1523 }
1524
1525 if (!dbus_message_iter_close_container (iter, &subiter))
1526 goto out;
1527 ret = TRUE;
1528 out:
1529 return ret;
1530 }
1531
1532 static gboolean
marshal_valuearray(DBusMessageIter * iter,const GValue * value)1533 marshal_valuearray (DBusMessageIter *iter,
1534 const GValue *value)
1535 {
1536 GValueArray *array;
1537 guint i;
1538 DBusMessageIter subiter;
1539
1540 g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
1541
1542 array = g_value_get_boxed (value);
1543
1544 if (!dbus_message_iter_open_container (iter,
1545 DBUS_TYPE_STRUCT,
1546 NULL,
1547 &subiter))
1548 oom ();
1549
1550 if (array)
1551 {
1552 for (i = 0; i < array->n_values; i++)
1553 {
1554 if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
1555 {
1556 dbus_message_iter_abandon_container (iter, &subiter);
1557 return FALSE;
1558 }
1559 }
1560 }
1561
1562 return dbus_message_iter_close_container (iter, &subiter);
1563 }
1564
1565 static gboolean
marshal_proxy(DBusMessageIter * iter,const GValue * value)1566 marshal_proxy (DBusMessageIter *iter,
1567 const GValue *value)
1568 {
1569 const char *path;
1570 DBusGProxy *proxy;
1571
1572 g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
1573
1574 proxy = g_value_get_object (value);
1575 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
1576 path = dbus_g_proxy_get_path (proxy);
1577 g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
1578
1579 if (!dbus_message_iter_append_basic (iter,
1580 DBUS_TYPE_OBJECT_PATH,
1581 &path))
1582 oom ();
1583
1584 return TRUE;
1585 }
1586
1587 static gboolean
marshal_object_path(DBusMessageIter * iter,const GValue * value)1588 marshal_object_path (DBusMessageIter *iter,
1589 const GValue *value)
1590 {
1591 const char *path;
1592
1593 g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
1594
1595 path = g_value_get_boxed (value);
1596 g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
1597
1598 if (!dbus_message_iter_append_basic (iter,
1599 DBUS_TYPE_OBJECT_PATH,
1600 &path))
1601 oom ();
1602
1603 return TRUE;
1604 }
1605
1606 static gboolean
marshal_object(DBusMessageIter * iter,const GValue * value)1607 marshal_object (DBusMessageIter *iter,
1608 const GValue *value)
1609 {
1610 const char *path;
1611 GObject *obj;
1612
1613 obj = g_value_get_object (value);
1614 g_return_val_if_fail (G_IS_OBJECT (obj), FALSE);
1615
1616 path = _dbus_gobject_get_path (obj);
1617 g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
1618
1619 if (!dbus_message_iter_append_basic (iter,
1620 DBUS_TYPE_OBJECT_PATH,
1621 &path))
1622 oom ();
1623
1624 return TRUE;
1625 }
1626
1627 static gboolean
marshal_signature(DBusMessageIter * iter,const GValue * value)1628 marshal_signature (DBusMessageIter *iter,
1629 const GValue *value)
1630 {
1631 const char *sig;
1632
1633 g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_SIGNATURE);
1634
1635 sig = g_value_get_boxed (value);
1636 g_return_val_if_fail (g_variant_is_signature (sig), FALSE);
1637
1638 /* failure here isn't strictly *guaranteed* to be OOM, since GDBus might
1639 * understand more type-codes than our libdbus */
1640 if (!dbus_message_iter_append_basic (iter,
1641 DBUS_TYPE_SIGNATURE,
1642 &sig))
1643 return FALSE;
1644
1645 return TRUE;
1646 }
1647
1648 struct DBusGLibHashMarshalData
1649 {
1650 const char *entry_sig;
1651 DBusMessageIter *iter;
1652 gboolean err;
1653 };
1654
1655 static void
marshal_map_entry(const GValue * key,const GValue * value,gpointer data)1656 marshal_map_entry (const GValue *key,
1657 const GValue *value,
1658 gpointer data)
1659 {
1660 struct DBusGLibHashMarshalData *hashdata = data;
1661 DBusMessageIter subiter;
1662
1663 if (hashdata->err)
1664 return;
1665
1666 if (!dbus_message_iter_open_container (hashdata->iter,
1667 DBUS_TYPE_DICT_ENTRY,
1668 NULL,
1669 &subiter))
1670 goto lose;
1671
1672 if (!_dbus_gvalue_marshal (&subiter, key))
1673 goto lose;
1674
1675 if (!_dbus_gvalue_marshal (&subiter, value))
1676 goto lose;
1677
1678 if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
1679 goto lose;
1680
1681 return;
1682 lose:
1683 hashdata->err = TRUE;
1684 }
1685
1686 static gboolean
marshal_map(DBusMessageIter * iter,const GValue * value)1687 marshal_map (DBusMessageIter *iter,
1688 const GValue *value)
1689 {
1690 GType gtype;
1691 DBusMessageIter arr_iter;
1692 struct DBusGLibHashMarshalData hashdata;
1693 char *key_sig;
1694 char *value_sig;
1695 GType key_type;
1696 GType value_type;
1697 char *entry_sig;
1698 char *array_sig;
1699
1700 gtype = G_VALUE_TYPE (value);
1701
1702 key_type = dbus_g_type_get_map_key_specialization (gtype);
1703 g_assert (_dbus_gtype_is_valid_hash_key (key_type));
1704 value_type = dbus_g_type_get_map_value_specialization (gtype);
1705 g_assert (_dbus_gtype_is_valid_hash_value (value_type));
1706
1707 key_sig = _dbus_gtype_to_signature (key_type);
1708 if (!key_sig)
1709 {
1710 g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
1711 return FALSE;
1712 }
1713 value_sig = _dbus_gtype_to_signature (value_type);
1714 if (!value_sig)
1715 {
1716 g_free (key_sig);
1717 g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
1718 return FALSE;
1719 }
1720 entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
1721 g_free (key_sig);
1722 g_free (value_sig);
1723 array_sig = g_strdup_printf ("%c%s%c",
1724 DBUS_DICT_ENTRY_BEGIN_CHAR,
1725 entry_sig,
1726 DBUS_DICT_ENTRY_END_CHAR);
1727 if (!dbus_message_iter_open_container (iter,
1728 DBUS_TYPE_ARRAY,
1729 array_sig,
1730 &arr_iter))
1731 goto lose;
1732
1733 hashdata.iter = &arr_iter;
1734 hashdata.err = FALSE;
1735 hashdata.entry_sig = entry_sig;
1736
1737 dbus_g_type_map_value_iterate (value,
1738 marshal_map_entry,
1739 &hashdata);
1740
1741 if (hashdata.err)
1742 {
1743 dbus_message_iter_abandon_container (iter, &arr_iter);
1744 goto lose;
1745 }
1746 else if (!dbus_message_iter_close_container (iter, &arr_iter))
1747 {
1748 goto lose;
1749 }
1750
1751 out:
1752 g_free (entry_sig);
1753 g_free (array_sig);
1754 return !hashdata.err;
1755 lose:
1756 hashdata.err = TRUE;
1757 goto out;
1758 }
1759
1760 static gboolean
marshal_struct(DBusMessageIter * iter,const GValue * value)1761 marshal_struct (DBusMessageIter *iter,
1762 const GValue *value)
1763 {
1764 GType gtype;
1765 DBusMessageIter subiter;
1766 guint size, i;
1767 GValue val = {0,};
1768
1769 gtype = G_VALUE_TYPE (value);
1770
1771 size = dbus_g_type_get_struct_size (gtype);
1772
1773 if (!dbus_message_iter_open_container (iter,
1774 DBUS_TYPE_STRUCT,
1775 NULL,
1776 &subiter))
1777 oom ();
1778
1779 for (i = 0; i < size; i++)
1780 {
1781 g_value_init (&val, dbus_g_type_get_struct_member_type
1782 (G_VALUE_TYPE(value), i));
1783
1784 if (!dbus_g_type_struct_get_member (value, i, &val))
1785 goto abandon;
1786
1787 if (!_dbus_gvalue_marshal (&subiter, &val))
1788 goto abandon;
1789
1790 g_value_unset(&val);
1791 }
1792
1793 return dbus_message_iter_close_container (iter, &subiter);
1794
1795 abandon:
1796 dbus_message_iter_abandon_container (iter, &subiter);
1797 return FALSE;
1798 }
1799
1800 static gboolean
marshal_variant(DBusMessageIter * iter,const GValue * value)1801 marshal_variant (DBusMessageIter *iter,
1802 const GValue *value)
1803 {
1804 GType value_gtype;
1805 DBusMessageIter subiter;
1806 char *variant_sig;
1807 GValue *real_value;
1808 gboolean ret = FALSE;
1809
1810 real_value = g_value_get_boxed (value);
1811 value_gtype = G_VALUE_TYPE (real_value);
1812
1813 variant_sig = _dbus_gvalue_to_signature (real_value);
1814 if (variant_sig == NULL)
1815 {
1816 g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
1817 return FALSE;
1818 }
1819
1820 if (!dbus_message_iter_open_container (iter,
1821 DBUS_TYPE_VARIANT,
1822 variant_sig,
1823 &subiter))
1824 goto out;
1825
1826 if (!_dbus_gvalue_marshal (&subiter, real_value))
1827 {
1828 dbus_message_iter_abandon_container (iter, &subiter);
1829 goto out;
1830 }
1831
1832 if (!dbus_message_iter_close_container (iter, &subiter))
1833 goto out;
1834
1835 ret = TRUE;
1836 out:
1837 g_free (variant_sig);
1838 return ret;
1839 }
1840
1841 static DBusGValueMarshalFunc
get_type_marshaller(GType type)1842 get_type_marshaller (GType type)
1843 {
1844 DBusGTypeMarshalData *typedata;
1845
1846 typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
1847 if (typedata == NULL)
1848 {
1849 if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
1850 return marshal_valuearray;
1851 if (dbus_g_type_is_collection (type))
1852 return marshal_collection;
1853 if (dbus_g_type_is_map (type))
1854 return marshal_map;
1855 if (dbus_g_type_is_struct (type))
1856 return marshal_struct;
1857
1858 g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
1859 return NULL;
1860 }
1861 g_assert (typedata->vtable);
1862 return typedata->vtable->marshaller;
1863 }
1864
1865 typedef struct
1866 {
1867 DBusMessageIter *iter;
1868 DBusGValueMarshalFunc marshaller;
1869 gboolean err;
1870 } DBusGValueCollectionMarshalData;
1871
1872 static void
collection_marshal_iterator(const GValue * eltval,gpointer user_data)1873 collection_marshal_iterator (const GValue *eltval,
1874 gpointer user_data)
1875 {
1876 DBusGValueCollectionMarshalData *data = user_data;
1877
1878 if (data->err)
1879 return;
1880
1881 if (!data->marshaller (data->iter, eltval))
1882 data->err = TRUE;
1883 }
1884
1885 static gboolean
marshal_collection(DBusMessageIter * iter,const GValue * value)1886 marshal_collection (DBusMessageIter *iter,
1887 const GValue *value)
1888 {
1889 GType coltype;
1890 GType subtype;
1891
1892 coltype = G_VALUE_TYPE (value);
1893 subtype = dbus_g_type_get_collection_specialization (coltype);
1894
1895 if (_dbus_g_type_is_fixed (subtype))
1896 return marshal_collection_array (iter, value);
1897 else
1898 return marshal_collection_ptrarray (iter, value);
1899 }
1900
1901 static gboolean
marshal_collection_ptrarray(DBusMessageIter * iter,const GValue * value)1902 marshal_collection_ptrarray (DBusMessageIter *iter,
1903 const GValue *value)
1904 {
1905 GType coltype;
1906 GType elt_gtype;
1907 DBusGValueCollectionMarshalData data;
1908 DBusMessageIter subiter;
1909 char *elt_sig;
1910
1911 coltype = G_VALUE_TYPE (value);
1912 elt_gtype = dbus_g_type_get_collection_specialization (coltype);
1913 data.marshaller = get_type_marshaller (elt_gtype);
1914 if (!data.marshaller)
1915 return FALSE;
1916
1917 elt_sig = _dbus_gtype_to_signature (elt_gtype);
1918 if (!elt_sig)
1919 {
1920 g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
1921 return FALSE;
1922 }
1923 g_assert (g_variant_is_signature (elt_sig));
1924
1925 if (!dbus_message_iter_open_container (iter,
1926 DBUS_TYPE_ARRAY,
1927 elt_sig,
1928 &subiter))
1929 oom ();
1930
1931 g_free (elt_sig);
1932
1933 data.iter = &subiter;
1934 data.err = FALSE;
1935
1936 dbus_g_type_collection_value_iterate (value,
1937 collection_marshal_iterator,
1938 &data);
1939
1940 if (data.err)
1941 {
1942 dbus_message_iter_abandon_container (iter, &subiter);
1943 return FALSE;
1944 }
1945
1946 return dbus_message_iter_close_container (iter, &subiter);
1947 }
1948
1949 /* If any of these assertions are violated, then marshal_collection_array
1950 * is buggy for that type. dbus_g_value_basic_array_parse_variant() has
1951 * general size-conversion code, if needed. */
1952 G_STATIC_ASSERT (sizeof (dbus_bool_t) == sizeof (gboolean));
1953 G_STATIC_ASSERT (sizeof (dbus_int32_t) == sizeof (gint));
1954 G_STATIC_ASSERT (sizeof (dbus_uint32_t) == sizeof (guint));
1955 /* These should be true regardless, but just for completeness... */
1956 G_STATIC_ASSERT (sizeof (dbus_int64_t) == sizeof (gint64));
1957 G_STATIC_ASSERT (sizeof (dbus_uint64_t) == sizeof (guint64));
1958 G_STATIC_ASSERT (sizeof (double) == sizeof (gdouble));
1959
1960 static gboolean
marshal_collection_array(DBusMessageIter * iter,const GValue * value)1961 marshal_collection_array (DBusMessageIter *iter,
1962 const GValue *value)
1963 {
1964 GType elt_gtype;
1965 DBusMessageIter subiter;
1966 GArray *array;
1967 char *subsignature_str;
1968
1969 array = g_value_get_boxed (value);
1970 g_return_val_if_fail (array != NULL, FALSE);
1971
1972 elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
1973 g_assert (_dbus_g_type_is_fixed (elt_gtype));
1974 subsignature_str = _dbus_gtype_to_signature (elt_gtype);
1975 if (!subsignature_str)
1976 {
1977 g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
1978 return FALSE;
1979 }
1980 g_assert (g_variant_is_signature (subsignature_str));
1981
1982 if (!dbus_message_iter_open_container (iter,
1983 DBUS_TYPE_ARRAY,
1984 subsignature_str,
1985 &subiter))
1986 oom ();
1987
1988 /* TODO - This assumes that basic values are the same size
1989 * is this always true? If it is we can probably avoid
1990 * a lot of the overhead in _marshal_basic_instance...
1991 */
1992 if (!dbus_message_iter_append_fixed_array (&subiter,
1993 subsignature_str[0],
1994 &(array->data),
1995 array->len))
1996 {
1997 g_critical ("Unable to serialize %u GArray members as signature %s "
1998 "(OOM or invalid boolean value?)", array->len, subsignature_str);
1999
2000 g_free (subsignature_str);
2001 dbus_message_iter_abandon_container (iter, &subiter);
2002 return FALSE;
2003 }
2004
2005 g_free (subsignature_str);
2006 return dbus_message_iter_close_container (iter, &subiter);
2007 }
2008
2009 gboolean
_dbus_gvalue_marshal(DBusMessageIter * iter,const GValue * value)2010 _dbus_gvalue_marshal (DBusMessageIter *iter,
2011 const GValue *value)
2012 {
2013 GType gtype;
2014 DBusGValueMarshalFunc marshaller;
2015
2016 gtype = G_VALUE_TYPE (value);
2017
2018 marshaller = get_type_marshaller (gtype);
2019 if (marshaller == NULL)
2020 return FALSE;
2021 return marshaller (iter, value);
2022 }
2023
2024 #ifdef DBUS_BUILD_TESTS
2025
2026 static void
assert_type_maps_to(GType gtype,const char * expected_sig)2027 assert_type_maps_to (GType gtype, const char *expected_sig)
2028 {
2029 char *sig;
2030 sig = _dbus_gtype_to_signature (gtype);
2031 g_assert_nonnull (sig);
2032 g_assert_cmpstr (expected_sig, ==, sig);
2033 g_free (sig);
2034 }
2035
2036 static void
assert_signature_maps_to(const char * sig,GType expected_gtype)2037 assert_signature_maps_to (const char *sig, GType expected_gtype)
2038 {
2039 g_assert_cmpuint (_dbus_gtype_from_signature (sig, TRUE), ==, expected_gtype);
2040 }
2041
2042 static void
assert_bidirectional_mapping(GType gtype,const char * expected_sig)2043 assert_bidirectional_mapping (GType gtype, const char *expected_sig)
2044 {
2045 assert_type_maps_to (gtype, expected_sig);
2046 assert_signature_maps_to (expected_sig, gtype);
2047 }
2048
2049 /*
2050 * Unit test for general glib stuff
2051 * Returns: %TRUE on success.
2052 */
2053 gboolean
_dbus_gvalue_test(const char * test_data_dir)2054 _dbus_gvalue_test (const char *test_data_dir)
2055 {
2056 GType type;
2057 GType rectype;
2058
2059 g_type_init ();
2060 _dbus_g_value_types_init ();
2061
2062 assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
2063 assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
2064 assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
2065
2066 assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
2067 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);
2068 assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
2069 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
2070 assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
2071 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
2072
2073 assert_bidirectional_mapping (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID),
2074 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 );
2075
2076 rectype = dbus_g_type_get_collection ("GArray", G_TYPE_UINT);
2077 g_assert_cmpuint (rectype, !=, G_TYPE_INVALID);
2078 g_assert_cmpstr (g_type_name (rectype), ==, "GArray_guint_");
2079
2080 type = _dbus_gtype_from_signature ("au", TRUE);
2081 g_assert_cmpuint (type, ==, rectype);
2082
2083 rectype = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING);
2084 g_assert_cmpuint (rectype, !=, G_TYPE_INVALID);
2085 g_assert_cmpstr (g_type_name (rectype), ==, "GHashTable_gchararray+gchararray_");
2086
2087 type = _dbus_gtype_from_signature ("a{ss}", TRUE);
2088 g_assert_cmpuint (type, ==, rectype);
2089
2090 type = _dbus_gtype_from_signature ("o", FALSE);
2091 g_assert_cmpuint (type, ==, DBUS_TYPE_G_OBJECT_PATH);
2092 type = _dbus_gtype_from_signature ("o", TRUE);
2093 g_assert_cmpuint (type, ==, DBUS_TYPE_G_OBJECT_PATH);
2094
2095 type = _dbus_gtype_from_signature ("g", TRUE);
2096 g_assert_cmpuint (type, ==, DBUS_TYPE_G_SIGNATURE);
2097
2098 return TRUE;
2099 }
2100
2101 #endif /* DBUS_BUILD_TESTS */
2102