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