// -*- c++ -*- /** * A C++ wrapper around uthash. */ #ifndef HASH_MAP #define HASH_MAP #include #include "../uthash/uthash.h" template class hash_map { struct map_entry { K key; V value; UT_hash_handle hh; }; map_entry * _head; public: hash_map(); ~hash_map(); /** * Associates a value with the specified key in this hash map. * If a mapping already exists the old value is replaced. * * returns: * true if the mapping was successfully created and false otherwise. */ bool put(K key, V value); /** * Updates the value associated with the specified key in this hash map. * * returns: * true if the value was updated, or false if the key was not found. */ bool set(K key, V value); /** * Gets the value associated with the specified key in this hash map. * * returns: * true if the value was found and updates the specified *value parameter * with the associated value, or false otherwise. */ bool get(K key, V *value); /** * Removes a key-value pair from this hash map. * * returns: * true if a key-value pair exists and updates the specified * *key and *value parameters, or false otherwise. */ bool pop(K *key, V *value); /** * Checks if the specified key exists in this hash map. * * returns: * true if the specified key exists in this hash map, or false otherwise. */ bool contains(K key); /** * Removes the value associated with the specified key from this hash map. * * returns: * true if the specified key exists and updates the specified *old_value * parameter with the associated value, or false otherwise. */ bool remove(K key, V *old_value); bool remove(K key); /** * Returns the number of key-value pairs in this hash map. */ size_t count(); bool is_empty() { return count() == 0; } /** * Clears all the key-value pairs in this hash map. * * returns: * the number of deleted key-value pairs. */ size_t clear(); }; template hash_map::hash_map() { _head = NULL; } template hash_map::~hash_map() { clear(); } template bool hash_map::put(K key, V value) { if (contains(key)) { return set(key, value); } map_entry *entry = (map_entry *) malloc(sizeof(map_entry)); entry->key = key; entry->value = value; HASH_ADD(hh, _head, key, sizeof(K), entry); return true; } template bool hash_map::get(K key, V *value) { map_entry *entry = NULL; HASH_FIND(hh, _head, &key, sizeof(K), entry); if (entry == NULL) { return false; } *value = entry->value; return true; } template bool hash_map::set(K key, V value) { map_entry *entry = NULL; HASH_FIND(hh, _head, &key, sizeof(K), entry); if (entry == NULL) { return false; } entry->value = value; return true; } template bool hash_map::contains(K key) { V value; return get(key, &value); } template bool hash_map::remove(K key, V *old_value) { map_entry *entry = NULL; HASH_FIND(hh, _head, &key, sizeof(K), entry); if (entry == NULL) { return false; } *old_value = entry->value; HASH_DEL(_head, entry); free(entry); return true; } template bool hash_map::pop(K *key, V *value) { if (is_empty()) { return false; } map_entry *entry = _head; HASH_DEL(_head, entry); *key = entry->key; *value = entry->value; free(entry); return true; } template bool hash_map::remove(K key) { V old_value; return remove(key, &old_value); } template size_t hash_map::count() { return HASH_CNT(hh, _head); } template size_t hash_map::clear() { size_t deleted_entries = 0; while (_head != NULL) { map_entry *entry = _head; HASH_DEL(_head, entry); free(entry); deleted_entries ++; } assert(count() == 0); return deleted_entries; } #endif /* HASH_MAP */