]> git.mdlowis.com Git - projs/libcds.git/commitdiff
Initial implementation of map
authorMichael D. Lowis <mike@mdlowis.com>
Mon, 25 May 2015 21:23:33 +0000 (17:23 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Mon, 25 May 2015 21:23:33 +0000 (17:23 -0400)
source/map/map.c [new file with mode: 0644]
source/map/map.h

diff --git a/source/map/map.c b/source/map/map.c
new file mode 100644 (file)
index 0000000..f9b37c5
--- /dev/null
@@ -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);
+}
+
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e7479032218712c62fc5fc1cf6bdee9cf4a8b47a 100644 (file)
@@ -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 */