util: Simple hash table implementation.
authorTaekyun Kim <tkq.kim@samsung.com>
Tue, 19 May 2015 08:07:59 +0000 (17:07 +0900)
committerTaekyun Kim <tkq.kim@samsung.com>
Fri, 19 Jun 2015 09:06:41 +0000 (18:06 +0900)
Change-Id: I5992e76740ea1b3d4a78539ab377d3e7146b9af7

src/Makefile.am
src/pepper-util.c [new file with mode: 0644]
src/pepper-util.h

index 2ee747d..e122db4 100644 (file)
@@ -26,7 +26,8 @@ libpepper_la_SOURCES = pepper.h                 \
                        data-device.c            \
                        view.c                   \
                        layer.c                  \
-                       pepper-util.h
+                       pepper-util.h            \
+                       pepper-util.c
 
 # gl renderer
 if ENABLE_GL_RENDERER
diff --git a/src/pepper-util.c b/src/pepper-util.c
new file mode 100644 (file)
index 0000000..f5f1b2f
--- /dev/null
@@ -0,0 +1,195 @@
+#include "pepper-util.h"
+
+struct pepper_map_entry
+{
+    const void         *key;
+    void               *data;
+    pepper_free_func_t  free_func;
+    pepper_map_entry_t *next;
+};
+
+struct pepper_map
+{
+    pepper_hash_func_t          hash_func;
+    pepper_key_length_func_t    key_length_func;
+    pepper_key_compare_func_t   key_compare_func;
+
+    int                         bucket_bits;
+    int                         bucket_size;
+    int                         bucket_mask;
+    pepper_map_entry_t        **buckets;
+};
+
+static inline int
+get_bucket_index(pepper_map_t *map, const void *key)
+{
+    int                 key_length = 0;
+    int                 hash;
+
+    if (map->key_length_func)
+        key_length = map->key_length_func(key);
+
+    hash = map->hash_func(key, key_length);
+    return hash & map->bucket_mask;
+}
+
+static inline pepper_map_entry_t **
+get_bucket(pepper_map_t *map, const void *key)
+{
+    return &map->buckets[get_bucket_index(map, key)];
+}
+
+pepper_map_t *
+pepper_map_create(int                       bucket_bits,
+                  pepper_hash_func_t        hash_func,
+                  pepper_key_length_func_t  key_length_func,
+                  pepper_key_compare_func_t key_compare_func)
+{
+    pepper_map_t *map;
+
+    map = pepper_calloc(1, sizeof(pepper_map_t));
+    if (!map)
+        return NULL;
+
+    map->hash_func = hash_func;
+    map->key_length_func = key_length_func;
+    map->key_compare_func = key_compare_func;
+
+    map->bucket_bits = bucket_bits;
+    map->bucket_size = 1 << bucket_bits;
+    map->bucket_mask = map->bucket_size - 1;
+
+    map->buckets = pepper_calloc(map->bucket_size, sizeof(pepper_map_entry_t *));
+    if (!map->buckets)
+    {
+        free(map);
+        return NULL;
+    }
+
+    return map;
+}
+
+void
+pepper_map_clear(pepper_map_t *map)
+{
+    int i;
+
+    for (i = 0; i < map->bucket_size; i++)
+    {
+        pepper_map_entry_t *curr = map->buckets[i];
+
+        while (curr)
+        {
+            pepper_map_entry_t *next = curr->next;
+
+            if (curr->free_func)
+                curr->free_func(curr->data);
+
+            free(curr);
+            curr = next;
+        }
+    }
+
+    memset(map->buckets, 0x00, map->bucket_size * sizeof(pepper_map_entry_t *));
+}
+
+void
+pepper_map_destroy(pepper_map_t *map)
+{
+    pepper_map_clear(map);
+    free(map->buckets);
+    free(map);
+}
+
+void *
+pepper_map_get(pepper_map_t *map, const void *key)
+{
+    pepper_map_entry_t *curr = *get_bucket(map, key);
+
+    while (curr)
+    {
+        int len0 = 0;
+        int len1 = 0;
+
+        if (map->key_length_func)
+        {
+            len0 = map->key_length_func(curr->key);
+            len1 = map->key_length_func(key);
+        }
+
+        if (map->key_compare_func(curr->key, len0, key, len1) == 0)
+            return &curr->data;
+
+        curr = curr->next;
+    }
+
+    return NULL;
+}
+
+void
+pepper_map_set(pepper_map_t *map, const void *key, void *data, pepper_free_func_t free_func)
+{
+    pepper_map_entry_t    **bucket = get_bucket(map, key);
+    pepper_map_entry_t     *curr = *bucket;
+    pepper_map_entry_t     *prev = NULL;
+
+    /* Find existing entry for the key. */
+    while (curr)
+    {
+        int len0 = 0;
+        int len1 = 0;
+
+        if (map->key_length_func)
+        {
+            len0 = map->key_length_func(curr->key);
+            len1 = map->key_length_func(key);
+        }
+
+        if (map->key_compare_func(curr->key, len0, key, len1) == 0)
+        {
+            /* Free previous data. */
+            if (curr->free_func)
+                curr->free_func(curr->data);
+
+            if (data)
+            {
+                /* Set new data. */
+                curr->data = data;
+                curr->free_func = free_func;
+            }
+            else
+            {
+                /* Delete entry. */
+                if (prev)
+                    prev->next = curr->next;
+                else
+                    *bucket = curr->next;
+
+                free(curr);
+            }
+
+            return;
+        }
+
+        prev = curr;
+        curr = curr->next;
+    }
+
+    if (data == NULL)
+    {
+        /* Nothing to delete. */
+        return;
+    }
+
+    /* Allocate a new entry. */
+    curr = malloc(sizeof(pepper_map_entry_t));
+    PEPPER_ASSERT(curr != NULL);
+
+    curr->key = key;
+    curr->data = data;
+    curr->free_func = free_func;
+
+    /* Insert at the head of the bucket. */
+    curr->next = *bucket;
+    *bucket = curr;
+}
index 33edee2..dee3488 100644 (file)
@@ -1,7 +1,9 @@
 #ifndef PEPPER_UTIL_H
 #define PEPPER_UTIL_H
 
+#include "common.h"
 #include <stdlib.h>
+#include <string.h>
 
 typedef struct pepper_list  pepper_list_t;
 typedef void (*pepper_free_func_t)(void *);
@@ -130,4 +132,30 @@ pepper_list_insert_list(pepper_list_t *list, pepper_list_t *other)
     list->next = other->next;
 }
 
+typedef struct pepper_map_entry pepper_map_entry_t;
+typedef struct pepper_map       pepper_map_t;
+
+typedef int (*pepper_hash_func_t)(const void *key, int key_length);
+typedef int (*pepper_key_length_func_t)(const void *key);
+typedef int (*pepper_key_compare_func_t)(const void *key0, int key0_length,
+                                         const void *key1, int key1_length);
+
+pepper_map_t *
+pepper_map_create(int                       bucket_bits,
+                  pepper_hash_func_t        hash_func,
+                  pepper_key_length_func_t  key_length_func,
+                  pepper_key_compare_func_t key_compare_func);
+
+void
+pepper_map_clear(pepper_map_t *map);
+
+void
+pepper_map_destroy(pepper_map_t *map);
+
+void *
+pepper_map_get(pepper_map_t *map, const void *key);
+
+void
+pepper_map_set(pepper_map_t *map, const void *key, void *data, pepper_free_func_t free_func);
+
 #endif /* PEPPER_UTIL_H */