/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-gtype-specialized.c: Non-DBus-specific functions for specialized GTypes
*
* Copyright (C) 2005 Red Hat, Inc.
* Copyright (C) 2007 Codethink Ltd.
* 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 "dbus-gtype-specialized.h"
#include <glib.h>
#include <string.h>
#include <gobject/gvaluecollector.h>
#ifdef __SYMBIAN32__
#ifndef DBUS_GTOOL_STATIC_LIBRARY_BUILD
#include "libdbus_glib_wsd_solution.h"
#endif
#endif
/**
* SECTION:dbus-gtype-specialized
* @short_description: Specialized GTypes
* @stability: Unstable
*
* Specialized gtypes are basically a way to allow the definition of
* recursive GTypes. It allows the definition of 'containers' which is
* basically a user defined structure capabale of holding other data and a
* set of functions defining how to access that structure. Containers come in
* 3 flavors: collections, maps and structs.
*
* A collection is a container that holds an ordered set of items, all
* of which must be the same type.
*
* A map is a container that holds a set of key/value pairs.
* The keys have one type, and the values another.
*
* A struct is a container that holds a fixed number of members, each member
* having a predefined type.
*
* A specialization is a GType detailing a particular container with
* particular types (a type specialization).
*
* Functions are provided for constructing and manipulating specializations.
*
* This documentation needs splitting into two pages, one for defining new
* containers and using existing containers. I expect most users to only do
* the latter. I also need to add some examples.
*/
typedef enum {
DBUS_G_SPECTYPE_COLLECTION,
DBUS_G_SPECTYPE_MAP,
DBUS_G_SPECTYPE_STRUCT
} DBusGTypeSpecializedType;
typedef struct {
DBusGTypeSpecializedType type;
const DBusGTypeSpecializedVtable *vtable;
} DBusGTypeSpecializedContainer;
typedef struct {
guint num_types;
GType *types;
const DBusGTypeSpecializedContainer *klass;
} DBusGTypeSpecializedData;
#if EMULATOR
GET_STATIC_VAR_FROM_TLS(specialized_containers,dbus_gtype_specialized,GHashTable *)
#define specialized_containers (*GET_DBUS_WSD_VAR_NAME(specialized_containers,dbus_gtype_specialized,s)())
#else
static GHashTable /* char * -> data* */ *specialized_containers;
#endif
#if EMULATOR
GET_STATIC_VAR_FROM_TLS(quark,dbus_gtype_specialized,GQuark )
#define quark (*GET_DBUS_WSD_VAR_NAME(quark,dbus_gtype_specialized,s)())
#endif
static GQuark
specialized_type_data_quark ()
{
#ifndef EMULATOR
static GQuark quark;
#endif
if (!quark)
quark = g_quark_from_static_string ("DBusGTypeSpecializedData");
return quark;
}
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_type_specialized_init (void)
{
specialized_containers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
}
static gboolean
specialized_types_is_initialized (void)
{
return specialized_containers != NULL;
}
static DBusGTypeSpecializedData *
lookup_specialization_data (GType type)
{
return g_type_get_qdata (type, specialized_type_data_quark ());
}
/* Copied from gboxed.c */
static void
proxy_value_init (GValue *value)
{
value->data[0].v_pointer = NULL;
}
/* Adapted from gboxed.c */
static void
proxy_value_free (GValue *value)
{
if (value->data[0].v_pointer && !(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS))
{
DBusGTypeSpecializedData *data;
GType type;
type = G_VALUE_TYPE (value);
data = lookup_specialization_data (type);
g_assert (data != NULL);
if (data->klass->vtable->free_func)
{
data->klass->vtable->free_func (type, value->data[0].v_pointer);
}
else
{
g_assert (data->klass->vtable->simple_free_func != NULL);
data->klass->vtable->simple_free_func (value->data[0].v_pointer);
}
}
}
/* Adapted from gboxed.c */
static void
proxy_value_copy (const GValue *src_value,
GValue *dest_value)
{
if (src_value->data[0].v_pointer)
{
DBusGTypeSpecializedData *data;
GType type;
type = G_VALUE_TYPE (src_value);
data = lookup_specialization_data (type);
g_assert (data != NULL);
dest_value->data[0].v_pointer = data->klass->vtable->copy_func (type, src_value->data[0].v_pointer);
}
else
dest_value->data[0].v_pointer = src_value->data[0].v_pointer;
}
/* Copied from gboxed.c */
static gpointer
proxy_value_peek_pointer (const GValue *value)
{
return value->data[0].v_pointer;
}
/* Adapted from gboxed.c */
static gchar*
proxy_collect_value (GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags)
{
DBusGTypeSpecializedData *data;
GType type;
type = G_VALUE_TYPE (value);
data = lookup_specialization_data (type);
if (!collect_values[0].v_pointer)
value->data[0].v_pointer = NULL;
else
{
if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
{
value->data[0].v_pointer = collect_values[0].v_pointer;
value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
}
else
{
value->data[0].v_pointer = data->klass->vtable->copy_func (type, collect_values[0].v_pointer);
}
}
return NULL;
}
/* Adapted from gboxed.c */
static gchar*
proxy_lcopy_value (const GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags)
{
gpointer *boxed_p = collect_values[0].v_pointer;
if (!boxed_p)
return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
if (!value->data[0].v_pointer)
*boxed_p = NULL;
else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
*boxed_p = value->data[0].v_pointer;
else
{
DBusGTypeSpecializedData *data;
GType type;
type = G_VALUE_TYPE (value);
data = lookup_specialization_data (type);
*boxed_p = data->klass->vtable->copy_func (type, value->data[0].v_pointer);
}
return NULL;
}
static char *
build_specialization_name (const char *prefix, guint num_types, const GType *types)
{
GString *fullname;
guint i;
fullname = g_string_new (prefix);
g_string_append_c (fullname, '_');
for (i=0; i < num_types; i++)
{
if (i!=0)
g_string_append_c (fullname, '+');
g_string_append (fullname, g_type_name (types[i]));
}
g_string_append_c (fullname, '_');
return g_string_free (fullname, FALSE);
}
static void
register_container (const char *name,
DBusGTypeSpecializedType type,
const DBusGTypeSpecializedVtable *vtable)
{
DBusGTypeSpecializedContainer *klass;
klass = g_new0 (DBusGTypeSpecializedContainer, 1);
klass->type = type;
klass->vtable = vtable;
g_hash_table_insert (specialized_containers, g_strdup (name), klass);
}
/**
* dbus_g_type_register_collection:
* @name: The name of a new collection container
* @vtable: the vtable defining the new container
* @flags: As yet unused.
*
* Defines a new collection container.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_type_register_collection (const char *name,
const DBusGTypeSpecializedCollectionVtable *vtable,
guint flags)
{
g_return_if_fail (specialized_types_is_initialized ());
register_container (name, DBUS_G_SPECTYPE_COLLECTION, (const DBusGTypeSpecializedVtable*) vtable);
}
/**
* dbus_g_type_register_map:
* @name: The name of a new map container
* @vtable: the vtable defining the new container
* @flags: As yet unused.
*
* Defines a new map container.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_type_register_map (const char *name,
const DBusGTypeSpecializedMapVtable *vtable,
guint flags)
{
g_return_if_fail (specialized_types_is_initialized ());
register_container (name, DBUS_G_SPECTYPE_MAP, (const DBusGTypeSpecializedVtable*) vtable);
}
/**
* dbus_g_type_register_struct:
* @name: The name of a new struct container
* @vtable: the vtable defining the new container
* @flags: As yet unused.
*
* Defines a new struct container.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_type_register_struct (const char *name,
const DBusGTypeSpecializedStructVtable *vtable,
guint flags)
{
g_return_if_fail (specialized_types_is_initialized ());
register_container (name, DBUS_G_SPECTYPE_STRUCT, (const DBusGTypeSpecializedVtable*) vtable);
}
/**
* dbus_g_type_map_peek_vtable:
* @map_type: a gtype of a map specialization
*
* Peek the vtable for a given map specialization
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
const DBusGTypeSpecializedMapVtable* dbus_g_type_map_peek_vtable (GType map_type)
{
DBusGTypeSpecializedData *data;
g_return_val_if_fail (dbus_g_type_is_map(map_type), NULL);
data = lookup_specialization_data (map_type);
g_assert (data != NULL);
return (DBusGTypeSpecializedMapVtable *)(data->klass->vtable);
}
/**
* dbus_g_type_collection_peek_vtable:
* @collection_type: a gtype of a collection specialization
*
* Peek the vtable for a given collection specialization
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
const DBusGTypeSpecializedCollectionVtable* dbus_g_type_collection_peek_vtable (GType collection_type)
{
DBusGTypeSpecializedData *data;
g_return_val_if_fail (dbus_g_type_is_collection(collection_type), NULL);
data = lookup_specialization_data (collection_type);
g_assert (data != NULL);
return (DBusGTypeSpecializedCollectionVtable *)(data->klass->vtable);
}
/**
* dbus_g_type_struct_peek_vtable:
* @collection_type: a gtype of a struct specialization
*
* Peek the vtable for a given struct specialization
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
const DBusGTypeSpecializedStructVtable* dbus_g_type_struct_peek_vtable (GType struct_type)
{
DBusGTypeSpecializedData *data;
g_return_val_if_fail (dbus_g_type_is_struct (struct_type), NULL);
data = lookup_specialization_data (struct_type);
g_assert (data != NULL);
return (DBusGTypeSpecializedStructVtable *)(data->klass->vtable);
}
static GType
register_specialized_instance (const DBusGTypeSpecializedContainer *klass,
const char *name,
guint num_types,
const GType *types)
{
GType ret;
static const GTypeValueTable vtable =
{
proxy_value_init,
proxy_value_free,
proxy_value_copy,
proxy_value_peek_pointer,
"p",
proxy_collect_value,
"p",
proxy_lcopy_value,
};
static const GTypeInfo derived_info =
{
0, /* class_size */
NULL, /* base_init */
NULL, /* base_finalize */
NULL, /* class_init */
NULL, /* class_finalize */
NULL, /* class_data */
0, /* instance_size */
0, /* n_preallocs */
NULL, /* instance_init */
&vtable, /* value_table */
};
ret = g_type_register_static (G_TYPE_BOXED, name, &derived_info, 0);
/* install proxy functions upon successfull registration */
if (ret != G_TYPE_INVALID)
{
DBusGTypeSpecializedData *data;
data = g_new0 (DBusGTypeSpecializedData, 1);
data->num_types = num_types;
data->types = g_memdup (types, sizeof (GType) * num_types);
data->klass = klass;
g_type_set_qdata (ret, specialized_type_data_quark (), data);
}
return ret;
}
static GType
lookup_or_register_specialized (const char *container,
guint num_types,
const GType *types)
{
GType ret;
char *name;
const DBusGTypeSpecializedContainer *klass;
g_return_val_if_fail (specialized_types_is_initialized (), G_TYPE_INVALID);
klass = g_hash_table_lookup (specialized_containers, container);
g_return_val_if_fail (klass != NULL, G_TYPE_INVALID);
name = build_specialization_name (container, num_types, types);
ret = g_type_from_name (name);
if (ret == G_TYPE_INVALID)
{
/* Take ownership of name */
ret = register_specialized_instance (klass, name,
num_types,
types);
}
g_free (name);
return ret;
}
/**
* dbus_g_type_get_collection:
* @container: a string specifying a registered collection type
* @specialization: #GType of collection elements
*
* Gets a #GType for a particular collection instance,
* creating the type if not already created.
*
* Returns: the #GType of that instance
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
GType
dbus_g_type_get_collection (const char *container,
GType specialization)
{
return lookup_or_register_specialized (container, 1, &specialization);
}
/**
* dbus_g_type_get_map:
* @container: a string specifying a registered map type
* @key_specialization: #GType of keys
* @value_specialization: #GType of values
*
* Gets a #GType for a particular map instance,
* creating the type if not already created.
*
* Returns: the #GType of that instance
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
GType
dbus_g_type_get_map (const char *container,
GType key_specialization,
GType value_specialization)
{
GType returnValue = 0;
#ifdef __SYMBIAN32__
GType types[2];
types[0] = key_specialization;
types[1] = value_specialization;
returnValue = lookup_or_register_specialized (container, 2, types);
#else
GType types[2] = {key_specialization, value_specialization};
returnValue = lookup_or_register_specialized (container, 2, types);
#endif
return returnValue;
}
/**
* dbus_g_type_get_structv:
* @container: a string specifying a registered struct type
* @num_members: number of members in the struct
* @types: an array specufying a GType for each struct element
*
* Gets a #GType for a particular struct instance,
* creating the type if not already created.
*
* Returns: the #GType of that instance
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
GType
dbus_g_type_get_structv (const char *container,
guint num_members,
GType *types)
{
return lookup_or_register_specialized (container, num_members, types);
}
/**
* dbus_g_type_get_struct:
* @container: a string specifying a registered struct type
* @first_type: #GType for the struct's first member
* @...: more GTypes for the struct's members, terminated by G_TYPE_INVALID
*
* Varags methsod to get a #GType for a particular struct instance,
* creating the type if not already created.
*
* Returns: the #GType of that instance
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
GType
dbus_g_type_get_struct (const char *container,
GType first_type,
...)
{
GArray *types;
GType curtype, ret;
va_list args;
va_start (args, first_type);
types = g_array_new (FALSE, FALSE, sizeof (GType));
curtype = first_type;
while (curtype != G_TYPE_INVALID)
{
g_array_append_val (types, curtype);
curtype = va_arg (args, GType);
}
va_end (args);
ret = lookup_or_register_specialized (container, types->len,
(GType *) types->data);
g_array_free (types, TRUE);
return ret;
}
/**
* dbus_g_type_is_collection:
* @gtype: a GType to test
*
* Tests if a given GType is a collection.
*
* Returns: true if the given GType is a collection
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
gboolean
dbus_g_type_is_collection (GType gtype)
{
DBusGTypeSpecializedData *data;
data = lookup_specialization_data (gtype);
if (data == NULL)
return FALSE;
return data->klass->type == DBUS_G_SPECTYPE_COLLECTION;
}
/**
* dbus_g_type_is_map:
* @gtype: a GType to test
*
* Tests if a given GType is a map,
* i.e. it was created with #dbus_g_type_get_map.
*
* Returns: true if the given GType is a map
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
gboolean
dbus_g_type_is_map (GType gtype)
{
DBusGTypeSpecializedData *data;
data = lookup_specialization_data (gtype);
if (data == NULL)
return FALSE;
return data->klass->type == DBUS_G_SPECTYPE_MAP;
}
/**
* dbus_g_type_is_struct:
* @gtype: a GType to test
*
* Tests if a given GType is a struct,
* i.e. it was created with #dbus_g_type_get_struct
*
* Returns: true if the given GType is a struct
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
gboolean
dbus_g_type_is_struct (GType gtype)
{
DBusGTypeSpecializedData *data;
data = lookup_specialization_data (gtype);
if (data == NULL)
return FALSE;
return data->klass->type == DBUS_G_SPECTYPE_STRUCT;
}
static GType
get_specialization_index (GType gtype, guint i)
{
DBusGTypeSpecializedData *data;
data = lookup_specialization_data (gtype);
if (i < data->num_types)
return data->types[i];
else
return G_TYPE_INVALID;
}
/**
* dbus_g_type_get_collection_specialization:
* @gtype: a collection GType, as created by #dbus_g_type_get_collection.
*
* Returns: the element type for a given collection GType.
* Returns G_TYPE_INVALID if not a collection GType
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
GType
dbus_g_type_get_collection_specialization (GType gtype)
{
g_return_val_if_fail (dbus_g_type_is_collection (gtype), G_TYPE_INVALID);
return get_specialization_index (gtype, 0);
}
/**
* dbus_g_type_get_map_key_specialization:
* @gtype: a map GType, as created by #dbus_g_type_get_map.
*
* Returns: the key type for a given map GType.
* Returns G_TYPE_INVALID if not a map GType
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
GType
dbus_g_type_get_map_key_specialization (GType gtype)
{
g_return_val_if_fail (dbus_g_type_is_map (gtype), G_TYPE_INVALID);
return get_specialization_index (gtype, 0);
}
/**
* dbus_g_type_get_map_value_specialization:
* @gtype: a map GType, as created by #dbus_g_type_get_map.
*
* Returns: the value type for a given map GType.
* Returns G_TYPE_INVALID if not a map GType
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
GType
dbus_g_type_get_map_value_specialization (GType gtype)
{
g_return_val_if_fail (dbus_g_type_is_map (gtype), G_TYPE_INVALID);
return get_specialization_index (gtype, 1);
}
/**
* dbus_g_type_get_struct_member_type
* @gtype: a struct GType, as created with #dbus_g_type_get_struct
* @member: the index of a struct member
*
* Returns: the type for a given member of a struct #GType.
* Returns G_TYPE_INVALID if not a struct GType
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
GType
dbus_g_type_get_struct_member_type (GType gtype, guint member)
{
g_return_val_if_fail (dbus_g_type_is_struct (gtype), G_TYPE_INVALID);
return get_specialization_index (gtype, member);
}
/**
* dbus_g_type_get_struct_size
* @gtype: a struct GType, as created with #dbus_g_type_get_struct.
*
* Returns: the number of members in a given struct #GType.
* Returns G_TYPE_INVALID if not a struct GType
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
guint
dbus_g_type_get_struct_size (GType gtype)
{
DBusGTypeSpecializedData *data;
g_return_val_if_fail (dbus_g_type_is_struct (gtype), G_TYPE_INVALID);
data = lookup_specialization_data (gtype);
return data->num_types;
}
/**
* dbus_g_type_specialized_construct:
* @gtype: a specialized #GType, as created by #dbus_g_type_get_collection, #dbus_g_type_get_map or #dbus_g_type_get_struct.
*
* Create an instance of a given specialized type.
* The structure created and returned will depend on the container type of the
* GType. E.g. If the given type was created by
* dbus_g_type_get_collection("GArray", G_TYPE_INT),
* then this will return a GArray with element_size of sizeof(int)
*
* Returns: a pointer to a newly constructed instance of the given type.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
gpointer
dbus_g_type_specialized_construct (GType gtype)
{
DBusGTypeSpecializedData *data;
g_return_val_if_fail (specialized_types_is_initialized (), FALSE);
data = lookup_specialization_data (gtype);
g_return_val_if_fail (data != NULL, FALSE);
return data->klass->vtable->constructor (gtype);
}
/**
* dbus_g_type_collection_get_fixed:
* @deprecated: maybe?
*
* if the collection has elements of fixed size (i.e. a fundamental type),
* return the contents of the array.
* Its pretty obscure and I don't think anyone uses it.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
gboolean
dbus_g_type_collection_get_fixed (GValue *value,
gpointer *data_ret,
guint *len_ret)
{
DBusGTypeSpecializedData *data;
GType gtype;
g_return_val_if_fail (specialized_types_is_initialized (), FALSE);
g_return_val_if_fail (G_VALUE_HOLDS_BOXED (value), FALSE);
gtype = G_VALUE_TYPE (value);
data = lookup_specialization_data (gtype);
g_return_val_if_fail (data != NULL, FALSE);
return ((DBusGTypeSpecializedCollectionVtable *) (data->klass->vtable))->fixed_accessor (gtype,
g_value_get_boxed (value),
data_ret, len_ret);
}
/**
* dbus_g_type_collection_value_iterate:
* @value: a #GValue holding a collection type.
* @iterator: a function to call for each element
* @user_data: user data to pass to the @iterator
*
* Calls the given function for each element of the collection.
* The function is passed a #GValue containing the element and the given
* @user_data parameter. The collection may not be modified while iterating over
* it.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_type_collection_value_iterate (const GValue *value,
DBusGTypeSpecializedCollectionIterator iterator,
gpointer user_data)
{
DBusGTypeSpecializedData *data;
GType gtype;
g_return_if_fail (specialized_types_is_initialized ());
g_return_if_fail (G_VALUE_HOLDS_BOXED (value));
gtype = G_VALUE_TYPE (value);
data = lookup_specialization_data (gtype);
g_return_if_fail (data != NULL);
((DBusGTypeSpecializedCollectionVtable *) data->klass->vtable)->iterator (gtype,
g_value_get_boxed (value),
iterator, user_data);
}
typedef struct {
GValue *val;
GType specialization_type;
DBusGTypeSpecializedData *specdata;
} DBusGTypeSpecializedAppendContextReal;
/**
* dbus_g_type_specialized_init_append:
* @value: a #GValue containing an instance of specialized type
* @ctx: a #DBusGTypeSpecializedAppendContext in which to return a new appending context.
* @deprecated: maybe i'll deprecate this as its a bit wank.
*
* Create a new context for adding elements to a collection or key/value pairs
* to a map. You generally don't need or want to use this..
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_type_specialized_init_append (GValue *value, DBusGTypeSpecializedAppendContext *ctx)
{
DBusGTypeSpecializedAppendContextReal *realctx = (DBusGTypeSpecializedAppendContextReal *) ctx;
GType gtype;
DBusGTypeSpecializedData *specdata;
g_return_if_fail (specialized_types_is_initialized ());
g_return_if_fail (G_VALUE_HOLDS_BOXED (value));
gtype = G_VALUE_TYPE (value);
specdata = lookup_specialization_data (gtype);
g_return_if_fail (specdata != NULL);
g_return_if_fail (specdata->num_types != 0);
realctx->val = value;
realctx->specialization_type = specdata->types[0];
realctx->specdata = specdata;
}
/**
* dbus_g_type_specialized_collection_append:
* @ctx: a context created by #dbus_g_type_specialized_init_append
* @elt: a GValue containing an element to append to the collection.
* @deprecated: maybe i'll deprecate this as its a bit wank.
*
* Appends a given element to the end of a collection.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_type_specialized_collection_append (DBusGTypeSpecializedAppendContext *ctx,
GValue *elt)
{
DBusGTypeSpecializedAppendContextReal *realctx = (DBusGTypeSpecializedAppendContextReal *) ctx;
((DBusGTypeSpecializedCollectionVtable *) realctx->specdata->klass->vtable)->append_func (ctx, elt);
}
/**
* dbus_g_type_specialized_collection_end_append:
* @ctx: a context created by #dbus_g_type_specialized_init_append
* @deprecated: maybe i'll deprecate this as its a bit wank.
*
* Finish appending elements to a given collection
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_type_specialized_collection_end_append (DBusGTypeSpecializedAppendContext *ctx)
{
DBusGTypeSpecializedAppendContextReal *realctx = (DBusGTypeSpecializedAppendContextReal *) ctx;
if (((DBusGTypeSpecializedCollectionVtable *) realctx->specdata->klass->vtable)->end_append_func != NULL)
((DBusGTypeSpecializedCollectionVtable *) realctx->specdata->klass->vtable)->end_append_func (ctx);
}
/**
* dbus_g_type_specialized_map_append:
* @ctx: a context created by #dbus_g_type_specialized_init_append
* @key: a GValue containing a key
* @val: a GValue containing a value
* @deprecated: maybe i'll deprecate this as its a bit wank.
*
* Inserts the given key/value pair into the map instance.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_type_specialized_map_append (DBusGTypeSpecializedAppendContext *ctx,
GValue *key,
GValue *val)
{
DBusGTypeSpecializedAppendContextReal *realctx = (DBusGTypeSpecializedAppendContextReal *) ctx;
((DBusGTypeSpecializedMapVtable *) realctx->specdata->klass->vtable)->append_func (ctx, key, val);
}
/**
* dbus_g_type_map_value_iterate:
* @value: a #GValue holding a collection type.
* @iterator: a function to call for each element
* @user_data: user data to pass to the @iterator
*
* Calls the given function for each key/value pair of the map.
* The function is passed two GValues containing the key/value pair and the given
* @user_data parameter. The map may not be modified while iterating over
* it.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
void
dbus_g_type_map_value_iterate (const GValue *value,
DBusGTypeSpecializedMapIterator iterator,
gpointer user_data)
{
DBusGTypeSpecializedData *data;
GType gtype;
g_return_if_fail (specialized_types_is_initialized ());
g_return_if_fail (G_VALUE_HOLDS_BOXED (value));
gtype = G_VALUE_TYPE (value);
data = lookup_specialization_data (gtype);
g_return_if_fail (data != NULL);
((DBusGTypeSpecializedMapVtable *) data->klass->vtable)->iterator (gtype,
g_value_get_boxed (value),
iterator, user_data);
}
/**
* dbus_g_type_struct_get_member:
* @value: a #GValue containing a struct instance
* @member: the index of a given member
* @dest: an initialised #GValue in which to return the struct member
*
* Fetches a given member of a given struct instance. @dest must be initialised
* was the correct type for that member, e.g. as returned by
* @dbus_g_type_get_struct_member_type
*
* Returns: TRUE if sucessful
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
gboolean
dbus_g_type_struct_get_member (const GValue *value,
guint member,
GValue *dest)
{
DBusGTypeSpecializedData *data;
GType gtype;
g_return_val_if_fail (specialized_types_is_initialized (), FALSE);
g_return_val_if_fail (G_VALUE_HOLDS_BOXED (value), FALSE);
gtype = G_VALUE_TYPE (value);
data = lookup_specialization_data (gtype);
g_return_val_if_fail (data != NULL, FALSE);
return ((DBusGTypeSpecializedStructVtable *) (data->klass->vtable))->get_member(gtype,
g_value_get_boxed (value),
member, dest);
}
/**
* dbus_g_type_struct_set_member:
* @value: a #GValue containing a struct instance
* @member: the index of a given member
* @src: an #GValue containing the new value for that struct member
*
* Sets a given member of a struct to a new value. The type of @src must match
* the exiting type of @member member of the struct.
*
* Returns: TRUE if sucessful
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
gboolean
dbus_g_type_struct_set_member (GValue *value,
guint member,
const GValue *src)
{
DBusGTypeSpecializedData *data;
GType gtype;
g_return_val_if_fail (specialized_types_is_initialized (), FALSE);
g_return_val_if_fail (G_VALUE_HOLDS_BOXED (value), FALSE);
gtype = G_VALUE_TYPE (value);
data = lookup_specialization_data (gtype);
g_return_val_if_fail (data != NULL, FALSE);
return ((DBusGTypeSpecializedStructVtable *) (data->klass->vtable))->set_member(gtype,
g_value_get_boxed (value),
member, src);
}
/**
* dbus_g_type_struct_get:
* @value: a #GValue containing a #DBusGTypeStruct type
* @member: struct member to get
* @...: location in which to return the value of this member,
* followed optionally by more member/return locations pairs, followed by
* by #G_MAXUINT
*
* Collects the selected values of this struct into the return locations
* provided.
*
* Returns: #FALSE on failure
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
gboolean
dbus_g_type_struct_get (const GValue *value,
guint first_member,
...)
{
va_list var_args;
GType type;
guint size,i;
gchar *error;
GValue val = {0,};
g_return_val_if_fail (dbus_g_type_is_struct (G_VALUE_TYPE (value)), FALSE);
va_start (var_args, first_member);
size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value));
i = first_member;
while (i != G_MAXUINT)
{
if (i >= size)
goto error;
type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE (value),i);
g_value_init (&val, type);
dbus_g_type_struct_get_member (value, i, &val);
G_VALUE_LCOPY (&val, var_args, 0, &error);
if (error)
{
g_warning ("%s, %s", G_STRFUNC, error);
g_free (error);
g_value_unset (&val);
goto error;
}
g_value_unset (&val);
i = va_arg (var_args, guint);
}
va_end (var_args);
return TRUE;
error:
va_end (var_args);
return FALSE;
}
/**
* dbus_g_type_struct_set:
* @value: a #GValue containing a #DBusGTypeStruct type
* @member: struct member to set
* @...: value for the first member, followed optionally by
* more member/value pairs, followed by #G_MAXUINT
*
* Sets the selected members of the struct in @value.
*
* Returns: #FALSE on failure
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
gboolean
dbus_g_type_struct_set (GValue *value,
guint first_member,
...)
{
va_list var_args;
GType type;
guint size,i;
gchar *error;
GValue val = {0,};
g_return_val_if_fail (dbus_g_type_is_struct (G_VALUE_TYPE (value)), FALSE);
va_start (var_args, first_member);
size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value));
i = first_member;
while (i != G_MAXUINT)
{
if (i >= size)
goto error;
type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE (value),i);
g_value_init (&val, type);
G_VALUE_COLLECT (&val, var_args, 0, &error);
if (error)
{
g_warning ("%s, %s", G_STRFUNC, error);
g_free (error);
g_value_unset (&val);
goto error;
}
dbus_g_type_struct_set_member (value, i, &val);
g_value_unset (&val);
i = va_arg (var_args, guint);
}
va_end (var_args);
return TRUE;
error:
va_end (var_args);
return FALSE;
}