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       if (elt_type == G_TYPE_INVALID)
00770         {
00771           g_value_array_free (ret);
00772           g_set_error (error,
00773                        DBUS_GERROR,
00774                        DBUS_GERROR_INVALID_ARGS,
00775                        _("Couldn't demarshal argument with signature \"%s\""), current_sig);
00776           dbus_free (current_sig);
00777           return FALSE;
00778         }
00779       dbus_free (current_sig);
00780       
00781       g_value_init (val, elt_type);
00782 
00783       if (!_dbus_gvalue_demarshal (context, &subiter, val, error))
00784         {
00785           g_value_array_free (ret);
00786           return FALSE;
00787         }
00788 
00789       dbus_message_iter_next (&subiter);
00790     }
00791 
00792   g_value_set_boxed_take_ownership (value, ret);
00793   
00794   return TRUE;
00795 }
00796 
00797 static gboolean
00798 demarshal_map (DBusGValueMarshalCtx    *context,
00799                DBusMessageIter         *iter,
00800                GValue                  *value,
00801                GError                 **error)
00802 {
00803   GType gtype;
00804   DBusMessageIter subiter;
00805   int current_type;
00806   gpointer ret;
00807   GType key_gtype;
00808   GType value_gtype;
00809   DBusGTypeSpecializedAppendContext appendctx;
00810 
00811   current_type = dbus_message_iter_get_arg_type (iter);
00812   if (current_type != DBUS_TYPE_ARRAY)
00813     {
00814       g_set_error (error,
00815                    DBUS_GERROR,
00816                    DBUS_GERROR_INVALID_ARGS,
00817                    _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
00818       return FALSE;
00819     }
00820 
00821   gtype = G_VALUE_TYPE (value);
00822 
00823   dbus_message_iter_recurse (iter, &subiter);
00824 
00825   current_type = dbus_message_iter_get_arg_type (&subiter);
00826   if (current_type != DBUS_TYPE_INVALID
00827       && current_type != DBUS_TYPE_DICT_ENTRY)
00828     {
00829       g_set_error (error,
00830                    DBUS_GERROR,
00831                    DBUS_GERROR_INVALID_ARGS,
00832                    _("Expected D-BUS dict entry, got type code \'%c\'"), (guchar) current_type);
00833       return FALSE;
00834     }
00835 
00836   key_gtype = dbus_g_type_get_map_key_specialization (gtype);
00837   value_gtype = dbus_g_type_get_map_value_specialization (gtype);
00838 
00839   ret = dbus_g_type_specialized_construct (gtype);
00840   g_value_set_boxed_take_ownership (value, ret);
00841 
00842   dbus_g_type_specialized_init_append (value, &appendctx);
00843 
00844   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
00845     {
00846       DBusMessageIter entry_iter;
00847       GValue key_value = {0,};
00848       GValue value_value = {0,};
00849 
00850       current_type = dbus_message_iter_get_arg_type (&subiter);
00851       g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
00852 
00853       dbus_message_iter_recurse (&subiter, &entry_iter);
00854 
00855       g_value_init (&key_value, key_gtype);
00856       if (!_dbus_gvalue_demarshal (context,
00857                                   &entry_iter,
00858                                   &key_value,
00859                                   error))
00860         return FALSE;
00861 
00862       dbus_message_iter_next (&entry_iter);
00863 
00864       g_value_init (&value_value, value_gtype);
00865       if (!_dbus_gvalue_demarshal (context,
00866                                   &entry_iter,
00867                                   &value_value,
00868                                   error))
00869         return FALSE;
00870 
00871       dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
00872       /* Ownership of values passes to map, don't unset */
00873 
00874       dbus_message_iter_next (&subiter);
00875     }
00876   
00877   return TRUE;
00878 }
00879 
00880 static gboolean
00881 demarshal_struct (DBusGValueMarshalCtx    *context,
00882                   DBusMessageIter         *iter,
00883                   GValue                  *value,
00884                   GError                 **error)
00885 {
00886   int current_type;
00887   DBusMessageIter subiter;
00888   guint i, size;
00889   GValue val = {0,};
00890   GType elt_type;
00891 
00892   current_type = dbus_message_iter_get_arg_type (iter);
00893   if (current_type != DBUS_TYPE_STRUCT)
00894     {
00895       g_set_error (error,
00896                    DBUS_GERROR,
00897                    DBUS_GERROR_INVALID_ARGS,
00898                    _("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type);
00899       return FALSE;
00900     }
00901 
00902   dbus_message_iter_recurse (iter, &subiter);
00903 
00904   g_value_set_boxed_take_ownership (value,
00905     dbus_g_type_specialized_construct (G_VALUE_TYPE (value)));
00906 
00907   size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value));
00908 
00909   for (i=0; i < size; i++)
00910     {
00911 
00912       elt_type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE(value), i);
00913       if (elt_type == G_TYPE_INVALID)
00914         {
00915           g_value_unset (value);
00916           g_set_error (error,
00917                        DBUS_GERROR,
00918                        DBUS_GERROR_INVALID_ARGS,
00919                        _("Couldn't demarshal argument, "
00920                          "struct type %s has no member %d"),
00921                        g_type_name (G_VALUE_TYPE(value)), i);
00922           return FALSE;
00923         }
00924 
00925       g_value_init (&val, elt_type);
00926 
00927       if (!_dbus_gvalue_demarshal (context, &subiter, &val, error))
00928         {
00929           g_value_unset (&val);
00930           g_value_unset (value);
00931           return FALSE;
00932         }
00933       if (!dbus_g_type_struct_set_member (value, i, &val))
00934         {
00935           g_value_unset (&val);
00936           g_value_unset (value);
00937           return FALSE;
00938         }
00939 
00940       dbus_message_iter_next (&subiter);
00941       g_value_unset (&val);
00942     }
00943 
00944   g_assert (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_INVALID);
00945 
00946   return TRUE;
00947 }
00948 
00949 
00950 static DBusGValueDemarshalFunc
00951 get_type_demarshaller (GType type)
00952 {
00953   DBusGTypeMarshalData *typedata;
00954 
00955   typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
00956   if (typedata == NULL)
00957     {
00958       if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
00959         return demarshal_valuearray;
00960       if (dbus_g_type_is_collection (type))
00961         return demarshal_collection;
00962       if (dbus_g_type_is_map (type))
00963         return demarshal_map;
00964       if (dbus_g_type_is_struct (type))
00965         return demarshal_struct;
00966 
00967       g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
00968       return NULL;
00969     }
00970   g_assert (typedata->vtable);
00971   return typedata->vtable->demarshaller;
00972 }
00973 
00974 static gboolean
00975 demarshal_collection (DBusGValueMarshalCtx    *context,
00976                       DBusMessageIter         *iter,
00977                       GValue                  *value,
00978                       GError                 **error)
00979 {
00980   GType coltype;
00981   GType subtype;
00982   
00983   coltype = G_VALUE_TYPE (value);
00984   subtype = dbus_g_type_get_collection_specialization (coltype);
00985 
00986   if (_dbus_g_type_is_fixed (subtype))
00987     return demarshal_collection_array (context, iter, value, error);
00988   else
00989     return demarshal_collection_ptrarray (context, iter, value, error);
00990 }
00991 
00992 static gboolean
00993 demarshal_collection_ptrarray (DBusGValueMarshalCtx    *context,
00994                                DBusMessageIter         *iter,
00995                                GValue                  *value,
00996                                GError                 **error)
00997 {
00998   GType coltype;
00999   GType subtype;
01000   gpointer instance;
01001   DBusGTypeSpecializedAppendContext ctx;
01002   DBusGValueDemarshalFunc demarshaller;
01003   DBusMessageIter subiter;
01004   int current_type;
01005 
01006   current_type = dbus_message_iter_get_arg_type (iter);
01007 
01008   if (current_type != DBUS_TYPE_ARRAY)
01009     {
01010       g_set_error (error,
01011                    DBUS_GERROR,
01012                    DBUS_GERROR_INVALID_ARGS,
01013                    _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
01014       return FALSE;
01015     }
01016 
01017   dbus_message_iter_recurse (iter, &subiter);
01018   
01019   coltype = G_VALUE_TYPE (value);
01020   subtype = dbus_g_type_get_collection_specialization (coltype);
01021 
01022   demarshaller = get_type_demarshaller (subtype);
01023 
01024   if (!demarshaller)
01025     {
01026       g_set_error (error,
01027                    DBUS_GERROR,
01028                    DBUS_GERROR_INVALID_ARGS,
01029                    _("No demarshaller registered for type \"%s\" of collection \"%s\""),
01030                    g_type_name (coltype),
01031                    g_type_name (subtype));
01032       return FALSE;
01033     }
01034 
01035   instance = dbus_g_type_specialized_construct (coltype);
01036   g_value_set_boxed_take_ownership (value, instance);
01037 
01038   dbus_g_type_specialized_init_append (value, &ctx);
01039 
01040   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
01041     {
01042       GValue eltval = {0, };
01043 
01044       g_value_init (&eltval, subtype);
01045 
01046       if (!demarshaller (context, &subiter, &eltval, error))
01047         {
01048           dbus_g_type_specialized_collection_end_append (&ctx);
01049           g_value_unset (value);
01050           return FALSE;
01051         }
01052       dbus_g_type_specialized_collection_append (&ctx, &eltval);
01053       
01054       dbus_message_iter_next (&subiter);
01055     }
01056   dbus_g_type_specialized_collection_end_append (&ctx);
01057   
01058   return TRUE;
01059 }
01060 
01061 static gboolean
01062 demarshal_collection_array (DBusGValueMarshalCtx    *context,
01063                             DBusMessageIter         *iter,
01064                             GValue                  *value,
01065                             GError                 **error)
01066 {
01067   DBusMessageIter subiter;
01068   GArray *ret;
01069   GType elt_gtype;
01070   int elt_size;
01071   void *msgarray;
01072   int msgarray_len;
01073 
01074   dbus_message_iter_recurse (iter, &subiter);
01075 
01076   elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
01077   g_assert (elt_gtype != G_TYPE_INVALID);
01078   g_assert (_dbus_g_type_is_fixed (elt_gtype));
01079 
01080   elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
01081   
01082   ret = g_array_new (FALSE, TRUE, elt_size);
01083 
01084   msgarray = NULL;
01085   dbus_message_iter_get_fixed_array (&subiter,
01086                                      &msgarray,
01087                                      &msgarray_len);
01088   g_assert (msgarray != NULL || msgarray_len == 0);
01089 
01090   if (msgarray_len)
01091     g_array_append_vals (ret, msgarray, (guint) msgarray_len);
01092 
01093   g_value_set_boxed_take_ownership (value, ret);
01094   
01095   return TRUE;
01096 }
01097 
01098 gboolean
01099 _dbus_gvalue_demarshal (DBusGValueMarshalCtx    *context,
01100                        DBusMessageIter         *iter,
01101                        GValue                  *value,
01102                        GError                 **error)
01103 {
01104   GType gtype;
01105   DBusGValueDemarshalFunc demarshaller;
01106 
01107   gtype = G_VALUE_TYPE (value);
01108 
01109   demarshaller = get_type_demarshaller (gtype);
01110 
01111   if (demarshaller == NULL)
01112     {
01113       g_set_error (error,
01114                    DBUS_GERROR,
01115                    DBUS_GERROR_INVALID_ARGS,
01116                    _("No demarshaller registered for type \"%s\""),
01117                    g_type_name (gtype));
01118       return FALSE;
01119     }
01120   
01121   return demarshaller (context, iter, value, error);
01122 }
01123 
01124 gboolean
01125 _dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx    *context,
01126                                DBusMessageIter         *iter,
01127                                GValue                  *value,
01128                                GError                 **error)
01129 {
01130   return demarshal_static_variant (context, iter, value, error);
01131 }
01132 
01133 GValueArray *
01134 _dbus_gvalue_demarshal_message  (DBusGValueMarshalCtx    *context,
01135                                 DBusMessage             *message,
01136                                 guint                    n_types,
01137                                 const GType             *types,
01138                                 GError                 **error)
01139 {
01140   GValueArray *ret;
01141   DBusMessageIter iter;
01142   int current_type;
01143   guint index_;
01144   
01145   ret = g_value_array_new (6);  /* 6 is a typical maximum for arguments */
01146 
01147   dbus_message_iter_init (message, &iter);
01148   index_ = 0;
01149   while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
01150     {
01151       GValue *value;
01152       GType gtype;
01153 
01154       if (index_ >= n_types)
01155         {
01156           g_set_error (error, DBUS_GERROR,
01157                        DBUS_GERROR_INVALID_ARGS,
01158                        _("Too many arguments in message"));
01159           goto lose;
01160         }
01161       
01162       g_value_array_append (ret, NULL);
01163       value = g_value_array_get_nth (ret, index_);
01164 
01165       gtype = types[index_]; 
01166       g_value_init (value, gtype);
01167 
01168       if (!_dbus_gvalue_demarshal (context, &iter, value, error))
01169         goto lose;
01170       dbus_message_iter_next (&iter);
01171       index_++;
01172     }
01173   if (index_ < n_types)
01174     {
01175       g_set_error (error, DBUS_GERROR,
01176                    DBUS_GERROR_INVALID_ARGS,
01177                    _("Too few arguments in message"));
01178       goto lose;
01179     }
01180 
01181   return ret;
01182  lose:
01183   g_value_array_free (ret);
01184   return NULL;
01185 }
01186 
01187 static gboolean
01188 marshal_basic (DBusMessageIter *iter, const GValue *value)
01189 {
01190   GType value_type;
01191 
01192   value_type = G_VALUE_TYPE (value);
01193   
01194   switch (value_type)
01195     {
01196     case G_TYPE_CHAR:
01197       {
01198         char b = g_value_get_char (value);
01199         if (!dbus_message_iter_append_basic (iter,
01200                                              DBUS_TYPE_BYTE,
01201                                              &b))
01202           goto nomem;
01203       }
01204       return TRUE;
01205     case G_TYPE_UCHAR:
01206       {
01207         unsigned char b = g_value_get_uchar (value);
01208         if (!dbus_message_iter_append_basic (iter,
01209                                              DBUS_TYPE_BYTE,
01210                                              &b))
01211           goto nomem;
01212       }
01213       return TRUE;
01214     case G_TYPE_BOOLEAN:
01215       {
01216         dbus_bool_t b = g_value_get_boolean (value);
01217         if (!dbus_message_iter_append_basic (iter,
01218                                              DBUS_TYPE_BOOLEAN,
01219                                              &b))
01220           goto nomem;
01221       }
01222       return TRUE;
01223     case G_TYPE_INT:
01224       {
01225         dbus_int32_t v = g_value_get_int (value);
01226         if (!dbus_message_iter_append_basic (iter,
01227                                              DBUS_TYPE_INT32,
01228                                              &v))
01229           goto nomem;
01230       }
01231       return TRUE;
01232     case G_TYPE_UINT:
01233       {
01234         dbus_uint32_t v = g_value_get_uint (value);
01235         if (!dbus_message_iter_append_basic (iter,
01236                                              DBUS_TYPE_UINT32,
01237                                              &v))
01238           goto nomem;
01239       }
01240       return TRUE;
01241     case G_TYPE_LONG:
01242       {
01243         dbus_int32_t v = g_value_get_long (value);
01244         if (!dbus_message_iter_append_basic (iter,
01245                                              DBUS_TYPE_INT32,
01246                                              &v))
01247           goto nomem;
01248       }
01249       return TRUE;
01250     case G_TYPE_ULONG:
01251       {
01252         dbus_uint32_t v = g_value_get_ulong (value);
01253         if (!dbus_message_iter_append_basic (iter,
01254                                              DBUS_TYPE_UINT32,
01255                                              &v))
01256           goto nomem;
01257       }
01258       return TRUE;
01259     case G_TYPE_INT64:
01260       {
01261         gint64 v = g_value_get_int64 (value);
01262         if (!dbus_message_iter_append_basic (iter,
01263                                              DBUS_TYPE_INT64,
01264                                              &v))
01265           goto nomem;
01266       }
01267       return TRUE;
01268     case G_TYPE_UINT64:
01269       {
01270         guint64 v = g_value_get_uint64 (value);
01271         if (!dbus_message_iter_append_basic (iter,
01272                                              DBUS_TYPE_UINT64,
01273                                              &v))
01274           goto nomem;
01275       }
01276       return TRUE;
01277     case G_TYPE_FLOAT:
01278       {
01279         double v = g_value_get_float (value);
01280         
01281         if (!dbus_message_iter_append_basic (iter,
01282                                              DBUS_TYPE_DOUBLE,
01283                                              &v))
01284           goto nomem;
01285       }
01286       return TRUE;
01287     case G_TYPE_DOUBLE:
01288       {
01289         double v = g_value_get_double (value);
01290         
01291         if (!dbus_message_iter_append_basic (iter,
01292                                              DBUS_TYPE_DOUBLE,
01293                                              &v))
01294           goto nomem;
01295       }
01296       return TRUE;
01297     case G_TYPE_STRING:
01298       /* FIXME, the GValue string may not be valid UTF-8 */
01299       {
01300         const char *v = g_value_get_string (value);
01301         if (!v)
01302           v = "";
01303         if (!dbus_message_iter_append_basic (iter,
01304                                              DBUS_TYPE_STRING,
01305                                              &v))
01306           goto nomem;
01307       }
01308       return TRUE;
01309       
01310     default:
01311       {
01312         g_assert_not_reached ();
01313         return FALSE;
01314       }
01315     }
01316 
01317  nomem:
01318   g_error ("no memory");
01319   return FALSE;
01320 }
01321 
01322 static gboolean
01323 marshal_strv (DBusMessageIter   *iter,
01324               const GValue       *value)
01325 {
01326   DBusMessageIter subiter;
01327   char **array;
01328   char **elt;
01329   gboolean ret = FALSE;
01330 
01331   g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
01332 
01333   array = g_value_get_boxed (value);
01334 
01335   if (!dbus_message_iter_open_container (iter,
01336                                          DBUS_TYPE_ARRAY,
01337                                          "s",
01338                                          &subiter))
01339     goto out;
01340 
01341   if (array)
01342     {
01343       for (elt = array; *elt; elt++)
01344         {
01345           if (!dbus_message_iter_append_basic (&subiter,
01346                                            DBUS_TYPE_STRING,
01347                                            elt))
01348                 goto out;
01349         }
01350     }
01351 
01352   if (!dbus_message_iter_close_container (iter, &subiter))
01353     goto out;
01354   ret = TRUE;
01355  out:
01356   return ret;
01357 }
01358 
01359 static gboolean
01360 marshal_valuearray (DBusMessageIter   *iter,
01361                     const GValue       *value)
01362 {
01363   GValueArray *array;
01364   guint i;
01365   DBusMessageIter subiter;
01366 
01367   g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
01368 
01369   array = g_value_get_boxed (value);
01370 
01371   if (!dbus_message_iter_open_container (iter,
01372                                          DBUS_TYPE_STRUCT,
01373                                          NULL,
01374                                          &subiter))
01375     goto oom;
01376 
01377   if (array)
01378     {
01379       for (i = 0; i < array->n_values; i++)
01380         {
01381           if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
01382             return FALSE;
01383         }
01384     }
01385 
01386   if (!dbus_message_iter_close_container (iter, &subiter))
01387     goto oom;
01388 
01389   return TRUE;
01390  oom:
01391   g_error ("out of memory");
01392   return FALSE;
01393 }
01394 
01395 static gboolean
01396 marshal_proxy (DBusMessageIter         *iter,
01397                const GValue            *value)
01398 {
01399   const char *path;
01400   DBusGProxy *proxy;
01401 
01402   g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
01403 
01404   proxy = g_value_get_object (value);
01405   path = dbus_g_proxy_get_path (proxy);
01406   
01407   if (!dbus_message_iter_append_basic (iter,
01408                                        DBUS_TYPE_OBJECT_PATH,
01409                                        &path))
01410     return FALSE;
01411   return TRUE;
01412 }
01413 
01414 static gboolean
01415 marshal_object_path (DBusMessageIter         *iter,
01416                      const GValue            *value)
01417 {
01418   const char *path;
01419 
01420   g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
01421 
01422   path = (const char*) g_value_get_boxed (value);
01423   
01424   if (!dbus_message_iter_append_basic (iter,
01425                                        DBUS_TYPE_OBJECT_PATH,
01426                                        &path))
01427     return FALSE;
01428   return TRUE;
01429 }
01430 
01431 static gboolean
01432 marshal_object (DBusMessageIter         *iter,
01433                 const GValue            *value)
01434 {
01435   const char *path;
01436   GObject *obj;
01437 
01438   obj = g_value_get_object (value);
01439   path = _dbus_gobject_get_path (obj);
01440 
01441   if (path == NULL)
01442     /* FIXME should throw error */
01443     return FALSE;
01444   
01445   if (!dbus_message_iter_append_basic (iter,
01446                                        DBUS_TYPE_OBJECT_PATH,
01447                                        &path))
01448     return FALSE;
01449   return TRUE;
01450 }
01451 
01452 struct DBusGLibHashMarshalData
01453 {
01454   const char *entry_sig;
01455   DBusMessageIter *iter;
01456   gboolean err;
01457 };
01458 
01459 static void
01460 marshal_map_entry (const GValue *key,
01461                    const GValue *value,
01462                    gpointer data)
01463 {
01464   struct DBusGLibHashMarshalData *hashdata = data;
01465   DBusMessageIter subiter;
01466 
01467   if (hashdata->err)
01468     return;
01469 
01470   if (!dbus_message_iter_open_container (hashdata->iter,
01471                                          DBUS_TYPE_DICT_ENTRY,
01472                                          NULL,
01473                                          &subiter))
01474     goto lose;
01475 
01476   if (!_dbus_gvalue_marshal (&subiter, key))
01477     goto lose;
01478 
01479   if (!_dbus_gvalue_marshal (&subiter, value))
01480     goto lose;
01481 
01482   if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
01483     goto lose;
01484   
01485   return;
01486  lose:
01487   hashdata->err = TRUE;
01488 }
01489 
01490 static gboolean
01491 marshal_map (DBusMessageIter   *iter,
01492              const GValue      *value)
01493 {
01494   GType gtype;
01495   DBusMessageIter arr_iter;
01496   gboolean ret;
01497   struct DBusGLibHashMarshalData hashdata;
01498   char *key_sig;
01499   char *value_sig;
01500   GType key_type;
01501   GType value_type;
01502   char *entry_sig;
01503   char *array_sig;
01504 
01505   gtype = G_VALUE_TYPE (value);
01506 
01507   ret = FALSE;
01508 
01509   key_type = dbus_g_type_get_map_key_specialization (gtype);
01510   g_assert (_dbus_gtype_is_valid_hash_key (key_type));
01511   value_type = dbus_g_type_get_map_value_specialization (gtype);
01512   g_assert (_dbus_gtype_is_valid_hash_value (value_type));
01513 
01514   key_sig = _dbus_gtype_to_signature (key_type);
01515   if (!key_sig)
01516     {
01517       g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
01518       return FALSE;
01519     }
01520   value_sig = _dbus_gtype_to_signature (value_type);
01521   if (!value_sig)
01522     {
01523       g_free (key_sig);
01524       g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
01525       return FALSE;
01526     }
01527   entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
01528   g_free (key_sig);
01529   g_free (value_sig);
01530   array_sig = g_strdup_printf ("%c%s%c",
01531                                DBUS_DICT_ENTRY_BEGIN_CHAR,
01532                                entry_sig,
01533                                DBUS_DICT_ENTRY_END_CHAR);
01534   if (!dbus_message_iter_open_container (iter,
01535                                          DBUS_TYPE_ARRAY,
01536                                          array_sig,
01537                                          &arr_iter))
01538     goto lose;
01539 
01540   hashdata.iter = &arr_iter;
01541   hashdata.err = FALSE;
01542   hashdata.entry_sig = entry_sig;
01543 
01544   dbus_g_type_map_value_iterate (value,
01545                                  marshal_map_entry,
01546                                  &hashdata);
01547 
01548   if (!dbus_message_iter_close_container (iter, &arr_iter))
01549     goto lose;
01550 
01551  out:
01552   g_free (entry_sig);
01553   g_free (array_sig);
01554   return !hashdata.err;
01555  lose:
01556   hashdata.err = TRUE;
01557   goto out;
01558 }
01559 
01560 static gboolean
01561 marshal_struct (DBusMessageIter   *iter,
01562                 const GValue      *value)
01563 {
01564   GType gtype;
01565   DBusMessageIter subiter;
01566   gboolean ret;
01567   guint size, i;
01568   GValue val = {0,};
01569 
01570   gtype = G_VALUE_TYPE (value);
01571 
01572   ret = FALSE;
01573 
01574   size = dbus_g_type_get_struct_size (gtype);
01575 
01576   if (!dbus_message_iter_open_container (iter,
01577                                          DBUS_TYPE_STRUCT,
01578                                          NULL,
01579                                          &subiter))
01580     goto oom;
01581 
01582   for (i = 0; i < size; i++)
01583     {
01584       g_value_init (&val, dbus_g_type_get_struct_member_type
01585           (G_VALUE_TYPE(value), i));
01586       if (!dbus_g_type_struct_get_member (value, i, &val))
01587         return FALSE;
01588       if (!_dbus_gvalue_marshal (&subiter, &val))
01589         return FALSE;
01590       g_value_unset(&val);
01591     }
01592 
01593   if (!dbus_message_iter_close_container (iter, &subiter))
01594     goto oom;
01595 
01596   return TRUE;
01597  oom:
01598   g_error ("out of memory");
01599   return FALSE;
01600 }
01601 
01602 static gboolean
01603 marshal_variant (DBusMessageIter          *iter,
01604                  const GValue             *value)
01605 {
01606   GType value_gtype;
01607   DBusMessageIter subiter;
01608   char *variant_sig;
01609   GValue *real_value;
01610   gboolean ret = FALSE;
01611 
01612   real_value = g_value_get_boxed (value);
01613   value_gtype = G_VALUE_TYPE (real_value);
01614 
01615   variant_sig = _dbus_gvalue_to_signature (real_value);
01616   if (variant_sig == NULL)
01617     {
01618       g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
01619       return FALSE;
01620     }
01621 
01622   if (!dbus_message_iter_open_container (iter,
01623                                          DBUS_TYPE_VARIANT,
01624                                          variant_sig,
01625                                          &subiter))
01626     goto out;
01627 
01628   if (!_dbus_gvalue_marshal (&subiter, real_value))
01629     goto out;
01630 
01631   if (!dbus_message_iter_close_container (iter, &subiter))
01632     goto out;
01633 
01634   ret = TRUE;
01635  out:
01636   g_free (variant_sig);
01637   return ret;
01638 }
01639 
01640 static DBusGValueMarshalFunc
01641 get_type_marshaller (GType type)
01642 {
01643   DBusGTypeMarshalData *typedata;
01644 
01645   typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
01646   if (typedata == NULL)
01647     {
01648       if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
01649         return marshal_valuearray;
01650       if (dbus_g_type_is_collection (type))
01651         return marshal_collection;
01652       if (dbus_g_type_is_map (type))
01653         return marshal_map;
01654       if (dbus_g_type_is_struct (type))
01655         return marshal_struct;
01656 
01657       g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
01658       return NULL;
01659     }
01660   g_assert (typedata->vtable);
01661   return typedata->vtable->marshaller;
01662 }
01663 
01664 typedef struct
01665 {
01666   DBusMessageIter *iter;
01667   DBusGValueMarshalFunc marshaller;
01668   gboolean err;
01669 } DBusGValueCollectionMarshalData;
01670 
01671 static void
01672 collection_marshal_iterator (const GValue *eltval,
01673                              gpointer      user_data)
01674 {
01675   DBusGValueCollectionMarshalData *data = user_data;
01676 
01677   if (data->err)
01678     return;
01679 
01680   if (!data->marshaller (data->iter, eltval))
01681     data->err = TRUE;
01682 }
01683 
01684 static gboolean
01685 marshal_collection (DBusMessageIter         *iter,
01686                     const GValue            *value)
01687 {
01688   GType coltype;
01689   GType subtype;
01690   
01691   coltype = G_VALUE_TYPE (value);
01692   subtype = dbus_g_type_get_collection_specialization (coltype);
01693 
01694   if (_dbus_g_type_is_fixed (subtype))
01695     return marshal_collection_array (iter, value);
01696   else
01697     return marshal_collection_ptrarray (iter, value);
01698 }
01699 
01700 static gboolean
01701 marshal_collection_ptrarray (DBusMessageIter         *iter,
01702                              const GValue            *value)
01703 {
01704   GType coltype;
01705   GType elt_gtype;
01706   DBusGValueCollectionMarshalData data;
01707   DBusMessageIter subiter;
01708   char *elt_sig;
01709   
01710   coltype = G_VALUE_TYPE (value);
01711   elt_gtype = dbus_g_type_get_collection_specialization (coltype);
01712   data.marshaller = get_type_marshaller (elt_gtype);
01713   if (!data.marshaller)
01714     return FALSE;
01715 
01716   elt_sig = _dbus_gtype_to_signature (elt_gtype);
01717   if (!elt_sig)
01718     {
01719       g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
01720       return FALSE;
01721     }
01722 
01723   if (!dbus_message_iter_open_container (iter,
01724                                          DBUS_TYPE_ARRAY,
01725                                          elt_sig,
01726                                          &subiter))
01727     goto oom;
01728   g_free (elt_sig);
01729 
01730   data.iter = &subiter;
01731   data.err = FALSE;
01732 
01733   dbus_g_type_collection_value_iterate (value,
01734                                         collection_marshal_iterator,
01735                                         &data);
01736 
01737   if (!dbus_message_iter_close_container (iter, &subiter))
01738     goto oom;
01739   
01740   return !data.err;
01741  oom:
01742   g_error ("out of memory");
01743   return FALSE;
01744 }
01745 
01746 
01747 static gboolean
01748 marshal_collection_array (DBusMessageIter   *iter,
01749                           const GValue      *value)
01750 {
01751   GType elt_gtype;
01752   DBusMessageIter subiter;
01753   GArray *array;
01754   guint elt_size;
01755   char *subsignature_str;
01756 
01757   elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
01758   g_assert (_dbus_g_type_is_fixed (elt_gtype));
01759   subsignature_str = _dbus_gtype_to_signature (elt_gtype);
01760   if (!subsignature_str)
01761     {
01762       g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
01763       return FALSE;
01764     }
01765   
01766   elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
01767 
01768   array = g_value_get_boxed (value);
01769 
01770   if (!dbus_message_iter_open_container (iter,
01771                                          DBUS_TYPE_ARRAY,
01772                                          subsignature_str,
01773                                          &subiter))
01774     goto oom;
01775 
01776   /* TODO - This assumes that basic values are the same size
01777    * is this always true?  If it is we can probably avoid
01778    * a lot of the overhead in _marshal_basic_instance...
01779    */
01780   if (!array || !dbus_message_iter_append_fixed_array (&subiter,
01781                                              subsignature_str[0],
01782                                              &(array->data),
01783                                              array->len))
01784     goto oom;
01785 
01786   if (!dbus_message_iter_close_container (iter, &subiter))
01787     goto oom;
01788   g_free (subsignature_str);
01789   return TRUE;
01790  oom:
01791   g_error ("out of memory");
01792   return FALSE;
01793 }
01794 
01795 gboolean
01796 _dbus_gvalue_marshal (DBusMessageIter         *iter,
01797                      const GValue       *value)
01798 {
01799   GType gtype;
01800   DBusGValueMarshalFunc marshaller;
01801 
01802   gtype = G_VALUE_TYPE (value);
01803 
01804   marshaller = get_type_marshaller (gtype);
01805   if (marshaller == NULL)
01806     return FALSE;
01807   return marshaller (iter, value);
01808 }
01809 
01810 #ifdef DBUS_BUILD_TESTS
01811 
01812 static void
01813 assert_type_maps_to (GType gtype, const char *expected_sig)
01814 {
01815   char *sig;
01816   sig = _dbus_gtype_to_signature (gtype);
01817   g_assert (sig != NULL);
01818   g_assert (!strcmp (expected_sig, sig));
01819   g_free (sig);
01820 }
01821 
01822 static void
01823 assert_signature_maps_to (const char *sig, GType expected_gtype)
01824 {
01825   g_assert (_dbus_gtype_from_signature (sig, TRUE) == expected_gtype);
01826 }
01827 
01828 static void
01829 assert_bidirectional_mapping (GType gtype, const char *expected_sig)
01830 {
01831   assert_type_maps_to (gtype, expected_sig);
01832   assert_signature_maps_to (expected_sig, gtype);
01833 }
01834 
01842 gboolean
01843 _dbus_gvalue_test (const char *test_data_dir)
01844 {
01845   _dbus_g_value_types_init ();
01846   
01847   assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
01848   assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
01849   assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
01850 
01851   assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
01852                               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);
01853   assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
01854                                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
01855   assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
01856                                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
01857 
01858   assert_bidirectional_mapping (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID),
01859                                 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 );
01860   return TRUE;
01861 }
01862 
01863 #endif /* DBUS_BUILD_TESTS */

Generated on Mon Mar 17 16:28:50 2008 for D-BUSGLibBindings by  doxygen 1.5.1