1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA.
19 * Copyright 2007 - 2011 Red Hat, Inc.
20 * Copyright 2007 - 2008 Novell, Inc.
23 #include "nm-default.h"
25 #include "nm-gvaluearray-compat.h"
26 #include "nm-param-spec-specialized.h"
28 struct _NMParamSpecSpecialized {
34 #include <netinet/in.h>
35 #include <dbus/dbus-glib.h>
37 #include "nm-dbus-glib-types.h"
39 /***********************************************************/
40 /* _gvalues_compare */
42 static gint _gvalues_compare (const GValue *value1, const GValue *value2);
45 type_is_fixed_size (GType type, gsize *tsize)
49 if (tsize) *tsize = sizeof (char);
52 if (tsize) *tsize = sizeof (guchar);
55 if (tsize) *tsize = sizeof (gboolean);
58 if (tsize) *tsize = sizeof (glong);
61 if (tsize) *tsize = sizeof (gulong);
64 if (tsize) *tsize = sizeof (gint);
67 if (tsize) *tsize = sizeof (guint);
70 if (tsize) *tsize = sizeof (gint64);
73 if (tsize) *tsize = sizeof (guint64);
76 if (tsize) *tsize = sizeof (gfloat);
79 if (tsize) *tsize = sizeof (gdouble);
86 #define FLOAT_FACTOR 0.00000001
89 _gvalues_compare_fixed (const GValue *value1, const GValue *value2)
93 switch (G_VALUE_TYPE (value1)) {
95 gchar val1 = g_value_get_schar (value1);
96 gchar val2 = g_value_get_schar (value2);
98 ret = val1 < val2 ? -1 : val1 > val2;
102 guchar val1 = g_value_get_uchar (value1);
103 guchar val2 = g_value_get_uchar (value2);
105 ret = val1 < val2 ? -1 : val1 > val2;
108 case G_TYPE_BOOLEAN: {
109 gboolean val1 = g_value_get_boolean (value1);
110 gboolean val2 = g_value_get_boolean (value2);
112 ret = val1 < val2 ? -1 : val1 > val2;
116 glong val1 = g_value_get_long (value1);
117 glong val2 = g_value_get_long (value2);
119 ret = val1 < val2 ? -1 : val1 > val2;
123 gulong val1 = g_value_get_ulong (value1);
124 gulong val2 = g_value_get_ulong (value2);
126 ret = val1 < val2 ? -1 : val1 > val2;
130 gint val1 = g_value_get_int (value1);
131 gint val2 = g_value_get_int (value2);
133 ret = val1 < val2 ? -1 : val1 > val2;
137 guint val1 = g_value_get_uint (value1);
138 guint val2 = g_value_get_uint (value2);
140 ret = val1 < val2 ? -1 : val1 > val2;
144 gint64 val1 = g_value_get_int64 (value1);
145 gint64 val2 = g_value_get_int64 (value2);
147 ret = val1 < val2 ? -1 : val1 > val2;
150 case G_TYPE_UINT64: {
151 guint64 val1 = g_value_get_uint64 (value1);
152 guint64 val2 = g_value_get_uint64 (value2);
154 ret = val1 < val2 ? -1 : val1 > val2;
158 gfloat val1 = g_value_get_float (value1);
159 gfloat val2 = g_value_get_float (value2);
160 /* Can't use == or != here due to inexactness of FP */
161 if (fabsf (val1 - val2) > FLOAT_FACTOR)
162 ret = val1 < val2 ? -1 : val1 > val2;
165 case G_TYPE_DOUBLE: {
166 gdouble val1 = g_value_get_double (value1);
167 gdouble val2 = g_value_get_double (value2);
168 if (fabs (val1 - val2) > FLOAT_FACTOR)
169 ret = val1 < val2 ? -1 : val1 > val2;
173 g_warning ("Unhandled fixed size type '%s'", G_VALUE_TYPE_NAME (value1));
180 _gvalues_compare_string (const GValue *value1, const GValue *value2)
182 const char *str1 = g_value_get_string (value1);
183 const char *str2 = g_value_get_string (value2);
193 return strcmp (str1, str2);
197 _gvalues_compare_strv (const GValue *value1, const GValue *value2)
204 strv1 = (char **) g_value_get_boxed (value1);
205 strv2 = (char **) g_value_get_boxed (value2);
207 while (strv1[i] && strv2[i]) {
208 ret = strcmp (strv1[i], strv2[i]);
214 if (strv1[i] == NULL && strv2[i] == NULL)
224 _gvalue_destroy (gpointer data)
226 GValue *value = (GValue *) data;
228 g_value_unset (value);
229 g_slice_free (GValue, value);
233 _gvalue_dup (const GValue *value)
237 dup = g_slice_new0 (GValue);
238 g_value_init (dup, G_VALUE_TYPE (value));
239 g_value_copy (value, dup);
245 iterate_collection (const GValue *value, gpointer user_data)
247 GSList **list = (GSList **) user_data;
249 *list = g_slist_prepend (*list, _gvalue_dup (value));
253 _gvalues_compare_collection (const GValue *value1, const GValue *value2)
258 GType value_type = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value1));
259 gsize element_size = 0;
261 if (type_is_fixed_size (value_type, &element_size)) {
262 gpointer data1 = NULL;
263 gpointer data2 = NULL;
265 dbus_g_type_collection_get_fixed ((GValue *) value1, &data1, &len1);
266 dbus_g_type_collection_get_fixed ((GValue *) value2, &data2, &len2);
269 ret = len1 < len2 ? -1 : len1 > len2;
271 ret = memcmp (data1, data2, len1 * element_size);
273 GSList *list1 = NULL;
274 GSList *list2 = NULL;
276 dbus_g_type_collection_value_iterate (value1, iterate_collection, &list1);
277 len1 = g_slist_length (list1);
278 dbus_g_type_collection_value_iterate (value2, iterate_collection, &list2);
279 len2 = g_slist_length (list2);
282 ret = len1 < len2 ? -1 : len1 > len2;
287 for (iter1 = list1, iter2 = list2, ret = 0;
288 ret == 0 && iter1 && iter2;
289 iter1 = iter1->next, iter2 = iter2->next)
290 ret = _gvalues_compare ((GValue *) iter1->data, (GValue *) iter2->data);
293 g_slist_free_full (list1, _gvalue_destroy);
294 g_slist_free_full (list2, _gvalue_destroy);
301 iterate_map (const GValue *key_val,
302 const GValue *value_val,
305 GHashTable **hash = (GHashTable **) user_data;
307 g_hash_table_insert (*hash, g_value_dup_string (key_val), _gvalue_dup (value_val));
316 compare_one_map_item (gpointer key, gpointer val, gpointer user_data)
318 CompareMapInfo *info = (CompareMapInfo *) user_data;
324 value2 = (GValue *) g_hash_table_lookup (info->hash2, key);
326 info->ret = _gvalues_compare ((GValue *) val, value2);
332 _gvalues_compare_map (const GValue *value1, const GValue *value2)
334 GHashTable *hash1 = NULL;
335 GHashTable *hash2 = NULL;
340 if (dbus_g_type_get_map_key_specialization (G_VALUE_TYPE (value1)) != G_TYPE_STRING) {
341 g_warning ("Can not compare maps with '%s' for keys",
342 g_type_name (dbus_g_type_get_map_key_specialization (G_VALUE_TYPE (value1))));
346 hash1 = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, _gvalue_destroy);
347 dbus_g_type_map_value_iterate (value1, iterate_map, &hash1);
348 len1 = g_hash_table_size (hash1);
350 hash2 = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, _gvalue_destroy);
351 dbus_g_type_map_value_iterate (value2, iterate_map, &hash2);
352 len2 = g_hash_table_size (hash2);
355 ret = len1 < len2 ? -1 : len1 > len2;
361 g_hash_table_foreach (hash1, compare_one_map_item, &info);
365 g_hash_table_destroy (hash1);
366 g_hash_table_destroy (hash2);
372 _gvalue_ip6_address_compare (const GValue *value1, const GValue *value2)
374 GValueArray *values1, *values2;
376 GByteArray *addr1, *addr2;
377 guint32 prefix1, prefix2;
378 GByteArray *gw1, *gw2;
382 /* IP6 addresses are GValueArrays (see nm-dbus-glib-types.h) */
383 values1 = g_value_get_boxed (value1);
384 values2 = g_value_get_boxed (value2);
386 /* Since they are NM IPv6 address structures, we expect both
387 * to contain two elements as specified in nm-dbus-glib-types.h.
389 g_return_val_if_fail (values1->n_values == 3, 0);
390 g_return_val_if_fail (values2->n_values == 3, 0);
392 /* First struct IPv6 address */
393 tmp_val = g_value_array_get_nth (values1, 0);
394 addr1 = g_value_get_boxed (tmp_val);
395 /* First struct IPv6 prefix */
396 tmp_val = g_value_array_get_nth (values1, 1);
397 prefix1 = g_value_get_uint (tmp_val);
398 /* First struct IPv6 gateway */
399 tmp_val = g_value_array_get_nth (values1, 2);
400 gw1 = g_value_get_boxed (tmp_val);
402 /* Second struct IPv6 address */
403 tmp_val = g_value_array_get_nth (values2, 0);
404 addr2 = g_value_get_boxed (tmp_val);
405 /* Second struct IPv6 prefix */
406 tmp_val = g_value_array_get_nth (values2, 1);
407 prefix2 = g_value_get_uint (tmp_val);
408 /* Second struct IPv6 gateway */
409 tmp_val = g_value_array_get_nth (values2, 2);
410 gw2 = g_value_get_boxed (tmp_val);
412 /* Compare IPv6 addresses */
413 if (prefix1 != prefix2)
414 return prefix1 < prefix2 ? -1 : prefix1 > prefix2;
416 if (!IN6_ARE_ADDR_EQUAL ((struct in6_addr *)addr1->data, (struct in6_addr *)addr2->data)) {
417 for (i = 0; ret == 0 && i < addr1->len; i++)
418 ret = addr1->data[i] < addr2->data[i] ? -1 : addr1->data[i] > addr2->data[i];
421 if (!IN6_ARE_ADDR_EQUAL ((struct in6_addr *) gw1->data, (struct in6_addr *) gw2->data)) {
422 for (i = 0; ret == 0 && i < gw1->len; i++)
423 ret = gw1->data[i] < gw2->data[i] ? -1 : gw1->data[i] > gw2->data[i];
430 _gvalue_ip6_route_compare (const GValue *value1, const GValue *value2)
432 GValueArray *values1, *values2;
434 GByteArray *dest1, *dest2;
435 GByteArray *next_hop1, *next_hop2;
436 guint32 prefix1, prefix2;
437 guint32 metric1, metric2;
441 /* IP6 routes are GValueArrays (see nm-dbus-glib-types.h) */
442 values1 = g_value_get_boxed (value1);
443 values2 = g_value_get_boxed (value2);
445 /* Since they are NM IPv6 route structures, we expect both
446 * to contain 4 elements as specified in nm-dbus-glib-types.h.
448 g_return_val_if_fail (values1->n_values == 4, 0);
449 g_return_val_if_fail (values2->n_values == 4, 0);
451 /* First struct IPv6 route */
452 tmp_val = g_value_array_get_nth (values1, 0);
453 dest1 = g_value_get_boxed (tmp_val);
454 tmp_val = g_value_array_get_nth (values1, 1);
455 prefix1 = g_value_get_uint (tmp_val);
456 tmp_val = g_value_array_get_nth (values1, 2);
457 next_hop1 = g_value_get_boxed (tmp_val);
458 tmp_val = g_value_array_get_nth (values1, 3);
459 metric1 = g_value_get_uint (tmp_val);
461 /* Second struct IPv6 route */
462 tmp_val = g_value_array_get_nth (values2, 0);
463 dest2 = g_value_get_boxed (tmp_val);
464 tmp_val = g_value_array_get_nth (values2, 1);
465 prefix2 = g_value_get_uint (tmp_val);
466 tmp_val = g_value_array_get_nth (values2, 2);
467 next_hop2 = g_value_get_boxed (tmp_val);
468 tmp_val = g_value_array_get_nth (values2, 3);
469 metric2 = g_value_get_uint (tmp_val);
471 /* Compare the routes */
472 if (prefix1 != prefix2)
473 return prefix1 < prefix2 ? -1 : prefix1 > prefix2;
475 if (!IN6_ARE_ADDR_EQUAL ((struct in6_addr *)dest1->data, (struct in6_addr *)dest2->data)) {
476 for (i = 0; ret == 0 && i < dest1->len; i++)
477 ret = dest1->data[i] < dest2->data[i] ? -1 : dest1->data[i] > dest2->data[i];
480 if (!IN6_ARE_ADDR_EQUAL ((struct in6_addr *)next_hop1->data, (struct in6_addr *)next_hop2->data)) {
481 for (i = 0; ret == 0 && i < next_hop1->len; i++)
482 ret = next_hop1->data[i] < next_hop2->data[i] ? -1 : next_hop1->data[i] > next_hop2->data[i];
485 if (metric1 != metric2)
486 ret = metric1 < metric2 ? -1 : metric1 > metric2;
492 _gvalues_compare_struct (const GValue *value1, const GValue *value2)
494 /* value1 and value2 must contain the same type since
495 * _gvalues_compare() enforced that already.
498 if (G_VALUE_HOLDS (value1, DBUS_TYPE_G_IP6_ADDRESS)) {
499 return _gvalue_ip6_address_compare (value1, value2);
500 } else if (G_VALUE_HOLDS (value1, DBUS_TYPE_G_IP6_ROUTE)) {
501 return _gvalue_ip6_route_compare (value1, value2);
503 g_warning ("Don't know how to compare structures");
504 return (value1 == value2);
509 _gvalues_compare (const GValue *value1, const GValue *value2)
515 if (value1 == value2)
522 type1 = G_VALUE_TYPE (value1);
523 type2 = G_VALUE_TYPE (value2);
526 return type1 < type2 ? -1 : type1 > type2;
528 if (type_is_fixed_size (type1, NULL))
529 ret = _gvalues_compare_fixed (value1, value2);
530 else if (type1 == G_TYPE_STRING)
531 ret = _gvalues_compare_string (value1, value2);
532 else if (G_VALUE_HOLDS_BOXED (value1)) {
533 gpointer p1 = g_value_get_boxed (value1);
534 gpointer p2 = g_value_get_boxed (value2);
537 ret = 0; /* Exactly the same values */
539 ret = 1; /* The comparision functions below don't handle NULLs */
541 ret = -1; /* The comparision functions below don't handle NULLs */
542 else if (type1 == G_TYPE_STRV)
543 ret = _gvalues_compare_strv (value1, value2);
544 else if (dbus_g_type_is_collection (type1))
545 ret = _gvalues_compare_collection (value1, value2);
546 else if (dbus_g_type_is_map (type1))
547 ret = _gvalues_compare_map (value1, value2);
548 else if (dbus_g_type_is_struct (type1))
549 ret = _gvalues_compare_struct (value1, value2);
550 else if (type1 == G_TYPE_VALUE)
551 ret = _gvalues_compare ((GValue *) g_value_get_boxed (value1), (GValue *) g_value_get_boxed (value2));
553 g_warning ("Don't know how to compare boxed types '%s'", g_type_name (type1));
554 ret = value1 == value2;
557 g_warning ("Don't know how to compare types '%s'", g_type_name (type1));
558 ret = value1 == value2;
564 /***********************************************************/
567 param_specialized_init (GParamSpec *pspec)
572 param_specialized_set_default (GParamSpec *pspec, GValue *value)
574 value->data[0].v_pointer = NULL;
578 param_specialized_validate (GParamSpec *pspec, GValue *value)
580 NMParamSpecSpecialized *sspec = NM_PARAM_SPEC_SPECIALIZED (pspec);
581 GType value_type = G_VALUE_TYPE (value);
582 gboolean changed = FALSE;
584 if (!g_value_type_compatible (value_type, G_PARAM_SPEC_VALUE_TYPE (sspec))) {
585 g_value_reset (value);
593 param_specialized_values_cmp (GParamSpec *pspec,
594 const GValue *value1,
595 const GValue *value2)
597 return _gvalues_compare (value1, value2);
601 _nm_param_spec_specialized_get_type (void)
605 if (G_UNLIKELY (type) == 0) {
606 static const GParamSpecTypeInfo pspec_info = {
607 sizeof (NMParamSpecSpecialized),
609 param_specialized_init,
610 G_TYPE_OBJECT, /* value_type */
612 param_specialized_set_default,
613 param_specialized_validate,
614 param_specialized_values_cmp,
616 type = g_param_type_register_static ("NMParamSpecSpecialized", &pspec_info);
623 _nm_param_spec_specialized (const char *name,
626 GType specialized_type,
629 NMParamSpecSpecialized *pspec;
631 g_return_val_if_fail (g_type_is_a (specialized_type, G_TYPE_BOXED), NULL);
633 pspec = g_param_spec_internal (NM_TYPE_PARAM_SPEC_SPECIALIZED,
634 name, nick, blurb, flags);
636 G_PARAM_SPEC (pspec)->value_type = specialized_type;
638 return G_PARAM_SPEC (pspec);
641 /***********************************************************/
649 GValue value1 = G_VALUE_INIT;
650 GValue value2 = G_VALUE_INIT;
652 g_value_init (&value1, G_TYPE_INT);
653 g_value_init (&value2, G_TYPE_INT);
655 g_value_set_int (&value1, 5);
656 g_value_set_int (&value2, 5);
657 g_print ("Comparing ints 5 and 5: %d\n", _gvalues_compare (&value1, &value2));
659 g_value_set_int (&value2, 10);
660 g_print ("Comparing ints 5 and 10: %d\n", _gvalues_compare (&value1, &value2));
662 g_value_set_int (&value2, 1);
663 g_print ("Comparing ints 5 and 1: %d\n", _gvalues_compare (&value1, &value2));
667 compare_strings (void)
669 GValue value1 = G_VALUE_INIT;
670 GValue value2 = G_VALUE_INIT;
671 const char *str1 = "hello";
672 const char *str2 = "world";
674 g_value_init (&value1, G_TYPE_STRING);
675 g_value_init (&value2, G_TYPE_STRING);
677 g_value_set_string (&value1, str1);
678 g_value_set_string (&value2, str1);
679 g_print ("Comparing identical strings: %d\n", _gvalues_compare (&value1, &value2));
681 g_value_set_string (&value2, str2);
682 g_print ("Comparing different strings: %d\n", _gvalues_compare (&value1, &value2));
688 GValue value1 = G_VALUE_INIT;
689 GValue value2 = G_VALUE_INIT;
690 char *strv1[] = { "foo", "bar", "baz", NULL };
691 char *strv2[] = { "foo", "bar", "bar", NULL };
692 char *strv3[] = { "foo", "bar", NULL };
693 char *strv4[] = { "foo", "bar", "baz", "bam", NULL };
695 g_value_init (&value1, G_TYPE_STRV);
696 g_value_init (&value2, G_TYPE_STRV);
698 g_value_set_boxed (&value1, strv1);
699 g_value_set_boxed (&value2, strv1);
700 g_print ("Comparing identical strv's: %d\n", _gvalues_compare (&value1, &value2));
702 g_value_set_boxed (&value2, strv2);
703 g_print ("Comparing different strv's: %d\n", _gvalues_compare (&value1, &value2));
705 g_value_set_boxed (&value2, strv3);
706 g_print ("Comparing different len (smaller) strv's: %d\n", _gvalues_compare (&value1, &value2));
708 g_value_set_boxed (&value2, strv4);
709 g_print ("Comparing different len (longer) strv's: %d\n", _gvalues_compare (&value1, &value2));
713 compare_garrays (void)
717 GValue value1 = G_VALUE_INIT;
718 GValue value2 = G_VALUE_INIT;
721 g_value_init (&value1, DBUS_TYPE_G_UINT_ARRAY);
722 array1 = g_array_new (FALSE, FALSE, sizeof (guint32));
724 g_value_init (&value2, DBUS_TYPE_G_UINT_ARRAY);
725 array2 = g_array_new (FALSE, FALSE, sizeof (guint32));
727 for (i = 0; i < 5; i++) {
728 g_array_append_val (array1, i);
729 g_array_append_val (array2, i);
732 g_value_set_boxed (&value1, array1);
733 g_value_set_boxed (&value2, array2);
735 g_print ("Comparing identical arrays's: %d\n", _gvalues_compare (&value1, &value2));
737 g_array_remove_index (array2, 0);
738 g_value_set_boxed (&value2, array2);
739 g_print ("Comparing different length arrays's: %d\n", _gvalues_compare (&value1, &value2));
742 g_array_prepend_val (array2, i);
743 g_value_set_boxed (&value2, array2);
744 g_print ("Comparing different arrays's: %d\n", _gvalues_compare (&value1, &value2));
748 compare_ptrarrays (void)
752 GValue value1 = G_VALUE_INIT;
753 GValue value2 = G_VALUE_INIT;
755 g_value_init (&value1, dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING));
756 array1 = g_ptr_array_new ();
758 g_value_init (&value2, dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING));
759 array2 = g_ptr_array_new ();
761 g_ptr_array_add (array1, "hello");
762 g_ptr_array_add (array1, "world");
763 g_value_set_boxed (&value1, array1);
765 g_ptr_array_add (array2, "hello");
766 g_ptr_array_add (array2, "world");
767 g_value_set_boxed (&value2, array2);
769 g_print ("Comparing identical ptr arrays's: %d\n", _gvalues_compare (&value1, &value2));
771 g_ptr_array_add (array2, "boo");
772 g_value_set_boxed (&value2, array2);
773 g_print ("Comparing different len ptr arrays's: %d\n", _gvalues_compare (&value1, &value2));
775 g_ptr_array_add (array1, "booz");
776 g_value_set_boxed (&value1, array1);
777 g_print ("Comparing different ptr arrays's: %d\n", _gvalues_compare (&value1, &value2));
781 compare_str_hash (void)
785 GValue value1 = G_VALUE_INIT;
786 GValue value2 = G_VALUE_INIT;
788 g_value_init (&value1, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING));
789 g_value_init (&value2, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING));
791 hash1 = g_hash_table_new (g_str_hash, g_str_equal);
792 hash2 = g_hash_table_new (g_str_hash, g_str_equal);
794 g_hash_table_insert (hash1, "key1", "hello");
795 g_hash_table_insert (hash1, "key2", "world");
797 g_hash_table_insert (hash2, "key1", "hello");
798 g_hash_table_insert (hash2, "key2", "world");
800 g_value_set_boxed (&value1, hash1);
801 g_value_set_boxed (&value2, hash2);
802 g_print ("Comparing identical str hashes: %d\n", _gvalues_compare (&value1, &value2));
804 g_hash_table_remove (hash2, "key2");
805 g_value_set_boxed (&value2, hash2);
806 g_print ("Comparing different length str hashes: %d\n", _gvalues_compare (&value1, &value2));
808 g_hash_table_insert (hash2, "key2", "moon");
809 g_value_set_boxed (&value2, hash2);
810 g_print ("Comparing different str hashes: %d\n", _gvalues_compare (&value1, &value2));
814 str_to_gvalue (const char *str)
818 value = g_slice_new0 (GValue);
819 g_value_init (value, G_TYPE_STRING);
820 g_value_set_string (value, str);
826 int_to_gvalue (int i)
830 value = g_slice_new0 (GValue);
831 g_value_init (value, G_TYPE_INT);
832 g_value_set_int (value, i);
838 compare_gvalue_hash (void)
842 GValue value1 = G_VALUE_INIT;
843 GValue value2 = G_VALUE_INIT;
845 g_value_init (&value1, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE));
846 g_value_init (&value2, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE));
848 hash1 = g_hash_table_new (g_str_hash, g_str_equal);
849 hash2 = g_hash_table_new (g_str_hash, g_str_equal);
851 g_hash_table_insert (hash1, "key1", str_to_gvalue ("hello"));
852 g_hash_table_insert (hash1, "key2", int_to_gvalue (5));
854 g_hash_table_insert (hash2, "key1", str_to_gvalue ("hello"));
855 g_hash_table_insert (hash2, "key2", int_to_gvalue (5));
857 g_value_set_boxed (&value1, hash1);
858 g_value_set_boxed (&value2, hash2);
859 g_print ("Comparing identical gvalue hashes: %d\n", _gvalues_compare (&value1, &value2));
861 g_hash_table_remove (hash2, "key2");
862 g_value_set_boxed (&value2, hash2);
863 g_print ("Comparing different length str hashes: %d\n", _gvalues_compare (&value1, &value2));
865 g_hash_table_insert (hash2, "key2", str_to_gvalue ("moon"));
866 g_value_set_boxed (&value2, hash2);
867 g_print ("Comparing different str hashes: %d\n", _gvalues_compare (&value1, &value2));
871 compare_ip6_addresses (void)
879 GValue element = G_VALUE_INIT;
880 GValue value1 = G_VALUE_INIT;
881 GValue value2 = G_VALUE_INIT;
882 struct in6_addr addr1;
883 struct in6_addr addr2;
884 struct in6_addr addr3;
885 guint32 prefix1 = 64;
886 guint32 prefix2 = 64;
889 inet_pton (AF_INET6, "1:2:3:4:5:6:7:8", &addr1, sizeof (struct in6_addr));
890 inet_pton (AF_INET6, "ffff:2:3:4:5:6:7:8", &addr2, sizeof (struct in6_addr));
891 inet_pton (AF_INET6, "::", &addr3, sizeof (struct in6_addr));
894 ba1 = g_byte_array_new ();
895 array1 = g_value_array_new (2);
896 g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
897 g_byte_array_append (ba1, (guint8 *) addr1.s6_addr, 16);
898 g_value_take_boxed (&element, ba1);
899 g_value_array_append (array1, &element);
900 g_value_unset (&element);
902 g_value_init (&element, G_TYPE_UINT);
903 g_value_set_uint (&element, prefix1);
904 g_value_array_append (array1, &element);
905 g_value_unset (&element);
908 ba2 = g_byte_array_new ();
909 array2 = g_value_array_new (2);
910 g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
911 g_byte_array_append (ba2, (guint8 *) addr2.s6_addr, 16);
912 g_value_take_boxed (&element, ba2);
913 g_value_array_append (array2, &element);
914 g_value_unset (&element);
916 g_value_init (&element, G_TYPE_UINT);
917 g_value_set_uint (&element, prefix2);
918 g_value_array_append (array2, &element);
919 g_value_unset (&element);
922 ba3 = g_byte_array_new ();
923 array3 = g_value_array_new (2);
924 g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
925 g_byte_array_append (ba3, (guint8 *) addr3.s6_addr, 16);
926 g_value_take_boxed (&element, ba3);
927 g_value_array_append (array3, &element);
928 g_value_unset (&element);
930 g_value_init (&element, G_TYPE_UINT);
931 g_value_set_uint (&element, prefix3);
932 g_value_array_append (array3, &element);
933 g_value_unset (&element);
935 g_value_init (&value1, DBUS_TYPE_G_IP6_ADDRESS);
936 g_value_init (&value2, DBUS_TYPE_G_IP6_ADDRESS);
938 g_value_set_boxed (&value1, array1);
939 g_value_set_boxed (&value2, array1);
940 g_print ("Comparing identical IPv6 address structures: %d\n", _gvalues_compare (&value1, &value2));
942 g_value_set_boxed (&value1, array1);
943 g_value_set_boxed (&value2, array2);
944 g_print ("Comparing different IPv6 address structures: %d\n", _gvalues_compare (&value1, &value2));
946 g_value_set_boxed (&value1, array1);
947 g_value_set_boxed (&value2, array3);
948 g_print ("Comparing different IPv6 address structures: %d\n", _gvalues_compare (&value1, &value2));
952 main (int argc, char *argv[])
954 DBusGConnection *bus;
958 bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
964 compare_ptrarrays ();
966 compare_gvalue_hash ();
967 compare_ip6_addresses ();