1 /* -*- mode: C; c-file-style: "gnu" -*- */ 2 /* dbus-hash.c Generic hash table utility (internal to D-Bus implementation) 3 * 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. 7 * 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. 12 * 13 * Licensed under the Academic Free License version 2.1 14 * 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. 19 * 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. 24 * 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 28 * 29 */ 30 /* 31 * The following copyright applies to code from the Tcl distribution. 32 * 33 * Copyright (c) 1991-1993 The Regents of the University of California. 34 * Copyright (c) 1994 Sun Microsystems, Inc. 35 * 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. 40 * 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. 50 * 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. 56 * 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. 63 * 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. 75 */ 76 77 #include "dbus-hash.h" 78 #include "dbus-internals.h" 79 #include "dbus-mempool.h" 80 81 /** 82 * @defgroup DBusHashTable Hash table 83 * @ingroup DBusInternals 84 * @brief DBusHashTable data structure 85 * 86 * Types and functions related to DBusHashTable. 87 */ 88 89 /** 90 * @defgroup DBusHashTableInternals Hash table implementation details 91 * @ingroup DBusInternals 92 * @brief DBusHashTable implementation details 93 * 94 * The guts of DBusHashTable. 95 * 96 * @{ 97 */ 98 99 /** 100 * When there are this many entries per bucket, on average, rebuild 101 * the hash table to make it larger. 102 */ 103 #define REBUILD_MULTIPLIER 3 104 105 /** 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.) 111 * 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? 119 * 120 */ 121 #define RANDOM_INDEX(table, i) \ 122 (((((long) (i))*1103515245) >> (table)->down_shift) & (table)->mask) 123 124 /** 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. 128 */ 129 #define DBUS_SMALL_HASH_TABLE 4 130 131 /** 132 * Typedef for DBusHashEntry 133 */ 134 typedef struct DBusHashEntry DBusHashEntry; 135 136 /** 137 * @brief Internal representation of a hash entry. 138 * 139 * A single entry (key-value pair) in the hash table. 140 * Internal to hash table implementation. 141 */ 142 struct DBusHashEntry 143 { 144 DBusHashEntry *next; /**< Pointer to next entry in this 145 * hash bucket, or #NULL for end of 146 * chain. 147 */ 148 void *key; /**< Hash key */ 149 void *value; /**< Hash value */ 150 }; 151 152 /** 153 * Function used to find and optionally create a hash entry. 154 */ 155 typedef DBusHashEntry* (* DBusFindEntryFunction) (DBusHashTable *table, 156 void *key, 157 dbus_bool_t create_if_not_found, 158 DBusHashEntry ***bucket, 159 DBusPreallocatedHash *preallocated); 160 161 /** 162 * @brief Internals of DBusHashTable. 163 * 164 * Hash table internals. Hash tables are opaque objects, they must be 165 * used via accessor functions. 166 */ 167 struct DBusHashTable { 168 int refcount; /**< Reference count */ 169 170 DBusHashEntry **buckets; /**< Pointer to bucket array. Each 171 * element points to first entry in 172 * bucket's hash chain, or #NULL. 173 */ 174 DBusHashEntry *static_buckets[DBUS_SMALL_HASH_TABLE]; 175 /**< Bucket array used for small tables 176 * (to avoid mallocs and frees). 177 */ 178 int n_buckets; /**< Total number of buckets allocated 179 * at **buckets. 180 */ 181 int n_entries; /**< Total number of entries present 182 * in table. 183 */ 184 int hi_rebuild_size; /**< Enlarge table when n_entries gets 185 * to be this large. 186 */ 187 int lo_rebuild_size; /**< Shrink table when n_entries gets 188 * below this. 189 */ 190 int down_shift; /**< Shift count used in hashing 191 * function. Designed to use high- 192 * order bits of randomized keys. 193 */ 194 int mask; /**< Mask value used in hashing 195 * function. 196 */ 197 DBusHashType key_type; /**< Type of keys used in this table */ 198 199 200 DBusFindEntryFunction find_function; /**< Function for finding entries */ 201 202 DBusFreeFunction free_key_function; /**< Function to free keys */ 203 DBusFreeFunction free_value_function; /**< Function to free values */ 204 205 DBusMemPool *entry_pool; /**< Memory pool for hash entries */ 206 }; 207 208 /** 209 * @brief Internals of DBusHashIter. 210 */ 211 typedef struct 212 { 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. 217 */ 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 */ 222 } DBusRealHashIter; 223 224 static DBusHashEntry* find_direct_function (DBusHashTable *table, 225 void *key, 226 dbus_bool_t create_if_not_found, 227 DBusHashEntry ***bucket, 228 DBusPreallocatedHash *preallocated); 229 static DBusHashEntry* find_string_function (DBusHashTable *table, 230 void *key, 231 dbus_bool_t create_if_not_found, 232 DBusHashEntry ***bucket, 233 DBusPreallocatedHash *preallocated); 234 #ifdef DBUS_BUILD_TESTS 235 static DBusHashEntry* find_two_strings_function (DBusHashTable *table, 236 void *key, 237 dbus_bool_t create_if_not_found, 238 DBusHashEntry ***bucket, 239 DBusPreallocatedHash *preallocated); 240 #endif 241 static unsigned int string_hash (const char *str); 242 #ifdef DBUS_BUILD_TESTS 243 static unsigned int two_strings_hash (const char *str); 244 #endif 245 static void rebuild_table (DBusHashTable *table); 246 static DBusHashEntry* alloc_entry (DBusHashTable *table); 247 static void remove_entry (DBusHashTable *table, 248 DBusHashEntry **bucket, 249 DBusHashEntry *entry); 250 static void free_entry (DBusHashTable *table, 251 DBusHashEntry *entry); 252 static void free_entry_data (DBusHashTable *table, 253 DBusHashEntry *entry); 254 255 256 /** @} */ 257 258 /** 259 * @addtogroup DBusHashTable 260 * @{ 261 */ 262 263 /** 264 * @typedef DBusHashIter 265 * 266 * Public opaque hash table iterator object. 267 */ 268 269 /** 270 * @typedef DBusHashTable 271 * 272 * Public opaque hash table object. 273 */ 274 275 /** 276 * @typedef DBusHashType 277 * 278 * Indicates the type of a key in the hash table. 279 */ 280 281 /** 282 * Constructs a new hash table. Should be freed with 283 * _dbus_hash_table_unref(). If memory cannot be 284 * allocated for the hash table, returns #NULL. 285 * 286 * @param type the type of hash key to use. 287 * @param key_free_function function to free hash keys. 288 * @param value_free_function function to free hash values. 289 * @returns a new DBusHashTable or #NULL if no memory. 290 */ 291 DBusHashTable* 292 _dbus_hash_table_new (DBusHashType type, 293 DBusFreeFunction key_free_function, 294 DBusFreeFunction value_free_function) 295 { 296 DBusHashTable *table; 297 DBusMemPool *entry_pool; 298 299 table = dbus_new0 (DBusHashTable, 1); 300 if (table == NULL) 301 return NULL; 302 303 entry_pool = _dbus_mem_pool_new (sizeof (DBusHashEntry), TRUE); 304 if (entry_pool == NULL) 305 { 306 dbus_free (table); 307 return NULL; 308 } 309 310 table->refcount = 1; 311 table->entry_pool = entry_pool; 312 313 _dbus_assert (DBUS_SMALL_HASH_TABLE == _DBUS_N_ELEMENTS (table->static_buckets)); 314 315 table->buckets = table->static_buckets; 316 table->n_buckets = DBUS_SMALL_HASH_TABLE; 317 table->n_entries = 0; 318 table->hi_rebuild_size = DBUS_SMALL_HASH_TABLE * REBUILD_MULTIPLIER; 319 table->lo_rebuild_size = 0; 320 table->down_shift = 28; 321 table->mask = 3; 322 table->key_type = type; 323 324 _dbus_assert (table->mask < table->n_buckets); 325 326 switch (table->key_type) 327 { 328 case DBUS_HASH_INT: 329 case DBUS_HASH_POINTER: 330 case DBUS_HASH_ULONG: 331 table->find_function = find_direct_function; 332 break; 333 case DBUS_HASH_STRING: 334 table->find_function = find_string_function; 335 break; 336 case DBUS_HASH_TWO_STRINGS: 337 #ifdef DBUS_BUILD_TESTS 338 table->find_function = find_two_strings_function; 339 #endif 340 break; 341 default: 342 _dbus_assert_not_reached ("Unknown hash table type"); 343 break; 344 } 345 346 table->free_key_function = key_free_function; 347 table->free_value_function = value_free_function; 348 349 return table; 350 } 351 352 353 /** 354 * Increments the reference count for a hash table. 355 * 356 * @param table the hash table to add a reference to. 357 * @returns the hash table. 358 */ 359 DBusHashTable * 360 _dbus_hash_table_ref (DBusHashTable *table) 361 { 362 table->refcount += 1; 363 364 return table; 365 } 366 367 /** 368 * Decrements the reference count for a hash table, 369 * freeing the hash table if the count reaches zero. 370 * 371 * @param table the hash table to remove a reference from. 372 */ 373 void 374 _dbus_hash_table_unref (DBusHashTable *table) 375 { 376 table->refcount -= 1; 377 378 if (table->refcount == 0) 379 { 380 #if 0 381 DBusHashEntry *entry; 382 DBusHashEntry *next; 383 int i; 384 385 /* Free the entries in the table. */ 386 for (i = 0; i < table->n_buckets; i++) 387 { 388 entry = table->buckets[i]; 389 while (entry != NULL) 390 { 391 next = entry->next; 392 393 free_entry (table, entry); 394 395 entry = next; 396 } 397 } 398 #else 399 DBusHashEntry *entry; 400 int i; 401 402 /* Free the entries in the table. */ 403 for (i = 0; i < table->n_buckets; i++) 404 { 405 entry = table->buckets[i]; 406 while (entry != NULL) 407 { 408 free_entry_data (table, entry); 409 410 entry = entry->next; 411 } 412 } 413 /* We can do this very quickly with memory pools ;-) */ 414 _dbus_mem_pool_free (table->entry_pool); 415 #endif 416 417 /* Free the bucket array, if it was dynamically allocated. */ 418 if (table->buckets != table->static_buckets) 419 dbus_free (table->buckets); 420 421 dbus_free (table); 422 } 423 } 424 425 /** 426 * Removed all entries from a hash table. 427 * 428 * @param table the hash table to remove all entries from. 429 */ 430 void 431 _dbus_hash_table_remove_all (DBusHashTable *table) 432 { 433 DBusHashIter iter; 434 _dbus_hash_iter_init (table, &iter); 435 while (_dbus_hash_iter_next (&iter)) 436 { 437 _dbus_hash_iter_remove_entry(&iter); 438 } 439 } 440 441 static DBusHashEntry* 442 alloc_entry (DBusHashTable *table) 443 { 444 DBusHashEntry *entry; 445 446 entry = _dbus_mem_pool_alloc (table->entry_pool); 447 448 return entry; 449 } 450 451 static void 452 free_entry_data (DBusHashTable *table, 453 DBusHashEntry *entry) 454 { 455 if (table->free_key_function) 456 (* table->free_key_function) (entry->key); 457 if (table->free_value_function) 458 (* table->free_value_function) (entry->value); 459 } 460 461 static void 462 free_entry (DBusHashTable *table, 463 DBusHashEntry *entry) 464 { 465 free_entry_data (table, entry); 466 _dbus_mem_pool_dealloc (table->entry_pool, entry); 467 } 468 469 static void 470 remove_entry (DBusHashTable *table, 471 DBusHashEntry **bucket, 472 DBusHashEntry *entry) 473 { 474 _dbus_assert (table != NULL); 475 _dbus_assert (bucket != NULL); 476 _dbus_assert (*bucket != NULL); 477 _dbus_assert (entry != NULL); 478 479 if (*bucket == entry) 480 *bucket = entry->next; 481 else 482 { 483 DBusHashEntry *prev; 484 prev = *bucket; 485 486 while (prev->next != entry) 487 prev = prev->next; 488 489 _dbus_assert (prev != NULL); 490 491 prev->next = entry->next; 492 } 493 494 table->n_entries -= 1; 495 free_entry (table, entry); 496 } 497 498 /** 499 * Initializes a hash table iterator. To iterate over all entries in a 500 * hash table, use the following code (the printf assumes a hash 501 * from strings to strings obviously): 502 * 503 * @code 504 * DBusHashIter iter; 505 * 506 * _dbus_hash_iter_init (table, &iter); 507 * while (_dbus_hash_iter_next (&iter)) 508 * { 509 * printf ("The first key is %s and value is %s\n", 510 * _dbus_hash_iter_get_string_key (&iter), 511 * _dbus_hash_iter_get_value (&iter)); 512 * } 513 * 514 * 515 * @endcode 516 * 517 * The iterator is initialized pointing "one before" the first hash 518 * entry. The first call to _dbus_hash_iter_next() moves it onto 519 * the first valid entry or returns #FALSE if the hash table is 520 * empty. Subsequent calls move to the next valid entry or return 521 * #FALSE if there are no more entries. 522 * 523 * Note that it is guaranteed to be safe to remove a hash entry during 524 * iteration, but it is not safe to add a hash entry. 525 * 526 * @param table the hash table to iterate over. 527 * @param iter the iterator to initialize. 528 */ 529 void 530 _dbus_hash_iter_init (DBusHashTable *table, 531 DBusHashIter *iter) 532 { 533 DBusRealHashIter *real; 534 535 _dbus_assert (sizeof (DBusHashIter) == sizeof (DBusRealHashIter)); 536 537 real = (DBusRealHashIter*) iter; 538 539 real->table = table; 540 real->bucket = NULL; 541 real->entry = NULL; 542 real->next_entry = NULL; 543 real->next_bucket = 0; 544 real->n_entries_on_init = table->n_entries; 545 } 546 547 /** 548 * Move the hash iterator forward one step, to the next hash entry. 549 * The documentation for _dbus_hash_iter_init() explains in more 550 * detail. 551 * 552 * @param iter the iterator to move forward. 553 * @returns #FALSE if there are no more entries to move to. 554 */ 555 dbus_bool_t 556 _dbus_hash_iter_next (DBusHashIter *iter) 557 { 558 DBusRealHashIter *real; 559 560 _dbus_assert (sizeof (DBusHashIter) == sizeof (DBusRealHashIter)); 561 562 real = (DBusRealHashIter*) iter; 563 564 /* if this assertion failed someone probably added hash entries 565 * during iteration, which is bad. 566 */ 567 _dbus_assert (real->n_entries_on_init >= real->table->n_entries); 568 569 /* Remember that real->entry may have been deleted */ 570 571 while (real->next_entry == NULL) 572 { 573 if (real->next_bucket >= real->table->n_buckets) 574 { 575 /* invalidate iter and return false */ 576 real->entry = NULL; 577 real->table = NULL; 578 real->bucket = NULL; 579 return FALSE; 580 } 581 582 real->bucket = &(real->table->buckets[real->next_bucket]); 583 real->next_entry = *(real->bucket); 584 real->next_bucket += 1; 585 } 586 587 _dbus_assert (real->next_entry != NULL); 588 _dbus_assert (real->bucket != NULL); 589 590 real->entry = real->next_entry; 591 real->next_entry = real->entry->next; 592 593 return TRUE; 594 } 595 596 /** 597 * Removes the current entry from the hash table. 598 * If a key_free_function or value_free_function 599 * was provided to _dbus_hash_table_new(), 600 * frees the key and/or value for this entry. 601 * 602 * @param iter the hash table iterator. 603 */ 604 void 605 _dbus_hash_iter_remove_entry (DBusHashIter *iter) 606 { 607 DBusRealHashIter *real; 608 609 real = (DBusRealHashIter*) iter; 610 611 _dbus_assert (real->table != NULL); 612 _dbus_assert (real->entry != NULL); 613 _dbus_assert (real->bucket != NULL); 614 615 remove_entry (real->table, real->bucket, real->entry); 616 617 real->entry = NULL; /* make it crash if you try to use this entry */ 618 } 619 620 /** 621 * Gets the value of the current entry. 622 * 623 * @param iter the hash table iterator. 624 */ 625 void* 626 _dbus_hash_iter_get_value (DBusHashIter *iter) 627 { 628 DBusRealHashIter *real; 629 630 real = (DBusRealHashIter*) iter; 631 632 _dbus_assert (real->table != NULL); 633 _dbus_assert (real->entry != NULL); 634 635 return real->entry->value; 636 } 637 638 /** 639 * Sets the value of the current entry. 640 * If the hash table has a value_free_function 641 * it will be used to free the previous value. 642 * The hash table will own the passed-in value 643 * (it will not be copied). 644 * 645 * @param iter the hash table iterator. 646 * @param value the new value. 647 */ 648 void 649 _dbus_hash_iter_set_value (DBusHashIter *iter, 650 void *value) 651 { 652 DBusRealHashIter *real; 653 654 real = (DBusRealHashIter*) iter; 655 656 _dbus_assert (real->table != NULL); 657 _dbus_assert (real->entry != NULL); 658 659 if (real->table->free_value_function && value != real->entry->value) 660 (* real->table->free_value_function) (real->entry->value); 661 662 real->entry->value = value; 663 } 664 665 /** 666 * Gets the key for the current entry. 667 * Only works for hash tables of type #DBUS_HASH_INT. 668 * 669 * @param iter the hash table iterator. 670 */ 671 int 672 _dbus_hash_iter_get_int_key (DBusHashIter *iter) 673 { 674 DBusRealHashIter *real; 675 676 real = (DBusRealHashIter*) iter; 677 678 _dbus_assert (real->table != NULL); 679 _dbus_assert (real->entry != NULL); 680 681 return _DBUS_POINTER_TO_INT (real->entry->key); 682 } 683 684 /** 685 * Gets the key for the current entry. 686 * Only works for hash tables of type #DBUS_HASH_ULONG. 687 * 688 * @param iter the hash table iterator. 689 */ 690 unsigned long 691 _dbus_hash_iter_get_ulong_key (DBusHashIter *iter) 692 { 693 DBusRealHashIter *real; 694 695 real = (DBusRealHashIter*) iter; 696 697 _dbus_assert (real->table != NULL); 698 _dbus_assert (real->entry != NULL); 699 700 return (unsigned long) real->entry->key; 701 } 702 703 /** 704 * Gets the key for the current entry. 705 * Only works for hash tables of type #DBUS_HASH_STRING 706 * @param iter the hash table iterator. 707 */ 708 const char* 709 _dbus_hash_iter_get_string_key (DBusHashIter *iter) 710 { 711 DBusRealHashIter *real; 712 713 real = (DBusRealHashIter*) iter; 714 715 _dbus_assert (real->table != NULL); 716 _dbus_assert (real->entry != NULL); 717 718 return real->entry->key; 719 } 720 721 #ifdef DBUS_BUILD_TESTS 722 /** 723 * Gets the key for the current entry. 724 * Only works for hash tables of type #DBUS_HASH_TWO_STRINGS 725 * @param iter the hash table iterator. 726 */ 727 const char* 728 _dbus_hash_iter_get_two_strings_key (DBusHashIter *iter) 729 { 730 DBusRealHashIter *real; 731 732 real = (DBusRealHashIter*) iter; 733 734 _dbus_assert (real->table != NULL); 735 _dbus_assert (real->entry != NULL); 736 737 return real->entry->key; 738 } 739 #endif /* DBUS_BUILD_TESTS */ 740 741 /** 742 * A low-level but efficient interface for manipulating the hash 743 * table. It's efficient because you can get, set, and optionally 744 * create the hash entry while only running the hash function one 745 * time. 746 * 747 * Note that while calling _dbus_hash_iter_next() on the iterator 748 * filled in by this function may work, it's completely 749 * undefined which entries are after this iter and which 750 * are before it. So it would be silly to iterate using this 751 * iterator. 752 * 753 * If the hash entry is created, its value will be initialized 754 * to all bits zero. 755 * 756 * #FALSE may be returned due to memory allocation failure, or 757 * because create_if_not_found was #FALSE and the entry 758 * did not exist. 759 * 760 * If create_if_not_found is #TRUE and the entry is created, the hash 761 * table takes ownership of the key that's passed in. 762 * 763 * For a hash table of type #DBUS_HASH_INT, cast the int 764 * key to the key parameter using #_DBUS_INT_TO_POINTER(). 765 * 766 * @param table the hash table. 767 * @param key the hash key. 768 * @param create_if_not_found if #TRUE, create the entry if it didn't exist. 769 * @param iter the iterator to initialize. 770 * @returns #TRUE if the hash entry now exists (and the iterator is thus valid). 771 */ 772 dbus_bool_t 773 _dbus_hash_iter_lookup (DBusHashTable *table, 774 void *key, 775 dbus_bool_t create_if_not_found, 776 DBusHashIter *iter) 777 { 778 DBusRealHashIter *real; 779 DBusHashEntry *entry; 780 DBusHashEntry **bucket; 781 782 _dbus_assert (sizeof (DBusHashIter) == sizeof (DBusRealHashIter)); 783 784 real = (DBusRealHashIter*) iter; 785 786 entry = (* table->find_function) (table, key, create_if_not_found, &bucket, NULL); 787 788 if (entry == NULL) 789 return FALSE; 790 791 real->table = table; 792 real->bucket = bucket; 793 real->entry = entry; 794 real->next_entry = entry->next; 795 real->next_bucket = (bucket - table->buckets) + 1; 796 real->n_entries_on_init = table->n_entries; 797 798 _dbus_assert (&(table->buckets[real->next_bucket-1]) == real->bucket); 799 800 return TRUE; 801 } 802 803 static void 804 add_allocated_entry (DBusHashTable *table, 805 DBusHashEntry *entry, 806 unsigned int idx, 807 void *key, 808 DBusHashEntry ***bucket) 809 { 810 DBusHashEntry **b; 811 812 entry->key = key; 813 814 b = &(table->buckets[idx]); 815 entry->next = *b; 816 *b = entry; 817 818 if (bucket) 819 *bucket = b; 820 821 table->n_entries += 1; 822 823 /* note we ONLY rebuild when ADDING - because you can iterate over a 824 * table and remove entries safely. 825 */ 826 if (table->n_entries >= table->hi_rebuild_size || 827 table->n_entries < table->lo_rebuild_size) 828 rebuild_table (table); 829 } 830 831 static DBusHashEntry* 832 add_entry (DBusHashTable *table, 833 unsigned int idx, 834 void *key, 835 DBusHashEntry ***bucket, 836 DBusPreallocatedHash *preallocated) 837 { 838 DBusHashEntry *entry; 839 840 if (preallocated == NULL) 841 { 842 entry = alloc_entry (table); 843 if (entry == NULL) 844 { 845 if (bucket) 846 *bucket = NULL; 847 return NULL; 848 } 849 } 850 else 851 { 852 entry = (DBusHashEntry*) preallocated; 853 } 854 855 add_allocated_entry (table, entry, idx, key, bucket); 856 857 return entry; 858 } 859 860 /* This is g_str_hash from GLib which was 861 * extensively discussed/tested/profiled 862 */ 863 static unsigned int 864 string_hash (const char *str) 865 { 866 const char *p = str; 867 unsigned int h = *p; 868 869 if (h) 870 for (p += 1; *p != '\0'; p++) 871 h = (h << 5) - h + *p; 872 873 return h; 874 } 875 876 #ifdef DBUS_BUILD_TESTS 877 /* This hashes a memory block with two nul-terminated strings 878 * in it, used in dbus-object-registry.c at the moment. 879 */ 880 static unsigned int 881 two_strings_hash (const char *str) 882 { 883 const char *p = str; 884 unsigned int h = *p; 885 886 if (h) 887 for (p += 1; *p != '\0'; p++) 888 h = (h << 5) - h + *p; 889 890 for (p += 1; *p != '\0'; p++) 891 h = (h << 5) - h + *p; 892 893 return h; 894 } 895 #endif /* DBUS_BUILD_TESTS */ 896 897 /** Key comparison function */ 898 typedef int (* KeyCompareFunc) (const void *key_a, const void *key_b); 899 900 static DBusHashEntry* 901 find_generic_function (DBusHashTable *table, 902 void *key, 903 unsigned int idx, 904 KeyCompareFunc compare_func, 905 dbus_bool_t create_if_not_found, 906 DBusHashEntry ***bucket, 907 DBusPreallocatedHash *preallocated) 908 { 909 DBusHashEntry *entry; 910 911 if (bucket) 912 *bucket = NULL; 913 914 /* Search all of the entries in this bucket. */ 915 entry = table->buckets[idx]; 916 while (entry != NULL) 917 { 918 if ((compare_func == NULL && key == entry->key) || 919 (compare_func != NULL && (* compare_func) (key, entry->key) == 0)) 920 { 921 if (bucket) 922 *bucket = &(table->buckets[idx]); 923 924 if (preallocated) 925 _dbus_hash_table_free_preallocated_entry (table, preallocated); 926 927 return entry; 928 } 929 930 entry = entry->next; 931 } 932 933 if (create_if_not_found) 934 entry = add_entry (table, idx, key, bucket, preallocated); 935 else if (preallocated) 936 _dbus_hash_table_free_preallocated_entry (table, preallocated); 937 938 return entry; 939 } 940 941 static DBusHashEntry* 942 find_string_function (DBusHashTable *table, 943 void *key, 944 dbus_bool_t create_if_not_found, 945 DBusHashEntry ***bucket, 946 DBusPreallocatedHash *preallocated) 947 { 948 unsigned int idx; 949 950 idx = string_hash (key) & table->mask; 951 952 return find_generic_function (table, key, idx, 953 (KeyCompareFunc) strcmp, create_if_not_found, bucket, 954 preallocated); 955 } 956 957 #ifdef DBUS_BUILD_TESTS 958 static int 959 two_strings_cmp (const char *a, 960 const char *b) 961 { 962 size_t len_a; 963 size_t len_b; 964 int res; 965 966 res = strcmp (a, b); 967 if (res != 0) 968 return res; 969 970 len_a = strlen (a); 971 len_b = strlen (b); 972 973 return strcmp (a + len_a + 1, b + len_b + 1); 974 } 975 #endif 976 977 #ifdef DBUS_BUILD_TESTS 978 static DBusHashEntry* 979 find_two_strings_function (DBusHashTable *table, 980 void *key, 981 dbus_bool_t create_if_not_found, 982 DBusHashEntry ***bucket, 983 DBusPreallocatedHash *preallocated) 984 { 985 unsigned int idx; 986 987 idx = two_strings_hash (key) & table->mask; 988 989 return find_generic_function (table, key, idx, 990 (KeyCompareFunc) two_strings_cmp, create_if_not_found, bucket, 991 preallocated); 992 } 993 #endif /* DBUS_BUILD_TESTS */ 994 995 static DBusHashEntry* 996 find_direct_function (DBusHashTable *table, 997 void *key, 998 dbus_bool_t create_if_not_found, 999 DBusHashEntry ***bucket, 1000 DBusPreallocatedHash *preallocated) 1001 { 1002 unsigned int idx; 1003 1004 idx = RANDOM_INDEX (table, key) & table->mask; 1005 1006 1007 return find_generic_function (table, key, idx, 1008 NULL, create_if_not_found, bucket, 1009 preallocated); 1010 } 1011 1012 static void 1013 rebuild_table (DBusHashTable *table) 1014 { 1015 int old_size; 1016 int new_buckets; 1017 DBusHashEntry **old_buckets; 1018 DBusHashEntry **old_chain; 1019 DBusHashEntry *entry; 1020 dbus_bool_t growing; 1021 1022 /* 1023 * Allocate and initialize the new bucket array, and set up 1024 * hashing constants for new array size. 1025 */ 1026 1027 growing = table->n_entries >= table->hi_rebuild_size; 1028 1029 old_size = table->n_buckets; 1030 old_buckets = table->buckets; 1031 1032 if (growing) 1033 { 1034 /* overflow paranoia */ 1035 if (table->n_buckets < _DBUS_INT_MAX / 4 && 1036 table->down_shift >= 0) 1037 new_buckets = table->n_buckets * 4; 1038 else 1039 return; /* can't grow anymore */ 1040 } 1041 else 1042 { 1043 new_buckets = table->n_buckets / 4; 1044 if (new_buckets < DBUS_SMALL_HASH_TABLE) 1045 return; /* don't bother shrinking this far */ 1046 } 1047 1048 table->buckets = dbus_new0 (DBusHashEntry*, new_buckets); 1049 if (table->buckets == NULL) 1050 { 1051 /* out of memory, yay - just don't reallocate, the table will 1052 * still work, albeit more slowly. 1053 */ 1054 table->buckets = old_buckets; 1055 return; 1056 } 1057 1058 table->n_buckets = new_buckets; 1059 1060 if (growing) 1061 { 1062 table->lo_rebuild_size = table->hi_rebuild_size; 1063 table->hi_rebuild_size *= 4; 1064 1065 table->down_shift -= 2; /* keep 2 more high bits */ 1066 table->mask = (table->mask << 2) + 3; /* keep 2 more high bits */ 1067 } 1068 else 1069 { 1070 table->hi_rebuild_size = table->lo_rebuild_size; 1071 table->lo_rebuild_size /= 4; 1072 1073 table->down_shift += 2; /* keep 2 fewer high bits */ 1074 table->mask = table->mask >> 2; /* keep 2 fewer high bits */ 1075 } 1076 1077 #if 0 1078 printf ("%s table to lo = %d hi = %d downshift = %d mask = 0x%x\n", 1079 growing ? "GROW" : "SHRINK", 1080 table->lo_rebuild_size, 1081 table->hi_rebuild_size, 1082 table->down_shift, 1083 table->mask); 1084 #endif 1085 1086 _dbus_assert (table->lo_rebuild_size >= 0); 1087 _dbus_assert (table->hi_rebuild_size > table->lo_rebuild_size); 1088 _dbus_assert (table->mask != 0); 1089 /* the mask is essentially the max index */ 1090 _dbus_assert (table->mask < table->n_buckets); 1091 1092 /* 1093 * Rehash all of the existing entries into the new bucket array. 1094 */ 1095 1096 for (old_chain = old_buckets; old_size > 0; old_size--, old_chain++) 1097 { 1098 for (entry = *old_chain; entry != NULL; entry = *old_chain) 1099 { 1100 unsigned int idx; 1101 DBusHashEntry **bucket; 1102 1103 *old_chain = entry->next; 1104 switch (table->key_type) 1105 { 1106 case DBUS_HASH_STRING: 1107 idx = string_hash (entry->key) & table->mask; 1108 break; 1109 case DBUS_HASH_TWO_STRINGS: 1110 #ifdef DBUS_BUILD_TESTS 1111 idx = two_strings_hash (entry->key) & table->mask; 1112 #else 1113 idx = 0; 1114 _dbus_assert_not_reached ("two-strings is not enabled"); 1115 #endif 1116 break; 1117 case DBUS_HASH_INT: 1118 case DBUS_HASH_ULONG: 1119 case DBUS_HASH_POINTER: 1120 idx = RANDOM_INDEX (table, entry->key); 1121 break; 1122 default: 1123 idx = 0; 1124 _dbus_assert_not_reached ("Unknown hash table type"); 1125 break; 1126 } 1127 1128 bucket = &(table->buckets[idx]); 1129 entry->next = *bucket; 1130 *bucket = entry; 1131 } 1132 } 1133 1134 /* Free the old bucket array, if it was dynamically allocated. */ 1135 1136 if (old_buckets != table->static_buckets) 1137 dbus_free (old_buckets); 1138 } 1139 1140 /** 1141 * Looks up the value for a given string in a hash table 1142 * of type #DBUS_HASH_STRING. Returns %NULL if the value 1143 * is not present. (A not-present entry is indistinguishable 1144 * from an entry with a value of %NULL.) 1145 * @param table the hash table. 1146 * @param key the string to look up. 1147 * @returns the value of the hash entry. 1148 */ 1149 void* 1150 _dbus_hash_table_lookup_string (DBusHashTable *table, 1151 const char *key) 1152 { 1153 DBusHashEntry *entry; 1154 1155 _dbus_assert (table->key_type == DBUS_HASH_STRING); 1156 1157 entry = (* table->find_function) (table, (char*) key, FALSE, NULL, NULL); 1158 1159 if (entry) 1160 return entry->value; 1161 else 1162 return NULL; 1163 } 1164 1165 #ifdef DBUS_BUILD_TESTS 1166 /** 1167 * Looks up the value for a given string in a hash table 1168 * of type #DBUS_HASH_TWO_STRINGS. Returns %NULL if the value 1169 * is not present. (A not-present entry is indistinguishable 1170 * from an entry with a value of %NULL.) 1171 * @param table the hash table. 1172 * @param key the string to look up. 1173 * @returns the value of the hash entry. 1174 */ 1175 void* 1176 _dbus_hash_table_lookup_two_strings (DBusHashTable *table, 1177 const char *key) 1178 { 1179 DBusHashEntry *entry; 1180 1181 _dbus_assert (table->key_type == DBUS_HASH_TWO_STRINGS); 1182 1183 entry = (* table->find_function) (table, (char*) key, FALSE, NULL, NULL); 1184 1185 if (entry) 1186 return entry->value; 1187 else 1188 return NULL; 1189 } 1190 #endif /* DBUS_BUILD_TESTS */ 1191 1192 /** 1193 * Looks up the value for a given integer in a hash table 1194 * of type #DBUS_HASH_INT. Returns %NULL if the value 1195 * is not present. (A not-present entry is indistinguishable 1196 * from an entry with a value of %NULL.) 1197 * @param table the hash table. 1198 * @param key the integer to look up. 1199 * @returns the value of the hash entry. 1200 */ 1201 void* 1202 _dbus_hash_table_lookup_int (DBusHashTable *table, 1203 int key) 1204 { 1205 DBusHashEntry *entry; 1206 1207 _dbus_assert (table->key_type == DBUS_HASH_INT); 1208 1209 entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, NULL, NULL); 1210 1211 if (entry) 1212 return entry->value; 1213 else 1214 return NULL; 1215 } 1216 1217 #ifdef DBUS_BUILD_TESTS 1218 /* disabled since it's only used for testing */ 1219 /** 1220 * Looks up the value for a given integer in a hash table 1221 * of type #DBUS_HASH_POINTER. Returns %NULL if the value 1222 * is not present. (A not-present entry is indistinguishable 1223 * from an entry with a value of %NULL.) 1224 * @param table the hash table. 1225 * @param key the integer to look up. 1226 * @returns the value of the hash entry. 1227 */ 1228 void* 1229 _dbus_hash_table_lookup_pointer (DBusHashTable *table, 1230 void *key) 1231 { 1232 DBusHashEntry *entry; 1233 1234 _dbus_assert (table->key_type == DBUS_HASH_POINTER); 1235 1236 entry = (* table->find_function) (table, key, FALSE, NULL, NULL); 1237 1238 if (entry) 1239 return entry->value; 1240 else 1241 return NULL; 1242 } 1243 #endif /* DBUS_BUILD_TESTS */ 1244 1245 /** 1246 * Looks up the value for a given integer in a hash table 1247 * of type #DBUS_HASH_ULONG. Returns %NULL if the value 1248 * is not present. (A not-present entry is indistinguishable 1249 * from an entry with a value of %NULL.) 1250 * @param table the hash table. 1251 * @param key the integer to look up. 1252 * @returns the value of the hash entry. 1253 */ 1254 void* 1255 _dbus_hash_table_lookup_ulong (DBusHashTable *table, 1256 unsigned long key) 1257 { 1258 DBusHashEntry *entry; 1259 1260 _dbus_assert (table->key_type == DBUS_HASH_ULONG); 1261 1262 entry = (* table->find_function) (table, (void*) key, FALSE, NULL, NULL); 1263 1264 if (entry) 1265 return entry->value; 1266 else 1267 return NULL; 1268 } 1269 1270 /** 1271 * Removes the hash entry for the given key. If no hash entry 1272 * for the key exists, does nothing. 1273 * 1274 * @param table the hash table. 1275 * @param key the hash key. 1276 * @returns #TRUE if the entry existed 1277 */ 1278 dbus_bool_t 1279 _dbus_hash_table_remove_string (DBusHashTable *table, 1280 const char *key) 1281 { 1282 DBusHashEntry *entry; 1283 DBusHashEntry **bucket; 1284 1285 _dbus_assert (table->key_type == DBUS_HASH_STRING); 1286 1287 entry = (* table->find_function) (table, (char*) key, FALSE, &bucket, NULL); 1288 1289 if (entry) 1290 { 1291 remove_entry (table, bucket, entry); 1292 return TRUE; 1293 } 1294 else 1295 return FALSE; 1296 } 1297 1298 #ifdef DBUS_BUILD_TESTS 1299 /** 1300 * Removes the hash entry for the given key. If no hash entry 1301 * for the key exists, does nothing. 1302 * 1303 * @param table the hash table. 1304 * @param key the hash key. 1305 * @returns #TRUE if the entry existed 1306 */ 1307 dbus_bool_t 1308 _dbus_hash_table_remove_two_strings (DBusHashTable *table, 1309 const char *key) 1310 { 1311 DBusHashEntry *entry; 1312 DBusHashEntry **bucket; 1313 1314 _dbus_assert (table->key_type == DBUS_HASH_TWO_STRINGS); 1315 1316 entry = (* table->find_function) (table, (char*) key, FALSE, &bucket, NULL); 1317 1318 if (entry) 1319 { 1320 remove_entry (table, bucket, entry); 1321 return TRUE; 1322 } 1323 else 1324 return FALSE; 1325 } 1326 #endif /* DBUS_BUILD_TESTS */ 1327 1328 /** 1329 * Removes the hash entry for the given key. If no hash entry 1330 * for the key exists, does nothing. 1331 * 1332 * @param table the hash table. 1333 * @param key the hash key. 1334 * @returns #TRUE if the entry existed 1335 */ 1336 dbus_bool_t 1337 _dbus_hash_table_remove_int (DBusHashTable *table, 1338 int key) 1339 { 1340 DBusHashEntry *entry; 1341 DBusHashEntry **bucket; 1342 1343 _dbus_assert (table->key_type == DBUS_HASH_INT); 1344 1345 entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, &bucket, NULL); 1346 1347 if (entry) 1348 { 1349 remove_entry (table, bucket, entry); 1350 return TRUE; 1351 } 1352 else 1353 return FALSE; 1354 } 1355 1356 #ifdef DBUS_BUILD_TESTS 1357 /* disabled since it's only used for testing */ 1358 /** 1359 * Removes the hash entry for the given key. If no hash entry 1360 * for the key exists, does nothing. 1361 * 1362 * @param table the hash table. 1363 * @param key the hash key. 1364 * @returns #TRUE if the entry existed 1365 */ 1366 dbus_bool_t 1367 _dbus_hash_table_remove_pointer (DBusHashTable *table, 1368 void *key) 1369 { 1370 DBusHashEntry *entry; 1371 DBusHashEntry **bucket; 1372 1373 _dbus_assert (table->key_type == DBUS_HASH_POINTER); 1374 1375 entry = (* table->find_function) (table, key, FALSE, &bucket, NULL); 1376 1377 if (entry) 1378 { 1379 remove_entry (table, bucket, entry); 1380 return TRUE; 1381 } 1382 else 1383 return FALSE; 1384 } 1385 #endif /* DBUS_BUILD_TESTS */ 1386 1387 /** 1388 * Removes the hash entry for the given key. If no hash entry 1389 * for the key exists, does nothing. 1390 * 1391 * @param table the hash table. 1392 * @param key the hash key. 1393 * @returns #TRUE if the entry existed 1394 */ 1395 dbus_bool_t 1396 _dbus_hash_table_remove_ulong (DBusHashTable *table, 1397 unsigned long key) 1398 { 1399 DBusHashEntry *entry; 1400 DBusHashEntry **bucket; 1401 1402 _dbus_assert (table->key_type == DBUS_HASH_ULONG); 1403 1404 entry = (* table->find_function) (table, (void*) key, FALSE, &bucket, NULL); 1405 1406 if (entry) 1407 { 1408 remove_entry (table, bucket, entry); 1409 return TRUE; 1410 } 1411 else 1412 return FALSE; 1413 } 1414 1415 /** 1416 * Creates a hash entry with the given key and value. 1417 * The key and value are not copied; they are stored 1418 * in the hash table by reference. If an entry with the 1419 * given key already exists, the previous key and value 1420 * are overwritten (and freed if the hash table has 1421 * a key_free_function and/or value_free_function). 1422 * 1423 * Returns #FALSE if memory for the new hash entry 1424 * can't be allocated. 1425 * 1426 * @param table the hash table. 1427 * @param key the hash entry key. 1428 * @param value the hash entry value. 1429 */ 1430 dbus_bool_t 1431 _dbus_hash_table_insert_string (DBusHashTable *table, 1432 char *key, 1433 void *value) 1434 { 1435 DBusPreallocatedHash *preallocated; 1436 1437 _dbus_assert (table->key_type == DBUS_HASH_STRING); 1438 1439 preallocated = _dbus_hash_table_preallocate_entry (table); 1440 if (preallocated == NULL) 1441 return FALSE; 1442 1443 _dbus_hash_table_insert_string_preallocated (table, preallocated, 1444 key, value); 1445 1446 return TRUE; 1447 } 1448 1449 #ifdef DBUS_BUILD_TESTS 1450 /** 1451 * Creates a hash entry with the given key and value. 1452 * The key and value are not copied; they are stored 1453 * in the hash table by reference. If an entry with the 1454 * given key already exists, the previous key and value 1455 * are overwritten (and freed if the hash table has 1456 * a key_free_function and/or value_free_function). 1457 * 1458 * Returns #FALSE if memory for the new hash entry 1459 * can't be allocated. 1460 * 1461 * @param table the hash table. 1462 * @param key the hash entry key. 1463 * @param value the hash entry value. 1464 */ 1465 dbus_bool_t 1466 _dbus_hash_table_insert_two_strings (DBusHashTable *table, 1467 char *key, 1468 void *value) 1469 { 1470 DBusHashEntry *entry; 1471 1472 _dbus_assert (table->key_type == DBUS_HASH_TWO_STRINGS); 1473 1474 entry = (* table->find_function) (table, key, TRUE, NULL, NULL); 1475 1476 if (entry == NULL) 1477 return FALSE; /* no memory */ 1478 1479 if (table->free_key_function && entry->key != key) 1480 (* table->free_key_function) (entry->key); 1481 1482 if (table->free_value_function && entry->value != value) 1483 (* table->free_value_function) (entry->value); 1484 1485 entry->key = key; 1486 entry->value = value; 1487 1488 return TRUE; 1489 } 1490 #endif /* DBUS_BUILD_TESTS */ 1491 1492 /** 1493 * Creates a hash entry with the given key and value. 1494 * The key and value are not copied; they are stored 1495 * in the hash table by reference. If an entry with the 1496 * given key already exists, the previous key and value 1497 * are overwritten (and freed if the hash table has 1498 * a key_free_function and/or value_free_function). 1499 * 1500 * Returns #FALSE if memory for the new hash entry 1501 * can't be allocated. 1502 * 1503 * @param table the hash table. 1504 * @param key the hash entry key. 1505 * @param value the hash entry value. 1506 */ 1507 dbus_bool_t 1508 _dbus_hash_table_insert_int (DBusHashTable *table, 1509 int key, 1510 void *value) 1511 { 1512 DBusHashEntry *entry; 1513 1514 _dbus_assert (table->key_type == DBUS_HASH_INT); 1515 1516 entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), TRUE, NULL, NULL); 1517 1518 if (entry == NULL) 1519 return FALSE; /* no memory */ 1520 1521 if (table->free_key_function && entry->key != _DBUS_INT_TO_POINTER (key)) 1522 (* table->free_key_function) (entry->key); 1523 1524 if (table->free_value_function && entry->value != value) 1525 (* table->free_value_function) (entry->value); 1526 1527 entry->key = _DBUS_INT_TO_POINTER (key); 1528 entry->value = value; 1529 1530 return TRUE; 1531 } 1532 1533 #ifdef DBUS_BUILD_TESTS 1534 /* disabled since it's only used for testing */ 1535 /** 1536 * Creates a hash entry with the given key and value. 1537 * The key and value are not copied; they are stored 1538 * in the hash table by reference. If an entry with the 1539 * given key already exists, the previous key and value 1540 * are overwritten (and freed if the hash table has 1541 * a key_free_function and/or value_free_function). 1542 * 1543 * Returns #FALSE if memory for the new hash entry 1544 * can't be allocated. 1545 * 1546 * @param table the hash table. 1547 * @param key the hash entry key. 1548 * @param value the hash entry value. 1549 */ 1550 dbus_bool_t 1551 _dbus_hash_table_insert_pointer (DBusHashTable *table, 1552 void *key, 1553 void *value) 1554 { 1555 DBusHashEntry *entry; 1556 1557 _dbus_assert (table->key_type == DBUS_HASH_POINTER); 1558 1559 entry = (* table->find_function) (table, key, TRUE, NULL, NULL); 1560 1561 if (entry == NULL) 1562 return FALSE; /* no memory */ 1563 1564 if (table->free_key_function && entry->key != key) 1565 (* table->free_key_function) (entry->key); 1566 1567 if (table->free_value_function && entry->value != value) 1568 (* table->free_value_function) (entry->value); 1569 1570 entry->key = key; 1571 entry->value = value; 1572 1573 return TRUE; 1574 } 1575 #endif /* DBUS_BUILD_TESTS */ 1576 1577 /** 1578 * Creates a hash entry with the given key and value. 1579 * The key and value are not copied; they are stored 1580 * in the hash table by reference. If an entry with the 1581 * given key already exists, the previous key and value 1582 * are overwritten (and freed if the hash table has 1583 * a key_free_function and/or value_free_function). 1584 * 1585 * Returns #FALSE if memory for the new hash entry 1586 * can't be allocated. 1587 * 1588 * @param table the hash table. 1589 * @param key the hash entry key. 1590 * @param value the hash entry value. 1591 */ 1592 dbus_bool_t 1593 _dbus_hash_table_insert_ulong (DBusHashTable *table, 1594 unsigned long key, 1595 void *value) 1596 { 1597 DBusHashEntry *entry; 1598 1599 _dbus_assert (table->key_type == DBUS_HASH_ULONG); 1600 1601 entry = (* table->find_function) (table, (void*) key, TRUE, NULL, NULL); 1602 1603 if (entry == NULL) 1604 return FALSE; /* no memory */ 1605 1606 if (table->free_key_function && entry->key != (void*) key) 1607 (* table->free_key_function) (entry->key); 1608 1609 if (table->free_value_function && entry->value != value) 1610 (* table->free_value_function) (entry->value); 1611 1612 entry->key = (void*) key; 1613 entry->value = value; 1614 1615 return TRUE; 1616 } 1617 1618 /** 1619 * Preallocate an opaque data blob that allows us to insert into the 1620 * hash table at a later time without allocating any memory. 1621 * 1622 * @param table the hash table 1623 * @returns the preallocated data, or #NULL if no memory 1624 */ 1625 DBusPreallocatedHash* 1626 _dbus_hash_table_preallocate_entry (DBusHashTable *table) 1627 { 1628 DBusHashEntry *entry; 1629 1630 entry = alloc_entry (table); 1631 1632 return (DBusPreallocatedHash*) entry; 1633 } 1634 1635 /** 1636 * Frees an opaque DBusPreallocatedHash that was *not* used 1637 * in order to insert into the hash table. 1638 * 1639 * @param table the hash table 1640 * @param preallocated the preallocated data 1641 */ 1642 void 1643 _dbus_hash_table_free_preallocated_entry (DBusHashTable *table, 1644 DBusPreallocatedHash *preallocated) 1645 { 1646 DBusHashEntry *entry; 1647 1648 _dbus_assert (preallocated != NULL); 1649 1650 entry = (DBusHashEntry*) preallocated; 1651 1652 /* Don't use free_entry(), since this entry has no key/data */ 1653 _dbus_mem_pool_dealloc (table->entry_pool, entry); 1654 } 1655 1656 /** 1657 * Inserts a string-keyed entry into the hash table, using a 1658 * preallocated data block from 1659 * _dbus_hash_table_preallocate_entry(). This function cannot fail due 1660 * to lack of memory. The DBusPreallocatedHash object is consumed and 1661 * should not be reused or freed. Otherwise this function works 1662 * just like _dbus_hash_table_insert_string(). 1663 * 1664 * @param table the hash table 1665 * @param preallocated the preallocated data 1666 * @param key the hash key 1667 * @param value the value 1668 */ 1669 void 1670 _dbus_hash_table_insert_string_preallocated (DBusHashTable *table, 1671 DBusPreallocatedHash *preallocated, 1672 char *key, 1673 void *value) 1674 { 1675 DBusHashEntry *entry; 1676 1677 _dbus_assert (table->key_type == DBUS_HASH_STRING); 1678 _dbus_assert (preallocated != NULL); 1679 1680 entry = (* table->find_function) (table, key, TRUE, NULL, preallocated); 1681 1682 _dbus_assert (entry != NULL); 1683 1684 if (table->free_key_function && entry->key != key) 1685 (* table->free_key_function) (entry->key); 1686 1687 if (table->free_value_function && entry->value != value) 1688 (* table->free_value_function) (entry->value); 1689 1690 entry->key = key; 1691 entry->value = value; 1692 } 1693 1694 /** 1695 * Gets the number of hash entries in a hash table. 1696 * 1697 * @param table the hash table. 1698 * @returns the number of entries in the table. 1699 */ 1700 int 1701 _dbus_hash_table_get_n_entries (DBusHashTable *table) 1702 { 1703 return table->n_entries; 1704 } 1705 1706 /** @} */ 1707 1708 #ifdef DBUS_BUILD_TESTS 1709 #include "dbus-test.h" 1710 #include <stdio.h> 1711 1712 /* If you're wondering why the hash table test takes 1713 * forever to run, it's because we call this function 1714 * in inner loops thus making things quadratic. 1715 */ 1716 static int 1717 count_entries (DBusHashTable *table) 1718 { 1719 DBusHashIter iter; 1720 int count; 1721 1722 count = 0; 1723 _dbus_hash_iter_init (table, &iter); 1724 while (_dbus_hash_iter_next (&iter)) 1725 ++count; 1726 1727 _dbus_assert (count == _dbus_hash_table_get_n_entries (table)); 1728 1729 return count; 1730 } 1731 1732 /* Copy the foo\0bar\0 double string thing */ 1733 static char* 1734 _dbus_strdup2 (const char *str) 1735 { 1736 size_t len; 1737 char *copy; 1738 1739 if (str == NULL) 1740 return NULL; 1741 1742 len = strlen (str); 1743 len += strlen ((str + len + 1)); 1744 1745 copy = dbus_malloc (len + 2); 1746 if (copy == NULL) 1747 return NULL; 1748 1749 memcpy (copy, str, len + 2); 1750 1751 return copy; 1752 } 1753 1754 /** 1755 * @ingroup DBusHashTableInternals 1756 * Unit test for DBusHashTable 1757 * @returns #TRUE on success. 1758 */ 1759 dbus_bool_t 1760 _dbus_hash_test (void) 1761 { 1762 int i; 1763 DBusHashTable *table1; 1764 DBusHashTable *table2; 1765 DBusHashTable *table3; 1766 DBusHashTable *table4; 1767 DBusHashIter iter; 1768 #define N_HASH_KEYS 5000 1769 char **keys; 1770 dbus_bool_t ret = FALSE; 1771 1772 keys = dbus_new (char *, N_HASH_KEYS); 1773 if (keys == NULL) 1774 _dbus_assert_not_reached ("no memory"); 1775 1776 for (i = 0; i < N_HASH_KEYS; i++) 1777 { 1778 keys[i] = dbus_malloc (128); 1779 1780 if (keys[i] == NULL) 1781 _dbus_assert_not_reached ("no memory"); 1782 } 1783 1784 printf ("Computing test hash keys...\n"); 1785 i = 0; 1786 while (i < N_HASH_KEYS) 1787 { 1788 int len; 1789 1790 /* all the hash keys are TWO_STRINGS, but 1791 * then we can also use those as regular strings. 1792 */ 1793 1794 len = sprintf (keys[i], "Hash key %d", i); 1795 sprintf (keys[i] + len + 1, "Two string %d", i); 1796 _dbus_assert (*(keys[i] + len) == '\0'); 1797 _dbus_assert (*(keys[i] + len + 1) != '\0'); 1798 ++i; 1799 } 1800 printf ("... done.\n"); 1801 1802 table1 = _dbus_hash_table_new (DBUS_HASH_STRING, 1803 dbus_free, dbus_free); 1804 if (table1 == NULL) 1805 goto out; 1806 1807 table2 = _dbus_hash_table_new (DBUS_HASH_INT, 1808 NULL, dbus_free); 1809 if (table2 == NULL) 1810 goto out; 1811 1812 table3 = _dbus_hash_table_new (DBUS_HASH_ULONG, 1813 NULL, dbus_free); 1814 if (table3 == NULL) 1815 goto out; 1816 1817 table4 = _dbus_hash_table_new (DBUS_HASH_TWO_STRINGS, 1818 dbus_free, dbus_free); 1819 if (table4 == NULL) 1820 goto out; 1821 1822 1823 /* Insert and remove a bunch of stuff, counting the table in between 1824 * to be sure it's not broken and that iteration works 1825 */ 1826 i = 0; 1827 while (i < 3000) 1828 { 1829 void *value; 1830 char *key; 1831 1832 key = _dbus_strdup (keys[i]); 1833 if (key == NULL) 1834 goto out; 1835 value = _dbus_strdup ("Value!"); 1836 if (value == NULL) 1837 goto out; 1838 1839 if (!_dbus_hash_table_insert_string (table1, 1840 key, value)) 1841 goto out; 1842 1843 value = _dbus_strdup (keys[i]); 1844 if (value == NULL) 1845 goto out; 1846 1847 if (!_dbus_hash_table_insert_int (table2, 1848 i, value)) 1849 goto out; 1850 1851 value = _dbus_strdup (keys[i]); 1852 if (value == NULL) 1853 goto out; 1854 1855 if (!_dbus_hash_table_insert_ulong (table3, 1856 i, value)) 1857 goto out; 1858 1859 key = _dbus_strdup2 (keys[i]); 1860 if (key == NULL) 1861 goto out; 1862 value = _dbus_strdup ("Value!"); 1863 if (value == NULL) 1864 goto out; 1865 1866 if (!_dbus_hash_table_insert_two_strings (table4, 1867 key, value)) 1868 goto out; 1869 1870 _dbus_assert (count_entries (table1) == i + 1); 1871 _dbus_assert (count_entries (table2) == i + 1); 1872 _dbus_assert (count_entries (table3) == i + 1); 1873 _dbus_assert (count_entries (table4) == i + 1); 1874 1875 value = _dbus_hash_table_lookup_string (table1, keys[i]); 1876 _dbus_assert (value != NULL); 1877 _dbus_assert (strcmp (value, "Value!") == 0); 1878 1879 value = _dbus_hash_table_lookup_int (table2, i); 1880 _dbus_assert (value != NULL); 1881 _dbus_assert (strcmp (value, keys[i]) == 0); 1882 1883 value = _dbus_hash_table_lookup_ulong (table3, i); 1884 _dbus_assert (value != NULL); 1885 _dbus_assert (strcmp (value, keys[i]) == 0); 1886 1887 value = _dbus_hash_table_lookup_two_strings (table4, keys[i]); 1888 _dbus_assert (value != NULL); 1889 _dbus_assert (strcmp (value, "Value!") == 0); 1890 1891 ++i; 1892 } 1893 1894 --i; 1895 while (i >= 0) 1896 { 1897 _dbus_hash_table_remove_string (table1, 1898 keys[i]); 1899 1900 _dbus_hash_table_remove_int (table2, i); 1901 1902 _dbus_hash_table_remove_ulong (table3, i); 1903 1904 _dbus_hash_table_remove_two_strings (table4, 1905 keys[i]); 1906 1907 _dbus_assert (count_entries (table1) == i); 1908 _dbus_assert (count_entries (table2) == i); 1909 _dbus_assert (count_entries (table3) == i); 1910 _dbus_assert (count_entries (table4) == i); 1911 1912 --i; 1913 } 1914 1915 _dbus_hash_table_ref (table1); 1916 _dbus_hash_table_ref (table2); 1917 _dbus_hash_table_ref (table3); 1918 _dbus_hash_table_ref (table4); 1919 _dbus_hash_table_unref (table1); 1920 _dbus_hash_table_unref (table2); 1921 _dbus_hash_table_unref (table3); 1922 _dbus_hash_table_unref (table4); 1923 _dbus_hash_table_unref (table1); 1924 _dbus_hash_table_unref (table2); 1925 _dbus_hash_table_unref (table3); 1926 _dbus_hash_table_unref (table4); 1927 table3 = NULL; 1928 1929 /* Insert a bunch of stuff then check 1930 * that iteration works correctly (finds the right 1931 * values, iter_set_value works, etc.) 1932 */ 1933 table1 = _dbus_hash_table_new (DBUS_HASH_STRING, 1934 dbus_free, dbus_free); 1935 if (table1 == NULL) 1936 goto out; 1937 1938 table2 = _dbus_hash_table_new (DBUS_HASH_INT, 1939 NULL, dbus_free); 1940 if (table2 == NULL) 1941 goto out; 1942 1943 i = 0; 1944 while (i < 5000) 1945 { 1946 char *key; 1947 void *value; 1948 1949 key = _dbus_strdup (keys[i]); 1950 if (key == NULL) 1951 goto out; 1952 value = _dbus_strdup ("Value!"); 1953 if (value == NULL) 1954 goto out; 1955 1956 if (!_dbus_hash_table_insert_string (table1, 1957 key, value)) 1958 goto out; 1959 1960 value = _dbus_strdup (keys[i]); 1961 if (value == NULL) 1962 goto out; 1963 1964 if (!_dbus_hash_table_insert_int (table2, 1965 i, value)) 1966 goto out; 1967 1968 _dbus_assert (count_entries (table1) == i + 1); 1969 _dbus_assert (count_entries (table2) == i + 1); 1970 1971 ++i; 1972 } 1973 1974 _dbus_hash_iter_init (table1, &iter); 1975 while (_dbus_hash_iter_next (&iter)) 1976 { 1977 const char *key; 1978 void *value; 1979 1980 key = _dbus_hash_iter_get_string_key (&iter); 1981 value = _dbus_hash_iter_get_value (&iter); 1982 1983 _dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value); 1984 1985 value = _dbus_strdup ("Different value!"); 1986 if (value == NULL) 1987 goto out; 1988 1989 _dbus_hash_iter_set_value (&iter, value); 1990 1991 _dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value); 1992 } 1993 1994 _dbus_hash_iter_init (table1, &iter); 1995 while (_dbus_hash_iter_next (&iter)) 1996 { 1997 _dbus_hash_iter_remove_entry (&iter); 1998 _dbus_assert (count_entries (table1) == i - 1); 1999 --i; 2000 } 2001 2002 _dbus_hash_iter_init (table2, &iter); 2003 while (_dbus_hash_iter_next (&iter)) 2004 { 2005 int key; 2006 void *value; 2007 2008 key = _dbus_hash_iter_get_int_key (&iter); 2009 value = _dbus_hash_iter_get_value (&iter); 2010 2011 _dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value); 2012 2013 value = _dbus_strdup ("Different value!"); 2014 if (value == NULL) 2015 goto out; 2016 2017 _dbus_hash_iter_set_value (&iter, value); 2018 2019 _dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value); 2020 } 2021 2022 i = count_entries (table2); 2023 _dbus_hash_iter_init (table2, &iter); 2024 while (_dbus_hash_iter_next (&iter)) 2025 { 2026 _dbus_hash_iter_remove_entry (&iter); 2027 _dbus_assert (count_entries (table2) + 1 == i); 2028 --i; 2029 } 2030 2031 /* add/remove interleaved, to check that we grow/shrink the table 2032 * appropriately 2033 */ 2034 i = 0; 2035 while (i < 1000) 2036 { 2037 char *key; 2038 void *value; 2039 2040 key = _dbus_strdup (keys[i]); 2041 if (key == NULL) 2042 goto out; 2043 2044 value = _dbus_strdup ("Value!"); 2045 if (value == NULL) 2046 goto out; 2047 2048 if (!_dbus_hash_table_insert_string (table1, 2049 key, value)) 2050 goto out; 2051 2052 ++i; 2053 } 2054 2055 --i; 2056 while (i >= 0) 2057 { 2058 char *key; 2059 void *value; 2060 2061 key = _dbus_strdup (keys[i]); 2062 if (key == NULL) 2063 goto out; 2064 value = _dbus_strdup ("Value!"); 2065 if (value == NULL) 2066 goto out; 2067 2068 if (!_dbus_hash_table_remove_string (table1, keys[i])) 2069 goto out; 2070 2071 if (!_dbus_hash_table_insert_string (table1, 2072 key, value)) 2073 goto out; 2074 2075 if (!_dbus_hash_table_remove_string (table1, keys[i])) 2076 goto out; 2077 2078 _dbus_assert (_dbus_hash_table_get_n_entries (table1) == i); 2079 2080 --i; 2081 } 2082 2083 /* nuke these tables */ 2084 _dbus_hash_table_unref (table1); 2085 _dbus_hash_table_unref (table2); 2086 2087 2088 /* Now do a bunch of things again using _dbus_hash_iter_lookup() to 2089 * be sure that interface works. 2090 */ 2091 table1 = _dbus_hash_table_new (DBUS_HASH_STRING, 2092 dbus_free, dbus_free); 2093 if (table1 == NULL) 2094 goto out; 2095 2096 table2 = _dbus_hash_table_new (DBUS_HASH_INT, 2097 NULL, dbus_free); 2098 if (table2 == NULL) 2099 goto out; 2100 2101 i = 0; 2102 while (i < 3000) 2103 { 2104 void *value; 2105 char *key; 2106 2107 key = _dbus_strdup (keys[i]); 2108 if (key == NULL) 2109 goto out; 2110 value = _dbus_strdup ("Value!"); 2111 if (value == NULL) 2112 goto out; 2113 2114 if (!_dbus_hash_iter_lookup (table1, 2115 key, TRUE, &iter)) 2116 goto out; 2117 _dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL); 2118 _dbus_hash_iter_set_value (&iter, value); 2119 2120 value = _dbus_strdup (keys[i]); 2121 if (value == NULL) 2122 goto out; 2123 2124 if (!_dbus_hash_iter_lookup (table2, 2125 _DBUS_INT_TO_POINTER (i), TRUE, &iter)) 2126 goto out; 2127 _dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL); 2128 _dbus_hash_iter_set_value (&iter, value); 2129 2130 _dbus_assert (count_entries (table1) == i + 1); 2131 _dbus_assert (count_entries (table2) == i + 1); 2132 2133 if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter)) 2134 goto out; 2135 2136 value = _dbus_hash_iter_get_value (&iter); 2137 _dbus_assert (value != NULL); 2138 _dbus_assert (strcmp (value, "Value!") == 0); 2139 2140 /* Iterate just to be sure it works, though 2141 * it's a stupid thing to do 2142 */ 2143 while (_dbus_hash_iter_next (&iter)) 2144 ; 2145 2146 if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter)) 2147 goto out; 2148 2149 value = _dbus_hash_iter_get_value (&iter); 2150 _dbus_assert (value != NULL); 2151 _dbus_assert (strcmp (value, keys[i]) == 0); 2152 2153 /* Iterate just to be sure it works, though 2154 * it's a stupid thing to do 2155 */ 2156 while (_dbus_hash_iter_next (&iter)) 2157 ; 2158 2159 ++i; 2160 } 2161 2162 --i; 2163 while (i >= 0) 2164 { 2165 if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter)) 2166 _dbus_assert_not_reached ("hash entry should have existed"); 2167 _dbus_hash_iter_remove_entry (&iter); 2168 2169 if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter)) 2170 _dbus_assert_not_reached ("hash entry should have existed"); 2171 _dbus_hash_iter_remove_entry (&iter); 2172 2173 _dbus_assert (count_entries (table1) == i); 2174 _dbus_assert (count_entries (table2) == i); 2175 2176 --i; 2177 } 2178 2179 _dbus_hash_table_unref (table1); 2180 _dbus_hash_table_unref (table2); 2181 2182 ret = TRUE; 2183 2184 out: 2185 for (i = 0; i < N_HASH_KEYS; i++) 2186 dbus_free (keys[i]); 2187 2188 dbus_free (keys); 2189 2190 return ret; 2191 } 2192 2193 #endif /* DBUS_BUILD_TESTS */ 2194