/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-gvalue.c GValue to-from DBusMessageIter
*
* Copyright (C) 2004 Ximian, Inc.
* Copyright (C) 2005 Red Hat, Inc.
* Portion Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "config.h"
#include "dbus-gtest.h"
#include "dbus-gvalue.h"
#include "dbus-gsignature.h"
#include "dbus-gobject.h"
#include "dbus-gvalue-utils.h"
#include "dbus/dbus-glib.h"
#include <string.h>
#include <glib.h>
#ifndef __SYMBIAN32__
#include <glib/gi18n.h>
#include <libintl.h>
#define _(x) dgettext (GETTEXT_PACKAGE, x)
#define N_(x) x
#else
#define _(x) x
#define N_(x) x
#endif
#include "dbus/dbus-signature.h"
#ifdef __SYMBIAN32__
#include "libdbus_glib_wsd_solution.h"
#endif
static gboolean demarshal_static_variant (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error);
static gboolean marshal_basic (DBusMessageIter *iter,
const GValue *value);
static gboolean demarshal_basic (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error);
static gboolean marshal_strv (DBusMessageIter *iter,
const GValue *value);
static gboolean demarshal_strv (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error);
static gboolean marshal_valuearray (DBusMessageIter *iter,
const GValue *value);
static gboolean demarshal_valuearray (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error);
static gboolean marshal_variant (DBusMessageIter *iter,
const GValue *value);
static gboolean demarshal_variant (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error);
static gboolean marshal_proxy (DBusMessageIter *iter,
const GValue *value);
static gboolean demarshal_proxy (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error);
static gboolean marshal_object_path (DBusMessageIter *iter,
const GValue *value);
static gboolean demarshal_object_path (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error);
static gboolean marshal_object (DBusMessageIter *iter,
const GValue *value);
static gboolean demarshal_object (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error);
static gboolean marshal_map (DBusMessageIter *iter,
const GValue *value);
static gboolean demarshal_map (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error);
static gboolean marshal_collection (DBusMessageIter *iter,
const GValue *value);
static gboolean marshal_collection_ptrarray (DBusMessageIter *iter,
const GValue *value);
static gboolean marshal_collection_array (DBusMessageIter *iter,
const GValue *value);
static gboolean demarshal_collection (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error);
static gboolean demarshal_collection_ptrarray (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error);
static gboolean demarshal_collection_array (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error);
static gboolean marshal_struct (DBusMessageIter *iter,
const GValue *value);
static gboolean demarshal_struct (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error);
typedef gboolean (*DBusGValueMarshalFunc) (DBusMessageIter *iter,
const GValue *value);
typedef gboolean (*DBusGValueDemarshalFunc) (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error);
typedef struct {
DBusGValueMarshalFunc marshaller;
DBusGValueDemarshalFunc demarshaller;
} DBusGTypeMarshalVtable;
typedef struct {
const char *sig;
const DBusGTypeMarshalVtable *vtable;
} DBusGTypeMarshalData;
#if EMULATOR
GET_STATIC_VAR_FROM_TLS(quark,dbus_gvalue,GQuark )
#define quark (*GET_DBUS_WSD_VAR_NAME(quark,dbus_gvalue,s)())
#endif
static GQuark
dbus_g_type_metadata_data_quark ()
{
#ifndef EMULATOR
static GQuark quark;
#endif
if (!quark)
quark = g_quark_from_static_string ("DBusGTypeMetaData");
return quark;
}
static void
set_type_metadata (GType type, const DBusGTypeMarshalData *data)
{
g_type_set_qdata (type, dbus_g_type_metadata_data_quark (), (gpointer) data);
}
static void
register_basic (int typecode, const DBusGTypeMarshalData *typedata)
{
set_type_metadata (_dbus_gtype_from_basic_typecode (typecode), typedata);
}
#if EMULATOR
GET_STATIC_VAR_FROM_TLS(types_initialized,dbus_gvalue,gboolean )
#define types_initialized (*GET_DBUS_WSD_VAR_NAME(types_initialized,dbus_gvalue,s)())
#endif
void
_dbus_g_value_types_init (void)
{
#ifndef EMULATOR
static gboolean types_initialized;
#endif
static const DBusGTypeMarshalVtable basic_vtable = {
marshal_basic,
demarshal_basic
};
if (types_initialized)
return;
dbus_g_type_specialized_init ();
_dbus_g_type_specialized_builtins_init ();
/* Register basic types */
{
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_BOOLEAN_AS_STRING,
&basic_vtable,
};
register_basic (DBUS_TYPE_BOOLEAN, &typedata);
}
{
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_BYTE_AS_STRING,
&basic_vtable,
};
register_basic (DBUS_TYPE_BYTE, &typedata);
}
{
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_INT16_AS_STRING,
&basic_vtable,
};
register_basic (DBUS_TYPE_INT16, &typedata);
}
{
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_UINT16_AS_STRING,
&basic_vtable,
};
register_basic (DBUS_TYPE_UINT16, &typedata);
}
{
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_UINT32_AS_STRING,
&basic_vtable,
};
register_basic (DBUS_TYPE_UINT32, &typedata);
}
{
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_INT32_AS_STRING,
&basic_vtable,
};
register_basic (DBUS_TYPE_INT32, &typedata);
}
{
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_UINT64_AS_STRING,
&basic_vtable,
};
register_basic (DBUS_TYPE_UINT64, &typedata);
}
{
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_INT64_AS_STRING,
&basic_vtable,
};
register_basic (DBUS_TYPE_INT64, &typedata);
}
{
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_DOUBLE_AS_STRING,
&basic_vtable,
};
register_basic (DBUS_TYPE_DOUBLE, &typedata);
}
{
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_STRING_AS_STRING,
&basic_vtable,
};
register_basic (DBUS_TYPE_STRING, &typedata);
}
/* fundamental GTypes that don't map 1:1 with D-BUS types */
{
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_BYTE_AS_STRING,
&basic_vtable,
};
set_type_metadata (G_TYPE_CHAR, &typedata);
}
{
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_INT32_AS_STRING,
&basic_vtable,
};
set_type_metadata (G_TYPE_LONG, &typedata);
}
{
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_UINT32_AS_STRING,
&basic_vtable,
};
set_type_metadata (G_TYPE_ULONG, &typedata);
}
{
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_DOUBLE_AS_STRING,
&basic_vtable,
};
set_type_metadata (G_TYPE_FLOAT, &typedata);
}
/* Register complex types with builtin GType mappings */
{
static const DBusGTypeMarshalVtable vtable = {
marshal_variant,
demarshal_variant
};
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_VARIANT_AS_STRING,
&vtable
};
set_type_metadata (G_TYPE_VALUE, &typedata);
};
{
static const DBusGTypeMarshalVtable vtable = {
marshal_strv,
demarshal_strv
};
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
&vtable
};
set_type_metadata (G_TYPE_STRV, &typedata);
};
/* Register some types specific to the D-BUS GLib bindings */
{
static const DBusGTypeMarshalVtable vtable = {
marshal_proxy,
demarshal_proxy
};
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_OBJECT_PATH_AS_STRING,
&vtable
};
set_type_metadata (DBUS_TYPE_G_PROXY, &typedata);
}
{
static const DBusGTypeMarshalVtable vtable = {
marshal_object_path,
demarshal_object_path
};
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_OBJECT_PATH_AS_STRING,
&vtable
};
set_type_metadata (DBUS_TYPE_G_OBJECT_PATH, &typedata);
}
{
static const DBusGTypeMarshalVtable vtable = {
marshal_object,
demarshal_object
};
static const DBusGTypeMarshalData typedata = {
DBUS_TYPE_OBJECT_PATH_AS_STRING,
&vtable
};
set_type_metadata (G_TYPE_OBJECT, &typedata);
}
types_initialized = TRUE;
}
/**
* Get the GLib type ID for a DBusGObjectPath boxed type.
*
* Returns: GLib type
*/
#if EMULATOR
GET_STATIC_VAR_FROM_TLS(type_id,dbus_gvalue,GType )
#define type_id (*GET_DBUS_WSD_VAR_NAME(type_id,dbus_gvalue,s)())
#endif
#ifdef __SYMBIAN32__
EXPORT_C
#endif
GType
dbus_g_object_path_get_g_type (void)
{
#ifndef EMULATOR
static GType type_id = 0;
#endif
if (!type_id)
type_id = g_boxed_type_register_static ("DBusGObjectPath",
(GBoxedCopyFunc) g_strdup,
(GBoxedFreeFunc) g_free);
return type_id;
}
char *
_dbus_gtype_to_signature (GType gtype)
{
char *ret;
DBusGTypeMarshalData *typedata;
if (dbus_g_type_is_collection (gtype))
{
GType elt_gtype;
char *subsig;
elt_gtype = dbus_g_type_get_collection_specialization (gtype);
subsig = _dbus_gtype_to_signature (elt_gtype);
ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING, subsig, NULL);
g_free (subsig);
}
else if (dbus_g_type_is_map (gtype))
{
GType key_gtype;
GType val_gtype;
char *key_subsig;
char *val_subsig;
key_gtype = dbus_g_type_get_map_key_specialization (gtype);
val_gtype = dbus_g_type_get_map_value_specialization (gtype);
key_subsig = _dbus_gtype_to_signature (key_gtype);
val_subsig = _dbus_gtype_to_signature (val_gtype);
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);
g_free (key_subsig);
g_free (val_subsig);
}
else if (dbus_g_type_is_struct (gtype))
{
guint i, size;
GString *sig;
size = dbus_g_type_get_struct_size (gtype);
sig = g_string_sized_new (size+2); /*some sensible starting size*/
g_string_assign (sig, DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
for (i = 0; i < size; i++)
{
gchar *subsig;
subsig = _dbus_gtype_to_signature (
dbus_g_type_get_struct_member_type (gtype, i));
g_string_append (sig, subsig);
g_free (subsig);
}
g_string_append (sig, DBUS_STRUCT_END_CHAR_AS_STRING);
ret = g_string_free (sig, FALSE);
}
else
{
typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ());
if (typedata == NULL)
return NULL;
ret = g_strdup (typedata->sig);
}
return ret;
}
char *
_dbus_gvalue_to_signature (const GValue *val)
{
GType gtype;
gtype = G_VALUE_TYPE (val);
if (g_type_is_a (gtype, G_TYPE_VALUE_ARRAY))
{
GString *str;
guint i;
GValueArray *array;
array = g_value_get_boxed (val);
str = g_string_new (DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
for (i = 0; i < array->n_values; i++)
{
char *sig;
sig = _dbus_gvalue_to_signature (g_value_array_get_nth (array, i));
g_string_append (str, sig);
g_free (sig);
}
g_string_append (str, DBUS_STRUCT_END_CHAR_AS_STRING);
return g_string_free (str, FALSE);
}
else
return _dbus_gtype_to_signature (gtype);
}
static gboolean
demarshal_basic (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
int current_type;
current_type = dbus_message_iter_get_arg_type (iter);
g_assert (dbus_type_is_basic (current_type));
switch (current_type)
{
case DBUS_TYPE_BOOLEAN:
{
dbus_bool_t bool;
dbus_message_iter_get_basic (iter, &bool);
g_value_set_boolean (value, bool);
return TRUE;
}
case DBUS_TYPE_BYTE:
{
unsigned char byte;
dbus_message_iter_get_basic (iter, &byte);
g_value_set_uchar (value, byte);
return TRUE;
}
case DBUS_TYPE_INT32:
{
dbus_int32_t intval;
dbus_message_iter_get_basic (iter, &intval);
g_value_set_int (value, intval);
return TRUE;
}
case DBUS_TYPE_UINT32:
{
dbus_uint32_t intval;
dbus_message_iter_get_basic (iter, &intval);
g_value_set_uint (value, intval);
return TRUE;
}
case DBUS_TYPE_INT64:
{
dbus_int64_t intval;
dbus_message_iter_get_basic (iter, &intval);
g_value_set_int64 (value, intval);
return TRUE;
}
case DBUS_TYPE_UINT64:
{
dbus_uint64_t intval;
dbus_message_iter_get_basic (iter, &intval);
g_value_set_uint64 (value, intval);
return TRUE;
}
case DBUS_TYPE_DOUBLE:
{
double dval;
dbus_message_iter_get_basic (iter, &dval);
g_value_set_double (value, dval);
return TRUE;
}
case DBUS_TYPE_INT16:
{
dbus_int16_t v;
dbus_message_iter_get_basic (iter, &v);
g_value_set_int (value, v);
return TRUE;
}
case DBUS_TYPE_UINT16:
{
dbus_uint16_t v;
dbus_message_iter_get_basic (iter, &v);
g_value_set_uint (value, v);
return TRUE;
}
case DBUS_TYPE_STRING:
{
const char *s;
dbus_message_iter_get_basic (iter, &s);
g_value_set_string (value, s);
return TRUE;
}
default:
g_assert_not_reached ();
return FALSE;
}
}
static gboolean
demarshal_static_variant (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
char *sig;
int current_type;
DBusMessageIter subiter;
GType variant_type;
current_type = dbus_message_iter_get_arg_type (iter);
dbus_message_iter_recurse (iter, &subiter);
sig = dbus_message_iter_get_signature (&subiter);
variant_type = _dbus_gtype_from_signature (sig, context->proxy != NULL);
if (variant_type != G_TYPE_INVALID)
{
g_value_init (value, variant_type);
if (!_dbus_gvalue_demarshal (context, &subiter, value, error))
{
dbus_free (sig);
return FALSE;
}
}
dbus_free (sig);
return TRUE;
}
static gboolean
demarshal_variant (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
GValue *variant_val;
variant_val = g_new0 (GValue, 1);
if (!demarshal_static_variant (context, iter, variant_val, error))
return FALSE;
g_value_set_boxed_take_ownership (value, variant_val);
return TRUE;
}
static gboolean
demarshal_proxy (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
DBusGProxy *new_proxy;
const char *objpath;
int current_type;
current_type = dbus_message_iter_get_arg_type (iter);
if (current_type != DBUS_TYPE_OBJECT_PATH)
{
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
return FALSE;
}
g_assert (context->proxy != NULL);
dbus_message_iter_get_basic (iter, &objpath);
new_proxy = dbus_g_proxy_new_from_proxy (context->proxy, NULL, objpath);
g_value_set_object_take_ownership (value, new_proxy);
return TRUE;
}
static gboolean
demarshal_object_path (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
const char *objpath;
int current_type;
current_type = dbus_message_iter_get_arg_type (iter);
if (current_type != DBUS_TYPE_OBJECT_PATH)
{
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
return FALSE;
}
dbus_message_iter_get_basic (iter, &objpath);
g_value_set_boxed_take_ownership (value, g_strdup (objpath));
return TRUE;
}
static gboolean
demarshal_object (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
const char *objpath;
int current_type;
GObject *obj;
current_type = dbus_message_iter_get_arg_type (iter);
if (current_type != DBUS_TYPE_OBJECT_PATH)
{
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Expected D-BUS object path, got type code \'%c\'"), (guchar) current_type);
return FALSE;
}
g_assert (context->proxy == NULL);
dbus_message_iter_get_basic (iter, &objpath);
obj = dbus_g_connection_lookup_g_object (context->gconnection, objpath);
if (obj == NULL)
{
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Unregistered object at path '%s'"),
objpath);
return FALSE;
}
g_value_set_object (value, obj);
return TRUE;
}
static gboolean
demarshal_strv (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
DBusMessageIter subiter;
int current_type;
char **ret;
int len;
int i;
current_type = dbus_message_iter_get_arg_type (iter);
if (current_type != DBUS_TYPE_ARRAY)
{
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
return FALSE;
}
dbus_message_iter_recurse (iter, &subiter);
current_type = dbus_message_iter_get_arg_type (&subiter);
if (current_type != DBUS_TYPE_INVALID
&& current_type != DBUS_TYPE_STRING)
{
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Expected D-BUS string, got type code \'%c\'"), (guchar) current_type);
return FALSE;
}
len = dbus_message_iter_get_array_len (&subiter);
g_assert (len >= 0);
ret = g_malloc (sizeof (char *) * (len + 1));
i = 0;
while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
{
g_assert (i < len);
g_assert (current_type == DBUS_TYPE_STRING);
dbus_message_iter_get_basic (&subiter, &(ret[i]));
ret[i] = g_strdup (ret[i]);
dbus_message_iter_next (&subiter);
i++;
}
ret[i] = NULL;
g_value_set_boxed_take_ownership (value, ret);
return TRUE;
}
static gboolean
demarshal_valuearray (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
int current_type;
GValueArray *ret;
DBusMessageIter subiter;
current_type = dbus_message_iter_get_arg_type (iter);
if (current_type != DBUS_TYPE_STRUCT)
{
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type);
return FALSE;
}
dbus_message_iter_recurse (iter, &subiter);
ret = g_value_array_new (12);
while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
{
GValue *val;
GType elt_type;
char *current_sig;
g_value_array_append (ret, NULL);
val = g_value_array_get_nth (ret, ret->n_values - 1);
current_sig = dbus_message_iter_get_signature (&subiter);
elt_type = _dbus_gtype_from_signature (current_sig, TRUE);
dbus_free (current_sig);
if (elt_type == G_TYPE_INVALID)
{
g_value_array_free (ret);
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Couldn't demarshal argument with signature \"%s\""), current_sig);
return FALSE;
}
g_value_init (val, elt_type);
if (!_dbus_gvalue_demarshal (context, &subiter, val, error))
{
g_value_array_free (ret);
return FALSE;
}
dbus_message_iter_next (&subiter);
}
g_value_set_boxed_take_ownership (value, ret);
return TRUE;
}
static gboolean
demarshal_map (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
GType gtype;
DBusMessageIter subiter;
int current_type;
gpointer ret;
GType key_gtype;
GType value_gtype;
DBusGTypeSpecializedAppendContext appendctx;
current_type = dbus_message_iter_get_arg_type (iter);
if (current_type != DBUS_TYPE_ARRAY)
{
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
return FALSE;
}
gtype = G_VALUE_TYPE (value);
dbus_message_iter_recurse (iter, &subiter);
current_type = dbus_message_iter_get_arg_type (&subiter);
if (current_type != DBUS_TYPE_INVALID
&& current_type != DBUS_TYPE_DICT_ENTRY)
{
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Expected D-BUS dict entry, got type code \'%c\'"), (guchar) current_type);
return FALSE;
}
key_gtype = dbus_g_type_get_map_key_specialization (gtype);
value_gtype = dbus_g_type_get_map_value_specialization (gtype);
ret = dbus_g_type_specialized_construct (gtype);
g_value_set_boxed_take_ownership (value, ret);
dbus_g_type_specialized_init_append (value, &appendctx);
while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
{
DBusMessageIter entry_iter;
GValue key_value = {0,};
GValue value_value = {0,};
current_type = dbus_message_iter_get_arg_type (&subiter);
g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
dbus_message_iter_recurse (&subiter, &entry_iter);
g_value_init (&key_value, key_gtype);
if (!_dbus_gvalue_demarshal (context,
&entry_iter,
&key_value,
error))
return FALSE;
dbus_message_iter_next (&entry_iter);
g_value_init (&value_value, value_gtype);
if (!_dbus_gvalue_demarshal (context,
&entry_iter,
&value_value,
error))
return FALSE;
dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
/* Ownership of values passes to map, don't unset */
dbus_message_iter_next (&subiter);
}
return TRUE;
}
static gboolean
demarshal_struct (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
int current_type;
DBusMessageIter subiter;
guint i, size;
GValue val = {0,};
GType elt_type;
current_type = dbus_message_iter_get_arg_type (iter);
if (current_type != DBUS_TYPE_STRUCT)
{
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Expected D-BUS struct, got type code \'%c\'"), (guchar) current_type);
return FALSE;
}
dbus_message_iter_recurse (iter, &subiter);
g_value_set_boxed_take_ownership (value,
dbus_g_type_specialized_construct (G_VALUE_TYPE (value)));
size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value));
for (i=0; i < size; i++)
{
elt_type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE(value), i);
if (elt_type == G_TYPE_INVALID)
{
g_value_unset (value);
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Couldn't demarshal argument, "
"struct type %s has no member %d"),
g_type_name (G_VALUE_TYPE(value)), i);
return FALSE;
}
g_value_init (&val, elt_type);
if (!_dbus_gvalue_demarshal (context, &subiter, &val, error))
{
g_value_unset (&val);
g_value_unset (value);
return FALSE;
}
if (!dbus_g_type_struct_set_member (value, i, &val))
{
g_value_unset (&val);
g_value_unset (value);
return FALSE;
}
dbus_message_iter_next (&subiter);
g_value_unset (&val);
}
g_assert (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_INVALID);
return TRUE;
}
static DBusGValueDemarshalFunc
get_type_demarshaller (GType type)
{
DBusGTypeMarshalData *typedata;
typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
if (typedata == NULL)
{
if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
return demarshal_valuearray;
if (dbus_g_type_is_collection (type))
return demarshal_collection;
if (dbus_g_type_is_map (type))
return demarshal_map;
if (dbus_g_type_is_struct (type))
return demarshal_struct;
g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
return NULL;
}
g_assert (typedata->vtable);
return typedata->vtable->demarshaller;
}
static gboolean
demarshal_collection (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
GType coltype;
GType subtype;
coltype = G_VALUE_TYPE (value);
subtype = dbus_g_type_get_collection_specialization (coltype);
if (_dbus_g_type_is_fixed (subtype))
return demarshal_collection_array (context, iter, value, error);
else
return demarshal_collection_ptrarray (context, iter, value, error);
}
static gboolean
demarshal_collection_ptrarray (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
GType coltype;
GType subtype;
gpointer instance;
DBusGTypeSpecializedAppendContext ctx;
DBusGValueDemarshalFunc demarshaller;
DBusMessageIter subiter;
int current_type;
current_type = dbus_message_iter_get_arg_type (iter);
if (current_type != DBUS_TYPE_ARRAY)
{
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Expected D-BUS array, got type code \'%c\'"), (guchar) current_type);
return FALSE;
}
dbus_message_iter_recurse (iter, &subiter);
coltype = G_VALUE_TYPE (value);
subtype = dbus_g_type_get_collection_specialization (coltype);
demarshaller = get_type_demarshaller (subtype);
if (!demarshaller)
{
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("No demarshaller registered for type \"%s\" of collection \"%s\""),
g_type_name (coltype),
g_type_name (subtype));
return FALSE;
}
instance = dbus_g_type_specialized_construct (coltype);
g_value_set_boxed_take_ownership (value, instance);
dbus_g_type_specialized_init_append (value, &ctx);
while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
{
GValue eltval = {0, };
g_value_init (&eltval, subtype);
if (!demarshaller (context, &subiter, &eltval, error))
{
dbus_g_type_specialized_collection_end_append (&ctx);
g_value_unset (value);
return FALSE;
}
dbus_g_type_specialized_collection_append (&ctx, &eltval);
dbus_message_iter_next (&subiter);
}
dbus_g_type_specialized_collection_end_append (&ctx);
return TRUE;
}
static gboolean
demarshal_collection_array (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
DBusMessageIter subiter;
GArray *ret;
GType elt_gtype;
int elt_size;
void *msgarray;
int msgarray_len;
dbus_message_iter_recurse (iter, &subiter);
elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
g_assert (elt_gtype != G_TYPE_INVALID);
g_assert (_dbus_g_type_is_fixed (elt_gtype));
elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
ret = g_array_new (FALSE, TRUE, elt_size);
msgarray = NULL;
dbus_message_iter_get_fixed_array (&subiter,
&msgarray,
&msgarray_len);
g_assert (msgarray != NULL || msgarray_len == 0);
if (msgarray_len)
g_array_append_vals (ret, msgarray, (guint) msgarray_len);
g_value_set_boxed_take_ownership (value, ret);
return TRUE;
}
gboolean
_dbus_gvalue_demarshal (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
GType gtype;
DBusGValueDemarshalFunc demarshaller;
gtype = G_VALUE_TYPE (value);
demarshaller = get_type_demarshaller (gtype);
if (demarshaller == NULL)
{
g_set_error (error,
DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("No demarshaller registered for type \"%s\""),
g_type_name (gtype));
return FALSE;
}
return demarshaller (context, iter, value, error);
}
gboolean
_dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx *context,
DBusMessageIter *iter,
GValue *value,
GError **error)
{
return demarshal_static_variant (context, iter, value, error);
}
GValueArray *
_dbus_gvalue_demarshal_message (DBusGValueMarshalCtx *context,
DBusMessage *message,
guint n_types,
const GType *types,
GError **error)
{
GValueArray *ret;
DBusMessageIter iter;
int current_type;
guint index_;
ret = g_value_array_new (6); /* 6 is a typical maximum for arguments */
dbus_message_iter_init (message, &iter);
index_ = 0;
while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
{
GValue *value;
GType gtype;
if (index_ >= n_types)
{
g_set_error (error, DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Too many arguments in message"));
goto lose;
}
g_value_array_append (ret, NULL);
value = g_value_array_get_nth (ret, index_);
gtype = types[index_];
g_value_init (value, gtype);
if (!_dbus_gvalue_demarshal (context, &iter, value, error))
goto lose;
dbus_message_iter_next (&iter);
index_++;
}
if (index_ < n_types)
{
g_set_error (error, DBUS_GERROR,
DBUS_GERROR_INVALID_ARGS,
_("Too few arguments in message"));
goto lose;
}
return ret;
lose:
g_value_array_free (ret);
return NULL;
}
static gboolean
marshal_basic (DBusMessageIter *iter, const GValue *value)
{
GType value_type;
value_type = G_VALUE_TYPE (value);
switch (value_type)
{
case G_TYPE_CHAR:
{
char b = g_value_get_char (value);
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_BYTE,
&b))
goto nomem;
}
return TRUE;
case G_TYPE_UCHAR:
{
unsigned char b = g_value_get_uchar (value);
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_BYTE,
&b))
goto nomem;
}
return TRUE;
case G_TYPE_BOOLEAN:
{
dbus_bool_t b = g_value_get_boolean (value);
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_BOOLEAN,
&b))
goto nomem;
}
return TRUE;
case G_TYPE_INT:
{
dbus_int32_t v = g_value_get_int (value);
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_INT32,
&v))
goto nomem;
}
return TRUE;
case G_TYPE_UINT:
{
dbus_uint32_t v = g_value_get_uint (value);
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_UINT32,
&v))
goto nomem;
}
return TRUE;
case G_TYPE_LONG:
{
dbus_int32_t v = g_value_get_long (value);
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_INT32,
&v))
goto nomem;
}
return TRUE;
case G_TYPE_ULONG:
{
dbus_uint32_t v = g_value_get_ulong (value);
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_UINT32,
&v))
goto nomem;
}
return TRUE;
case G_TYPE_INT64:
{
gint64 v = g_value_get_int64 (value);
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_INT64,
&v))
goto nomem;
}
return TRUE;
case G_TYPE_UINT64:
{
guint64 v = g_value_get_uint64 (value);
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_UINT64,
&v))
goto nomem;
}
return TRUE;
case G_TYPE_FLOAT:
{
double v = g_value_get_float (value);
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_DOUBLE,
&v))
goto nomem;
}
return TRUE;
case G_TYPE_DOUBLE:
{
double v = g_value_get_double (value);
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_DOUBLE,
&v))
goto nomem;
}
return TRUE;
case G_TYPE_STRING:
/* FIXME, the GValue string may not be valid UTF-8 */
{
const char *v = g_value_get_string (value);
if (!v)
v = "";
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_STRING,
&v))
goto nomem;
}
return TRUE;
default:
{
g_assert_not_reached ();
return FALSE;
}
}
nomem:
g_error ("no memory");
return FALSE;
}
static gboolean
marshal_strv (DBusMessageIter *iter,
const GValue *value)
{
DBusMessageIter subiter;
char **array;
char **elt;
gboolean ret = FALSE;
g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
array = g_value_get_boxed (value);
if (!dbus_message_iter_open_container (iter,
DBUS_TYPE_ARRAY,
"s",
&subiter))
goto out;
if (array)
{
for (elt = array; *elt; elt++)
{
if (!dbus_message_iter_append_basic (&subiter,
DBUS_TYPE_STRING,
elt))
goto out;
}
}
if (!dbus_message_iter_close_container (iter, &subiter))
goto out;
ret = TRUE;
out:
return ret;
}
static gboolean
marshal_valuearray (DBusMessageIter *iter,
const GValue *value)
{
GValueArray *array;
guint i;
DBusMessageIter subiter;
g_assert (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
array = g_value_get_boxed (value);
if (!dbus_message_iter_open_container (iter,
DBUS_TYPE_STRUCT,
NULL,
&subiter))
goto oom;
if (array)
{
for (i = 0; i < array->n_values; i++)
{
if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
return FALSE;
}
}
if (!dbus_message_iter_close_container (iter, &subiter))
goto oom;
return TRUE;
oom:
g_error ("out of memory");
return FALSE;
}
static gboolean
marshal_proxy (DBusMessageIter *iter,
const GValue *value)
{
const char *path;
DBusGProxy *proxy;
g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
proxy = g_value_get_object (value);
path = dbus_g_proxy_get_path (proxy);
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_OBJECT_PATH,
&path))
return FALSE;
return TRUE;
}
static gboolean
marshal_object_path (DBusMessageIter *iter,
const GValue *value)
{
const char *path;
g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
path = (const char*) g_value_get_boxed (value);
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_OBJECT_PATH,
&path))
return FALSE;
return TRUE;
}
static gboolean
marshal_object (DBusMessageIter *iter,
const GValue *value)
{
const char *path;
GObject *obj;
obj = g_value_get_object (value);
path = _dbus_gobject_get_path (obj);
if (path == NULL)
/* FIXME should throw error */
return FALSE;
if (!dbus_message_iter_append_basic (iter,
DBUS_TYPE_OBJECT_PATH,
&path))
return FALSE;
return TRUE;
}
struct DBusGLibHashMarshalData
{
const char *entry_sig;
DBusMessageIter *iter;
gboolean err;
};
static void
marshal_map_entry (const GValue *key,
const GValue *value,
gpointer data)
{
struct DBusGLibHashMarshalData *hashdata = data;
DBusMessageIter subiter;
if (hashdata->err)
return;
if (!dbus_message_iter_open_container (hashdata->iter,
DBUS_TYPE_DICT_ENTRY,
NULL,
&subiter))
goto lose;
if (!_dbus_gvalue_marshal (&subiter, key))
goto lose;
if (!_dbus_gvalue_marshal (&subiter, value))
goto lose;
if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
goto lose;
return;
lose:
hashdata->err = TRUE;
}
static gboolean
marshal_map (DBusMessageIter *iter,
const GValue *value)
{
GType gtype;
DBusMessageIter arr_iter;
gboolean ret;
struct DBusGLibHashMarshalData hashdata;
char *key_sig;
char *value_sig;
GType key_type;
GType value_type;
char *entry_sig;
char *array_sig;
gtype = G_VALUE_TYPE (value);
ret = FALSE;
key_type = dbus_g_type_get_map_key_specialization (gtype);
g_assert (_dbus_gtype_is_valid_hash_key (key_type));
value_type = dbus_g_type_get_map_value_specialization (gtype);
g_assert (_dbus_gtype_is_valid_hash_value (value_type));
key_sig = _dbus_gtype_to_signature (key_type);
if (!key_sig)
{
g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
return FALSE;
}
value_sig = _dbus_gtype_to_signature (value_type);
if (!value_sig)
{
g_free (key_sig);
g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
return FALSE;
}
entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
g_free (key_sig);
g_free (value_sig);
array_sig = g_strdup_printf ("%c%s%c",
DBUS_DICT_ENTRY_BEGIN_CHAR,
entry_sig,
DBUS_DICT_ENTRY_END_CHAR);
if (!dbus_message_iter_open_container (iter,
DBUS_TYPE_ARRAY,
array_sig,
&arr_iter))
goto lose;
hashdata.iter = &arr_iter;
hashdata.err = FALSE;
hashdata.entry_sig = entry_sig;
dbus_g_type_map_value_iterate (value,
marshal_map_entry,
&hashdata);
if (!dbus_message_iter_close_container (iter, &arr_iter))
goto lose;
out:
g_free (entry_sig);
g_free (array_sig);
return !hashdata.err;
lose:
hashdata.err = TRUE;
goto out;
}
static gboolean
marshal_struct (DBusMessageIter *iter,
const GValue *value)
{
GType gtype;
DBusMessageIter subiter;
gboolean ret;
guint size, i;
GValue val = {0,};
gtype = G_VALUE_TYPE (value);
ret = FALSE;
size = dbus_g_type_get_struct_size (gtype);
if (!dbus_message_iter_open_container (iter,
DBUS_TYPE_STRUCT,
NULL,
&subiter))
goto oom;
for (i = 0; i < size; i++)
{
g_value_init (&val, dbus_g_type_get_struct_member_type
(G_VALUE_TYPE(value), i));
if (!dbus_g_type_struct_get_member (value, i, &val))
return FALSE;
if (!_dbus_gvalue_marshal (&subiter, &val))
return FALSE;
g_value_unset(&val);
}
if (!dbus_message_iter_close_container (iter, &subiter))
goto oom;
return TRUE;
oom:
g_error ("out of memory");
return FALSE;
}
static gboolean
marshal_variant (DBusMessageIter *iter,
const GValue *value)
{
GType value_gtype;
DBusMessageIter subiter;
char *variant_sig;
GValue *real_value;
gboolean ret = FALSE;
real_value = g_value_get_boxed (value);
value_gtype = G_VALUE_TYPE (real_value);
variant_sig = _dbus_gvalue_to_signature (real_value);
if (variant_sig == NULL)
{
g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
return FALSE;
}
if (!dbus_message_iter_open_container (iter,
DBUS_TYPE_VARIANT,
variant_sig,
&subiter))
goto out;
if (!_dbus_gvalue_marshal (&subiter, real_value))
goto out;
if (!dbus_message_iter_close_container (iter, &subiter))
goto out;
ret = TRUE;
out:
g_free (variant_sig);
return ret;
}
static DBusGValueMarshalFunc
get_type_marshaller (GType type)
{
DBusGTypeMarshalData *typedata;
typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
if (typedata == NULL)
{
if (g_type_is_a (type, G_TYPE_VALUE_ARRAY))
return marshal_valuearray;
if (dbus_g_type_is_collection (type))
return marshal_collection;
if (dbus_g_type_is_map (type))
return marshal_map;
if (dbus_g_type_is_struct (type))
return marshal_struct;
g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
return NULL;
}
g_assert (typedata->vtable);
return typedata->vtable->marshaller;
}
typedef struct
{
DBusMessageIter *iter;
DBusGValueMarshalFunc marshaller;
gboolean err;
} DBusGValueCollectionMarshalData;
static void
collection_marshal_iterator (const GValue *eltval,
gpointer user_data)
{
DBusGValueCollectionMarshalData *data = user_data;
if (data->err)
return;
if (!data->marshaller (data->iter, eltval))
data->err = TRUE;
}
static gboolean
marshal_collection (DBusMessageIter *iter,
const GValue *value)
{
GType coltype;
GType subtype;
coltype = G_VALUE_TYPE (value);
subtype = dbus_g_type_get_collection_specialization (coltype);
if (_dbus_g_type_is_fixed (subtype))
return marshal_collection_array (iter, value);
else
return marshal_collection_ptrarray (iter, value);
}
static gboolean
marshal_collection_ptrarray (DBusMessageIter *iter,
const GValue *value)
{
GType coltype;
GType elt_gtype;
DBusGValueCollectionMarshalData data;
DBusMessageIter subiter;
char *elt_sig;
coltype = G_VALUE_TYPE (value);
elt_gtype = dbus_g_type_get_collection_specialization (coltype);
data.marshaller = get_type_marshaller (elt_gtype);
if (!data.marshaller)
return FALSE;
elt_sig = _dbus_gtype_to_signature (elt_gtype);
if (!elt_sig)
{
g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
return FALSE;
}
if (!dbus_message_iter_open_container (iter,
DBUS_TYPE_ARRAY,
elt_sig,
&subiter))
goto oom;
g_free (elt_sig);
data.iter = &subiter;
data.err = FALSE;
dbus_g_type_collection_value_iterate (value,
collection_marshal_iterator,
&data);
if (!dbus_message_iter_close_container (iter, &subiter))
goto oom;
return !data.err;
oom:
g_error ("out of memory");
return FALSE;
}
static gboolean
marshal_collection_array (DBusMessageIter *iter,
const GValue *value)
{
GType elt_gtype;
DBusMessageIter subiter;
GArray *array;
guint elt_size;
char *subsignature_str;
elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
g_assert (_dbus_g_type_is_fixed (elt_gtype));
subsignature_str = _dbus_gtype_to_signature (elt_gtype);
if (!subsignature_str)
{
g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
return FALSE;
}
elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
array = g_value_get_boxed (value);
if (!dbus_message_iter_open_container (iter,
DBUS_TYPE_ARRAY,
subsignature_str,
&subiter))
goto oom;
/* TODO - This assumes that basic values are the same size
* is this always true? If it is we can probably avoid
* a lot of the overhead in _marshal_basic_instance...
*/
if (!array || !dbus_message_iter_append_fixed_array (&subiter,
subsignature_str[0],
&(array->data),
array->len))
goto oom;
if (!dbus_message_iter_close_container (iter, &subiter))
goto oom;
g_free (subsignature_str);
return TRUE;
oom:
g_error ("out of memory");
return FALSE;
}
gboolean
_dbus_gvalue_marshal (DBusMessageIter *iter,
const GValue *value)
{
GType gtype;
DBusGValueMarshalFunc marshaller;
gtype = G_VALUE_TYPE (value);
marshaller = get_type_marshaller (gtype);
if (marshaller == NULL)
return FALSE;
return marshaller (iter, value);
}
#ifdef DBUS_BUILD_TESTS
static void
assert_type_maps_to (GType gtype, const char *expected_sig)
{
char *sig;
sig = _dbus_gtype_to_signature (gtype);
g_assert (sig != NULL);
g_assert (!strcmp (expected_sig, sig));
g_free (sig);
}
static void
assert_signature_maps_to (const char *sig, GType expected_gtype)
{
g_assert (_dbus_gtype_from_signature (sig, TRUE) == expected_gtype);
}
static void
assert_bidirectional_mapping (GType gtype, const char *expected_sig)
{
assert_type_maps_to (gtype, expected_sig);
assert_signature_maps_to (expected_sig, gtype);
}
/**
* @ingroup DBusGLibInternals
* @test_data_dir:
*
* Unit test for general glib stuff
* Returns: #TRUE on success.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
gboolean
_dbus_gvalue_test (const char *test_data_dir)
{
_dbus_g_value_types_init ();
assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
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);
assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
assert_bidirectional_mapping (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID),
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 );
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */