-/* -*- mode: C; c-file-style: "gnu" -*- */
-/* dbus-hash.c Generic hash table utility (internal to D-BUS implementation)
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-hash.c Generic hash table utility (internal to D-Bus implementation)
*
* Copyright (C) 2002 Red Hat, Inc.
* Copyright (c) 1991-1993 The Regents of the University of California.
*
* Hash table implementation based on generic/tclHash.c from the Tcl
* source code. The original Tcl license applies to portions of the
- * code from tclHash.c; the Tcl license follows this standad D-BUS
+ * code from tclHash.c; the Tcl license follows this standad D-Bus
* license information.
*
- * Licensed under the Academic Free License version 1.2
+ * Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* accordance with the terms specified in this license.
*/
+#include <config.h>
#include "dbus-hash.h"
#include "dbus-internals.h"
#include "dbus-mempool.h"
*
*/
#define RANDOM_INDEX(table, i) \
- (((((long) (i))*1103515245) >> (table)->down_shift) & (table)->mask)
+ (((((intptr_t) (i))*1103515245) >> (table)->down_shift) & (table)->mask)
/**
* Initial number of buckets in hash table (hash table statically
/**
* Function used to find and optionally create a hash entry.
*/
-typedef DBusHashEntry* (* DBusFindEntryFunction) (DBusHashTable *table,
- void *key,
- dbus_bool_t create_if_not_found,
- DBusHashEntry ***bucket);
+typedef DBusHashEntry* (* DBusFindEntryFunction) (DBusHashTable *table,
+ void *key,
+ dbus_bool_t create_if_not_found,
+ DBusHashEntry ***bucket,
+ DBusPreallocatedHash *preallocated);
/**
* @brief Internals of DBusHashTable.
int n_entries_on_init; /**< used to detect table resize since initialization */
} DBusRealHashIter;
-static DBusHashEntry* find_direct_function (DBusHashTable *table,
- void *key,
- dbus_bool_t create_if_not_found,
- DBusHashEntry ***bucket);
-static DBusHashEntry* find_string_function (DBusHashTable *table,
- void *key,
- dbus_bool_t create_if_not_found,
- DBusHashEntry ***bucket);
-static unsigned int string_hash (const char *str);
-static void rebuild_table (DBusHashTable *table);
-static DBusHashEntry* alloc_entry (DBusHashTable *table);
-static void remove_entry (DBusHashTable *table,
- DBusHashEntry **bucket,
- DBusHashEntry *entry);
-static void free_entry (DBusHashTable *table,
- DBusHashEntry *entry);
-static void free_entry_data (DBusHashTable *table,
- DBusHashEntry *entry);
+_DBUS_STATIC_ASSERT (sizeof (DBusRealHashIter) == sizeof (DBusHashIter));
+
+static DBusHashEntry* find_direct_function (DBusHashTable *table,
+ void *key,
+ dbus_bool_t create_if_not_found,
+ DBusHashEntry ***bucket,
+ DBusPreallocatedHash *preallocated);
+static DBusHashEntry* find_string_function (DBusHashTable *table,
+ void *key,
+ dbus_bool_t create_if_not_found,
+ DBusHashEntry ***bucket,
+ DBusPreallocatedHash *preallocated);
+static unsigned int string_hash (const char *str);
+static void rebuild_table (DBusHashTable *table);
+static DBusHashEntry* alloc_entry (DBusHashTable *table);
+static void remove_entry (DBusHashTable *table,
+ DBusHashEntry **bucket,
+ DBusHashEntry *entry);
+static void free_entry (DBusHashTable *table,
+ DBusHashEntry *entry);
+static void free_entry_data (DBusHashTable *table,
+ DBusHashEntry *entry);
+
/** @} */
switch (table->key_type)
{
case DBUS_HASH_INT:
- case DBUS_HASH_POINTER:
+ case DBUS_HASH_UINTPTR:
table->find_function = find_direct_function;
break;
case DBUS_HASH_STRING:
* Increments the reference count for a hash table.
*
* @param table the hash table to add a reference to.
+ * @returns the hash table.
*/
-void
+DBusHashTable *
_dbus_hash_table_ref (DBusHashTable *table)
{
table->refcount += 1;
+
+ return table;
}
/**
}
}
+/**
+ * Removed all entries from a hash table.
+ *
+ * @param table the hash table to remove all entries from.
+ */
+void
+_dbus_hash_table_remove_all (DBusHashTable *table)
+{
+ DBusHashIter iter;
+ _dbus_hash_iter_init (table, &iter);
+ while (_dbus_hash_iter_next (&iter))
+ {
+ _dbus_hash_iter_remove_entry(&iter);
+ }
+}
+
static DBusHashEntry*
alloc_entry (DBusHashTable *table)
{
/**
* Gets the key for the current entry.
+ * Only works for hash tables of type #DBUS_HASH_UINTPTR.
+ *
+ * @param iter the hash table iterator.
+ */
+uintptr_t
+_dbus_hash_iter_get_uintptr_key (DBusHashIter *iter)
+{
+ DBusRealHashIter *real;
+
+ real = (DBusRealHashIter*) iter;
+
+ _dbus_assert (real->table != NULL);
+ _dbus_assert (real->entry != NULL);
+
+ return (uintptr_t) real->entry->key;
+}
+
+/**
+ * Gets the key for the current entry.
* Only works for hash tables of type #DBUS_HASH_STRING
* @param iter the hash table iterator.
*/
real = (DBusRealHashIter*) iter;
- entry = (* table->find_function) (table, key, create_if_not_found, &bucket);
+ entry = (* table->find_function) (table, key, create_if_not_found, &bucket, NULL);
if (entry == NULL)
return FALSE;
return TRUE;
}
-static DBusHashEntry*
-add_entry (DBusHashTable *table,
- unsigned int idx,
- void *key,
- DBusHashEntry ***bucket)
+static void
+add_allocated_entry (DBusHashTable *table,
+ DBusHashEntry *entry,
+ unsigned int idx,
+ void *key,
+ DBusHashEntry ***bucket)
{
- DBusHashEntry *entry;
- DBusHashEntry **b;
-
- entry = alloc_entry (table);
- if (entry == NULL)
- {
- if (bucket)
- *bucket = NULL;
- return NULL;
- }
+ DBusHashEntry **b;
entry->key = key;
if (table->n_entries >= table->hi_rebuild_size ||
table->n_entries < table->lo_rebuild_size)
rebuild_table (table);
+}
+
+static DBusHashEntry*
+add_entry (DBusHashTable *table,
+ unsigned int idx,
+ void *key,
+ DBusHashEntry ***bucket,
+ DBusPreallocatedHash *preallocated)
+{
+ DBusHashEntry *entry;
+
+ if (preallocated == NULL)
+ {
+ entry = alloc_entry (table);
+ if (entry == NULL)
+ {
+ if (bucket)
+ *bucket = NULL;
+ return NULL;
+ }
+ }
+ else
+ {
+ entry = (DBusHashEntry*) preallocated;
+ }
+
+ add_allocated_entry (table, entry, idx, key, bucket);
return entry;
}
-
+
+/* This is g_str_hash from GLib which was
+ * extensively discussed/tested/profiled
+ */
static unsigned int
string_hash (const char *str)
{
- register unsigned int result;
- register int c;
+ const char *p = str;
+ unsigned int h = *p;
- /*
- * I tried a zillion different hash functions and asked many other
- * people for advice. Many people had their own favorite functions,
- * all different, but no-one had much idea why they were good ones.
- * I chose the one below (multiply by 9 and add new character)
- * because of the following reasons:
- *
- * 1. Multiplying by 10 is perfect for keys that are decimal strings,
- * and multiplying by 9 is just about as good.
- * 2. Times-9 is (shift-left-3) plus (old). This means that each
- * character's bits hang around in the low-order bits of the
- * hash value for ever, plus they spread fairly rapidly up to
- * the high-order bits to fill out the hash value. This seems
- * works well both for decimal and non-decimal strings.
- */
+ if (h)
+ for (p += 1; *p != '\0'; p++)
+ h = (h << 5) - h + *p;
- result = 0;
- while (TRUE)
- {
- c = *str;
- str++;
- if (c == 0)
- break;
-
- result += (result << 3) + c;
- }
-
- return result;
+ return h;
}
+/** Key comparison function */
+typedef int (* KeyCompareFunc) (const void *key_a, const void *key_b);
+
static DBusHashEntry*
-find_string_function (DBusHashTable *table,
- void *key,
- dbus_bool_t create_if_not_found,
- DBusHashEntry ***bucket)
+find_generic_function (DBusHashTable *table,
+ void *key,
+ unsigned int idx,
+ KeyCompareFunc compare_func,
+ dbus_bool_t create_if_not_found,
+ DBusHashEntry ***bucket,
+ DBusPreallocatedHash *preallocated)
{
DBusHashEntry *entry;
- unsigned int idx;
if (bucket)
*bucket = NULL;
-
- idx = string_hash (key) & table->mask;
/* Search all of the entries in this bucket. */
entry = table->buckets[idx];
while (entry != NULL)
{
- if (strcmp (key, entry->key) == 0)
+ if ((compare_func == NULL && key == entry->key) ||
+ (compare_func != NULL && (* compare_func) (key, entry->key) == 0))
{
if (bucket)
*bucket = &(table->buckets[idx]);
+
+ if (preallocated)
+ _dbus_hash_table_free_preallocated_entry (table, preallocated);
+
return entry;
}
}
if (create_if_not_found)
- entry = add_entry (table, idx, key, bucket);
-
+ entry = add_entry (table, idx, key, bucket, preallocated);
+ else if (preallocated)
+ _dbus_hash_table_free_preallocated_entry (table, preallocated);
+
return entry;
}
static DBusHashEntry*
-find_direct_function (DBusHashTable *table,
- void *key,
- dbus_bool_t create_if_not_found,
- DBusHashEntry ***bucket)
+find_string_function (DBusHashTable *table,
+ void *key,
+ dbus_bool_t create_if_not_found,
+ DBusHashEntry ***bucket,
+ DBusPreallocatedHash *preallocated)
{
- DBusHashEntry *entry;
unsigned int idx;
+
+ idx = string_hash (key) & table->mask;
- if (bucket)
- *bucket = NULL;
+ return find_generic_function (table, key, idx,
+ (KeyCompareFunc) strcmp, create_if_not_found, bucket,
+ preallocated);
+}
+
+static DBusHashEntry*
+find_direct_function (DBusHashTable *table,
+ void *key,
+ dbus_bool_t create_if_not_found,
+ DBusHashEntry ***bucket,
+ DBusPreallocatedHash *preallocated)
+{
+ unsigned int idx;
idx = RANDOM_INDEX (table, key) & table->mask;
- /* Search all of the entries in this bucket. */
- entry = table->buckets[idx];
- while (entry != NULL)
- {
- if (key == entry->key)
- {
- if (bucket)
- *bucket = &(table->buckets[idx]);
- return entry;
- }
-
- entry = entry->next;
- }
-
- /* Entry not found. Add a new one to the bucket. */
- if (create_if_not_found)
- entry = add_entry (table, idx, key, bucket);
- return entry;
+ return find_generic_function (table, key, idx,
+ NULL, create_if_not_found, bucket,
+ preallocated);
}
static void
idx = string_hash (entry->key) & table->mask;
break;
case DBUS_HASH_INT:
- case DBUS_HASH_POINTER:
+ case DBUS_HASH_UINTPTR:
idx = RANDOM_INDEX (table, entry->key);
break;
default:
_dbus_assert (table->key_type == DBUS_HASH_STRING);
- entry = (* table->find_function) (table, (char*) key, FALSE, NULL);
+ entry = (* table->find_function) (table, (char*) key, FALSE, NULL, NULL);
if (entry)
return entry->value;
_dbus_assert (table->key_type == DBUS_HASH_INT);
- entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, NULL);
+ entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, NULL, NULL);
if (entry)
return entry->value;
/**
* Looks up the value for a given integer in a hash table
- * of type #DBUS_HASH_POINTER. Returns %NULL if the value
+ * of type #DBUS_HASH_UINTPTR. Returns %NULL if the value
* is not present. (A not-present entry is indistinguishable
* from an entry with a value of %NULL.)
* @param table the hash table.
* @returns the value of the hash entry.
*/
void*
-_dbus_hash_table_lookup_pointer (DBusHashTable *table,
- void *key)
+_dbus_hash_table_lookup_uintptr (DBusHashTable *table,
+ uintptr_t key)
{
DBusHashEntry *entry;
- _dbus_assert (table->key_type == DBUS_HASH_POINTER);
+ _dbus_assert (table->key_type == DBUS_HASH_UINTPTR);
- entry = (* table->find_function) (table, key, FALSE, NULL);
+ entry = (* table->find_function) (table, (void*) key, FALSE, NULL, NULL);
if (entry)
return entry->value;
_dbus_assert (table->key_type == DBUS_HASH_STRING);
- entry = (* table->find_function) (table, (char*) key, FALSE, &bucket);
+ entry = (* table->find_function) (table, (char*) key, FALSE, &bucket, NULL);
if (entry)
{
_dbus_assert (table->key_type == DBUS_HASH_INT);
- entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, &bucket);
+ entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, &bucket, NULL);
if (entry)
{
* @returns #TRUE if the entry existed
*/
dbus_bool_t
-_dbus_hash_table_remove_pointer (DBusHashTable *table,
- void *key)
+_dbus_hash_table_remove_uintptr (DBusHashTable *table,
+ uintptr_t key)
{
DBusHashEntry *entry;
DBusHashEntry **bucket;
- _dbus_assert (table->key_type == DBUS_HASH_POINTER);
+ _dbus_assert (table->key_type == DBUS_HASH_UINTPTR);
- entry = (* table->find_function) (table, key, FALSE, &bucket);
+ entry = (* table->find_function) (table, (void*) key, FALSE, &bucket, NULL);
if (entry)
{
return FALSE;
}
-
/**
* Creates a hash entry with the given key and value.
* The key and value are not copied; they are stored
char *key,
void *value)
{
- DBusHashEntry *entry;
+ DBusPreallocatedHash *preallocated;
_dbus_assert (table->key_type == DBUS_HASH_STRING);
-
- entry = (* table->find_function) (table, key, TRUE, NULL);
-
- if (entry == NULL)
- return FALSE; /* no memory */
-
- if (table->free_key_function && entry->key != key)
- (* table->free_key_function) (entry->key);
- if (table->free_value_function && entry->value != value)
- (* table->free_value_function) (entry->value);
-
- entry->key = key;
- entry->value = value;
+ preallocated = _dbus_hash_table_preallocate_entry (table);
+ if (preallocated == NULL)
+ return FALSE;
+ _dbus_hash_table_insert_string_preallocated (table, preallocated,
+ key, value);
+
return TRUE;
}
_dbus_assert (table->key_type == DBUS_HASH_INT);
- entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), TRUE, NULL);
+ entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), TRUE, NULL, NULL);
if (entry == NULL)
return FALSE; /* no memory */
* @param value the hash entry value.
*/
dbus_bool_t
-_dbus_hash_table_insert_pointer (DBusHashTable *table,
- void *key,
+_dbus_hash_table_insert_uintptr (DBusHashTable *table,
+ uintptr_t key,
void *value)
{
DBusHashEntry *entry;
- _dbus_assert (table->key_type == DBUS_HASH_POINTER);
+ _dbus_assert (table->key_type == DBUS_HASH_UINTPTR);
- entry = (* table->find_function) (table, key, TRUE, NULL);
+ entry = (* table->find_function) (table, (void*) key, TRUE, NULL, NULL);
if (entry == NULL)
return FALSE; /* no memory */
- if (table->free_key_function && entry->key != key)
+ if (table->free_key_function && entry->key != (void*) key)
(* table->free_key_function) (entry->key);
if (table->free_value_function && entry->value != value)
(* table->free_value_function) (entry->value);
- entry->key = key;
+ entry->key = (void*) key;
entry->value = value;
return TRUE;
}
/**
+ * Preallocate an opaque data blob that allows us to insert into the
+ * hash table at a later time without allocating any memory.
+ *
+ * @param table the hash table
+ * @returns the preallocated data, or #NULL if no memory
+ */
+DBusPreallocatedHash*
+_dbus_hash_table_preallocate_entry (DBusHashTable *table)
+{
+ DBusHashEntry *entry;
+
+ entry = alloc_entry (table);
+
+ return (DBusPreallocatedHash*) entry;
+}
+
+/**
+ * Frees an opaque DBusPreallocatedHash that was *not* used
+ * in order to insert into the hash table.
+ *
+ * @param table the hash table
+ * @param preallocated the preallocated data
+ */
+void
+_dbus_hash_table_free_preallocated_entry (DBusHashTable *table,
+ DBusPreallocatedHash *preallocated)
+{
+ DBusHashEntry *entry;
+
+ _dbus_assert (preallocated != NULL);
+
+ entry = (DBusHashEntry*) preallocated;
+
+ /* Don't use free_entry(), since this entry has no key/data */
+ _dbus_mem_pool_dealloc (table->entry_pool, entry);
+}
+
+/**
+ * Inserts a string-keyed entry into the hash table, using a
+ * preallocated data block from
+ * _dbus_hash_table_preallocate_entry(). This function cannot fail due
+ * to lack of memory. The DBusPreallocatedHash object is consumed and
+ * should not be reused or freed. Otherwise this function works
+ * just like _dbus_hash_table_insert_string().
+ *
+ * @param table the hash table
+ * @param preallocated the preallocated data
+ * @param key the hash key
+ * @param value the value
+ */
+void
+_dbus_hash_table_insert_string_preallocated (DBusHashTable *table,
+ DBusPreallocatedHash *preallocated,
+ char *key,
+ void *value)
+{
+ DBusHashEntry *entry;
+
+ _dbus_assert (table->key_type == DBUS_HASH_STRING);
+ _dbus_assert (preallocated != NULL);
+
+ entry = (* table->find_function) (table, key, TRUE, NULL, preallocated);
+
+ _dbus_assert (entry != NULL);
+
+ if (table->free_key_function && entry->key != key)
+ (* table->free_key_function) (entry->key);
+
+ if (table->free_value_function && entry->value != value)
+ (* table->free_value_function) (entry->value);
+
+ entry->key = key;
+ entry->value = value;
+}
+
+/**
* Gets the number of hash entries in a hash table.
*
* @param table the hash table.
/** @} */
-#ifdef DBUS_BUILD_TESTS
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
#include "dbus-test.h"
#include <stdio.h>
int i;
DBusHashTable *table1;
DBusHashTable *table2;
+ DBusHashTable *table3;
DBusHashIter iter;
#define N_HASH_KEYS 5000
- char keys[N_HASH_KEYS][128];
+ char **keys;
+ dbus_bool_t ret = FALSE;
+
+ keys = dbus_new (char *, N_HASH_KEYS);
+ if (keys == NULL)
+ _dbus_assert_not_reached ("no memory");
+
+ for (i = 0; i < N_HASH_KEYS; i++)
+ {
+ keys[i] = dbus_malloc (128);
+
+ if (keys[i] == NULL)
+ _dbus_assert_not_reached ("no memory");
+ }
printf ("Computing test hash keys...\n");
i = 0;
while (i < N_HASH_KEYS)
{
- sprintf (keys[i], "Hash key %d", i);
+ int len;
+
+ len = sprintf (keys[i], "Hash key %d", i);
+ _dbus_assert (*(keys[i] + len) == '\0');
++i;
}
printf ("... done.\n");
table1 = _dbus_hash_table_new (DBUS_HASH_STRING,
dbus_free, dbus_free);
if (table1 == NULL)
- return FALSE;
+ goto out;
table2 = _dbus_hash_table_new (DBUS_HASH_INT,
NULL, dbus_free);
if (table2 == NULL)
- return FALSE;
+ goto out;
+
+ table3 = _dbus_hash_table_new (DBUS_HASH_UINTPTR,
+ NULL, dbus_free);
+ if (table3 == NULL)
+ goto out;
/* Insert and remove a bunch of stuff, counting the table in between
* to be sure it's not broken and that iteration works
key = _dbus_strdup (keys[i]);
if (key == NULL)
- return FALSE;
+ goto out;
value = _dbus_strdup ("Value!");
if (value == NULL)
- return FALSE;
+ goto out;
if (!_dbus_hash_table_insert_string (table1,
key, value))
- return FALSE;
+ goto out;
value = _dbus_strdup (keys[i]);
if (value == NULL)
- return FALSE;
+ goto out;
if (!_dbus_hash_table_insert_int (table2,
i, value))
- return FALSE;
+ goto out;
+
+ value = _dbus_strdup (keys[i]);
+ if (value == NULL)
+ goto out;
+ if (!_dbus_hash_table_insert_uintptr (table3,
+ i, 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);
value = _dbus_hash_table_lookup_int (table2, i);
_dbus_assert (value != NULL);
_dbus_assert (strcmp (value, keys[i]) == 0);
-
+
+ value = _dbus_hash_table_lookup_uintptr (table3, i);
+ _dbus_assert (value != NULL);
+ _dbus_assert (strcmp (value, keys[i]) == 0);
+
++i;
}
_dbus_hash_table_remove_int (table2, i);
+ _dbus_hash_table_remove_uintptr (table3, i);
+
_dbus_assert (count_entries (table1) == i);
_dbus_assert (count_entries (table2) == i);
+ _dbus_assert (count_entries (table3) == i);
--i;
}
_dbus_hash_table_ref (table1);
_dbus_hash_table_ref (table2);
+ _dbus_hash_table_ref (table3);
_dbus_hash_table_unref (table1);
_dbus_hash_table_unref (table2);
+ _dbus_hash_table_unref (table3);
_dbus_hash_table_unref (table1);
_dbus_hash_table_unref (table2);
-
+ _dbus_hash_table_unref (table3);
+ table3 = NULL;
/* Insert a bunch of stuff then check
* that iteration works correctly (finds the right
table1 = _dbus_hash_table_new (DBUS_HASH_STRING,
dbus_free, dbus_free);
if (table1 == NULL)
- return FALSE;
+ goto out;
table2 = _dbus_hash_table_new (DBUS_HASH_INT,
NULL, dbus_free);
if (table2 == NULL)
- return FALSE;
+ goto out;
i = 0;
while (i < 5000)
key = _dbus_strdup (keys[i]);
if (key == NULL)
- return FALSE;
+ goto out;
value = _dbus_strdup ("Value!");
if (value == NULL)
- return FALSE;
+ goto out;
if (!_dbus_hash_table_insert_string (table1,
key, value))
- return FALSE;
+ goto out;
value = _dbus_strdup (keys[i]);
if (value == NULL)
- return FALSE;
+ goto out;
if (!_dbus_hash_table_insert_int (table2,
i, value))
- return FALSE;
+ goto out;
_dbus_assert (count_entries (table1) == i + 1);
_dbus_assert (count_entries (table2) == i + 1);
value = _dbus_strdup ("Different value!");
if (value == NULL)
- return FALSE;
+ goto out;
_dbus_hash_iter_set_value (&iter, value);
value = _dbus_strdup ("Different value!");
if (value == NULL)
- return FALSE;
+ goto out;
_dbus_hash_iter_set_value (&iter, value);
key = _dbus_strdup (keys[i]);
if (key == NULL)
- return FALSE;
+ goto out;
value = _dbus_strdup ("Value!");
if (value == NULL)
- return FALSE;
+ goto out;
if (!_dbus_hash_table_insert_string (table1,
key, value))
- return FALSE;
+ goto out;
++i;
}
key = _dbus_strdup (keys[i]);
if (key == NULL)
- return FALSE;
+ goto out;
value = _dbus_strdup ("Value!");
if (value == NULL)
- return FALSE;
+ goto out;
if (!_dbus_hash_table_remove_string (table1, keys[i]))
- return FALSE;
+ goto out;
if (!_dbus_hash_table_insert_string (table1,
key, value))
- return FALSE;
+ goto out;
if (!_dbus_hash_table_remove_string (table1, keys[i]))
- return FALSE;
+ goto out;
_dbus_assert (_dbus_hash_table_get_n_entries (table1) == i);
table1 = _dbus_hash_table_new (DBUS_HASH_STRING,
dbus_free, dbus_free);
if (table1 == NULL)
- return FALSE;
+ goto out;
table2 = _dbus_hash_table_new (DBUS_HASH_INT,
NULL, dbus_free);
if (table2 == NULL)
- return FALSE;
+ goto out;
i = 0;
while (i < 3000)
key = _dbus_strdup (keys[i]);
if (key == NULL)
- return FALSE;
+ goto out;
value = _dbus_strdup ("Value!");
if (value == NULL)
- return FALSE;
+ goto out;
if (!_dbus_hash_iter_lookup (table1,
key, TRUE, &iter))
- return FALSE;
+ goto out;
_dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL);
_dbus_hash_iter_set_value (&iter, value);
value = _dbus_strdup (keys[i]);
if (value == NULL)
- return FALSE;
+ goto out;
if (!_dbus_hash_iter_lookup (table2,
_DBUS_INT_TO_POINTER (i), TRUE, &iter))
- return FALSE;
+ goto out;
_dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL);
_dbus_hash_iter_set_value (&iter, value);
_dbus_assert (count_entries (table2) == i + 1);
if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter))
- return FALSE;
+ goto out;
value = _dbus_hash_iter_get_value (&iter);
_dbus_assert (value != NULL);
;
if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter))
- return FALSE;
+ goto out;
value = _dbus_hash_iter_get_value (&iter);
_dbus_assert (value != NULL);
_dbus_hash_table_unref (table1);
_dbus_hash_table_unref (table2);
+ ret = TRUE;
+
+ out:
+ for (i = 0; i < N_HASH_KEYS; i++)
+ dbus_free (keys[i]);
+
+ dbus_free (keys);
- return TRUE;
+ return ret;
}
-#endif /* DBUS_BUILD_TESTS */
+#endif /* DBUS_ENABLE_EMBEDDED_TESTS */