mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Use 0xff in hash_table_clear.
This commit is contained in:
parent
e5332ac6fc
commit
bf1ce5b2ad
@ -1,3 +1,10 @@
|
|||||||
|
2003-11-08 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
|
* hash.c (HASH_POSITION): Explicitly accept the hash function.
|
||||||
|
(grow_hash_table): Extract ht->hash_function outside the loop.
|
||||||
|
(hash_table_remove): Ditto.
|
||||||
|
(hash_table_clear): Fill entries with 0xff to clear them.
|
||||||
|
|
||||||
2003-11-08 Hrvoje Niksic <hniksic@xemacs.org>
|
2003-11-08 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
* http.c (persistent_available_p): No reason for the host lookup
|
* http.c (persistent_available_p): No reason for the host lookup
|
||||||
|
63
src/hash.c
63
src/hash.c
@ -141,19 +141,21 @@ struct mapping {
|
|||||||
void *value;
|
void *value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef unsigned long (*hashfun_t) PARAMS ((const void *));
|
||||||
|
typedef int (*testfun_t) PARAMS ((const void *, const void *));
|
||||||
|
|
||||||
struct hash_table {
|
struct hash_table {
|
||||||
unsigned long (*hash_function) PARAMS ((const void *));
|
hashfun_t hash_function;
|
||||||
int (*test_function) PARAMS ((const void *, const void *));
|
testfun_t test_function;
|
||||||
|
|
||||||
|
struct mapping *mappings; /* pointer to the table entries. */
|
||||||
int size; /* size of the array. */
|
int size; /* size of the array. */
|
||||||
int count; /* number of non-empty entries. */
|
|
||||||
|
|
||||||
|
int count; /* number of non-empty entries. */
|
||||||
int resize_threshold; /* after size exceeds this number of
|
int resize_threshold; /* after size exceeds this number of
|
||||||
entries, resize the table. */
|
entries, resize the table. */
|
||||||
int prime_offset; /* the offset of the current prime in
|
int prime_offset; /* the offset of the current prime in
|
||||||
the prime table. */
|
the prime table. */
|
||||||
|
|
||||||
struct mapping *mappings; /* the array of mapping pairs. */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* We use all-bit-set marker to mean that a mapping is empty. It is
|
/* We use all-bit-set marker to mean that a mapping is empty. It is
|
||||||
@ -170,22 +172,21 @@ struct hash_table {
|
|||||||
#define LOOP_NON_EMPTY(mp, mappings, size) \
|
#define LOOP_NON_EMPTY(mp, mappings, size) \
|
||||||
for (; NON_EMPTY (mp); mp = NEXT_MAPPING (mp, mappings, size))
|
for (; NON_EMPTY (mp); mp = NEXT_MAPPING (mp, mappings, size))
|
||||||
|
|
||||||
/* #### Some implementations multiply the hash with the "golden ratio"
|
/* Return the position of KEY in hash table SIZE large, hash function
|
||||||
of the table to get better spread for keys that do not come from a
|
being HASHFUN. #### Some implementations multiply HASHFUN's output
|
||||||
good hashing source. I'm not sure if that is necessary for the
|
with the table's "golden ratio" to get better spreading of keys.
|
||||||
hash functions we use. */
|
I'm not sure if that is necessary with our hash functions. */
|
||||||
|
#define HASH_POSITION(key, hashfun, size) ((hashfun) (key) % size)
|
||||||
#define HASH_POSITION(ht, key) (ht->hash_function (key) % ht->size)
|
|
||||||
|
|
||||||
/* Find a prime near, but greather than or equal to SIZE. Of course,
|
/* Find a prime near, but greather than or equal to SIZE. Of course,
|
||||||
the primes are not calculated, but looked up from a table. The
|
the primes are not calculated, but looked up from a table. The
|
||||||
table does not contain all primes in range, just a selection useful
|
table does not contain all primes in range, just a selection useful
|
||||||
for this purpose.
|
for this purpose.
|
||||||
|
|
||||||
PRIME_OFFSET is a minor optimization: if specified, it starts the
|
PRIME_OFFSET is a minor optimization: it specifies start position
|
||||||
search for the prime number beginning with the specific offset in
|
for the search for the large enough prime. The final offset is
|
||||||
the prime number table. The final offset is stored in the same
|
stored in the same variable. That way the list of primes does not
|
||||||
variable. */
|
have to be scanned from the beginning each time around. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
prime_size (int size, int *prime_offset)
|
prime_size (int size, int *prime_offset)
|
||||||
@ -202,9 +203,9 @@ prime_size (int size, int *prime_offset)
|
|||||||
1174703521, 1527114613, 1985248999,
|
1174703521, 1527114613, 1985248999,
|
||||||
(unsigned long)0x99d43ea5, (unsigned long)0xc7fa5177
|
(unsigned long)0x99d43ea5, (unsigned long)0xc7fa5177
|
||||||
};
|
};
|
||||||
int i = *prime_offset;
|
int i;
|
||||||
|
|
||||||
for (; i < countof (primes); i++)
|
for (i = *prime_offset; i < countof (primes); i++)
|
||||||
if (primes[i] >= size)
|
if (primes[i] >= size)
|
||||||
{
|
{
|
||||||
/* Set the offset to the next prime. That is safe because,
|
/* Set the offset to the next prime. That is safe because,
|
||||||
@ -239,9 +240,10 @@ static int ptrcmp PARAMS ((const void *, const void *));
|
|||||||
used as size unchanged. To start with a small table that grows as
|
used as size unchanged. To start with a small table that grows as
|
||||||
needed, simply specify zero ITEMS.
|
needed, simply specify zero ITEMS.
|
||||||
|
|
||||||
If HASH_FUNCTION is not provided, identity table is assumed,
|
If hash and test callbacks are not specified, identity mapping is
|
||||||
i.e. key pointers are compared as keys. If you want strings with
|
assumed, i.e. pointer values are used for key comparison. If,
|
||||||
equal contents to hash the same, use make_string_hash_table. */
|
instead of that, you want strings with equal contents to hash the
|
||||||
|
same, use make_string_hash_table. */
|
||||||
|
|
||||||
struct hash_table *
|
struct hash_table *
|
||||||
hash_table_new (int items,
|
hash_table_new (int items,
|
||||||
@ -269,7 +271,7 @@ hash_table_new (int items,
|
|||||||
ht->mappings = xnew_array (struct mapping, ht->size);
|
ht->mappings = xnew_array (struct mapping, ht->size);
|
||||||
/* Mark mappings as empty. We use 0xff rather than 0 to mark empty
|
/* 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. */
|
keys because it allows us to store NULL keys to the table. */
|
||||||
memset (ht->mappings, 255, size * sizeof (struct mapping));
|
memset (ht->mappings, 0xff, size * sizeof (struct mapping));
|
||||||
|
|
||||||
ht->count = 0;
|
ht->count = 0;
|
||||||
|
|
||||||
@ -294,8 +296,8 @@ find_mapping (const struct hash_table *ht, const void *key)
|
|||||||
{
|
{
|
||||||
struct mapping *mappings = ht->mappings;
|
struct mapping *mappings = ht->mappings;
|
||||||
int size = ht->size;
|
int size = ht->size;
|
||||||
struct mapping *mp = mappings + HASH_POSITION (ht, key);
|
struct mapping *mp = mappings + HASH_POSITION (key, ht->hash_function, size);
|
||||||
int (*equals) PARAMS ((const void *, const void *)) = ht->test_function;
|
testfun_t equals = ht->test_function;
|
||||||
|
|
||||||
LOOP_NON_EMPTY (mp, mappings, size)
|
LOOP_NON_EMPTY (mp, mappings, size)
|
||||||
if (equals (key, mp->key))
|
if (equals (key, mp->key))
|
||||||
@ -355,6 +357,7 @@ hash_table_contains (const struct hash_table *ht, const void *key)
|
|||||||
static void
|
static void
|
||||||
grow_hash_table (struct hash_table *ht)
|
grow_hash_table (struct hash_table *ht)
|
||||||
{
|
{
|
||||||
|
hashfun_t hasher = ht->hash_function;
|
||||||
struct mapping *old_mappings = ht->mappings;
|
struct mapping *old_mappings = ht->mappings;
|
||||||
struct mapping *old_end = ht->mappings + ht->size;
|
struct mapping *old_end = ht->mappings + ht->size;
|
||||||
struct mapping *mp, *mappings;
|
struct mapping *mp, *mappings;
|
||||||
@ -372,16 +375,17 @@ grow_hash_table (struct hash_table *ht)
|
|||||||
ht->resize_threshold = newsize * HASH_MAX_FULLNESS;
|
ht->resize_threshold = newsize * HASH_MAX_FULLNESS;
|
||||||
|
|
||||||
mappings = xnew_array (struct mapping, newsize);
|
mappings = xnew_array (struct mapping, newsize);
|
||||||
memset (mappings, 255, newsize * sizeof (struct mapping));
|
memset (mappings, 0xff, newsize * sizeof (struct mapping));
|
||||||
ht->mappings = mappings;
|
ht->mappings = mappings;
|
||||||
|
|
||||||
for (mp = old_mappings; mp < old_end; mp++)
|
for (mp = old_mappings; mp < old_end; mp++)
|
||||||
if (NON_EMPTY (mp))
|
if (NON_EMPTY (mp))
|
||||||
{
|
{
|
||||||
struct mapping *new_mp = mappings + HASH_POSITION (ht, mp->key);
|
struct mapping *new_mp;
|
||||||
/* We don't need to test for uniqueness of keys because they
|
/* We don't need to test for uniqueness of keys because they
|
||||||
come from the hash table and are therefore known to be
|
come from the hash table and are therefore known to be
|
||||||
unique. */
|
unique. */
|
||||||
|
new_mp = mappings + HASH_POSITION (mp->key, hasher, newsize);
|
||||||
LOOP_NON_EMPTY (new_mp, mappings, newsize)
|
LOOP_NON_EMPTY (new_mp, mappings, newsize)
|
||||||
;
|
;
|
||||||
*new_mp = *mp;
|
*new_mp = *mp;
|
||||||
@ -432,23 +436,24 @@ hash_table_remove (struct hash_table *ht, const void *key)
|
|||||||
{
|
{
|
||||||
int size = ht->size;
|
int size = ht->size;
|
||||||
struct mapping *mappings = ht->mappings;
|
struct mapping *mappings = ht->mappings;
|
||||||
|
hashfun_t hasher = ht->hash_function;
|
||||||
|
|
||||||
mp->key = NULL;
|
mp->key = NULL;
|
||||||
--ht->count;
|
--ht->count;
|
||||||
|
|
||||||
/* Rehash all the entries following MP. The alternative
|
/* Rehash all the entries following MP. The alternative
|
||||||
approach is to mark the entry as deleted, i.e. create a
|
approach is to mark the entry as deleted, i.e. create a
|
||||||
"tombstone". That makes remove faster, but leaves a lot of
|
"tombstone". That speeds up removal, but leaves a lot of
|
||||||
garbage and slows down hash_table_get and hash_table_put. */
|
garbage and slows down hash_table_get and hash_table_put. */
|
||||||
|
|
||||||
mp = NEXT_MAPPING (mp, mappings, size);
|
mp = NEXT_MAPPING (mp, mappings, size);
|
||||||
LOOP_NON_EMPTY (mp, mappings, size)
|
LOOP_NON_EMPTY (mp, mappings, size)
|
||||||
{
|
{
|
||||||
const void *key2 = mp->key;
|
const void *key2 = mp->key;
|
||||||
struct mapping *mp_new = mappings + HASH_POSITION (ht, key2);
|
struct mapping *mp_new;
|
||||||
|
|
||||||
/* Find the new location for the key. */
|
/* Find the new location for the key. */
|
||||||
|
mp_new = mappings + HASH_POSITION (key2, hasher, size);
|
||||||
LOOP_NON_EMPTY (mp_new, mappings, size)
|
LOOP_NON_EMPTY (mp_new, mappings, size)
|
||||||
if (key2 == mp_new->key)
|
if (key2 == mp_new->key)
|
||||||
/* The mapping MP (key2) is already where we want it (in
|
/* The mapping MP (key2) is already where we want it (in
|
||||||
@ -472,7 +477,7 @@ hash_table_remove (struct hash_table *ht, const void *key)
|
|||||||
void
|
void
|
||||||
hash_table_clear (struct hash_table *ht)
|
hash_table_clear (struct hash_table *ht)
|
||||||
{
|
{
|
||||||
memset (ht->mappings, '\0', ht->size * sizeof (struct mapping));
|
memset (ht->mappings, 0xff, ht->size * sizeof (struct mapping));
|
||||||
ht->count = 0;
|
ht->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user