hash_table_remove is careful to rehash the mappings that follow the
deleted one. */
-/* When hash table's fullness exceeds this threshold, the hash table
- is resized. */
-#define HASH_FULLNESS_THRESHOLD 0.75
+/* Maximum allowed fullness: when hash table's fullness exceeds this
+ value, the table is resized. */
+#define HASH_MAX_FULLNESS 0.75
-/* The hash table size is multiplied by this factor with each resize.
- This guarantees infrequent resizes. */
+/* The hash table size is multiplied by this factor (and then rounded
+ to the next prime) with each resize. This guarantees infrequent
+ resizes. */
#define HASH_RESIZE_FACTOR 2
struct mapping {
struct mapping *mappings; /* the array of mapping pairs. */
};
-/* We use NULL key to mark a mapping as empty. It is consequently
- illegal to store NULL keys. */
-#define NON_EMPTY(mp) (mp->key != NULL)
+/* We use all-bit-set marker to mean that a mapping is empty. It is
+ (hopefully) illegal as a pointer, and it allows the users to use
+ NULL (as well as any non-negative integer) as key. */
+#define NON_EMPTY(mp) (mp->key != (void *)~(unsigned long)0)
/* "Next" mapping is the mapping after MP, but wrapping back to
MAPPINGS when MP would reach MAPPINGS+SIZE. */
return 0;
}
+static unsigned long ptrhash PARAMS ((const void *));
+static int ptrcmp PARAMS ((const void *, const void *));
+
/* Create a hash table with hash function HASH_FUNCTION and test
function TEST_FUNCTION. The table is empty (its count is 0), but
pre-allocated to store at least ITEMS items.
int (*test_function) (const void *, const void *))
{
int size;
- struct hash_table *ht
- = (struct hash_table *)xmalloc (sizeof (struct hash_table));
+ struct hash_table *ht = xnew (struct hash_table);
ht->hash_function = hash_function ? hash_function : ptrhash;
ht->test_function = test_function ? test_function : ptrcmp;
+ /* If the size of struct hash_table ever becomes a concern, this
+ field can go. (Wget doesn't create many hashes.) */
ht->prime_offset = 0;
/* Calculate the size that ensures that the table will store at
least ITEMS keys without the need to resize. */
- size = 1 + items / HASH_FULLNESS_THRESHOLD;
+ size = 1 + items / HASH_MAX_FULLNESS;
size = prime_size (size, &ht->prime_offset);
ht->size = size;
- ht->resize_threshold = size * HASH_FULLNESS_THRESHOLD;
+ ht->resize_threshold = size * HASH_MAX_FULLNESS;
/*assert (ht->resize_threshold >= items);*/
- ht->mappings = xmalloc (ht->size * sizeof (struct mapping));
- memset (ht->mappings, '\0', ht->size * sizeof (struct mapping));
+ ht->mappings = xnew_array (struct mapping, ht->size);
+ /* Mark mappings as empty. We use 0xff rather than 0 to mark empty
+ keys because it allows us to store NULL keys to the table. */
+ memset (ht->mappings, 255, size * sizeof (struct mapping));
ht->count = 0;
#endif
ht->size = newsize;
- ht->resize_threshold = newsize * HASH_FULLNESS_THRESHOLD;
+ ht->resize_threshold = newsize * HASH_MAX_FULLNESS;
- mappings = xmalloc (ht->size * sizeof (struct mapping));
- memset (mappings, '\0', ht->size * sizeof (struct mapping));
+ mappings = xnew_array (struct mapping, newsize);
+ memset (mappings, 255, newsize * sizeof (struct mapping));
ht->mappings = mappings;
for (mp = old_mappings; mp < old_end; mp++)
if (NON_EMPTY (mp))
{
struct mapping *new_mp = mappings + HASH_POSITION (ht, mp->key);
- /* We don't need to test for uniqueness of keys because all
- the keys come from the hash table and are therefore known
- to be unique. */
+ /* We don't need to test for uniqueness of keys because they
+ come from the hash table and are therefore known to be
+ unique. */
LOOP_NON_EMPTY (new_mp, mappings, newsize)
;
*new_mp = *mp;
pointer identity. (Common Lisp calls them EQ hash tables, and Java
calls them IdentityHashMaps.) */
-unsigned long
+static unsigned long
ptrhash (const void *ptr)
{
unsigned long key = (unsigned long)ptr;
return key;
}
-int
+static int
ptrcmp (const void *ptr1, const void *ptr2)
{
return ptr1 == ptr2;
}
-
-#if 0
-/* Currently unused: hashing of integers. */
-
-unsigned long
-inthash (unsigned int key)
-{
- key += (key << 12);
- key ^= (key >> 22);
- key += (key << 4);
- key ^= (key >> 9);
- key += (key << 10);
- key ^= (key >> 2);
- key += (key << 7);
- key ^= (key >> 12);
- return key;
-}
-#endif
\f
#ifdef STANDALONE