static void mt_hash_insert_pair(MtHash* hash, MtPair* pair) { assert(hash != NULL); assert(pair != NULL); size_t index = pair->key->hash % hash->size; MtPair* element = hash->buckets[index]; // No Collision if (element == NULL) { hash->buckets[index] = pair; ++hash->length; // Expand the hash if necessary if (hash->length >= 0.75 * hash->size) mt_hash_double_size(hash); } // Collision handling, linear probing while (element != NULL) { // Key already exists in the hash, replace the value if (mt_string_compare(element->key, pair->key) == 0) { hash->buckets[index] = pair; return; } ++index; index %= hash->size; element = hash->buckets[index]; } }
void mt_hash_move_pair(MtHash* hash, MtPair* pair) { assert(hash != NULL); assert(pair != NULL); // Can only be moved from another hash // Had better have a key if that is the case assert(pair->key->hash != 0); size_t index = pair->key->hash % hash->size; MtHashElement* element = &hash->buckets[index]; assert(element != NULL); // Collision if (element->data != NULL) { // Standard Collision if (element->is_tree) { mt_tree_move_pair((MtTree*) element->data, pair); } // First Collision else { // Have to handle both pairs being moved into the tree MtPair* old_pair = element->data; element->data = mt_tree_new(); mt_tree_move_pair((MtTree*) element->data, pair); mt_tree_move_pair((MtTree*) element->data, old_pair); element->is_tree = true; } } // No Collision else { element->data = pair; ++hash->length; // Grow the table if is 75% or more full if (hash->length >= 0.75 * hash->size) mt_hash_double_size(hash); } }
void mt_hash_insert(MtHash* hash, MtString* key, void* value) { assert(hash != NULL); assert(key != NULL); if (key->hash == 0) key->hash = Murmur3(mt_string_get_utf8(key), mt_string_get_length(key)); size_t index = key->hash % hash->size; MtHashElement* element = &hash->buckets[index]; assert(element != NULL); // Collision handling if (element->data != NULL) { if (element->is_tree) { // Collision, tree already made mt_tree_insert((MtTree *) element->data, key, value); } else { // First collision, make a tree MtPair* pair = element->data; element->data = mt_tree_new(); mt_tree_move_pair((MtTree *) element->data, pair); ++hash->length; mt_tree_insert((MtTree *) element->data, key, value); element->is_tree = true; } } // No collision else { element->data = mt_pair_new(key, value); ++hash->length; if (hash->length >= 0.75 * hash->size) mt_hash_double_size(hash); } }