From: Michael D. Lowis Date: Mon, 25 May 2015 21:23:33 +0000 (-0400) Subject: Initial implementation of map X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=51dcf9dc5fdaf1564faa37e2e2bb9a5ccad3f048;p=projs%2Flibcds.git Initial implementation of map --- diff --git a/source/map/map.c b/source/map/map.c new file mode 100644 index 0000000..f9b37c5 --- /dev/null +++ b/source/map/map.c @@ -0,0 +1,95 @@ +/** + @file map.c + @brief See header for details +*/ +#include "map.h" + +typedef struct { + uint32_t hash; + void* key; + void* value; +} map_pair_t; + +struct map_t { + hashfn_t hash_func; + rbt_t* tree; +}; + +static void map_pair_free(void* obj) +{ + mem_release(((map_pair_t*)obj)->key); + mem_release(((map_pair_t*)obj)->value); +} + +static map_pair_t* map_pair_new(uint32_t hash, void* key, void* value) +{ + map_pair_t* pair = (map_pair_t*)mem_allocate(sizeof(map_pair_t), &map_pair_free); + pair->key = key; + pair->value = value; + pair->hash = hash; + return pair; +} + +static void map_free(void* obj) +{ + mem_release(((map_t*)obj)->tree); +} + +static int map_compare_nodes(void* env, void* p_a, void* p_b) +{ + int cmp; + cmp_t* user_comp = (cmp_t*)env; + map_pair_t* pair_a = (map_pair_t*)p_a; + map_pair_t* pair_b = (map_pair_t*)p_b; + if (pair_a->hash < pair_b->hash) { + cmp = -1; + } else if (pair_a->hash > pair_b->hash) { + cmp = 1; + } else { + cmp = cmp_compare(user_comp, pair_a->key, pair_b->key); + } + return cmp; +} + +map_t* map_new(cmp_t* cmp, hashfn_t hash_fn) +{ + map_t* map = (map_t*)mem_allocate(sizeof(map_t), &map_free); + cmp_t* comp = cmp_new(cmp, &map_compare_nodes); + map->hash_func = hash_fn; + map->tree = rbt_new(comp); + return map; +} + +bool map_has_key(map_t* map, void* key) +{ + return (NULL != map_lookup(map, key)); +} + +size_t map_size(map_t* map) +{ + return rbt_size(map->tree); +} + +void* map_lookup(map_t* map, void* key) +{ + map_pair_t pair = { map->hash_func(key), key, NULL }; + rbt_node_t* curr = rbt_lookup(map->tree, &pair); + void* value = (NULL == curr) ? NULL : ((map_pair_t*)curr->contents)->value; + return value; +} + +void map_insert(map_t* map, void* key, void* value) +{ + map_pair_t* pair = map_pair_new(map->hash_func(key), key, value); + if (!rbt_lookup(map->tree, pair)) + rbt_insert(map->tree, pair); + else + mem_release(pair); +} + +void map_delete(map_t* map, void* key) +{ + map_pair_t pair = { map->hash_func(key), key, NULL }; + rbt_delete(map->tree, &pair); +} + diff --git a/source/map/map.h b/source/map/map.h index e69de29..e747903 100644 --- a/source/map/map.h +++ b/source/map/map.h @@ -0,0 +1,83 @@ +/** + @file map.h + @brief Implementation of a HashMap data structure. +*/ +#ifndef MAP_H +#define MAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "rbt.h" + +/** Function pointer that returns the 32-bit hash of the given object. */ +typedef uint32_t (*hashfn_t)(void* obj); + +/* map data structure */ +struct map_t; + +/* map stat structure type alias */ +typedef struct map_t map_t; + +/** + * @brief Create a new map with the provided comparator and hash function. + * + * @param cmp User-provided comparator. + * @param hash_fn User provided hash function. + * + * @return The new map. + */ +map_t* map_new(cmp_t* cmp, hashfn_t hash_fn); + +/** + * @brief Determines whether the map contains the given key or not. + * + * @param map The map to search. + * @param key The key to search for. + * + * @return True if the map has the key, false otherwise. + */ +bool map_has_key(map_t* map, void* key); + +/** + * @brief Returns the number of key/value pairs in the map. + * + * @param map The map. + * + * @return The number of keys. + */ +size_t map_size(map_t* map); + +/** + * @brief Lookup a value by key. + * + * @param map The map. + * @param key The key to lookup. + * + * @return The value associated with the key or null if no association exists. + */ +void* map_lookup(map_t* map, void* key); + +/** + * @brief Associate the key with the given value in map. + * + * @param map The map. + * @param key The key. + * @param value The value. + */ +void map_insert(map_t* map, void* key, void* value); + +/** + * @brief Delete the given key/value association from the map. + * + * @param map The map. + * @param key The key of the association to delete. + */ +void map_delete(map_t* map, void* key); + +#ifdef __cplusplus +} +#endif + +#endif /* MAP_H */