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