|
| static hnode_t * | hnode_alloc (void *context) |
| static void | hnode_free (hnode_t *node, void *context) |
| static hash_val_t | hash_fun_default (const void *key) |
| static int | hash_comp_default (const void *key1, const void *key2) |
| static void | compute_bits (void) |
| | Compute the number of bits in the hash_val_t type.
|
| static int | is_power_of_two (hash_val_t arg) |
| static void | clear_table (hash_t *hash) |
| static void | grow_table (hash_t *hash) |
| | Double the size of a dynamic table.
|
| static void | shrink_table (hash_t *hash) |
| | Cut a table size in half.
|
| hash_t * | hash_create (hashcount_t maxcount, hash_comp_t compfun, hash_fun_t hashfun) |
| | Create a dynamic hash table.
|
| void | hash_set_allocator (hash_t *hash, hnode_alloc_t al, hnode_free_t fr, void *context) |
| void | hash_free_nodes (hash_t *hash) |
| void | hash_destroy (hash_t *hash) |
| void | hash_scan_begin (hscan_t *scan, hash_t *hash) |
| | Initialize a hash scanner.
|
| hnode_t * | hash_scan_next (hscan_t *scan) |
| | Retrieve the next node from the hash table, and update the pointer for the next invocation of hash_scan_next().
|
| void | hash_insert (hash_t *hash, hnode_t *node, const void *key) |
| | Insert a node into the hash table.
|
| hnode_t * | hash_lookup (hash_t *hash, const void *key) |
| | Find a node in the hash table and return a pointer to it.
|
| hnode_t * | hash_delete (hash_t *hash, hnode_t *node) |
| | Delete the given node from the hash table. Since the chains are singly linked, we must locate the start of the node's chain and traverse.
|
| int | hash_alloc_insert (hash_t *hash, const void *key, void *data) |
| void | hash_delete_free (hash_t *hash, hnode_t *node) |
| hnode_t * | hash_scan_delete (hash_t *hash, hnode_t *node) |
| void | hash_scan_delfree (hash_t *hash, hnode_t *node) |
| int | hash_verify (hash_t *hash) |
| | Verify whether the given object is a valid hash table.
|
| hnode_t * | hnode_init (hnode_t *hnode, void *data) |
| void * | hnode_get (hnode_t *node) |
| const void * | hnode_getkey (hnode_t *node) |
| hashcount_t | hash_count (hash_t *hash) |
| hashcount_t | hash_size (hash_t *hash) |
| void grow_table |
( |
hash_t * | hash | ) |
|
|
static |
Double the size of a dynamic table.
This works as follows. Each chain splits into two adjacent chains. The shift amount increases by one, exposing an additional bit of each hashed key. For each node in the original chain, the value of this newly exposed bit will decide which of the two new chains will receive the node: if the bit is 1, the chain with the higher index will have the node, otherwise the lower chain will receive the node. In this manner, the hash table will continue to function exactly as before without having to rehash any of the keys.
- Note
- Overflow check.
- The new number of chains is twice the old number of chains.
- The new mask is one bit wider than the previous, revealing a new bit in all hashed keys.
- Allocate a new table of chain pointers that is twice as large as the previous one.
- If the reallocation was successful, we perform the rest of the growth algorithm, otherwise we do nothing.
- The exposed_bit variable holds a mask with which each hashed key can be AND-ed to test the value of its newly exposed bit.
- Now loop over each chain in the table and sort its nodes into two chains based on the value of each node's newly exposed hash bit.
- The low chain replaces the current chain. The high chain goes into the corresponding sister chain in the upper half of the table.
- We have finished dealing with the chains and nodes. We now update the various bookeeping fields of the hash structure.