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