Main Page | Modules | Data Structures | Directories | File List | Data Fields | Related Pages

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 static 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 ("");
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       return g_string_free (str, FALSE);
00414     }
00415   else
00416     return _dbus_gtype_to_signature (gtype);
00417 }
00418 
00419 static gboolean
00420 demarshal_basic (DBusGValueMarshalCtx      *context,
00421                  DBusMessageIter           *iter,
00422                  GValue                    *value,
00423                  GError                   **error)
00424 {
00425   int current_type;
00426   
00427   current_type = dbus_message_iter_get_arg_type (iter);
00428   g_assert (dbus_type_is_basic (current_type));
00429 
00430   switch (current_type)
00431     {
00432     case DBUS_TYPE_BOOLEAN:
00433       {
00434         dbus_bool_t bool;
00435         dbus_message_iter_get_basic (iter, &bool);
00436         g_value_set_boolean (value, bool);
00437         return TRUE;
00438       }
00439     case DBUS_TYPE_BYTE:
00440       {
00441         unsigned char byte;
00442         dbus_message_iter_get_basic (iter, &byte);
00443         g_value_set_uchar (value, byte);
00444         return TRUE;
00445       }
00446     case DBUS_TYPE_INT32:
00447       {
00448         dbus_int32_t intval;
00449         dbus_message_iter_get_basic (iter, &intval);
00450         g_value_set_int (value, intval);
00451         return TRUE;
00452       }
00453     case DBUS_TYPE_UINT32:
00454       {
00455         dbus_uint32_t intval;
00456         dbus_message_iter_get_basic (iter, &intval);
00457         g_value_set_uint (value, intval);
00458         return TRUE;
00459       }
00460     case DBUS_TYPE_INT64:
00461       {
00462         dbus_int64_t intval;
00463         dbus_message_iter_get_basic (iter, &intval);
00464         g_value_set_int64 (value, intval);
00465         return TRUE;
00466       }
00467     case DBUS_TYPE_UINT64:
00468       {
00469         dbus_uint64_t intval;
00470         dbus_message_iter_get_basic (iter, &intval);
00471         g_value_set_uint64 (value, intval);
00472         return TRUE;
00473       }
00474     case DBUS_TYPE_DOUBLE:
00475       {
00476         double dval;
00477         dbus_message_iter_get_basic (iter, &dval);
00478         g_value_set_double (value, dval);
00479         return TRUE;
00480       }
00481     case DBUS_TYPE_INT16:
00482       {
00483         dbus_int16_t v;
00484         dbus_message_iter_get_basic (iter, &v);
00485         g_value_set_int (value, v);
00486         return TRUE;
00487       }
00488     case DBUS_TYPE_UINT16:
00489       {
00490         dbus_uint16_t v;
00491         dbus_message_iter_get_basic (iter, &v);
00492         g_value_set_uint (value, v);
00493         return TRUE;
00494       }
00495     case DBUS_TYPE_STRING:
00496       {
00497         const char *s;
00498         dbus_message_iter_get_basic (iter, &s);
00499         g_value_set_string (value, s);
00500         return TRUE;
00501       }
00502     default:
00503       g_assert_not_reached ();
00504       return FALSE;
00505     }
00506 }
00507 
00508 static gboolean
00509 demarshal_static_variant (DBusGValueMarshalCtx    *context,
00510                           DBusMessageIter         *iter,
00511                           GValue                  *value,
00512                           GError                 **error)
00513 {
00514   char *sig;
00515   int current_type;
00516   DBusMessageIter subiter;
00517   GType variant_type;
00518 
00519   current_type = dbus_message_iter_get_arg_type (iter);
00520   dbus_message_iter_recurse (iter, &subiter);
00521   sig = dbus_message_iter_get_signature (&subiter);
00522 
00523   variant_type = _dbus_gtype_from_signature (sig, context->proxy != NULL);
00524   if (variant_type != G_TYPE_INVALID)
00525     {
00526       g_value_init (value, variant_type);
00527 
00528       if (!_dbus_gvalue_demarshal (context, &subiter, value, error))
00529         {
00530           dbus_free (sig);
00531           return FALSE;
00532         }
00533     }
00534   dbus_free (sig);
00535   return TRUE;
00536 }
00537 
00538 static gboolean
00539 demarshal_variant (DBusGValueMarshalCtx    *context,
00540                    DBusMessageIter         *iter,
00541                    GValue                  *value,
00542                    GError                 **error)
00543 
00544 {
00545   GValue *variant_val;
00546   variant_val = g_new0 (GValue, 1);
00547 
00548   if (!demarshal_static_variant (context, iter, variant_val, error))
00549     return FALSE;
00550   
00551   g_value_set_boxed_take_ownership (value, variant_val);
00552   return TRUE;
00553 }
00554 
00555 static gboolean
00556 demarshal_proxy (DBusGValueMarshalCtx    *context,
00557                  DBusMessageIter         *iter,
00558                  GValue                  *value,
00559                  GError                 **error)
00560 {
00561   DBusGProxy *new_proxy;
00562   const char *objpath;
00563   int current_type;
00564 
00565   current_type = dbus_message_iter_get_arg_type (iter);
00566   if (current_type != DBUS_TYPE_OBJECT_PATH)
00567     {
00568       g_set_error (error,
00569                    DBUS_GERROR,
00570                    DBUS_GERROR_INVALID_ARGS,
00571                    _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
00572       return FALSE;
00573     }
00574 
00575   g_assert (context->proxy != NULL);
00576   
00577   dbus_message_iter_get_basic (iter, &objpath);
00578 
00579   new_proxy = dbus_g_proxy_new_from_proxy (context->proxy, NULL, objpath);
00580   g_value_set_object_take_ownership (value, new_proxy);
00581 
00582   return TRUE;
00583 }
00584 
00585 static gboolean
00586 demarshal_object_path (DBusGValueMarshalCtx    *context,
00587                        DBusMessageIter         *iter,
00588                        GValue                  *value,
00589                        GError                 **error)
00590 {
00591   const char *objpath;
00592   int current_type;
00593 
00594   current_type = dbus_message_iter_get_arg_type (iter);
00595   if (current_type != DBUS_TYPE_OBJECT_PATH)
00596     {
00597       g_set_error (error,
00598                    DBUS_GERROR,
00599                    DBUS_GERROR_INVALID_ARGS,
00600                    _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
00601       return FALSE;
00602     }
00603 
00604   dbus_message_iter_get_basic (iter, &objpath);
00605 
00606   g_value_set_boxed_take_ownership (value, g_strdup (objpath));
00607 
00608   return TRUE;
00609 }
00610 
00611 static gboolean
00612 demarshal_object (DBusGValueMarshalCtx    *context,
00613                   DBusMessageIter         *iter,
00614                   GValue                  *value,
00615                   GError                 **error)
00616 {
00617   const char *objpath;
00618   int current_type;
00619   GObject *obj;
00620 
00621   current_type = dbus_message_iter_get_arg_type (iter);
00622   if (current_type != DBUS_TYPE_OBJECT_PATH)
00623     {
00624       g_set_error (error,
00625                    DBUS_GERROR,
00626                    DBUS_GERROR_INVALID_ARGS,
00627                    _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
00628       return FALSE;
00629     }
00630   g_assert (context->proxy == NULL);
00631 
00632   dbus_message_iter_get_basic (iter, &objpath);
00633 
00634   obj = dbus_g_connection_lookup_g_object (context->gconnection, objpath);
00635   if (obj == NULL)
00636     {
00637       g_set_error (error,
00638                    DBUS_GERROR,
00639                    DBUS_GERROR_INVALID_ARGS,
00640                    _("Unregistered object at path '%s'"),
00641                    objpath);
00642       return FALSE;
00643     }
00644   g_value_set_object (value, obj);
00645 
00646   return TRUE;
00647 }
00648 
00649 static gboolean
00650 demarshal_strv (DBusGValueMarshalCtx    *context,
00651                 DBusMessageIter         *iter,
00652                 GValue                  *value,
00653                 GError                 **error)
00654 {
00655   DBusMessageIter subiter;
00656   int current_type;
00657   char **ret;
00658   int len;
00659   int i;
00660 
00661   current_type = dbus_message_iter_get_arg_type (iter);
00662   if (current_type != DBUS_TYPE_ARRAY)
00663     {
00664       g_set_error (error,
00665                    DBUS_GERROR,
00666                    DBUS_GERROR_INVALID_ARGS,
00667                    _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
00668       return FALSE;
00669     }
00670 
00671   dbus_message_iter_recurse (iter, &subiter);
00672 
00673   current_type = dbus_message_iter_get_arg_type (&subiter);
00674   if (current_type != DBUS_TYPE_INVALID
00675       && current_type != DBUS_TYPE_STRING)
00676     {
00677       g_set_error (error,
00678                    DBUS_GERROR,
00679                    DBUS_GERROR_INVALID_ARGS,
00680                    _("Expected D-BUS string, got type code \'%c\'"), (guchar) current_type);
00681       return FALSE;
00682     }
00683 
00684   len = dbus_message_iter_get_array_len (&subiter);
00685   g_assert (len >= 0);
00686   ret = g_malloc (sizeof (char *) * (len + 1));
00687   
00688   i = 0;
00689   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00690     {
00691       g_assert (i < len);
00692       g_assert (current_type == DBUS_TYPE_STRING);
00693       
00694       dbus_message_iter_get_basic (&subiter, &(ret[i]));
00695       ret[i] = g_strdup (ret[i]);
00696 
00697       dbus_message_iter_next (&subiter);
00698       i++;
00699     }
00700   ret[i] = NULL; 
00701   g_value_set_boxed_take_ownership (value, ret);
00702   
00703   return TRUE;
00704 }
00705 
00706 static gboolean
00707 demarshal_valuearray (DBusGValueMarshalCtx    *context,
00708                       DBusMessageIter         *iter,
00709                       GValue                  *value,
00710                       GError                 **error)
00711 {
00712   int current_type;
00713   GValueArray *ret;
00714   DBusMessageIter subiter;
00715 
00716   current_type = dbus_message_iter_get_arg_type (iter);
00717   if (current_type != DBUS_TYPE_STRUCT)
00718     {
00719       g_set_error (error,
00720                    DBUS_GERROR,
00721                    DBUS_GERROR_INVALID_ARGS,
00722                    _("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type);
00723       return FALSE;
00724     }
00725 
00726   dbus_message_iter_recurse (iter, &subiter);
00727 
00728   ret = g_value_array_new (12);
00729 
00730   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00731     {
00732       GValue *val;
00733       GType elt_type; 
00734       char *current_sig;
00735 
00736       g_value_array_append (ret, NULL);
00737       val = g_value_array_get_nth (ret, ret->n_values - 1);
00738 
00739       current_sig = dbus_message_iter_get_signature (&subiter);
00740       elt_type = _dbus_gtype_from_signature (current_sig, TRUE);
00741 
00742       g_free (current_sig);
00743       if (elt_type == G_TYPE_INVALID)
00744         {
00745           g_value_array_free (ret);
00746           g_set_error (error,
00747                        DBUS_GERROR,
00748                        DBUS_GERROR_INVALID_ARGS,
00749                        _("Couldn't demarshal argument with signature \"%s\""), current_sig);
00750           return FALSE;
00751         }
00752       
00753       g_value_init (val, elt_type);
00754 
00755       if (!_dbus_gvalue_demarshal (context, &subiter, val, error))
00756         {
00757           g_value_array_free (ret);
00758           return FALSE;
00759         }
00760 
00761       dbus_message_iter_next (&subiter);
00762     }
00763 
00764   g_value_set_boxed_take_ownership (value, ret);
00765   
00766   return TRUE;
00767 }
00768 
00769 static gboolean
00770 demarshal_map (DBusGValueMarshalCtx    *context,
00771                DBusMessageIter         *iter,
00772                GValue                  *value,
00773                GError                 **error)
00774 {
00775   GType gtype;
00776   DBusMessageIter subiter;
00777   int current_type;
00778   gpointer ret;
00779   GType key_gtype;
00780   GType value_gtype;
00781   DBusGTypeSpecializedAppendContext appendctx;
00782 
00783   current_type = dbus_message_iter_get_arg_type (iter);
00784   if (current_type != DBUS_TYPE_ARRAY)
00785     {
00786       g_set_error (error,
00787                    DBUS_GERROR,
00788                    DBUS_GERROR_INVALID_ARGS,
00789                    _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
00790       return FALSE;
00791     }
00792 
00793   gtype = G_VALUE_TYPE (value);
00794 
00795   dbus_message_iter_recurse (iter, &subiter);
00796 
00797   current_type = dbus_message_iter_get_arg_type (&subiter);
00798   if (current_type != DBUS_TYPE_INVALID
00799       && current_type != DBUS_TYPE_DICT_ENTRY)
00800     {
00801       g_set_error (error,
00802                    DBUS_GERROR,
00803                    DBUS_GERROR_INVALID_ARGS,
00804                    _("Expected D-BUS dict entry, got type code \'%c\'"), (guchar) current_type);
00805       return FALSE;
00806     }
00807 
00808   key_gtype = dbus_g_type_get_map_key_specialization (gtype);
00809   value_gtype = dbus_g_type_get_map_value_specialization (gtype);
00810 
00811   ret = dbus_g_type_specialized_construct (gtype);
00812   g_value_set_boxed_take_ownership (value, ret);
00813 
00814   dbus_g_type_specialized_init_append (value, &appendctx);
00815 
00816   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00817     {
00818       DBusMessageIter entry_iter;
00819       GValue key_value = {0,};
00820       GValue value_value = {0,};
00821 
00822       current_type = dbus_message_iter_get_arg_type (&subiter);
00823       g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
00824 
00825       dbus_message_iter_recurse (&subiter, &entry_iter);
00826 
00827       g_value_init (&key_value, key_gtype);
00828       if (!_dbus_gvalue_demarshal (context,
00829                                   &entry_iter,
00830                                   &key_value,
00831                                   error))
00832         return FALSE;
00833 
00834       dbus_message_iter_next (&entry_iter);
00835 
00836       g_value_init (&value_value, value_gtype);
00837       if (!_dbus_gvalue_demarshal (context,
00838                                   &entry_iter,
00839                                   &value_value,
00840                                   error))
00841         return FALSE;
00842 
00843       dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
00844       /* Ownership of values passes to map, don't unset */
00845 
00846       dbus_message_iter_next (&subiter);
00847     }
00848   
00849   return TRUE;
00850 }
00851 
00852 static DBusGValueDemarshalFunc
00853 get_type_demarshaller (GType type)
00854 {
00855   DBusGTypeMarshalData *typedata;
00856 
00857   typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
00858   if (typedata == NULL)
00859     {
00860       if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
00861         return demarshal_valuearray;
00862       if (dbus_g_type_is_collection (type))
00863         return demarshal_collection;
00864       if (dbus_g_type_is_map (type))
00865         return demarshal_map;
00866 
00867       g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
00868       return NULL;
00869     }
00870   g_assert (typedata->vtable);
00871   return typedata->vtable->demarshaller;
00872 }
00873 
00874 static gboolean
00875 demarshal_collection (DBusGValueMarshalCtx    *context,
00876                       DBusMessageIter         *iter,
00877                       GValue                  *value,
00878                       GError                 **error)
00879 {
00880   GType coltype;
00881   GType subtype;
00882   
00883   coltype = G_VALUE_TYPE (value);
00884   subtype = dbus_g_type_get_collection_specialization (coltype);
00885 
00886   if (_dbus_g_type_is_fixed (subtype))
00887     return demarshal_collection_array (context, iter, value, error);
00888   else
00889     return demarshal_collection_ptrarray (context, iter, value, error);
00890 }
00891 
00892 static gboolean
00893 demarshal_collection_ptrarray (DBusGValueMarshalCtx    *context,
00894                                DBusMessageIter         *iter,
00895                                GValue                  *value,
00896                                GError                 **error)
00897 {
00898   GType coltype;
00899   GType subtype;
00900   gpointer instance;
00901   DBusGTypeSpecializedAppendContext ctx;
00902   DBusGValueDemarshalFunc demarshaller;
00903   DBusMessageIter subiter;
00904   int current_type;
00905 
00906   current_type = dbus_message_iter_get_arg_type (iter);
00907 
00908   if (current_type != DBUS_TYPE_ARRAY)
00909     {
00910       g_set_error (error,
00911                    DBUS_GERROR,
00912                    DBUS_GERROR_INVALID_ARGS,
00913                    _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
00914       return FALSE;
00915     }
00916 
00917   dbus_message_iter_recurse (iter, &subiter);
00918   
00919   coltype = G_VALUE_TYPE (value);
00920   subtype = dbus_g_type_get_collection_specialization (coltype);
00921 
00922   demarshaller = get_type_demarshaller (subtype);
00923 
00924   if (!demarshaller)
00925     {
00926       g_set_error (error,
00927                    DBUS_GERROR,
00928                    DBUS_GERROR_INVALID_ARGS,
00929                    _("No demarshaller registered for type \"%s\" of collection \"%s\""),
00930                    g_type_name (coltype),
00931                    g_type_name (subtype));
00932       return FALSE;
00933     }
00934 
00935   instance = dbus_g_type_specialized_construct (coltype);
00936   g_value_set_boxed_take_ownership (value, instance);
00937 
00938   dbus_g_type_specialized_init_append (value, &ctx);
00939 
00940   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00941     {
00942       GValue eltval = {0, };
00943 
00944       g_value_init (&eltval, subtype);
00945 
00946       if (!demarshaller (context, &subiter, &eltval, error))
00947         {
00948           dbus_g_type_specialized_collection_end_append (&ctx);
00949           g_value_unset (value);
00950           return FALSE;
00951         }
00952       dbus_g_type_specialized_collection_append (&ctx, &eltval);
00953       
00954       dbus_message_iter_next (&subiter);
00955     }
00956   dbus_g_type_specialized_collection_end_append (&ctx);
00957   
00958   return TRUE;
00959 }
00960 
00961 static gboolean
00962 demarshal_collection_array (DBusGValueMarshalCtx    *context,
00963                             DBusMessageIter         *iter,
00964                             GValue                  *value,
00965                             GError                 **error)
00966 {
00967   DBusMessageIter subiter;
00968   GArray *ret;
00969   GType elt_gtype;
00970   int elt_size;
00971   void *msgarray;
00972   int msgarray_len;
00973 
00974   dbus_message_iter_recurse (iter, &subiter);
00975 
00976   elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
00977   g_assert (elt_gtype != G_TYPE_INVALID);
00978   g_assert (_dbus_g_type_is_fixed (elt_gtype));
00979 
00980   elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
00981   
00982   ret = g_array_new (FALSE, TRUE, elt_size);
00983 
00984   msgarray = NULL;
00985   dbus_message_iter_get_fixed_array (&subiter,
00986                                      &msgarray,
00987                                      &msgarray_len);
00988   g_assert (msgarray != NULL);
00989   g_assert (msgarray_len >= 0);
00990   g_array_append_vals (ret, msgarray, (guint) msgarray_len);
00991 
00992   g_value_set_boxed_take_ownership (value, ret);
00993   
00994   return TRUE;
00995 }
00996 
00997 gboolean
00998 _dbus_gvalue_demarshal (DBusGValueMarshalCtx    *context,
00999                        DBusMessageIter         *iter,
01000                        GValue                  *value,
01001                        GError                 **error)
01002 {
01003   GType gtype;
01004   DBusGValueDemarshalFunc demarshaller;
01005 
01006   gtype = G_VALUE_TYPE (value);
01007 
01008   demarshaller = get_type_demarshaller (gtype);
01009 
01010   if (demarshaller == NULL)
01011     {
01012       g_set_error (error,
01013                    DBUS_GERROR,
01014                    DBUS_GERROR_INVALID_ARGS,
01015                    _("No demarshaller registered for type \"%s\""),
01016                    g_type_name (gtype));
01017       return FALSE;
01018     }
01019   
01020   return demarshaller (context, iter, value, error);
01021 }
01022 
01023 gboolean
01024 _dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx    *context,
01025                                DBusMessageIter         *iter,
01026                                GValue                  *value,
01027                                GError                 **error)
01028 {
01029   return demarshal_static_variant (context, iter, value, error);
01030 }
01031 
01032 GValueArray *
01033 _dbus_gvalue_demarshal_message  (DBusGValueMarshalCtx    *context,
01034                                 DBusMessage             *message,
01035                                 guint                    n_types,
01036                                 const GType             *types,
01037                                 GError                 **error)
01038 {
01039   GValueArray *ret;
01040   DBusMessageIter iter;
01041   int current_type;
01042   guint index;
01043   
01044   ret = g_value_array_new (6);  /* 6 is a typical maximum for arguments */
01045 
01046   dbus_message_iter_init (message, &iter);
01047   index = 0;
01048   while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
01049     {
01050       GValue *value;
01051       GType gtype;
01052 
01053       if (index >= n_types)
01054         {
01055           g_set_error (error, DBUS_GERROR,
01056                        DBUS_GERROR_INVALID_ARGS,
01057                        _("Too many arguments in message"));
01058           goto lose;
01059         }
01060       
01061       g_value_array_append (ret, NULL);
01062       value = g_value_array_get_nth (ret, index);
01063 
01064       gtype = types[index]; 
01065       g_value_init (value, gtype);
01066 
01067       if (!_dbus_gvalue_demarshal (context, &iter, value, error))
01068         goto lose;
01069       dbus_message_iter_next (&iter);
01070       index++;
01071     }
01072   if (index < n_types)
01073     {
01074       g_set_error (error, DBUS_GERROR,
01075                    DBUS_GERROR_INVALID_ARGS,
01076                    _("Too few arguments in message"));
01077       goto lose;
01078     }
01079 
01080   return ret;
01081  lose:
01082   g_value_array_free (ret);
01083   return NULL;
01084 }
01085 
01086 static gboolean
01087 marshal_basic (DBusMessageIter *iter, const GValue *value)
01088 {
01089   GType value_type;
01090 
01091   value_type = G_VALUE_TYPE (value);
01092   
01093   switch (value_type)
01094     {
01095     case G_TYPE_CHAR:
01096       {
01097         char b = g_value_get_char (value);
01098         if (!dbus_message_iter_append_basic (iter,
01099                                              DBUS_TYPE_BYTE,
01100                                              &b))
01101           goto nomem;
01102       }
01103       return TRUE;
01104     case G_TYPE_UCHAR:
01105       {
01106         unsigned char b = g_value_get_uchar (value);
01107         if (!dbus_message_iter_append_basic (iter,
01108                                              DBUS_TYPE_BYTE,
01109                                              &b))
01110           goto nomem;
01111       }
01112       return TRUE;
01113     case G_TYPE_BOOLEAN:
01114       {
01115         dbus_bool_t b = g_value_get_boolean (value);
01116         if (!dbus_message_iter_append_basic (iter,
01117                                              DBUS_TYPE_BOOLEAN,
01118                                              &b))
01119           goto nomem;
01120       }
01121       return TRUE;
01122     case G_TYPE_INT:
01123       {
01124         dbus_int32_t v = g_value_get_int (value);
01125         if (!dbus_message_iter_append_basic (iter,
01126                                              DBUS_TYPE_INT32,
01127                                              &v))
01128           goto nomem;
01129       }
01130       return TRUE;
01131     case G_TYPE_UINT:
01132       {
01133         dbus_uint32_t v = g_value_get_uint (value);
01134         if (!dbus_message_iter_append_basic (iter,
01135                                              DBUS_TYPE_UINT32,
01136                                              &v))
01137           goto nomem;
01138       }
01139       return TRUE;
01140     case G_TYPE_LONG:
01141       {
01142         dbus_int32_t v = g_value_get_long (value);
01143         if (!dbus_message_iter_append_basic (iter,
01144                                              DBUS_TYPE_INT32,
01145                                              &v))
01146           goto nomem;
01147       }
01148       return TRUE;
01149     case G_TYPE_ULONG:
01150       {
01151         dbus_uint32_t v = g_value_get_ulong (value);
01152         if (!dbus_message_iter_append_basic (iter,
01153                                              DBUS_TYPE_UINT32,
01154                                              &v))
01155           goto nomem;
01156       }
01157       return TRUE;
01158     case G_TYPE_INT64:
01159       {
01160         gint64 v = g_value_get_int64 (value);
01161         if (!dbus_message_iter_append_basic (iter,
01162                                              DBUS_TYPE_INT64,
01163                                              &v))
01164           goto nomem;
01165       }
01166       return TRUE;
01167     case G_TYPE_UINT64:
01168       {
01169         guint64 v = g_value_get_uint64 (value);
01170         if (!dbus_message_iter_append_basic (iter,
01171                                              DBUS_TYPE_UINT64,
01172                                              &v))
01173           goto nomem;
01174       }
01175       return TRUE;
01176     case G_TYPE_FLOAT:
01177       {
01178         double v = g_value_get_float (value);
01179         
01180         if (!dbus_message_iter_append_basic (iter,
01181                                              DBUS_TYPE_DOUBLE,
01182                                              &v))
01183           goto nomem;
01184       }
01185       return TRUE;
01186     case G_TYPE_DOUBLE:
01187       {
01188         double v = g_value_get_double (value);
01189         
01190         if (!dbus_message_iter_append_basic (iter,
01191                                              DBUS_TYPE_DOUBLE,
01192                                              &v))
01193           goto nomem;
01194       }
01195       return TRUE;
01196     case G_TYPE_STRING:
01197       /* FIXME, the GValue string may not be valid UTF-8 */
01198       {
01199         const char *v = g_value_get_string (value);
01200         if (!v)
01201           v = "";
01202         if (!dbus_message_iter_append_basic (iter,
01203                                              DBUS_TYPE_STRING,
01204                                              &v))
01205           goto nomem;
01206       }
01207       return TRUE;
01208       
01209     default:
01210       {
01211         g_assert_not_reached ();
01212         return FALSE;
01213       }
01214     }
01215 
01216  nomem:
01217   g_error ("no memory");
01218   return FALSE;
01219 }
01220 
01221 static gboolean
01222 marshal_strv (DBusMessageIter   *iter,
01223               const GValue       *value)
01224 {
01225   DBusMessageIter subiter;
01226   char **array;
01227   char **elt;
01228   gboolean ret = FALSE;
01229 
01230   g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
01231 
01232   array = g_value_get_boxed (value);
01233 
01234   if (!dbus_message_iter_open_container (iter,
01235                                          DBUS_TYPE_ARRAY,
01236                                          "s",
01237                                          &subiter))
01238     goto out;
01239 
01240   for (elt = array; *elt; elt++)
01241     {
01242       if (!dbus_message_iter_append_basic (&subiter,
01243                                            DBUS_TYPE_STRING,
01244                                            elt))
01245         goto out;
01246     }
01247 
01248   if (!dbus_message_iter_close_container (iter, &subiter))
01249     goto out;
01250   ret = TRUE;
01251  out:
01252   return ret;
01253 }
01254 
01255 static gboolean
01256 marshal_valuearray (DBusMessageIter   *iter,
01257                     const GValue       *value)
01258 {
01259   GValueArray *array;
01260   guint i;
01261   DBusMessageIter subiter;
01262 
01263   g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
01264 
01265   array = g_value_get_boxed (value);
01266 
01267   if (!dbus_message_iter_open_container (iter,
01268                                          DBUS_TYPE_STRUCT,
01269                                          NULL,
01270                                          &subiter))
01271     goto oom;
01272 
01273   for (i = 0; i < array->n_values; i++)
01274     {
01275       if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
01276         return FALSE;
01277     }
01278 
01279   if (!dbus_message_iter_close_container (iter, &subiter))
01280     goto oom;
01281 
01282   return TRUE;
01283  oom:
01284   g_error ("out of memory");
01285   return FALSE;
01286 }
01287 
01288 static gboolean
01289 marshal_proxy (DBusMessageIter         *iter,
01290                const GValue            *value)
01291 {
01292   const char *path;
01293   DBusGProxy *proxy;
01294 
01295   g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
01296 
01297   proxy = g_value_get_object (value);
01298   path = dbus_g_proxy_get_path (proxy);
01299   
01300   if (!dbus_message_iter_append_basic (iter,
01301                                        DBUS_TYPE_OBJECT_PATH,
01302                                        &path))
01303     return FALSE;
01304   return TRUE;
01305 }
01306 
01307 static gboolean
01308 marshal_object_path (DBusMessageIter         *iter,
01309                      const GValue            *value)
01310 {
01311   const char *path;
01312 
01313   g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
01314 
01315   path = (const char*) g_value_get_boxed (value);
01316   
01317   if (!dbus_message_iter_append_basic (iter,
01318                                        DBUS_TYPE_OBJECT_PATH,
01319                                        &path))
01320     return FALSE;
01321   return TRUE;
01322 }
01323 
01324 static gboolean
01325 marshal_object (DBusMessageIter         *iter,
01326                 const GValue            *value)
01327 {
01328   const char *path;
01329   GObject *obj;
01330 
01331   obj = g_value_get_object (value);
01332   path = _dbus_gobject_get_path (obj);
01333 
01334   if (path == NULL)
01335     /* FIXME should throw error */
01336     return FALSE;
01337   
01338   if (!dbus_message_iter_append_basic (iter,
01339                                        DBUS_TYPE_OBJECT_PATH,
01340                                        &path))
01341     return FALSE;
01342   return TRUE;
01343 }
01344 
01345 struct DBusGLibHashMarshalData
01346 {
01347   const char *entry_sig;
01348   DBusMessageIter *iter;
01349   gboolean err;
01350 };
01351 
01352 static void
01353 marshal_map_entry (const GValue *key,
01354                    const GValue *value,
01355                    gpointer data)
01356 {
01357   struct DBusGLibHashMarshalData *hashdata = data;
01358   DBusMessageIter subiter;
01359 
01360   if (hashdata->err)
01361     return;
01362 
01363   if (!dbus_message_iter_open_container (hashdata->iter,
01364                                          DBUS_TYPE_DICT_ENTRY,
01365                                          NULL,
01366                                          &subiter))
01367     goto lose;
01368 
01369   if (!_dbus_gvalue_marshal (&subiter, key))
01370     goto lose;
01371 
01372   if (!_dbus_gvalue_marshal (&subiter, value))
01373     goto lose;
01374 
01375   if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
01376     goto lose;
01377   
01378   return;
01379  lose:
01380   hashdata->err = TRUE;
01381 }
01382 
01383 static gboolean
01384 marshal_map (DBusMessageIter   *iter,
01385              const GValue      *value)
01386 {
01387   GType gtype;
01388   DBusMessageIter arr_iter;
01389   gboolean ret;
01390   struct DBusGLibHashMarshalData hashdata;
01391   char *key_sig;
01392   char *value_sig;
01393   GType key_type;
01394   GType value_type;
01395   char *entry_sig;
01396   char *array_sig;
01397 
01398   gtype = G_VALUE_TYPE (value);
01399 
01400   ret = FALSE;
01401 
01402   key_type = dbus_g_type_get_map_key_specialization (gtype);
01403   g_assert (_dbus_gtype_is_valid_hash_key (key_type));
01404   value_type = dbus_g_type_get_map_value_specialization (gtype);
01405   g_assert (_dbus_gtype_is_valid_hash_value (value_type));
01406 
01407   key_sig = _dbus_gtype_to_signature (key_type);
01408   if (!key_sig)
01409     {
01410       g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
01411       return FALSE;
01412     }
01413   value_sig = _dbus_gtype_to_signature (value_type);
01414   if (!value_sig)
01415     {
01416       g_free (key_sig);
01417       g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
01418       return FALSE;
01419     }
01420   entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
01421   g_free (key_sig);
01422   g_free (value_sig);
01423   array_sig = g_strdup_printf ("%c%s%c",
01424                                DBUS_DICT_ENTRY_BEGIN_CHAR,
01425                                entry_sig,
01426                                DBUS_DICT_ENTRY_END_CHAR);
01427   if (!dbus_message_iter_open_container (iter,
01428                                          DBUS_TYPE_ARRAY,
01429                                          array_sig,
01430                                          &arr_iter))
01431     goto lose;
01432 
01433   hashdata.iter = &arr_iter;
01434   hashdata.err = FALSE;
01435   hashdata.entry_sig = entry_sig;
01436 
01437   dbus_g_type_map_value_iterate (value,
01438                                  marshal_map_entry,
01439                                  &hashdata);
01440 
01441   if (!dbus_message_iter_close_container (iter, &arr_iter))
01442     goto lose;
01443 
01444  out:
01445   g_free (entry_sig);
01446   g_free (array_sig);
01447   return !hashdata.err;
01448  lose:
01449   hashdata.err = TRUE;
01450   goto out;
01451 }
01452 
01453 static gboolean
01454 marshal_variant (DBusMessageIter          *iter,
01455                  const GValue             *value)
01456 {
01457   GType value_gtype;
01458   DBusMessageIter subiter;
01459   char *variant_sig;
01460   GValue *real_value;
01461   gboolean ret = FALSE;
01462 
01463   real_value = g_value_get_boxed (value);
01464   value_gtype = G_VALUE_TYPE (real_value);
01465 
01466   variant_sig = dbus_gvalue_to_signature (real_value);
01467   if (variant_sig == NULL)
01468     {
01469       g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
01470       return FALSE;
01471     }
01472 
01473   if (!dbus_message_iter_open_container (iter,
01474                                          DBUS_TYPE_VARIANT,
01475                                          variant_sig,
01476                                          &subiter))
01477     goto out;
01478 
01479   if (!marshal_basic (&subiter, real_value))
01480     goto out;
01481 
01482   if (!dbus_message_iter_close_container (iter, &subiter))
01483     goto out;
01484 
01485   ret = TRUE;
01486  out:
01487   g_free (variant_sig);
01488   return ret;
01489 }
01490 
01491 static DBusGValueMarshalFunc
01492 get_type_marshaller (GType type)
01493 {
01494   DBusGTypeMarshalData *typedata;
01495 
01496   typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
01497   if (typedata == NULL)
01498     {
01499       if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
01500         return marshal_valuearray;
01501       if (dbus_g_type_is_collection (type))
01502         return marshal_collection;
01503       if (dbus_g_type_is_map (type))
01504         return marshal_map;
01505 
01506       g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
01507       return NULL;
01508     }
01509   g_assert (typedata->vtable);
01510   return typedata->vtable->marshaller;
01511 }
01512 
01513 typedef struct
01514 {
01515   DBusMessageIter *iter;
01516   DBusGValueMarshalFunc marshaller;
01517   gboolean err;
01518 } DBusGValueCollectionMarshalData;
01519 
01520 static void
01521 collection_marshal_iterator (const GValue *eltval,
01522                              gpointer      user_data)
01523 {
01524   DBusGValueCollectionMarshalData *data = user_data;
01525 
01526   if (data->err)
01527     return;
01528 
01529   if (!data->marshaller (data->iter, eltval))
01530     data->err = TRUE;
01531 }
01532 
01533 static gboolean
01534 marshal_collection (DBusMessageIter         *iter,
01535                     const GValue            *value)
01536 {
01537   GType coltype;
01538   GType subtype;
01539   
01540   coltype = G_VALUE_TYPE (value);
01541   subtype = dbus_g_type_get_collection_specialization (coltype);
01542 
01543   if (_dbus_g_type_is_fixed (subtype))
01544     return marshal_collection_array (iter, value);
01545   else
01546     return marshal_collection_ptrarray (iter, value);
01547 }
01548 
01549 static gboolean
01550 marshal_collection_ptrarray (DBusMessageIter         *iter,
01551                              const GValue            *value)
01552 {
01553   GType coltype;
01554   GType elt_gtype;
01555   DBusGValueCollectionMarshalData data;
01556   DBusMessageIter subiter;
01557   char *elt_sig;
01558   
01559   coltype = G_VALUE_TYPE (value);
01560   elt_gtype = dbus_g_type_get_collection_specialization (coltype);
01561   data.marshaller = get_type_marshaller (elt_gtype);
01562   if (!data.marshaller)
01563     return FALSE;
01564 
01565   elt_sig = _dbus_gtype_to_signature (elt_gtype);
01566   if (!elt_sig)
01567     {
01568       g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
01569       return FALSE;
01570     }
01571 
01572   if (!dbus_message_iter_open_container (iter,
01573                                          DBUS_TYPE_ARRAY,
01574                                          elt_sig,
01575                                          &subiter))
01576     goto oom;
01577   g_free (elt_sig);
01578 
01579   data.iter = &subiter;
01580   data.err = FALSE;
01581 
01582   dbus_g_type_collection_value_iterate (value,
01583                                         collection_marshal_iterator,
01584                                         &data);
01585 
01586   if (!dbus_message_iter_close_container (iter, &subiter))
01587     goto oom;
01588   
01589   return !data.err;
01590  oom:
01591   g_error ("out of memory");
01592   return FALSE;
01593 }
01594 
01595 
01596 static gboolean
01597 marshal_collection_array (DBusMessageIter   *iter,
01598                           const GValue      *value)
01599 {
01600   GType elt_gtype;
01601   DBusMessageIter subiter;
01602   GArray *array;
01603   guint elt_size;
01604   char *subsignature_str;
01605 
01606   elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
01607   g_assert (_dbus_g_type_is_fixed (elt_gtype));
01608   subsignature_str = _dbus_gtype_to_signature (elt_gtype);
01609   if (!subsignature_str)
01610     {
01611       g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
01612       return FALSE;
01613     }
01614   
01615   elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
01616 
01617   array = g_value_get_boxed (value);
01618 
01619   if (!dbus_message_iter_open_container (iter,
01620                                          DBUS_TYPE_ARRAY,
01621                                          subsignature_str,
01622                                          &subiter))
01623     goto oom;
01624 
01625   /* TODO - This assumes that basic values are the same size
01626    * is this always true?  If it is we can probably avoid
01627    * a lot of the overhead in _marshal_basic_instance...
01628    */
01629   if (!dbus_message_iter_append_fixed_array (&subiter,
01630                                              subsignature_str[0],
01631                                              &(array->data),
01632                                              array->len))
01633     goto oom;
01634 
01635   if (!dbus_message_iter_close_container (iter, &subiter))
01636     goto oom;
01637   g_free (subsignature_str);
01638   return TRUE;
01639  oom:
01640   g_error ("out of memory");
01641   return FALSE;
01642 }
01643 
01644 gboolean
01645 _dbus_gvalue_marshal (DBusMessageIter         *iter,
01646                      const GValue       *value)
01647 {
01648   GType gtype;
01649   DBusGValueMarshalFunc marshaller;
01650 
01651   gtype = G_VALUE_TYPE (value);
01652 
01653   marshaller = get_type_marshaller (gtype);
01654   if (marshaller == NULL)
01655     return FALSE;
01656   return marshaller (iter, value);
01657 }
01658 
01659 #ifdef DBUS_BUILD_TESTS
01660 
01661 static void
01662 assert_type_maps_to (GType gtype, const char *expected_sig)
01663 {
01664   char *sig;
01665   sig = _dbus_gtype_to_signature (gtype);
01666   g_assert (sig != NULL);
01667   g_assert (!strcmp (expected_sig, sig));
01668   g_free (sig);
01669 }
01670 
01671 static void
01672 assert_signature_maps_to (const char *sig, GType expected_gtype)
01673 {
01674   g_assert (_dbus_gtype_from_signature (sig, TRUE) == expected_gtype);
01675 }
01676 
01677 static void
01678 assert_bidirectional_mapping (GType gtype, const char *expected_sig)
01679 {
01680   assert_type_maps_to (gtype, expected_sig);
01681   assert_signature_maps_to (expected_sig, gtype);
01682 }
01683 
01689 gboolean
01690 _dbus_gvalue_test (const char *test_data_dir)
01691 {
01692   _dbus_g_value_types_init ();
01693   
01694   assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
01695   assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
01696   assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
01697 
01698   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);
01699   assert_signature_maps_to (DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING, G_TYPE_VALUE_ARRAY);
01700   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);
01701 
01702   assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
01703                                 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);
01704   assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
01705                                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
01706   assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
01707                                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
01708 
01709   return TRUE;
01710 }
01711 
01712 #endif /* DBUS_BUILD_TESTS */

Generated on Tue Aug 30 16:35:50 2005 for D-BUS by  doxygen 1.4.3