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,
159 DBusPreallocatedHash *preallocated);
162 * @brief Internals of DBusHashTable.
164 * Hash table internals. Hash tables are opaque objects, they must be
165 * used via accessor functions.
167 struct DBusHashTable {
168 int refcount; /**< Reference count */
170 DBusHashEntry **buckets; /**< Pointer to bucket array. Each
171 * element points to first entry in
172 * bucket's hash chain, or #NULL.
174 DBusHashEntry *static_buckets[DBUS_SMALL_HASH_TABLE];
175 /**< Bucket array used for small tables
176 * (to avoid mallocs and frees).
178 int n_buckets; /**< Total number of buckets allocated
181 int n_entries; /**< Total number of entries present
184 int hi_rebuild_size; /**< Enlarge table when n_entries gets
187 int lo_rebuild_size; /**< Shrink table when n_entries gets
190 int down_shift; /**< Shift count used in hashing
191 * function. Designed to use high-
192 * order bits of randomized keys.
194 int mask; /**< Mask value used in hashing
197 DBusHashType key_type; /**< Type of keys used in this table */
200 DBusFindEntryFunction find_function; /**< Function for finding entries */
202 DBusFreeFunction free_key_function; /**< Function to free keys */
203 DBusFreeFunction free_value_function; /**< Function to free values */
205 DBusMemPool *entry_pool; /**< Memory pool for hash entries */
209 * @brief Internals of DBusHashIter.
213 DBusHashTable *table; /**< Pointer to table containing entry. */
214 DBusHashEntry **bucket; /**< Pointer to bucket that points to
215 * first entry in this entry's chain:
216 * used for deleting the entry.
218 DBusHashEntry *entry; /**< Current hash entry */
219 DBusHashEntry *next_entry; /**< Next entry to be iterated onto in current bucket */
220 int next_bucket; /**< index of next bucket */
221 int n_entries_on_init; /**< used to detect table resize since initialization */
224 static DBusHashEntry* find_direct_function (DBusHashTable *table,
226 dbus_bool_t create_if_not_found,
227 DBusHashEntry ***bucket,
228 DBusPreallocatedHash *preallocated);
229 static DBusHashEntry* find_string_function (DBusHashTable *table,
231 dbus_bool_t create_if_not_found,
232 DBusHashEntry ***bucket,
233 DBusPreallocatedHash *preallocated);
234 static unsigned int string_hash (const char *str);
235 static void rebuild_table (DBusHashTable *table);
236 static DBusHashEntry* alloc_entry (DBusHashTable *table);
237 static void remove_entry (DBusHashTable *table,
238 DBusHashEntry **bucket,
239 DBusHashEntry *entry);
240 static void free_entry (DBusHashTable *table,
241 DBusHashEntry *entry);
242 static void free_entry_data (DBusHashTable *table,
243 DBusHashEntry *entry);
249 * @addtogroup DBusHashTable
254 * @typedef DBusHashIter
256 * Public opaque hash table iterator object.
260 * @typedef DBusHashTable
262 * Public opaque hash table object.
266 * @typedef DBusHashType
268 * Indicates the type of a key in the hash table.
272 * Constructs a new hash table. Should be freed with
273 * _dbus_hash_table_unref(). If memory cannot be
274 * allocated for the hash table, returns #NULL.
276 * @param type the type of hash key to use.
277 * @param key_free_function function to free hash keys.
278 * @param value_free_function function to free hash values.
279 * @returns a new DBusHashTable or #NULL if no memory.
282 _dbus_hash_table_new (DBusHashType type,
283 DBusFreeFunction key_free_function,
284 DBusFreeFunction value_free_function)
286 DBusHashTable *table;
287 DBusMemPool *entry_pool;
289 table = dbus_new0 (DBusHashTable, 1);
293 entry_pool = _dbus_mem_pool_new (sizeof (DBusHashEntry), TRUE);
294 if (entry_pool == NULL)
301 table->entry_pool = entry_pool;
303 _dbus_assert (DBUS_SMALL_HASH_TABLE == _DBUS_N_ELEMENTS (table->static_buckets));
305 table->buckets = table->static_buckets;
306 table->n_buckets = DBUS_SMALL_HASH_TABLE;
307 table->n_entries = 0;
308 table->hi_rebuild_size = DBUS_SMALL_HASH_TABLE * REBUILD_MULTIPLIER;
309 table->lo_rebuild_size = 0;
310 table->down_shift = 28;
312 table->key_type = type;
314 _dbus_assert (table->mask < table->n_buckets);
316 switch (table->key_type)
319 case DBUS_HASH_POINTER:
320 case DBUS_HASH_ULONG:
321 table->find_function = find_direct_function;
323 case DBUS_HASH_STRING:
324 table->find_function = find_string_function;
327 _dbus_assert_not_reached ("Unknown hash table type");
331 table->free_key_function = key_free_function;
332 table->free_value_function = value_free_function;
339 * Increments the reference count for a hash table.
341 * @param table the hash table to add a reference to.
344 _dbus_hash_table_ref (DBusHashTable *table)
346 table->refcount += 1;
350 * Decrements the reference count for a hash table,
351 * freeing the hash table if the count reaches zero.
353 * @param table the hash table to remove a reference from.
356 _dbus_hash_table_unref (DBusHashTable *table)
358 table->refcount -= 1;
360 if (table->refcount == 0)
363 DBusHashEntry *entry;
367 /* Free the entries in the table. */
368 for (i = 0; i < table->n_buckets; i++)
370 entry = table->buckets[i];
371 while (entry != NULL)
375 free_entry (table, entry);
381 DBusHashEntry *entry;
384 /* Free the entries in the table. */
385 for (i = 0; i < table->n_buckets; i++)
387 entry = table->buckets[i];
388 while (entry != NULL)
390 free_entry_data (table, entry);
395 /* We can do this very quickly with memory pools ;-) */
396 _dbus_mem_pool_free (table->entry_pool);
399 /* Free the bucket array, if it was dynamically allocated. */
400 if (table->buckets != table->static_buckets)
401 dbus_free (table->buckets);
407 static DBusHashEntry*
408 alloc_entry (DBusHashTable *table)
410 DBusHashEntry *entry;
412 entry = _dbus_mem_pool_alloc (table->entry_pool);
418 free_entry_data (DBusHashTable *table,
419 DBusHashEntry *entry)
421 if (table->free_key_function)
422 (* table->free_key_function) (entry->key);
423 if (table->free_value_function)
424 (* table->free_value_function) (entry->value);
428 free_entry (DBusHashTable *table,
429 DBusHashEntry *entry)
431 free_entry_data (table, entry);
432 _dbus_mem_pool_dealloc (table->entry_pool, entry);
436 remove_entry (DBusHashTable *table,
437 DBusHashEntry **bucket,
438 DBusHashEntry *entry)
440 _dbus_assert (table != NULL);
441 _dbus_assert (bucket != NULL);
442 _dbus_assert (*bucket != NULL);
443 _dbus_assert (entry != NULL);
445 if (*bucket == entry)
446 *bucket = entry->next;
452 while (prev->next != entry)
455 _dbus_assert (prev != NULL);
457 prev->next = entry->next;
460 table->n_entries -= 1;
461 free_entry (table, entry);
465 * Initializes a hash table iterator. To iterate over all entries in a
466 * hash table, use the following code (the printf assumes a hash
467 * from strings to strings obviously):
472 * _dbus_hash_iter_init (table, &iter);
473 * while (_dbus_hash_iter_next (&iter))
475 * printf ("The first key is %s and value is %s\n",
476 * _dbus_hash_iter_get_string_key (&iter),
477 * _dbus_hash_iter_get_value (&iter));
483 * The iterator is initialized pointing "one before" the first hash
484 * entry. The first call to _dbus_hash_iter_next() moves it onto
485 * the first valid entry or returns #FALSE if the hash table is
486 * empty. Subsequent calls move to the next valid entry or return
487 * #FALSE if there are no more entries.
489 * Note that it is guaranteed to be safe to remove a hash entry during
490 * iteration, but it is not safe to add a hash entry.
492 * @param table the hash table to iterate over.
493 * @param iter the iterator to initialize.
496 _dbus_hash_iter_init (DBusHashTable *table,
499 DBusRealHashIter *real;
501 _dbus_assert (sizeof (DBusHashIter) == sizeof (DBusRealHashIter));
503 real = (DBusRealHashIter*) iter;
508 real->next_entry = NULL;
509 real->next_bucket = 0;
510 real->n_entries_on_init = table->n_entries;
514 * Move the hash iterator forward one step, to the next hash entry.
515 * The documentation for _dbus_hash_iter_init() explains in more
518 * @param iter the iterator to move forward.
519 * @returns #FALSE if there are no more entries to move to.
522 _dbus_hash_iter_next (DBusHashIter *iter)
524 DBusRealHashIter *real;
526 _dbus_assert (sizeof (DBusHashIter) == sizeof (DBusRealHashIter));
528 real = (DBusRealHashIter*) iter;
530 /* if this assertion failed someone probably added hash entries
531 * during iteration, which is bad.
533 _dbus_assert (real->n_entries_on_init >= real->table->n_entries);
535 /* Remember that real->entry may have been deleted */
537 while (real->next_entry == NULL)
539 if (real->next_bucket >= real->table->n_buckets)
541 /* invalidate iter and return false */
548 real->bucket = &(real->table->buckets[real->next_bucket]);
549 real->next_entry = *(real->bucket);
550 real->next_bucket += 1;
553 _dbus_assert (real->next_entry != NULL);
554 _dbus_assert (real->bucket != NULL);
556 real->entry = real->next_entry;
557 real->next_entry = real->entry->next;
563 * Removes the current entry from the hash table.
564 * If a key_free_function or value_free_function
565 * was provided to _dbus_hash_table_new(),
566 * frees the key and/or value for this entry.
568 * @param iter the hash table iterator.
571 _dbus_hash_iter_remove_entry (DBusHashIter *iter)
573 DBusRealHashIter *real;
575 real = (DBusRealHashIter*) iter;
577 _dbus_assert (real->table != NULL);
578 _dbus_assert (real->entry != NULL);
579 _dbus_assert (real->bucket != NULL);
581 remove_entry (real->table, real->bucket, real->entry);
583 real->entry = NULL; /* make it crash if you try to use this entry */
587 * Gets the value of the current entry.
589 * @param iter the hash table iterator.
592 _dbus_hash_iter_get_value (DBusHashIter *iter)
594 DBusRealHashIter *real;
596 real = (DBusRealHashIter*) iter;
598 _dbus_assert (real->table != NULL);
599 _dbus_assert (real->entry != NULL);
601 return real->entry->value;
605 * Sets the value of the current entry.
606 * If the hash table has a value_free_function
607 * it will be used to free the previous value.
608 * The hash table will own the passed-in value
609 * (it will not be copied).
611 * @param iter the hash table iterator.
612 * @param value the new value.
615 _dbus_hash_iter_set_value (DBusHashIter *iter,
618 DBusRealHashIter *real;
620 real = (DBusRealHashIter*) iter;
622 _dbus_assert (real->table != NULL);
623 _dbus_assert (real->entry != NULL);
625 if (real->table->free_value_function && value != real->entry->value)
626 (* real->table->free_value_function) (real->entry->value);
628 real->entry->value = value;
632 * Gets the key for the current entry.
633 * Only works for hash tables of type #DBUS_HASH_INT.
635 * @param iter the hash table iterator.
638 _dbus_hash_iter_get_int_key (DBusHashIter *iter)
640 DBusRealHashIter *real;
642 real = (DBusRealHashIter*) iter;
644 _dbus_assert (real->table != NULL);
645 _dbus_assert (real->entry != NULL);
647 return _DBUS_POINTER_TO_INT (real->entry->key);
651 * Gets the key for the current entry.
652 * Only works for hash tables of type #DBUS_HASH_ULONG.
654 * @param iter the hash table iterator.
657 _dbus_hash_iter_get_ulong_key (DBusHashIter *iter)
659 DBusRealHashIter *real;
661 real = (DBusRealHashIter*) iter;
663 _dbus_assert (real->table != NULL);
664 _dbus_assert (real->entry != NULL);
666 return (unsigned long) real->entry->key;
670 * Gets the key for the current entry.
671 * Only works for hash tables of type #DBUS_HASH_STRING
672 * @param iter the hash table iterator.
675 _dbus_hash_iter_get_string_key (DBusHashIter *iter)
677 DBusRealHashIter *real;
679 real = (DBusRealHashIter*) iter;
681 _dbus_assert (real->table != NULL);
682 _dbus_assert (real->entry != NULL);
684 return real->entry->key;
688 * A low-level but efficient interface for manipulating the hash
689 * table. It's efficient because you can get, set, and optionally
690 * create the hash entry while only running the hash function one
693 * Note that while calling _dbus_hash_iter_next() on the iterator
694 * filled in by this function may work, it's completely
695 * undefined which entries are after this iter and which
696 * are before it. So it would be silly to iterate using this
699 * If the hash entry is created, its value will be initialized
702 * #FALSE may be returned due to memory allocation failure, or
703 * because create_if_not_found was #FALSE and the entry
706 * If create_if_not_found is #TRUE and the entry is created, the hash
707 * table takes ownership of the key that's passed in.
709 * For a hash table of type #DBUS_HASH_INT, cast the int
710 * key to the key parameter using #_DBUS_INT_TO_POINTER().
712 * @param table the hash table.
713 * @param key the hash key.
714 * @param create_if_not_found if #TRUE, create the entry if it didn't exist.
715 * @param iter the iterator to initialize.
716 * @returns #TRUE if the hash entry now exists (and the iterator is thus valid).
719 _dbus_hash_iter_lookup (DBusHashTable *table,
721 dbus_bool_t create_if_not_found,
724 DBusRealHashIter *real;
725 DBusHashEntry *entry;
726 DBusHashEntry **bucket;
728 _dbus_assert (sizeof (DBusHashIter) == sizeof (DBusRealHashIter));
730 real = (DBusRealHashIter*) iter;
732 entry = (* table->find_function) (table, key, create_if_not_found, &bucket, NULL);
738 real->bucket = bucket;
740 real->next_entry = entry->next;
741 real->next_bucket = (bucket - table->buckets) + 1;
742 real->n_entries_on_init = table->n_entries;
744 _dbus_assert (&(table->buckets[real->next_bucket-1]) == real->bucket);
750 add_allocated_entry (DBusHashTable *table,
751 DBusHashEntry *entry,
754 DBusHashEntry ***bucket)
760 b = &(table->buckets[idx]);
767 table->n_entries += 1;
769 /* note we ONLY rebuild when ADDING - because you can iterate over a
770 * table and remove entries safely.
772 if (table->n_entries >= table->hi_rebuild_size ||
773 table->n_entries < table->lo_rebuild_size)
774 rebuild_table (table);
777 static DBusHashEntry*
778 add_entry (DBusHashTable *table,
781 DBusHashEntry ***bucket,
782 DBusPreallocatedHash *preallocated)
784 DBusHashEntry *entry;
786 if (preallocated == NULL)
788 entry = alloc_entry (table);
798 entry = (DBusHashEntry*) preallocated;
801 add_allocated_entry (table, entry, idx, key, bucket);
807 string_hash (const char *str)
809 register unsigned int result;
813 * I tried a zillion different hash functions and asked many other
814 * people for advice. Many people had their own favorite functions,
815 * all different, but no-one had much idea why they were good ones.
816 * I chose the one below (multiply by 9 and add new character)
817 * because of the following reasons:
819 * 1. Multiplying by 10 is perfect for keys that are decimal strings,
820 * and multiplying by 9 is just about as good.
821 * 2. Times-9 is (shift-left-3) plus (old). This means that each
822 * character's bits hang around in the low-order bits of the
823 * hash value for ever, plus they spread fairly rapidly up to
824 * the high-order bits to fill out the hash value. This seems
825 * works well both for decimal and non-decimal strings.
828 /* FIXME the hash function in GLib is better than this one */
838 result += (result << 3) + c;
844 static DBusHashEntry*
845 find_string_function (DBusHashTable *table,
847 dbus_bool_t create_if_not_found,
848 DBusHashEntry ***bucket,
849 DBusPreallocatedHash *preallocated)
851 DBusHashEntry *entry;
857 idx = string_hash (key) & table->mask;
859 /* Search all of the entries in this bucket. */
860 entry = table->buckets[idx];
861 while (entry != NULL)
863 if (strcmp (key, entry->key) == 0)
866 *bucket = &(table->buckets[idx]);
869 _dbus_hash_table_free_preallocated_entry (table, preallocated);
877 if (create_if_not_found)
878 entry = add_entry (table, idx, key, bucket, preallocated);
879 else if (preallocated)
880 _dbus_hash_table_free_preallocated_entry (table, preallocated);
885 static DBusHashEntry*
886 find_direct_function (DBusHashTable *table,
888 dbus_bool_t create_if_not_found,
889 DBusHashEntry ***bucket,
890 DBusPreallocatedHash *preallocated)
892 DBusHashEntry *entry;
898 idx = RANDOM_INDEX (table, key) & table->mask;
900 /* Search all of the entries in this bucket. */
901 entry = table->buckets[idx];
902 while (entry != NULL)
904 if (key == entry->key)
907 *bucket = &(table->buckets[idx]);
910 _dbus_hash_table_free_preallocated_entry (table, preallocated);
918 /* Entry not found. Add a new one to the bucket. */
919 if (create_if_not_found)
920 entry = add_entry (table, idx, key, bucket, preallocated);
921 else if (preallocated)
922 _dbus_hash_table_free_preallocated_entry (table, preallocated);
928 rebuild_table (DBusHashTable *table)
932 DBusHashEntry **old_buckets;
933 DBusHashEntry **old_chain;
934 DBusHashEntry *entry;
938 * Allocate and initialize the new bucket array, and set up
939 * hashing constants for new array size.
942 growing = table->n_entries >= table->hi_rebuild_size;
944 old_size = table->n_buckets;
945 old_buckets = table->buckets;
949 /* overflow paranoia */
950 if (table->n_buckets < _DBUS_INT_MAX / 4 &&
951 table->down_shift >= 0)
952 new_buckets = table->n_buckets * 4;
954 return; /* can't grow anymore */
958 new_buckets = table->n_buckets / 4;
959 if (new_buckets < DBUS_SMALL_HASH_TABLE)
960 return; /* don't bother shrinking this far */
963 table->buckets = dbus_new0 (DBusHashEntry*, new_buckets);
964 if (table->buckets == NULL)
966 /* out of memory, yay - just don't reallocate, the table will
967 * still work, albeit more slowly.
969 table->buckets = old_buckets;
973 table->n_buckets = new_buckets;
977 table->lo_rebuild_size = table->hi_rebuild_size;
978 table->hi_rebuild_size *= 4;
980 table->down_shift -= 2; /* keep 2 more high bits */
981 table->mask = (table->mask << 2) + 3; /* keep 2 more high bits */
985 table->hi_rebuild_size = table->lo_rebuild_size;
986 table->lo_rebuild_size /= 4;
988 table->down_shift += 2; /* keep 2 fewer high bits */
989 table->mask = table->mask >> 2; /* keep 2 fewer high bits */
993 printf ("%s table to lo = %d hi = %d downshift = %d mask = 0x%x\n",
994 growing ? "GROW" : "SHRINK",
995 table->lo_rebuild_size,
996 table->hi_rebuild_size,
1001 _dbus_assert (table->lo_rebuild_size >= 0);
1002 _dbus_assert (table->hi_rebuild_size > table->lo_rebuild_size);
1003 _dbus_assert (table->mask != 0);
1004 /* the mask is essentially the max index */
1005 _dbus_assert (table->mask < table->n_buckets);
1008 * Rehash all of the existing entries into the new bucket array.
1011 for (old_chain = old_buckets; old_size > 0; old_size--, old_chain++)
1013 for (entry = *old_chain; entry != NULL; entry = *old_chain)
1016 DBusHashEntry **bucket;
1018 *old_chain = entry->next;
1019 switch (table->key_type)
1021 case DBUS_HASH_STRING:
1022 idx = string_hash (entry->key) & table->mask;
1025 case DBUS_HASH_ULONG:
1026 case DBUS_HASH_POINTER:
1027 idx = RANDOM_INDEX (table, entry->key);
1031 _dbus_assert_not_reached ("Unknown hash table type");
1035 bucket = &(table->buckets[idx]);
1036 entry->next = *bucket;
1041 /* Free the old bucket array, if it was dynamically allocated. */
1043 if (old_buckets != table->static_buckets)
1044 dbus_free (old_buckets);
1048 * Looks up the value for a given string in a hash table
1049 * of type #DBUS_HASH_STRING. Returns %NULL if the value
1050 * is not present. (A not-present entry is indistinguishable
1051 * from an entry with a value of %NULL.)
1052 * @param table the hash table.
1053 * @param key the string to look up.
1054 * @returns the value of the hash entry.
1057 _dbus_hash_table_lookup_string (DBusHashTable *table,
1060 DBusHashEntry *entry;
1062 _dbus_assert (table->key_type == DBUS_HASH_STRING);
1064 entry = (* table->find_function) (table, (char*) key, FALSE, NULL, NULL);
1067 return entry->value;
1073 * Looks up the value for a given integer in a hash table
1074 * of type #DBUS_HASH_INT. Returns %NULL if the value
1075 * is not present. (A not-present entry is indistinguishable
1076 * from an entry with a value of %NULL.)
1077 * @param table the hash table.
1078 * @param key the integer to look up.
1079 * @returns the value of the hash entry.
1082 _dbus_hash_table_lookup_int (DBusHashTable *table,
1085 DBusHashEntry *entry;
1087 _dbus_assert (table->key_type == DBUS_HASH_INT);
1089 entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, NULL, NULL);
1092 return entry->value;
1097 #ifdef DBUS_BUILD_TESTS
1098 /* disabled since it's only used for testing */
1100 * Looks up the value for a given integer in a hash table
1101 * of type #DBUS_HASH_POINTER. Returns %NULL if the value
1102 * is not present. (A not-present entry is indistinguishable
1103 * from an entry with a value of %NULL.)
1104 * @param table the hash table.
1105 * @param key the integer to look up.
1106 * @returns the value of the hash entry.
1109 _dbus_hash_table_lookup_pointer (DBusHashTable *table,
1112 DBusHashEntry *entry;
1114 _dbus_assert (table->key_type == DBUS_HASH_POINTER);
1116 entry = (* table->find_function) (table, key, FALSE, NULL, NULL);
1119 return entry->value;
1123 #endif /* DBUS_BUILD_TESTS */
1126 * Looks up the value for a given integer in a hash table
1127 * of type #DBUS_HASH_ULONG. Returns %NULL if the value
1128 * is not present. (A not-present entry is indistinguishable
1129 * from an entry with a value of %NULL.)
1130 * @param table the hash table.
1131 * @param key the integer to look up.
1132 * @returns the value of the hash entry.
1135 _dbus_hash_table_lookup_ulong (DBusHashTable *table,
1138 DBusHashEntry *entry;
1140 _dbus_assert (table->key_type == DBUS_HASH_ULONG);
1142 entry = (* table->find_function) (table, (void*) key, FALSE, NULL, NULL);
1145 return entry->value;
1151 * Removes the hash entry for the given key. If no hash entry
1152 * for the key exists, does nothing.
1154 * @param table the hash table.
1155 * @param key the hash key.
1156 * @returns #TRUE if the entry existed
1159 _dbus_hash_table_remove_string (DBusHashTable *table,
1162 DBusHashEntry *entry;
1163 DBusHashEntry **bucket;
1165 _dbus_assert (table->key_type == DBUS_HASH_STRING);
1167 entry = (* table->find_function) (table, (char*) key, FALSE, &bucket, NULL);
1171 remove_entry (table, bucket, entry);
1179 * Removes the hash entry for the given key. If no hash entry
1180 * for the key exists, does nothing.
1182 * @param table the hash table.
1183 * @param key the hash key.
1184 * @returns #TRUE if the entry existed
1187 _dbus_hash_table_remove_int (DBusHashTable *table,
1190 DBusHashEntry *entry;
1191 DBusHashEntry **bucket;
1193 _dbus_assert (table->key_type == DBUS_HASH_INT);
1195 entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, &bucket, NULL);
1199 remove_entry (table, bucket, entry);
1206 #ifdef DBUS_BUILD_TESTS
1207 /* disabled since it's only used for testing */
1209 * Removes the hash entry for the given key. If no hash entry
1210 * for the key exists, does nothing.
1212 * @param table the hash table.
1213 * @param key the hash key.
1214 * @returns #TRUE if the entry existed
1217 _dbus_hash_table_remove_pointer (DBusHashTable *table,
1220 DBusHashEntry *entry;
1221 DBusHashEntry **bucket;
1223 _dbus_assert (table->key_type == DBUS_HASH_POINTER);
1225 entry = (* table->find_function) (table, key, FALSE, &bucket, NULL);
1229 remove_entry (table, bucket, entry);
1235 #endif /* DBUS_BUILD_TESTS */
1238 * Removes the hash entry for the given key. If no hash entry
1239 * for the key exists, does nothing.
1241 * @param table the hash table.
1242 * @param key the hash key.
1243 * @returns #TRUE if the entry existed
1246 _dbus_hash_table_remove_ulong (DBusHashTable *table,
1249 DBusHashEntry *entry;
1250 DBusHashEntry **bucket;
1252 _dbus_assert (table->key_type == DBUS_HASH_ULONG);
1254 entry = (* table->find_function) (table, (void*) key, FALSE, &bucket, NULL);
1258 remove_entry (table, bucket, entry);
1266 * Creates a hash entry with the given key and value.
1267 * The key and value are not copied; they are stored
1268 * in the hash table by reference. If an entry with the
1269 * given key already exists, the previous key and value
1270 * are overwritten (and freed if the hash table has
1271 * a key_free_function and/or value_free_function).
1273 * Returns #FALSE if memory for the new hash entry
1274 * can't be allocated.
1276 * @param table the hash table.
1277 * @param key the hash entry key.
1278 * @param value the hash entry value.
1281 _dbus_hash_table_insert_string (DBusHashTable *table,
1285 DBusPreallocatedHash *preallocated;
1287 _dbus_assert (table->key_type == DBUS_HASH_STRING);
1289 preallocated = _dbus_hash_table_preallocate_entry (table);
1290 if (preallocated == NULL)
1293 _dbus_hash_table_insert_string_preallocated (table, preallocated,
1300 * Creates a hash entry with the given key and value.
1301 * The key and value are not copied; they are stored
1302 * in the hash table by reference. If an entry with the
1303 * given key already exists, the previous key and value
1304 * are overwritten (and freed if the hash table has
1305 * a key_free_function and/or value_free_function).
1307 * Returns #FALSE if memory for the new hash entry
1308 * can't be allocated.
1310 * @param table the hash table.
1311 * @param key the hash entry key.
1312 * @param value the hash entry value.
1315 _dbus_hash_table_insert_int (DBusHashTable *table,
1319 DBusHashEntry *entry;
1321 _dbus_assert (table->key_type == DBUS_HASH_INT);
1323 entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), TRUE, NULL, NULL);
1326 return FALSE; /* no memory */
1328 if (table->free_key_function && entry->key != _DBUS_INT_TO_POINTER (key))
1329 (* table->free_key_function) (entry->key);
1331 if (table->free_value_function && entry->value != value)
1332 (* table->free_value_function) (entry->value);
1334 entry->key = _DBUS_INT_TO_POINTER (key);
1335 entry->value = value;
1340 #ifdef DBUS_BUILD_TESTS
1341 /* disabled since it's only used for testing */
1343 * Creates a hash entry with the given key and value.
1344 * The key and value are not copied; they are stored
1345 * in the hash table by reference. If an entry with the
1346 * given key already exists, the previous key and value
1347 * are overwritten (and freed if the hash table has
1348 * a key_free_function and/or value_free_function).
1350 * Returns #FALSE if memory for the new hash entry
1351 * can't be allocated.
1353 * @param table the hash table.
1354 * @param key the hash entry key.
1355 * @param value the hash entry value.
1358 _dbus_hash_table_insert_pointer (DBusHashTable *table,
1362 DBusHashEntry *entry;
1364 _dbus_assert (table->key_type == DBUS_HASH_POINTER);
1366 entry = (* table->find_function) (table, key, TRUE, NULL, NULL);
1369 return FALSE; /* no memory */
1371 if (table->free_key_function && entry->key != key)
1372 (* table->free_key_function) (entry->key);
1374 if (table->free_value_function && entry->value != value)
1375 (* table->free_value_function) (entry->value);
1378 entry->value = value;
1382 #endif /* DBUS_BUILD_TESTS */
1385 * Creates a hash entry with the given key and value.
1386 * The key and value are not copied; they are stored
1387 * in the hash table by reference. If an entry with the
1388 * given key already exists, the previous key and value
1389 * are overwritten (and freed if the hash table has
1390 * a key_free_function and/or value_free_function).
1392 * Returns #FALSE if memory for the new hash entry
1393 * can't be allocated.
1395 * @param table the hash table.
1396 * @param key the hash entry key.
1397 * @param value the hash entry value.
1400 _dbus_hash_table_insert_ulong (DBusHashTable *table,
1404 DBusHashEntry *entry;
1406 _dbus_assert (table->key_type == DBUS_HASH_ULONG);
1408 entry = (* table->find_function) (table, (void*) key, TRUE, NULL, NULL);
1411 return FALSE; /* no memory */
1413 if (table->free_key_function && entry->key != (void*) key)
1414 (* table->free_key_function) (entry->key);
1416 if (table->free_value_function && entry->value != value)
1417 (* table->free_value_function) (entry->value);
1419 entry->key = (void*) key;
1420 entry->value = value;
1426 * Preallocate an opaque data blob that allows us to insert into the
1427 * hash table at a later time without allocating any memory.
1429 * @param table the hash table
1430 * @returns the preallocated data, or #NULL if no memory
1432 DBusPreallocatedHash*
1433 _dbus_hash_table_preallocate_entry (DBusHashTable *table)
1435 DBusHashEntry *entry;
1437 entry = alloc_entry (table);
1439 return (DBusPreallocatedHash*) entry;
1443 * Frees an opaque DBusPreallocatedHash that was *not* used
1444 * in order to insert into the hash table.
1446 * @param table the hash table
1447 * @param preallocated the preallocated data
1450 _dbus_hash_table_free_preallocated_entry (DBusHashTable *table,
1451 DBusPreallocatedHash *preallocated)
1453 DBusHashEntry *entry;
1455 _dbus_assert (preallocated != NULL);
1457 entry = (DBusHashEntry*) preallocated;
1459 /* Don't use free_entry(), since this entry has no key/data */
1460 _dbus_mem_pool_dealloc (table->entry_pool, entry);
1464 * Inserts a string-keyed entry into the hash table, using a
1465 * preallocated data block from
1466 * _dbus_hash_table_preallocate_entry(). This function cannot fail due
1467 * to lack of memory. The DBusPreallocatedHash object is consumed and
1468 * should not be reused or freed. Otherwise this function works
1469 * just like _dbus_hash_table_insert_string().
1471 * @param table the hash table
1472 * @param preallocated the preallocated data
1473 * @param key the hash key
1474 * @param value the value
1477 _dbus_hash_table_insert_string_preallocated (DBusHashTable *table,
1478 DBusPreallocatedHash *preallocated,
1482 DBusHashEntry *entry;
1484 _dbus_assert (table->key_type == DBUS_HASH_STRING);
1485 _dbus_assert (preallocated != NULL);
1487 entry = (* table->find_function) (table, key, TRUE, NULL, preallocated);
1489 _dbus_assert (entry != NULL);
1491 if (table->free_key_function && entry->key != key)
1492 (* table->free_key_function) (entry->key);
1494 if (table->free_value_function && entry->value != value)
1495 (* table->free_value_function) (entry->value);
1498 entry->value = value;
1502 * Gets the number of hash entries in a hash table.
1504 * @param table the hash table.
1505 * @returns the number of entries in the table.
1508 _dbus_hash_table_get_n_entries (DBusHashTable *table)
1510 return table->n_entries;
1515 #ifdef DBUS_BUILD_TESTS
1516 #include "dbus-test.h"
1519 /* If you're wondering why the hash table test takes
1520 * forever to run, it's because we call this function
1521 * in inner loops thus making things quadratic.
1524 count_entries (DBusHashTable *table)
1530 _dbus_hash_iter_init (table, &iter);
1531 while (_dbus_hash_iter_next (&iter))
1534 _dbus_assert (count == _dbus_hash_table_get_n_entries (table));
1540 * @ingroup DBusHashTableInternals
1541 * Unit test for DBusHashTable
1542 * @returns #TRUE on success.
1545 _dbus_hash_test (void)
1548 DBusHashTable *table1;
1549 DBusHashTable *table2;
1550 DBusHashTable *table3;
1552 #define N_HASH_KEYS 5000
1554 dbus_bool_t ret = FALSE;
1556 keys = dbus_new (char *, N_HASH_KEYS);
1558 _dbus_assert_not_reached ("no memory");
1560 for (i = 0; i < N_HASH_KEYS; i++)
1562 keys[i] = dbus_malloc (128);
1564 if (keys[i] == NULL)
1565 _dbus_assert_not_reached ("no memory");
1568 printf ("Computing test hash keys...\n");
1570 while (i < N_HASH_KEYS)
1572 sprintf (keys[i], "Hash key %d", i);
1575 printf ("... done.\n");
1577 table1 = _dbus_hash_table_new (DBUS_HASH_STRING,
1578 dbus_free, dbus_free);
1582 table2 = _dbus_hash_table_new (DBUS_HASH_INT,
1587 table3 = _dbus_hash_table_new (DBUS_HASH_ULONG,
1592 /* Insert and remove a bunch of stuff, counting the table in between
1593 * to be sure it's not broken and that iteration works
1601 key = _dbus_strdup (keys[i]);
1604 value = _dbus_strdup ("Value!");
1608 if (!_dbus_hash_table_insert_string (table1,
1612 value = _dbus_strdup (keys[i]);
1616 if (!_dbus_hash_table_insert_int (table2,
1620 value = _dbus_strdup (keys[i]);
1624 if (!_dbus_hash_table_insert_ulong (table3,
1628 _dbus_assert (count_entries (table1) == i + 1);
1629 _dbus_assert (count_entries (table2) == i + 1);
1630 _dbus_assert (count_entries (table3) == i + 1);
1632 value = _dbus_hash_table_lookup_string (table1, keys[i]);
1633 _dbus_assert (value != NULL);
1634 _dbus_assert (strcmp (value, "Value!") == 0);
1636 value = _dbus_hash_table_lookup_int (table2, i);
1637 _dbus_assert (value != NULL);
1638 _dbus_assert (strcmp (value, keys[i]) == 0);
1640 value = _dbus_hash_table_lookup_ulong (table3, i);
1641 _dbus_assert (value != NULL);
1642 _dbus_assert (strcmp (value, keys[i]) == 0);
1650 _dbus_hash_table_remove_string (table1,
1653 _dbus_hash_table_remove_int (table2, i);
1655 _dbus_hash_table_remove_ulong (table3, i);
1657 _dbus_assert (count_entries (table1) == i);
1658 _dbus_assert (count_entries (table2) == i);
1659 _dbus_assert (count_entries (table3) == i);
1664 _dbus_hash_table_ref (table1);
1665 _dbus_hash_table_ref (table2);
1666 _dbus_hash_table_ref (table3);
1667 _dbus_hash_table_unref (table1);
1668 _dbus_hash_table_unref (table2);
1669 _dbus_hash_table_unref (table3);
1670 _dbus_hash_table_unref (table1);
1671 _dbus_hash_table_unref (table2);
1672 _dbus_hash_table_unref (table3);
1675 /* Insert a bunch of stuff then check
1676 * that iteration works correctly (finds the right
1677 * values, iter_set_value works, etc.)
1679 table1 = _dbus_hash_table_new (DBUS_HASH_STRING,
1680 dbus_free, dbus_free);
1684 table2 = _dbus_hash_table_new (DBUS_HASH_INT,
1695 key = _dbus_strdup (keys[i]);
1698 value = _dbus_strdup ("Value!");
1702 if (!_dbus_hash_table_insert_string (table1,
1706 value = _dbus_strdup (keys[i]);
1710 if (!_dbus_hash_table_insert_int (table2,
1714 _dbus_assert (count_entries (table1) == i + 1);
1715 _dbus_assert (count_entries (table2) == i + 1);
1720 _dbus_hash_iter_init (table1, &iter);
1721 while (_dbus_hash_iter_next (&iter))
1726 key = _dbus_hash_iter_get_string_key (&iter);
1727 value = _dbus_hash_iter_get_value (&iter);
1729 _dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value);
1731 value = _dbus_strdup ("Different value!");
1735 _dbus_hash_iter_set_value (&iter, value);
1737 _dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value);
1740 _dbus_hash_iter_init (table1, &iter);
1741 while (_dbus_hash_iter_next (&iter))
1743 _dbus_hash_iter_remove_entry (&iter);
1744 _dbus_assert (count_entries (table1) == i - 1);
1748 _dbus_hash_iter_init (table2, &iter);
1749 while (_dbus_hash_iter_next (&iter))
1754 key = _dbus_hash_iter_get_int_key (&iter);
1755 value = _dbus_hash_iter_get_value (&iter);
1757 _dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value);
1759 value = _dbus_strdup ("Different value!");
1763 _dbus_hash_iter_set_value (&iter, value);
1765 _dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value);
1768 i = count_entries (table2);
1769 _dbus_hash_iter_init (table2, &iter);
1770 while (_dbus_hash_iter_next (&iter))
1772 _dbus_hash_iter_remove_entry (&iter);
1773 _dbus_assert (count_entries (table2) + 1 == i);
1777 /* add/remove interleaved, to check that we grow/shrink the table
1786 key = _dbus_strdup (keys[i]);
1790 value = _dbus_strdup ("Value!");
1794 if (!_dbus_hash_table_insert_string (table1,
1807 key = _dbus_strdup (keys[i]);
1810 value = _dbus_strdup ("Value!");
1814 if (!_dbus_hash_table_remove_string (table1, keys[i]))
1817 if (!_dbus_hash_table_insert_string (table1,
1821 if (!_dbus_hash_table_remove_string (table1, keys[i]))
1824 _dbus_assert (_dbus_hash_table_get_n_entries (table1) == i);
1829 /* nuke these tables */
1830 _dbus_hash_table_unref (table1);
1831 _dbus_hash_table_unref (table2);
1834 /* Now do a bunch of things again using _dbus_hash_iter_lookup() to
1835 * be sure that interface works.
1837 table1 = _dbus_hash_table_new (DBUS_HASH_STRING,
1838 dbus_free, dbus_free);
1842 table2 = _dbus_hash_table_new (DBUS_HASH_INT,
1853 key = _dbus_strdup (keys[i]);
1856 value = _dbus_strdup ("Value!");
1860 if (!_dbus_hash_iter_lookup (table1,
1863 _dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL);
1864 _dbus_hash_iter_set_value (&iter, value);
1866 value = _dbus_strdup (keys[i]);
1870 if (!_dbus_hash_iter_lookup (table2,
1871 _DBUS_INT_TO_POINTER (i), TRUE, &iter))
1873 _dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL);
1874 _dbus_hash_iter_set_value (&iter, value);
1876 _dbus_assert (count_entries (table1) == i + 1);
1877 _dbus_assert (count_entries (table2) == i + 1);
1879 if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter))
1882 value = _dbus_hash_iter_get_value (&iter);
1883 _dbus_assert (value != NULL);
1884 _dbus_assert (strcmp (value, "Value!") == 0);
1886 /* Iterate just to be sure it works, though
1887 * it's a stupid thing to do
1889 while (_dbus_hash_iter_next (&iter))
1892 if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter))
1895 value = _dbus_hash_iter_get_value (&iter);
1896 _dbus_assert (value != NULL);
1897 _dbus_assert (strcmp (value, keys[i]) == 0);
1899 /* Iterate just to be sure it works, though
1900 * it's a stupid thing to do
1902 while (_dbus_hash_iter_next (&iter))
1911 if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter))
1912 _dbus_assert_not_reached ("hash entry should have existed");
1913 _dbus_hash_iter_remove_entry (&iter);
1915 if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter))
1916 _dbus_assert_not_reached ("hash entry should have existed");
1917 _dbus_hash_iter_remove_entry (&iter);
1919 _dbus_assert (count_entries (table1) == i);
1920 _dbus_assert (count_entries (table2) == i);
1925 _dbus_hash_table_unref (table1);
1926 _dbus_hash_table_unref (table2);
1931 for (i = 0; i < N_HASH_KEYS; i++)
1932 dbus_free (keys[i]);
1939 #endif /* DBUS_BUILD_TESTS */