00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025 #include "dbus/dbus-glib.h"
00026 #include "dbus-gvalue-utils.h"
00027 #include "dbus-gtest.h"
00028 #include <glib.h>
00029 #include <string.h>
00030 #include <gobject/gvaluecollector.h>
00031
00032
00033 static guint
00034 fixed_type_get_size (GType type)
00035 {
00036 switch (type)
00037 {
00038 case G_TYPE_CHAR:
00039 case G_TYPE_UCHAR:
00040 return sizeof (gchar);
00041 case G_TYPE_BOOLEAN:
00042 return sizeof (gboolean);
00043 case G_TYPE_LONG:
00044 case G_TYPE_ULONG:
00045 return sizeof (glong);
00046 case G_TYPE_INT:
00047 case G_TYPE_UINT:
00048 return sizeof (gint);
00049 case G_TYPE_INT64:
00050 case G_TYPE_UINT64:
00051 return sizeof (gint64);
00052 case G_TYPE_FLOAT:
00053 return sizeof (gfloat);
00054 case G_TYPE_DOUBLE:
00055 return sizeof (gdouble);
00056 default:
00057 return 0;
00058 }
00059 }
00060
00061 gboolean
00062 _dbus_g_type_is_fixed (GType type)
00063 {
00064 return fixed_type_get_size (type) > 0;
00065 }
00066
00067 guint
00068 _dbus_g_type_fixed_get_size (GType type)
00069 {
00070 g_assert (_dbus_g_type_is_fixed (type));
00071 return fixed_type_get_size (type);
00072 }
00073
00074 gboolean
00075 _dbus_gvalue_store (GValue *value,
00076 gpointer storage)
00077 {
00078
00079
00080
00081 switch (g_type_fundamental (G_VALUE_TYPE (value)))
00082 {
00083 case G_TYPE_CHAR:
00084 *((gchar *) storage) = g_value_get_char (value);
00085 return TRUE;
00086 case G_TYPE_UCHAR:
00087 *((guchar *) storage) = g_value_get_uchar (value);
00088 return TRUE;
00089 case G_TYPE_BOOLEAN:
00090 *((gboolean *) storage) = g_value_get_boolean (value);
00091 return TRUE;
00092 case G_TYPE_LONG:
00093 *((glong *) storage) = g_value_get_long (value);
00094 return TRUE;
00095 case G_TYPE_ULONG:
00096 *((gulong *) storage) = g_value_get_ulong (value);
00097 return TRUE;
00098 case G_TYPE_INT:
00099 *((gint *) storage) = g_value_get_int (value);
00100 return TRUE;
00101 case G_TYPE_UINT:
00102 *((guint *) storage) = g_value_get_uint (value);
00103 return TRUE;
00104 case G_TYPE_INT64:
00105 *((gint64 *) storage) = g_value_get_int64 (value);
00106 return TRUE;
00107 case G_TYPE_UINT64:
00108 *((guint64 *) storage) = g_value_get_uint64 (value);
00109 return TRUE;
00110 case G_TYPE_DOUBLE:
00111 *((gdouble *) storage) = g_value_get_double (value);
00112 return TRUE;
00113 case G_TYPE_STRING:
00114 *((gchar **) storage) = (char*) g_value_get_string (value);
00115 return TRUE;
00116 case G_TYPE_OBJECT:
00117 *((gpointer *) storage) = g_value_get_object (value);
00118 return TRUE;
00119 case G_TYPE_BOXED:
00120 *((gpointer *) storage) = g_value_get_boxed (value);
00121 return TRUE;
00122 default:
00123 return FALSE;
00124 }
00125 }
00126
00127 gboolean
00128 _dbus_gvalue_set_from_pointer (GValue *value,
00129 gconstpointer storage)
00130 {
00131
00132 switch (g_type_fundamental (G_VALUE_TYPE (value)))
00133 {
00134 case G_TYPE_CHAR:
00135 g_value_set_char (value, *((gchar *) storage));
00136 return TRUE;
00137 case G_TYPE_UCHAR:
00138 g_value_set_uchar (value, *((guchar *) storage));
00139 return TRUE;
00140 case G_TYPE_BOOLEAN:
00141 g_value_set_boolean (value, *((gboolean *) storage));
00142 return TRUE;
00143 case G_TYPE_LONG:
00144 g_value_set_long (value, *((glong *) storage));
00145 return TRUE;
00146 case G_TYPE_ULONG:
00147 g_value_set_ulong (value, *((gulong *) storage));
00148 return TRUE;
00149 case G_TYPE_INT:
00150 g_value_set_int (value, *((gint *) storage));
00151 return TRUE;
00152 case G_TYPE_UINT:
00153 g_value_set_uint (value, *((guint *) storage));
00154 return TRUE;
00155 case G_TYPE_INT64:
00156 g_value_set_int64 (value, *((gint64 *) storage));
00157 return TRUE;
00158 case G_TYPE_UINT64:
00159 g_value_set_uint64 (value, *((guint64 *) storage));
00160 return TRUE;
00161 case G_TYPE_DOUBLE:
00162 g_value_set_double (value, *((gdouble *) storage));
00163 return TRUE;
00164 case G_TYPE_STRING:
00165 g_value_set_string (value, *((gchar **) storage));
00166 return TRUE;
00167 case G_TYPE_OBJECT:
00168 g_value_set_object (value, *((gpointer *) storage));
00169 return TRUE;
00170 case G_TYPE_BOXED:
00171 g_value_set_boxed (value, *((gpointer *) storage));
00172 return TRUE;
00173 default:
00174 return FALSE;
00175 }
00176 }
00177
00178 gboolean
00179 _dbus_gvalue_take (GValue *value,
00180 GTypeCValue *cvalue)
00181 {
00182 GType g_type;
00183 GTypeValueTable *value_table;
00184 char *error_msg;
00185
00186 g_type = G_VALUE_TYPE (value);
00187 value_table = g_type_value_table_peek (g_type);
00188
00189 error_msg = value_table->collect_value (value, 1, cvalue, G_VALUE_NOCOPY_CONTENTS);
00190 if (error_msg)
00191 {
00192 g_warning ("%s: %s", G_STRLOC, error_msg);
00193 g_free (error_msg);
00194 return FALSE;
00195 }
00196
00197
00198
00199 value->data[1].v_uint &= ~(G_VALUE_NOCOPY_CONTENTS);
00200 return TRUE;
00201 }
00202
00203 gboolean
00204 _dbus_gtype_can_signal_error (GType gtype)
00205 {
00206 switch (gtype)
00207 {
00208 case G_TYPE_BOOLEAN:
00209 case G_TYPE_INT:
00210 case G_TYPE_UINT:
00211 case G_TYPE_STRING:
00212 case G_TYPE_BOXED:
00213 case G_TYPE_OBJECT:
00214 return TRUE;
00215 default:
00216 return FALSE;
00217 }
00218 }
00219
00220 gboolean
00221 _dbus_gvalue_signals_error (const GValue *value)
00222 {
00223
00224
00225
00226
00227
00228
00229 switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)))
00230 {
00231 case G_TYPE_BOOLEAN:
00232 return (g_value_get_boolean (value) == FALSE);
00233 break;
00234 case G_TYPE_INT:
00235 return (g_value_get_int (value) < 0);
00236 break;
00237 case G_TYPE_UINT:
00238 return (g_value_get_uint (value) == 0);
00239 break;
00240 case G_TYPE_STRING:
00241 return (g_value_get_string (value) == NULL);
00242 break;
00243 case G_TYPE_BOXED:
00244 return (g_value_get_boxed (value) == NULL);
00245 break;
00246 case G_TYPE_OBJECT:
00247 return (g_value_get_object (value) == NULL);
00248 break;
00249 default:
00250 g_assert_not_reached ();
00251 return FALSE;
00252 }
00253 }
00254
00255
00256 static gboolean
00257 hash_func_from_gtype (GType gtype, GHashFunc *func)
00258 {
00259 switch (gtype)
00260 {
00261 case G_TYPE_CHAR:
00262 case G_TYPE_UCHAR:
00263 case G_TYPE_BOOLEAN:
00264 case G_TYPE_INT:
00265 case G_TYPE_UINT:
00266 *func = NULL;
00267 return TRUE;
00268 case G_TYPE_STRING:
00269 *func = g_str_hash;
00270 return TRUE;
00271 default:
00272 if (gtype == DBUS_TYPE_G_OBJECT_PATH)
00273 {
00274 *func = g_str_hash;
00275 return TRUE;
00276 }
00277 else if (gtype == DBUS_TYPE_G_SIGNATURE)
00278 {
00279 *func = g_str_hash;
00280 return TRUE;
00281 }
00282 return FALSE;
00283 }
00284 }
00285
00286 static void
00287 unset_and_free_g_value (gpointer val)
00288 {
00289 GValue *value = val;
00290
00291 g_value_unset (value);
00292 g_free (value);
00293 }
00294
00295 static gboolean
00296 gtype_can_simple_free (GType type);
00297
00298 static gboolean
00299 hash_simple_free_from_gtype (GType gtype, GDestroyNotify *func)
00300 {
00301 switch (gtype)
00302 {
00303 case G_TYPE_CHAR:
00304 case G_TYPE_UCHAR:
00305 case G_TYPE_BOOLEAN:
00306 case G_TYPE_INT:
00307 case G_TYPE_UINT:
00308 *func = NULL;
00309 return TRUE;
00310 case G_TYPE_DOUBLE:
00311 case G_TYPE_STRING:
00312 *func = g_free;
00313 return TRUE;
00314 default:
00315 if (gtype == G_TYPE_VALUE)
00316 {
00317 *func = unset_and_free_g_value;
00318 return TRUE;
00319 }
00320 else if (gtype == G_TYPE_VALUE_ARRAY)
00321 {
00322 *func = (GDestroyNotify) g_value_array_free;
00323 return TRUE;
00324 }
00325 else if (gtype == G_TYPE_STRV)
00326 {
00327 *func = (GDestroyNotify) g_strfreev;
00328 return TRUE;
00329 }
00330 else if (gtype == DBUS_TYPE_G_OBJECT_PATH)
00331 {
00332 *func = g_free;
00333 return TRUE;
00334 }
00335 else if (gtype == DBUS_TYPE_G_SIGNATURE)
00336 {
00337 *func = g_free;
00338 return TRUE;
00339 }
00340 else if (dbus_g_type_is_collection (gtype))
00341 {
00342 const DBusGTypeSpecializedCollectionVtable* vtable;
00343 vtable = dbus_g_type_collection_peek_vtable (gtype);
00344 if (vtable->base_vtable.simple_free_func)
00345 {
00346 *func = vtable->base_vtable.simple_free_func;
00347 return TRUE;
00348 }
00349 }
00350 else if (dbus_g_type_is_map (gtype))
00351 {
00352 const DBusGTypeSpecializedMapVtable* vtable;
00353 GType key_gtype, value_gtype;
00354
00355 key_gtype = dbus_g_type_get_map_key_specialization (gtype);
00356 value_gtype = dbus_g_type_get_map_value_specialization (gtype);
00357
00358
00359
00360
00361
00362 if (!gtype_can_simple_free (key_gtype) ||
00363 !gtype_can_simple_free (value_gtype))
00364 return FALSE;
00365
00366 vtable = dbus_g_type_map_peek_vtable (gtype);
00367 if (vtable->base_vtable.simple_free_func)
00368 {
00369 *func = vtable->base_vtable.simple_free_func;
00370 return TRUE;
00371 }
00372 }
00373 else if (dbus_g_type_is_struct (gtype))
00374 {
00375 const DBusGTypeSpecializedStructVtable *vtable;
00376 vtable = dbus_g_type_struct_peek_vtable (gtype);
00377 if (vtable->base_vtable.simple_free_func)
00378 {
00379 *func = vtable->base_vtable.simple_free_func;
00380 return TRUE;
00381 }
00382 }
00383 return FALSE;
00384 }
00385 }
00386
00387 static gboolean
00388 gtype_can_simple_free (GType type)
00389 {
00390 GDestroyNotify func;
00391 return hash_simple_free_from_gtype (type, &func);
00392 }
00393
00394 gboolean
00395 _dbus_gtype_is_valid_hash_key (GType type)
00396 {
00397 GHashFunc func;
00398 return hash_func_from_gtype (type, &func);
00399 }
00400
00401 gboolean
00402 _dbus_gtype_is_valid_hash_value (GType gtype)
00403 {
00404
00405 switch (g_type_fundamental (gtype))
00406 {
00407 case G_TYPE_CHAR:
00408 case G_TYPE_UCHAR:
00409 case G_TYPE_BOOLEAN:
00410 case G_TYPE_INT:
00411 case G_TYPE_UINT:
00412 case G_TYPE_DOUBLE:
00413 case G_TYPE_STRING:
00414 case G_TYPE_BOXED:
00415 case G_TYPE_OBJECT:
00416 return TRUE;
00417 }
00418
00419 return FALSE;
00420 }
00421
00422 GHashFunc
00423 _dbus_g_hash_func_from_gtype (GType gtype)
00424 {
00425 GHashFunc func;
00426 gboolean ret;
00427 ret = hash_func_from_gtype (gtype, &func);
00428 g_assert (ret != FALSE);
00429 return func;
00430 }
00431
00432 GEqualFunc
00433 _dbus_g_hash_equal_from_gtype (GType gtype)
00434 {
00435 g_assert (_dbus_gtype_is_valid_hash_key (gtype));
00436
00437 switch (gtype)
00438 {
00439 case G_TYPE_CHAR:
00440 case G_TYPE_UCHAR:
00441 case G_TYPE_BOOLEAN:
00442 case G_TYPE_INT:
00443 case G_TYPE_UINT:
00444 return NULL;
00445 case G_TYPE_STRING:
00446 return g_str_equal;
00447 default:
00448 if (gtype == DBUS_TYPE_G_OBJECT_PATH)
00449 return g_str_equal;
00450 else if (gtype == DBUS_TYPE_G_SIGNATURE)
00451 return g_str_equal;
00452 g_assert_not_reached ();
00453 return NULL;
00454 }
00455 }
00456
00457 static void
00458 hash_fake_simple_free_func (gpointer val)
00459 {
00460
00461 g_critical ("If you see this message then the author of this application or "
00462 "one of its libraries has tried to remove or replace the value %p in a "
00463 "hash table which was constructed by the D-Bus Glib bindings.\n\n"
00464
00465 "However, it was not possible for the bindings to provide a destroy "
00466 "function to g_hash_table_new_full which is able to free this value, as "
00467 "its GType must be known in order to free it. This means the memory "
00468 "allocated to store the value has most likely just been leaked.\n\n"
00469
00470 "To avoid this error, the GHashTable (or keys/values \"stolen\" from "
00471 "it) should be freed by using g_boxed_free as follows:\n"
00472 " g_boxed_free (dbus_g_type_get_map (\"GHashTable\", key_gtype, "
00473 "value_gtype), hash_table);\n", val);
00474 }
00475
00476 GDestroyNotify
00477 _dbus_g_hash_free_from_gtype (GType gtype)
00478 {
00479 GDestroyNotify func;
00480 gboolean ret;
00481
00482 ret = hash_simple_free_from_gtype (gtype, &func);
00483
00484
00485
00486
00487
00488
00489 if (ret == FALSE)
00490 {
00491 g_assert (_dbus_gtype_is_valid_hash_value (gtype));
00492
00493 func = hash_fake_simple_free_func;
00494 }
00495
00496 return func;
00497 }
00498
00499 static void gvalue_take_ptrarray_value (GValue *value, gpointer instance);
00500
00501 static void
00502 gvalue_take_hash_value (GValue *value, gpointer instance)
00503 {
00504 switch (g_type_fundamental (G_VALUE_TYPE (value)))
00505 {
00506 case G_TYPE_CHAR:
00507 g_value_set_char (value, (gchar) GPOINTER_TO_INT (instance));
00508 break;
00509 case G_TYPE_UCHAR:
00510 g_value_set_uchar (value, (guchar) GPOINTER_TO_UINT (instance));
00511 break;
00512 case G_TYPE_BOOLEAN:
00513 g_value_set_boolean (value, (gboolean) GPOINTER_TO_UINT (instance));
00514 break;
00515 case G_TYPE_INT:
00516 g_value_set_int (value, GPOINTER_TO_INT (instance));
00517 break;
00518 case G_TYPE_UINT:
00519 g_value_set_uint (value, GPOINTER_TO_UINT (instance));
00520 break;
00521 case G_TYPE_DOUBLE:
00522 g_value_set_double (value, *(gdouble *) instance);
00523 break;
00524 default:
00525 gvalue_take_ptrarray_value (value, instance);
00526 break;
00527 }
00528 }
00529
00530 static gpointer ptrarray_value_from_gvalue (const GValue *value);
00531
00532 static gpointer
00533 hash_value_from_gvalue (GValue *value)
00534 {
00535 switch (g_type_fundamental (G_VALUE_TYPE (value)))
00536 {
00537 case G_TYPE_CHAR:
00538 return GINT_TO_POINTER ((int) g_value_get_char (value));
00539 break;
00540 case G_TYPE_UCHAR:
00541 return GUINT_TO_POINTER ((guint) g_value_get_uchar (value));
00542 break;
00543 case G_TYPE_BOOLEAN:
00544 return GUINT_TO_POINTER ((guint) g_value_get_boolean (value));
00545 break;
00546 case G_TYPE_INT:
00547 return GINT_TO_POINTER (g_value_get_int (value));
00548 break;
00549 case G_TYPE_UINT:
00550 return GUINT_TO_POINTER (g_value_get_uint (value));
00551 break;
00552 case G_TYPE_DOUBLE:
00553 {
00554 gdouble *p = (gdouble *) g_malloc0 (sizeof (gdouble));
00555 *p = g_value_get_double (value);
00556 return (gpointer) p;
00557 }
00558 break;
00559 default:
00560 return ptrarray_value_from_gvalue (value);
00561 break;
00562 }
00563 }
00564
00565 struct DBusGHashTableValueForeachData
00566 {
00567 DBusGTypeSpecializedMapIterator func;
00568 GType key_type;
00569 GType value_type;
00570 gpointer data;
00571 };
00572
00573 static void
00574 hashtable_foreach_with_values (gpointer key, gpointer value, gpointer user_data)
00575 {
00576 GValue key_val = {0, };
00577 GValue value_val = {0, };
00578 struct DBusGHashTableValueForeachData *data = user_data;
00579
00580 g_value_init (&key_val, data->key_type);
00581 g_value_init (&value_val, data->value_type);
00582 gvalue_take_hash_value (&key_val, key);
00583 gvalue_take_hash_value (&value_val, value);
00584
00585 data->func (&key_val, &value_val, data->data);
00586 }
00587
00588
00589 static void
00590 hashtable_iterator (GType hash_type,
00591 gpointer instance,
00592 DBusGTypeSpecializedMapIterator iterator,
00593 gpointer user_data)
00594 {
00595 struct DBusGHashTableValueForeachData data;
00596 GType key_gtype;
00597 GType value_gtype;
00598
00599 key_gtype = dbus_g_type_get_map_key_specialization (hash_type);
00600 value_gtype = dbus_g_type_get_map_value_specialization (hash_type);
00601
00602 data.func = iterator;
00603 data.key_type = key_gtype;
00604 data.value_type = value_gtype;
00605 data.data = user_data;
00606
00607 g_hash_table_foreach (instance, hashtable_foreach_with_values, &data);
00608 }
00609
00610 void
00611 _dbus_g_hash_table_insert_steal_values (GHashTable *table,
00612 GValue *key_val,
00613 GValue *value_val)
00614 {
00615 gpointer key, val;
00616
00617 key = hash_value_from_gvalue (key_val);
00618 val = hash_value_from_gvalue (value_val);
00619
00620 g_hash_table_insert (table, key, val);
00621 }
00622
00623 static void
00624 hashtable_append (DBusGTypeSpecializedAppendContext *ctx,
00625 GValue *key,
00626 GValue *val)
00627 {
00628 GHashTable *table;
00629
00630 table = g_value_get_boxed (ctx->val);
00631 _dbus_g_hash_table_insert_steal_values (table, key, val);
00632 }
00633
00634 static gpointer
00635 hashtable_constructor (GType type)
00636 {
00637 GHashTable *ret;
00638 GType key_gtype;
00639 GType value_gtype;
00640
00641 key_gtype = dbus_g_type_get_map_key_specialization (type);
00642 value_gtype = dbus_g_type_get_map_value_specialization (type);
00643
00644 ret = g_hash_table_new_full (_dbus_g_hash_func_from_gtype (key_gtype),
00645 _dbus_g_hash_equal_from_gtype (key_gtype),
00646 _dbus_g_hash_free_from_gtype (key_gtype),
00647 _dbus_g_hash_free_from_gtype (value_gtype));
00648 return ret;
00649 }
00650
00651 static void
00652 hashtable_insert_values (GHashTable *table,
00653 const GValue *key_val,
00654 const GValue *value_val)
00655 {
00656 GValue key_copy = {0, };
00657 GValue value_copy = {0, };
00658
00659 g_value_init (&key_copy, G_VALUE_TYPE (key_val));
00660 g_value_copy (key_val, &key_copy);
00661 g_value_init (&value_copy, G_VALUE_TYPE (value_val));
00662 g_value_copy (value_val, &value_copy);
00663
00664 _dbus_g_hash_table_insert_steal_values (table, &key_copy, &value_copy);
00665 }
00666
00667 static void
00668 hashtable_foreach_copy (const GValue *key, const GValue *val, gpointer data)
00669 {
00670 hashtable_insert_values ((GHashTable *) data, key, val);
00671 }
00672
00673 static gpointer
00674 hashtable_copy (GType type, gpointer src)
00675 {
00676 GHashTable *ghash;
00677 GHashTable *ret;
00678 GValue hashval = {0,};
00679
00680 ghash = src;
00681
00682 ret = hashtable_constructor (type);
00683
00684 g_value_init (&hashval, type);
00685 g_value_set_static_boxed (&hashval, ghash);
00686 dbus_g_type_map_value_iterate (&hashval, hashtable_foreach_copy, ret);
00687 return ret;
00688 }
00689
00690
00691
00692
00693
00694 static void
00695 hashtable_simple_free (gpointer val)
00696 {
00697 g_hash_table_unref (val);
00698 }
00699
00700 struct DBusGHashTableFreeData
00701 {
00702 GType key_gtype;
00703 GType value_gtype;
00704 };
00705
00706 static gboolean
00707 hashtable_free_foreach_steal (gpointer key,
00708 gpointer value,
00709 gpointer user_data)
00710 {
00711 struct DBusGHashTableFreeData *data = user_data;
00712 GValue val = { 0, };
00713
00714 g_value_init (&val, data->key_gtype);
00715 gvalue_take_hash_value (&val, key);
00716 g_value_unset (&val);
00717
00718 g_value_init (&val, data->value_gtype);
00719 gvalue_take_hash_value (&val, value);
00720 g_value_unset (&val);
00721
00722 return TRUE;
00723 }
00724
00725 static void
00726 hashtable_free (GType type,
00727 gpointer val)
00728 {
00729 struct DBusGHashTableFreeData data = { 0, };
00730 GHashTable *hash = val;
00731
00732 data.key_gtype = dbus_g_type_get_map_key_specialization (type);
00733 data.value_gtype = dbus_g_type_get_map_value_specialization (type);
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752 if (gtype_can_simple_free (data.key_gtype) &&
00753 gtype_can_simple_free (data.value_gtype))
00754 {
00755 g_hash_table_unref (hash);
00756 }
00757 else
00758 {
00759 g_hash_table_foreach_steal (hash, hashtable_free_foreach_steal, &data);
00760 g_hash_table_unref (hash);
00761 }
00762 }
00763
00764 static gpointer
00765 valuearray_constructor (GType type)
00766 {
00767 GValueArray *ret;
00768 guint size = dbus_g_type_get_struct_size (type);
00769 guint i;
00770 ret = g_value_array_new (size);
00771 for (i=0; i < size; i++)
00772 {
00773 GValue val = {0,};
00774 g_value_init (&val, dbus_g_type_get_struct_member_type (type, i));
00775 g_value_array_append(ret, &val);
00776 }
00777 return (gpointer)ret;
00778 }
00779
00780 static gpointer
00781 valuearray_copy (GType type, gpointer src)
00782 {
00783 return g_value_array_copy ((GValueArray*) src);
00784 }
00785
00786 static void
00787 valuearray_simple_free (gpointer val)
00788 {
00789 g_value_array_free (val);
00790 }
00791
00792 static gboolean
00793 valuearray_get_member (GType type, gpointer instance,
00794 guint member, GValue *ret)
00795 {
00796 GValueArray *va = (GValueArray*) instance;
00797 const GValue *val;
00798 if (member < dbus_g_type_get_struct_size (type))
00799 {
00800 val = g_value_array_get_nth (va, member);
00801 g_value_copy (val, ret);
00802 return TRUE;
00803 }
00804 else
00805 return FALSE;
00806 }
00807
00808 static gboolean
00809 valuearray_set_member (GType type, gpointer instance,
00810 guint member, const GValue *member_type)
00811 {
00812 GValueArray *va = (GValueArray*) instance;
00813 GValue *vp;
00814 if (member < dbus_g_type_get_struct_size (type))
00815 {
00816 vp = g_value_array_get_nth (va, member);
00817 g_value_copy (member_type, vp);
00818 return TRUE;
00819 }
00820 else
00821 return FALSE;
00822 }
00823
00824
00825 static gpointer
00826 array_constructor (GType type)
00827 {
00828 GArray *array;
00829 guint elt_size;
00830 GType elt_type;
00831 gboolean zero_terminated;
00832 gboolean clear;
00833
00834 elt_type = dbus_g_type_get_collection_specialization (type);
00835 g_assert (elt_type != G_TYPE_INVALID);
00836
00837 elt_size = _dbus_g_type_fixed_get_size (elt_type);
00838
00839
00840 zero_terminated = TRUE;
00841 clear = TRUE;
00842
00843 array = g_array_new (zero_terminated, clear, elt_size);
00844 return array;
00845 }
00846
00847 static gpointer
00848 array_copy (GType type, gpointer src)
00849 {
00850 GArray *garray;
00851 GArray *new;
00852
00853 garray = src;
00854
00855 new = array_constructor (type);
00856 g_array_append_vals (new, garray->data, garray->len);
00857
00858 return new;
00859 }
00860
00861 static void
00862 array_simple_free (gpointer val)
00863 {
00864 GArray *array;
00865 array = val;
00866 g_array_free (array, TRUE);
00867 }
00868
00869 static gboolean
00870 array_fixed_accessor (GType type, gpointer instance, gpointer *values, guint *len)
00871 {
00872 GType elt_type;
00873 GArray *array = instance;
00874
00875 elt_type = dbus_g_type_get_collection_specialization (type);
00876 if (!_dbus_g_type_is_fixed (elt_type))
00877 return FALSE;
00878
00879 *values = array->data;
00880 *len = array->len;
00881 return TRUE;
00882 }
00883
00884 static gpointer
00885 ptrarray_constructor (GType type)
00886 {
00887
00888 return g_ptr_array_new ();
00889 }
00890
00891 static void
00892 gvalue_take_ptrarray_value (GValue *value, gpointer instance)
00893 {
00894 switch (g_type_fundamental (G_VALUE_TYPE (value)))
00895 {
00896 case G_TYPE_STRING:
00897 g_value_take_string (value, instance);
00898 break;
00899 case G_TYPE_BOXED:
00900 g_value_take_boxed (value, instance);
00901 break;
00902 case G_TYPE_OBJECT:
00903 g_value_take_object (value, instance);
00904 break;
00905 default:
00906 g_assert_not_reached ();
00907 break;
00908 }
00909 }
00910
00911 static gpointer
00912 ptrarray_value_from_gvalue (const GValue *value)
00913 {
00914 GValue tmp = {0, };
00915
00916
00917
00918
00919
00920
00921 if (value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)
00922 {
00923 g_value_init (&tmp, G_VALUE_TYPE (value));
00924 g_value_copy (value, &tmp);
00925 value = &tmp;
00926 }
00927
00928 switch (g_type_fundamental (G_VALUE_TYPE (value)))
00929 {
00930 case G_TYPE_STRING:
00931 return (gpointer) g_value_get_string (value);
00932 break;
00933 case G_TYPE_BOXED:
00934 return g_value_get_boxed (value);
00935 break;
00936 case G_TYPE_OBJECT:
00937 return g_value_get_object (value);
00938 break;
00939 default:
00940 g_assert_not_reached ();
00941 return NULL;
00942 }
00943 }
00944
00945 static void
00946 ptrarray_iterator (GType ptrarray_type,
00947 gpointer instance,
00948 DBusGTypeSpecializedCollectionIterator iterator,
00949 gpointer user_data)
00950 {
00951 GPtrArray *ptrarray;
00952 GType elt_gtype;
00953 guint i;
00954
00955 ptrarray = instance;
00956
00957 elt_gtype = dbus_g_type_get_collection_specialization (ptrarray_type);
00958
00959 for (i = 0; i < ptrarray->len; i++)
00960 {
00961 GValue val = {0, };
00962 g_value_init (&val, elt_gtype);
00963 gvalue_take_ptrarray_value (&val, g_ptr_array_index (ptrarray, i));
00964 iterator (&val, user_data);
00965 }
00966 }
00967
00968 static void
00969 ptrarray_copy_elt (const GValue *val, gpointer user_data)
00970 {
00971 GPtrArray *dest = user_data;
00972 GValue val_copy = {0, };
00973
00974 g_value_init (&val_copy, G_VALUE_TYPE (val));
00975 g_value_copy (val, &val_copy);
00976
00977 g_ptr_array_add (dest, ptrarray_value_from_gvalue (&val_copy));
00978 }
00979
00980 static gpointer
00981 ptrarray_copy (GType type, gpointer src)
00982 {
00983 GPtrArray *new;
00984 GValue array_val = {0, };
00985
00986 g_value_init (&array_val, type);
00987 g_value_set_static_boxed (&array_val, src);
00988
00989 new = ptrarray_constructor (type);
00990 dbus_g_type_collection_value_iterate (&array_val, ptrarray_copy_elt, new);
00991
00992 return new;
00993 }
00994
00995 static void
00996 ptrarray_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value)
00997 {
00998 GPtrArray *array;
00999
01000 array = g_value_get_boxed (ctx->val);
01001
01002 g_ptr_array_add (array, ptrarray_value_from_gvalue (value));
01003 }
01004
01005 static void
01006 ptrarray_free (GType type, gpointer val)
01007 {
01008 GPtrArray *array;
01009 GValue elt_val = {0, };
01010 GType elt_gtype;
01011 unsigned int i;
01012
01013 array = val;
01014
01015 elt_gtype = dbus_g_type_get_collection_specialization (type);
01016
01017 for (i = 0; i < array->len; i++)
01018 {
01019 g_value_init (&elt_val, elt_gtype);
01020 gvalue_take_ptrarray_value (&elt_val, g_ptr_array_index (array, i));
01021 g_value_unset (&elt_val);
01022 }
01023
01024 g_ptr_array_free (array, TRUE);
01025 }
01026
01027 static gpointer
01028 slist_constructor (GType type)
01029 {
01030 return NULL;
01031 }
01032
01033 static void
01034 slist_iterator (GType list_type,
01035 gpointer instance,
01036 DBusGTypeSpecializedCollectionIterator iterator,
01037 gpointer user_data)
01038 {
01039 GSList *slist;
01040 GType elt_gtype;
01041
01042 slist = instance;
01043
01044 elt_gtype = dbus_g_type_get_collection_specialization (list_type);
01045
01046 for (slist = instance; slist != NULL; slist = slist->next)
01047 {
01048 GValue val = {0, };
01049 g_value_init (&val, elt_gtype);
01050 gvalue_take_ptrarray_value (&val, slist->data);
01051 iterator (&val, user_data);
01052 }
01053 }
01054
01055 static void
01056 slist_copy_elt (const GValue *val, gpointer user_data)
01057 {
01058 GSList **dest = user_data;
01059 GValue val_copy = {0, };
01060
01061 g_value_init (&val_copy, G_VALUE_TYPE (val));
01062 g_value_copy (val, &val_copy);
01063
01064 *dest = g_slist_append (*dest, ptrarray_value_from_gvalue (&val_copy));
01065 }
01066
01067 static gpointer
01068 slist_copy (GType type, gpointer src)
01069 {
01070 GSList *new;
01071 GValue slist_val = {0, };
01072
01073 g_value_init (&slist_val, type);
01074 g_value_set_static_boxed (&slist_val, src);
01075
01076 new = slist_constructor (type);
01077 dbus_g_type_collection_value_iterate (&slist_val, slist_copy_elt, &new);
01078
01079 return new;
01080 }
01081
01082 static void
01083 slist_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value)
01084 {
01085 GSList *list;
01086
01087 list = g_value_get_boxed (ctx->val);
01088 list = g_slist_prepend (list, ptrarray_value_from_gvalue (value));
01089 g_value_set_static_boxed (ctx->val, list);
01090 }
01091
01092 static void
01093 slist_end_append (DBusGTypeSpecializedAppendContext *ctx)
01094 {
01095 GSList *list;
01096
01097
01098
01099 list = g_value_get_boxed (ctx->val);
01100 list = g_slist_reverse (list);
01101
01102 g_value_take_boxed (ctx->val, list);
01103 }
01104
01105 static void
01106 slist_free (GType type, gpointer val)
01107 {
01108 GSList *list;
01109 GType elt_gtype;
01110 list = val;
01111
01112 elt_gtype = dbus_g_type_get_collection_specialization (type);
01113
01114 while (list != NULL)
01115 {
01116 GValue elt_val = {0, };
01117 g_value_init (&elt_val, elt_gtype);
01118 gvalue_take_ptrarray_value (&elt_val, list->data);
01119 g_value_unset (&elt_val);
01120 list = g_slist_next(list);
01121 }
01122 list=val;
01123 g_slist_free (list);
01124 }
01125
01126 void
01127 _dbus_g_type_specialized_builtins_init (void)
01128 {
01129
01130
01131
01132
01133 static const DBusGTypeSpecializedCollectionVtable array_vtable = {
01134 {
01135 array_constructor,
01136 NULL,
01137 array_copy,
01138 array_simple_free,
01139 NULL,
01140 NULL,
01141 },
01142 array_fixed_accessor,
01143 NULL,
01144 NULL,
01145 NULL
01146 };
01147
01148
01149 static const DBusGTypeSpecializedCollectionVtable ptrarray_vtable = {
01150 {
01151 ptrarray_constructor,
01152 ptrarray_free,
01153 ptrarray_copy,
01154 NULL,
01155 NULL,
01156 NULL,
01157 },
01158 NULL,
01159 ptrarray_iterator,
01160 ptrarray_append,
01161 NULL,
01162 };
01163
01164
01165 static const DBusGTypeSpecializedCollectionVtable slist_vtable = {
01166 {
01167 slist_constructor,
01168 slist_free,
01169 slist_copy,
01170 NULL,
01171 NULL,
01172 NULL,
01173 },
01174 NULL,
01175 slist_iterator,
01176 slist_append,
01177 slist_end_append,
01178 };
01179
01180 static const DBusGTypeSpecializedMapVtable hashtable_vtable = {
01181 {
01182 hashtable_constructor,
01183 hashtable_free,
01184 hashtable_copy,
01185 hashtable_simple_free,
01186 NULL,
01187 NULL
01188 },
01189 hashtable_iterator,
01190 hashtable_append
01191 };
01192
01193 static const DBusGTypeSpecializedStructVtable valuearray_vtable = {
01194 {
01195 valuearray_constructor,
01196 NULL,
01197 valuearray_copy,
01198 valuearray_simple_free,
01199 NULL,
01200 NULL
01201 },
01202 valuearray_get_member,
01203 valuearray_set_member
01204 };
01205
01206 dbus_g_type_register_collection ("GSList", &slist_vtable, 0);
01207 dbus_g_type_register_collection ("GArray", &array_vtable, 0);
01208 dbus_g_type_register_collection ("GPtrArray", &ptrarray_vtable, 0);
01209 dbus_g_type_register_map ("GHashTable", &hashtable_vtable, 0);
01210 dbus_g_type_register_struct ("GValueArray", &valuearray_vtable, 0);
01211 }
01212
01213 #ifdef DBUS_BUILD_TESTS
01214
01215 typedef struct
01216 {
01217 gboolean seen_foo;
01218 gboolean seen_baz;
01219 } TestSpecializedHashData;
01220
01221 static void
01222 test_specialized_hash (const GValue *key, const GValue *val, gpointer user_data)
01223 {
01224 TestSpecializedHashData *data = user_data;
01225
01226 g_assert (G_VALUE_HOLDS_STRING (key));
01227 g_assert (G_VALUE_HOLDS_STRING (val));
01228
01229 if (!strcmp (g_value_get_string (key), "foo"))
01230 {
01231 data->seen_foo = TRUE;
01232 g_assert (!strcmp (g_value_get_string (val), "bar"));
01233 }
01234 else if (!strcmp (g_value_get_string (key), "baz"))
01235 {
01236 data->seen_baz = TRUE;
01237 g_assert (!strcmp (g_value_get_string (val), "moo"));
01238 }
01239 else
01240 {
01241 g_assert_not_reached ();
01242 }
01243 }
01244
01245 static void
01246 test_specialized_hash_2 (const GValue *key, const GValue *val, gpointer user_data)
01247 {
01248 TestSpecializedHashData *data = user_data;
01249 const GValue *realval;
01250
01251 g_assert (G_VALUE_HOLDS_STRING (key));
01252 g_assert (G_VALUE_TYPE (val) == G_TYPE_VALUE);
01253
01254 realval = g_value_get_boxed (val);
01255
01256 if (!strcmp (g_value_get_string (key), "foo"))
01257 {
01258 data->seen_foo = TRUE;
01259 g_assert (G_VALUE_HOLDS_UINT (realval));
01260 g_assert (g_value_get_uint (realval) == 20);
01261 }
01262 else if (!strcmp (g_value_get_string (key), "baz"))
01263 {
01264 data->seen_baz = TRUE;
01265 g_assert (G_VALUE_HOLDS_STRING (realval));
01266 g_assert (!strcmp ("bar", g_value_get_string (realval)));
01267 }
01268 else
01269 {
01270 g_assert_not_reached ();
01271 }
01272 }
01273
01274 gboolean
01275 _dbus_gvalue_utils_test (const char *datadir)
01276 {
01277 GType type;
01278
01279 dbus_g_type_specialized_init ();
01280 _dbus_g_type_specialized_builtins_init ();
01281
01282 type = dbus_g_type_get_collection ("GArray", G_TYPE_UINT);
01283 g_assert (dbus_g_type_is_collection (type));
01284 g_assert (dbus_g_type_get_collection_specialization (type) == G_TYPE_UINT);
01285 {
01286 GArray *instance;
01287
01288 instance = dbus_g_type_specialized_construct (type);
01289
01290 g_assert (instance->len == 0);
01291
01292 g_array_free (instance, TRUE);
01293 }
01294
01295 type = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING);
01296 g_assert (dbus_g_type_is_map (type));
01297 g_assert (dbus_g_type_get_map_key_specialization (type) == G_TYPE_STRING);
01298 g_assert (dbus_g_type_get_map_value_specialization (type) == G_TYPE_STRING);
01299 {
01300 GHashTable *instance;
01301 GValue val = { 0, };
01302 TestSpecializedHashData hashdata;
01303
01304 instance = dbus_g_type_specialized_construct (type);
01305
01306 g_assert (g_hash_table_size (instance) == 0);
01307 g_hash_table_insert (instance, g_strdup ("foo"), g_strdup ("bar"));
01308 g_hash_table_insert (instance, g_strdup ("baz"), g_strdup ("moo"));
01309 g_assert (g_hash_table_size (instance) == 2);
01310
01311 g_value_init (&val, type);
01312 g_value_set_boxed_take_ownership (&val, instance);
01313 hashdata.seen_foo = FALSE;
01314 hashdata.seen_baz = FALSE;
01315 dbus_g_type_map_value_iterate (&val,
01316 test_specialized_hash,
01317 &hashdata);
01318
01319 g_assert (hashdata.seen_foo);
01320 g_assert (hashdata.seen_baz);
01321
01322 g_value_unset (&val);
01323 }
01324
01325 type = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE);
01326 g_assert (dbus_g_type_is_map (type));
01327 g_assert (dbus_g_type_get_map_key_specialization (type) == G_TYPE_STRING);
01328 g_assert (dbus_g_type_get_map_value_specialization (type) == G_TYPE_VALUE);
01329 {
01330 GHashTable *instance;
01331 GValue val = { 0, };
01332 TestSpecializedHashData hashdata;
01333 DBusGTypeSpecializedAppendContext ctx;
01334 GValue *eltval;
01335
01336 instance = dbus_g_type_specialized_construct (type);
01337 g_value_init (&val, type);
01338 g_value_set_boxed_take_ownership (&val, instance);
01339
01340 dbus_g_type_specialized_init_append (&val, &ctx);
01341
01342 {
01343 GValue keyval = { 0, };
01344 GValue valval = { 0, };
01345 g_value_init (&keyval, G_TYPE_STRING);
01346 g_value_set_string (&keyval, "foo");
01347
01348 g_value_init (&valval, G_TYPE_VALUE);
01349 eltval = g_new0 (GValue, 1);
01350 g_value_init (eltval, G_TYPE_UINT);
01351 g_value_set_uint (eltval, 20);
01352 g_value_set_boxed_take_ownership (&valval, eltval);
01353 dbus_g_type_specialized_map_append (&ctx, &keyval, &valval);
01354 }
01355
01356 {
01357 GValue keyval = { 0, };
01358 GValue valval = { 0, };
01359 g_value_init (&keyval, G_TYPE_STRING);
01360 g_value_set_string (&keyval, "baz");
01361 g_value_init (&valval, G_TYPE_VALUE);
01362 eltval = g_new0 (GValue, 1);
01363 g_value_init (eltval, G_TYPE_STRING);
01364 g_value_set_string (eltval, "bar");
01365 g_value_set_boxed_take_ownership (&valval, eltval);
01366 dbus_g_type_specialized_map_append (&ctx, &keyval, &valval);
01367 }
01368
01369 hashdata.seen_foo = FALSE;
01370 hashdata.seen_baz = FALSE;
01371 dbus_g_type_map_value_iterate (&val,
01372 test_specialized_hash_2,
01373 &hashdata);
01374
01375 g_assert (hashdata.seen_foo);
01376 g_assert (hashdata.seen_baz);
01377
01378 g_value_unset (&val);
01379 }
01380
01381 type = dbus_g_type_get_collection ("GSList", G_TYPE_OBJECT);
01382 g_assert (dbus_g_type_is_collection (type));
01383 g_assert (dbus_g_type_get_collection_specialization (type) == G_TYPE_OBJECT);
01384 {
01385 GSList *instance, *tmp, *copy;
01386 GValue val = {0, };
01387 GValue copyval = {0, };
01388 DBusGTypeSpecializedAppendContext ctx;
01389 GObject *objects[3];
01390 int i;
01391
01392 instance = dbus_g_type_specialized_construct (type);
01393 g_assert (instance == NULL);
01394
01395 g_value_init (&val, type);
01396 g_value_take_boxed (&val, instance);
01397
01398 dbus_g_type_specialized_init_append (&val, &ctx);
01399
01400 for (i = 0; i < 3; i++)
01401 {
01402 GValue eltval = { 0, };
01403 GObject *obj = g_object_new (G_TYPE_OBJECT, NULL);
01404
01405 g_assert (obj != NULL);
01406 objects[i] = obj;
01407 g_object_add_weak_pointer (obj, (gpointer) (objects + i));
01408
01409 g_value_init (&eltval, G_TYPE_OBJECT);
01410 g_value_take_object (&eltval, obj);
01411 dbus_g_type_specialized_collection_append (&ctx, &eltval);
01412 }
01413
01414 dbus_g_type_specialized_collection_end_append (&ctx);
01415
01416 instance = g_value_get_boxed (&val);
01417 g_assert (g_slist_length (instance) == 3);
01418
01419 for (tmp = instance; tmp; tmp = tmp->next)
01420 {
01421 GObject *obj = tmp->data;
01422 g_assert (G_IS_OBJECT (obj));
01423 g_assert (obj->ref_count == 1);
01424 }
01425
01426 g_value_init (©val, type);
01427 g_value_copy (&val, ©val);
01428
01429 copy = g_value_get_boxed (©val);
01430 g_assert (g_slist_length (copy) == 3);
01431
01432 for (tmp = copy; tmp; tmp = tmp->next)
01433 {
01434 GObject *obj = tmp->data;
01435 g_assert (G_IS_OBJECT (obj));
01436 g_assert (obj->ref_count == 2);
01437 }
01438
01439 g_value_unset (©val);
01440
01441 for (i = 0; i < 3; i++)
01442 {
01443 g_assert (objects[i] != NULL);
01444 }
01445
01446 for (tmp = instance; tmp; tmp = tmp->next)
01447 {
01448 GObject *obj = tmp->data;
01449 g_assert (G_IS_OBJECT (obj));
01450 g_assert (obj->ref_count == 1);
01451 }
01452
01453 g_value_unset (&val);
01454
01455 for (i = 0; i < 3; i++)
01456 {
01457 g_assert (objects[i] == NULL);
01458 }
01459 }
01460
01461 type = dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING);
01462 g_assert (dbus_g_type_is_collection (type));
01463 g_assert (dbus_g_type_get_collection_specialization (type) == G_TYPE_STRING);
01464 {
01465 GPtrArray *instance;
01466 DBusGTypeSpecializedAppendContext ctx;
01467 GValue val = {0, };
01468 GValue eltval = {0, };
01469
01470 instance = dbus_g_type_specialized_construct (type);
01471
01472 g_assert (instance->len == 0);
01473
01474 g_value_init (&val, type);
01475 g_value_set_boxed_take_ownership (&val, instance);
01476
01477 dbus_g_type_specialized_init_append (&val, &ctx);
01478
01479 g_value_init (&eltval, G_TYPE_STRING);
01480 g_value_set_static_string (&eltval, "foo");
01481 dbus_g_type_specialized_collection_append (&ctx, &eltval);
01482
01483 g_value_reset (&eltval);
01484 g_value_set_static_string (&eltval, "bar");
01485 dbus_g_type_specialized_collection_append (&ctx, &eltval);
01486
01487 g_value_reset (&eltval);
01488 g_value_set_static_string (&eltval, "baz");
01489 dbus_g_type_specialized_collection_append (&ctx, &eltval);
01490
01491 dbus_g_type_specialized_collection_end_append (&ctx);
01492
01493 g_assert (instance->len == 3);
01494
01495 g_assert (!strcmp ("foo", g_ptr_array_index (instance, 0)));
01496 g_assert (!strcmp ("bar", g_ptr_array_index (instance, 1)));
01497 g_assert (!strcmp ("baz", g_ptr_array_index (instance, 2)));
01498
01499 g_value_unset (&val);
01500 }
01501
01502 type = dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_UINT, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
01503 g_assert (dbus_g_type_is_struct (type));
01504 g_assert (dbus_g_type_get_struct_size (type) == 3);
01505 g_assert (dbus_g_type_get_struct_member_type (type, 0) == G_TYPE_STRING);
01506 g_assert (dbus_g_type_get_struct_member_type (type, 1) == G_TYPE_UINT);
01507 g_assert (dbus_g_type_get_struct_member_type (type, 2) == DBUS_TYPE_G_OBJECT_PATH);
01508 {
01509 GValueArray *instance;
01510 GValue val = {0, };
01511 GValue memval = {0, };
01512
01513 instance = dbus_g_type_specialized_construct (type);
01514
01515 g_assert (instance->n_values == 3);
01516
01517 g_value_init (&val, type);
01518 g_value_set_boxed_take_ownership (&val, instance);
01519
01520 g_value_init (&memval, G_TYPE_STRING);
01521 g_value_set_static_string (&memval, "foo");
01522 dbus_g_type_struct_set_member (&val, 0, &memval);
01523 g_value_unset (&memval);
01524
01525 g_value_init (&memval, G_TYPE_UINT);
01526 g_value_set_uint (&memval, 42);
01527 dbus_g_type_struct_set_member (&val, 1, &memval);
01528 g_value_unset (&memval);
01529
01530 g_value_init (&memval, DBUS_TYPE_G_OBJECT_PATH);
01531 g_value_set_static_boxed (&memval, "/bar/moo/foo/baz");
01532 dbus_g_type_struct_set_member (&val, 2, &memval);
01533 g_value_unset (&memval);
01534
01535 g_assert (instance->n_values == 3);
01536
01537 g_value_init (&memval, G_TYPE_STRING);
01538 dbus_g_type_struct_get_member (&val, 0, &memval);
01539 g_assert (0 == strcmp (g_value_get_string (&memval), "foo"));
01540 g_value_unset (&memval);
01541
01542 g_value_init (&memval, G_TYPE_UINT);
01543 dbus_g_type_struct_get_member (&val, 1, &memval);
01544 g_assert (g_value_get_uint (&memval) == 42);
01545 g_value_unset (&memval);
01546
01547 g_value_init (&memval, DBUS_TYPE_G_OBJECT_PATH);
01548 dbus_g_type_struct_get_member (&val, 2, &memval);
01549 g_assert (0 == strcmp ((gchar*) g_value_get_boxed (&memval),
01550 "/bar/moo/foo/baz"));
01551 g_value_unset (&memval);
01552
01553 g_value_unset (&val);
01554 }
01555
01556 type = dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_UINT, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
01557 g_assert (dbus_g_type_is_struct (type));
01558 g_assert (dbus_g_type_get_struct_size (type) == 3);
01559 g_assert (dbus_g_type_get_struct_member_type (type, 0) == G_TYPE_STRING);
01560 g_assert (dbus_g_type_get_struct_member_type (type, 1) == G_TYPE_UINT);
01561 g_assert (dbus_g_type_get_struct_member_type (type, 2) == DBUS_TYPE_G_OBJECT_PATH);
01562 {
01563 GValueArray *instance;
01564 GValue val = {0, };
01565
01566 instance = dbus_g_type_specialized_construct (type);
01567
01568 g_assert (instance->n_values == 3);
01569
01570 g_value_init (&val, type);
01571 g_value_set_boxed_take_ownership (&val, instance);
01572
01573 dbus_g_type_struct_set (&val,
01574 0,"foo",
01575 1, 42,
01576 2, "/bar/moo/foo/baz",
01577 G_MAXUINT);
01578
01579 g_assert (instance->n_values == 3);
01580
01581 {
01582 gchar *string;
01583 guint intval;
01584 gchar *path;
01585
01586 dbus_g_type_struct_get (&val,
01587 0, &string,
01588 1, &intval,
01589 2, &path,
01590 G_MAXUINT);
01591
01592 g_assert (0 == strcmp (string, "foo"));
01593 g_assert (intval == 42);
01594 g_assert (0 == strcmp (path, "/bar/moo/foo/baz"));
01595 }
01596
01597 g_value_unset (&val);
01598 }
01599
01600
01601 return TRUE;
01602 }
01603
01604
01605
01606 #endif