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

Generated on Wed Oct 3 10:04:23 2007 for D-BUSGLibBindings by  doxygen 1.5.1