1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-hash.c Generic hash table utility (internal to D-BUS implementation)
4 * Copyright (C) 2002 Red Hat, Inc.
5 * Copyright (c) 1991-1993 The Regents of the University of California.
6 * Copyright (c) 1994 Sun Microsystems, Inc.
8 * Hash table implementation based on generic/tclHash.c from the Tcl
9 * source code. The original Tcl license applies to portions of the
10 * code from tclHash.c; the Tcl license follows this standad D-BUS
11 * license information.
13 * Licensed under the Academic Free License version 1.2
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 * The following copyright applies to code from the Tcl distribution.
33 * Copyright (c) 1991-1993 The Regents of the University of California.
34 * Copyright (c) 1994 Sun Microsystems, Inc.
36 * This software is copyrighted by the Regents of the University of
37 * California, Sun Microsystems, Inc., Scriptics Corporation, and
38 * other parties. The following terms apply to all files associated
39 * with the software unless explicitly disclaimed in individual files.
41 * The authors hereby grant permission to use, copy, modify,
42 * distribute, and license this software and its documentation for any
43 * purpose, provided that existing copyright notices are retained in
44 * all copies and that this notice is included verbatim in any
45 * distributions. No written agreement, license, or royalty fee is
46 * required for any of the authorized uses. Modifications to this
47 * software may be copyrighted by their authors and need not follow
48 * the licensing terms described here, provided that the new terms are
49 * clearly indicated on the first page of each file where they apply.
51 * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY
52 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
53 * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION,
54 * OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED
55 * OF THE POSSIBILITY OF SUCH DAMAGE.
57 * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
58 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
59 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
60 * NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
61 * AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
62 * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
64 * GOVERNMENT USE: If you are acquiring this software on behalf of the
65 * U.S. government, the Government shall have only "Restricted Rights"
66 * in the software and related documentation as defined in the Federal
67 * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
68 * are acquiring the software on behalf of the Department of Defense,
69 * the software shall be classified as "Commercial Computer Software"
70 * and the Government shall have only "Restricted Rights" as defined
71 * in Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the
72 * foregoing, the authors grant the U.S. Government and others acting
73 * in its behalf permission to use and distribute the software in
74 * accordance with the terms specified in this license.
77 #include "dbus-hash.h"
78 #include "dbus-internals.h"
79 #include "dbus-mempool.h"
82 * @defgroup DBusHashTable Hash table
83 * @ingroup DBusInternals
84 * @brief DBusHashTable data structure
86 * Types and functions related to DBusHashTable.
90 * @defgroup DBusHashTableInternals Hash table implementation details
91 * @ingroup DBusInternals
92 * @brief DBusHashTable implementation details
94 * The guts of DBusHashTable.
100 * When there are this many entries per bucket, on average, rebuild
101 * the hash table to make it larger.
103 #define REBUILD_MULTIPLIER 3
106 * Takes a preliminary integer hash value and produces an index into a
107 * hash tables bucket list. The idea is to make it so that
108 * preliminary values that are arbitrarily similar will end up in
109 * different buckets. The hash function was taken from a
110 * random-number generator. (This is used to hash integers.)
112 * The down_shift drops off the high bits of the hash index, and
113 * decreases as we increase the number of hash buckets (to keep more
114 * range in the hash index). The mask also strips high bits and strips
115 * fewer high bits as the number of hash buckets increases.
116 * I don't understand two things: why is the initial downshift 28
117 * to keep 4 bits when the initial mask is 011 to keep 2 bits,
118 * and why do we have both a mask and a downshift?
121 #define RANDOM_INDEX(table, i) \
122 (((((long) (i))*1103515245) >> (table)->down_shift) & (table)->mask)
125 * Initial number of buckets in hash table (hash table statically
126 * allocates its buckets for this size and below).
127 * The initial mask has to be synced to this.
129 #define DBUS_SMALL_HASH_TABLE 4
132 * Typedef for DBusHashEntry
134 typedef struct DBusHashEntry DBusHashEntry;
137 * @brief Internal representation of a hash entry.
139 * A single entry (key-value pair) in the hash table.
140 * Internal to hash table implementation.
144 DBusHashEntry *next; /**< Pointer to next entry in this
145 * hash bucket, or #NULL for end of
148 void *key; /**< Hash key */
149 void *value; /**< Hash value */
153 * Function used to find and optionally create a hash entry.
155 typedef DBusHashEntry* (* DBusFindEntryFunction) (DBusHashTable *table,
157 dbus_bool_t create_if_not_found,
158 DBusHashEntry ***bucket);
161 * @brief Internals of DBusHashTable.
163 * Hash table internals. Hash tables are opaque objects, they must be
164 * used via accessor functions.
166 struct DBusHashTable {
167 int refcount; /**< Reference count */
169 DBusHashEntry **buckets; /**< Pointer to bucket array. Each
170 * element points to first entry in
171 * bucket's hash chain, or #NULL.
173 DBusHashEntry *static_buckets[DBUS_SMALL_HASH_TABLE];
174 /**< Bucket array used for small tables
175 * (to avoid mallocs and frees).
177 int n_buckets; /**< Total number of buckets allocated
180 int n_entries; /**< Total number of entries present
183 int hi_rebuild_size; /**< Enlarge table when n_entries gets
186 int lo_rebuild_size; /**< Shrink table when n_entries gets
189 int down_shift; /**< Shift count used in hashing
190 * function. Designed to use high-
191 * order bits of randomized keys.
193 int mask; /**< Mask value used in hashing
196 DBusHashType key_type; /**< Type of keys used in this table */
199 DBusFindEntryFunction find_function; /**< Function for finding entries */
201 DBusFreeFunction free_key_function; /**< Function to free keys */
202 DBusFreeFunction free_value_function; /**< Function to free values */
204 DBusMemPool *entry_pool; /**< Memory pool for hash entries */
208 * @brief Internals of DBusHashIter.
212 DBusHashTable *table; /**< Pointer to table containing entry. */
213 DBusHashEntry **bucket; /**< Pointer to bucket that points to
214 * first entry in this entry's chain:
215 * used for deleting the entry.
217 DBusHashEntry *entry; /**< Current hash entry */
218 DBusHashEntry *next_entry; /**< Next entry to be iterated onto in current bucket */
219 int next_bucket; /**< index of next bucket */
220 int n_entries_on_init; /**< used to detect table resize since initialization */
223 static DBusHashEntry* find_direct_function (DBusHashTable *table,
225 dbus_bool_t create_if_not_found,
226 DBusHashEntry ***bucket);
227 static DBusHashEntry* find_string_function (DBusHashTable *table,
229 dbus_bool_t create_if_not_found,
230 DBusHashEntry ***bucket);
231 static unsigned int string_hash (const char *str);
232 static void rebuild_table (DBusHashTable *table);
233 static DBusHashEntry* alloc_entry (DBusHashTable *table);
234 static void remove_entry (DBusHashTable *table,
235 DBusHashEntry **bucket,
236 DBusHashEntry *entry);
237 static void free_entry (DBusHashTable *table,
238 DBusHashEntry *entry);
239 static void free_entry_data (DBusHashTable *table,
240 DBusHashEntry *entry);
245 * @addtogroup DBusHashTable
250 * @typedef DBusHashIter
252 * Public opaque hash table iterator object.
256 * @typedef DBusHashTable
258 * Public opaque hash table object.
262 * @typedef DBusHashType
264 * Indicates the type of a key in the hash table.
268 * Constructs a new hash table. Should be freed with
269 * _dbus_hash_table_unref(). If memory cannot be
270 * allocated for the hash table, returns #NULL.
272 * @param type the type of hash key to use.
273 * @param key_free_function function to free hash keys.
274 * @param value_free_function function to free hash values.
275 * @returns a new DBusHashTable or #NULL if no memory.
278 _dbus_hash_table_new (DBusHashType type,
279 DBusFreeFunction key_free_function,
280 DBusFreeFunction value_free_function)
282 DBusHashTable *table;
283 DBusMemPool *entry_pool;
285 table = dbus_new0 (DBusHashTable, 1);
289 entry_pool = _dbus_mem_pool_new (sizeof (DBusHashEntry), TRUE);
290 if (entry_pool == NULL)
297 table->entry_pool = entry_pool;
299 _dbus_assert (DBUS_SMALL_HASH_TABLE == _DBUS_N_ELEMENTS (table->static_buckets));
301 table->buckets = table->static_buckets;
302 table->n_buckets = DBUS_SMALL_HASH_TABLE;
303 table->n_entries = 0;
304 table->hi_rebuild_size = DBUS_SMALL_HASH_TABLE * REBUILD_MULTIPLIER;
305 table->lo_rebuild_size = 0;
306 table->down_shift = 28;
308 table->key_type = type;
310 _dbus_assert (table->mask < table->n_buckets);
312 switch (table->key_type)
315 case DBUS_HASH_POINTER:
316 case DBUS_HASH_ULONG:
317 table->find_function = find_direct_function;
319 case DBUS_HASH_STRING:
320 table->find_function = find_string_function;
323 _dbus_assert_not_reached ("Unknown hash table type");
327 table->free_key_function = key_free_function;
328 table->free_value_function = value_free_function;
335 * Increments the reference count for a hash table.
337 * @param table the hash table to add a reference to.
340 _dbus_hash_table_ref (DBusHashTable *table)
342 table->refcount += 1;
346 * Decrements the reference count for a hash table,
347 * freeing the hash table if the count reaches zero.
349 * @param table the hash table to remove a reference from.
352 _dbus_hash_table_unref (DBusHashTable *table)
354 table->refcount -= 1;
356 if (table->refcount == 0)
359 DBusHashEntry *entry;
363 /* Free the entries in the table. */
364 for (i = 0; i < table->n_buckets; i++)
366 entry = table->buckets[i];
367 while (entry != NULL)
371 free_entry (table, entry);
377 DBusHashEntry *entry;
380 /* Free the entries in the table. */
381 for (i = 0; i < table->n_buckets; i++)
383 entry = table->buckets[i];
384 while (entry != NULL)
386 free_entry_data (table, entry);
391 /* We can do this very quickly with memory pools ;-) */
392 _dbus_mem_pool_free (table->entry_pool);
395 /* Free the bucket array, if it was dynamically allocated. */
396 if (table->buckets != table->static_buckets)
397 dbus_free (table->buckets);
403 static DBusHashEntry*
404 alloc_entry (DBusHashTable *table)
406 DBusHashEntry *entry;
408 entry = _dbus_mem_pool_alloc (table->entry_pool);
414 free_entry_data (DBusHashTable *table,
415 DBusHashEntry *entry)
417 if (table->free_key_function)
418 (* table->free_key_function) (entry->key);
419 if (table->free_value_function)
420 (* table->free_value_function) (entry->value);
424 free_entry (DBusHashTable *table,
425 DBusHashEntry *entry)
427 free_entry_data (table, entry);
428 _dbus_mem_pool_dealloc (table->entry_pool, entry);
432 remove_entry (DBusHashTable *table,
433 DBusHashEntry **bucket,
434 DBusHashEntry *entry)
436 _dbus_assert (table != NULL);
437 _dbus_assert (bucket != NULL);
438 _dbus_assert (*bucket != NULL);
439 _dbus_assert (entry != NULL);
441 if (*bucket == entry)
442 *bucket = entry->next;
448 while (prev->next != entry)
451 _dbus_assert (prev != NULL);
453 prev->next = entry->next;
456 table->n_entries -= 1;
457 free_entry (table, entry);
461 * Initializes a hash table iterator. To iterate over all entries in a
462 * hash table, use the following code (the printf assumes a hash
463 * from strings to strings obviously):
468 * _dbus_hash_iter_init (table, &iter);
469 * while (_dbus_hash_iter_next (&iter))
471 * printf ("The first key is %s and value is %s\n",
472 * _dbus_hash_iter_get_string_key (&iter),
473 * _dbus_hash_iter_get_value (&iter));
479 * The iterator is initialized pointing "one before" the first hash
480 * entry. The first call to _dbus_hash_iter_next() moves it onto
481 * the first valid entry or returns #FALSE if the hash table is
482 * empty. Subsequent calls move to the next valid entry or return
483 * #FALSE if there are no more entries.
485 * Note that it is guaranteed to be safe to remove a hash entry during
486 * iteration, but it is not safe to add a hash entry.
488 * @param table the hash table to iterate over.
489 * @param iter the iterator to initialize.
492 _dbus_hash_iter_init (DBusHashTable *table,
495 DBusRealHashIter *real;
497 _dbus_assert (sizeof (DBusHashIter) == sizeof (DBusRealHashIter));
499 real = (DBusRealHashIter*) iter;
504 real->next_entry = NULL;
505 real->next_bucket = 0;
506 real->n_entries_on_init = table->n_entries;
510 * Move the hash iterator forward one step, to the next hash entry.
511 * The documentation for _dbus_hash_iter_init() explains in more
514 * @param iter the iterator to move forward.
515 * @returns #FALSE if there are no more entries to move to.
518 _dbus_hash_iter_next (DBusHashIter *iter)
520 DBusRealHashIter *real;
522 _dbus_assert (sizeof (DBusHashIter) == sizeof (DBusRealHashIter));
524 real = (DBusRealHashIter*) iter;
526 /* if this assertion failed someone probably added hash entries
527 * during iteration, which is bad.
529 _dbus_assert (real->n_entries_on_init >= real->table->n_entries);
531 /* Remember that real->entry may have been deleted */
533 while (real->next_entry == NULL)
535 if (real->next_bucket >= real->table->n_buckets)
537 /* invalidate iter and return false */
544 real->bucket = &(real->table->buckets[real->next_bucket]);
545 real->next_entry = *(real->bucket);
546 real->next_bucket += 1;
549 _dbus_assert (real->next_entry != NULL);
550 _dbus_assert (real->bucket != NULL);
552 real->entry = real->next_entry;
553 real->next_entry = real->entry->next;
559 * Removes the current entry from the hash table.
560 * If a key_free_function or value_free_function
561 * was provided to _dbus_hash_table_new(),
562 * frees the key and/or value for this entry.
564 * @param iter the hash table iterator.
567 _dbus_hash_iter_remove_entry (DBusHashIter *iter)
569 DBusRealHashIter *real;
571 real = (DBusRealHashIter*) iter;
573 _dbus_assert (real->table != NULL);
574 _dbus_assert (real->entry != NULL);
575 _dbus_assert (real->bucket != NULL);
577 remove_entry (real->table, real->bucket, real->entry);
579 real->entry = NULL; /* make it crash if you try to use this entry */
583 * Gets the value of the current entry.
585 * @param iter the hash table iterator.
588 _dbus_hash_iter_get_value (DBusHashIter *iter)
590 DBusRealHashIter *real;
592 real = (DBusRealHashIter*) iter;
594 _dbus_assert (real->table != NULL);
595 _dbus_assert (real->entry != NULL);
597 return real->entry->value;
601 * Sets the value of the current entry.
602 * If the hash table has a value_free_function
603 * it will be used to free the previous value.
604 * The hash table will own the passed-in value
605 * (it will not be copied).
607 * @param iter the hash table iterator.
608 * @param value the new value.
611 _dbus_hash_iter_set_value (DBusHashIter *iter,
614 DBusRealHashIter *real;
616 real = (DBusRealHashIter*) iter;
618 _dbus_assert (real->table != NULL);
619 _dbus_assert (real->entry != NULL);
621 if (real->table->free_value_function && value != real->entry->value)
622 (* real->table->free_value_function) (real->entry->value);
624 real->entry->value = value;
628 * Gets the key for the current entry.
629 * Only works for hash tables of type #DBUS_HASH_INT.
631 * @param iter the hash table iterator.
634 _dbus_hash_iter_get_int_key (DBusHashIter *iter)
636 DBusRealHashIter *real;
638 real = (DBusRealHashIter*) iter;
640 _dbus_assert (real->table != NULL);
641 _dbus_assert (real->entry != NULL);
643 return _DBUS_POINTER_TO_INT (real->entry->key);
647 * Gets the key for the current entry.
648 * Only works for hash tables of type #DBUS_HASH_ULONG.
650 * @param iter the hash table iterator.
653 _dbus_hash_iter_get_ulong_key (DBusHashIter *iter)
655 DBusRealHashIter *real;
657 real = (DBusRealHashIter*) iter;
659 _dbus_assert (real->table != NULL);
660 _dbus_assert (real->entry != NULL);
662 return (unsigned long) real->entry->key;
666 * Gets the key for the current entry.
667 * Only works for hash tables of type #DBUS_HASH_STRING
668 * @param iter the hash table iterator.
671 _dbus_hash_iter_get_string_key (DBusHashIter *iter)
673 DBusRealHashIter *real;
675 real = (DBusRealHashIter*) iter;
677 _dbus_assert (real->table != NULL);
678 _dbus_assert (real->entry != NULL);
680 return real->entry->key;
684 * A low-level but efficient interface for manipulating the hash
685 * table. It's efficient because you can get, set, and optionally
686 * create the hash entry while only running the hash function one
689 * Note that while calling _dbus_hash_iter_next() on the iterator
690 * filled in by this function may work, it's completely
691 * undefined which entries are after this iter and which
692 * are before it. So it would be silly to iterate using this
695 * If the hash entry is created, its value will be initialized
698 * #FALSE may be returned due to memory allocation failure, or
699 * because create_if_not_found was #FALSE and the entry
702 * If create_if_not_found is #TRUE and the entry is created, the hash
703 * table takes ownership of the key that's passed in.
705 * For a hash table of type #DBUS_HASH_INT, cast the int
706 * key to the key parameter using #_DBUS_INT_TO_POINTER().
708 * @param table the hash table.
709 * @param key the hash key.
710 * @param create_if_not_found if #TRUE, create the entry if it didn't exist.
711 * @param iter the iterator to initialize.
712 * @returns #TRUE if the hash entry now exists (and the iterator is thus valid).
715 _dbus_hash_iter_lookup (DBusHashTable *table,
717 dbus_bool_t create_if_not_found,
720 DBusRealHashIter *real;
721 DBusHashEntry *entry;
722 DBusHashEntry **bucket;
724 _dbus_assert (sizeof (DBusHashIter) == sizeof (DBusRealHashIter));
726 real = (DBusRealHashIter*) iter;
728 entry = (* table->find_function) (table, key, create_if_not_found, &bucket);
734 real->bucket = bucket;
736 real->next_entry = entry->next;
737 real->next_bucket = (bucket - table->buckets) + 1;
738 real->n_entries_on_init = table->n_entries;
740 _dbus_assert (&(table->buckets[real->next_bucket-1]) == real->bucket);
745 static DBusHashEntry*
746 add_entry (DBusHashTable *table,
749 DBusHashEntry ***bucket)
751 DBusHashEntry *entry;
754 entry = alloc_entry (table);
764 b = &(table->buckets[idx]);
771 table->n_entries += 1;
773 /* note we ONLY rebuild when ADDING - because you can iterate over a
774 * table and remove entries safely.
776 if (table->n_entries >= table->hi_rebuild_size ||
777 table->n_entries < table->lo_rebuild_size)
778 rebuild_table (table);
784 string_hash (const char *str)
786 register unsigned int result;
790 * I tried a zillion different hash functions and asked many other
791 * people for advice. Many people had their own favorite functions,
792 * all different, but no-one had much idea why they were good ones.
793 * I chose the one below (multiply by 9 and add new character)
794 * because of the following reasons:
796 * 1. Multiplying by 10 is perfect for keys that are decimal strings,
797 * and multiplying by 9 is just about as good.
798 * 2. Times-9 is (shift-left-3) plus (old). This means that each
799 * character's bits hang around in the low-order bits of the
800 * hash value for ever, plus they spread fairly rapidly up to
801 * the high-order bits to fill out the hash value. This seems
802 * works well both for decimal and non-decimal strings.
813 result += (result << 3) + c;
819 static DBusHashEntry*
820 find_string_function (DBusHashTable *table,
822 dbus_bool_t create_if_not_found,
823 DBusHashEntry ***bucket)
825 DBusHashEntry *entry;
831 idx = string_hash (key) & table->mask;
833 /* Search all of the entries in this bucket. */
834 entry = table->buckets[idx];
835 while (entry != NULL)
837 if (strcmp (key, entry->key) == 0)
840 *bucket = &(table->buckets[idx]);
847 if (create_if_not_found)
848 entry = add_entry (table, idx, key, bucket);
853 static DBusHashEntry*
854 find_direct_function (DBusHashTable *table,
856 dbus_bool_t create_if_not_found,
857 DBusHashEntry ***bucket)
859 DBusHashEntry *entry;
865 idx = RANDOM_INDEX (table, key) & table->mask;
867 /* Search all of the entries in this bucket. */
868 entry = table->buckets[idx];
869 while (entry != NULL)
871 if (key == entry->key)
874 *bucket = &(table->buckets[idx]);
881 /* Entry not found. Add a new one to the bucket. */
882 if (create_if_not_found)
883 entry = add_entry (table, idx, key, bucket);
889 rebuild_table (DBusHashTable *table)
893 DBusHashEntry **old_buckets;
894 DBusHashEntry **old_chain;
895 DBusHashEntry *entry;
899 * Allocate and initialize the new bucket array, and set up
900 * hashing constants for new array size.
903 growing = table->n_entries >= table->hi_rebuild_size;
905 old_size = table->n_buckets;
906 old_buckets = table->buckets;
910 /* overflow paranoia */
911 if (table->n_buckets < _DBUS_INT_MAX / 4 &&
912 table->down_shift >= 0)
913 new_buckets = table->n_buckets * 4;
915 return; /* can't grow anymore */
919 new_buckets = table->n_buckets / 4;
920 if (new_buckets < DBUS_SMALL_HASH_TABLE)
921 return; /* don't bother shrinking this far */
924 table->buckets = dbus_new0 (DBusHashEntry*, new_buckets);
925 if (table->buckets == NULL)
927 /* out of memory, yay - just don't reallocate, the table will
928 * still work, albeit more slowly.
930 table->buckets = old_buckets;
934 table->n_buckets = new_buckets;
938 table->lo_rebuild_size = table->hi_rebuild_size;
939 table->hi_rebuild_size *= 4;
941 table->down_shift -= 2; /* keep 2 more high bits */
942 table->mask = (table->mask << 2) + 3; /* keep 2 more high bits */
946 table->hi_rebuild_size = table->lo_rebuild_size;
947 table->lo_rebuild_size /= 4;
949 table->down_shift += 2; /* keep 2 fewer high bits */
950 table->mask = table->mask >> 2; /* keep 2 fewer high bits */
954 printf ("%s table to lo = %d hi = %d downshift = %d mask = 0x%x\n",
955 growing ? "GROW" : "SHRINK",
956 table->lo_rebuild_size,
957 table->hi_rebuild_size,
962 _dbus_assert (table->lo_rebuild_size >= 0);
963 _dbus_assert (table->hi_rebuild_size > table->lo_rebuild_size);
964 _dbus_assert (table->mask != 0);
965 /* the mask is essentially the max index */
966 _dbus_assert (table->mask < table->n_buckets);
969 * Rehash all of the existing entries into the new bucket array.
972 for (old_chain = old_buckets; old_size > 0; old_size--, old_chain++)
974 for (entry = *old_chain; entry != NULL; entry = *old_chain)
977 DBusHashEntry **bucket;
979 *old_chain = entry->next;
980 switch (table->key_type)
982 case DBUS_HASH_STRING:
983 idx = string_hash (entry->key) & table->mask;
986 case DBUS_HASH_ULONG:
987 case DBUS_HASH_POINTER:
988 idx = RANDOM_INDEX (table, entry->key);
992 _dbus_assert_not_reached ("Unknown hash table type");
996 bucket = &(table->buckets[idx]);
997 entry->next = *bucket;
1002 /* Free the old bucket array, if it was dynamically allocated. */
1004 if (old_buckets != table->static_buckets)
1005 dbus_free (old_buckets);
1009 * Looks up the value for a given string in a hash table
1010 * of type #DBUS_HASH_STRING. Returns %NULL if the value
1011 * is not present. (A not-present entry is indistinguishable
1012 * from an entry with a value of %NULL.)
1013 * @param table the hash table.
1014 * @param key the string to look up.
1015 * @returns the value of the hash entry.
1018 _dbus_hash_table_lookup_string (DBusHashTable *table,
1021 DBusHashEntry *entry;
1023 _dbus_assert (table->key_type == DBUS_HASH_STRING);
1025 entry = (* table->find_function) (table, (char*) key, FALSE, NULL);
1028 return entry->value;
1034 * Looks up the value for a given integer in a hash table
1035 * of type #DBUS_HASH_INT. Returns %NULL if the value
1036 * is not present. (A not-present entry is indistinguishable
1037 * from an entry with a value of %NULL.)
1038 * @param table the hash table.
1039 * @param key the integer to look up.
1040 * @returns the value of the hash entry.
1043 _dbus_hash_table_lookup_int (DBusHashTable *table,
1046 DBusHashEntry *entry;
1048 _dbus_assert (table->key_type == DBUS_HASH_INT);
1050 entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, NULL);
1053 return entry->value;
1059 * Looks up the value for a given integer in a hash table
1060 * of type #DBUS_HASH_POINTER. Returns %NULL if the value
1061 * is not present. (A not-present entry is indistinguishable
1062 * from an entry with a value of %NULL.)
1063 * @param table the hash table.
1064 * @param key the integer to look up.
1065 * @returns the value of the hash entry.
1068 _dbus_hash_table_lookup_pointer (DBusHashTable *table,
1071 DBusHashEntry *entry;
1073 _dbus_assert (table->key_type == DBUS_HASH_POINTER);
1075 entry = (* table->find_function) (table, key, FALSE, NULL);
1078 return entry->value;
1084 * Looks up the value for a given integer in a hash table
1085 * of type #DBUS_HASH_ULONG. Returns %NULL if the value
1086 * is not present. (A not-present entry is indistinguishable
1087 * from an entry with a value of %NULL.)
1088 * @param table the hash table.
1089 * @param key the integer to look up.
1090 * @returns the value of the hash entry.
1093 _dbus_hash_table_lookup_ulong (DBusHashTable *table,
1096 DBusHashEntry *entry;
1098 _dbus_assert (table->key_type == DBUS_HASH_ULONG);
1100 entry = (* table->find_function) (table, (void*) key, FALSE, NULL);
1103 return entry->value;
1109 * Removes the hash entry for the given key. If no hash entry
1110 * for the key exists, does nothing.
1112 * @param table the hash table.
1113 * @param key the hash key.
1114 * @returns #TRUE if the entry existed
1117 _dbus_hash_table_remove_string (DBusHashTable *table,
1120 DBusHashEntry *entry;
1121 DBusHashEntry **bucket;
1123 _dbus_assert (table->key_type == DBUS_HASH_STRING);
1125 entry = (* table->find_function) (table, (char*) key, FALSE, &bucket);
1129 remove_entry (table, bucket, entry);
1137 * Removes the hash entry for the given key. If no hash entry
1138 * for the key exists, does nothing.
1140 * @param table the hash table.
1141 * @param key the hash key.
1142 * @returns #TRUE if the entry existed
1145 _dbus_hash_table_remove_int (DBusHashTable *table,
1148 DBusHashEntry *entry;
1149 DBusHashEntry **bucket;
1151 _dbus_assert (table->key_type == DBUS_HASH_INT);
1153 entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, &bucket);
1157 remove_entry (table, bucket, entry);
1165 * Removes the hash entry for the given key. If no hash entry
1166 * for the key exists, does nothing.
1168 * @param table the hash table.
1169 * @param key the hash key.
1170 * @returns #TRUE if the entry existed
1173 _dbus_hash_table_remove_pointer (DBusHashTable *table,
1176 DBusHashEntry *entry;
1177 DBusHashEntry **bucket;
1179 _dbus_assert (table->key_type == DBUS_HASH_POINTER);
1181 entry = (* table->find_function) (table, key, FALSE, &bucket);
1185 remove_entry (table, bucket, entry);
1194 * Removes the hash entry for the given key. If no hash entry
1195 * for the key exists, does nothing.
1197 * @param table the hash table.
1198 * @param key the hash key.
1199 * @returns #TRUE if the entry existed
1202 _dbus_hash_table_remove_ulong (DBusHashTable *table,
1205 DBusHashEntry *entry;
1206 DBusHashEntry **bucket;
1208 _dbus_assert (table->key_type == DBUS_HASH_ULONG);
1210 entry = (* table->find_function) (table, (void*) key, FALSE, &bucket);
1214 remove_entry (table, bucket, entry);
1222 * Creates a hash entry with the given key and value.
1223 * The key and value are not copied; they are stored
1224 * in the hash table by reference. If an entry with the
1225 * given key already exists, the previous key and value
1226 * are overwritten (and freed if the hash table has
1227 * a key_free_function and/or value_free_function).
1229 * Returns #FALSE if memory for the new hash entry
1230 * can't be allocated.
1232 * @param table the hash table.
1233 * @param key the hash entry key.
1234 * @param value the hash entry value.
1237 _dbus_hash_table_insert_string (DBusHashTable *table,
1241 DBusHashEntry *entry;
1243 _dbus_assert (table->key_type == DBUS_HASH_STRING);
1245 entry = (* table->find_function) (table, key, TRUE, NULL);
1248 return FALSE; /* no memory */
1250 if (table->free_key_function && entry->key != key)
1251 (* table->free_key_function) (entry->key);
1253 if (table->free_value_function && entry->value != value)
1254 (* table->free_value_function) (entry->value);
1257 entry->value = value;
1263 * Creates a hash entry with the given key and value.
1264 * The key and value are not copied; they are stored
1265 * in the hash table by reference. If an entry with the
1266 * given key already exists, the previous key and value
1267 * are overwritten (and freed if the hash table has
1268 * a key_free_function and/or value_free_function).
1270 * Returns #FALSE if memory for the new hash entry
1271 * can't be allocated.
1273 * @param table the hash table.
1274 * @param key the hash entry key.
1275 * @param value the hash entry value.
1278 _dbus_hash_table_insert_int (DBusHashTable *table,
1282 DBusHashEntry *entry;
1284 _dbus_assert (table->key_type == DBUS_HASH_INT);
1286 entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), TRUE, NULL);
1289 return FALSE; /* no memory */
1291 if (table->free_key_function && entry->key != _DBUS_INT_TO_POINTER (key))
1292 (* table->free_key_function) (entry->key);
1294 if (table->free_value_function && entry->value != value)
1295 (* table->free_value_function) (entry->value);
1297 entry->key = _DBUS_INT_TO_POINTER (key);
1298 entry->value = value;
1304 * Creates a hash entry with the given key and value.
1305 * The key and value are not copied; they are stored
1306 * in the hash table by reference. If an entry with the
1307 * given key already exists, the previous key and value
1308 * are overwritten (and freed if the hash table has
1309 * a key_free_function and/or value_free_function).
1311 * Returns #FALSE if memory for the new hash entry
1312 * can't be allocated.
1314 * @param table the hash table.
1315 * @param key the hash entry key.
1316 * @param value the hash entry value.
1319 _dbus_hash_table_insert_pointer (DBusHashTable *table,
1323 DBusHashEntry *entry;
1325 _dbus_assert (table->key_type == DBUS_HASH_POINTER);
1327 entry = (* table->find_function) (table, key, TRUE, NULL);
1330 return FALSE; /* no memory */
1332 if (table->free_key_function && entry->key != key)
1333 (* table->free_key_function) (entry->key);
1335 if (table->free_value_function && entry->value != value)
1336 (* table->free_value_function) (entry->value);
1339 entry->value = value;
1346 * Creates a hash entry with the given key and value.
1347 * The key and value are not copied; they are stored
1348 * in the hash table by reference. If an entry with the
1349 * given key already exists, the previous key and value
1350 * are overwritten (and freed if the hash table has
1351 * a key_free_function and/or value_free_function).
1353 * Returns #FALSE if memory for the new hash entry
1354 * can't be allocated.
1356 * @param table the hash table.
1357 * @param key the hash entry key.
1358 * @param value the hash entry value.
1361 _dbus_hash_table_insert_ulong (DBusHashTable *table,
1365 DBusHashEntry *entry;
1367 _dbus_assert (table->key_type == DBUS_HASH_ULONG);
1369 entry = (* table->find_function) (table, (void*) key, TRUE, NULL);
1372 return FALSE; /* no memory */
1374 if (table->free_key_function && entry->key != (void*) key)
1375 (* table->free_key_function) (entry->key);
1377 if (table->free_value_function && entry->value != value)
1378 (* table->free_value_function) (entry->value);
1380 entry->key = (void*) key;
1381 entry->value = value;
1387 * Gets the number of hash entries in a hash table.
1389 * @param table the hash table.
1390 * @returns the number of entries in the table.
1393 _dbus_hash_table_get_n_entries (DBusHashTable *table)
1395 return table->n_entries;
1400 #ifdef DBUS_BUILD_TESTS
1401 #include "dbus-test.h"
1404 /* If you're wondering why the hash table test takes
1405 * forever to run, it's because we call this function
1406 * in inner loops thus making things quadratic.
1409 count_entries (DBusHashTable *table)
1415 _dbus_hash_iter_init (table, &iter);
1416 while (_dbus_hash_iter_next (&iter))
1419 _dbus_assert (count == _dbus_hash_table_get_n_entries (table));
1425 * @ingroup DBusHashTableInternals
1426 * Unit test for DBusHashTable
1427 * @returns #TRUE on success.
1430 _dbus_hash_test (void)
1433 DBusHashTable *table1;
1434 DBusHashTable *table2;
1435 DBusHashTable *table3;
1437 #define N_HASH_KEYS 5000
1439 dbus_bool_t ret = FALSE;
1441 keys = dbus_new (char *, N_HASH_KEYS);
1443 _dbus_assert_not_reached ("no memory");
1445 for (i = 0; i < N_HASH_KEYS; i++)
1447 keys[i] = dbus_malloc (128);
1449 if (keys[i] == NULL)
1450 _dbus_assert_not_reached ("no memory");
1453 printf ("Computing test hash keys...\n");
1455 while (i < N_HASH_KEYS)
1457 sprintf (keys[i], "Hash key %d", i);
1460 printf ("... done.\n");
1462 table1 = _dbus_hash_table_new (DBUS_HASH_STRING,
1463 dbus_free, dbus_free);
1467 table2 = _dbus_hash_table_new (DBUS_HASH_INT,
1472 table3 = _dbus_hash_table_new (DBUS_HASH_ULONG,
1477 /* Insert and remove a bunch of stuff, counting the table in between
1478 * to be sure it's not broken and that iteration works
1486 key = _dbus_strdup (keys[i]);
1489 value = _dbus_strdup ("Value!");
1493 if (!_dbus_hash_table_insert_string (table1,
1497 value = _dbus_strdup (keys[i]);
1501 if (!_dbus_hash_table_insert_int (table2,
1505 value = _dbus_strdup (keys[i]);
1509 if (!_dbus_hash_table_insert_ulong (table3,
1513 _dbus_assert (count_entries (table1) == i + 1);
1514 _dbus_assert (count_entries (table2) == i + 1);
1515 _dbus_assert (count_entries (table3) == i + 1);
1517 value = _dbus_hash_table_lookup_string (table1, keys[i]);
1518 _dbus_assert (value != NULL);
1519 _dbus_assert (strcmp (value, "Value!") == 0);
1521 value = _dbus_hash_table_lookup_int (table2, i);
1522 _dbus_assert (value != NULL);
1523 _dbus_assert (strcmp (value, keys[i]) == 0);
1525 value = _dbus_hash_table_lookup_ulong (table3, i);
1526 _dbus_assert (value != NULL);
1527 _dbus_assert (strcmp (value, keys[i]) == 0);
1535 _dbus_hash_table_remove_string (table1,
1538 _dbus_hash_table_remove_int (table2, i);
1540 _dbus_hash_table_remove_ulong (table3, i);
1542 _dbus_assert (count_entries (table1) == i);
1543 _dbus_assert (count_entries (table2) == i);
1544 _dbus_assert (count_entries (table3) == i);
1549 _dbus_hash_table_ref (table1);
1550 _dbus_hash_table_ref (table2);
1551 _dbus_hash_table_ref (table3);
1552 _dbus_hash_table_unref (table1);
1553 _dbus_hash_table_unref (table2);
1554 _dbus_hash_table_unref (table3);
1555 _dbus_hash_table_unref (table1);
1556 _dbus_hash_table_unref (table2);
1557 _dbus_hash_table_unref (table3);
1560 /* Insert a bunch of stuff then check
1561 * that iteration works correctly (finds the right
1562 * values, iter_set_value works, etc.)
1564 table1 = _dbus_hash_table_new (DBUS_HASH_STRING,
1565 dbus_free, dbus_free);
1569 table2 = _dbus_hash_table_new (DBUS_HASH_INT,
1580 key = _dbus_strdup (keys[i]);
1583 value = _dbus_strdup ("Value!");
1587 if (!_dbus_hash_table_insert_string (table1,
1591 value = _dbus_strdup (keys[i]);
1595 if (!_dbus_hash_table_insert_int (table2,
1599 _dbus_assert (count_entries (table1) == i + 1);
1600 _dbus_assert (count_entries (table2) == i + 1);
1605 _dbus_hash_iter_init (table1, &iter);
1606 while (_dbus_hash_iter_next (&iter))
1611 key = _dbus_hash_iter_get_string_key (&iter);
1612 value = _dbus_hash_iter_get_value (&iter);
1614 _dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value);
1616 value = _dbus_strdup ("Different value!");
1620 _dbus_hash_iter_set_value (&iter, value);
1622 _dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value);
1625 _dbus_hash_iter_init (table1, &iter);
1626 while (_dbus_hash_iter_next (&iter))
1628 _dbus_hash_iter_remove_entry (&iter);
1629 _dbus_assert (count_entries (table1) == i - 1);
1633 _dbus_hash_iter_init (table2, &iter);
1634 while (_dbus_hash_iter_next (&iter))
1639 key = _dbus_hash_iter_get_int_key (&iter);
1640 value = _dbus_hash_iter_get_value (&iter);
1642 _dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value);
1644 value = _dbus_strdup ("Different value!");
1648 _dbus_hash_iter_set_value (&iter, value);
1650 _dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value);
1653 i = count_entries (table2);
1654 _dbus_hash_iter_init (table2, &iter);
1655 while (_dbus_hash_iter_next (&iter))
1657 _dbus_hash_iter_remove_entry (&iter);
1658 _dbus_assert (count_entries (table2) + 1 == i);
1662 /* add/remove interleaved, to check that we grow/shrink the table
1671 key = _dbus_strdup (keys[i]);
1675 value = _dbus_strdup ("Value!");
1679 if (!_dbus_hash_table_insert_string (table1,
1692 key = _dbus_strdup (keys[i]);
1695 value = _dbus_strdup ("Value!");
1699 if (!_dbus_hash_table_remove_string (table1, keys[i]))
1702 if (!_dbus_hash_table_insert_string (table1,
1706 if (!_dbus_hash_table_remove_string (table1, keys[i]))
1709 _dbus_assert (_dbus_hash_table_get_n_entries (table1) == i);
1714 /* nuke these tables */
1715 _dbus_hash_table_unref (table1);
1716 _dbus_hash_table_unref (table2);
1719 /* Now do a bunch of things again using _dbus_hash_iter_lookup() to
1720 * be sure that interface works.
1722 table1 = _dbus_hash_table_new (DBUS_HASH_STRING,
1723 dbus_free, dbus_free);
1727 table2 = _dbus_hash_table_new (DBUS_HASH_INT,
1738 key = _dbus_strdup (keys[i]);
1741 value = _dbus_strdup ("Value!");
1745 if (!_dbus_hash_iter_lookup (table1,
1748 _dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL);
1749 _dbus_hash_iter_set_value (&iter, value);
1751 value = _dbus_strdup (keys[i]);
1755 if (!_dbus_hash_iter_lookup (table2,
1756 _DBUS_INT_TO_POINTER (i), TRUE, &iter))
1758 _dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL);
1759 _dbus_hash_iter_set_value (&iter, value);
1761 _dbus_assert (count_entries (table1) == i + 1);
1762 _dbus_assert (count_entries (table2) == i + 1);
1764 if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter))
1767 value = _dbus_hash_iter_get_value (&iter);
1768 _dbus_assert (value != NULL);
1769 _dbus_assert (strcmp (value, "Value!") == 0);
1771 /* Iterate just to be sure it works, though
1772 * it's a stupid thing to do
1774 while (_dbus_hash_iter_next (&iter))
1777 if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter))
1780 value = _dbus_hash_iter_get_value (&iter);
1781 _dbus_assert (value != NULL);
1782 _dbus_assert (strcmp (value, keys[i]) == 0);
1784 /* Iterate just to be sure it works, though
1785 * it's a stupid thing to do
1787 while (_dbus_hash_iter_next (&iter))
1796 if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter))
1797 _dbus_assert_not_reached ("hash entry should have existed");
1798 _dbus_hash_iter_remove_entry (&iter);
1800 if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter))
1801 _dbus_assert_not_reached ("hash entry should have existed");
1802 _dbus_hash_iter_remove_entry (&iter);
1804 _dbus_assert (count_entries (table1) == i);
1805 _dbus_assert (count_entries (table2) == i);
1810 _dbus_hash_table_unref (table1);
1811 _dbus_hash_table_unref (table2);
1816 for (i = 0; i < N_HASH_KEYS; i++)
1817 dbus_free (keys[i]);
1824 #endif /* DBUS_BUILD_TESTS */