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

Generated on Tue Feb 24 16:47:59 2009 for D-BUSGLibBindings by  doxygen 1.5.1