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

Generated on Tue Sep 13 01:28:06 2005 for D-BUS by  doxygen 1.4.4