void mt_hash_remove(MtHash* hash, MtString* key) { 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; MtPair* element = hash->buckets[index]; while (element != NULL) { if (mt_string_compare(key, element->key) == 0) { hash->buckets[index] = NULL; --hash->length; return; } ++index; index %= hash->size; element = hash->buckets[index]; } }
MtPair* mt_hash_search(MtHash* hash, MtString* key) { 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); // Key Collides if (element->data != NULL) { // If it is a tree, search the tree for the key if (element->is_tree) { return mt_tree_search((MtTree*) element->data, key); } else if (mt_string_compare(((MtPair*) element->data)->key, key) == 0) { return (MtPair*) element->data; } } // Nothing was found return NULL; }
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)); mt_hash_insert_pair(hash, mt_pair_new(key, value)); }
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); } }
void mt_hash_remove(MtHash* hash, MtString* key) { 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); if (element->data != NULL) { if (element->is_tree) { MtTree* tree = element->data; // Save the size before attempting to remove element from tree size_t old_size = tree->size; mt_tree_remove(tree, key); // Decrement the size of the hash by the difference in the // old and new sizes of the tree. This shouldn't ever be more than 1. assert((old_size - tree->size) <= 1); hash->length -= old_size - tree->size; } else { mt_pair_free((MtPair*) element->data); --hash->length; } } }
MtPair* mt_hash_search(MtHash* hash, MtString* key) { 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; MtPair* element = hash->buckets[index]; while (element != NULL) { if (mt_string_compare(key, element->key) == 0) return element; ++index; index %= hash->size; element = hash->buckets[index]; } // Nothing was found return NULL; }