dbus-gvalue.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-gvalue.c GValue to-from DBusMessageIter
00003  *
00004  * Copyright (C) 2004 Ximian, Inc.
00005  * Copyright (C) 2005 Red Hat, Inc.
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "config.h"
00026 #include "dbus-gtest.h"
00027 #include "dbus-gvalue.h"
00028 #include "dbus-gsignature.h"
00029 #include "dbus-gobject.h"
00030 #include "dbus-gvalue-utils.h"
00031 #include "dbus/dbus-glib.h"
00032 #include <string.h>
00033 #include <glib.h>
00034 #include <glib/gi18n.h>
00035 #include "dbus/dbus-signature.h"
00036 
00037 static gboolean demarshal_static_variant (DBusGValueMarshalCtx    *context,
00038                                           DBusMessageIter         *iter,
00039                                           GValue                  *value,
00040                                           GError                 **error);
00041 
00042 
00043 static gboolean marshal_basic                   (DBusMessageIter           *iter,
00044                                                  const GValue              *value);
00045 static gboolean demarshal_basic                 (DBusGValueMarshalCtx      *context,
00046                                                  DBusMessageIter           *iter,
00047                                                  GValue                    *value,
00048                                                  GError                   **error);
00049 static gboolean marshal_strv                    (DBusMessageIter           *iter,
00050                                                  const GValue              *value);
00051 static gboolean demarshal_strv                  (DBusGValueMarshalCtx      *context,
00052                                                  DBusMessageIter           *iter,
00053                                                  GValue                    *value,
00054                                                  GError                   **error);
00055 static gboolean marshal_valuearray              (DBusMessageIter           *iter,
00056                                                  const GValue              *value);
00057 static gboolean demarshal_valuearray            (DBusGValueMarshalCtx      *context,
00058                                                  DBusMessageIter           *iter,
00059                                                  GValue                    *value,
00060                                                  GError                   **error);
00061 static gboolean marshal_variant                 (DBusMessageIter           *iter,
00062                                                  const GValue              *value);
00063 static gboolean demarshal_variant               (DBusGValueMarshalCtx      *context,
00064                                                  DBusMessageIter           *iter,
00065                                                  GValue                    *value,
00066                                                  GError                   **error);
00067 static gboolean marshal_proxy                   (DBusMessageIter           *iter,
00068                                                  const GValue             *value);
00069 static gboolean demarshal_proxy                 (DBusGValueMarshalCtx      *context,
00070                                                  DBusMessageIter           *iter,
00071                                                  GValue                    *value,
00072                                                  GError                   **error);
00073 static gboolean marshal_object_path             (DBusMessageIter           *iter,
00074                                                  const GValue             *value);
00075 static gboolean demarshal_object_path           (DBusGValueMarshalCtx      *context,
00076                                                  DBusMessageIter           *iter,
00077                                                  GValue                    *value,
00078                                                  GError                   **error);
00079 static gboolean marshal_object                  (DBusMessageIter           *iter,
00080                                                  const GValue              *value);
00081 static gboolean demarshal_object                (DBusGValueMarshalCtx      *context,
00082                                                  DBusMessageIter           *iter,
00083                                                  GValue                    *value,
00084                                                  GError                   **error);
00085 static gboolean marshal_map                     (DBusMessageIter           *iter,
00086                                                  const GValue              *value);
00087 static gboolean demarshal_map                   (DBusGValueMarshalCtx      *context,
00088                                                  DBusMessageIter           *iter,
00089                                                  GValue                    *value,
00090                                                  GError                   **error);
00091 
00092 static gboolean marshal_collection              (DBusMessageIter           *iter,
00093                                                  const GValue              *value);
00094 static gboolean marshal_collection_ptrarray     (DBusMessageIter           *iter,
00095                                                  const GValue              *value);
00096 static gboolean marshal_collection_array        (DBusMessageIter           *iter,
00097                                                  const GValue              *value);
00098 static gboolean demarshal_collection            (DBusGValueMarshalCtx      *context,
00099                                                  DBusMessageIter           *iter,
00100                                                  GValue                    *value,
00101                                                  GError                   **error);
00102 static gboolean demarshal_collection_ptrarray   (DBusGValueMarshalCtx      *context,
00103                                                  DBusMessageIter           *iter,
00104                                                  GValue                    *value,
00105                                                  GError                   **error);
00106 static gboolean demarshal_collection_array      (DBusGValueMarshalCtx      *context,
00107                                                  DBusMessageIter           *iter,
00108                                                  GValue                    *value,
00109                                                  GError                   **error);
00110 
00111 typedef gboolean (*DBusGValueMarshalFunc)       (DBusMessageIter           *iter,
00112                                                  const GValue              *value);
00113 typedef gboolean (*DBusGValueDemarshalFunc)     (DBusGValueMarshalCtx      *context,
00114                                                  DBusMessageIter           *iter,
00115                                                  GValue                    *value,
00116                                                  GError                   **error);
00117 
00118 typedef struct {
00119   DBusGValueMarshalFunc       marshaller;
00120   DBusGValueDemarshalFunc     demarshaller;
00121 } DBusGTypeMarshalVtable;
00122 
00123 typedef struct {
00124   const char                       *sig;
00125   const DBusGTypeMarshalVtable     *vtable;
00126 } DBusGTypeMarshalData;
00127 
00128 static GQuark
00129 dbus_g_type_metadata_data_quark ()
00130 {
00131   static GQuark quark;
00132   if (!quark)
00133     quark = g_quark_from_static_string ("DBusGTypeMetaData");
00134   
00135   return quark;
00136 }
00137 
00138 static void
00139 set_type_metadata (GType type, const DBusGTypeMarshalData *data)
00140 {
00141   g_type_set_qdata (type, dbus_g_type_metadata_data_quark (), (gpointer) data);
00142 }
00143 
00144 static void
00145 register_basic (int typecode, const DBusGTypeMarshalData *typedata)
00146 {
00147   set_type_metadata (_dbus_gtype_from_basic_typecode (typecode), typedata);
00148 }
00149 
00150 void
00151 _dbus_g_value_types_init (void)
00152 {
00153   static gboolean types_initialized;
00154 
00155   static const DBusGTypeMarshalVtable basic_vtable = {
00156     marshal_basic,
00157     demarshal_basic
00158   };
00159 
00160   if (types_initialized)
00161     return;
00162 
00163   dbus_g_type_specialized_init ();
00164   _dbus_g_type_specialized_builtins_init ();
00165 
00166   /* Register basic types */
00167   {
00168     static const DBusGTypeMarshalData typedata = {
00169       DBUS_TYPE_BOOLEAN_AS_STRING,
00170       &basic_vtable,
00171     };
00172     register_basic (DBUS_TYPE_BOOLEAN, &typedata);
00173   }
00174   {
00175     static const DBusGTypeMarshalData typedata = {
00176       DBUS_TYPE_BYTE_AS_STRING,
00177       &basic_vtable,
00178     };
00179     register_basic (DBUS_TYPE_BYTE, &typedata);
00180   }
00181   {
00182     static const DBusGTypeMarshalData typedata = {
00183       DBUS_TYPE_INT16_AS_STRING,
00184       &basic_vtable,
00185     };
00186     register_basic (DBUS_TYPE_INT16, &typedata);
00187   }
00188   {
00189     static const DBusGTypeMarshalData typedata = {
00190       DBUS_TYPE_UINT16_AS_STRING,
00191       &basic_vtable,
00192     };
00193     register_basic (DBUS_TYPE_UINT16, &typedata);
00194   }
00195   {
00196     static const DBusGTypeMarshalData typedata = {
00197       DBUS_TYPE_UINT32_AS_STRING,
00198       &basic_vtable,
00199     };
00200     register_basic (DBUS_TYPE_UINT32, &typedata);
00201   }
00202   {
00203     static const DBusGTypeMarshalData typedata = {
00204       DBUS_TYPE_INT32_AS_STRING,
00205       &basic_vtable,
00206     };
00207     register_basic (DBUS_TYPE_INT32, &typedata);
00208   }
00209   {
00210     static const DBusGTypeMarshalData typedata = {
00211       DBUS_TYPE_UINT64_AS_STRING,
00212       &basic_vtable,
00213     };
00214     register_basic (DBUS_TYPE_UINT64, &typedata);
00215   }
00216   {
00217     static const DBusGTypeMarshalData typedata = {
00218       DBUS_TYPE_INT64_AS_STRING,
00219       &basic_vtable,
00220     };
00221     register_basic (DBUS_TYPE_INT64, &typedata);
00222   }
00223   {
00224     static const DBusGTypeMarshalData typedata = {
00225       DBUS_TYPE_DOUBLE_AS_STRING,
00226       &basic_vtable,
00227     };
00228     register_basic (DBUS_TYPE_DOUBLE, &typedata);
00229   }
00230   {
00231     static const DBusGTypeMarshalData typedata = {
00232       DBUS_TYPE_STRING_AS_STRING,
00233       &basic_vtable,
00234     };
00235     register_basic (DBUS_TYPE_STRING, &typedata);
00236   }
00237   /* fundamental GTypes that don't map 1:1 with D-BUS types */
00238   {
00239     static const DBusGTypeMarshalData typedata = {
00240       DBUS_TYPE_BYTE_AS_STRING,
00241       &basic_vtable,
00242     };
00243     set_type_metadata (G_TYPE_CHAR, &typedata);
00244   }
00245   {
00246     static const DBusGTypeMarshalData typedata = {
00247       DBUS_TYPE_INT32_AS_STRING,
00248       &basic_vtable,
00249     };
00250     set_type_metadata (G_TYPE_LONG, &typedata);
00251   }
00252   {
00253     static const DBusGTypeMarshalData typedata = {
00254       DBUS_TYPE_UINT32_AS_STRING,
00255       &basic_vtable,
00256     };
00257     set_type_metadata (G_TYPE_ULONG, &typedata);
00258   }
00259   {
00260     static const DBusGTypeMarshalData typedata = {
00261       DBUS_TYPE_DOUBLE_AS_STRING,
00262       &basic_vtable,
00263     };
00264     set_type_metadata (G_TYPE_FLOAT, &typedata);
00265   }
00266 
00267   /* Register complex types with builtin GType mappings */
00268   {
00269     static const DBusGTypeMarshalVtable vtable = {
00270       marshal_variant,
00271       demarshal_variant
00272     };
00273     static const DBusGTypeMarshalData typedata = {
00274       DBUS_TYPE_VARIANT_AS_STRING,
00275       &vtable
00276     };
00277     set_type_metadata (G_TYPE_VALUE, &typedata);
00278   };
00279   {
00280     static const DBusGTypeMarshalVtable vtable = {
00281       marshal_strv,
00282       demarshal_strv
00283     };
00284     static const DBusGTypeMarshalData typedata = {
00285       DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
00286       &vtable
00287     };
00288     set_type_metadata (G_TYPE_STRV, &typedata);
00289   };
00290 
00291 
00292   /* Register some types specific to the D-BUS GLib bindings */
00293   {
00294     static const DBusGTypeMarshalVtable vtable = {
00295       marshal_proxy,
00296       demarshal_proxy
00297     };
00298     static const DBusGTypeMarshalData typedata = {
00299       DBUS_TYPE_OBJECT_PATH_AS_STRING,
00300       &vtable
00301     };
00302     set_type_metadata (DBUS_TYPE_G_PROXY, &typedata);
00303   }
00304 
00305   {
00306     static const DBusGTypeMarshalVtable vtable = {
00307       marshal_object_path,
00308       demarshal_object_path
00309     };
00310     static const DBusGTypeMarshalData typedata = {
00311       DBUS_TYPE_OBJECT_PATH_AS_STRING,
00312       &vtable
00313     };
00314     set_type_metadata (DBUS_TYPE_G_OBJECT_PATH, &typedata);
00315   }
00316 
00317   {
00318     static const DBusGTypeMarshalVtable vtable = {
00319       marshal_object,
00320       demarshal_object
00321     };
00322     static const DBusGTypeMarshalData typedata = {
00323       DBUS_TYPE_OBJECT_PATH_AS_STRING,
00324       &vtable
00325     };
00326     set_type_metadata (G_TYPE_OBJECT, &typedata);
00327   }
00328 
00329   types_initialized = TRUE;
00330 }
00331 
00337 GType
00338 dbus_g_object_path_get_g_type (void)
00339 {
00340   static GType type_id = 0;
00341 
00342   if (!type_id)
00343     type_id = g_boxed_type_register_static ("DBusGObjectPath",
00344                                             (GBoxedCopyFunc) g_strdup,
00345                                             (GBoxedFreeFunc) g_free);
00346   return type_id;
00347 }
00348 
00349 char *
00350 _dbus_gtype_to_signature (GType gtype)
00351 {
00352   char *ret;
00353   DBusGTypeMarshalData *typedata;
00354 
00355   if (dbus_g_type_is_collection (gtype))
00356     {
00357       GType elt_gtype;
00358       char *subsig;
00359 
00360       elt_gtype = dbus_g_type_get_collection_specialization (gtype);
00361       subsig = _dbus_gtype_to_signature (elt_gtype);
00362       ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING, subsig, NULL);
00363       g_free (subsig);
00364     }
00365   else if (dbus_g_type_is_map (gtype))
00366     {
00367       GType key_gtype;
00368       GType val_gtype;
00369       char *key_subsig;
00370       char *val_subsig;
00371 
00372       key_gtype = dbus_g_type_get_map_key_specialization (gtype);
00373       val_gtype = dbus_g_type_get_map_value_specialization (gtype);
00374       key_subsig = _dbus_gtype_to_signature (key_gtype);
00375       val_subsig = _dbus_gtype_to_signature (val_gtype);
00376       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);
00377       g_free (key_subsig);
00378       g_free (val_subsig);
00379     }
00380   else
00381     {
00382       typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ());
00383       if (typedata == NULL)
00384         return NULL;
00385       ret = g_strdup (typedata->sig);
00386     }
00387   
00388   return ret;
00389 }
00390 
00391 char *
00392 _dbus_gvalue_to_signature (const GValue *val)
00393 {
00394   GType gtype;
00395 
00396   gtype = G_VALUE_TYPE (val);
00397   if (g_type_is_a (gtype, G_TYPE_VALUE_ARRAY))
00398     {
00399       GString *str;
00400       guint i;
00401       GValueArray *array;
00402 
00403       array = g_value_get_boxed (val);
00404       
00405       str = g_string_new (DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
00406       for (i = 0; i < array->n_values; i++)
00407         {
00408           char *sig;
00409           sig = _dbus_gvalue_to_signature (g_value_array_get_nth (array, i));
00410           g_string_append (str, sig);
00411           g_free (sig);
00412         }
00413       g_string_append (str, DBUS_STRUCT_END_CHAR_AS_STRING);
00414       
00415       return g_string_free (str, FALSE);
00416     }
00417   else
00418     return _dbus_gtype_to_signature (gtype);
00419 }
00420 
00421 static gboolean
00422 demarshal_basic (DBusGValueMarshalCtx      *context,
00423                  DBusMessageIter           *iter,
00424                  GValue                    *value,
00425                  GError                   **error)
00426 {
00427   int current_type;
00428   
00429   current_type = dbus_message_iter_get_arg_type (iter);
00430   g_assert (dbus_type_is_basic (current_type));
00431 
00432   switch (current_type)
00433     {
00434     case DBUS_TYPE_BOOLEAN:
00435       {
00436         dbus_bool_t bool;
00437         dbus_message_iter_get_basic (iter, &bool);
00438         g_value_set_boolean (value, bool);
00439         return TRUE;
00440       }
00441     case DBUS_TYPE_BYTE:
00442       {
00443         unsigned char byte;
00444         dbus_message_iter_get_basic (iter, &byte);
00445         g_value_set_uchar (value, byte);
00446         return TRUE;
00447       }
00448     case DBUS_TYPE_INT32:
00449       {
00450         dbus_int32_t intval;
00451         dbus_message_iter_get_basic (iter, &intval);
00452         g_value_set_int (value, intval);
00453         return TRUE;
00454       }
00455     case DBUS_TYPE_UINT32:
00456       {
00457         dbus_uint32_t intval;
00458         dbus_message_iter_get_basic (iter, &intval);
00459         g_value_set_uint (value, intval);
00460         return TRUE;
00461       }
00462     case DBUS_TYPE_INT64:
00463       {
00464         dbus_int64_t intval;
00465         dbus_message_iter_get_basic (iter, &intval);
00466         g_value_set_int64 (value, intval);
00467         return TRUE;
00468       }
00469     case DBUS_TYPE_UINT64:
00470       {
00471         dbus_uint64_t intval;
00472         dbus_message_iter_get_basic (iter, &intval);
00473         g_value_set_uint64 (value, intval);
00474         return TRUE;
00475       }
00476     case DBUS_TYPE_DOUBLE:
00477       {
00478         double dval;
00479         dbus_message_iter_get_basic (iter, &dval);
00480         g_value_set_double (value, dval);
00481         return TRUE;
00482       }
00483     case DBUS_TYPE_INT16:
00484       {
00485         dbus_int16_t v;
00486         dbus_message_iter_get_basic (iter, &v);
00487         g_value_set_int (value, v);
00488         return TRUE;
00489       }
00490     case DBUS_TYPE_UINT16:
00491       {
00492         dbus_uint16_t v;
00493         dbus_message_iter_get_basic (iter, &v);
00494         g_value_set_uint (value, v);
00495         return TRUE;
00496       }
00497     case DBUS_TYPE_STRING:
00498       {
00499         const char *s;
00500         dbus_message_iter_get_basic (iter, &s);
00501         g_value_set_string (value, s);
00502         return TRUE;
00503       }
00504     default:
00505       g_assert_not_reached ();
00506       return FALSE;
00507     }
00508 }
00509 
00510 static gboolean
00511 demarshal_static_variant (DBusGValueMarshalCtx    *context,
00512                           DBusMessageIter         *iter,
00513                           GValue                  *value,
00514                           GError                 **error)
00515 {
00516   char *sig;
00517   int current_type;
00518   DBusMessageIter subiter;
00519   GType variant_type;
00520 
00521   current_type = dbus_message_iter_get_arg_type (iter);
00522   dbus_message_iter_recurse (iter, &subiter);
00523   sig = dbus_message_iter_get_signature (&subiter);
00524 
00525   variant_type = _dbus_gtype_from_signature (sig, context->proxy != NULL);
00526   if (variant_type != G_TYPE_INVALID)
00527     {
00528       g_value_init (value, variant_type);
00529 
00530       if (!_dbus_gvalue_demarshal (context, &subiter, value, error))
00531         {
00532           dbus_free (sig);
00533           return FALSE;
00534         }
00535     }
00536   dbus_free (sig);
00537   return TRUE;
00538 }
00539 
00540 static gboolean
00541 demarshal_variant (DBusGValueMarshalCtx    *context,
00542                    DBusMessageIter         *iter,
00543                    GValue                  *value,
00544                    GError                 **error)
00545 
00546 {
00547   GValue *variant_val;
00548   variant_val = g_new0 (GValue, 1);
00549 
00550   if (!demarshal_static_variant (context, iter, variant_val, error))
00551     return FALSE;
00552   
00553   g_value_set_boxed_take_ownership (value, variant_val);
00554   return TRUE;
00555 }
00556 
00557 static gboolean
00558 demarshal_proxy (DBusGValueMarshalCtx    *context,
00559                  DBusMessageIter         *iter,
00560                  GValue                  *value,
00561                  GError                 **error)
00562 {
00563   DBusGProxy *new_proxy;
00564   const char *objpath;
00565   int current_type;
00566 
00567   current_type = dbus_message_iter_get_arg_type (iter);
00568   if (current_type != DBUS_TYPE_OBJECT_PATH)
00569     {
00570       g_set_error (error,
00571                    DBUS_GERROR,
00572                    DBUS_GERROR_INVALID_ARGS,
00573                    _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
00574       return FALSE;
00575     }
00576 
00577   g_assert (context->proxy != NULL);
00578   
00579   dbus_message_iter_get_basic (iter, &objpath);
00580 
00581   new_proxy = dbus_g_proxy_new_from_proxy (context->proxy, NULL, objpath);
00582   g_value_set_object_take_ownership (value, new_proxy);
00583 
00584   return TRUE;
00585 }
00586 
00587 static gboolean
00588 demarshal_object_path (DBusGValueMarshalCtx    *context,
00589                        DBusMessageIter         *iter,
00590                        GValue                  *value,
00591                        GError                 **error)
00592 {
00593   const char *objpath;
00594   int current_type;
00595 
00596   current_type = dbus_message_iter_get_arg_type (iter);
00597   if (current_type != DBUS_TYPE_OBJECT_PATH)
00598     {
00599       g_set_error (error,
00600                    DBUS_GERROR,
00601                    DBUS_GERROR_INVALID_ARGS,
00602                    _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
00603       return FALSE;
00604     }
00605 
00606   dbus_message_iter_get_basic (iter, &objpath);
00607 
00608   g_value_set_boxed_take_ownership (value, g_strdup (objpath));
00609 
00610   return TRUE;
00611 }
00612 
00613 static gboolean
00614 demarshal_object (DBusGValueMarshalCtx    *context,
00615                   DBusMessageIter         *iter,
00616                   GValue                  *value,
00617                   GError                 **error)
00618 {
00619   const char *objpath;
00620   int current_type;
00621   GObject *obj;
00622 
00623   current_type = dbus_message_iter_get_arg_type (iter);
00624   if (current_type != DBUS_TYPE_OBJECT_PATH)
00625     {
00626       g_set_error (error,
00627                    DBUS_GERROR,
00628                    DBUS_GERROR_INVALID_ARGS,
00629                    _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
00630       return FALSE;
00631     }
00632   g_assert (context->proxy == NULL);
00633 
00634   dbus_message_iter_get_basic (iter, &objpath);
00635 
00636   obj = dbus_g_connection_lookup_g_object (context->gconnection, objpath);
00637   if (obj == NULL)
00638     {
00639       g_set_error (error,
00640                    DBUS_GERROR,
00641                    DBUS_GERROR_INVALID_ARGS,
00642                    _("Unregistered object at path '%s'"),
00643                    objpath);
00644       return FALSE;
00645     }
00646   g_value_set_object (value, obj);
00647 
00648   return TRUE;
00649 }
00650 
00651 static gboolean
00652 demarshal_strv (DBusGValueMarshalCtx    *context,
00653                 DBusMessageIter         *iter,
00654                 GValue                  *value,
00655                 GError                 **error)
00656 {
00657   DBusMessageIter subiter;
00658   int current_type;
00659   char **ret;
00660   int len;
00661   int i;
00662 
00663   current_type = dbus_message_iter_get_arg_type (iter);
00664   if (current_type != DBUS_TYPE_ARRAY)
00665     {
00666       g_set_error (error,
00667                    DBUS_GERROR,
00668                    DBUS_GERROR_INVALID_ARGS,
00669                    _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
00670       return FALSE;
00671     }
00672 
00673   dbus_message_iter_recurse (iter, &subiter);
00674 
00675   current_type = dbus_message_iter_get_arg_type (&subiter);
00676   if (current_type != DBUS_TYPE_INVALID
00677       && current_type != DBUS_TYPE_STRING)
00678     {
00679       g_set_error (error,
00680                    DBUS_GERROR,
00681                    DBUS_GERROR_INVALID_ARGS,
00682                    _("Expected D-BUS string, got type code \'%c\'"), (guchar) current_type);
00683       return FALSE;
00684     }
00685 
00686   len = dbus_message_iter_get_array_len (&subiter);
00687   g_assert (len >= 0);
00688   ret = g_malloc (sizeof (char *) * (len + 1));
00689   
00690   i = 0;
00691   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00692     {
00693       g_assert (i < len);
00694       g_assert (current_type == DBUS_TYPE_STRING);
00695       
00696       dbus_message_iter_get_basic (&subiter, &(ret[i]));
00697       ret[i] = g_strdup (ret[i]);
00698 
00699       dbus_message_iter_next (&subiter);
00700       i++;
00701     }
00702   ret[i] = NULL; 
00703   g_value_set_boxed_take_ownership (value, ret);
00704   
00705   return TRUE;
00706 }
00707 
00708 static gboolean
00709 demarshal_valuearray (DBusGValueMarshalCtx    *context,
00710                       DBusMessageIter         *iter,
00711                       GValue                  *value,
00712                       GError                 **error)
00713 {
00714   int current_type;
00715   GValueArray *ret;
00716   DBusMessageIter subiter;
00717 
00718   current_type = dbus_message_iter_get_arg_type (iter);
00719   if (current_type != DBUS_TYPE_STRUCT)
00720     {
00721       g_set_error (error,
00722                    DBUS_GERROR,
00723                    DBUS_GERROR_INVALID_ARGS,
00724                    _("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type);
00725       return FALSE;
00726     }
00727 
00728   dbus_message_iter_recurse (iter, &subiter);
00729 
00730   ret = g_value_array_new (12);
00731 
00732   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00733     {
00734       GValue *val;
00735       GType elt_type; 
00736       char *current_sig;
00737 
00738       g_value_array_append (ret, NULL);
00739       val = g_value_array_get_nth (ret, ret->n_values - 1);
00740 
00741       current_sig = dbus_message_iter_get_signature (&subiter);
00742       elt_type = _dbus_gtype_from_signature (current_sig, TRUE);
00743 
00744       g_free (current_sig);
00745       if (elt_type == G_TYPE_INVALID)
00746         {
00747           g_value_array_free (ret);
00748           g_set_error (error,
00749                        DBUS_GERROR,
00750                        DBUS_GERROR_INVALID_ARGS,
00751                        _("Couldn't demarshal argument with signature \"%s\""), current_sig);
00752           return FALSE;
00753         }
00754       
00755       g_value_init (val, elt_type);
00756 
00757       if (!_dbus_gvalue_demarshal (context, &subiter, val, error))
00758         {
00759           g_value_array_free (ret);
00760           return FALSE;
00761         }
00762 
00763       dbus_message_iter_next (&subiter);
00764     }
00765 
00766   g_value_set_boxed_take_ownership (value, ret);
00767   
00768   return TRUE;
00769 }
00770 
00771 static gboolean
00772 demarshal_map (DBusGValueMarshalCtx    *context,
00773                DBusMessageIter         *iter,
00774                GValue                  *value,
00775                GError                 **error)
00776 {
00777   GType gtype;
00778   DBusMessageIter subiter;
00779   int current_type;
00780   gpointer ret;
00781   GType key_gtype;
00782   GType value_gtype;
00783   DBusGTypeSpecializedAppendContext appendctx;
00784 
00785   current_type = dbus_message_iter_get_arg_type (iter);
00786   if (current_type != DBUS_TYPE_ARRAY)
00787     {
00788       g_set_error (error,
00789                    DBUS_GERROR,
00790                    DBUS_GERROR_INVALID_ARGS,
00791                    _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
00792       return FALSE;
00793     }
00794 
00795   gtype = G_VALUE_TYPE (value);
00796 
00797   dbus_message_iter_recurse (iter, &subiter);
00798 
00799   current_type = dbus_message_iter_get_arg_type (&subiter);
00800   if (current_type != DBUS_TYPE_INVALID
00801       && current_type != DBUS_TYPE_DICT_ENTRY)
00802     {
00803       g_set_error (error,
00804                    DBUS_GERROR,
00805                    DBUS_GERROR_INVALID_ARGS,
00806                    _("Expected D-BUS dict entry, got type code \'%c\'"), (guchar) current_type);
00807       return FALSE;
00808     }
00809 
00810   key_gtype = dbus_g_type_get_map_key_specialization (gtype);
00811   value_gtype = dbus_g_type_get_map_value_specialization (gtype);
00812 
00813   ret = dbus_g_type_specialized_construct (gtype);
00814   g_value_set_boxed_take_ownership (value, ret);
00815 
00816   dbus_g_type_specialized_init_append (value, &appendctx);
00817 
00818   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00819     {
00820       DBusMessageIter entry_iter;
00821       GValue key_value = {0,};
00822       GValue value_value = {0,};
00823 
00824       current_type = dbus_message_iter_get_arg_type (&subiter);
00825       g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
00826 
00827       dbus_message_iter_recurse (&subiter, &entry_iter);
00828 
00829       g_value_init (&key_value, key_gtype);
00830       if (!_dbus_gvalue_demarshal (context,
00831                                   &entry_iter,
00832                                   &key_value,
00833                                   error))
00834         return FALSE;
00835 
00836       dbus_message_iter_next (&entry_iter);
00837 
00838       g_value_init (&value_value, value_gtype);
00839       if (!_dbus_gvalue_demarshal (context,
00840                                   &entry_iter,
00841                                   &value_value,
00842                                   error))
00843         return FALSE;
00844 
00845       dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
00846       /* Ownership of values passes to map, don't unset */
00847 
00848       dbus_message_iter_next (&subiter);
00849     }
00850   
00851   return TRUE;
00852 }
00853 
00854 static DBusGValueDemarshalFunc
00855 get_type_demarshaller (GType type)
00856 {
00857   DBusGTypeMarshalData *typedata;
00858 
00859   typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
00860   if (typedata == NULL)
00861     {
00862       if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
00863         return demarshal_valuearray;
00864       if (dbus_g_type_is_collection (type))
00865         return demarshal_collection;
00866       if (dbus_g_type_is_map (type))
00867         return demarshal_map;
00868 
00869       g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
00870       return NULL;
00871     }
00872   g_assert (typedata->vtable);
00873   return typedata->vtable->demarshaller;
00874 }
00875 
00876 static gboolean
00877 demarshal_collection (DBusGValueMarshalCtx    *context,
00878                       DBusMessageIter         *iter,
00879                       GValue                  *value,
00880                       GError                 **error)
00881 {
00882   GType coltype;
00883   GType subtype;
00884   
00885   coltype = G_VALUE_TYPE (value);
00886   subtype = dbus_g_type_get_collection_specialization (coltype);
00887 
00888   if (_dbus_g_type_is_fixed (subtype))
00889     return demarshal_collection_array (context, iter, value, error);
00890   else
00891     return demarshal_collection_ptrarray (context, iter, value, error);
00892 }
00893 
00894 static gboolean
00895 demarshal_collection_ptrarray (DBusGValueMarshalCtx    *context,
00896                                DBusMessageIter         *iter,
00897                                GValue                  *value,
00898                                GError                 **error)
00899 {
00900   GType coltype;
00901   GType subtype;
00902   gpointer instance;
00903   DBusGTypeSpecializedAppendContext ctx;
00904   DBusGValueDemarshalFunc demarshaller;
00905   DBusMessageIter subiter;
00906   int current_type;
00907 
00908   current_type = dbus_message_iter_get_arg_type (iter);
00909 
00910   if (current_type != DBUS_TYPE_ARRAY)
00911     {
00912       g_set_error (error,
00913                    DBUS_GERROR,
00914                    DBUS_GERROR_INVALID_ARGS,
00915                    _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
00916       return FALSE;
00917     }
00918 
00919   dbus_message_iter_recurse (iter, &subiter);
00920   
00921   coltype = G_VALUE_TYPE (value);
00922   subtype = dbus_g_type_get_collection_specialization (coltype);
00923 
00924   demarshaller = get_type_demarshaller (subtype);
00925 
00926   if (!demarshaller)
00927     {
00928       g_set_error (error,
00929                    DBUS_GERROR,
00930                    DBUS_GERROR_INVALID_ARGS,
00931                    _("No demarshaller registered for type \"%s\" of collection \"%s\""),
00932                    g_type_name (coltype),
00933                    g_type_name (subtype));
00934       return FALSE;
00935     }
00936 
00937   instance = dbus_g_type_specialized_construct (coltype);
00938   g_value_set_boxed_take_ownership (value, instance);
00939 
00940   dbus_g_type_specialized_init_append (value, &ctx);
00941 
00942   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00943     {
00944       GValue eltval = {0, };
00945 
00946       g_value_init (&eltval, subtype);
00947 
00948       if (!demarshaller (context, &subiter, &eltval, error))
00949         {
00950           dbus_g_type_specialized_collection_end_append (&ctx);
00951           g_value_unset (value);
00952           return FALSE;
00953         }
00954       dbus_g_type_specialized_collection_append (&ctx, &eltval);
00955       
00956       dbus_message_iter_next (&subiter);
00957     }
00958   dbus_g_type_specialized_collection_end_append (&ctx);
00959   
00960   return TRUE;
00961 }
00962 
00963 static gboolean
00964 demarshal_collection_array (DBusGValueMarshalCtx    *context,
00965                             DBusMessageIter         *iter,
00966                             GValue                  *value,
00967                             GError                 **error)
00968 {
00969   DBusMessageIter subiter;
00970   GArray *ret;
00971   GType elt_gtype;
00972   int elt_size;
00973   void *msgarray;
00974   int msgarray_len;
00975 
00976   dbus_message_iter_recurse (iter, &subiter);
00977 
00978   elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
00979   g_assert (elt_gtype != G_TYPE_INVALID);
00980   g_assert (_dbus_g_type_is_fixed (elt_gtype));
00981 
00982   elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
00983   
00984   ret = g_array_new (FALSE, TRUE, elt_size);
00985 
00986   msgarray = NULL;
00987   dbus_message_iter_get_fixed_array (&subiter,
00988                                      &msgarray,
00989                                      &msgarray_len);
00990   g_assert (msgarray != NULL);
00991   g_assert (msgarray_len >= 0);
00992   g_array_append_vals (ret, msgarray, (guint) msgarray_len);
00993 
00994   g_value_set_boxed_take_ownership (value, ret);
00995   
00996   return TRUE;
00997 }
00998 
00999 gboolean
01000 _dbus_gvalue_demarshal (DBusGValueMarshalCtx    *context,
01001                        DBusMessageIter         *iter,
01002                        GValue                  *value,
01003                        GError                 **error)
01004 {
01005   GType gtype;
01006   DBusGValueDemarshalFunc demarshaller;
01007 
01008   gtype = G_VALUE_TYPE (value);
01009 
01010   demarshaller = get_type_demarshaller (gtype);
01011 
01012   if (demarshaller == NULL)
01013     {
01014       g_set_error (error,
01015                    DBUS_GERROR,
01016                    DBUS_GERROR_INVALID_ARGS,
01017                    _("No demarshaller registered for type \"%s\""),
01018                    g_type_name (gtype));
01019       return FALSE;
01020     }
01021   
01022   return demarshaller (context, iter, value, error);
01023 }
01024 
01025 gboolean
01026 _dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx    *context,
01027                                DBusMessageIter         *iter,
01028                                GValue                  *value,
01029                                GError                 **error)
01030 {
01031   return demarshal_static_variant (context, iter, value, error);
01032 }
01033 
01034 GValueArray *
01035 _dbus_gvalue_demarshal_message  (DBusGValueMarshalCtx    *context,
01036                                 DBusMessage             *message,
01037                                 guint                    n_types,
01038                                 const GType             *types,
01039                                 GError                 **error)
01040 {
01041   GValueArray *ret;
01042   DBusMessageIter iter;
01043   int current_type;
01044   guint index;
01045   
01046   ret = g_value_array_new (6);  /* 6 is a typical maximum for arguments */
01047 
01048   dbus_message_iter_init (message, &iter);
01049   index = 0;
01050   while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
01051     {
01052       GValue *value;
01053       GType gtype;
01054 
01055       if (index >= n_types)
01056         {
01057           g_set_error (error, DBUS_GERROR,
01058                        DBUS_GERROR_INVALID_ARGS,
01059                        _("Too many arguments in message"));
01060           goto lose;
01061         }
01062       
01063       g_value_array_append (ret, NULL);
01064       value = g_value_array_get_nth (ret, index);
01065 
01066       gtype = types[index]; 
01067       g_value_init (value, gtype);
01068 
01069       if (!_dbus_gvalue_demarshal (context, &iter, value, error))
01070         goto lose;
01071       dbus_message_iter_next (&iter);
01072       index++;
01073     }
01074   if (index < n_types)
01075     {
01076       g_set_error (error, DBUS_GERROR,
01077                    DBUS_GERROR_INVALID_ARGS,
01078                    _("Too few arguments in message"));
01079       goto lose;
01080     }
01081 
01082   return ret;
01083  lose:
01084   g_value_array_free (ret);
01085   return NULL;
01086 }
01087 
01088 static gboolean
01089 marshal_basic (DBusMessageIter *iter, const GValue *value)
01090 {
01091   GType value_type;
01092 
01093   value_type = G_VALUE_TYPE (value);
01094   
01095   switch (value_type)
01096     {
01097     case G_TYPE_CHAR:
01098       {
01099         char b = g_value_get_char (value);
01100         if (!dbus_message_iter_append_basic (iter,
01101                                              DBUS_TYPE_BYTE,
01102                                              &b))
01103           goto nomem;
01104       }
01105       return TRUE;
01106     case G_TYPE_UCHAR:
01107       {
01108         unsigned char b = g_value_get_uchar (value);
01109         if (!dbus_message_iter_append_basic (iter,
01110                                              DBUS_TYPE_BYTE,
01111                                              &b))
01112           goto nomem;
01113       }
01114       return TRUE;
01115     case G_TYPE_BOOLEAN:
01116       {
01117         dbus_bool_t b = g_value_get_boolean (value);
01118         if (!dbus_message_iter_append_basic (iter,
01119                                              DBUS_TYPE_BOOLEAN,
01120                                              &b))
01121           goto nomem;
01122       }
01123       return TRUE;
01124     case G_TYPE_INT:
01125       {
01126         dbus_int32_t v = g_value_get_int (value);
01127         if (!dbus_message_iter_append_basic (iter,
01128                                              DBUS_TYPE_INT32,
01129                                              &v))
01130           goto nomem;
01131       }
01132       return TRUE;
01133     case G_TYPE_UINT:
01134       {
01135         dbus_uint32_t v = g_value_get_uint (value);
01136         if (!dbus_message_iter_append_basic (iter,
01137                                              DBUS_TYPE_UINT32,
01138                                              &v))
01139           goto nomem;
01140       }
01141       return TRUE;
01142     case G_TYPE_LONG:
01143       {
01144         dbus_int32_t v = g_value_get_long (value);
01145         if (!dbus_message_iter_append_basic (iter,
01146                                              DBUS_TYPE_INT32,
01147                                              &v))
01148           goto nomem;
01149       }
01150       return TRUE;
01151     case G_TYPE_ULONG:
01152       {
01153         dbus_uint32_t v = g_value_get_ulong (value);
01154         if (!dbus_message_iter_append_basic (iter,
01155                                              DBUS_TYPE_UINT32,
01156                                              &v))
01157           goto nomem;
01158       }
01159       return TRUE;
01160     case G_TYPE_INT64:
01161       {
01162         gint64 v = g_value_get_int64 (value);
01163         if (!dbus_message_iter_append_basic (iter,
01164                                              DBUS_TYPE_INT64,
01165                                              &v))
01166           goto nomem;
01167       }
01168       return TRUE;
01169     case G_TYPE_UINT64:
01170       {
01171         guint64 v = g_value_get_uint64 (value);
01172         if (!dbus_message_iter_append_basic (iter,
01173                                              DBUS_TYPE_UINT64,
01174                                              &v))
01175           goto nomem;
01176       }
01177       return TRUE;
01178     case G_TYPE_FLOAT:
01179       {
01180         double v = g_value_get_float (value);
01181         
01182         if (!dbus_message_iter_append_basic (iter,
01183                                              DBUS_TYPE_DOUBLE,
01184                                              &v))
01185           goto nomem;
01186       }
01187       return TRUE;
01188     case G_TYPE_DOUBLE:
01189       {
01190         double v = g_value_get_double (value);
01191         
01192         if (!dbus_message_iter_append_basic (iter,
01193                                              DBUS_TYPE_DOUBLE,
01194                                              &v))
01195           goto nomem;
01196       }
01197       return TRUE;
01198     case G_TYPE_STRING:
01199       /* FIXME, the GValue string may not be valid UTF-8 */
01200       {
01201         const char *v = g_value_get_string (value);
01202         if (!v)
01203           v = "";
01204         if (!dbus_message_iter_append_basic (iter,
01205                                              DBUS_TYPE_STRING,
01206                                              &v))
01207           goto nomem;
01208       }
01209       return TRUE;
01210       
01211     default:
01212       {
01213         g_assert_not_reached ();
01214         return FALSE;
01215       }
01216     }
01217 
01218  nomem:
01219   g_error ("no memory");
01220   return FALSE;
01221 }
01222 
01223 static gboolean
01224 marshal_strv (DBusMessageIter   *iter,
01225               const GValue       *value)
01226 {
01227   DBusMessageIter subiter;
01228   char **array;
01229   char **elt;
01230   gboolean ret = FALSE;
01231 
01232   g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
01233 
01234   array = g_value_get_boxed (value);
01235 
01236   if (!dbus_message_iter_open_container (iter,
01237                                          DBUS_TYPE_ARRAY,
01238                                          "s",
01239                                          &subiter))
01240     goto out;
01241 
01242   for (elt = array; *elt; elt++)
01243     {
01244       if (!dbus_message_iter_append_basic (&subiter,
01245                                            DBUS_TYPE_STRING,
01246                                            elt))
01247         goto out;
01248     }
01249 
01250   if (!dbus_message_iter_close_container (iter, &subiter))
01251     goto out;
01252   ret = TRUE;
01253  out:
01254   return ret;
01255 }
01256 
01257 static gboolean
01258 marshal_valuearray (DBusMessageIter   *iter,
01259                     const GValue       *value)
01260 {
01261   GValueArray *array;
01262   guint i;
01263   DBusMessageIter subiter;
01264 
01265   g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
01266 
01267   array = g_value_get_boxed (value);
01268 
01269   if (!dbus_message_iter_open_container (iter,
01270                                          DBUS_TYPE_STRUCT,
01271                                          NULL,
01272                                          &subiter))
01273     goto oom;
01274 
01275   for (i = 0; i < array->n_values; i++)
01276     {
01277       if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
01278         return FALSE;
01279     }
01280 
01281   if (!dbus_message_iter_close_container (iter, &subiter))
01282     goto oom;
01283 
01284   return TRUE;
01285  oom:
01286   g_error ("out of memory");
01287   return FALSE;
01288 }
01289 
01290 static gboolean
01291 marshal_proxy (DBusMessageIter         *iter,
01292                const GValue            *value)
01293 {
01294   const char *path;
01295   DBusGProxy *proxy;
01296 
01297   g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
01298 
01299   proxy = g_value_get_object (value);
01300   path = dbus_g_proxy_get_path (proxy);
01301   
01302   if (!dbus_message_iter_append_basic (iter,
01303                                        DBUS_TYPE_OBJECT_PATH,
01304                                        &path))
01305     return FALSE;
01306   return TRUE;
01307 }
01308 
01309 static gboolean
01310 marshal_object_path (DBusMessageIter         *iter,
01311                      const GValue            *value)
01312 {
01313   const char *path;
01314 
01315   g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
01316 
01317   path = (const char*) g_value_get_boxed (value);
01318   
01319   if (!dbus_message_iter_append_basic (iter,
01320                                        DBUS_TYPE_OBJECT_PATH,
01321                                        &path))
01322     return FALSE;
01323   return TRUE;
01324 }
01325 
01326 static gboolean
01327 marshal_object (DBusMessageIter         *iter,
01328                 const GValue            *value)
01329 {
01330   const char *path;
01331   GObject *obj;
01332 
01333   obj = g_value_get_object (value);
01334   path = _dbus_gobject_get_path (obj);
01335 
01336   if (path == NULL)
01337     /* FIXME should throw error */
01338     return FALSE;
01339   
01340   if (!dbus_message_iter_append_basic (iter,
01341                                        DBUS_TYPE_OBJECT_PATH,
01342                                        &path))
01343     return FALSE;
01344   return TRUE;
01345 }
01346 
01347 struct DBusGLibHashMarshalData
01348 {
01349   const char *entry_sig;
01350   DBusMessageIter *iter;
01351   gboolean err;
01352 };
01353 
01354 static void
01355 marshal_map_entry (const GValue *key,
01356                    const GValue *value,
01357                    gpointer data)
01358 {
01359   struct DBusGLibHashMarshalData *hashdata = data;
01360   DBusMessageIter subiter;
01361 
01362   if (hashdata->err)
01363     return;
01364 
01365   if (!dbus_message_iter_open_container (hashdata->iter,
01366                                          DBUS_TYPE_DICT_ENTRY,
01367                                          NULL,
01368                                          &subiter))
01369     goto lose;
01370 
01371   if (!_dbus_gvalue_marshal (&subiter, key))
01372     goto lose;
01373 
01374   if (!_dbus_gvalue_marshal (&subiter, value))
01375     goto lose;
01376 
01377   if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
01378     goto lose;
01379   
01380   return;
01381  lose:
01382   hashdata->err = TRUE;
01383 }
01384 
01385 static gboolean
01386 marshal_map (DBusMessageIter   *iter,
01387              const GValue      *value)
01388 {
01389   GType gtype;
01390   DBusMessageIter arr_iter;
01391   gboolean ret;
01392   struct DBusGLibHashMarshalData hashdata;
01393   char *key_sig;
01394   char *value_sig;
01395   GType key_type;
01396   GType value_type;
01397   char *entry_sig;
01398   char *array_sig;
01399 
01400   gtype = G_VALUE_TYPE (value);
01401 
01402   ret = FALSE;
01403 
01404   key_type = dbus_g_type_get_map_key_specialization (gtype);
01405   g_assert (_dbus_gtype_is_valid_hash_key (key_type));
01406   value_type = dbus_g_type_get_map_value_specialization (gtype);
01407   g_assert (_dbus_gtype_is_valid_hash_value (value_type));
01408 
01409   key_sig = _dbus_gtype_to_signature (key_type);
01410   if (!key_sig)
01411     {
01412       g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
01413       return FALSE;
01414     }
01415   value_sig = _dbus_gtype_to_signature (value_type);
01416   if (!value_sig)
01417     {
01418       g_free (key_sig);
01419       g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
01420       return FALSE;
01421     }
01422   entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
01423   g_free (key_sig);
01424   g_free (value_sig);
01425   array_sig = g_strdup_printf ("%c%s%c",
01426                                DBUS_DICT_ENTRY_BEGIN_CHAR,
01427                                entry_sig,
01428                                DBUS_DICT_ENTRY_END_CHAR);
01429   if (!dbus_message_iter_open_container (iter,
01430                                          DBUS_TYPE_ARRAY,
01431                                          array_sig,
01432                                          &arr_iter))
01433     goto lose;
01434 
01435   hashdata.iter = &arr_iter;
01436   hashdata.err = FALSE;
01437   hashdata.entry_sig = entry_sig;
01438 
01439   dbus_g_type_map_value_iterate (value,
01440                                  marshal_map_entry,
01441                                  &hashdata);
01442 
01443   if (!dbus_message_iter_close_container (iter, &arr_iter))
01444     goto lose;
01445 
01446  out:
01447   g_free (entry_sig);
01448   g_free (array_sig);
01449   return !hashdata.err;
01450  lose:
01451   hashdata.err = TRUE;
01452   goto out;
01453 }
01454 
01455 static gboolean
01456 marshal_variant (DBusMessageIter          *iter,
01457                  const GValue             *value)
01458 {
01459   GType value_gtype;
01460   DBusMessageIter subiter;
01461   char *variant_sig;
01462   GValue *real_value;
01463   gboolean ret = FALSE;
01464 
01465   real_value = g_value_get_boxed (value);
01466   value_gtype = G_VALUE_TYPE (real_value);
01467 
01468   variant_sig = _dbus_gvalue_to_signature (real_value);
01469   if (variant_sig == NULL)
01470     {
01471       g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
01472       return FALSE;
01473     }
01474 
01475   if (!dbus_message_iter_open_container (iter,
01476                                          DBUS_TYPE_VARIANT,
01477                                          variant_sig,
01478                                          &subiter))
01479     goto out;
01480 
01481   if (!_dbus_gvalue_marshal (&subiter, real_value))
01482     goto out;
01483 
01484   if (!dbus_message_iter_close_container (iter, &subiter))
01485     goto out;
01486 
01487   ret = TRUE;
01488  out:
01489   g_free (variant_sig);
01490   return ret;
01491 }
01492 
01493 static DBusGValueMarshalFunc
01494 get_type_marshaller (GType type)
01495 {
01496   DBusGTypeMarshalData *typedata;
01497 
01498   typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
01499   if (typedata == NULL)
01500     {
01501       if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
01502         return marshal_valuearray;
01503       if (dbus_g_type_is_collection (type))
01504         return marshal_collection;
01505       if (dbus_g_type_is_map (type))
01506         return marshal_map;
01507 
01508       g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
01509       return NULL;
01510     }
01511   g_assert (typedata->vtable);
01512   return typedata->vtable->marshaller;
01513 }
01514 
01515 typedef struct
01516 {
01517   DBusMessageIter *iter;
01518   DBusGValueMarshalFunc marshaller;
01519   gboolean err;
01520 } DBusGValueCollectionMarshalData;
01521 
01522 static void
01523 collection_marshal_iterator (const GValue *eltval,
01524                              gpointer      user_data)
01525 {
01526   DBusGValueCollectionMarshalData *data = user_data;
01527 
01528   if (data->err)
01529     return;
01530 
01531   if (!data->marshaller (data->iter, eltval))
01532     data->err = TRUE;
01533 }
01534 
01535 static gboolean
01536 marshal_collection (DBusMessageIter         *iter,
01537                     const GValue            *value)
01538 {
01539   GType coltype;
01540   GType subtype;
01541   
01542   coltype = G_VALUE_TYPE (value);
01543   subtype = dbus_g_type_get_collection_specialization (coltype);
01544 
01545   if (_dbus_g_type_is_fixed (subtype))
01546     return marshal_collection_array (iter, value);
01547   else
01548     return marshal_collection_ptrarray (iter, value);
01549 }
01550 
01551 static gboolean
01552 marshal_collection_ptrarray (DBusMessageIter         *iter,
01553                              const GValue            *value)
01554 {
01555   GType coltype;
01556   GType elt_gtype;
01557   DBusGValueCollectionMarshalData data;
01558   DBusMessageIter subiter;
01559   char *elt_sig;
01560   
01561   coltype = G_VALUE_TYPE (value);
01562   elt_gtype = dbus_g_type_get_collection_specialization (coltype);
01563   data.marshaller = get_type_marshaller (elt_gtype);
01564   if (!data.marshaller)
01565     return FALSE;
01566 
01567   elt_sig = _dbus_gtype_to_signature (elt_gtype);
01568   if (!elt_sig)
01569     {
01570       g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
01571       return FALSE;
01572     }
01573 
01574   if (!dbus_message_iter_open_container (iter,
01575                                          DBUS_TYPE_ARRAY,
01576                                          elt_sig,
01577                                          &subiter))
01578     goto oom;
01579   g_free (elt_sig);
01580 
01581   data.iter = &subiter;
01582   data.err = FALSE;
01583 
01584   dbus_g_type_collection_value_iterate (value,
01585                                         collection_marshal_iterator,
01586                                         &data);
01587 
01588   if (!dbus_message_iter_close_container (iter, &subiter))
01589     goto oom;
01590   
01591   return !data.err;
01592  oom:
01593   g_error ("out of memory");
01594   return FALSE;
01595 }
01596 
01597 
01598 static gboolean
01599 marshal_collection_array (DBusMessageIter   *iter,
01600                           const GValue      *value)
01601 {
01602   GType elt_gtype;
01603   DBusMessageIter subiter;
01604   GArray *array;
01605   guint elt_size;
01606   char *subsignature_str;
01607 
01608   elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
01609   g_assert (_dbus_g_type_is_fixed (elt_gtype));
01610   subsignature_str = _dbus_gtype_to_signature (elt_gtype);
01611   if (!subsignature_str)
01612     {
01613       g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
01614       return FALSE;
01615     }
01616   
01617   elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
01618 
01619   array = g_value_get_boxed (value);
01620 
01621   if (!dbus_message_iter_open_container (iter,
01622                                          DBUS_TYPE_ARRAY,
01623                                          subsignature_str,
01624                                          &subiter))
01625     goto oom;
01626 
01627   /* TODO - This assumes that basic values are the same size
01628    * is this always true?  If it is we can probably avoid
01629    * a lot of the overhead in _marshal_basic_instance...
01630    */
01631   if (!dbus_message_iter_append_fixed_array (&subiter,
01632                                              subsignature_str[0],
01633                                              &(array->data),
01634                                              array->len))
01635     goto oom;
01636 
01637   if (!dbus_message_iter_close_container (iter, &subiter))
01638     goto oom;
01639   g_free (subsignature_str);
01640   return TRUE;
01641  oom:
01642   g_error ("out of memory");
01643   return FALSE;
01644 }
01645 
01646 gboolean
01647 _dbus_gvalue_marshal (DBusMessageIter         *iter,
01648                      const GValue       *value)
01649 {
01650   GType gtype;
01651   DBusGValueMarshalFunc marshaller;
01652 
01653   gtype = G_VALUE_TYPE (value);
01654 
01655   marshaller = get_type_marshaller (gtype);
01656   if (marshaller == NULL)
01657     return FALSE;
01658   return marshaller (iter, value);
01659 }
01660 
01661 #ifdef DBUS_BUILD_TESTS
01662 
01663 static void
01664 assert_type_maps_to (GType gtype, const char *expected_sig)
01665 {
01666   char *sig;
01667   sig = _dbus_gtype_to_signature (gtype);
01668   g_assert (sig != NULL);
01669   g_assert (!strcmp (expected_sig, sig));
01670   g_free (sig);
01671 }
01672 
01673 static void
01674 assert_signature_maps_to (const char *sig, GType expected_gtype)
01675 {
01676   g_assert (_dbus_gtype_from_signature (sig, TRUE) == expected_gtype);
01677 }
01678 
01679 static void
01680 assert_bidirectional_mapping (GType gtype, const char *expected_sig)
01681 {
01682   assert_type_maps_to (gtype, expected_sig);
01683   assert_signature_maps_to (expected_sig, gtype);
01684 }
01685 
01691 gboolean
01692 _dbus_gvalue_test (const char *test_data_dir)
01693 {
01694   _dbus_g_value_types_init ();
01695   
01696   assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
01697   assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
01698   assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
01699 
01700   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);
01701   assert_signature_maps_to (DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING, G_TYPE_VALUE_ARRAY);
01702   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);
01703 
01704   assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
01705                                 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);
01706   assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
01707                                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
01708   assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
01709                                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
01710 
01711   return TRUE;
01712 }
01713 
01714 #endif /* DBUS_BUILD_TESTS */

Generated on Tue Jul 7 15:13:59 2009 for D-BUS by  doxygen 1.4.6