os/ossrv/ofdbus/dbus-glib/dbus/dbus-gvalue.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/ofdbus/dbus-glib/dbus/dbus-gvalue.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1908 @@
     1.4 +/* -*- mode: C; c-file-style: "gnu" -*- */
     1.5 +/* dbus-gvalue.c GValue to-from DBusMessageIter
     1.6 + *
     1.7 + * Copyright (C) 2004 Ximian, Inc.
     1.8 + * Copyright (C) 2005 Red Hat, Inc.
     1.9 + * Portion Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
    1.10 + * Licensed under the Academic Free License version 2.1
    1.11 + * 
    1.12 + * This program is free software; you can redistribute it and/or modify
    1.13 + * it under the terms of the GNU General Public License as published by
    1.14 + * the Free Software Foundation; either version 2 of the License, or
    1.15 + * (at your option) any later version.
    1.16 + *
    1.17 + * This program is distributed in the hope that it will be useful,
    1.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.20 + * GNU General Public License for more details.
    1.21 + * 
    1.22 + * You should have received a copy of the GNU General Public License
    1.23 + * along with this program; if not, write to the Free Software
    1.24 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "config.h"
    1.29 +#include "dbus-gtest.h"
    1.30 +#include "dbus-gvalue.h"
    1.31 +#include "dbus-gsignature.h"
    1.32 +#include "dbus-gobject.h"
    1.33 +#include "dbus-gvalue-utils.h"
    1.34 +#include "dbus/dbus-glib.h"
    1.35 +#include <string.h>
    1.36 +#include <glib.h>
    1.37 +#ifndef __SYMBIAN32__
    1.38 +#include <glib/gi18n.h>
    1.39 +#include <libintl.h>
    1.40 +#define _(x) dgettext (GETTEXT_PACKAGE, x)
    1.41 +#define N_(x) x
    1.42 +#else
    1.43 +
    1.44 +#define _(x) x
    1.45 +#define N_(x) x
    1.46 +#endif
    1.47 +
    1.48 +
    1.49 +#include "dbus/dbus-signature.h"
    1.50 +#ifdef __SYMBIAN32__
    1.51 +#include "libdbus_glib_wsd_solution.h"
    1.52 +#endif
    1.53 +
    1.54 +static gboolean demarshal_static_variant (DBusGValueMarshalCtx    *context,
    1.55 +					  DBusMessageIter         *iter,
    1.56 +					  GValue                  *value,
    1.57 +					  GError                 **error);
    1.58 +
    1.59 +
    1.60 +static gboolean marshal_basic                   (DBusMessageIter           *iter,
    1.61 +						 const GValue              *value);
    1.62 +static gboolean demarshal_basic                 (DBusGValueMarshalCtx      *context,
    1.63 +						 DBusMessageIter           *iter,
    1.64 +						 GValue                    *value,
    1.65 +						 GError                   **error);
    1.66 +static gboolean marshal_strv                    (DBusMessageIter           *iter,
    1.67 +						 const GValue              *value);
    1.68 +static gboolean demarshal_strv                  (DBusGValueMarshalCtx      *context,
    1.69 +						 DBusMessageIter           *iter,
    1.70 +						 GValue                    *value,
    1.71 +						 GError                   **error);
    1.72 +static gboolean marshal_valuearray              (DBusMessageIter           *iter,
    1.73 +						 const GValue              *value);
    1.74 +static gboolean demarshal_valuearray            (DBusGValueMarshalCtx      *context,
    1.75 +						 DBusMessageIter           *iter,
    1.76 +						 GValue                    *value,
    1.77 +						 GError                   **error);
    1.78 +static gboolean marshal_variant                 (DBusMessageIter           *iter,
    1.79 +						 const GValue              *value);
    1.80 +static gboolean demarshal_variant               (DBusGValueMarshalCtx      *context,
    1.81 +						 DBusMessageIter           *iter,
    1.82 +						 GValue                    *value,
    1.83 +						 GError                   **error);
    1.84 +static gboolean marshal_proxy                   (DBusMessageIter           *iter,
    1.85 +						 const GValue             *value);
    1.86 +static gboolean demarshal_proxy                 (DBusGValueMarshalCtx      *context,
    1.87 +						 DBusMessageIter           *iter,
    1.88 +						 GValue                    *value,
    1.89 +						 GError                   **error);
    1.90 +static gboolean marshal_object_path             (DBusMessageIter           *iter,
    1.91 +						 const GValue             *value);
    1.92 +static gboolean demarshal_object_path           (DBusGValueMarshalCtx      *context,
    1.93 +						 DBusMessageIter           *iter,
    1.94 +						 GValue                    *value,
    1.95 +						 GError                   **error);
    1.96 +static gboolean marshal_object                  (DBusMessageIter           *iter,
    1.97 +						 const GValue              *value);
    1.98 +static gboolean demarshal_object                (DBusGValueMarshalCtx      *context,
    1.99 +						 DBusMessageIter           *iter,
   1.100 +						 GValue                    *value,
   1.101 +						 GError                   **error);
   1.102 +static gboolean marshal_map                     (DBusMessageIter           *iter,
   1.103 +						 const GValue              *value);
   1.104 +static gboolean demarshal_map                   (DBusGValueMarshalCtx      *context,
   1.105 +						 DBusMessageIter           *iter,
   1.106 +						 GValue                    *value,
   1.107 +						 GError                   **error);
   1.108 +
   1.109 +static gboolean marshal_collection              (DBusMessageIter           *iter,
   1.110 +						 const GValue              *value);
   1.111 +static gboolean marshal_collection_ptrarray     (DBusMessageIter           *iter,
   1.112 +						 const GValue              *value);
   1.113 +static gboolean marshal_collection_array        (DBusMessageIter           *iter,
   1.114 +						 const GValue              *value);
   1.115 +static gboolean demarshal_collection            (DBusGValueMarshalCtx      *context,
   1.116 +						 DBusMessageIter           *iter,
   1.117 +						 GValue                    *value,
   1.118 +						 GError                   **error);
   1.119 +static gboolean demarshal_collection_ptrarray   (DBusGValueMarshalCtx      *context,
   1.120 +						 DBusMessageIter           *iter,
   1.121 +						 GValue                    *value,
   1.122 +						 GError                   **error);
   1.123 +static gboolean demarshal_collection_array      (DBusGValueMarshalCtx      *context,
   1.124 +						 DBusMessageIter           *iter,
   1.125 +						 GValue                    *value,
   1.126 +						 GError                   **error);
   1.127 +static gboolean marshal_struct                  (DBusMessageIter           *iter,
   1.128 +						 const GValue              *value);
   1.129 +static gboolean demarshal_struct                (DBusGValueMarshalCtx      *context,
   1.130 +						 DBusMessageIter           *iter,
   1.131 +						 GValue                    *value,
   1.132 +						 GError                   **error);
   1.133 +
   1.134 +
   1.135 +typedef gboolean (*DBusGValueMarshalFunc)       (DBusMessageIter           *iter,
   1.136 +						 const GValue              *value);
   1.137 +typedef gboolean (*DBusGValueDemarshalFunc)     (DBusGValueMarshalCtx      *context,
   1.138 +						 DBusMessageIter           *iter,
   1.139 +						 GValue                    *value,
   1.140 +						 GError                   **error);
   1.141 +
   1.142 +typedef struct {
   1.143 +  DBusGValueMarshalFunc       marshaller;
   1.144 +  DBusGValueDemarshalFunc     demarshaller;
   1.145 +} DBusGTypeMarshalVtable;
   1.146 +
   1.147 +typedef struct {
   1.148 +  const char                       *sig;
   1.149 +  const DBusGTypeMarshalVtable     *vtable;
   1.150 +} DBusGTypeMarshalData;
   1.151 +
   1.152 +
   1.153 +#if EMULATOR
   1.154 +GET_STATIC_VAR_FROM_TLS(quark,dbus_gvalue,GQuark )
   1.155 +#define quark (*GET_DBUS_WSD_VAR_NAME(quark,dbus_gvalue,s)())
   1.156 +#endif
   1.157 +
   1.158 +static GQuark
   1.159 +dbus_g_type_metadata_data_quark ()
   1.160 +{
   1.161 +#ifndef EMULATOR
   1.162 +  static GQuark quark;
   1.163 +#endif
   1.164 +  if (!quark)
   1.165 +    quark = g_quark_from_static_string ("DBusGTypeMetaData");
   1.166 +  
   1.167 +  return quark;
   1.168 +}
   1.169 +
   1.170 +static void
   1.171 +set_type_metadata (GType type, const DBusGTypeMarshalData *data)
   1.172 +{
   1.173 +  g_type_set_qdata (type, dbus_g_type_metadata_data_quark (), (gpointer) data);
   1.174 +}
   1.175 +
   1.176 +static void
   1.177 +register_basic (int typecode, const DBusGTypeMarshalData *typedata)
   1.178 +{
   1.179 +  set_type_metadata (_dbus_gtype_from_basic_typecode (typecode), typedata);
   1.180 +}
   1.181 +
   1.182 +#if EMULATOR
   1.183 +GET_STATIC_VAR_FROM_TLS(types_initialized,dbus_gvalue,gboolean )
   1.184 +#define types_initialized (*GET_DBUS_WSD_VAR_NAME(types_initialized,dbus_gvalue,s)())
   1.185 +
   1.186 +#endif
   1.187 +
   1.188 +void
   1.189 +_dbus_g_value_types_init (void)
   1.190 +{
   1.191 + 
   1.192 +#ifndef EMULATOR
   1.193 +   static gboolean types_initialized;
   1.194 +#endif
   1.195 +
   1.196 +  static const DBusGTypeMarshalVtable basic_vtable = {
   1.197 +    marshal_basic,
   1.198 +    demarshal_basic
   1.199 +  };
   1.200 +
   1.201 +  if (types_initialized)
   1.202 +    return;
   1.203 +
   1.204 +  dbus_g_type_specialized_init ();
   1.205 +  _dbus_g_type_specialized_builtins_init ();
   1.206 +
   1.207 +  /* Register basic types */
   1.208 +  {
   1.209 +    static const DBusGTypeMarshalData typedata = {
   1.210 +      DBUS_TYPE_BOOLEAN_AS_STRING,
   1.211 +      &basic_vtable,
   1.212 +    };
   1.213 +    register_basic (DBUS_TYPE_BOOLEAN, &typedata);
   1.214 +  }
   1.215 +  {
   1.216 +    static const DBusGTypeMarshalData typedata = {
   1.217 +      DBUS_TYPE_BYTE_AS_STRING,
   1.218 +      &basic_vtable,
   1.219 +    };
   1.220 +    register_basic (DBUS_TYPE_BYTE, &typedata);
   1.221 +  }
   1.222 +  {
   1.223 +    static const DBusGTypeMarshalData typedata = {
   1.224 +      DBUS_TYPE_INT16_AS_STRING,
   1.225 +      &basic_vtable,
   1.226 +    };
   1.227 +    register_basic (DBUS_TYPE_INT16, &typedata);
   1.228 +  }
   1.229 +  {
   1.230 +    static const DBusGTypeMarshalData typedata = {
   1.231 +      DBUS_TYPE_UINT16_AS_STRING,
   1.232 +      &basic_vtable,
   1.233 +    };
   1.234 +    register_basic (DBUS_TYPE_UINT16, &typedata);
   1.235 +  }
   1.236 +  {
   1.237 +    static const DBusGTypeMarshalData typedata = {
   1.238 +      DBUS_TYPE_UINT32_AS_STRING,
   1.239 +      &basic_vtable,
   1.240 +    };
   1.241 +    register_basic (DBUS_TYPE_UINT32, &typedata);
   1.242 +  }
   1.243 +  {
   1.244 +    static const DBusGTypeMarshalData typedata = {
   1.245 +      DBUS_TYPE_INT32_AS_STRING,
   1.246 +      &basic_vtable,
   1.247 +    };
   1.248 +    register_basic (DBUS_TYPE_INT32, &typedata);
   1.249 +  }
   1.250 +  {
   1.251 +    static const DBusGTypeMarshalData typedata = {
   1.252 +      DBUS_TYPE_UINT64_AS_STRING,
   1.253 +      &basic_vtable,
   1.254 +    };
   1.255 +    register_basic (DBUS_TYPE_UINT64, &typedata);
   1.256 +  }
   1.257 +  {
   1.258 +    static const DBusGTypeMarshalData typedata = {
   1.259 +      DBUS_TYPE_INT64_AS_STRING,
   1.260 +      &basic_vtable,
   1.261 +    };
   1.262 +    register_basic (DBUS_TYPE_INT64, &typedata);
   1.263 +  }
   1.264 +  {
   1.265 +    static const DBusGTypeMarshalData typedata = {
   1.266 +      DBUS_TYPE_DOUBLE_AS_STRING,
   1.267 +      &basic_vtable,
   1.268 +    };
   1.269 +    register_basic (DBUS_TYPE_DOUBLE, &typedata);
   1.270 +  }
   1.271 +  {
   1.272 +    static const DBusGTypeMarshalData typedata = {
   1.273 +      DBUS_TYPE_STRING_AS_STRING,
   1.274 +      &basic_vtable,
   1.275 +    };
   1.276 +    register_basic (DBUS_TYPE_STRING, &typedata);
   1.277 +  }
   1.278 +  /* fundamental GTypes that don't map 1:1 with D-BUS types */
   1.279 +  {
   1.280 +    static const DBusGTypeMarshalData typedata = {
   1.281 +      DBUS_TYPE_BYTE_AS_STRING,
   1.282 +      &basic_vtable,
   1.283 +    };
   1.284 +    set_type_metadata (G_TYPE_CHAR, &typedata);
   1.285 +  }
   1.286 +  {
   1.287 +    static const DBusGTypeMarshalData typedata = {
   1.288 +      DBUS_TYPE_INT32_AS_STRING,
   1.289 +      &basic_vtable,
   1.290 +    };
   1.291 +    set_type_metadata (G_TYPE_LONG, &typedata);
   1.292 +  }
   1.293 +  {
   1.294 +    static const DBusGTypeMarshalData typedata = {
   1.295 +      DBUS_TYPE_UINT32_AS_STRING,
   1.296 +      &basic_vtable,
   1.297 +    };
   1.298 +    set_type_metadata (G_TYPE_ULONG, &typedata);
   1.299 +  }
   1.300 +  {
   1.301 +    static const DBusGTypeMarshalData typedata = {
   1.302 +      DBUS_TYPE_DOUBLE_AS_STRING,
   1.303 +      &basic_vtable,
   1.304 +    };
   1.305 +    set_type_metadata (G_TYPE_FLOAT, &typedata);
   1.306 +  }
   1.307 +
   1.308 +  /* Register complex types with builtin GType mappings */
   1.309 +  {
   1.310 +    static const DBusGTypeMarshalVtable vtable = {
   1.311 +      marshal_variant,
   1.312 +      demarshal_variant
   1.313 +    };
   1.314 +    static const DBusGTypeMarshalData typedata = {
   1.315 +      DBUS_TYPE_VARIANT_AS_STRING,
   1.316 +      &vtable
   1.317 +    };
   1.318 +    set_type_metadata (G_TYPE_VALUE, &typedata);
   1.319 +  };
   1.320 +  {
   1.321 +    static const DBusGTypeMarshalVtable vtable = {
   1.322 +      marshal_strv,
   1.323 +      demarshal_strv
   1.324 +    };
   1.325 +    static const DBusGTypeMarshalData typedata = {
   1.326 +      DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
   1.327 +      &vtable
   1.328 +    };
   1.329 +    set_type_metadata (G_TYPE_STRV, &typedata);
   1.330 +  };
   1.331 +
   1.332 +
   1.333 +  /* Register some types specific to the D-BUS GLib bindings */
   1.334 +  {
   1.335 +    static const DBusGTypeMarshalVtable vtable = {
   1.336 +      marshal_proxy,
   1.337 +      demarshal_proxy
   1.338 +    };
   1.339 +    static const DBusGTypeMarshalData typedata = {
   1.340 +      DBUS_TYPE_OBJECT_PATH_AS_STRING,
   1.341 +      &vtable
   1.342 +    };
   1.343 +    set_type_metadata (DBUS_TYPE_G_PROXY, &typedata);
   1.344 +  }
   1.345 +
   1.346 +  {
   1.347 +    static const DBusGTypeMarshalVtable vtable = {
   1.348 +      marshal_object_path,
   1.349 +      demarshal_object_path
   1.350 +    };
   1.351 +    static const DBusGTypeMarshalData typedata = {
   1.352 +      DBUS_TYPE_OBJECT_PATH_AS_STRING,
   1.353 +      &vtable
   1.354 +    };
   1.355 +    set_type_metadata (DBUS_TYPE_G_OBJECT_PATH, &typedata);
   1.356 +  }
   1.357 +
   1.358 +  {
   1.359 +    static const DBusGTypeMarshalVtable vtable = {
   1.360 +      marshal_object,
   1.361 +      demarshal_object
   1.362 +    };
   1.363 +    static const DBusGTypeMarshalData typedata = {
   1.364 +      DBUS_TYPE_OBJECT_PATH_AS_STRING,
   1.365 +      &vtable
   1.366 +    };
   1.367 +    set_type_metadata (G_TYPE_OBJECT, &typedata);
   1.368 +  }
   1.369 +
   1.370 +  types_initialized = TRUE;
   1.371 +}
   1.372 +
   1.373 +/**
   1.374 + * Get the GLib type ID for a DBusGObjectPath boxed type.
   1.375 + *
   1.376 + * Returns: GLib type
   1.377 + */
   1.378 + #if EMULATOR
   1.379 +GET_STATIC_VAR_FROM_TLS(type_id,dbus_gvalue,GType )
   1.380 +#define type_id (*GET_DBUS_WSD_VAR_NAME(type_id,dbus_gvalue,s)())
   1.381 +#endif
   1.382 +
   1.383 + 	#ifdef __SYMBIAN32__
   1.384 +	EXPORT_C
   1.385 +	#endif
   1.386 +GType
   1.387 +dbus_g_object_path_get_g_type (void)
   1.388 +{
   1.389 +  #ifndef EMULATOR
   1.390 +  static GType type_id = 0;
   1.391 +#endif
   1.392 +
   1.393 +
   1.394 +
   1.395 +  if (!type_id)
   1.396 +    type_id = g_boxed_type_register_static ("DBusGObjectPath",
   1.397 +					    (GBoxedCopyFunc) g_strdup,
   1.398 +					    (GBoxedFreeFunc) g_free);
   1.399 +  return type_id;
   1.400 +}
   1.401 +
   1.402 +
   1.403 +char *
   1.404 +_dbus_gtype_to_signature (GType gtype)
   1.405 +{
   1.406 +  char *ret;
   1.407 +  DBusGTypeMarshalData *typedata;
   1.408 +
   1.409 +  if (dbus_g_type_is_collection (gtype))
   1.410 +    {
   1.411 +      GType elt_gtype;
   1.412 +      char *subsig;
   1.413 +
   1.414 +      elt_gtype = dbus_g_type_get_collection_specialization (gtype);
   1.415 +      subsig = _dbus_gtype_to_signature (elt_gtype);
   1.416 +      ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING, subsig, NULL);
   1.417 +      g_free (subsig);
   1.418 +    }
   1.419 +  else if (dbus_g_type_is_map (gtype))
   1.420 +    {
   1.421 +      GType key_gtype;
   1.422 +      GType val_gtype;
   1.423 +      char *key_subsig;
   1.424 +      char *val_subsig;
   1.425 +
   1.426 +      key_gtype = dbus_g_type_get_map_key_specialization (gtype);
   1.427 +      val_gtype = dbus_g_type_get_map_value_specialization (gtype);
   1.428 +      key_subsig = _dbus_gtype_to_signature (key_gtype);
   1.429 +      val_subsig = _dbus_gtype_to_signature (val_gtype);
   1.430 +      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);
   1.431 +      g_free (key_subsig);
   1.432 +      g_free (val_subsig);
   1.433 +    }
   1.434 +  else if (dbus_g_type_is_struct (gtype))
   1.435 +    {
   1.436 +      guint i, size;
   1.437 +      GString *sig;
   1.438 +      size = dbus_g_type_get_struct_size (gtype);
   1.439 +      sig = g_string_sized_new (size+2); /*some sensible starting size*/
   1.440 +      g_string_assign (sig, DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
   1.441 +      for (i = 0; i < size; i++)
   1.442 +        {
   1.443 +          gchar *subsig;
   1.444 +          subsig = _dbus_gtype_to_signature (
   1.445 +              dbus_g_type_get_struct_member_type (gtype, i));
   1.446 +          g_string_append (sig, subsig);
   1.447 +          g_free (subsig);
   1.448 +        }
   1.449 +      g_string_append (sig, DBUS_STRUCT_END_CHAR_AS_STRING);
   1.450 +      ret = g_string_free (sig, FALSE);
   1.451 +    }
   1.452 +  else
   1.453 +    {
   1.454 +      typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ());
   1.455 +      if (typedata == NULL)
   1.456 +	return NULL;
   1.457 +      ret = g_strdup (typedata->sig);
   1.458 +    }
   1.459 +  return ret;
   1.460 +}
   1.461 +
   1.462 +char *
   1.463 +_dbus_gvalue_to_signature (const GValue *val)
   1.464 +{
   1.465 +  GType gtype;
   1.466 +
   1.467 +  gtype = G_VALUE_TYPE (val);
   1.468 +  if (g_type_is_a (gtype, G_TYPE_VALUE_ARRAY))
   1.469 +    {
   1.470 +      GString *str;
   1.471 +      guint i;
   1.472 +      GValueArray *array;
   1.473 +
   1.474 +      array = g_value_get_boxed (val);
   1.475 +      
   1.476 +      str = g_string_new (DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
   1.477 +      for (i = 0; i < array->n_values; i++)
   1.478 +	{
   1.479 +	  char *sig;
   1.480 +	  sig = _dbus_gvalue_to_signature (g_value_array_get_nth (array, i));
   1.481 +	  g_string_append (str, sig);
   1.482 +	  g_free (sig);
   1.483 +	}
   1.484 +      g_string_append (str, DBUS_STRUCT_END_CHAR_AS_STRING);
   1.485 +      
   1.486 +      return g_string_free (str, FALSE);
   1.487 +    }
   1.488 +  else
   1.489 +    return _dbus_gtype_to_signature (gtype);
   1.490 +}
   1.491 +
   1.492 +static gboolean
   1.493 +demarshal_basic (DBusGValueMarshalCtx      *context,
   1.494 +		 DBusMessageIter           *iter,
   1.495 +		 GValue                    *value,
   1.496 +		 GError                   **error)
   1.497 +{
   1.498 +  int current_type;
   1.499 +  
   1.500 +  current_type = dbus_message_iter_get_arg_type (iter);
   1.501 +  g_assert (dbus_type_is_basic (current_type));
   1.502 +
   1.503 +  switch (current_type)
   1.504 +    {
   1.505 +    case DBUS_TYPE_BOOLEAN:
   1.506 +      {
   1.507 +	dbus_bool_t bool;
   1.508 +	dbus_message_iter_get_basic (iter, &bool);
   1.509 +	g_value_set_boolean (value, bool);
   1.510 +	return TRUE;
   1.511 +      }
   1.512 +    case DBUS_TYPE_BYTE:
   1.513 +      {
   1.514 +	unsigned char byte;
   1.515 +	dbus_message_iter_get_basic (iter, &byte);
   1.516 +	g_value_set_uchar (value, byte);
   1.517 +	return TRUE;
   1.518 +      }
   1.519 +    case DBUS_TYPE_INT32:
   1.520 +      {
   1.521 +	dbus_int32_t intval;
   1.522 +	dbus_message_iter_get_basic (iter, &intval);
   1.523 +	g_value_set_int (value, intval);
   1.524 +	return TRUE;
   1.525 +      }
   1.526 +    case DBUS_TYPE_UINT32:
   1.527 +      {
   1.528 +	dbus_uint32_t intval;
   1.529 +	dbus_message_iter_get_basic (iter, &intval);
   1.530 +	g_value_set_uint (value, intval);
   1.531 +	return TRUE;
   1.532 +      }
   1.533 +    case DBUS_TYPE_INT64:
   1.534 +      {
   1.535 +	dbus_int64_t intval;
   1.536 +	dbus_message_iter_get_basic (iter, &intval);
   1.537 +	g_value_set_int64 (value, intval);
   1.538 +	return TRUE;
   1.539 +      }
   1.540 +    case DBUS_TYPE_UINT64:
   1.541 +      {
   1.542 +	dbus_uint64_t intval;
   1.543 +	dbus_message_iter_get_basic (iter, &intval);
   1.544 +	g_value_set_uint64 (value, intval);
   1.545 +	return TRUE;
   1.546 +      }
   1.547 +    case DBUS_TYPE_DOUBLE:
   1.548 +      {
   1.549 +	double dval;
   1.550 +	dbus_message_iter_get_basic (iter, &dval);
   1.551 +	g_value_set_double (value, dval);
   1.552 +	return TRUE;
   1.553 +      }
   1.554 +    case DBUS_TYPE_INT16:
   1.555 +      {
   1.556 +        dbus_int16_t v;
   1.557 +        dbus_message_iter_get_basic (iter, &v);
   1.558 +        g_value_set_int (value, v);
   1.559 +	return TRUE;
   1.560 +      }
   1.561 +    case DBUS_TYPE_UINT16:
   1.562 +      {
   1.563 +        dbus_uint16_t v;
   1.564 +        dbus_message_iter_get_basic (iter, &v);
   1.565 +        g_value_set_uint (value, v);
   1.566 +	return TRUE;
   1.567 +      }
   1.568 +    case DBUS_TYPE_STRING:
   1.569 +      {
   1.570 +        const char *s;
   1.571 +        dbus_message_iter_get_basic (iter, &s);
   1.572 +	g_value_set_string (value, s);
   1.573 +	return TRUE;
   1.574 +      }
   1.575 +    default:
   1.576 +      g_assert_not_reached ();
   1.577 +      return FALSE;
   1.578 +    }
   1.579 +}
   1.580 +
   1.581 +static gboolean
   1.582 +demarshal_static_variant (DBusGValueMarshalCtx    *context,
   1.583 +			  DBusMessageIter         *iter,
   1.584 +			  GValue                  *value,
   1.585 +			  GError                 **error)
   1.586 +{
   1.587 +  char *sig;
   1.588 +  int current_type;
   1.589 +  DBusMessageIter subiter;
   1.590 +  GType variant_type;
   1.591 +
   1.592 +  current_type = dbus_message_iter_get_arg_type (iter);
   1.593 +  dbus_message_iter_recurse (iter, &subiter);
   1.594 +  sig = dbus_message_iter_get_signature (&subiter);
   1.595 +
   1.596 +  variant_type = _dbus_gtype_from_signature (sig, context->proxy != NULL);
   1.597 +  if (variant_type != G_TYPE_INVALID)
   1.598 +    {
   1.599 +      g_value_init (value, variant_type);
   1.600 +
   1.601 +      if (!_dbus_gvalue_demarshal (context, &subiter, value, error))
   1.602 +	{
   1.603 +	  dbus_free (sig);
   1.604 +	  return FALSE;
   1.605 +	}
   1.606 +    }
   1.607 +  dbus_free (sig);
   1.608 +  return TRUE;
   1.609 +}
   1.610 +
   1.611 +static gboolean
   1.612 +demarshal_variant (DBusGValueMarshalCtx    *context,
   1.613 +		   DBusMessageIter         *iter,
   1.614 +		   GValue                  *value,
   1.615 +		   GError                 **error)
   1.616 +
   1.617 +{
   1.618 +  GValue *variant_val;
   1.619 +  variant_val = g_new0 (GValue, 1);
   1.620 +
   1.621 +  if (!demarshal_static_variant (context, iter, variant_val, error))
   1.622 +    return FALSE;
   1.623 +  
   1.624 +  g_value_set_boxed_take_ownership (value, variant_val);
   1.625 +  return TRUE;
   1.626 +}
   1.627 +
   1.628 +static gboolean
   1.629 +demarshal_proxy (DBusGValueMarshalCtx    *context,
   1.630 +		 DBusMessageIter         *iter,
   1.631 +		 GValue                  *value,
   1.632 +		 GError                 **error)
   1.633 +{
   1.634 +  DBusGProxy *new_proxy;
   1.635 +  const char *objpath;
   1.636 +  int current_type;
   1.637 +
   1.638 +  current_type = dbus_message_iter_get_arg_type (iter);
   1.639 +  if (current_type != DBUS_TYPE_OBJECT_PATH)
   1.640 +    {
   1.641 +      g_set_error (error,
   1.642 +		   DBUS_GERROR,
   1.643 +		   DBUS_GERROR_INVALID_ARGS,
   1.644 +		   _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
   1.645 +      return FALSE;
   1.646 +    }
   1.647 +
   1.648 +  g_assert (context->proxy != NULL);
   1.649 +  
   1.650 +  dbus_message_iter_get_basic (iter, &objpath);
   1.651 +
   1.652 +  new_proxy = dbus_g_proxy_new_from_proxy (context->proxy, NULL, objpath);
   1.653 +  g_value_set_object_take_ownership (value, new_proxy);
   1.654 +
   1.655 +  return TRUE;
   1.656 +}
   1.657 +
   1.658 +static gboolean
   1.659 +demarshal_object_path (DBusGValueMarshalCtx    *context,
   1.660 +		       DBusMessageIter         *iter,
   1.661 +		       GValue                  *value,
   1.662 +		       GError                 **error)
   1.663 +{
   1.664 +  const char *objpath;
   1.665 +  int current_type;
   1.666 +
   1.667 +  current_type = dbus_message_iter_get_arg_type (iter);
   1.668 +  if (current_type != DBUS_TYPE_OBJECT_PATH)
   1.669 +    {
   1.670 +      g_set_error (error,
   1.671 +		   DBUS_GERROR,
   1.672 +		   DBUS_GERROR_INVALID_ARGS,
   1.673 +		   _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
   1.674 +      return FALSE;
   1.675 +    }
   1.676 +
   1.677 +  dbus_message_iter_get_basic (iter, &objpath);
   1.678 +
   1.679 +  g_value_set_boxed_take_ownership (value, g_strdup (objpath));
   1.680 +
   1.681 +  return TRUE;
   1.682 +}
   1.683 +
   1.684 +static gboolean
   1.685 +demarshal_object (DBusGValueMarshalCtx    *context,
   1.686 +		  DBusMessageIter         *iter,
   1.687 +		  GValue                  *value,
   1.688 +		  GError                 **error)
   1.689 +{
   1.690 +  const char *objpath;
   1.691 +  int current_type;
   1.692 +  GObject *obj;
   1.693 +
   1.694 +  current_type = dbus_message_iter_get_arg_type (iter);
   1.695 +  if (current_type != DBUS_TYPE_OBJECT_PATH)
   1.696 +    {
   1.697 +      g_set_error (error,
   1.698 +		   DBUS_GERROR,
   1.699 +		   DBUS_GERROR_INVALID_ARGS,
   1.700 +		   _("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
   1.701 +      return FALSE;
   1.702 +    }
   1.703 +  g_assert (context->proxy == NULL);
   1.704 +
   1.705 +  dbus_message_iter_get_basic (iter, &objpath);
   1.706 +
   1.707 +  obj = dbus_g_connection_lookup_g_object (context->gconnection, objpath);
   1.708 +  if (obj == NULL)
   1.709 +    {
   1.710 +      g_set_error (error,
   1.711 +		   DBUS_GERROR,
   1.712 +		   DBUS_GERROR_INVALID_ARGS,
   1.713 +		   _("Unregistered object at path '%s'"),
   1.714 +		   objpath);
   1.715 +      return FALSE;
   1.716 +    }
   1.717 +  g_value_set_object (value, obj);
   1.718 +
   1.719 +  return TRUE;
   1.720 +}
   1.721 +
   1.722 +static gboolean
   1.723 +demarshal_strv (DBusGValueMarshalCtx    *context,
   1.724 +		DBusMessageIter         *iter,
   1.725 +		GValue                  *value,
   1.726 +		GError                 **error)
   1.727 +{
   1.728 +  DBusMessageIter subiter;
   1.729 +  int current_type;
   1.730 +  char **ret;
   1.731 +  int len;
   1.732 +  int i;
   1.733 +
   1.734 +  current_type = dbus_message_iter_get_arg_type (iter);
   1.735 +  if (current_type != DBUS_TYPE_ARRAY)
   1.736 +    {
   1.737 +      g_set_error (error,
   1.738 +		   DBUS_GERROR,
   1.739 +		   DBUS_GERROR_INVALID_ARGS,
   1.740 +		   _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
   1.741 +      return FALSE;
   1.742 +    }
   1.743 +
   1.744 +  dbus_message_iter_recurse (iter, &subiter);
   1.745 +
   1.746 +  current_type = dbus_message_iter_get_arg_type (&subiter);
   1.747 +  if (current_type != DBUS_TYPE_INVALID
   1.748 +      && current_type != DBUS_TYPE_STRING)
   1.749 +    {
   1.750 +      g_set_error (error,
   1.751 +		   DBUS_GERROR,
   1.752 +		   DBUS_GERROR_INVALID_ARGS,
   1.753 +		   _("Expected D-BUS string, got type code \'%c\'"), (guchar) current_type);
   1.754 +      return FALSE;
   1.755 +    }
   1.756 +
   1.757 +  len = dbus_message_iter_get_array_len (&subiter);
   1.758 +  g_assert (len >= 0);
   1.759 +  ret = g_malloc (sizeof (char *) * (len + 1));
   1.760 +  
   1.761 +  i = 0;
   1.762 +  while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
   1.763 +    {
   1.764 +      g_assert (i < len);
   1.765 +      g_assert (current_type == DBUS_TYPE_STRING);
   1.766 +      
   1.767 +      dbus_message_iter_get_basic (&subiter, &(ret[i]));
   1.768 +      ret[i] = g_strdup (ret[i]);
   1.769 +
   1.770 +      dbus_message_iter_next (&subiter);
   1.771 +      i++;
   1.772 +    }
   1.773 +  ret[i] = NULL; 
   1.774 +  g_value_set_boxed_take_ownership (value, ret);
   1.775 +  
   1.776 +  return TRUE;
   1.777 +}
   1.778 +
   1.779 +static gboolean
   1.780 +demarshal_valuearray (DBusGValueMarshalCtx    *context,
   1.781 +		      DBusMessageIter         *iter,
   1.782 +		      GValue                  *value,
   1.783 +		      GError                 **error)
   1.784 +{
   1.785 +  int current_type;
   1.786 +  GValueArray *ret;
   1.787 +  DBusMessageIter subiter;
   1.788 +
   1.789 +  current_type = dbus_message_iter_get_arg_type (iter);
   1.790 +  if (current_type != DBUS_TYPE_STRUCT)
   1.791 +    {
   1.792 +      g_set_error (error,
   1.793 +		   DBUS_GERROR,
   1.794 +		   DBUS_GERROR_INVALID_ARGS,
   1.795 +		   _("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type);
   1.796 +      return FALSE;
   1.797 +    }
   1.798 +
   1.799 +  dbus_message_iter_recurse (iter, &subiter);
   1.800 +
   1.801 +  ret = g_value_array_new (12);
   1.802 +
   1.803 +  while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
   1.804 +    {
   1.805 +      GValue *val;
   1.806 +      GType elt_type; 
   1.807 +      char *current_sig;
   1.808 +
   1.809 +      g_value_array_append (ret, NULL);
   1.810 +      val = g_value_array_get_nth (ret, ret->n_values - 1);
   1.811 +
   1.812 +      current_sig = dbus_message_iter_get_signature (&subiter);
   1.813 +      elt_type = _dbus_gtype_from_signature (current_sig, TRUE);
   1.814 +
   1.815 +      dbus_free (current_sig);
   1.816 +      if (elt_type == G_TYPE_INVALID)
   1.817 +	{
   1.818 +	  g_value_array_free (ret);
   1.819 +	  g_set_error (error,
   1.820 +		       DBUS_GERROR,
   1.821 +		       DBUS_GERROR_INVALID_ARGS,
   1.822 +		       _("Couldn't demarshal argument with signature \"%s\""), current_sig);
   1.823 +	  return FALSE;
   1.824 +	}
   1.825 +      
   1.826 +      g_value_init (val, elt_type);
   1.827 +
   1.828 +      if (!_dbus_gvalue_demarshal (context, &subiter, val, error))
   1.829 +	{
   1.830 +	  g_value_array_free (ret);
   1.831 +	  return FALSE;
   1.832 +	}
   1.833 +
   1.834 +      dbus_message_iter_next (&subiter);
   1.835 +    }
   1.836 +
   1.837 +  g_value_set_boxed_take_ownership (value, ret);
   1.838 +  
   1.839 +  return TRUE;
   1.840 +}
   1.841 +
   1.842 +static gboolean
   1.843 +demarshal_map (DBusGValueMarshalCtx    *context,
   1.844 +	       DBusMessageIter         *iter,
   1.845 +	       GValue                  *value,
   1.846 +	       GError                 **error)
   1.847 +{
   1.848 +  GType gtype;
   1.849 +  DBusMessageIter subiter;
   1.850 +  int current_type;
   1.851 +  gpointer ret;
   1.852 +  GType key_gtype;
   1.853 +  GType value_gtype;
   1.854 +  DBusGTypeSpecializedAppendContext appendctx;
   1.855 +
   1.856 +  current_type = dbus_message_iter_get_arg_type (iter);
   1.857 +  if (current_type != DBUS_TYPE_ARRAY)
   1.858 +    {
   1.859 +      g_set_error (error,
   1.860 +		   DBUS_GERROR,
   1.861 +		   DBUS_GERROR_INVALID_ARGS,
   1.862 +		   _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
   1.863 +      return FALSE;
   1.864 +    }
   1.865 +
   1.866 +  gtype = G_VALUE_TYPE (value);
   1.867 +
   1.868 +  dbus_message_iter_recurse (iter, &subiter);
   1.869 +
   1.870 +  current_type = dbus_message_iter_get_arg_type (&subiter);
   1.871 +  if (current_type != DBUS_TYPE_INVALID
   1.872 +      && current_type != DBUS_TYPE_DICT_ENTRY)
   1.873 +    {
   1.874 +      g_set_error (error,
   1.875 +		   DBUS_GERROR,
   1.876 +		   DBUS_GERROR_INVALID_ARGS,
   1.877 +		   _("Expected D-BUS dict entry, got type code \'%c\'"), (guchar) current_type);
   1.878 +      return FALSE;
   1.879 +    }
   1.880 +
   1.881 +  key_gtype = dbus_g_type_get_map_key_specialization (gtype);
   1.882 +  value_gtype = dbus_g_type_get_map_value_specialization (gtype);
   1.883 +
   1.884 +  ret = dbus_g_type_specialized_construct (gtype);
   1.885 +  g_value_set_boxed_take_ownership (value, ret);
   1.886 +
   1.887 +  dbus_g_type_specialized_init_append (value, &appendctx);
   1.888 +
   1.889 +  while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
   1.890 +    {
   1.891 +      DBusMessageIter entry_iter;
   1.892 +      GValue key_value = {0,};
   1.893 +      GValue value_value = {0,};
   1.894 +
   1.895 +      current_type = dbus_message_iter_get_arg_type (&subiter);
   1.896 +      g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
   1.897 +
   1.898 +      dbus_message_iter_recurse (&subiter, &entry_iter);
   1.899 +
   1.900 +      g_value_init (&key_value, key_gtype);
   1.901 +      if (!_dbus_gvalue_demarshal (context,
   1.902 +				  &entry_iter,
   1.903 +				  &key_value,
   1.904 +				  error))
   1.905 +	return FALSE;
   1.906 +
   1.907 +      dbus_message_iter_next (&entry_iter);
   1.908 +
   1.909 +      g_value_init (&value_value, value_gtype);
   1.910 +      if (!_dbus_gvalue_demarshal (context,
   1.911 +				  &entry_iter,
   1.912 +				  &value_value,
   1.913 +				  error))
   1.914 +	return FALSE;
   1.915 +
   1.916 +      dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
   1.917 +      /* Ownership of values passes to map, don't unset */
   1.918 +
   1.919 +      dbus_message_iter_next (&subiter);
   1.920 +    }
   1.921 +  
   1.922 +  return TRUE;
   1.923 +}
   1.924 +
   1.925 +static gboolean
   1.926 +demarshal_struct (DBusGValueMarshalCtx    *context,
   1.927 +                  DBusMessageIter         *iter,
   1.928 +                  GValue                  *value,
   1.929 +                  GError                 **error)
   1.930 +{
   1.931 +  int current_type;
   1.932 +  DBusMessageIter subiter;
   1.933 +  guint i, size;
   1.934 +  GValue val = {0,};
   1.935 +  GType elt_type;
   1.936 +
   1.937 +  current_type = dbus_message_iter_get_arg_type (iter);
   1.938 +  if (current_type != DBUS_TYPE_STRUCT)
   1.939 +    {
   1.940 +      g_set_error (error,
   1.941 +                   DBUS_GERROR,
   1.942 +                   DBUS_GERROR_INVALID_ARGS,
   1.943 +                   _("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type);
   1.944 +      return FALSE;
   1.945 +    }
   1.946 +
   1.947 +  dbus_message_iter_recurse (iter, &subiter);
   1.948 +
   1.949 +  g_value_set_boxed_take_ownership (value,
   1.950 +    dbus_g_type_specialized_construct (G_VALUE_TYPE (value)));
   1.951 +
   1.952 +  size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value));
   1.953 +
   1.954 +  for (i=0; i < size; i++)
   1.955 +    {
   1.956 +
   1.957 +      elt_type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE(value), i);
   1.958 +      if (elt_type == G_TYPE_INVALID)
   1.959 +        {
   1.960 +          g_value_unset (value);
   1.961 +          g_set_error (error,
   1.962 +                       DBUS_GERROR,
   1.963 +                       DBUS_GERROR_INVALID_ARGS,
   1.964 +                       _("Couldn't demarshal argument, "
   1.965 +                         "struct type %s has no member %d"),
   1.966 +                       g_type_name (G_VALUE_TYPE(value)), i);
   1.967 +          return FALSE;
   1.968 +        }
   1.969 +
   1.970 +      g_value_init (&val, elt_type);
   1.971 +
   1.972 +      if (!_dbus_gvalue_demarshal (context, &subiter, &val, error))
   1.973 +        {
   1.974 +          g_value_unset (&val);
   1.975 +          g_value_unset (value);
   1.976 +          return FALSE;
   1.977 +        }
   1.978 +      if (!dbus_g_type_struct_set_member (value, i, &val))
   1.979 +        {
   1.980 +          g_value_unset (&val);
   1.981 +          g_value_unset (value);
   1.982 +          return FALSE;
   1.983 +        }
   1.984 +
   1.985 +      dbus_message_iter_next (&subiter);
   1.986 +      g_value_unset (&val);
   1.987 +    }
   1.988 +
   1.989 +  g_assert (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_INVALID);
   1.990 +
   1.991 +  return TRUE;
   1.992 +}
   1.993 +
   1.994 +
   1.995 +static DBusGValueDemarshalFunc
   1.996 +get_type_demarshaller (GType type)
   1.997 +{
   1.998 +  DBusGTypeMarshalData *typedata;
   1.999 +
  1.1000 +  typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
  1.1001 +  if (typedata == NULL)
  1.1002 +    {
  1.1003 +      if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
  1.1004 +	return demarshal_valuearray;
  1.1005 +      if (dbus_g_type_is_collection (type))
  1.1006 +	return demarshal_collection;
  1.1007 +      if (dbus_g_type_is_map (type))
  1.1008 +	return demarshal_map;
  1.1009 +      if (dbus_g_type_is_struct (type))
  1.1010 +        return demarshal_struct;
  1.1011 +
  1.1012 +      g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
  1.1013 +      return NULL;
  1.1014 +    }
  1.1015 +  g_assert (typedata->vtable);
  1.1016 +  return typedata->vtable->demarshaller;
  1.1017 +}
  1.1018 +
  1.1019 +static gboolean
  1.1020 +demarshal_collection (DBusGValueMarshalCtx    *context,
  1.1021 +		      DBusMessageIter         *iter,
  1.1022 +		      GValue                  *value,
  1.1023 +		      GError                 **error)
  1.1024 +{
  1.1025 +  GType coltype;
  1.1026 +  GType subtype;
  1.1027 +  
  1.1028 +  coltype = G_VALUE_TYPE (value);
  1.1029 +  subtype = dbus_g_type_get_collection_specialization (coltype);
  1.1030 +
  1.1031 +  if (_dbus_g_type_is_fixed (subtype))
  1.1032 +    return demarshal_collection_array (context, iter, value, error);
  1.1033 +  else
  1.1034 +    return demarshal_collection_ptrarray (context, iter, value, error);
  1.1035 +}
  1.1036 +
  1.1037 +static gboolean
  1.1038 +demarshal_collection_ptrarray (DBusGValueMarshalCtx    *context,
  1.1039 +			       DBusMessageIter         *iter,
  1.1040 +			       GValue                  *value,
  1.1041 +			       GError                 **error)
  1.1042 +{
  1.1043 +  GType coltype;
  1.1044 +  GType subtype;
  1.1045 +  gpointer instance;
  1.1046 +  DBusGTypeSpecializedAppendContext ctx;
  1.1047 +  DBusGValueDemarshalFunc demarshaller;
  1.1048 +  DBusMessageIter subiter;
  1.1049 +  int current_type;
  1.1050 +
  1.1051 +  current_type = dbus_message_iter_get_arg_type (iter);
  1.1052 +
  1.1053 +  if (current_type != DBUS_TYPE_ARRAY)
  1.1054 +    {
  1.1055 +      g_set_error (error,
  1.1056 +		   DBUS_GERROR,
  1.1057 +		   DBUS_GERROR_INVALID_ARGS,
  1.1058 +		   _("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
  1.1059 +      return FALSE;
  1.1060 +    }
  1.1061 +
  1.1062 +  dbus_message_iter_recurse (iter, &subiter);
  1.1063 +  
  1.1064 +  coltype = G_VALUE_TYPE (value);
  1.1065 +  subtype = dbus_g_type_get_collection_specialization (coltype);
  1.1066 +
  1.1067 +  demarshaller = get_type_demarshaller (subtype);
  1.1068 +
  1.1069 +  if (!demarshaller)
  1.1070 +    {
  1.1071 +      g_set_error (error,
  1.1072 +		   DBUS_GERROR,
  1.1073 +		   DBUS_GERROR_INVALID_ARGS,
  1.1074 +		   _("No demarshaller registered for type \"%s\" of collection \"%s\""),
  1.1075 +		   g_type_name (coltype),
  1.1076 +		   g_type_name (subtype));
  1.1077 +      return FALSE;
  1.1078 +    }
  1.1079 +
  1.1080 +  instance = dbus_g_type_specialized_construct (coltype);
  1.1081 +  g_value_set_boxed_take_ownership (value, instance);
  1.1082 +
  1.1083 +  dbus_g_type_specialized_init_append (value, &ctx);
  1.1084 +
  1.1085 +  while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
  1.1086 +    {
  1.1087 +      GValue eltval = {0, };
  1.1088 +
  1.1089 +      g_value_init (&eltval, subtype);
  1.1090 +
  1.1091 +      if (!demarshaller (context, &subiter, &eltval, error))
  1.1092 +	{
  1.1093 +	  dbus_g_type_specialized_collection_end_append (&ctx);
  1.1094 +	  g_value_unset (value);
  1.1095 +	  return FALSE;
  1.1096 +	}
  1.1097 +      dbus_g_type_specialized_collection_append (&ctx, &eltval);
  1.1098 +      
  1.1099 +      dbus_message_iter_next (&subiter);
  1.1100 +    }
  1.1101 +  dbus_g_type_specialized_collection_end_append (&ctx);
  1.1102 +  
  1.1103 +  return TRUE;
  1.1104 +}
  1.1105 +
  1.1106 +static gboolean
  1.1107 +demarshal_collection_array (DBusGValueMarshalCtx    *context,
  1.1108 +			    DBusMessageIter         *iter,
  1.1109 +			    GValue                  *value,
  1.1110 +			    GError                 **error)
  1.1111 +{
  1.1112 +  DBusMessageIter subiter;
  1.1113 +  GArray *ret;
  1.1114 +  GType elt_gtype;
  1.1115 +  int elt_size;
  1.1116 +  void *msgarray;
  1.1117 +  int msgarray_len;
  1.1118 +
  1.1119 +  dbus_message_iter_recurse (iter, &subiter);
  1.1120 +
  1.1121 +  elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
  1.1122 +  g_assert (elt_gtype != G_TYPE_INVALID);
  1.1123 +  g_assert (_dbus_g_type_is_fixed (elt_gtype));
  1.1124 +
  1.1125 +  elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
  1.1126 +  
  1.1127 +  ret = g_array_new (FALSE, TRUE, elt_size);
  1.1128 +
  1.1129 +  msgarray = NULL;
  1.1130 +  dbus_message_iter_get_fixed_array (&subiter,
  1.1131 +				     &msgarray,
  1.1132 +				     &msgarray_len);
  1.1133 +  g_assert (msgarray != NULL || msgarray_len == 0);
  1.1134 +
  1.1135 +  if (msgarray_len)
  1.1136 +    g_array_append_vals (ret, msgarray, (guint) msgarray_len);
  1.1137 +
  1.1138 +  g_value_set_boxed_take_ownership (value, ret);
  1.1139 +  
  1.1140 +  return TRUE;
  1.1141 +}
  1.1142 +
  1.1143 +gboolean
  1.1144 +_dbus_gvalue_demarshal (DBusGValueMarshalCtx    *context,
  1.1145 +		       DBusMessageIter         *iter,
  1.1146 +		       GValue                  *value,
  1.1147 +		       GError                 **error)
  1.1148 +{
  1.1149 +  GType gtype;
  1.1150 +  DBusGValueDemarshalFunc demarshaller;
  1.1151 +
  1.1152 +  gtype = G_VALUE_TYPE (value);
  1.1153 +
  1.1154 +  demarshaller = get_type_demarshaller (gtype);
  1.1155 +
  1.1156 +  if (demarshaller == NULL)
  1.1157 +    {
  1.1158 +      g_set_error (error,
  1.1159 +		   DBUS_GERROR,
  1.1160 +		   DBUS_GERROR_INVALID_ARGS,
  1.1161 +		   _("No demarshaller registered for type \"%s\""),
  1.1162 +		   g_type_name (gtype));
  1.1163 +      return FALSE;
  1.1164 +    }
  1.1165 +  
  1.1166 +  return demarshaller (context, iter, value, error);
  1.1167 +}
  1.1168 +
  1.1169 +gboolean
  1.1170 +_dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx    *context,
  1.1171 +			       DBusMessageIter         *iter,
  1.1172 +			       GValue                  *value,
  1.1173 +			       GError                 **error)
  1.1174 +{
  1.1175 +  return demarshal_static_variant (context, iter, value, error);
  1.1176 +}
  1.1177 +
  1.1178 +GValueArray *
  1.1179 +_dbus_gvalue_demarshal_message  (DBusGValueMarshalCtx    *context,
  1.1180 +				DBusMessage             *message,
  1.1181 +				guint                    n_types,
  1.1182 +				const GType             *types,
  1.1183 +				GError                 **error)
  1.1184 +{
  1.1185 +  GValueArray *ret;
  1.1186 +  DBusMessageIter iter;
  1.1187 +  int current_type;
  1.1188 +  guint index_;
  1.1189 +  
  1.1190 +  ret = g_value_array_new (6);  /* 6 is a typical maximum for arguments */
  1.1191 +
  1.1192 +  dbus_message_iter_init (message, &iter);
  1.1193 +  index_ = 0;
  1.1194 +  while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
  1.1195 +    {
  1.1196 +      GValue *value;
  1.1197 +      GType gtype;
  1.1198 +
  1.1199 +      if (index_ >= n_types)
  1.1200 +	{
  1.1201 +	  g_set_error (error, DBUS_GERROR,
  1.1202 +		       DBUS_GERROR_INVALID_ARGS,
  1.1203 +		       _("Too many arguments in message"));
  1.1204 +	  goto lose;
  1.1205 +	}
  1.1206 +      
  1.1207 +      g_value_array_append (ret, NULL);
  1.1208 +      value = g_value_array_get_nth (ret, index_);
  1.1209 +
  1.1210 +      gtype = types[index_]; 
  1.1211 +      g_value_init (value, gtype);
  1.1212 +
  1.1213 +      if (!_dbus_gvalue_demarshal (context, &iter, value, error))
  1.1214 +	goto lose;
  1.1215 +      dbus_message_iter_next (&iter);
  1.1216 +      index_++;
  1.1217 +    }
  1.1218 +  if (index_ < n_types)
  1.1219 +    {
  1.1220 +      g_set_error (error, DBUS_GERROR,
  1.1221 +		   DBUS_GERROR_INVALID_ARGS,
  1.1222 +		   _("Too few arguments in message"));
  1.1223 +      goto lose;
  1.1224 +    }
  1.1225 +
  1.1226 +  return ret;
  1.1227 + lose:
  1.1228 +  g_value_array_free (ret);
  1.1229 +  return NULL;
  1.1230 +}
  1.1231 +
  1.1232 +static gboolean
  1.1233 +marshal_basic (DBusMessageIter *iter, const GValue *value)
  1.1234 +{
  1.1235 +  GType value_type;
  1.1236 +
  1.1237 +  value_type = G_VALUE_TYPE (value);
  1.1238 +  
  1.1239 +  switch (value_type)
  1.1240 +    {
  1.1241 +    case G_TYPE_CHAR:
  1.1242 +      {
  1.1243 +        char b = g_value_get_char (value);
  1.1244 +        if (!dbus_message_iter_append_basic (iter,
  1.1245 +                                             DBUS_TYPE_BYTE,
  1.1246 +                                             &b))
  1.1247 +          goto nomem;
  1.1248 +      }
  1.1249 +      return TRUE;
  1.1250 +    case G_TYPE_UCHAR:
  1.1251 +      {
  1.1252 +        unsigned char b = g_value_get_uchar (value);
  1.1253 +        if (!dbus_message_iter_append_basic (iter,
  1.1254 +                                             DBUS_TYPE_BYTE,
  1.1255 +                                             &b))
  1.1256 +          goto nomem;
  1.1257 +      }
  1.1258 +      return TRUE;
  1.1259 +    case G_TYPE_BOOLEAN:
  1.1260 +      {
  1.1261 +        dbus_bool_t b = g_value_get_boolean (value);
  1.1262 +        if (!dbus_message_iter_append_basic (iter,
  1.1263 +                                             DBUS_TYPE_BOOLEAN,
  1.1264 +                                             &b))
  1.1265 +          goto nomem;
  1.1266 +      }
  1.1267 +      return TRUE;
  1.1268 +    case G_TYPE_INT:
  1.1269 +      {
  1.1270 +        dbus_int32_t v = g_value_get_int (value);
  1.1271 +        if (!dbus_message_iter_append_basic (iter,
  1.1272 +                                             DBUS_TYPE_INT32,
  1.1273 +                                             &v))
  1.1274 +          goto nomem;
  1.1275 +      }
  1.1276 +      return TRUE;
  1.1277 +    case G_TYPE_UINT:
  1.1278 +      {
  1.1279 +        dbus_uint32_t v = g_value_get_uint (value);
  1.1280 +        if (!dbus_message_iter_append_basic (iter,
  1.1281 +                                             DBUS_TYPE_UINT32,
  1.1282 +                                             &v))
  1.1283 +          goto nomem;
  1.1284 +      }
  1.1285 +      return TRUE;
  1.1286 +    case G_TYPE_LONG:
  1.1287 +      {
  1.1288 +        dbus_int32_t v = g_value_get_long (value);
  1.1289 +        if (!dbus_message_iter_append_basic (iter,
  1.1290 +                                             DBUS_TYPE_INT32,
  1.1291 +                                             &v))
  1.1292 +          goto nomem;
  1.1293 +      }
  1.1294 +      return TRUE;
  1.1295 +    case G_TYPE_ULONG:
  1.1296 +      {
  1.1297 +        dbus_uint32_t v = g_value_get_ulong (value);
  1.1298 +        if (!dbus_message_iter_append_basic (iter,
  1.1299 +                                             DBUS_TYPE_UINT32,
  1.1300 +                                             &v))
  1.1301 +          goto nomem;
  1.1302 +      }
  1.1303 +      return TRUE;
  1.1304 +    case G_TYPE_INT64:
  1.1305 +      {
  1.1306 +        gint64 v = g_value_get_int64 (value);
  1.1307 +        if (!dbus_message_iter_append_basic (iter,
  1.1308 +                                             DBUS_TYPE_INT64,
  1.1309 +                                             &v))
  1.1310 +          goto nomem;
  1.1311 +      }
  1.1312 +      return TRUE;
  1.1313 +    case G_TYPE_UINT64:
  1.1314 +      {
  1.1315 +        guint64 v = g_value_get_uint64 (value);
  1.1316 +        if (!dbus_message_iter_append_basic (iter,
  1.1317 +                                             DBUS_TYPE_UINT64,
  1.1318 +                                             &v))
  1.1319 +          goto nomem;
  1.1320 +      }
  1.1321 +      return TRUE;
  1.1322 +    case G_TYPE_FLOAT:
  1.1323 +      {
  1.1324 +        double v = g_value_get_float (value);
  1.1325 +        
  1.1326 +        if (!dbus_message_iter_append_basic (iter,
  1.1327 +                                             DBUS_TYPE_DOUBLE,
  1.1328 +                                             &v))
  1.1329 +          goto nomem;
  1.1330 +      }
  1.1331 +      return TRUE;
  1.1332 +    case G_TYPE_DOUBLE:
  1.1333 +      {
  1.1334 +        double v = g_value_get_double (value);
  1.1335 +        
  1.1336 +        if (!dbus_message_iter_append_basic (iter,
  1.1337 +                                             DBUS_TYPE_DOUBLE,
  1.1338 +                                             &v))
  1.1339 +          goto nomem;
  1.1340 +      }
  1.1341 +      return TRUE;
  1.1342 +    case G_TYPE_STRING:
  1.1343 +      /* FIXME, the GValue string may not be valid UTF-8 */
  1.1344 +      {
  1.1345 +        const char *v = g_value_get_string (value);
  1.1346 +	if (!v)
  1.1347 +	  v = "";
  1.1348 +        if (!dbus_message_iter_append_basic (iter,
  1.1349 +                                             DBUS_TYPE_STRING,
  1.1350 +                                             &v))
  1.1351 +          goto nomem;
  1.1352 +      }
  1.1353 +      return TRUE;
  1.1354 +      
  1.1355 +    default:
  1.1356 +      {
  1.1357 +	g_assert_not_reached ();
  1.1358 +	return FALSE;
  1.1359 +      }
  1.1360 +    }
  1.1361 +
  1.1362 + nomem:
  1.1363 +  g_error ("no memory");
  1.1364 +  return FALSE;
  1.1365 +}
  1.1366 +
  1.1367 +static gboolean
  1.1368 +marshal_strv (DBusMessageIter   *iter,
  1.1369 +	      const GValue       *value)
  1.1370 +{
  1.1371 +  DBusMessageIter subiter;
  1.1372 +  char **array;
  1.1373 +  char **elt;
  1.1374 +  gboolean ret = FALSE;
  1.1375 +
  1.1376 +  g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
  1.1377 +
  1.1378 +  array = g_value_get_boxed (value);
  1.1379 +
  1.1380 +  if (!dbus_message_iter_open_container (iter,
  1.1381 +					 DBUS_TYPE_ARRAY,
  1.1382 +					 "s",
  1.1383 +					 &subiter))
  1.1384 +    goto out;
  1.1385 +
  1.1386 +  if (array)
  1.1387 +    {
  1.1388 +      for (elt = array; *elt; elt++)
  1.1389 +        {
  1.1390 +          if (!dbus_message_iter_append_basic (&subiter,
  1.1391 +					   DBUS_TYPE_STRING,
  1.1392 +					   elt))
  1.1393 +	        goto out;
  1.1394 +        }
  1.1395 +    }
  1.1396 +
  1.1397 +  if (!dbus_message_iter_close_container (iter, &subiter))
  1.1398 +    goto out;
  1.1399 +  ret = TRUE;
  1.1400 + out:
  1.1401 +  return ret;
  1.1402 +}
  1.1403 +
  1.1404 +static gboolean
  1.1405 +marshal_valuearray (DBusMessageIter   *iter,
  1.1406 +		    const GValue       *value)
  1.1407 +{
  1.1408 +  GValueArray *array;
  1.1409 +  guint i;
  1.1410 +  DBusMessageIter subiter;
  1.1411 +
  1.1412 +  g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
  1.1413 +
  1.1414 +  array = g_value_get_boxed (value);
  1.1415 +
  1.1416 +  if (!dbus_message_iter_open_container (iter,
  1.1417 +					 DBUS_TYPE_STRUCT,
  1.1418 +					 NULL,
  1.1419 +					 &subiter))
  1.1420 +    goto oom;
  1.1421 +
  1.1422 +  if (array)
  1.1423 +    {
  1.1424 +      for (i = 0; i < array->n_values; i++)
  1.1425 +        {
  1.1426 +          if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
  1.1427 +            return FALSE;
  1.1428 +        }
  1.1429 +    }
  1.1430 +
  1.1431 +  if (!dbus_message_iter_close_container (iter, &subiter))
  1.1432 +    goto oom;
  1.1433 +
  1.1434 +  return TRUE;
  1.1435 + oom:
  1.1436 +  g_error ("out of memory");
  1.1437 +  return FALSE;
  1.1438 +}
  1.1439 +
  1.1440 +static gboolean
  1.1441 +marshal_proxy (DBusMessageIter         *iter,
  1.1442 +	       const GValue            *value)
  1.1443 +{
  1.1444 +  const char *path;
  1.1445 +  DBusGProxy *proxy;
  1.1446 +
  1.1447 +  g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
  1.1448 +
  1.1449 +  proxy = g_value_get_object (value);
  1.1450 +  path = dbus_g_proxy_get_path (proxy);
  1.1451 +  
  1.1452 +  if (!dbus_message_iter_append_basic (iter,
  1.1453 +				       DBUS_TYPE_OBJECT_PATH,
  1.1454 +				       &path))
  1.1455 +    return FALSE;
  1.1456 +  return TRUE;
  1.1457 +}
  1.1458 +
  1.1459 +static gboolean
  1.1460 +marshal_object_path (DBusMessageIter         *iter,
  1.1461 +		     const GValue            *value)
  1.1462 +{
  1.1463 +  const char *path;
  1.1464 +
  1.1465 +  g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
  1.1466 +
  1.1467 +  path = (const char*) g_value_get_boxed (value);
  1.1468 +  
  1.1469 +  if (!dbus_message_iter_append_basic (iter,
  1.1470 +				       DBUS_TYPE_OBJECT_PATH,
  1.1471 +				       &path))
  1.1472 +    return FALSE;
  1.1473 +  return TRUE;
  1.1474 +}
  1.1475 +
  1.1476 +static gboolean
  1.1477 +marshal_object (DBusMessageIter         *iter,
  1.1478 +		const GValue            *value)
  1.1479 +{
  1.1480 +  const char *path;
  1.1481 +  GObject *obj;
  1.1482 +
  1.1483 +  obj = g_value_get_object (value);
  1.1484 +  path = _dbus_gobject_get_path (obj);
  1.1485 +
  1.1486 +  if (path == NULL)
  1.1487 +    /* FIXME should throw error */
  1.1488 +    return FALSE;
  1.1489 +  
  1.1490 +  if (!dbus_message_iter_append_basic (iter,
  1.1491 +				       DBUS_TYPE_OBJECT_PATH,
  1.1492 +				       &path))
  1.1493 +    return FALSE;
  1.1494 +  return TRUE;
  1.1495 +}
  1.1496 +
  1.1497 +struct DBusGLibHashMarshalData
  1.1498 +{
  1.1499 +  const char *entry_sig;
  1.1500 +  DBusMessageIter *iter;
  1.1501 +  gboolean err;
  1.1502 +};
  1.1503 +
  1.1504 +static void
  1.1505 +marshal_map_entry (const GValue *key,
  1.1506 +		   const GValue *value,
  1.1507 +		   gpointer data)
  1.1508 +{
  1.1509 +  struct DBusGLibHashMarshalData *hashdata = data;
  1.1510 +  DBusMessageIter subiter;
  1.1511 +
  1.1512 +  if (hashdata->err)
  1.1513 +    return;
  1.1514 +
  1.1515 +  if (!dbus_message_iter_open_container (hashdata->iter,
  1.1516 +					 DBUS_TYPE_DICT_ENTRY,
  1.1517 +					 NULL,
  1.1518 +					 &subiter))
  1.1519 +    goto lose;
  1.1520 +
  1.1521 +  if (!_dbus_gvalue_marshal (&subiter, key))
  1.1522 +    goto lose;
  1.1523 +
  1.1524 +  if (!_dbus_gvalue_marshal (&subiter, value))
  1.1525 +    goto lose;
  1.1526 +
  1.1527 +  if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
  1.1528 +    goto lose;
  1.1529 +  
  1.1530 +  return;
  1.1531 + lose:
  1.1532 +  hashdata->err = TRUE;
  1.1533 +}
  1.1534 +
  1.1535 +static gboolean
  1.1536 +marshal_map (DBusMessageIter   *iter,
  1.1537 +	     const GValue      *value)
  1.1538 +{
  1.1539 +  GType gtype;
  1.1540 +  DBusMessageIter arr_iter;
  1.1541 +  gboolean ret;
  1.1542 +  struct DBusGLibHashMarshalData hashdata;
  1.1543 +  char *key_sig;
  1.1544 +  char *value_sig;
  1.1545 +  GType key_type;
  1.1546 +  GType value_type;
  1.1547 +  char *entry_sig;
  1.1548 +  char *array_sig;
  1.1549 +
  1.1550 +  gtype = G_VALUE_TYPE (value);
  1.1551 +
  1.1552 +  ret = FALSE;
  1.1553 +
  1.1554 +  key_type = dbus_g_type_get_map_key_specialization (gtype);
  1.1555 +  g_assert (_dbus_gtype_is_valid_hash_key (key_type));
  1.1556 +  value_type = dbus_g_type_get_map_value_specialization (gtype);
  1.1557 +  g_assert (_dbus_gtype_is_valid_hash_value (value_type));
  1.1558 +
  1.1559 +  key_sig = _dbus_gtype_to_signature (key_type);
  1.1560 +  if (!key_sig)
  1.1561 +    {
  1.1562 +      g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
  1.1563 +      return FALSE;
  1.1564 +    }
  1.1565 +  value_sig = _dbus_gtype_to_signature (value_type);
  1.1566 +  if (!value_sig)
  1.1567 +    {
  1.1568 +      g_free (key_sig);
  1.1569 +      g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
  1.1570 +      return FALSE;
  1.1571 +    }
  1.1572 +  entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
  1.1573 +  g_free (key_sig);
  1.1574 +  g_free (value_sig);
  1.1575 +  array_sig = g_strdup_printf ("%c%s%c",
  1.1576 +			       DBUS_DICT_ENTRY_BEGIN_CHAR,
  1.1577 +			       entry_sig,
  1.1578 +			       DBUS_DICT_ENTRY_END_CHAR);
  1.1579 +  if (!dbus_message_iter_open_container (iter,
  1.1580 +					 DBUS_TYPE_ARRAY,
  1.1581 +					 array_sig,
  1.1582 +					 &arr_iter))
  1.1583 +    goto lose;
  1.1584 +
  1.1585 +  hashdata.iter = &arr_iter;
  1.1586 +  hashdata.err = FALSE;
  1.1587 +  hashdata.entry_sig = entry_sig;
  1.1588 +
  1.1589 +  dbus_g_type_map_value_iterate (value,
  1.1590 +				 marshal_map_entry,
  1.1591 +				 &hashdata);
  1.1592 +
  1.1593 +  if (!dbus_message_iter_close_container (iter, &arr_iter))
  1.1594 +    goto lose;
  1.1595 +
  1.1596 + out:
  1.1597 +  g_free (entry_sig);
  1.1598 +  g_free (array_sig);
  1.1599 +  return !hashdata.err;
  1.1600 + lose:
  1.1601 +  hashdata.err = TRUE;
  1.1602 +  goto out;
  1.1603 +}
  1.1604 +
  1.1605 +static gboolean
  1.1606 +marshal_struct (DBusMessageIter   *iter,
  1.1607 +                const GValue      *value)
  1.1608 +{
  1.1609 +  GType gtype;
  1.1610 +  DBusMessageIter subiter;
  1.1611 +  gboolean ret;
  1.1612 +  guint size, i;
  1.1613 +  GValue val = {0,};
  1.1614 +
  1.1615 +  gtype = G_VALUE_TYPE (value);
  1.1616 +
  1.1617 +  ret = FALSE;
  1.1618 +
  1.1619 +  size = dbus_g_type_get_struct_size (gtype);
  1.1620 +
  1.1621 +  if (!dbus_message_iter_open_container (iter,
  1.1622 +                                         DBUS_TYPE_STRUCT,
  1.1623 +                                         NULL,
  1.1624 +                                         &subiter))
  1.1625 +    goto oom;
  1.1626 +
  1.1627 +  for (i = 0; i < size; i++)
  1.1628 +    {
  1.1629 +      g_value_init (&val, dbus_g_type_get_struct_member_type
  1.1630 +          (G_VALUE_TYPE(value), i));
  1.1631 +      if (!dbus_g_type_struct_get_member (value, i, &val))
  1.1632 +        return FALSE;
  1.1633 +      if (!_dbus_gvalue_marshal (&subiter, &val))
  1.1634 +        return FALSE;
  1.1635 +      g_value_unset(&val);
  1.1636 +    }
  1.1637 +
  1.1638 +  if (!dbus_message_iter_close_container (iter, &subiter))
  1.1639 +    goto oom;
  1.1640 +
  1.1641 +  return TRUE;
  1.1642 + oom:
  1.1643 +  g_error ("out of memory");
  1.1644 +  return FALSE;
  1.1645 +}
  1.1646 +
  1.1647 +static gboolean
  1.1648 +marshal_variant (DBusMessageIter          *iter,
  1.1649 +		 const GValue             *value)
  1.1650 +{
  1.1651 +  GType value_gtype;
  1.1652 +  DBusMessageIter subiter;
  1.1653 +  char *variant_sig;
  1.1654 +  GValue *real_value;
  1.1655 +  gboolean ret = FALSE;
  1.1656 +
  1.1657 +  real_value = g_value_get_boxed (value);
  1.1658 +  value_gtype = G_VALUE_TYPE (real_value);
  1.1659 +
  1.1660 +  variant_sig = _dbus_gvalue_to_signature (real_value);
  1.1661 +  if (variant_sig == NULL)
  1.1662 +    {
  1.1663 +      g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
  1.1664 +      return FALSE;
  1.1665 +    }
  1.1666 +
  1.1667 +  if (!dbus_message_iter_open_container (iter,
  1.1668 +					 DBUS_TYPE_VARIANT,
  1.1669 +					 variant_sig,
  1.1670 +					 &subiter))
  1.1671 +    goto out;
  1.1672 +
  1.1673 +  if (!_dbus_gvalue_marshal (&subiter, real_value))
  1.1674 +    goto out;
  1.1675 +
  1.1676 +  if (!dbus_message_iter_close_container (iter, &subiter))
  1.1677 +    goto out;
  1.1678 +
  1.1679 +  ret = TRUE;
  1.1680 + out:
  1.1681 +  g_free (variant_sig);
  1.1682 +  return ret;
  1.1683 +}
  1.1684 +
  1.1685 +static DBusGValueMarshalFunc
  1.1686 +get_type_marshaller (GType type)
  1.1687 +{
  1.1688 +  DBusGTypeMarshalData *typedata;
  1.1689 +
  1.1690 +  typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
  1.1691 +  if (typedata == NULL)
  1.1692 +    {
  1.1693 +      if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
  1.1694 +	return marshal_valuearray;
  1.1695 +      if (dbus_g_type_is_collection (type))
  1.1696 +	return marshal_collection;
  1.1697 +      if (dbus_g_type_is_map (type))
  1.1698 +	return marshal_map;
  1.1699 +      if (dbus_g_type_is_struct (type))
  1.1700 +	return marshal_struct;
  1.1701 +
  1.1702 +      g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
  1.1703 +      return NULL;
  1.1704 +    }
  1.1705 +  g_assert (typedata->vtable);
  1.1706 +  return typedata->vtable->marshaller;
  1.1707 +}
  1.1708 +
  1.1709 +typedef struct
  1.1710 +{
  1.1711 +  DBusMessageIter *iter;
  1.1712 +  DBusGValueMarshalFunc marshaller;
  1.1713 +  gboolean err;
  1.1714 +} DBusGValueCollectionMarshalData;
  1.1715 +
  1.1716 +static void
  1.1717 +collection_marshal_iterator (const GValue *eltval,
  1.1718 +			     gpointer      user_data)
  1.1719 +{
  1.1720 +  DBusGValueCollectionMarshalData *data = user_data;
  1.1721 +
  1.1722 +  if (data->err)
  1.1723 +    return;
  1.1724 +
  1.1725 +  if (!data->marshaller (data->iter, eltval))
  1.1726 +    data->err = TRUE;
  1.1727 +}
  1.1728 +
  1.1729 +static gboolean
  1.1730 +marshal_collection (DBusMessageIter         *iter,
  1.1731 +		    const GValue            *value)
  1.1732 +{
  1.1733 +  GType coltype;
  1.1734 +  GType subtype;
  1.1735 +  
  1.1736 +  coltype = G_VALUE_TYPE (value);
  1.1737 +  subtype = dbus_g_type_get_collection_specialization (coltype);
  1.1738 +
  1.1739 +  if (_dbus_g_type_is_fixed (subtype))
  1.1740 +    return marshal_collection_array (iter, value);
  1.1741 +  else
  1.1742 +    return marshal_collection_ptrarray (iter, value);
  1.1743 +}
  1.1744 +
  1.1745 +static gboolean
  1.1746 +marshal_collection_ptrarray (DBusMessageIter         *iter,
  1.1747 +			     const GValue            *value)
  1.1748 +{
  1.1749 +  GType coltype;
  1.1750 +  GType elt_gtype;
  1.1751 +  DBusGValueCollectionMarshalData data;
  1.1752 +  DBusMessageIter subiter;
  1.1753 +  char *elt_sig;
  1.1754 +  
  1.1755 +  coltype = G_VALUE_TYPE (value);
  1.1756 +  elt_gtype = dbus_g_type_get_collection_specialization (coltype);
  1.1757 +  data.marshaller = get_type_marshaller (elt_gtype);
  1.1758 +  if (!data.marshaller)
  1.1759 +    return FALSE;
  1.1760 +
  1.1761 +  elt_sig = _dbus_gtype_to_signature (elt_gtype);
  1.1762 +  if (!elt_sig)
  1.1763 +    {
  1.1764 +      g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
  1.1765 +      return FALSE;
  1.1766 +    }
  1.1767 +
  1.1768 +  if (!dbus_message_iter_open_container (iter,
  1.1769 +					 DBUS_TYPE_ARRAY,
  1.1770 +					 elt_sig,
  1.1771 +					 &subiter))
  1.1772 +    goto oom;
  1.1773 +  g_free (elt_sig);
  1.1774 +
  1.1775 +  data.iter = &subiter;
  1.1776 +  data.err = FALSE;
  1.1777 +
  1.1778 +  dbus_g_type_collection_value_iterate (value,
  1.1779 +					collection_marshal_iterator,
  1.1780 +					&data);
  1.1781 +
  1.1782 +  if (!dbus_message_iter_close_container (iter, &subiter))
  1.1783 +    goto oom;
  1.1784 +  
  1.1785 +  return !data.err;
  1.1786 + oom:
  1.1787 +  g_error ("out of memory");
  1.1788 +  return FALSE;
  1.1789 +}
  1.1790 +
  1.1791 +
  1.1792 +static gboolean
  1.1793 +marshal_collection_array (DBusMessageIter   *iter,
  1.1794 +			  const GValue      *value)
  1.1795 +{
  1.1796 +  GType elt_gtype;
  1.1797 +  DBusMessageIter subiter;
  1.1798 +  GArray *array;
  1.1799 +  guint elt_size;
  1.1800 +  char *subsignature_str;
  1.1801 +
  1.1802 +  elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
  1.1803 +  g_assert (_dbus_g_type_is_fixed (elt_gtype));
  1.1804 +  subsignature_str = _dbus_gtype_to_signature (elt_gtype);
  1.1805 +  if (!subsignature_str)
  1.1806 +    {
  1.1807 +      g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
  1.1808 +      return FALSE;
  1.1809 +    }
  1.1810 +  
  1.1811 +  elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
  1.1812 +
  1.1813 +  array = g_value_get_boxed (value);
  1.1814 +
  1.1815 +  if (!dbus_message_iter_open_container (iter,
  1.1816 +					 DBUS_TYPE_ARRAY,
  1.1817 +					 subsignature_str,
  1.1818 +					 &subiter))
  1.1819 +    goto oom;
  1.1820 +
  1.1821 +  /* TODO - This assumes that basic values are the same size
  1.1822 +   * is this always true?  If it is we can probably avoid
  1.1823 +   * a lot of the overhead in _marshal_basic_instance...
  1.1824 +   */
  1.1825 +  if (!array || !dbus_message_iter_append_fixed_array (&subiter,
  1.1826 +					     subsignature_str[0],
  1.1827 +					     &(array->data),
  1.1828 +					     array->len))
  1.1829 +    goto oom;
  1.1830 +
  1.1831 +  if (!dbus_message_iter_close_container (iter, &subiter))
  1.1832 +    goto oom;
  1.1833 +  g_free (subsignature_str);
  1.1834 +  return TRUE;
  1.1835 + oom:
  1.1836 +  g_error ("out of memory");
  1.1837 +  return FALSE;
  1.1838 +}
  1.1839 +
  1.1840 +gboolean
  1.1841 +_dbus_gvalue_marshal (DBusMessageIter         *iter,
  1.1842 +		     const GValue       *value)
  1.1843 +{
  1.1844 +  GType gtype;
  1.1845 +  DBusGValueMarshalFunc marshaller;
  1.1846 +
  1.1847 +  gtype = G_VALUE_TYPE (value);
  1.1848 +
  1.1849 +  marshaller = get_type_marshaller (gtype);
  1.1850 +  if (marshaller == NULL)
  1.1851 +    return FALSE;
  1.1852 +  return marshaller (iter, value);
  1.1853 +}
  1.1854 +
  1.1855 +#ifdef DBUS_BUILD_TESTS
  1.1856 +
  1.1857 +static void
  1.1858 +assert_type_maps_to (GType gtype, const char *expected_sig)
  1.1859 +{
  1.1860 +  char *sig;
  1.1861 +  sig = _dbus_gtype_to_signature (gtype);
  1.1862 +  g_assert (sig != NULL);
  1.1863 +  g_assert (!strcmp (expected_sig, sig));
  1.1864 +  g_free (sig);
  1.1865 +}
  1.1866 +
  1.1867 +static void
  1.1868 +assert_signature_maps_to (const char *sig, GType expected_gtype)
  1.1869 +{
  1.1870 +  g_assert (_dbus_gtype_from_signature (sig, TRUE) == expected_gtype);
  1.1871 +}
  1.1872 +
  1.1873 +static void
  1.1874 +assert_bidirectional_mapping (GType gtype, const char *expected_sig)
  1.1875 +{
  1.1876 +  assert_type_maps_to (gtype, expected_sig);
  1.1877 +  assert_signature_maps_to (expected_sig, gtype);
  1.1878 +}
  1.1879 +
  1.1880 +/**
  1.1881 + * @ingroup DBusGLibInternals
  1.1882 + * @test_data_dir:
  1.1883 + *
  1.1884 + * Unit test for general glib stuff
  1.1885 + * Returns: #TRUE on success.
  1.1886 + */
  1.1887 + 	#ifdef __SYMBIAN32__
  1.1888 +	EXPORT_C
  1.1889 +	#endif
  1.1890 +gboolean
  1.1891 +_dbus_gvalue_test (const char *test_data_dir)
  1.1892 +{
  1.1893 +  _dbus_g_value_types_init ();
  1.1894 +  
  1.1895 +  assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
  1.1896 +  assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
  1.1897 +  assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
  1.1898 +
  1.1899 +  assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
  1.1900 +			      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);
  1.1901 +  assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
  1.1902 +				DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
  1.1903 +  assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
  1.1904 +				DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
  1.1905 +
  1.1906 +  assert_bidirectional_mapping (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID),
  1.1907 +  				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 );
  1.1908 +  return TRUE;
  1.1909 +}
  1.1910 +
  1.1911 +#endif /* DBUS_BUILD_TESTS */