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