* Released 0.50
[platform/upstream/dbus.git] / glib / dbus-gvalue.c
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  * Licensed under the Academic Free License version 2.1
8  * 
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.
13  *
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.
18  * 
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
22  *
23  */
24
25 #include "config.h"
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"
32 #include <string.h>
33 #include <glib.h>
34 #include <glib/gi18n.h>
35 #include "dbus/dbus-signature.h"
36
37 static gboolean demarshal_static_variant (DBusGValueMarshalCtx    *context,
38                                           DBusMessageIter         *iter,
39                                           GValue                  *value,
40                                           GError                 **error);
41
42
43 static gboolean marshal_basic                   (DBusMessageIter           *iter,
44                                                  const GValue              *value);
45 static gboolean demarshal_basic                 (DBusGValueMarshalCtx      *context,
46                                                  DBusMessageIter           *iter,
47                                                  GValue                    *value,
48                                                  GError                   **error);
49 static gboolean marshal_strv                    (DBusMessageIter           *iter,
50                                                  const GValue              *value);
51 static gboolean demarshal_strv                  (DBusGValueMarshalCtx      *context,
52                                                  DBusMessageIter           *iter,
53                                                  GValue                    *value,
54                                                  GError                   **error);
55 static gboolean marshal_valuearray              (DBusMessageIter           *iter,
56                                                  const GValue              *value);
57 static gboolean demarshal_valuearray            (DBusGValueMarshalCtx      *context,
58                                                  DBusMessageIter           *iter,
59                                                  GValue                    *value,
60                                                  GError                   **error);
61 static gboolean marshal_variant                 (DBusMessageIter           *iter,
62                                                  const GValue              *value);
63 static gboolean demarshal_variant               (DBusGValueMarshalCtx      *context,
64                                                  DBusMessageIter           *iter,
65                                                  GValue                    *value,
66                                                  GError                   **error);
67 static gboolean marshal_proxy                   (DBusMessageIter           *iter,
68                                                  const GValue             *value);
69 static gboolean demarshal_proxy                 (DBusGValueMarshalCtx      *context,
70                                                  DBusMessageIter           *iter,
71                                                  GValue                    *value,
72                                                  GError                   **error);
73 static gboolean marshal_object_path             (DBusMessageIter           *iter,
74                                                  const GValue             *value);
75 static gboolean demarshal_object_path           (DBusGValueMarshalCtx      *context,
76                                                  DBusMessageIter           *iter,
77                                                  GValue                    *value,
78                                                  GError                   **error);
79 static gboolean marshal_object                  (DBusMessageIter           *iter,
80                                                  const GValue              *value);
81 static gboolean demarshal_object                (DBusGValueMarshalCtx      *context,
82                                                  DBusMessageIter           *iter,
83                                                  GValue                    *value,
84                                                  GError                   **error);
85 static gboolean marshal_map                     (DBusMessageIter           *iter,
86                                                  const GValue              *value);
87 static gboolean demarshal_map                   (DBusGValueMarshalCtx      *context,
88                                                  DBusMessageIter           *iter,
89                                                  GValue                    *value,
90                                                  GError                   **error);
91
92 static gboolean marshal_collection              (DBusMessageIter           *iter,
93                                                  const GValue              *value);
94 static gboolean marshal_collection_ptrarray     (DBusMessageIter           *iter,
95                                                  const GValue              *value);
96 static gboolean marshal_collection_array        (DBusMessageIter           *iter,
97                                                  const GValue              *value);
98 static gboolean demarshal_collection            (DBusGValueMarshalCtx      *context,
99                                                  DBusMessageIter           *iter,
100                                                  GValue                    *value,
101                                                  GError                   **error);
102 static gboolean demarshal_collection_ptrarray   (DBusGValueMarshalCtx      *context,
103                                                  DBusMessageIter           *iter,
104                                                  GValue                    *value,
105                                                  GError                   **error);
106 static gboolean demarshal_collection_array      (DBusGValueMarshalCtx      *context,
107                                                  DBusMessageIter           *iter,
108                                                  GValue                    *value,
109                                                  GError                   **error);
110
111 typedef gboolean (*DBusGValueMarshalFunc)       (DBusMessageIter           *iter,
112                                                  const GValue              *value);
113 typedef gboolean (*DBusGValueDemarshalFunc)     (DBusGValueMarshalCtx      *context,
114                                                  DBusMessageIter           *iter,
115                                                  GValue                    *value,
116                                                  GError                   **error);
117
118 typedef struct {
119   DBusGValueMarshalFunc       marshaller;
120   DBusGValueDemarshalFunc     demarshaller;
121 } DBusGTypeMarshalVtable;
122
123 typedef struct {
124   const char                       *sig;
125   const DBusGTypeMarshalVtable     *vtable;
126 } DBusGTypeMarshalData;
127
128 static GQuark
129 dbus_g_type_metadata_data_quark ()
130 {
131   static GQuark quark;
132   if (!quark)
133     quark = g_quark_from_static_string ("DBusGTypeMetaData");
134   
135   return quark;
136 }
137
138 static void
139 set_type_metadata (GType type, const DBusGTypeMarshalData *data)
140 {
141   g_type_set_qdata (type, dbus_g_type_metadata_data_quark (), (gpointer) data);
142 }
143
144 static void
145 register_basic (int typecode, const DBusGTypeMarshalData *typedata)
146 {
147   set_type_metadata (_dbus_gtype_from_basic_typecode (typecode), typedata);
148 }
149
150 void
151 _dbus_g_value_types_init (void)
152 {
153   static gboolean types_initialized;
154
155   static const DBusGTypeMarshalVtable basic_vtable = {
156     marshal_basic,
157     demarshal_basic
158   };
159
160   if (types_initialized)
161     return;
162
163   dbus_g_type_specialized_init ();
164   _dbus_g_type_specialized_builtins_init ();
165
166   /* Register basic types */
167   {
168     static const DBusGTypeMarshalData typedata = {
169       DBUS_TYPE_BOOLEAN_AS_STRING,
170       &basic_vtable,
171     };
172     register_basic (DBUS_TYPE_BOOLEAN, &typedata);
173   }
174   {
175     static const DBusGTypeMarshalData typedata = {
176       DBUS_TYPE_BYTE_AS_STRING,
177       &basic_vtable,
178     };
179     register_basic (DBUS_TYPE_BYTE, &typedata);
180   }
181   {
182     static const DBusGTypeMarshalData typedata = {
183       DBUS_TYPE_INT16_AS_STRING,
184       &basic_vtable,
185     };
186     register_basic (DBUS_TYPE_INT16, &typedata);
187   }
188   {
189     static const DBusGTypeMarshalData typedata = {
190       DBUS_TYPE_UINT16_AS_STRING,
191       &basic_vtable,
192     };
193     register_basic (DBUS_TYPE_UINT16, &typedata);
194   }
195   {
196     static const DBusGTypeMarshalData typedata = {
197       DBUS_TYPE_UINT32_AS_STRING,
198       &basic_vtable,
199     };
200     register_basic (DBUS_TYPE_UINT32, &typedata);
201   }
202   {
203     static const DBusGTypeMarshalData typedata = {
204       DBUS_TYPE_INT32_AS_STRING,
205       &basic_vtable,
206     };
207     register_basic (DBUS_TYPE_INT32, &typedata);
208   }
209   {
210     static const DBusGTypeMarshalData typedata = {
211       DBUS_TYPE_UINT64_AS_STRING,
212       &basic_vtable,
213     };
214     register_basic (DBUS_TYPE_UINT64, &typedata);
215   }
216   {
217     static const DBusGTypeMarshalData typedata = {
218       DBUS_TYPE_INT64_AS_STRING,
219       &basic_vtable,
220     };
221     register_basic (DBUS_TYPE_INT64, &typedata);
222   }
223   {
224     static const DBusGTypeMarshalData typedata = {
225       DBUS_TYPE_DOUBLE_AS_STRING,
226       &basic_vtable,
227     };
228     register_basic (DBUS_TYPE_DOUBLE, &typedata);
229   }
230   {
231     static const DBusGTypeMarshalData typedata = {
232       DBUS_TYPE_STRING_AS_STRING,
233       &basic_vtable,
234     };
235     register_basic (DBUS_TYPE_STRING, &typedata);
236   }
237   /* fundamental GTypes that don't map 1:1 with D-BUS types */
238   {
239     static const DBusGTypeMarshalData typedata = {
240       DBUS_TYPE_BYTE_AS_STRING,
241       &basic_vtable,
242     };
243     set_type_metadata (G_TYPE_CHAR, &typedata);
244   }
245   {
246     static const DBusGTypeMarshalData typedata = {
247       DBUS_TYPE_INT32_AS_STRING,
248       &basic_vtable,
249     };
250     set_type_metadata (G_TYPE_LONG, &typedata);
251   }
252   {
253     static const DBusGTypeMarshalData typedata = {
254       DBUS_TYPE_UINT32_AS_STRING,
255       &basic_vtable,
256     };
257     set_type_metadata (G_TYPE_ULONG, &typedata);
258   }
259   {
260     static const DBusGTypeMarshalData typedata = {
261       DBUS_TYPE_DOUBLE_AS_STRING,
262       &basic_vtable,
263     };
264     set_type_metadata (G_TYPE_FLOAT, &typedata);
265   }
266
267   /* Register complex types with builtin GType mappings */
268   {
269     static const DBusGTypeMarshalVtable vtable = {
270       marshal_variant,
271       demarshal_variant
272     };
273     static const DBusGTypeMarshalData typedata = {
274       DBUS_TYPE_VARIANT_AS_STRING,
275       &vtable
276     };
277     set_type_metadata (G_TYPE_VALUE, &typedata);
278   };
279   {
280     static const DBusGTypeMarshalVtable vtable = {
281       marshal_strv,
282       demarshal_strv
283     };
284     static const DBusGTypeMarshalData typedata = {
285       DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
286       &vtable
287     };
288     set_type_metadata (G_TYPE_STRV, &typedata);
289   };
290
291
292   /* Register some types specific to the D-BUS GLib bindings */
293   {
294     static const DBusGTypeMarshalVtable vtable = {
295       marshal_proxy,
296       demarshal_proxy
297     };
298     static const DBusGTypeMarshalData typedata = {
299       DBUS_TYPE_OBJECT_PATH_AS_STRING,
300       &vtable
301     };
302     set_type_metadata (DBUS_TYPE_G_PROXY, &typedata);
303   }
304
305   {
306     static const DBusGTypeMarshalVtable vtable = {
307       marshal_object_path,
308       demarshal_object_path
309     };
310     static const DBusGTypeMarshalData typedata = {
311       DBUS_TYPE_OBJECT_PATH_AS_STRING,
312       &vtable
313     };
314     set_type_metadata (DBUS_TYPE_G_OBJECT_PATH, &typedata);
315   }
316
317   {
318     static const DBusGTypeMarshalVtable vtable = {
319       marshal_object,
320       demarshal_object
321     };
322     static const DBusGTypeMarshalData typedata = {
323       DBUS_TYPE_OBJECT_PATH_AS_STRING,
324       &vtable
325     };
326     set_type_metadata (G_TYPE_OBJECT, &typedata);
327   }
328
329   types_initialized = TRUE;
330 }
331
332 /**
333  * Get the GLib type ID for a DBusGObjectPath boxed type.
334  *
335  * @returns GLib type
336  */
337 GType
338 dbus_g_object_path_get_g_type (void)
339 {
340   static GType type_id = 0;
341
342   if (!type_id)
343     type_id = g_boxed_type_register_static ("DBusGObjectPath",
344                                             (GBoxedCopyFunc) g_strdup,
345                                             (GBoxedFreeFunc) g_free);
346   return type_id;
347 }
348
349 char *
350 _dbus_gtype_to_signature (GType gtype)
351 {
352   char *ret;
353   DBusGTypeMarshalData *typedata;
354
355   if (dbus_g_type_is_collection (gtype))
356     {
357       GType elt_gtype;
358       char *subsig;
359
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);
363       g_free (subsig);
364     }
365   else if (dbus_g_type_is_map (gtype))
366     {
367       GType key_gtype;
368       GType val_gtype;
369       char *key_subsig;
370       char *val_subsig;
371
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);
377       g_free (key_subsig);
378       g_free (val_subsig);
379     }
380   else
381     {
382       typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ());
383       if (typedata == NULL)
384         return NULL;
385       ret = g_strdup (typedata->sig);
386     }
387   
388   return ret;
389 }
390
391 static char *
392 dbus_gvalue_to_signature (const GValue *val)
393 {
394   GType gtype;
395
396   gtype = G_VALUE_TYPE (val);
397   if (g_type_is_a (gtype, G_TYPE_VALUE_ARRAY))
398     {
399       GString *str;
400       guint i;
401       GValueArray *array;
402
403       array = g_value_get_boxed (val);
404       
405       str = g_string_new ("");
406       for (i = 0; i < array->n_values; i++)
407         {
408           char *sig;
409           sig = dbus_gvalue_to_signature (g_value_array_get_nth (array, i));
410           g_string_append (str, sig);
411           g_free (sig);
412         }
413       return g_string_free (str, FALSE);
414     }
415   else
416     return _dbus_gtype_to_signature (gtype);
417 }
418
419 static gboolean
420 demarshal_basic (DBusGValueMarshalCtx      *context,
421                  DBusMessageIter           *iter,
422                  GValue                    *value,
423                  GError                   **error)
424 {
425   int current_type;
426   
427   current_type = dbus_message_iter_get_arg_type (iter);
428   g_assert (dbus_type_is_basic (current_type));
429
430   switch (current_type)
431     {
432     case DBUS_TYPE_BOOLEAN:
433       {
434         dbus_bool_t bool;
435         dbus_message_iter_get_basic (iter, &bool);
436         g_value_set_boolean (value, bool);
437         return TRUE;
438       }
439     case DBUS_TYPE_BYTE:
440       {
441         unsigned char byte;
442         dbus_message_iter_get_basic (iter, &byte);
443         g_value_set_uchar (value, byte);
444         return TRUE;
445       }
446     case DBUS_TYPE_INT32:
447       {
448         dbus_int32_t intval;
449         dbus_message_iter_get_basic (iter, &intval);
450         g_value_set_int (value, intval);
451         return TRUE;
452       }
453     case DBUS_TYPE_UINT32:
454       {
455         dbus_uint32_t intval;
456         dbus_message_iter_get_basic (iter, &intval);
457         g_value_set_uint (value, intval);
458         return TRUE;
459       }
460     case DBUS_TYPE_INT64:
461       {
462         dbus_int64_t intval;
463         dbus_message_iter_get_basic (iter, &intval);
464         g_value_set_int64 (value, intval);
465         return TRUE;
466       }
467     case DBUS_TYPE_UINT64:
468       {
469         dbus_uint64_t intval;
470         dbus_message_iter_get_basic (iter, &intval);
471         g_value_set_uint64 (value, intval);
472         return TRUE;
473       }
474     case DBUS_TYPE_DOUBLE:
475       {
476         double dval;
477         dbus_message_iter_get_basic (iter, &dval);
478         g_value_set_double (value, dval);
479         return TRUE;
480       }
481     case DBUS_TYPE_INT16:
482       {
483         dbus_int16_t v;
484         dbus_message_iter_get_basic (iter, &v);
485         g_value_set_int (value, v);
486         return TRUE;
487       }
488     case DBUS_TYPE_UINT16:
489       {
490         dbus_uint16_t v;
491         dbus_message_iter_get_basic (iter, &v);
492         g_value_set_uint (value, v);
493         return TRUE;
494       }
495     case DBUS_TYPE_STRING:
496       {
497         const char *s;
498         dbus_message_iter_get_basic (iter, &s);
499         g_value_set_string (value, s);
500         return TRUE;
501       }
502     default:
503       g_assert_not_reached ();
504       return FALSE;
505     }
506 }
507
508 static gboolean
509 demarshal_static_variant (DBusGValueMarshalCtx    *context,
510                           DBusMessageIter         *iter,
511                           GValue                  *value,
512                           GError                 **error)
513 {
514   char *sig;
515   int current_type;
516   DBusMessageIter subiter;
517   GType variant_type;
518
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);
522
523   variant_type = _dbus_gtype_from_signature (sig, context->proxy != NULL);
524   if (variant_type != G_TYPE_INVALID)
525     {
526       g_value_init (value, variant_type);
527
528       if (!_dbus_gvalue_demarshal (context, &subiter, value, error))
529         {
530           dbus_free (sig);
531           return FALSE;
532         }
533     }
534   dbus_free (sig);
535   return TRUE;
536 }
537
538 static gboolean
539 demarshal_variant (DBusGValueMarshalCtx    *context,
540                    DBusMessageIter         *iter,
541                    GValue                  *value,
542                    GError                 **error)
543
544 {
545   GValue *variant_val;
546   variant_val = g_new0 (GValue, 1);
547
548   if (!demarshal_static_variant (context, iter, variant_val, error))
549     return FALSE;
550   
551   g_value_set_boxed_take_ownership (value, variant_val);
552   return TRUE;
553 }
554
555 static gboolean
556 demarshal_proxy (DBusGValueMarshalCtx    *context,
557                  DBusMessageIter         *iter,
558                  GValue                  *value,
559                  GError                 **error)
560 {
561   DBusGProxy *new_proxy;
562   const char *objpath;
563   int current_type;
564
565   current_type = dbus_message_iter_get_arg_type (iter);
566   if (current_type != DBUS_TYPE_OBJECT_PATH)
567     {
568       g_set_error (error,
569                    DBUS_GERROR,
570                    DBUS_GERROR_INVALID_ARGS,
571                    _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
572       return FALSE;
573     }
574
575   g_assert (context->proxy != NULL);
576   
577   dbus_message_iter_get_basic (iter, &objpath);
578
579   new_proxy = dbus_g_proxy_new_from_proxy (context->proxy, NULL, objpath);
580   g_value_set_object_take_ownership (value, new_proxy);
581
582   return TRUE;
583 }
584
585 static gboolean
586 demarshal_object_path (DBusGValueMarshalCtx    *context,
587                        DBusMessageIter         *iter,
588                        GValue                  *value,
589                        GError                 **error)
590 {
591   const char *objpath;
592   int current_type;
593
594   current_type = dbus_message_iter_get_arg_type (iter);
595   if (current_type != DBUS_TYPE_OBJECT_PATH)
596     {
597       g_set_error (error,
598                    DBUS_GERROR,
599                    DBUS_GERROR_INVALID_ARGS,
600                    _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
601       return FALSE;
602     }
603
604   dbus_message_iter_get_basic (iter, &objpath);
605
606   g_value_set_boxed_take_ownership (value, g_strdup (objpath));
607
608   return TRUE;
609 }
610
611 static gboolean
612 demarshal_object (DBusGValueMarshalCtx    *context,
613                   DBusMessageIter         *iter,
614                   GValue                  *value,
615                   GError                 **error)
616 {
617   const char *objpath;
618   int current_type;
619   GObject *obj;
620
621   current_type = dbus_message_iter_get_arg_type (iter);
622   if (current_type != DBUS_TYPE_OBJECT_PATH)
623     {
624       g_set_error (error,
625                    DBUS_GERROR,
626                    DBUS_GERROR_INVALID_ARGS,
627                    _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
628       return FALSE;
629     }
630   g_assert (context->proxy == NULL);
631
632   dbus_message_iter_get_basic (iter, &objpath);
633
634   obj = dbus_g_connection_lookup_g_object (context->gconnection, objpath);
635   if (obj == NULL)
636     {
637       g_set_error (error,
638                    DBUS_GERROR,
639                    DBUS_GERROR_INVALID_ARGS,
640                    _("Unregistered object at path '%s'"),
641                    objpath);
642       return FALSE;
643     }
644   g_value_set_object (value, obj);
645
646   return TRUE;
647 }
648
649 static gboolean
650 demarshal_strv (DBusGValueMarshalCtx    *context,
651                 DBusMessageIter         *iter,
652                 GValue                  *value,
653                 GError                 **error)
654 {
655   DBusMessageIter subiter;
656   int current_type;
657   char **ret;
658   int len;
659   int i;
660
661   current_type = dbus_message_iter_get_arg_type (iter);
662   if (current_type != DBUS_TYPE_ARRAY)
663     {
664       g_set_error (error,
665                    DBUS_GERROR,
666                    DBUS_GERROR_INVALID_ARGS,
667                    _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
668       return FALSE;
669     }
670
671   dbus_message_iter_recurse (iter, &subiter);
672
673   current_type = dbus_message_iter_get_arg_type (&subiter);
674   if (current_type != DBUS_TYPE_INVALID
675       && current_type != DBUS_TYPE_STRING)
676     {
677       g_set_error (error,
678                    DBUS_GERROR,
679                    DBUS_GERROR_INVALID_ARGS,
680                    _("Expected D-BUS string, got type code \'%c\'"), (guchar) current_type);
681       return FALSE;
682     }
683
684   len = dbus_message_iter_get_array_len (&subiter);
685   g_assert (len >= 0);
686   ret = g_malloc (sizeof (char *) * (len + 1));
687   
688   i = 0;
689   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
690     {
691       g_assert (i < len);
692       g_assert (current_type == DBUS_TYPE_STRING);
693       
694       dbus_message_iter_get_basic (&subiter, &(ret[i]));
695       ret[i] = g_strdup (ret[i]);
696
697       dbus_message_iter_next (&subiter);
698       i++;
699     }
700   ret[i] = NULL; 
701   g_value_set_boxed_take_ownership (value, ret);
702   
703   return TRUE;
704 }
705
706 static gboolean
707 demarshal_valuearray (DBusGValueMarshalCtx    *context,
708                       DBusMessageIter         *iter,
709                       GValue                  *value,
710                       GError                 **error)
711 {
712   int current_type;
713   GValueArray *ret;
714   DBusMessageIter subiter;
715
716   current_type = dbus_message_iter_get_arg_type (iter);
717   if (current_type != DBUS_TYPE_STRUCT)
718     {
719       g_set_error (error,
720                    DBUS_GERROR,
721                    DBUS_GERROR_INVALID_ARGS,
722                    _("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type);
723       return FALSE;
724     }
725
726   dbus_message_iter_recurse (iter, &subiter);
727
728   ret = g_value_array_new (12);
729
730   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
731     {
732       GValue *val;
733       GType elt_type; 
734       char *current_sig;
735
736       g_value_array_append (ret, NULL);
737       val = g_value_array_get_nth (ret, ret->n_values - 1);
738
739       current_sig = dbus_message_iter_get_signature (&subiter);
740       elt_type = _dbus_gtype_from_signature (current_sig, TRUE);
741
742       g_free (current_sig);
743       if (elt_type == G_TYPE_INVALID)
744         {
745           g_value_array_free (ret);
746           g_set_error (error,
747                        DBUS_GERROR,
748                        DBUS_GERROR_INVALID_ARGS,
749                        _("Couldn't demarshal argument with signature \"%s\""), current_sig);
750           return FALSE;
751         }
752       
753       g_value_init (val, elt_type);
754
755       if (!_dbus_gvalue_demarshal (context, &subiter, val, error))
756         {
757           g_value_array_free (ret);
758           return FALSE;
759         }
760
761       dbus_message_iter_next (&subiter);
762     }
763
764   g_value_set_boxed_take_ownership (value, ret);
765   
766   return TRUE;
767 }
768
769 static gboolean
770 demarshal_map (DBusGValueMarshalCtx    *context,
771                DBusMessageIter         *iter,
772                GValue                  *value,
773                GError                 **error)
774 {
775   GType gtype;
776   DBusMessageIter subiter;
777   int current_type;
778   gpointer ret;
779   GType key_gtype;
780   GType value_gtype;
781   DBusGTypeSpecializedAppendContext appendctx;
782
783   current_type = dbus_message_iter_get_arg_type (iter);
784   if (current_type != DBUS_TYPE_ARRAY)
785     {
786       g_set_error (error,
787                    DBUS_GERROR,
788                    DBUS_GERROR_INVALID_ARGS,
789                    _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
790       return FALSE;
791     }
792
793   gtype = G_VALUE_TYPE (value);
794
795   dbus_message_iter_recurse (iter, &subiter);
796
797   current_type = dbus_message_iter_get_arg_type (&subiter);
798   if (current_type != DBUS_TYPE_INVALID
799       && current_type != DBUS_TYPE_DICT_ENTRY)
800     {
801       g_set_error (error,
802                    DBUS_GERROR,
803                    DBUS_GERROR_INVALID_ARGS,
804                    _("Expected D-BUS dict entry, got type code \'%c\'"), (guchar) current_type);
805       return FALSE;
806     }
807
808   key_gtype = dbus_g_type_get_map_key_specialization (gtype);
809   value_gtype = dbus_g_type_get_map_value_specialization (gtype);
810
811   ret = dbus_g_type_specialized_construct (gtype);
812   g_value_set_boxed_take_ownership (value, ret);
813
814   dbus_g_type_specialized_init_append (value, &appendctx);
815
816   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
817     {
818       DBusMessageIter entry_iter;
819       GValue key_value = {0,};
820       GValue value_value = {0,};
821
822       current_type = dbus_message_iter_get_arg_type (&subiter);
823       g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
824
825       dbus_message_iter_recurse (&subiter, &entry_iter);
826
827       g_value_init (&key_value, key_gtype);
828       if (!_dbus_gvalue_demarshal (context,
829                                   &entry_iter,
830                                   &key_value,
831                                   error))
832         return FALSE;
833
834       dbus_message_iter_next (&entry_iter);
835
836       g_value_init (&value_value, value_gtype);
837       if (!_dbus_gvalue_demarshal (context,
838                                   &entry_iter,
839                                   &value_value,
840                                   error))
841         return FALSE;
842
843       dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
844       /* Ownership of values passes to map, don't unset */
845
846       dbus_message_iter_next (&subiter);
847     }
848   
849   return TRUE;
850 }
851
852 static DBusGValueDemarshalFunc
853 get_type_demarshaller (GType type)
854 {
855   DBusGTypeMarshalData *typedata;
856
857   typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
858   if (typedata == NULL)
859     {
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;
866
867       g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
868       return NULL;
869     }
870   g_assert (typedata->vtable);
871   return typedata->vtable->demarshaller;
872 }
873
874 static gboolean
875 demarshal_collection (DBusGValueMarshalCtx    *context,
876                       DBusMessageIter         *iter,
877                       GValue                  *value,
878                       GError                 **error)
879 {
880   GType coltype;
881   GType subtype;
882   
883   coltype = G_VALUE_TYPE (value);
884   subtype = dbus_g_type_get_collection_specialization (coltype);
885
886   if (_dbus_g_type_is_fixed (subtype))
887     return demarshal_collection_array (context, iter, value, error);
888   else
889     return demarshal_collection_ptrarray (context, iter, value, error);
890 }
891
892 static gboolean
893 demarshal_collection_ptrarray (DBusGValueMarshalCtx    *context,
894                                DBusMessageIter         *iter,
895                                GValue                  *value,
896                                GError                 **error)
897 {
898   GType coltype;
899   GType subtype;
900   gpointer instance;
901   DBusGTypeSpecializedAppendContext ctx;
902   DBusGValueDemarshalFunc demarshaller;
903   DBusMessageIter subiter;
904   int current_type;
905
906   current_type = dbus_message_iter_get_arg_type (iter);
907
908   if (current_type != DBUS_TYPE_ARRAY)
909     {
910       g_set_error (error,
911                    DBUS_GERROR,
912                    DBUS_GERROR_INVALID_ARGS,
913                    _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
914       return FALSE;
915     }
916
917   dbus_message_iter_recurse (iter, &subiter);
918   
919   coltype = G_VALUE_TYPE (value);
920   subtype = dbus_g_type_get_collection_specialization (coltype);
921
922   demarshaller = get_type_demarshaller (subtype);
923
924   if (!demarshaller)
925     {
926       g_set_error (error,
927                    DBUS_GERROR,
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));
932       return FALSE;
933     }
934
935   instance = dbus_g_type_specialized_construct (coltype);
936   g_value_set_boxed_take_ownership (value, instance);
937
938   dbus_g_type_specialized_init_append (value, &ctx);
939
940   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
941     {
942       GValue eltval = {0, };
943
944       g_value_init (&eltval, subtype);
945
946       if (!demarshaller (context, &subiter, &eltval, error))
947         {
948           dbus_g_type_specialized_collection_end_append (&ctx);
949           g_value_unset (value);
950           return FALSE;
951         }
952       dbus_g_type_specialized_collection_append (&ctx, &eltval);
953       
954       dbus_message_iter_next (&subiter);
955     }
956   dbus_g_type_specialized_collection_end_append (&ctx);
957   
958   return TRUE;
959 }
960
961 static gboolean
962 demarshal_collection_array (DBusGValueMarshalCtx    *context,
963                             DBusMessageIter         *iter,
964                             GValue                  *value,
965                             GError                 **error)
966 {
967   DBusMessageIter subiter;
968   GArray *ret;
969   GType elt_gtype;
970   int elt_size;
971   void *msgarray;
972   int msgarray_len;
973
974   dbus_message_iter_recurse (iter, &subiter);
975
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));
979
980   elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
981   
982   ret = g_array_new (FALSE, TRUE, elt_size);
983
984   msgarray = NULL;
985   dbus_message_iter_get_fixed_array (&subiter,
986                                      &msgarray,
987                                      &msgarray_len);
988   g_assert (msgarray != NULL);
989   g_assert (msgarray_len >= 0);
990   g_array_append_vals (ret, msgarray, (guint) msgarray_len);
991
992   g_value_set_boxed_take_ownership (value, ret);
993   
994   return TRUE;
995 }
996
997 gboolean
998 _dbus_gvalue_demarshal (DBusGValueMarshalCtx    *context,
999                        DBusMessageIter         *iter,
1000                        GValue                  *value,
1001                        GError                 **error)
1002 {
1003   GType gtype;
1004   DBusGValueDemarshalFunc demarshaller;
1005
1006   gtype = G_VALUE_TYPE (value);
1007
1008   demarshaller = get_type_demarshaller (gtype);
1009
1010   if (demarshaller == NULL)
1011     {
1012       g_set_error (error,
1013                    DBUS_GERROR,
1014                    DBUS_GERROR_INVALID_ARGS,
1015                    _("No demarshaller registered for type \"%s\""),
1016                    g_type_name (gtype));
1017       return FALSE;
1018     }
1019   
1020   return demarshaller (context, iter, value, error);
1021 }
1022
1023 gboolean
1024 _dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx    *context,
1025                                DBusMessageIter         *iter,
1026                                GValue                  *value,
1027                                GError                 **error)
1028 {
1029   return demarshal_static_variant (context, iter, value, error);
1030 }
1031
1032 GValueArray *
1033 _dbus_gvalue_demarshal_message  (DBusGValueMarshalCtx    *context,
1034                                 DBusMessage             *message,
1035                                 guint                    n_types,
1036                                 const GType             *types,
1037                                 GError                 **error)
1038 {
1039   GValueArray *ret;
1040   DBusMessageIter iter;
1041   int current_type;
1042   guint index;
1043   
1044   ret = g_value_array_new (6);  /* 6 is a typical maximum for arguments */
1045
1046   dbus_message_iter_init (message, &iter);
1047   index = 0;
1048   while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
1049     {
1050       GValue *value;
1051       GType gtype;
1052
1053       if (index >= n_types)
1054         {
1055           g_set_error (error, DBUS_GERROR,
1056                        DBUS_GERROR_INVALID_ARGS,
1057                        _("Too many arguments in message"));
1058           goto lose;
1059         }
1060       
1061       g_value_array_append (ret, NULL);
1062       value = g_value_array_get_nth (ret, index);
1063
1064       gtype = types[index]; 
1065       g_value_init (value, gtype);
1066
1067       if (!_dbus_gvalue_demarshal (context, &iter, value, error))
1068         goto lose;
1069       dbus_message_iter_next (&iter);
1070       index++;
1071     }
1072   if (index < n_types)
1073     {
1074       g_set_error (error, DBUS_GERROR,
1075                    DBUS_GERROR_INVALID_ARGS,
1076                    _("Too few arguments in message"));
1077       goto lose;
1078     }
1079
1080   return ret;
1081  lose:
1082   g_value_array_free (ret);
1083   return NULL;
1084 }
1085
1086 static gboolean
1087 marshal_basic (DBusMessageIter *iter, const GValue *value)
1088 {
1089   GType value_type;
1090
1091   value_type = G_VALUE_TYPE (value);
1092   
1093   switch (value_type)
1094     {
1095     case G_TYPE_CHAR:
1096       {
1097         char b = g_value_get_char (value);
1098         if (!dbus_message_iter_append_basic (iter,
1099                                              DBUS_TYPE_BYTE,
1100                                              &b))
1101           goto nomem;
1102       }
1103       return TRUE;
1104     case G_TYPE_UCHAR:
1105       {
1106         unsigned char b = g_value_get_uchar (value);
1107         if (!dbus_message_iter_append_basic (iter,
1108                                              DBUS_TYPE_BYTE,
1109                                              &b))
1110           goto nomem;
1111       }
1112       return TRUE;
1113     case G_TYPE_BOOLEAN:
1114       {
1115         dbus_bool_t b = g_value_get_boolean (value);
1116         if (!dbus_message_iter_append_basic (iter,
1117                                              DBUS_TYPE_BOOLEAN,
1118                                              &b))
1119           goto nomem;
1120       }
1121       return TRUE;
1122     case G_TYPE_INT:
1123       {
1124         dbus_int32_t v = g_value_get_int (value);
1125         if (!dbus_message_iter_append_basic (iter,
1126                                              DBUS_TYPE_INT32,
1127                                              &v))
1128           goto nomem;
1129       }
1130       return TRUE;
1131     case G_TYPE_UINT:
1132       {
1133         dbus_uint32_t v = g_value_get_uint (value);
1134         if (!dbus_message_iter_append_basic (iter,
1135                                              DBUS_TYPE_UINT32,
1136                                              &v))
1137           goto nomem;
1138       }
1139       return TRUE;
1140     case G_TYPE_LONG:
1141       {
1142         dbus_int32_t v = g_value_get_long (value);
1143         if (!dbus_message_iter_append_basic (iter,
1144                                              DBUS_TYPE_INT32,
1145                                              &v))
1146           goto nomem;
1147       }
1148       return TRUE;
1149     case G_TYPE_ULONG:
1150       {
1151         dbus_uint32_t v = g_value_get_ulong (value);
1152         if (!dbus_message_iter_append_basic (iter,
1153                                              DBUS_TYPE_UINT32,
1154                                              &v))
1155           goto nomem;
1156       }
1157       return TRUE;
1158     case G_TYPE_INT64:
1159       {
1160         gint64 v = g_value_get_int64 (value);
1161         if (!dbus_message_iter_append_basic (iter,
1162                                              DBUS_TYPE_INT64,
1163                                              &v))
1164           goto nomem;
1165       }
1166       return TRUE;
1167     case G_TYPE_UINT64:
1168       {
1169         guint64 v = g_value_get_uint64 (value);
1170         if (!dbus_message_iter_append_basic (iter,
1171                                              DBUS_TYPE_UINT64,
1172                                              &v))
1173           goto nomem;
1174       }
1175       return TRUE;
1176     case G_TYPE_FLOAT:
1177       {
1178         double v = g_value_get_float (value);
1179         
1180         if (!dbus_message_iter_append_basic (iter,
1181                                              DBUS_TYPE_DOUBLE,
1182                                              &v))
1183           goto nomem;
1184       }
1185       return TRUE;
1186     case G_TYPE_DOUBLE:
1187       {
1188         double v = g_value_get_double (value);
1189         
1190         if (!dbus_message_iter_append_basic (iter,
1191                                              DBUS_TYPE_DOUBLE,
1192                                              &v))
1193           goto nomem;
1194       }
1195       return TRUE;
1196     case G_TYPE_STRING:
1197       /* FIXME, the GValue string may not be valid UTF-8 */
1198       {
1199         const char *v = g_value_get_string (value);
1200         if (!v)
1201           v = "";
1202         if (!dbus_message_iter_append_basic (iter,
1203                                              DBUS_TYPE_STRING,
1204                                              &v))
1205           goto nomem;
1206       }
1207       return TRUE;
1208       
1209     default:
1210       {
1211         g_assert_not_reached ();
1212         return FALSE;
1213       }
1214     }
1215
1216  nomem:
1217   g_error ("no memory");
1218   return FALSE;
1219 }
1220
1221 static gboolean
1222 marshal_strv (DBusMessageIter   *iter,
1223               const GValue       *value)
1224 {
1225   DBusMessageIter subiter;
1226   char **array;
1227   char **elt;
1228   gboolean ret = FALSE;
1229
1230   g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
1231
1232   array = g_value_get_boxed (value);
1233
1234   if (!dbus_message_iter_open_container (iter,
1235                                          DBUS_TYPE_ARRAY,
1236                                          "s",
1237                                          &subiter))
1238     goto out;
1239
1240   for (elt = array; *elt; elt++)
1241     {
1242       if (!dbus_message_iter_append_basic (&subiter,
1243                                            DBUS_TYPE_STRING,
1244                                            elt))
1245         goto out;
1246     }
1247
1248   if (!dbus_message_iter_close_container (iter, &subiter))
1249     goto out;
1250   ret = TRUE;
1251  out:
1252   return ret;
1253 }
1254
1255 static gboolean
1256 marshal_valuearray (DBusMessageIter   *iter,
1257                     const GValue       *value)
1258 {
1259   GValueArray *array;
1260   guint i;
1261   DBusMessageIter subiter;
1262
1263   g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
1264
1265   array = g_value_get_boxed (value);
1266
1267   if (!dbus_message_iter_open_container (iter,
1268                                          DBUS_TYPE_STRUCT,
1269                                          NULL,
1270                                          &subiter))
1271     goto oom;
1272
1273   for (i = 0; i < array->n_values; i++)
1274     {
1275       if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
1276         return FALSE;
1277     }
1278
1279   if (!dbus_message_iter_close_container (iter, &subiter))
1280     goto oom;
1281
1282   return TRUE;
1283  oom:
1284   g_error ("out of memory");
1285   return FALSE;
1286 }
1287
1288 static gboolean
1289 marshal_proxy (DBusMessageIter         *iter,
1290                const GValue            *value)
1291 {
1292   const char *path;
1293   DBusGProxy *proxy;
1294
1295   g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
1296
1297   proxy = g_value_get_object (value);
1298   path = dbus_g_proxy_get_path (proxy);
1299   
1300   if (!dbus_message_iter_append_basic (iter,
1301                                        DBUS_TYPE_OBJECT_PATH,
1302                                        &path))
1303     return FALSE;
1304   return TRUE;
1305 }
1306
1307 static gboolean
1308 marshal_object_path (DBusMessageIter         *iter,
1309                      const GValue            *value)
1310 {
1311   const char *path;
1312
1313   g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
1314
1315   path = (const char*) g_value_get_boxed (value);
1316   
1317   if (!dbus_message_iter_append_basic (iter,
1318                                        DBUS_TYPE_OBJECT_PATH,
1319                                        &path))
1320     return FALSE;
1321   return TRUE;
1322 }
1323
1324 static gboolean
1325 marshal_object (DBusMessageIter         *iter,
1326                 const GValue            *value)
1327 {
1328   const char *path;
1329   GObject *obj;
1330
1331   obj = g_value_get_object (value);
1332   path = _dbus_gobject_get_path (obj);
1333
1334   if (path == NULL)
1335     /* FIXME should throw error */
1336     return FALSE;
1337   
1338   if (!dbus_message_iter_append_basic (iter,
1339                                        DBUS_TYPE_OBJECT_PATH,
1340                                        &path))
1341     return FALSE;
1342   return TRUE;
1343 }
1344
1345 struct DBusGLibHashMarshalData
1346 {
1347   const char *entry_sig;
1348   DBusMessageIter *iter;
1349   gboolean err;
1350 };
1351
1352 static void
1353 marshal_map_entry (const GValue *key,
1354                    const GValue *value,
1355                    gpointer data)
1356 {
1357   struct DBusGLibHashMarshalData *hashdata = data;
1358   DBusMessageIter subiter;
1359
1360   if (hashdata->err)
1361     return;
1362
1363   if (!dbus_message_iter_open_container (hashdata->iter,
1364                                          DBUS_TYPE_DICT_ENTRY,
1365                                          NULL,
1366                                          &subiter))
1367     goto lose;
1368
1369   if (!_dbus_gvalue_marshal (&subiter, key))
1370     goto lose;
1371
1372   if (!_dbus_gvalue_marshal (&subiter, value))
1373     goto lose;
1374
1375   if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
1376     goto lose;
1377   
1378   return;
1379  lose:
1380   hashdata->err = TRUE;
1381 }
1382
1383 static gboolean
1384 marshal_map (DBusMessageIter   *iter,
1385              const GValue      *value)
1386 {
1387   GType gtype;
1388   DBusMessageIter arr_iter;
1389   gboolean ret;
1390   struct DBusGLibHashMarshalData hashdata;
1391   char *key_sig;
1392   char *value_sig;
1393   GType key_type;
1394   GType value_type;
1395   char *entry_sig;
1396   char *array_sig;
1397
1398   gtype = G_VALUE_TYPE (value);
1399
1400   ret = FALSE;
1401
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));
1406
1407   key_sig = _dbus_gtype_to_signature (key_type);
1408   if (!key_sig)
1409     {
1410       g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
1411       return FALSE;
1412     }
1413   value_sig = _dbus_gtype_to_signature (value_type);
1414   if (!value_sig)
1415     {
1416       g_free (key_sig);
1417       g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
1418       return FALSE;
1419     }
1420   entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
1421   g_free (key_sig);
1422   g_free (value_sig);
1423   array_sig = g_strdup_printf ("%c%s%c",
1424                                DBUS_DICT_ENTRY_BEGIN_CHAR,
1425                                entry_sig,
1426                                DBUS_DICT_ENTRY_END_CHAR);
1427   if (!dbus_message_iter_open_container (iter,
1428                                          DBUS_TYPE_ARRAY,
1429                                          array_sig,
1430                                          &arr_iter))
1431     goto lose;
1432
1433   hashdata.iter = &arr_iter;
1434   hashdata.err = FALSE;
1435   hashdata.entry_sig = entry_sig;
1436
1437   dbus_g_type_map_value_iterate (value,
1438                                  marshal_map_entry,
1439                                  &hashdata);
1440
1441   if (!dbus_message_iter_close_container (iter, &arr_iter))
1442     goto lose;
1443
1444  out:
1445   g_free (entry_sig);
1446   g_free (array_sig);
1447   return !hashdata.err;
1448  lose:
1449   hashdata.err = TRUE;
1450   goto out;
1451 }
1452
1453 static gboolean
1454 marshal_variant (DBusMessageIter          *iter,
1455                  const GValue             *value)
1456 {
1457   GType value_gtype;
1458   DBusMessageIter subiter;
1459   char *variant_sig;
1460   GValue *real_value;
1461   gboolean ret = FALSE;
1462
1463   real_value = g_value_get_boxed (value);
1464   value_gtype = G_VALUE_TYPE (real_value);
1465
1466   variant_sig = dbus_gvalue_to_signature (real_value);
1467   if (variant_sig == NULL)
1468     {
1469       g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
1470       return FALSE;
1471     }
1472
1473   if (!dbus_message_iter_open_container (iter,
1474                                          DBUS_TYPE_VARIANT,
1475                                          variant_sig,
1476                                          &subiter))
1477     goto out;
1478
1479   if (!marshal_basic (&subiter, real_value))
1480     goto out;
1481
1482   if (!dbus_message_iter_close_container (iter, &subiter))
1483     goto out;
1484
1485   ret = TRUE;
1486  out:
1487   g_free (variant_sig);
1488   return ret;
1489 }
1490
1491 static DBusGValueMarshalFunc
1492 get_type_marshaller (GType type)
1493 {
1494   DBusGTypeMarshalData *typedata;
1495
1496   typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
1497   if (typedata == NULL)
1498     {
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))
1504         return marshal_map;
1505
1506       g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
1507       return NULL;
1508     }
1509   g_assert (typedata->vtable);
1510   return typedata->vtable->marshaller;
1511 }
1512
1513 typedef struct
1514 {
1515   DBusMessageIter *iter;
1516   DBusGValueMarshalFunc marshaller;
1517   gboolean err;
1518 } DBusGValueCollectionMarshalData;
1519
1520 static void
1521 collection_marshal_iterator (const GValue *eltval,
1522                              gpointer      user_data)
1523 {
1524   DBusGValueCollectionMarshalData *data = user_data;
1525
1526   if (data->err)
1527     return;
1528
1529   if (!data->marshaller (data->iter, eltval))
1530     data->err = TRUE;
1531 }
1532
1533 static gboolean
1534 marshal_collection (DBusMessageIter         *iter,
1535                     const GValue            *value)
1536 {
1537   GType coltype;
1538   GType subtype;
1539   
1540   coltype = G_VALUE_TYPE (value);
1541   subtype = dbus_g_type_get_collection_specialization (coltype);
1542
1543   if (_dbus_g_type_is_fixed (subtype))
1544     return marshal_collection_array (iter, value);
1545   else
1546     return marshal_collection_ptrarray (iter, value);
1547 }
1548
1549 static gboolean
1550 marshal_collection_ptrarray (DBusMessageIter         *iter,
1551                              const GValue            *value)
1552 {
1553   GType coltype;
1554   GType elt_gtype;
1555   DBusGValueCollectionMarshalData data;
1556   DBusMessageIter subiter;
1557   char *elt_sig;
1558   
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)
1563     return FALSE;
1564
1565   elt_sig = _dbus_gtype_to_signature (elt_gtype);
1566   if (!elt_sig)
1567     {
1568       g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
1569       return FALSE;
1570     }
1571
1572   if (!dbus_message_iter_open_container (iter,
1573                                          DBUS_TYPE_ARRAY,
1574                                          elt_sig,
1575                                          &subiter))
1576     goto oom;
1577   g_free (elt_sig);
1578
1579   data.iter = &subiter;
1580   data.err = FALSE;
1581
1582   dbus_g_type_collection_value_iterate (value,
1583                                         collection_marshal_iterator,
1584                                         &data);
1585
1586   if (!dbus_message_iter_close_container (iter, &subiter))
1587     goto oom;
1588   
1589   return !data.err;
1590  oom:
1591   g_error ("out of memory");
1592   return FALSE;
1593 }
1594
1595
1596 static gboolean
1597 marshal_collection_array (DBusMessageIter   *iter,
1598                           const GValue      *value)
1599 {
1600   GType elt_gtype;
1601   DBusMessageIter subiter;
1602   GArray *array;
1603   guint elt_size;
1604   char *subsignature_str;
1605
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)
1610     {
1611       g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
1612       return FALSE;
1613     }
1614   
1615   elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
1616
1617   array = g_value_get_boxed (value);
1618
1619   if (!dbus_message_iter_open_container (iter,
1620                                          DBUS_TYPE_ARRAY,
1621                                          subsignature_str,
1622                                          &subiter))
1623     goto oom;
1624
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...
1628    */
1629   if (!dbus_message_iter_append_fixed_array (&subiter,
1630                                              subsignature_str[0],
1631                                              &(array->data),
1632                                              array->len))
1633     goto oom;
1634
1635   if (!dbus_message_iter_close_container (iter, &subiter))
1636     goto oom;
1637   g_free (subsignature_str);
1638   return TRUE;
1639  oom:
1640   g_error ("out of memory");
1641   return FALSE;
1642 }
1643
1644 gboolean
1645 _dbus_gvalue_marshal (DBusMessageIter         *iter,
1646                      const GValue       *value)
1647 {
1648   GType gtype;
1649   DBusGValueMarshalFunc marshaller;
1650
1651   gtype = G_VALUE_TYPE (value);
1652
1653   marshaller = get_type_marshaller (gtype);
1654   if (marshaller == NULL)
1655     return FALSE;
1656   return marshaller (iter, value);
1657 }
1658
1659 #ifdef DBUS_BUILD_TESTS
1660
1661 static void
1662 assert_type_maps_to (GType gtype, const char *expected_sig)
1663 {
1664   char *sig;
1665   sig = _dbus_gtype_to_signature (gtype);
1666   g_assert (sig != NULL);
1667   g_assert (!strcmp (expected_sig, sig));
1668   g_free (sig);
1669 }
1670
1671 static void
1672 assert_signature_maps_to (const char *sig, GType expected_gtype)
1673 {
1674   g_assert (_dbus_gtype_from_signature (sig, TRUE) == expected_gtype);
1675 }
1676
1677 static void
1678 assert_bidirectional_mapping (GType gtype, const char *expected_sig)
1679 {
1680   assert_type_maps_to (gtype, expected_sig);
1681   assert_signature_maps_to (expected_sig, gtype);
1682 }
1683
1684 /**
1685  * @ingroup DBusGLibInternals
1686  * Unit test for general glib stuff
1687  * @returns #TRUE on success.
1688  */
1689 gboolean
1690 _dbus_gvalue_test (const char *test_data_dir)
1691 {
1692   _dbus_g_value_types_init ();
1693   
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);
1697
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);
1701
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);
1708
1709   return TRUE;
1710 }
1711
1712 #endif /* DBUS_BUILD_TESTS */