diff options
Diffstat (limited to 'dbus/dbus-hash.c')
-rw-r--r-- | dbus/dbus-hash.c | 345 |
1 files changed, 247 insertions, 98 deletions
diff --git a/dbus/dbus-hash.c b/dbus/dbus-hash.c index 1a667056..ba5e7ca4 100644 --- a/dbus/dbus-hash.c +++ b/dbus/dbus-hash.c @@ -724,8 +724,9 @@ _dbus_hash_iter_get_string_key (DBusHashIter *iter) * because create_if_not_found was #FALSE and the entry * did not exist. * - * If create_if_not_found is #TRUE and the entry is created, the hash - * table takes ownership of the key that's passed in. + * If create_if_not_found is #TRUE, the hash + * table takes ownership of the key that's passed in (either using it to create + * the entry, or freeing it immediately). * * For a hash table of type #DBUS_HASH_INT, cast the int * key to the key parameter using #_DBUS_INT_TO_POINTER(). @@ -754,7 +755,15 @@ _dbus_hash_iter_lookup (DBusHashTable *table, if (entry == NULL) return FALSE; - + + if (create_if_not_found) + { + if (table->free_key_function && entry->key != key) + (* table->free_key_function) (entry->key); + + entry->key = key; + } + real->table = table; real->bucket = bucket; real->entry = entry; @@ -1400,6 +1409,135 @@ _dbus_hash_table_get_n_entries (DBusHashTable *table) return table->n_entries; } +/** + * Imports a string array into a hash table + * The hash table needs to be initialized with string keys, + * and dbus_free() as both key and value free-function. + * + * @param table the hash table + * @param array the string array to import + * @param delimiter the delimiter to separate key and value + * @return #TRUE on success. + * @return #FALSE if not enough memory. + */ + +dbus_bool_t +_dbus_hash_table_from_array (DBusHashTable *table, char **array, char delimiter) +{ + DBusString key; + DBusString value; + int i; + dbus_bool_t retval = FALSE; + + _dbus_assert (table != NULL); + _dbus_assert (array != NULL); + + if (!_dbus_string_init (&key)) + { + return FALSE; + } + + if (!_dbus_string_init (&value)) + { + _dbus_string_free (&key); + return FALSE; + } + + for (i = 0; array[i] != NULL; i++) + { + if (!_dbus_string_append (&key, array[i])) + break; + + if (_dbus_string_split_on_byte (&key, delimiter, &value)) + { + char *hash_key, *hash_value; + + if (!_dbus_string_steal_data (&key, &hash_key)) + break; + + if (!_dbus_string_steal_data (&value, &hash_value)) + break; + + if (!_dbus_hash_table_insert_string (table, + hash_key, hash_value)) + break; + } + _dbus_string_set_length (&key, 0); + _dbus_string_set_length (&value, 0); + } + + if (array[i] != NULL) + goto out; + + retval = TRUE; +out: + + _dbus_string_free (&key); + _dbus_string_free (&value); + + return retval; +} + +/** + * Creates a string array from a hash table + * + * @param table the hash table + * @param delimiter the delimiter to join key and value + * @return pointer to created string array (free with dbus_free_string_array) + * @return #FALSE if not enough memory. + */ +char ** +_dbus_hash_table_to_array (DBusHashTable *table, char delimiter) +{ + int i, length; + DBusString entry; + DBusHashIter iter; + char **array; + + _dbus_assert (table != NULL); + + length = _dbus_hash_table_get_n_entries (table); + + array = dbus_new0 (char *, length + 1); + + if (array == NULL) + return NULL; + + i = 0; + _dbus_hash_iter_init (table, &iter); + + if (!_dbus_string_init (&entry)) + { + dbus_free_string_array (array); + return NULL; + } + + while (_dbus_hash_iter_next (&iter)) + { + const char *key, *value; + + key = (const char *) _dbus_hash_iter_get_string_key (&iter); + value = (const char *) _dbus_hash_iter_get_value (&iter); + + if (!_dbus_string_append_printf (&entry, "%s%c%s", key, delimiter, value)) + break; + + if (!_dbus_string_steal_data (&entry, array + i)) + break; + i++; + } + + _dbus_string_free (&entry); + + if (i != length) + { + dbus_free_string_array (array); + array = NULL; + } + + return array; +} + /** @} */ #ifdef DBUS_ENABLE_EMBEDDED_TESTS @@ -1426,6 +1564,19 @@ count_entries (DBusHashTable *table) return count; } +static inline void * +steal (void *ptr) +{ + /* @ptr is passed in as void* to avoid casting in the call */ + void **_ptr = (void **) ptr; + void *val; + + val = *_ptr; + *_ptr = NULL; + + return val; +} + /** * @ingroup DBusHashTableInternals * Unit test for DBusHashTable @@ -1442,6 +1593,8 @@ _dbus_hash_test (void) #define N_HASH_KEYS 5000 char **keys; dbus_bool_t ret = FALSE; + char *str_key = NULL; + char *str_value = NULL; keys = dbus_new (char *, N_HASH_KEYS); if (keys == NULL) @@ -1488,51 +1641,51 @@ _dbus_hash_test (void) i = 0; while (i < 3000) { - void *value; - char *key; + const void *out_value; - key = _dbus_strdup (keys[i]); - if (key == NULL) + str_key = _dbus_strdup (keys[i]); + if (str_key == NULL) goto out; - value = _dbus_strdup ("Value!"); - if (value == NULL) + str_value = _dbus_strdup ("Value!"); + if (str_value == NULL) goto out; - + if (!_dbus_hash_table_insert_string (table1, - key, value)) + steal (&str_key), + steal (&str_value))) goto out; - value = _dbus_strdup (keys[i]); - if (value == NULL) + str_value = _dbus_strdup (keys[i]); + if (str_value == NULL) goto out; - + if (!_dbus_hash_table_insert_int (table2, - i, value)) + i, steal (&str_value))) goto out; - value = _dbus_strdup (keys[i]); - if (value == NULL) + str_value = _dbus_strdup (keys[i]); + if (str_value == NULL) goto out; - + if (!_dbus_hash_table_insert_uintptr (table3, - i, value)) + i, steal (&str_value))) goto out; _dbus_assert (count_entries (table1) == i + 1); _dbus_assert (count_entries (table2) == i + 1); _dbus_assert (count_entries (table3) == i + 1); - value = _dbus_hash_table_lookup_string (table1, keys[i]); - _dbus_assert (value != NULL); - _dbus_assert (strcmp (value, "Value!") == 0); + out_value = _dbus_hash_table_lookup_string (table1, keys[i]); + _dbus_assert (out_value != NULL); + _dbus_assert (strcmp (out_value, "Value!") == 0); - value = _dbus_hash_table_lookup_int (table2, i); - _dbus_assert (value != NULL); - _dbus_assert (strcmp (value, keys[i]) == 0); + out_value = _dbus_hash_table_lookup_int (table2, i); + _dbus_assert (out_value != NULL); + _dbus_assert (strcmp (out_value, keys[i]) == 0); - value = _dbus_hash_table_lookup_uintptr (table3, i); - _dbus_assert (value != NULL); - _dbus_assert (strcmp (value, keys[i]) == 0); + out_value = _dbus_hash_table_lookup_uintptr (table3, i); + _dbus_assert (out_value != NULL); + _dbus_assert (strcmp (out_value, keys[i]) == 0); ++i; } @@ -1573,40 +1726,38 @@ _dbus_hash_test (void) dbus_free, dbus_free); if (table1 == NULL) goto out; - + table2 = _dbus_hash_table_new (DBUS_HASH_INT, NULL, dbus_free); if (table2 == NULL) goto out; - + i = 0; while (i < 5000) { - char *key; - void *value; - - key = _dbus_strdup (keys[i]); - if (key == NULL) + str_key = _dbus_strdup (keys[i]); + if (str_key == NULL) goto out; - value = _dbus_strdup ("Value!"); - if (value == NULL) + str_value = _dbus_strdup ("Value!"); + if (str_value == NULL) goto out; - + if (!_dbus_hash_table_insert_string (table1, - key, value)) + steal (&str_key), + steal (&str_value))) goto out; - value = _dbus_strdup (keys[i]); - if (value == NULL) + str_value = _dbus_strdup (keys[i]); + if (str_value == NULL) goto out; - + if (!_dbus_hash_table_insert_int (table2, - i, value)) + i, steal (&str_value))) goto out; - + _dbus_assert (count_entries (table1) == i + 1); _dbus_assert (count_entries (table2) == i + 1); - + ++i; } @@ -1614,22 +1765,22 @@ _dbus_hash_test (void) while (_dbus_hash_iter_next (&iter)) { const char *key; - void *value; + const void *value; key = _dbus_hash_iter_get_string_key (&iter); value = _dbus_hash_iter_get_value (&iter); _dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value); - value = _dbus_strdup ("Different value!"); - if (value == NULL) + str_value = _dbus_strdup ("Different value!"); + if (str_value == NULL) goto out; - - _dbus_hash_iter_set_value (&iter, value); + value = str_value; + _dbus_hash_iter_set_value (&iter, steal (&str_value)); _dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value); } - + _dbus_hash_iter_init (table1, &iter); while (_dbus_hash_iter_next (&iter)) { @@ -1642,19 +1793,19 @@ _dbus_hash_test (void) while (_dbus_hash_iter_next (&iter)) { int key; - void *value; + const void *value; key = _dbus_hash_iter_get_int_key (&iter); value = _dbus_hash_iter_get_value (&iter); _dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value); - value = _dbus_strdup ("Different value!"); - if (value == NULL) + str_value = _dbus_strdup ("Different value!"); + if (str_value == NULL) goto out; - - _dbus_hash_iter_set_value (&iter, value); + value = str_value; + _dbus_hash_iter_set_value (&iter, steal (&str_value)); _dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value); } @@ -1673,42 +1824,38 @@ _dbus_hash_test (void) i = 0; while (i < 1000) { - char *key; - void *value; - - key = _dbus_strdup (keys[i]); - if (key == NULL) + str_key = _dbus_strdup (keys[i]); + if (str_key == NULL) goto out; - value = _dbus_strdup ("Value!"); - if (value == NULL) + str_value = _dbus_strdup ("Value!"); + if (str_value == NULL) goto out; - + if (!_dbus_hash_table_insert_string (table1, - key, value)) + steal (&str_key), + steal (&str_value))) goto out; - + ++i; } --i; while (i >= 0) { - char *key; - void *value; - - key = _dbus_strdup (keys[i]); - if (key == NULL) + str_key = _dbus_strdup (keys[i]); + if (str_key == NULL) goto out; - value = _dbus_strdup ("Value!"); - if (value == NULL) + str_value = _dbus_strdup ("Value!"); + if (str_value == NULL) goto out; if (!_dbus_hash_table_remove_string (table1, keys[i])) goto out; - + if (!_dbus_hash_table_insert_string (table1, - key, value)) + steal (&str_key), + steal (&str_value))) goto out; if (!_dbus_hash_table_remove_string (table1, keys[i])) @@ -1731,63 +1878,62 @@ _dbus_hash_test (void) dbus_free, dbus_free); if (table1 == NULL) goto out; - + table2 = _dbus_hash_table_new (DBUS_HASH_INT, NULL, dbus_free); if (table2 == NULL) goto out; - + i = 0; while (i < 3000) { - void *value; - char *key; + const void *out_value; - key = _dbus_strdup (keys[i]); - if (key == NULL) + str_key = _dbus_strdup (keys[i]); + if (str_key == NULL) goto out; - value = _dbus_strdup ("Value!"); - if (value == NULL) + str_value = _dbus_strdup ("Value!"); + if (str_value == NULL) goto out; - + if (!_dbus_hash_iter_lookup (table1, - key, TRUE, &iter)) + steal (&str_key), TRUE, &iter)) goto out; _dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL); - _dbus_hash_iter_set_value (&iter, value); + _dbus_hash_iter_set_value (&iter, steal (&str_value)); - value = _dbus_strdup (keys[i]); - if (value == NULL) + str_value = _dbus_strdup (keys[i]); + if (str_value == NULL) goto out; if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), TRUE, &iter)) goto out; _dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL); - _dbus_hash_iter_set_value (&iter, value); - + _dbus_hash_iter_set_value (&iter, steal (&str_value)); + _dbus_assert (count_entries (table1) == i + 1); _dbus_assert (count_entries (table2) == i + 1); if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter)) goto out; - - value = _dbus_hash_iter_get_value (&iter); - _dbus_assert (value != NULL); - _dbus_assert (strcmp (value, "Value!") == 0); + + out_value = _dbus_hash_iter_get_value (&iter); + _dbus_assert (out_value != NULL); + _dbus_assert (strcmp (out_value, "Value!") == 0); /* Iterate just to be sure it works, though * it's a stupid thing to do */ while (_dbus_hash_iter_next (&iter)) ; - + if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter)) goto out; - value = _dbus_hash_iter_get_value (&iter); - _dbus_assert (value != NULL); - _dbus_assert (strcmp (value, keys[i]) == 0); + out_value = _dbus_hash_iter_get_value (&iter); + _dbus_assert (out_value != NULL); + _dbus_assert (strcmp (out_value, keys[i]) == 0); /* Iterate just to be sure it works, though * it's a stupid thing to do @@ -1825,6 +1971,9 @@ _dbus_hash_test (void) dbus_free (keys[i]); dbus_free (keys); + + dbus_free (str_key); + dbus_free (str_value); return ret; } |