|
| static bool | is_collision_node (void *p) |
| | Return true if the pointer's LSB is 1 indicating a collision.
|
| |
| static hmap_collision_t * | untag_ptr (void *ptr) |
| | Since for non collision nodes the LSB is 0 then we don't need to untag it.
|
| |
| static void * | tag_ptr (void *ptr) |
| |
| hmap_hash_t | hmap_hash (srn_context_t *ctx, const void *data, size_t len) |
| | This is a simple hack to mock the hash function during tests to force a high collision hashing function.
|
| |
| static bool | hmap_key_equal (const hmap_key_t *a, const hmap_key_t *b) |
| | Compare key a with key b
|
| |
| static bool | is_key_in_collision_node (const hmap_control_t *ctl, srn_context_t *ctx, hmap_collision_t *head, hmap_hash_t hash, hmap_key_t *k) |
| |
| static uint32_t | hmap_hash_fragment (hmap_hash_t hash, uint8_t shift) |
| | Extract a HMAP_MAK-bit chunk from the hash at the given shift.
|
| |
| static hmap_bitmap_t | hmap_bitpos (hmap_hash_t hash, uint8_t shift) |
| | Bit position corresponding to this fragment.
|
| |
| static size_t | hmap_popcount (hmap_bitmap_t bm) |
| |
| static size_t | hmap_number_of_entries (const hmap_node_t *node) |
| | Number of entries (data + node) in a node regardless of a data pointer or a node pointer.
|
| |
| static size_t | hmap_entry_index (const hmap_node_t *node, hmap_bitmap_t bitpos) |
| | Index in the packed entries array for a given bitpos (either datamap or nodemap).
|
| |
| static bool | hmap_has_data_at (const hmap_node_t *node, hmap_bitmap_t bitpos) |
| | Is this bitpos occupied by a data (kv) entry?
|
| |
| static bool | hmap_has_node_at (const hmap_node_t *node, hmap_bitmap_t bitpos) |
| | Is this bitpos occupied by a child node?
|
| |
| static void * | hmap_get_entry_at (const hmap_node_t *node, hmap_bitmap_t bitpos) |
| | Make sure the result with is_collision_node and case the result to either an entry or a collision node.
|
| |
| static hmap_node_t * | hmap_get_child_at (const hmap_node_t *node, hmap_bitmap_t bitpos) |
| | Fetch the child node pointer at a given bitpos; we must ensure nodemap has this bit.
|
| |
| static bool | hmap_at_max_depth (uint32_t shift) |
| |
| static hmap_kv_entry_t * | hmap_new_kv_entry (srn_context_t *ctx, hmap_hash_t hash, hmap_key_t *k, void *v) |
| | Abstract away the kv entry allocation.
|
| |
| static hmap_node_t * | create_empty_node (srn_context_t *ctx) |
| |
| static hmap_node_t * | hmap_singleton_node (srn_context_t *ctx, hmap_hash_t hash, uint32_t shift, hmap_kv_entry_t *kv) |
| |
| static hmap_data_t * | hmap_copy_entries (srn_context_t *ctx, hmap_data_t *entries, size_t count) |
| | Copy entries array into a new one, returning pointer.
|
| |
| static hmap_node_t * | hmap_merge_two_kv (srn_context_t *ctx, hmap_kv_entry_t *kv1, hmap_kv_entry_t *kv2, uint32_t shift) |
| | Merge two distinct kv entries into a sub-trie.
|
| |
| static hmap_node_t * | hmap_insert_node (const hmap_control_t *ctl, srn_context_t *ctx, const hmap_node_t *node, hmap_hash_t hash, hmap_key_t *k, void *v, uint32_t shift, bool *out_added) |
| | Recursively insert a new node containing the k and v.
|
| |
| void * | hmap_lookup_in_collision (const hmap_control_t *ctl, srn_context_t *ctx, hmap_collision_t *cnode, hmap_hash_t hash, const hmap_key_t *k, void *default_value) |
| |
| static void * | hmap_lookup_in_node (const hmap_control_t *ctl, srn_context_t *ctx, const hmap_node_t *node, hmap_hash_t hash, const hmap_key_t *k, uint32_t shift, void *default_value) |
| |
| static bool | hmap_internal_cmp (srn_context_t *ctx, const hmap_key_t *a, const hmap_key_t *b) |
| |
| static hmap_hash_t | hmap_hash_internal (srn_context_t *ctx, const hmap_key_t *k) |
| |
| hmap_t | hmap_insert_ctl (const hmap_control_t *ctl, srn_context_t *ctx, const hmap_t *hmap, hmap_key_t *k, void *v) |
| | Just like the hmap_insert function but, it receives a hmap_control_t to customize the comparison and hashing function.
|
| |
| void * | hmap_lookup_ctl (const hmap_control_t *ctl, srn_context_t *ctx, const hmap_t *hmap, const hmap_key_t *k, void *default_value) |
| | Just like the hmap_lookup function but, it receives a hmap_control_t to customize the comparison and hashing function.
|
| |
| hmap_t | hmap_empty (srn_context_t *ctx) |
| | Create, initialize and return a new hashmap.
|
| |
| hmap_t | hmap_insert (srn_context_t *ctx, const hmap_t *hmap, hmap_key_t *k, void *v) |
| | Insert the given key k with the value v in the given hash hmap and return the new map.
|
| |
| void * | hmap_lookup (srn_context_t *ctx, const hmap_t *hmap, const hmap_key_t *k, void *default_value) |
| | Lookup the given k in the given hmap and return the value if it's been found.
|
| |
| hmap_key_t * | hmap_make_key (srn_context_t *ctx, void *data, size_t len) |
| | Create a new key out of the given data, with the given len.
|
| |
Notes:
- Persistent: old nodes are never mutated.
- hmap_node_t->entries is a single mixed array. Positions are determined by the ascending order of set bits in (datamap | nodemap). For a given bit:
- if bit ∈ datamap -> entries[idx] is (hmap_kv_entry_t*) OR a tagged collision*
- if bit ∈ nodemap -> entries[idx] is (hmap_node_t*)
- Collision lists are stored in data positions (datamap bit set) by tagging the pointer's LSB = 1. Normal child nodes have LSB = 0.
- Collisions are linked lists that form an associated list.
Safety: pointers returned by srn_allocate are naturally aligned. We only use LSB tagging for child pointers (never for kv pointers). Untag before deref.
Definition in file hashmap.c.