1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-dict.h Dict object for key-value data.
4 * Copyright (C) 2003 CodeFactory AB
6 * Licensed under the Academic Free License version 1.2
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "dbus-dict.h"
24 #include "dbus-hash.h"
25 #include "dbus-internals.h"
26 #include "dbus-protocol.h"
29 * @defgroup DBusDict DBusDict
31 * @brief key/value data structure.
33 * A DBusDict is a data structure that can store and lookup different
50 dbus_bool_t boolean_value;
51 dbus_int32_t int32_value;
52 dbus_uint32_t uint32_value;
79 dbus_dict_entry_free (DBusDictEntry *entry)
86 case DBUS_TYPE_INVALID:
87 case DBUS_TYPE_BOOLEAN:
89 case DBUS_TYPE_UINT32:
90 case DBUS_TYPE_DOUBLE:
92 case DBUS_TYPE_STRING:
93 dbus_free (entry->v.string_value);
95 case DBUS_TYPE_BOOLEAN_ARRAY:
96 dbus_free (entry->v.boolean_array.value);
98 case DBUS_TYPE_INT32_ARRAY:
99 dbus_free (entry->v.int32_array.value);
101 case DBUS_TYPE_UINT32_ARRAY:
102 dbus_free (entry->v.uint32_array.value);
104 case DBUS_TYPE_DOUBLE_ARRAY:
105 dbus_free (entry->v.uint32_array.value);
107 case DBUS_TYPE_STRING_ARRAY:
108 dbus_free_string_array (entry->v.string_array.value);
111 _dbus_assert_not_reached ("Unknown or invalid dict entry type\n");
118 * Constructs a new DBusDict. Returns #NULL if memory can't be
121 * @returns a new DBusDict or #NULL.
128 dict = dbus_new0 (DBusDict, 1);
133 dict->table = _dbus_hash_table_new (DBUS_HASH_STRING, dbus_free, (DBusFreeFunction)dbus_dict_entry_free);
147 * Increments the reference count of a DBusDict.
149 * @param dict the dict.
150 * @see dbus_dict_unref
153 dbus_dict_ref (DBusDict *dict)
157 _dbus_assert (dict->refcount > 1);
161 * Decrements the reference count of a DBusDict
163 * @param dict the dict
167 dbus_dict_unref (DBusDict *dict)
171 _dbus_assert (dict->refcount >= 0);
173 if (dict->refcount == 0)
175 _dbus_hash_table_unref (dict->table);
181 * Checks if the dict contains the specified key.
183 * @param dict the dict.
185 * @returns #TRUE if the dict contains the specified key.
188 dbus_dict_contains (DBusDict *dict,
191 return (_dbus_hash_table_lookup_string (dict->table, key) != NULL);
195 * Removes the dict entry for the given key. If no dict entry for the
196 * key exists, this function does nothing.
198 * @param dict the dict
200 * @returns #TRUE if the entry existed
203 dbus_dict_remove (DBusDict *dict,
206 return _dbus_hash_table_remove_string (dict->table, key);
210 * Returns the type of the value in the dict entry specified by the key.
212 * @param dict the dict
214 * @returns the value type or DBUS_TYPE_NIL if the key wasn't found.
217 dbus_dict_get_value_type (DBusDict *dict,
220 DBusDictEntry *entry;
222 entry = _dbus_hash_table_lookup_string (dict->table, key);
225 return DBUS_TYPE_NIL;
231 * Returns the keys in the dict as a string array.
233 * @param dict the dict
234 * @param keys return location for string array
235 * @param len return location for string array length
236 * ®returns #TRUE on success
239 dbus_dict_get_keys (DBusDict *dict,
248 size = _dbus_hash_table_get_n_entries (dict->table);
257 tmp = dbus_new0 (char *, size + 1);
263 _dbus_hash_iter_init (dict->table, &iter);
265 while (_dbus_hash_iter_next (&iter))
267 key = _dbus_strdup (_dbus_hash_iter_get_string_key (&iter));
271 dbus_free_string_array (tmp);
285 insert_entry (DBusDict *dict,
287 DBusDictEntry **entry)
291 tmp = _dbus_strdup (key);
296 *entry = dbus_new0 (DBusDictEntry, 1);
304 if (!_dbus_hash_table_insert_string (dict->table, tmp, *entry))
307 dbus_dict_entry_free (*entry);
316 * Adds a boolean value to the dict. If a value with the same key
317 * already exists, then it will be replaced by the new value.
319 * @param dict the dict
321 * @param value the value
322 * @returns #TRUE on success
325 dbus_dict_set_boolean (DBusDict *dict,
329 DBusDictEntry *entry;
331 if (insert_entry (dict, key, &entry))
333 entry->type = DBUS_TYPE_BOOLEAN;
334 entry->v.boolean_value = value;
343 * Adds a 32 bit signed integer value to the dict. If a value with the
344 * same key already exists, then it will be replaced by the new value.
346 * @param dict the dict
348 * @param value the value
349 * @returns #TRUE on success
352 dbus_dict_set_int32 (DBusDict *dict,
356 DBusDictEntry *entry;
358 if (insert_entry (dict, key, &entry))
360 entry->type = DBUS_TYPE_INT32;
361 entry->v.int32_value = value;
370 * Adds a 32 bit unsigned integer value to the dict. If a value with
371 * the same key already exists, then it will be replaced by the new
374 * @param dict the dict
376 * @param value the value
377 * @returns #TRUE on success
380 dbus_dict_set_uint32 (DBusDict *dict,
384 DBusDictEntry *entry;
386 if (insert_entry (dict, key, &entry))
388 entry->type = DBUS_TYPE_UINT32;
389 entry->v.uint32_value = value;
398 * Adds a 32 bit double value to the dict. If a value with the same
399 * key already exists, then it will be replaced by the new value.
401 * @param dict the dict
403 * @param value the value
404 * @returns #TRUE on success
407 dbus_dict_set_double (DBusDict *dict,
411 DBusDictEntry *entry;
413 if (insert_entry (dict, key, &entry))
415 entry->type = DBUS_TYPE_DOUBLE;
416 entry->v.double_value = value;
425 * Adds a string to the dict. If a value with the same key already
426 * exists, then it will be replaced by the new value.
428 * @param dict the dict
430 * @param value the value
431 * @returns #TRUE on success
434 dbus_dict_set_string (DBusDict *dict,
438 DBusDictEntry *entry;
441 tmp = _dbus_strdup (value);
446 if (insert_entry (dict, key, &entry))
448 entry->type = DBUS_TYPE_STRING;
449 entry->v.string_value = tmp;
458 * Adds a boolean array to the dict. If a value with the same key
459 * already exists, then it will be replaced by the new value.
461 * @param dict the dict
463 * @param value the value
464 * @param len the array length
465 * @returns #TRUE on success
468 dbus_dict_set_boolean_array (DBusDict *dict,
470 unsigned const char *value,
473 DBusDictEntry *entry;
476 tmp = dbus_malloc (len);
481 memcpy (tmp, value, len);
483 if (insert_entry (dict, key, &entry))
485 entry->type = DBUS_TYPE_BOOLEAN_ARRAY;
486 entry->v.boolean_array.value = tmp;
487 entry->v.boolean_array.len = len;
496 * Adds a 32 bit signed integer array to the dict. If a value with the
497 * same key already exists, then it will be replaced by the new value.
499 * @param dict the dict
501 * @param value the value
502 * @param len the array length
503 * @returns #TRUE on success
506 dbus_dict_set_int32_array (DBusDict *dict,
508 const dbus_int32_t *value,
511 DBusDictEntry *entry;
514 tmp = dbus_new (dbus_int32_t, len);
519 memcpy (tmp, value, len * sizeof (dbus_int32_t));
521 if (insert_entry (dict, key, &entry))
523 entry->type = DBUS_TYPE_INT32_ARRAY;
524 entry->v.int32_array.value = tmp;
525 entry->v.int32_array.len = len;
534 * Adds a 32 bit unsigned integer array to the dict. If a value with
535 * the same key already exists, then it will be replaced by the new
538 * @param dict the dict
540 * @param value the value
541 * @param len the array length
542 * @returns #TRUE on success
545 dbus_dict_set_uint32_array (DBusDict *dict,
547 const dbus_uint32_t *value,
550 DBusDictEntry *entry;
553 tmp = dbus_new (dbus_uint32_t, len);
558 memcpy (tmp, value, len * sizeof (dbus_uint32_t));
560 if (insert_entry (dict, key, &entry))
562 entry->type = DBUS_TYPE_UINT32_ARRAY;
563 entry->v.uint32_array.value = tmp;
564 entry->v.int32_array.len = len;
573 * Adds a double array to the dict. If a value with the same key
574 * already exists, then it will be replaced by the new value.
576 * @param dict the dict
578 * @param value the value
579 * @param len the array length
580 * @returns #TRUE on success
583 dbus_dict_set_double_array (DBusDict *dict,
588 DBusDictEntry *entry;
591 tmp = dbus_new (double, len);
596 memcpy (tmp, value, len * sizeof (double));
598 if (insert_entry (dict, key, &entry))
600 entry->type = DBUS_TYPE_DOUBLE_ARRAY;
601 entry->v.double_array.value = tmp;
602 entry->v.double_array.len = len;
611 * Adds a string array to the dict. If a value with the same key
612 * already exists, then it will be replaced by the new value.
614 * @param dict the dict
616 * @param value the value
617 * @param len the array length
618 * @returns #TRUE on success
621 dbus_dict_set_string_array (DBusDict *dict,
626 DBusDictEntry *entry;
630 tmp = dbus_new0 (char *, len + 1);
634 for (i = 0; i < len; i++)
636 tmp[i] = _dbus_strdup (value[i]);
639 dbus_free_string_array (tmp);
644 if (insert_entry (dict, key, &entry))
646 entry->type = DBUS_TYPE_STRING_ARRAY;
647 entry->v.string_array.value = tmp;
648 entry->v.string_array.len = len;
657 * Gets a boolean value from a dict using a key.
659 * @param dict the dict
661 * @param value return location for the value
662 * @returns #TRUE if the key exists and the value is of the correct
666 dbus_dict_get_boolean (DBusDict *dict,
670 DBusDictEntry *entry;
672 entry = _dbus_hash_table_lookup_string (dict->table, key);
674 if (!entry || entry->type != DBUS_TYPE_BOOLEAN)
677 *value = entry->v.boolean_value;
683 * Gets a 32 bit signed integer value from a dict using a key.
685 * @param dict the dict
687 * @param value return location for the value
688 * @returns #TRUE if the key exists and the value is of the correct
692 dbus_dict_get_int32 (DBusDict *dict,
696 DBusDictEntry *entry;
698 entry = _dbus_hash_table_lookup_string (dict->table, key);
700 if (!entry || entry->type != DBUS_TYPE_INT32)
703 *value = entry->v.int32_value;
709 * Gets a 32 bit unsigned integer value from a dict using a key.
711 * @param dict the dict
713 * @param value return location for the value
714 * @returns #TRUE if the key exists and the value is of the correct
718 dbus_dict_get_uint32 (DBusDict *dict,
720 dbus_uint32_t *value)
722 DBusDictEntry *entry;
724 entry = _dbus_hash_table_lookup_string (dict->table, key);
726 if (!entry || entry->type != DBUS_TYPE_UINT32)
729 *value = entry->v.uint32_value;
735 * Gets a double value from a dict using a key.
737 * @param dict the dict
739 * @param value return location for the value
740 * @returns #TRUE if the key exists and the value is of the correct
744 dbus_dict_get_double (DBusDict *dict,
748 DBusDictEntry *entry;
750 entry = _dbus_hash_table_lookup_string (dict->table, key);
752 if (!entry || entry->type != DBUS_TYPE_DOUBLE)
755 *value = entry->v.double_value;
761 * Gets a string from a dict using a key.
763 * @param dict the dict
765 * @param value return location for the value
766 * @returns #TRUE if the key exists and the value is of the correct
770 dbus_dict_get_string (DBusDict *dict,
774 DBusDictEntry *entry;
776 entry = _dbus_hash_table_lookup_string (dict->table, key);
778 if (!entry || entry->type != DBUS_TYPE_STRING)
781 *value = entry->v.string_value;
787 * Gets a boolean array from a dict using a key.
789 * @param dict the dict
791 * @param value return location for the value
792 * @param len return location for the array length
793 * @returns #TRUE if the key exists and the value is of the correct
797 dbus_dict_get_boolean_array (DBusDict *dict,
799 unsigned const char **value,
802 DBusDictEntry *entry;
804 entry = _dbus_hash_table_lookup_string (dict->table, key);
806 if (!entry || entry->type != DBUS_TYPE_BOOLEAN_ARRAY)
809 *value = entry->v.boolean_array.value;
810 *len = entry->v.boolean_array.len;
816 * Gets a 32 bit signed integer array from a dict using a key.
818 * @param dict the dict
820 * @param value return location for the value
821 * @param len return location for the array length
822 * @returns #TRUE if the key exists and the value is of the correct
826 dbus_dict_get_int32_array (DBusDict *dict,
828 const dbus_int32_t **value,
831 DBusDictEntry *entry;
833 entry = _dbus_hash_table_lookup_string (dict->table, key);
835 if (!entry || entry->type != DBUS_TYPE_INT32_ARRAY)
838 *value = entry->v.int32_array.value;
839 *len = entry->v.int32_array.len;
845 * Gets a 32 bit unsigned integer array from a dict using a key.
847 * @param dict the dict
849 * @param value return location for the value
850 * @param len return location for the array length
851 * @returns #TRUE if the key exists and the value is of the correct
855 dbus_dict_get_uint32_array (DBusDict *dict,
857 const dbus_uint32_t **value,
860 DBusDictEntry *entry;
862 entry = _dbus_hash_table_lookup_string (dict->table, key);
864 if (!entry || entry->type != DBUS_TYPE_UINT32_ARRAY)
867 *value = entry->v.uint32_array.value;
868 *len = entry->v.uint32_array.len;
874 * Gets a double array from a dict using a key.
876 * @param dict the dict
878 * @param value return location for the value
879 * @param len return location for the array length
880 * @returns #TRUE if the key exists and the value is of the correct
884 dbus_dict_get_double_array (DBusDict *dict,
886 const double **value,
889 DBusDictEntry *entry;
891 entry = _dbus_hash_table_lookup_string (dict->table, key);
893 if (!entry || entry->type != DBUS_TYPE_DOUBLE_ARRAY)
896 *value = entry->v.double_array.value;
897 *len = entry->v.double_array.len;
903 * Gets a string array from a dict using a key.
905 * @param dict the dict
907 * @param value return location for the value
908 * @param len return location for the array length
909 * @returns #TRUE if the key exists and the value is of the correct
913 dbus_dict_get_string_array (DBusDict *dict,
918 DBusDictEntry *entry;
920 entry = _dbus_hash_table_lookup_string (dict->table, key);
922 if (!entry || entry->type != DBUS_TYPE_STRING_ARRAY)
925 *value = (const char **)entry->v.string_array.value;
926 *len = entry->v.string_array.len;
933 #ifdef DBUS_BUILD_TESTS
934 #include "dbus-test.h"
937 _dbus_dict_test (void)
940 dbus_bool_t our_bool;
941 dbus_int32_t our_int;
942 dbus_uint32_t our_uint;
944 const char *our_string;
945 const unsigned char boolean_array[] = { TRUE, FALSE, FALSE, TRUE };
946 const unsigned char *our_boolean_array;
947 const dbus_int32_t int32_array[] = { 0x12345678, -1911, 0, 0xaffe, 0xedd1e };
948 const dbus_int32_t *our_int32_array;
949 const dbus_uint32_t uint32_array[] = { 0x12345678, 0, 0xdeadbeef, 0x87654321, 0xffffffff };
950 const dbus_uint32_t *our_uint32_array;
951 const double double_array[] = { 3.14159, 1.2345, 6.7890 };
952 const double *our_double_array;
953 const char *string_array[] = { "This", "Is", "A", "Test" };
954 const char **our_string_array;
957 /* We don't test much here since the hash table tests cover a great
958 deal of the functionality. */
960 dict = dbus_dict_new ();
962 if (dbus_dict_get_value_type (dict, "foo") != DBUS_TYPE_NIL)
963 _dbus_assert_not_reached ("didn't return DBUS_TYPE_NIL for non-existant entry");
965 if (!dbus_dict_set_boolean (dict, "boolean", TRUE))
966 _dbus_assert_not_reached ("could not add boolean value");
968 if (!dbus_dict_get_boolean (dict, "boolean", &our_bool) ||
970 _dbus_assert_not_reached ("could not get boolean value");
972 if (!dbus_dict_set_int32 (dict, "int32", 0x12345678))
973 _dbus_assert_not_reached ("could not add int32 value");
975 if (!dbus_dict_get_int32 (dict, "int32", &our_int) || our_int != 0x12345678)
976 _dbus_assert_not_reached ("could not get int32 value or int32 values differ");
978 if (!dbus_dict_set_uint32 (dict, "uint32", 0x87654321))
979 _dbus_assert_not_reached ("could not add uint32 value");
981 if (!dbus_dict_get_uint32 (dict, "uint32", &our_uint) || our_uint != 0x87654321)
982 _dbus_assert_not_reached ("could not get uint32 value or uint32 values differ");
984 if (!dbus_dict_set_double (dict, "double", 3.14159))
985 _dbus_assert_not_reached ("could not add double value");
987 if (!dbus_dict_get_double (dict, "double", &our_double) || our_double != 3.14159)
988 _dbus_assert_not_reached ("could not get double value or double values differ");
990 if (!dbus_dict_set_string (dict, "string", "test string"))
991 _dbus_assert_not_reached ("could not add string value");
993 if (!dbus_dict_get_string (dict, "string", &our_string) || strcmp (our_string, "test string") != 0)
994 _dbus_assert_not_reached ("could not get string value or string values differ");
996 if (!dbus_dict_set_boolean_array (dict, "boolean_array", boolean_array, 4))
997 _dbus_assert_not_reached ("could not add boolean array");
999 if (!dbus_dict_get_boolean_array (dict, "boolean_array", &our_boolean_array, &len) ||
1000 len != 4 || memcmp (boolean_array, our_boolean_array, 4) != 0)
1001 _dbus_assert_not_reached ("could not get boolean array value or boolean array values differ");
1003 if (!dbus_dict_set_int32_array (dict, "int32_array", int32_array, 5))
1004 _dbus_assert_not_reached ("could not add int32 array");
1006 if (!dbus_dict_get_int32_array (dict, "int32_array", &our_int32_array, &len) ||
1007 len != 5 || memcmp (int32_array, our_int32_array, 5 * sizeof (dbus_int32_t)) != 0)
1008 _dbus_assert_not_reached ("could not get int32 array value or int32 array values differ");
1010 if (!dbus_dict_set_uint32_array (dict, "uint32_array", uint32_array, 5))
1011 _dbus_assert_not_reached ("could not add uint32 array");
1013 if (!dbus_dict_get_uint32_array (dict, "uint32_array", &our_uint32_array, &len) ||
1014 len != 5 || memcmp (uint32_array, our_uint32_array, 5 * sizeof (dbus_uint32_t) ) != 0)
1015 _dbus_assert_not_reached ("could not get uint32 array value or uint32 array values differ");
1017 if (!dbus_dict_set_double_array (dict, "double_array", double_array, 3))
1018 _dbus_assert_not_reached ("could not add double array");
1020 if (!dbus_dict_get_double_array (dict, "double_array", &our_double_array, &len) ||
1021 len != 3 || memcmp (double_array, our_double_array, 3 * sizeof (double)) != 0)
1022 _dbus_assert_not_reached ("could not get double array value or double array values differ");
1024 if (!dbus_dict_set_string_array (dict, "string_array", string_array, 4))
1025 _dbus_assert_not_reached ("could not add string array");
1027 if (!dbus_dict_get_string_array (dict, "string_array", &our_string_array, &len))
1028 _dbus_assert_not_reached ("could not get string array value");
1031 _dbus_assert_not_reached ("string array lengths differ");
1033 for (i = 0; i < len; i++)
1035 if (strcmp (our_string_array[i], string_array[i]) != 0)
1036 _dbus_assert_not_reached ("string array fields differ");
1039 dbus_dict_unref (dict);
1043 #endif /* DBUS_BUILD_TESTS */