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_POINTER:
00117 *((gpointer *) storage) = g_value_get_pointer (value);
00118 return TRUE;
00119 case G_TYPE_OBJECT:
00120 *((gpointer *) storage) = g_value_get_object (value);
00121 return TRUE;
00122 case G_TYPE_BOXED:
00123 *((gpointer *) storage) = g_value_get_boxed (value);
00124 return TRUE;
00125 default:
00126 return FALSE;
00127 }
00128 }
00129
00130 gboolean
00131 dbus_gvalue_set_from_pointer (GValue *value,
00132 gconstpointer storage)
00133 {
00134
00135 switch (g_type_fundamental (G_VALUE_TYPE (value)))
00136 {
00137 case G_TYPE_CHAR:
00138 g_value_set_char (value, *((gchar *) storage));
00139 return TRUE;
00140 case G_TYPE_UCHAR:
00141 g_value_set_uchar (value, *((guchar *) storage));
00142 return TRUE;
00143 case G_TYPE_BOOLEAN:
00144 g_value_set_boolean (value, *((gboolean *) storage));
00145 return TRUE;
00146 case G_TYPE_LONG:
00147 g_value_set_long (value, *((glong *) storage));
00148 return TRUE;
00149 case G_TYPE_ULONG:
00150 g_value_set_ulong (value, *((gulong *) storage));
00151 return TRUE;
00152 case G_TYPE_INT:
00153 g_value_set_int (value, *((gint *) storage));
00154 return TRUE;
00155 case G_TYPE_UINT:
00156 g_value_set_uint (value, *((guint *) storage));
00157 return TRUE;
00158 case G_TYPE_INT64:
00159 g_value_set_int64 (value, *((gint64 *) storage));
00160 return TRUE;
00161 case G_TYPE_UINT64:
00162 g_value_set_uint64 (value, *((guint64 *) storage));
00163 return TRUE;
00164 case G_TYPE_DOUBLE:
00165 g_value_set_double (value, *((gdouble *) storage));
00166 return TRUE;
00167 case G_TYPE_STRING:
00168 g_value_set_string (value, *((gchar **) storage));
00169 return TRUE;
00170 case G_TYPE_POINTER:
00171 g_value_set_pointer (value, *((gpointer *) storage));
00172 return TRUE;
00173 case G_TYPE_OBJECT:
00174 g_value_set_object (value, *((gpointer *) storage));
00175 return TRUE;
00176 case G_TYPE_BOXED:
00177 g_value_set_boxed (value, *((gpointer *) storage));
00178 return TRUE;
00179 default:
00180 return FALSE;
00181 }
00182 }
00183
00184 gboolean
00185 dbus_gvalue_take (GValue *value,
00186 GTypeCValue *cvalue)
00187 {
00188 GType g_type;
00189 GTypeValueTable *value_table;
00190 char *error_msg;
00191
00192 g_type = G_VALUE_TYPE (value);
00193 value_table = g_type_value_table_peek (g_type);
00194
00195 error_msg = value_table->collect_value (value, 1, cvalue, G_VALUE_NOCOPY_CONTENTS);
00196 if (error_msg)
00197 {
00198 g_warning ("%s: %s", G_STRLOC, error_msg);
00199 g_free (error_msg);
00200 return FALSE;
00201 }
00202
00203
00204
00205 value->data[1].v_uint &= ~(G_VALUE_NOCOPY_CONTENTS);
00206 return TRUE;
00207 }
00208
00209 gboolean
00210 _dbus_gtype_can_signal_error (GType gtype)
00211 {
00212 switch (gtype)
00213 {
00214 case G_TYPE_BOOLEAN:
00215 case G_TYPE_INT:
00216 case G_TYPE_UINT:
00217 case G_TYPE_STRING:
00218 case G_TYPE_BOXED:
00219 case G_TYPE_OBJECT:
00220 return TRUE;
00221 default:
00222 return FALSE;
00223 }
00224 }
00225
00226 gboolean
00227 _dbus_gvalue_signals_error (const GValue *value)
00228 {
00229
00230
00231
00232
00233
00234
00235 switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)))
00236 {
00237 case G_TYPE_BOOLEAN:
00238 return (g_value_get_boolean (value) == FALSE);
00239 break;
00240 case G_TYPE_INT:
00241 return (g_value_get_int (value) < 0);
00242 break;
00243 case G_TYPE_UINT:
00244 return (g_value_get_uint (value) == 0);
00245 break;
00246 case G_TYPE_STRING:
00247 return (g_value_get_string (value) == NULL);
00248 break;
00249 case G_TYPE_BOXED:
00250 return (g_value_get_boxed (value) == NULL);
00251 break;
00252 case G_TYPE_OBJECT:
00253 return (g_value_get_boxed (value) == NULL);
00254 break;
00255 default:
00256 g_assert_not_reached ();
00257 return FALSE;
00258 }
00259 }
00260
00261
00262 static gboolean
00263 hash_func_from_gtype (GType gtype, GHashFunc *func)
00264 {
00265 switch (gtype)
00266 {
00267 case G_TYPE_CHAR:
00268 case G_TYPE_UCHAR:
00269 case G_TYPE_BOOLEAN:
00270 case G_TYPE_INT:
00271 case G_TYPE_UINT:
00272 *func = NULL;
00273 return TRUE;
00274 case G_TYPE_STRING:
00275 *func = g_str_hash;
00276 return TRUE;
00277 default:
00278 return FALSE;
00279 }
00280 }
00281
00282 static void
00283 unset_and_free_g_value (gpointer val)
00284 {
00285 GValue *value = val;
00286
00287 g_value_unset (value);
00288 g_free (value);
00289 }
00290
00291 static gboolean
00292 hash_free_from_gtype (GType gtype, GDestroyNotify *func)
00293 {
00294 switch (gtype)
00295 {
00296 case G_TYPE_CHAR:
00297 case G_TYPE_UCHAR:
00298 case G_TYPE_BOOLEAN:
00299 case G_TYPE_INT:
00300 case G_TYPE_UINT:
00301 *func = NULL;
00302 return TRUE;
00303 case G_TYPE_STRING:
00304 *func = g_free;
00305 return TRUE;
00306 default:
00307 if (gtype == G_TYPE_VALUE)
00308 {
00309 *func = unset_and_free_g_value;
00310 return TRUE;
00311 }
00312 return FALSE;
00313 }
00314 }
00315
00316 gboolean
00317 dbus_gtype_is_valid_hash_key (GType type)
00318 {
00319 GHashFunc func;
00320 return hash_func_from_gtype (type, &func);
00321 }
00322
00323 gboolean
00324 dbus_gtype_is_valid_hash_value (GType type)
00325 {
00326 GDestroyNotify func;
00327 return hash_free_from_gtype (type, &func);
00328 }
00329
00330 GHashFunc
00331 dbus_g_hash_func_from_gtype (GType gtype)
00332 {
00333 GHashFunc func;
00334 gboolean ret;
00335 ret = hash_func_from_gtype (gtype, &func);
00336 g_assert (ret != FALSE);
00337 return func;
00338 }
00339
00340 GEqualFunc
00341 dbus_g_hash_equal_from_gtype (GType gtype)
00342 {
00343 g_assert (dbus_gtype_is_valid_hash_key (gtype));
00344
00345 switch (gtype)
00346 {
00347 case G_TYPE_CHAR:
00348 case G_TYPE_UCHAR:
00349 case G_TYPE_BOOLEAN:
00350 case G_TYPE_INT:
00351 case G_TYPE_UINT:
00352 return NULL;
00353 case G_TYPE_STRING:
00354 return g_str_equal;
00355 default:
00356 g_assert_not_reached ();
00357 return NULL;
00358 }
00359 }
00360
00361 GDestroyNotify
00362 dbus_g_hash_free_from_gtype (GType gtype)
00363 {
00364 GDestroyNotify func;
00365 gboolean ret;
00366 ret = hash_free_from_gtype (gtype, &func);
00367 g_assert (ret != FALSE);
00368 return func;
00369 }
00370
00371 static void
00372 gvalue_from_hash_value (GValue *value, gpointer instance)
00373 {
00374 switch (g_type_fundamental (G_VALUE_TYPE (value)))
00375 {
00376 case G_TYPE_CHAR:
00377 g_value_set_char (value, (gchar) GPOINTER_TO_INT (instance));
00378 break;
00379 case G_TYPE_UCHAR:
00380 g_value_set_uchar (value, (guchar) GPOINTER_TO_UINT (instance));
00381 break;
00382 case G_TYPE_BOOLEAN:
00383 g_value_set_boolean (value, (gboolean) GPOINTER_TO_UINT (instance));
00384 break;
00385 case G_TYPE_INT:
00386 g_value_set_int (value, GPOINTER_TO_INT (instance));
00387 break;
00388 case G_TYPE_UINT:
00389 g_value_set_uint (value, GPOINTER_TO_UINT (instance));
00390 break;
00391 case G_TYPE_STRING:
00392 g_value_set_static_string (value, instance);
00393 break;
00394 case G_TYPE_POINTER:
00395 g_value_set_pointer (value, instance);
00396 break;
00397 case G_TYPE_BOXED:
00398 g_value_set_static_boxed (value, instance);
00399 break;
00400 case G_TYPE_OBJECT:
00401 g_value_set_object (value, instance);
00402 g_object_unref (g_value_get_object (value));
00403 break;
00404 default:
00405 g_assert_not_reached ();
00406 break;
00407 }
00408 }
00409
00410 static gpointer
00411 hash_value_from_gvalue (GValue *value)
00412 {
00413 switch (g_type_fundamental (G_VALUE_TYPE (value)))
00414 {
00415 case G_TYPE_CHAR:
00416 return GINT_TO_POINTER ((int) g_value_get_char (value));
00417 break;
00418 case G_TYPE_UCHAR:
00419 return GUINT_TO_POINTER ((guint) g_value_get_uchar (value));
00420 break;
00421 case G_TYPE_BOOLEAN:
00422 return GUINT_TO_POINTER ((guint) g_value_get_boolean (value));
00423 break;
00424 case G_TYPE_INT:
00425 return GINT_TO_POINTER (g_value_get_int (value));
00426 break;
00427 case G_TYPE_UINT:
00428 return GUINT_TO_POINTER (g_value_get_uint (value));
00429 break;
00430 case G_TYPE_STRING:
00431 return (gpointer) g_value_get_string (value);
00432 break;
00433 case G_TYPE_POINTER:
00434 return g_value_get_pointer (value);
00435 break;
00436 case G_TYPE_BOXED:
00437 return g_value_get_boxed (value);
00438 break;
00439 case G_TYPE_OBJECT:
00440 return g_value_get_object (value);
00441 break;
00442 default:
00443 g_assert_not_reached ();
00444 return NULL;
00445 }
00446 }
00447
00448 struct DBusGHashTableValueForeachData
00449 {
00450 DBusGTypeSpecializedMapIterator func;
00451 GType key_type;
00452 GType value_type;
00453 gpointer data;
00454 };
00455
00456 static void
00457 hashtable_foreach_with_values (gpointer key, gpointer value, gpointer user_data)
00458 {
00459 GValue key_val = {0, };
00460 GValue value_val = {0, };
00461 struct DBusGHashTableValueForeachData *data = user_data;
00462
00463 g_value_init (&key_val, data->key_type);
00464 g_value_init (&value_val, data->value_type);
00465 gvalue_from_hash_value (&key_val, key);
00466 gvalue_from_hash_value (&value_val, value);
00467
00468 data->func (&key_val, &value_val, data->data);
00469 }
00470
00471
00472 static void
00473 hashtable_iterator (GType hash_type,
00474 gpointer instance,
00475 DBusGTypeSpecializedMapIterator iterator,
00476 gpointer user_data)
00477 {
00478 struct DBusGHashTableValueForeachData data;
00479 GType key_gtype;
00480 GType value_gtype;
00481
00482 key_gtype = dbus_g_type_get_map_key_specialization (hash_type);
00483 value_gtype = dbus_g_type_get_map_value_specialization (hash_type);
00484
00485 data.func = iterator;
00486 data.key_type = key_gtype;
00487 data.value_type = value_gtype;
00488 data.data = user_data;
00489
00490 g_hash_table_foreach (instance, hashtable_foreach_with_values, &data);
00491 }
00492
00493 void
00494 dbus_g_hash_table_insert_steal_values (GHashTable *table,
00495 GValue *key_val,
00496 GValue *value_val)
00497 {
00498 gpointer key, val;
00499
00500 key = hash_value_from_gvalue (key_val);
00501 val = hash_value_from_gvalue (value_val);
00502
00503 g_hash_table_insert (table, key, val);
00504 }
00505
00506 static void
00507 hashtable_append (DBusGTypeSpecializedAppendContext *ctx,
00508 GValue *key,
00509 GValue *val)
00510 {
00511 GHashTable *table;
00512
00513 table = g_value_get_boxed (ctx->val);
00514 dbus_g_hash_table_insert_steal_values (table, key, val);
00515 }
00516
00517 static gpointer
00518 hashtable_constructor (GType type)
00519 {
00520 GHashTable *ret;
00521 GType key_gtype;
00522 GType value_gtype;
00523
00524 key_gtype = dbus_g_type_get_map_key_specialization (type);
00525 value_gtype = dbus_g_type_get_map_value_specialization (type);
00526
00527 ret = g_hash_table_new_full (dbus_g_hash_func_from_gtype (key_gtype),
00528 dbus_g_hash_equal_from_gtype (key_gtype),
00529 dbus_g_hash_free_from_gtype (key_gtype),
00530 dbus_g_hash_free_from_gtype (value_gtype));
00531 return ret;
00532 }
00533
00534 static void
00535 hashtable_insert_values (GHashTable *table,
00536 const GValue *key_val,
00537 const GValue *value_val)
00538 {
00539 GValue key_copy = {0, };
00540 GValue value_copy = {0, };
00541
00542 g_value_init (&key_copy, G_VALUE_TYPE (key_val));
00543 g_value_copy (key_val, &key_copy);
00544 g_value_init (&value_copy, G_VALUE_TYPE (value_val));
00545 g_value_copy (value_val, &value_copy);
00546
00547 dbus_g_hash_table_insert_steal_values (table, &key_copy, &value_copy);
00548 }
00549
00550 static void
00551 hashtable_foreach_copy (const GValue *key, const GValue *val, gpointer data)
00552 {
00553 hashtable_insert_values ((GHashTable *) data, key, val);
00554 }
00555
00556 static gpointer
00557 hashtable_copy (GType type, gpointer src)
00558 {
00559 GHashTable *ghash;
00560 GHashTable *ret;
00561 GValue hashval = {0,};
00562
00563 ghash = src;
00564
00565 ret = hashtable_constructor (type);
00566
00567 g_value_init (&hashval, type);
00568 g_value_set_static_boxed (&hashval, ghash);
00569 dbus_g_type_map_value_iterate (&hashval, hashtable_foreach_copy, ret);
00570 return ret;
00571 }
00572
00573 static void
00574 hashtable_free (GType type, gpointer val)
00575 {
00576 g_hash_table_destroy (val);
00577 }
00578
00579 static gpointer
00580 array_constructor (GType type)
00581 {
00582 GArray *array;
00583 guint elt_size;
00584 GType elt_type;
00585 gboolean zero_terminated;
00586 gboolean clear;
00587
00588 elt_type = dbus_g_type_get_collection_specialization (type);
00589 g_assert (elt_type != G_TYPE_INVALID);
00590
00591 elt_size = dbus_g_type_fixed_get_size (elt_type);
00592
00593
00594 zero_terminated = TRUE;
00595 clear = TRUE;
00596
00597 array = g_array_new (zero_terminated, clear, elt_size);
00598 return array;
00599 }
00600
00601 static gpointer
00602 array_copy (GType type, gpointer src)
00603 {
00604 GArray *garray;
00605 GArray *new;
00606
00607 garray = src;
00608
00609 new = array_constructor (type);
00610 g_array_append_vals (new, garray->data, garray->len);
00611
00612 return new;
00613 }
00614
00615 static void
00616 array_free (GType type, gpointer val)
00617 {
00618 GArray *array;
00619 array = val;
00620 g_array_free (array, TRUE);
00621 }
00622
00623 static gboolean
00624 array_fixed_accessor (GType type, gpointer instance, gpointer *values, guint *len)
00625 {
00626 GType elt_type;
00627 GArray *array = instance;
00628
00629 elt_type = dbus_g_type_get_collection_specialization (type);
00630 if (!dbus_g_type_is_fixed (elt_type))
00631 return FALSE;
00632
00633 *values = array->data;
00634 *len = array->len;
00635 return TRUE;
00636 }
00637
00638 static gpointer
00639 ptrarray_constructor (GType type)
00640 {
00641
00642 return g_ptr_array_new ();
00643 }
00644
00645 static void
00646 gvalue_from_ptrarray_value (GValue *value, gpointer instance)
00647 {
00648 switch (g_type_fundamental (G_VALUE_TYPE (value)))
00649 {
00650 case G_TYPE_STRING:
00651 g_value_set_string (value, instance);
00652 break;
00653 case G_TYPE_POINTER:
00654 g_value_set_pointer (value, instance);
00655 break;
00656 case G_TYPE_BOXED:
00657 g_value_set_static_boxed (value, instance);
00658 break;
00659 case G_TYPE_OBJECT:
00660 g_value_set_object (value, instance);
00661 g_object_unref (g_value_get_object (value));
00662 break;
00663 default:
00664 g_assert_not_reached ();
00665 break;
00666 }
00667 }
00668
00669 static gpointer
00670 ptrarray_value_from_gvalue (const GValue *value)
00671 {
00672 switch (g_type_fundamental (G_VALUE_TYPE (value)))
00673 {
00674 case G_TYPE_STRING:
00675 return (gpointer) g_value_get_string (value);
00676 break;
00677 case G_TYPE_POINTER:
00678 return g_value_get_pointer (value);
00679 break;
00680 case G_TYPE_BOXED:
00681 return g_value_get_boxed (value);
00682 break;
00683 case G_TYPE_OBJECT:
00684 return g_value_get_object (value);
00685 break;
00686 default:
00687 g_assert_not_reached ();
00688 return NULL;
00689 }
00690 }
00691
00692 static void
00693 ptrarray_iterator (GType hash_type,
00694 gpointer instance,
00695 DBusGTypeSpecializedCollectionIterator iterator,
00696 gpointer user_data)
00697 {
00698 GPtrArray *ptrarray;
00699 GType elt_gtype;
00700 guint i;
00701
00702 ptrarray = instance;
00703
00704 elt_gtype = dbus_g_type_get_collection_specialization (hash_type);
00705
00706 for (i = 0; i < ptrarray->len; i++)
00707 {
00708 GValue val = {0, };
00709 g_value_init (&val, elt_gtype);
00710 gvalue_from_ptrarray_value (&val, g_ptr_array_index (ptrarray, i));
00711 iterator (&val, user_data);
00712 }
00713 }
00714
00715 static void
00716 ptrarray_copy_elt (const GValue *val, gpointer user_data)
00717 {
00718 GPtrArray *dest = user_data;
00719 GValue val_copy = {0, };
00720
00721 g_value_init (&val_copy, G_VALUE_TYPE (val));
00722 g_value_copy (val, &val_copy);
00723
00724 g_ptr_array_add (dest, ptrarray_value_from_gvalue (&val_copy));
00725 }
00726
00727 static gpointer
00728 ptrarray_copy (GType type, gpointer src)
00729 {
00730 GPtrArray *new;
00731 GValue array_val = {0, };
00732
00733 g_value_init (&array_val, type);
00734 g_value_set_static_boxed (&array_val, src);
00735
00736 new = ptrarray_constructor (type);
00737 dbus_g_type_collection_value_iterate (&array_val, ptrarray_copy_elt, new);
00738
00739 return new;
00740 }
00741
00742 static void
00743 ptrarray_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value)
00744 {
00745 GPtrArray *array;
00746
00747 array = g_value_get_boxed (ctx->val);
00748
00749 g_ptr_array_add (array, ptrarray_value_from_gvalue (value));
00750 }
00751
00752 static void
00753 ptrarray_free (GType type, gpointer val)
00754 {
00755 GPtrArray *array;
00756 array = val;
00757 g_ptr_array_free (array, TRUE);
00758 }
00759
00760 static gpointer
00761 slist_constructor (GType type)
00762 {
00763 return NULL;
00764 }
00765
00766 static void
00767 slist_iterator (GType list_type,
00768 gpointer instance,
00769 DBusGTypeSpecializedCollectionIterator iterator,
00770 gpointer user_data)
00771 {
00772 GSList *slist;
00773 GType elt_gtype;
00774
00775 slist = instance;
00776
00777 elt_gtype = dbus_g_type_get_collection_specialization (list_type);
00778
00779 while (slist != NULL)
00780 {
00781 GValue val = {0, };
00782 g_value_init (&val, elt_gtype);
00783 gvalue_from_ptrarray_value (&val, slist->data);
00784 iterator (&val, user_data);
00785 }
00786 }
00787
00788 static void
00789 slist_copy_elt (const GValue *val, gpointer user_data)
00790 {
00791 GSList *dest = user_data;
00792 GValue val_copy = {0, };
00793
00794 g_value_init (&val_copy, G_VALUE_TYPE (val));
00795 g_value_copy (val, &val_copy);
00796
00797 g_slist_append (dest, ptrarray_value_from_gvalue (&val_copy));
00798 }
00799
00800 static gpointer
00801 slist_copy (GType type, gpointer src)
00802 {
00803 GSList *new;
00804 GValue slist_val = {0, };
00805
00806 g_value_init (&slist_val, type);
00807 g_value_set_static_boxed (&slist_val, src);
00808
00809 new = slist_constructor (type);
00810 dbus_g_type_collection_value_iterate (&slist_val, slist_copy_elt, new);
00811
00812 return new;
00813 }
00814
00815 static void
00816 slist_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value)
00817 {
00818 GSList *list;
00819
00820 list = g_value_get_boxed (ctx->val);
00821 list = g_slist_prepend (list, ptrarray_value_from_gvalue (value));
00822 g_value_set_static_boxed (ctx->val, list);
00823 }
00824
00825 static void
00826 slist_end_append (DBusGTypeSpecializedAppendContext *ctx)
00827 {
00828 GSList *list;
00829
00830 list = g_value_get_boxed (ctx->val);
00831 list = g_slist_reverse (list);
00832
00833 g_value_set_static_boxed (ctx->val, list);
00834 }
00835
00836 static void
00837 slist_free (GType type, gpointer val)
00838 {
00839 GSList *list;
00840 list = val;
00841 g_slist_free (list);
00842 }
00843
00844 void
00845 dbus_g_type_specialized_builtins_init (void)
00846 {
00847 static const DBusGTypeSpecializedCollectionVtable array_vtable = {
00848 {
00849 array_constructor,
00850 array_free,
00851 array_copy,
00852 },
00853 array_fixed_accessor,
00854 NULL,
00855 NULL,
00856 NULL
00857 };
00858
00859 dbus_g_type_register_collection ("GArray", &array_vtable, 0);
00860
00861 static const DBusGTypeSpecializedCollectionVtable ptrarray_vtable = {
00862 {
00863 ptrarray_constructor,
00864 ptrarray_free,
00865 ptrarray_copy,
00866 },
00867 NULL,
00868 ptrarray_iterator,
00869 ptrarray_append,
00870 NULL,
00871 };
00872
00873 dbus_g_type_register_collection ("GPtrArray", &ptrarray_vtable, 0);
00874
00875 static const DBusGTypeSpecializedCollectionVtable slist_vtable = {
00876 {
00877 slist_constructor,
00878 slist_free,
00879 slist_copy,
00880 },
00881 NULL,
00882 slist_iterator,
00883 slist_append,
00884 slist_end_append,
00885 };
00886
00887 dbus_g_type_register_collection ("GSList", &slist_vtable, 0);
00888
00889 static const DBusGTypeSpecializedMapVtable hashtable_vtable = {
00890 {
00891 hashtable_constructor,
00892 hashtable_free,
00893 hashtable_copy,
00894 NULL,
00895 NULL,
00896 NULL
00897 },
00898 hashtable_iterator,
00899 hashtable_append
00900 };
00901
00902 dbus_g_type_register_map ("GHashTable", &hashtable_vtable, 0);
00903 }
00904
00905 #ifdef DBUS_BUILD_TESTS
00906
00907 typedef struct
00908 {
00909 gboolean seen_foo;
00910 gboolean seen_baz;
00911 } TestSpecializedHashData;
00912
00913 static void
00914 test_specialized_hash (const GValue *key, const GValue *val, gpointer user_data)
00915 {
00916 TestSpecializedHashData *data = user_data;
00917
00918 g_assert (G_VALUE_HOLDS_STRING (key));
00919 g_assert (G_VALUE_HOLDS_STRING (val));
00920
00921 if (!strcmp (g_value_get_string (key), "foo"))
00922 {
00923 data->seen_foo = TRUE;
00924 g_assert (!strcmp (g_value_get_string (val), "bar"));
00925 }
00926 else if (!strcmp (g_value_get_string (key), "baz"))
00927 {
00928 data->seen_baz = TRUE;
00929 g_assert (!strcmp (g_value_get_string (val), "moo"));
00930 }
00931 else
00932 {
00933 g_assert_not_reached ();
00934 }
00935 }
00936
00937 static void
00938 test_specialized_hash_2 (const GValue *key, const GValue *val, gpointer user_data)
00939 {
00940 TestSpecializedHashData *data = user_data;
00941 const GValue *realval;
00942
00943 g_assert (G_VALUE_HOLDS_STRING (key));
00944 g_assert (G_VALUE_TYPE (val) == G_TYPE_VALUE);
00945
00946 realval = g_value_get_boxed (val);
00947
00948 if (!strcmp (g_value_get_string (key), "foo"))
00949 {
00950 data->seen_foo = TRUE;
00951 g_assert (G_VALUE_HOLDS_UINT (realval));
00952 g_assert (g_value_get_uint (realval) == 20);
00953 }
00954 else if (!strcmp (g_value_get_string (key), "baz"))
00955 {
00956 data->seen_baz = TRUE;
00957 g_assert (G_VALUE_HOLDS_STRING (realval));
00958 g_assert (!strcmp ("bar", g_value_get_string (realval)));
00959 }
00960 else
00961 {
00962 g_assert_not_reached ();
00963 }
00964 }
00965
00966 gboolean
00967 _dbus_gvalue_utils_test (const char *datadir)
00968 {
00969 GType type;
00970
00971 dbus_g_type_specialized_init ();
00972 dbus_g_type_specialized_builtins_init ();
00973
00974 type = dbus_g_type_get_collection ("GArray", G_TYPE_UINT);
00975 g_assert (dbus_g_type_is_collection (type));
00976 g_assert (dbus_g_type_get_collection_specialization (type) == G_TYPE_UINT);
00977 {
00978 GArray *instance;
00979
00980 instance = dbus_g_type_specialized_construct (type);
00981
00982 g_assert (instance->len == 0);
00983
00984 g_array_free (instance, TRUE);
00985 }
00986
00987 type = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING);
00988 g_assert (dbus_g_type_is_map (type));
00989 g_assert (dbus_g_type_get_map_key_specialization (type) == G_TYPE_STRING);
00990 g_assert (dbus_g_type_get_map_value_specialization (type) == G_TYPE_STRING);
00991 {
00992 GHashTable *instance;
00993 GValue val = { 0, };
00994 TestSpecializedHashData hashdata;
00995
00996 instance = dbus_g_type_specialized_construct (type);
00997
00998 g_assert (g_hash_table_size (instance) == 0);
00999 g_hash_table_insert (instance, g_strdup ("foo"), g_strdup ("bar"));
01000 g_hash_table_insert (instance, g_strdup ("baz"), g_strdup ("moo"));
01001 g_assert (g_hash_table_size (instance) == 2);
01002
01003 g_value_init (&val, type);
01004 g_value_set_boxed_take_ownership (&val, instance);
01005 hashdata.seen_foo = FALSE;
01006 hashdata.seen_baz = FALSE;
01007 dbus_g_type_map_value_iterate (&val,
01008 test_specialized_hash,
01009 &hashdata);
01010
01011 g_assert (hashdata.seen_foo);
01012 g_assert (hashdata.seen_baz);
01013
01014 g_value_unset (&val);
01015 }
01016
01017 type = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE);
01018 g_assert (dbus_g_type_is_map (type));
01019 g_assert (dbus_g_type_get_map_key_specialization (type) == G_TYPE_STRING);
01020 g_assert (dbus_g_type_get_map_value_specialization (type) == G_TYPE_VALUE);
01021 {
01022 GHashTable *instance;
01023 GValue val = { 0, };
01024 TestSpecializedHashData hashdata;
01025 DBusGTypeSpecializedAppendContext ctx;
01026 GValue *eltval;
01027
01028 instance = dbus_g_type_specialized_construct (type);
01029 g_value_init (&val, type);
01030 g_value_set_boxed_take_ownership (&val, instance);
01031
01032 dbus_g_type_specialized_init_append (&val, &ctx);
01033
01034 {
01035 GValue keyval = { 0, };
01036 GValue valval = { 0, };
01037 g_value_init (&keyval, G_TYPE_STRING);
01038 g_value_set_string (&keyval, "foo");
01039
01040 g_value_init (&valval, G_TYPE_VALUE);
01041 eltval = g_new0 (GValue, 1);
01042 g_value_init (eltval, G_TYPE_UINT);
01043 g_value_set_uint (eltval, 20);
01044 g_value_set_boxed_take_ownership (&valval, eltval);
01045 dbus_g_type_specialized_map_append (&ctx, &keyval, &valval);
01046 }
01047
01048 {
01049 GValue keyval = { 0, };
01050 GValue valval = { 0, };
01051 g_value_init (&keyval, G_TYPE_STRING);
01052 g_value_set_string (&keyval, "baz");
01053 g_value_init (&valval, G_TYPE_VALUE);
01054 eltval = g_new0 (GValue, 1);
01055 g_value_init (eltval, G_TYPE_STRING);
01056 g_value_set_string (eltval, "bar");
01057 g_value_set_boxed_take_ownership (&valval, eltval);
01058 dbus_g_type_specialized_map_append (&ctx, &keyval, &valval);
01059 }
01060
01061 hashdata.seen_foo = FALSE;
01062 hashdata.seen_baz = FALSE;
01063 dbus_g_type_map_value_iterate (&val,
01064 test_specialized_hash_2,
01065 &hashdata);
01066
01067 g_assert (hashdata.seen_foo);
01068 g_assert (hashdata.seen_baz);
01069
01070 g_value_unset (&val);
01071 }
01072
01073 type = dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING);
01074 g_assert (dbus_g_type_is_collection (type));
01075 g_assert (dbus_g_type_get_collection_specialization (type) == G_TYPE_STRING);
01076 {
01077 GPtrArray *instance;
01078 DBusGTypeSpecializedAppendContext ctx;
01079 GValue val = {0, };
01080 GValue eltval = {0, };
01081
01082 instance = dbus_g_type_specialized_construct (type);
01083
01084 g_assert (instance->len == 0);
01085
01086 g_value_init (&val, type);
01087 g_value_set_boxed_take_ownership (&val, instance);
01088
01089 dbus_g_type_specialized_init_append (&val, &ctx);
01090
01091 g_value_init (&eltval, G_TYPE_STRING);
01092 g_value_set_static_string (&eltval, "foo");
01093 dbus_g_type_specialized_collection_append (&ctx, &eltval);
01094
01095 g_value_reset (&eltval);
01096 g_value_set_static_string (&eltval, "bar");
01097 dbus_g_type_specialized_collection_append (&ctx, &eltval);
01098
01099 g_value_reset (&eltval);
01100 g_value_set_static_string (&eltval, "baz");
01101 dbus_g_type_specialized_collection_append (&ctx, &eltval);
01102
01103 dbus_g_type_specialized_collection_end_append (&ctx);
01104
01105 g_assert (instance->len == 3);
01106
01107 g_assert (!strcmp ("foo", g_ptr_array_index (instance, 0)));
01108 g_assert (!strcmp ("bar", g_ptr_array_index (instance, 1)));
01109 g_assert (!strcmp ("baz", g_ptr_array_index (instance, 2)));
01110
01111 g_value_unset (&val);
01112 }
01113
01114 return TRUE;
01115 }
01116
01117
01118
01119 #endif