Update contrib.
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-gvalue-utils.c: Non-DBus-specific functions related to GType/GValue
4 * Copyright (C) 2005 Red Hat, Inc.
5 * Portion Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #endif //__SYMBIAN32__
29 #include "dbus/dbus-glib.h"
30 #include "dbus-gvalue-utils.h"
31 #include "dbus-gtest.h"
34 #include <gobject/gvaluecollector.h>
38 fixed_type_get_size (GType type)
44 return sizeof (gchar);
46 return sizeof (gboolean);
49 return sizeof (glong);
55 return sizeof (gint64);
57 return sizeof (gfloat);
59 return sizeof (gdouble);
66 _dbus_g_type_is_fixed (GType type)
68 return fixed_type_get_size (type) > 0;
72 _dbus_g_type_fixed_get_size (GType type)
74 g_assert (_dbus_g_type_is_fixed (type));
75 return fixed_type_get_size (type);
79 _dbus_gvalue_store (GValue *value,
82 /* FIXME - can we use the GValue lcopy_value method
83 * to do this in a cleaner way?
85 switch (g_type_fundamental (G_VALUE_TYPE (value)))
88 *((gchar *) storage) = g_value_get_char (value);
91 *((guchar *) storage) = g_value_get_uchar (value);
94 *((gboolean *) storage) = g_value_get_boolean (value);
97 *((glong *) storage) = g_value_get_long (value);
100 *((gulong *) storage) = g_value_get_ulong (value);
103 *((gint *) storage) = g_value_get_int (value);
106 *((guint *) storage) = g_value_get_uint (value);
109 *((gint64 *) storage) = g_value_get_int64 (value);
112 *((guint64 *) storage) = g_value_get_uint64 (value);
115 *((gdouble *) storage) = g_value_get_double (value);
118 *((gchar **) storage) = (char*) g_value_get_string (value);
121 *((gpointer *) storage) = g_value_get_object (value);
124 *((gpointer *) storage) = g_value_get_boxed (value);
132 _dbus_gvalue_set_from_pointer (GValue *value,
133 gconstpointer storage)
135 /* FIXME - is there a better way to do this? */
136 switch (g_type_fundamental (G_VALUE_TYPE (value)))
139 g_value_set_char (value, *((gchar *) storage));
142 g_value_set_uchar (value, *((guchar *) storage));
145 g_value_set_boolean (value, *((gboolean *) storage));
148 g_value_set_long (value, *((glong *) storage));
151 g_value_set_ulong (value, *((gulong *) storage));
154 g_value_set_int (value, *((gint *) storage));
157 g_value_set_uint (value, *((guint *) storage));
160 g_value_set_int64 (value, *((gint64 *) storage));
163 g_value_set_uint64 (value, *((guint64 *) storage));
166 g_value_set_double (value, *((gdouble *) storage));
169 g_value_set_string (value, *((gchar **) storage));
172 g_value_set_object (value, *((gpointer *) storage));
175 g_value_set_boxed (value, *((gpointer *) storage));
183 _dbus_gvalue_take (GValue *value,
187 GTypeValueTable *value_table;
190 g_type = G_VALUE_TYPE (value);
191 value_table = g_type_value_table_peek (g_type);
193 error_msg = value_table->collect_value (value, 1, cvalue, G_VALUE_NOCOPY_CONTENTS);
196 g_warning ("%s: %s", G_STRLOC, error_msg);
200 /* Clear the NOCOPY_CONTENTS flag; we want to take ownership
203 value->data[1].v_uint &= ~(G_VALUE_NOCOPY_CONTENTS);
208 _dbus_gtype_can_signal_error (GType gtype)
225 _dbus_gvalue_signals_error (const GValue *value)
227 /* Hardcoded rules for return value semantics for certain
228 * types. Perhaps in the future we'd want an annotation
229 * specifying which return values are errors, but in
230 * reality people will probably just use boolean and
231 * boxed, and there the semantics are pretty standard.
233 switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)))
236 return (g_value_get_boolean (value) == FALSE);
239 return (g_value_get_int (value) < 0);
242 return (g_value_get_uint (value) == 0);
245 return (g_value_get_string (value) == NULL);
248 return (g_value_get_boxed (value) == NULL);
251 return (g_value_get_object (value) == NULL);
254 g_assert_not_reached ();
260 hash_func_from_gtype (GType gtype, GHashFunc *func)
280 unset_and_free_g_value (gpointer val)
284 g_value_unset (value);
289 hash_free_from_gtype (GType gtype, GDestroyNotify *func)
305 if (gtype == G_TYPE_VALUE)
307 *func = unset_and_free_g_value;
310 else if (gtype == G_TYPE_VALUE_ARRAY)
312 *func = (GDestroyNotify) g_value_array_free;
315 else if (dbus_g_type_is_collection (gtype))
317 const DBusGTypeSpecializedCollectionVtable* vtable;
318 vtable = dbus_g_type_collection_peek_vtable (gtype);
319 if (vtable->base_vtable.simple_free_func)
321 *func = vtable->base_vtable.simple_free_func;
325 else if (dbus_g_type_is_map (gtype))
327 const DBusGTypeSpecializedMapVtable* vtable;
328 vtable = dbus_g_type_map_peek_vtable (gtype);
329 if (vtable->base_vtable.simple_free_func)
331 *func = vtable->base_vtable.simple_free_func;
335 else if (dbus_g_type_is_struct (gtype))
337 const DBusGTypeSpecializedStructVtable *vtable;
338 vtable = dbus_g_type_struct_peek_vtable (gtype);
339 if (vtable->base_vtable.simple_free_func)
341 *func = vtable->base_vtable.simple_free_func;
350 _dbus_gtype_is_valid_hash_key (GType type)
353 return hash_func_from_gtype (type, &func);
357 _dbus_gtype_is_valid_hash_value (GType type)
360 return hash_free_from_gtype (type, &func);
364 _dbus_g_hash_func_from_gtype (GType gtype)
368 ret = hash_func_from_gtype (gtype, &func);
369 g_assert (ret != FALSE);
374 _dbus_g_hash_equal_from_gtype (GType gtype)
376 g_assert (_dbus_gtype_is_valid_hash_key (gtype));
389 g_assert_not_reached ();
395 _dbus_g_hash_free_from_gtype (GType gtype)
399 ret = hash_free_from_gtype (gtype, &func);
400 g_assert (ret != FALSE);
404 static void gvalue_take_ptrarray_value (GValue *value, gpointer instance);
407 gvalue_take_hash_value (GValue *value, gpointer instance)
409 switch (g_type_fundamental (G_VALUE_TYPE (value)))
412 g_value_set_char (value, (gchar) GPOINTER_TO_INT (instance));
415 g_value_set_uchar (value, (guchar) GPOINTER_TO_UINT (instance));
418 g_value_set_boolean (value, (gboolean) GPOINTER_TO_UINT (instance));
421 g_value_set_int (value, GPOINTER_TO_INT (instance));
424 g_value_set_uint (value, GPOINTER_TO_UINT (instance));
427 g_value_set_double (value, *(gdouble *) instance);
430 gvalue_take_ptrarray_value (value, instance);
435 static gpointer ptrarray_value_from_gvalue (const GValue *value);
438 hash_value_from_gvalue (GValue *value)
440 switch (g_type_fundamental (G_VALUE_TYPE (value)))
443 return GINT_TO_POINTER ((int) g_value_get_char (value));
446 return GUINT_TO_POINTER ((guint) g_value_get_uchar (value));
449 return GUINT_TO_POINTER ((guint) g_value_get_boolean (value));
452 return GINT_TO_POINTER (g_value_get_int (value));
455 return GUINT_TO_POINTER (g_value_get_uint (value));
459 gdouble *p = (gdouble *) g_malloc0 (sizeof (gdouble));
460 *p = g_value_get_double (value);
465 return ptrarray_value_from_gvalue (value);
470 struct DBusGHashTableValueForeachData
472 DBusGTypeSpecializedMapIterator func;
479 hashtable_foreach_with_values (gpointer key, gpointer value, gpointer user_data)
481 GValue key_val = {0, };
482 GValue value_val = {0, };
483 struct DBusGHashTableValueForeachData *data = user_data;
485 g_value_init (&key_val, data->key_type);
486 g_value_init (&value_val, data->value_type);
487 gvalue_take_hash_value (&key_val, key);
488 gvalue_take_hash_value (&value_val, value);
490 data->func (&key_val, &value_val, data->data);
495 hashtable_iterator (GType hash_type,
497 DBusGTypeSpecializedMapIterator iterator,
500 struct DBusGHashTableValueForeachData data;
504 key_gtype = dbus_g_type_get_map_key_specialization (hash_type);
505 value_gtype = dbus_g_type_get_map_value_specialization (hash_type);
507 data.func = iterator;
508 data.key_type = key_gtype;
509 data.value_type = value_gtype;
510 data.data = user_data;
512 g_hash_table_foreach (instance, hashtable_foreach_with_values, &data);
516 _dbus_g_hash_table_insert_steal_values (GHashTable *table,
522 key = hash_value_from_gvalue (key_val);
523 val = hash_value_from_gvalue (value_val);
525 g_hash_table_insert (table, key, val);
529 hashtable_append (DBusGTypeSpecializedAppendContext *ctx,
535 table = g_value_get_boxed (ctx->val);
536 _dbus_g_hash_table_insert_steal_values (table, key, val);
540 hashtable_constructor (GType type)
546 key_gtype = dbus_g_type_get_map_key_specialization (type);
547 value_gtype = dbus_g_type_get_map_value_specialization (type);
549 ret = g_hash_table_new_full (_dbus_g_hash_func_from_gtype (key_gtype),
550 _dbus_g_hash_equal_from_gtype (key_gtype),
551 _dbus_g_hash_free_from_gtype (key_gtype),
552 _dbus_g_hash_free_from_gtype (value_gtype));
557 hashtable_insert_values (GHashTable *table,
558 const GValue *key_val,
559 const GValue *value_val)
561 GValue key_copy = {0, };
562 GValue value_copy = {0, };
564 g_value_init (&key_copy, G_VALUE_TYPE (key_val));
565 g_value_copy (key_val, &key_copy);
566 g_value_init (&value_copy, G_VALUE_TYPE (value_val));
567 g_value_copy (value_val, &value_copy);
569 _dbus_g_hash_table_insert_steal_values (table, &key_copy, &value_copy);
573 hashtable_foreach_copy (const GValue *key, const GValue *val, gpointer data)
575 hashtable_insert_values ((GHashTable *) data, key, val);
579 hashtable_copy (GType type, gpointer src)
583 GValue hashval = {0,};
587 ret = hashtable_constructor (type);
589 g_value_init (&hashval, type);
590 g_value_set_static_boxed (&hashval, ghash);
591 dbus_g_type_map_value_iterate (&hashval, hashtable_foreach_copy, ret);
596 hashtable_simple_free (gpointer val)
598 g_hash_table_destroy (val);
602 valuearray_constructor (GType type)
605 guint size = dbus_g_type_get_struct_size (type);
607 ret = g_value_array_new (size);
608 for (i=0; i < size; i++)
611 g_value_init (&val, dbus_g_type_get_struct_member_type (type, i));
612 g_value_array_append(ret, &val);
614 return (gpointer)ret;
618 valuearray_copy (GType type, gpointer src)
620 return g_value_array_copy ((GValueArray*) src);
624 valuearray_simple_free (gpointer val)
626 g_value_array_free (val);
630 valuearray_get_member (GType type, gpointer instance,
631 guint member, GValue *ret)
633 GValueArray *va = (GValueArray*) instance;
635 if (member < dbus_g_type_get_struct_size (type))
637 val = g_value_array_get_nth (va, member);
638 g_value_copy (val, ret);
646 valuearray_set_member (GType type, gpointer instance,
647 guint member, const GValue *member_type)
649 GValueArray *va = (GValueArray*) instance;
651 if (member < dbus_g_type_get_struct_size (type))
653 vp = g_value_array_get_nth (va, member);
654 g_value_copy (member_type, vp);
663 array_constructor (GType type)
668 gboolean zero_terminated;
671 elt_type = dbus_g_type_get_collection_specialization (type);
672 g_assert (elt_type != G_TYPE_INVALID);
674 elt_size = _dbus_g_type_fixed_get_size (elt_type);
676 /* These are "safe" defaults */
677 zero_terminated = TRUE; /* ((struct _DBusGRealArray*) garray)->zero_terminated; */
678 clear = TRUE; /* ((struct _DBusGRealArray*) garray)->clear; */
680 array = g_array_new (zero_terminated, clear, elt_size);
685 array_copy (GType type, gpointer src)
692 new = array_constructor (type);
693 g_array_append_vals (new, garray->data, garray->len);
699 array_simple_free (gpointer val)
703 g_array_free (array, TRUE);
707 array_fixed_accessor (GType type, gpointer instance, gpointer *values, guint *len)
710 GArray *array = instance;
712 elt_type = dbus_g_type_get_collection_specialization (type);
713 if (!_dbus_g_type_is_fixed (elt_type))
716 *values = array->data;
722 ptrarray_constructor (GType type)
724 /* Later we should determine a destructor, need g_ptr_array_destroy */
725 return g_ptr_array_new ();
729 gvalue_take_ptrarray_value (GValue *value, gpointer instance)
731 switch (g_type_fundamental (G_VALUE_TYPE (value)))
734 g_value_take_string (value, instance);
737 g_value_take_boxed (value, instance);
740 g_value_take_object (value, instance);
743 g_assert_not_reached ();
749 ptrarray_value_from_gvalue (const GValue *value)
753 /* if the NOCOPY flag is set, then value was created via set_static and hence
754 * is not owned by us. in order to preserve the "take" semantics that the API
755 * has in general (which avoids copying in the common case), we must copy any
756 * static values so that we can indiscriminately free the entire collection
758 if (value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)
760 g_value_init (&tmp, G_VALUE_TYPE (value));
761 g_value_copy (value, &tmp);
765 switch (g_type_fundamental (G_VALUE_TYPE (value)))
768 return (gpointer) g_value_get_string (value);
771 return g_value_get_boxed (value);
774 return g_value_get_object (value);
777 g_assert_not_reached ();
783 ptrarray_iterator (GType ptrarray_type,
785 DBusGTypeSpecializedCollectionIterator iterator,
794 elt_gtype = dbus_g_type_get_collection_specialization (ptrarray_type);
796 for (i = 0; i < ptrarray->len; i++)
799 g_value_init (&val, elt_gtype);
800 gvalue_take_ptrarray_value (&val, g_ptr_array_index (ptrarray, i));
801 iterator (&val, user_data);
806 ptrarray_copy_elt (const GValue *val, gpointer user_data)
808 GPtrArray *dest = user_data;
809 GValue val_copy = {0, };
811 g_value_init (&val_copy, G_VALUE_TYPE (val));
812 g_value_copy (val, &val_copy);
814 g_ptr_array_add (dest, ptrarray_value_from_gvalue (&val_copy));
818 ptrarray_copy (GType type, gpointer src)
821 GValue array_val = {0, };
823 g_value_init (&array_val, type);
824 g_value_set_static_boxed (&array_val, src);
826 new = ptrarray_constructor (type);
827 dbus_g_type_collection_value_iterate (&array_val, ptrarray_copy_elt, new);
833 ptrarray_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value)
837 array = g_value_get_boxed (ctx->val);
839 g_ptr_array_add (array, ptrarray_value_from_gvalue (value));
843 ptrarray_free (GType type, gpointer val)
846 GValue elt_val = {0, };
852 elt_gtype = dbus_g_type_get_collection_specialization (type);
854 for (i = 0; i < array->len; i++)
856 g_value_init (&elt_val, elt_gtype);
857 gvalue_take_ptrarray_value (&elt_val, g_ptr_array_index (array, i));
858 g_value_unset (&elt_val);
861 g_ptr_array_free (array, TRUE);
865 slist_constructor (GType type)
871 slist_iterator (GType list_type,
873 DBusGTypeSpecializedCollectionIterator iterator,
881 elt_gtype = dbus_g_type_get_collection_specialization (list_type);
883 for (slist = instance; slist != NULL; slist = slist->next)
886 g_value_init (&val, elt_gtype);
887 gvalue_take_ptrarray_value (&val, slist->data);
888 iterator (&val, user_data);
893 slist_copy_elt (const GValue *val, gpointer user_data)
895 GSList **dest = user_data;
896 GValue val_copy = {0, };
898 g_value_init (&val_copy, G_VALUE_TYPE (val));
899 g_value_copy (val, &val_copy);
901 *dest = g_slist_append (*dest, ptrarray_value_from_gvalue (&val_copy));
905 slist_copy (GType type, gpointer src)
908 GValue slist_val = {0, };
910 g_value_init (&slist_val, type);
911 g_value_set_static_boxed (&slist_val, src);
913 new = slist_constructor (type);
914 dbus_g_type_collection_value_iterate (&slist_val, slist_copy_elt, &new);
920 slist_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value)
924 list = g_value_get_boxed (ctx->val);
925 list = g_slist_prepend (list, ptrarray_value_from_gvalue (value));
926 g_value_set_static_boxed (ctx->val, list);
930 slist_end_append (DBusGTypeSpecializedAppendContext *ctx)
934 /* if you append multiple times to the slist, this will reverse the existing
935 * elements... we need an init_append function */
936 list = g_value_get_boxed (ctx->val);
937 list = g_slist_reverse (list);
939 g_value_take_boxed (ctx->val, list);
943 slist_free (GType type, gpointer val)
949 elt_gtype = dbus_g_type_get_collection_specialization (type);
953 GValue elt_val = {0, };
954 g_value_init (&elt_val, elt_gtype);
955 gvalue_take_ptrarray_value (&elt_val, list->data);
956 g_value_unset (&elt_val);
957 list = g_slist_next(list);
964 _dbus_g_type_specialized_builtins_init (void)
966 /* types with a simple_free function can be freed at run-time without
967 * the destroy function needing to know the type, so they can be
968 * stored in hash tables */
970 static const DBusGTypeSpecializedCollectionVtable array_vtable = {
979 array_fixed_accessor,
986 static const DBusGTypeSpecializedCollectionVtable ptrarray_vtable = {
988 ptrarray_constructor,
1002 static const DBusGTypeSpecializedCollectionVtable slist_vtable = {
1017 static const DBusGTypeSpecializedMapVtable hashtable_vtable = {
1019 hashtable_constructor,
1022 hashtable_simple_free,
1030 static const DBusGTypeSpecializedStructVtable valuearray_vtable = {
1032 valuearray_constructor,
1035 valuearray_simple_free,
1039 valuearray_get_member,
1040 valuearray_set_member
1043 dbus_g_type_register_collection ("GSList", &slist_vtable, 0);
1044 dbus_g_type_register_collection ("GArray", &array_vtable, 0);
1045 dbus_g_type_register_collection ("GPtrArray", &ptrarray_vtable, 0);
1046 dbus_g_type_register_map ("GHashTable", &hashtable_vtable, 0);
1047 dbus_g_type_register_struct ("GValueArray", &valuearray_vtable, 0);
1050 #ifdef DBUS_BUILD_TESTS
1056 } TestSpecializedHashData;
1059 test_specialized_hash (const GValue *key, const GValue *val, gpointer user_data)
1061 TestSpecializedHashData *data = user_data;
1063 g_assert (G_VALUE_HOLDS_STRING (key));
1064 g_assert (G_VALUE_HOLDS_STRING (val));
1066 if (!strcmp (g_value_get_string (key), "foo"))
1068 data->seen_foo = TRUE;
1069 g_assert (!strcmp (g_value_get_string (val), "bar"));
1071 else if (!strcmp (g_value_get_string (key), "baz"))
1073 data->seen_baz = TRUE;
1074 g_assert (!strcmp (g_value_get_string (val), "moo"));
1078 g_assert_not_reached ();
1083 test_specialized_hash_2 (const GValue *key, const GValue *val, gpointer user_data)
1085 TestSpecializedHashData *data = user_data;
1086 const GValue *realval;
1088 g_assert (G_VALUE_HOLDS_STRING (key));
1089 g_assert (G_VALUE_TYPE (val) == G_TYPE_VALUE);
1091 realval = g_value_get_boxed (val);
1093 if (!strcmp (g_value_get_string (key), "foo"))
1095 data->seen_foo = TRUE;
1096 g_assert (G_VALUE_HOLDS_UINT (realval));
1097 g_assert (g_value_get_uint (realval) == 20);
1099 else if (!strcmp (g_value_get_string (key), "baz"))
1101 data->seen_baz = TRUE;
1102 g_assert (G_VALUE_HOLDS_STRING (realval));
1103 g_assert (!strcmp ("bar", g_value_get_string (realval)));
1107 g_assert_not_reached ();
1111 #ifdef __SYMBIAN32__
1115 _dbus_gvalue_utils_test (const char *datadir)
1119 dbus_g_type_specialized_init ();
1120 _dbus_g_type_specialized_builtins_init ();
1122 type = dbus_g_type_get_collection ("GArray", G_TYPE_UINT);
1123 g_assert (dbus_g_type_is_collection (type));
1124 g_assert (dbus_g_type_get_collection_specialization (type) == G_TYPE_UINT);
1128 instance = dbus_g_type_specialized_construct (type);
1130 g_assert (instance->len == 0);
1132 g_array_free (instance, TRUE);
1135 type = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING);
1136 g_assert (dbus_g_type_is_map (type));
1137 g_assert (dbus_g_type_get_map_key_specialization (type) == G_TYPE_STRING);
1138 g_assert (dbus_g_type_get_map_value_specialization (type) == G_TYPE_STRING);
1140 GHashTable *instance;
1141 GValue val = { 0, };
1142 TestSpecializedHashData hashdata;
1144 instance = dbus_g_type_specialized_construct (type);
1146 g_assert (g_hash_table_size (instance) == 0);
1147 g_hash_table_insert (instance, g_strdup ("foo"), g_strdup ("bar"));
1148 g_hash_table_insert (instance, g_strdup ("baz"), g_strdup ("moo"));
1149 g_assert (g_hash_table_size (instance) == 2);
1151 g_value_init (&val, type);
1152 g_value_set_boxed_take_ownership (&val, instance);
1153 hashdata.seen_foo = FALSE;
1154 hashdata.seen_baz = FALSE;
1155 dbus_g_type_map_value_iterate (&val,
1156 test_specialized_hash,
1159 g_assert (hashdata.seen_foo);
1160 g_assert (hashdata.seen_baz);
1162 g_value_unset (&val);
1165 type = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE);
1166 g_assert (dbus_g_type_is_map (type));
1167 g_assert (dbus_g_type_get_map_key_specialization (type) == G_TYPE_STRING);
1168 g_assert (dbus_g_type_get_map_value_specialization (type) == G_TYPE_VALUE);
1170 GHashTable *instance;
1171 GValue val = { 0, };
1172 TestSpecializedHashData hashdata;
1173 DBusGTypeSpecializedAppendContext ctx;
1176 instance = dbus_g_type_specialized_construct (type);
1177 g_value_init (&val, type);
1178 g_value_set_boxed_take_ownership (&val, instance);
1180 dbus_g_type_specialized_init_append (&val, &ctx);
1183 GValue keyval = { 0, };
1184 GValue valval = { 0, };
1185 g_value_init (&keyval, G_TYPE_STRING);
1186 g_value_set_string (&keyval, "foo");
1188 g_value_init (&valval, G_TYPE_VALUE);
1189 eltval = g_new0 (GValue, 1);
1190 g_value_init (eltval, G_TYPE_UINT);
1191 g_value_set_uint (eltval, 20);
1192 g_value_set_boxed_take_ownership (&valval, eltval);
1193 dbus_g_type_specialized_map_append (&ctx, &keyval, &valval);
1197 GValue keyval = { 0, };
1198 GValue valval = { 0, };
1199 g_value_init (&keyval, G_TYPE_STRING);
1200 g_value_set_string (&keyval, "baz");
1201 g_value_init (&valval, G_TYPE_VALUE);
1202 eltval = g_new0 (GValue, 1);
1203 g_value_init (eltval, G_TYPE_STRING);
1204 g_value_set_string (eltval, "bar");
1205 g_value_set_boxed_take_ownership (&valval, eltval);
1206 dbus_g_type_specialized_map_append (&ctx, &keyval, &valval);
1209 hashdata.seen_foo = FALSE;
1210 hashdata.seen_baz = FALSE;
1211 dbus_g_type_map_value_iterate (&val,
1212 test_specialized_hash_2,
1215 g_assert (hashdata.seen_foo);
1216 g_assert (hashdata.seen_baz);
1218 g_value_unset (&val);
1221 type = dbus_g_type_get_collection ("GSList", G_TYPE_OBJECT);
1222 g_assert (dbus_g_type_is_collection (type));
1223 g_assert (dbus_g_type_get_collection_specialization (type) == G_TYPE_OBJECT);
1225 GSList *instance, *tmp, *copy;
1227 GValue copyval = {0, };
1228 DBusGTypeSpecializedAppendContext ctx;
1229 GObject *objects[3];
1232 instance = dbus_g_type_specialized_construct (type);
1233 g_assert (instance == NULL);
1235 g_value_init (&val, type);
1236 g_value_take_boxed (&val, instance);
1238 dbus_g_type_specialized_init_append (&val, &ctx);
1240 for (i = 0; i < 3; i++)
1242 GValue eltval = { 0, };
1243 GObject *obj = g_object_new (G_TYPE_OBJECT, NULL);
1245 g_assert (obj != NULL);
1247 g_object_add_weak_pointer (obj, (gpointer) (objects + i));
1249 g_value_init (&eltval, G_TYPE_OBJECT);
1250 g_value_take_object (&eltval, obj);
1251 dbus_g_type_specialized_collection_append (&ctx, &eltval);
1254 dbus_g_type_specialized_collection_end_append (&ctx);
1256 instance = g_value_get_boxed (&val);
1257 g_assert (g_slist_length (instance) == 3);
1259 for (tmp = instance; tmp; tmp = tmp->next)
1261 GObject *obj = tmp->data;
1262 g_assert (G_IS_OBJECT (obj));
1263 g_assert (obj->ref_count == 1);
1266 g_value_init (©val, type);
1267 g_value_copy (&val, ©val);
1269 copy = g_value_get_boxed (©val);
1270 g_assert (g_slist_length (copy) == 3);
1272 for (tmp = copy; tmp; tmp = tmp->next)
1274 GObject *obj = tmp->data;
1275 g_assert (G_IS_OBJECT (obj));
1276 g_assert (obj->ref_count == 2);
1279 g_value_unset (©val);
1281 for (i = 0; i < 3; i++)
1283 g_assert (objects[i] != NULL);
1286 for (tmp = instance; tmp; tmp = tmp->next)
1288 GObject *obj = tmp->data;
1289 g_assert (G_IS_OBJECT (obj));
1290 g_assert (obj->ref_count == 1);
1293 g_value_unset (&val);
1295 for (i = 0; i < 3; i++)
1297 g_assert (objects[i] == NULL);
1301 type = dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING);
1302 g_assert (dbus_g_type_is_collection (type));
1303 g_assert (dbus_g_type_get_collection_specialization (type) == G_TYPE_STRING);
1305 GPtrArray *instance;
1306 DBusGTypeSpecializedAppendContext ctx;
1308 GValue eltval = {0, };
1310 instance = dbus_g_type_specialized_construct (type);
1312 g_assert (instance->len == 0);
1314 g_value_init (&val, type);
1315 g_value_set_boxed_take_ownership (&val, instance);
1317 dbus_g_type_specialized_init_append (&val, &ctx);
1319 g_value_init (&eltval, G_TYPE_STRING);
1320 g_value_set_static_string (&eltval, "foo");
1321 dbus_g_type_specialized_collection_append (&ctx, &eltval);
1323 g_value_reset (&eltval);
1324 g_value_set_static_string (&eltval, "bar");
1325 dbus_g_type_specialized_collection_append (&ctx, &eltval);
1327 g_value_reset (&eltval);
1328 g_value_set_static_string (&eltval, "baz");
1329 dbus_g_type_specialized_collection_append (&ctx, &eltval);
1331 dbus_g_type_specialized_collection_end_append (&ctx);
1333 g_assert (instance->len == 3);
1335 g_assert (!strcmp ("foo", g_ptr_array_index (instance, 0)));
1336 g_assert (!strcmp ("bar", g_ptr_array_index (instance, 1)));
1337 g_assert (!strcmp ("baz", g_ptr_array_index (instance, 2)));
1339 g_value_unset (&val);
1342 type = dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_UINT, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
1343 g_assert (dbus_g_type_is_struct (type));
1344 g_assert (dbus_g_type_get_struct_size (type) == 3);
1345 g_assert (dbus_g_type_get_struct_member_type (type, 0) == G_TYPE_STRING);
1346 g_assert (dbus_g_type_get_struct_member_type (type, 1) == G_TYPE_UINT);
1347 g_assert (dbus_g_type_get_struct_member_type (type, 2) == DBUS_TYPE_G_OBJECT_PATH);
1349 GValueArray *instance;
1351 GValue memval = {0, };
1353 instance = dbus_g_type_specialized_construct (type);
1355 g_assert (instance->n_values == 3);
1357 g_value_init (&val, type);
1358 g_value_set_boxed_take_ownership (&val, instance);
1360 g_value_init (&memval, G_TYPE_STRING);
1361 g_value_set_static_string (&memval, "foo");
1362 dbus_g_type_struct_set_member (&val, 0, &memval);
1363 g_value_unset (&memval);
1365 g_value_init (&memval, G_TYPE_UINT);
1366 g_value_set_uint (&memval, 42);
1367 dbus_g_type_struct_set_member (&val, 1, &memval);
1368 g_value_unset (&memval);
1370 g_value_init (&memval, DBUS_TYPE_G_OBJECT_PATH);
1371 g_value_set_static_boxed (&memval, "/bar/moo/foo/baz");
1372 dbus_g_type_struct_set_member (&val, 2, &memval);
1373 g_value_unset (&memval);
1375 g_assert (instance->n_values == 3);
1377 g_value_init (&memval, G_TYPE_STRING);
1378 dbus_g_type_struct_get_member (&val, 0, &memval);
1379 g_assert (0 == strcmp (g_value_get_string (&memval), "foo"));
1380 g_value_unset (&memval);
1382 g_value_init (&memval, G_TYPE_UINT);
1383 dbus_g_type_struct_get_member (&val, 1, &memval);
1384 g_assert (g_value_get_uint (&memval) == 42);
1385 g_value_unset (&memval);
1387 g_value_init (&memval, DBUS_TYPE_G_OBJECT_PATH);
1388 dbus_g_type_struct_get_member (&val, 2, &memval);
1389 g_assert (0 == strcmp ((gchar*) g_value_get_boxed (&memval),
1390 "/bar/moo/foo/baz"));
1391 g_value_unset (&memval);
1393 g_value_unset (&val);
1396 type = dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_UINT, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
1397 g_assert (dbus_g_type_is_struct (type));
1398 g_assert (dbus_g_type_get_struct_size (type) == 3);
1399 g_assert (dbus_g_type_get_struct_member_type (type, 0) == G_TYPE_STRING);
1400 g_assert (dbus_g_type_get_struct_member_type (type, 1) == G_TYPE_UINT);
1401 g_assert (dbus_g_type_get_struct_member_type (type, 2) == DBUS_TYPE_G_OBJECT_PATH);
1403 GValueArray *instance;
1406 instance = dbus_g_type_specialized_construct (type);
1408 g_assert (instance->n_values == 3);
1410 g_value_init (&val, type);
1411 g_value_set_boxed_take_ownership (&val, instance);
1413 dbus_g_type_struct_set (&val,
1416 2, "/bar/moo/foo/baz",
1419 g_assert (instance->n_values == 3);
1426 dbus_g_type_struct_get (&val,
1432 g_assert (0 == strcmp (string, "foo"));
1433 g_assert (intval == 42);
1434 g_assert (0 == strcmp (path, "/bar/moo/foo/baz"));
1437 g_value_unset (&val);
1446 #endif /* DBUS_BUILD_TESTS */