From ac136d4ffb933550f71fd41cc5ec7f287b6f6f62 Mon Sep 17 00:00:00 2001 From: Arek Date: Sat, 29 Jun 2024 23:18:00 +0200 Subject: [PATCH] Generic hash implementation --- CMakeLists.txt | 1 + hashtable.c | 130 ++++++++++++++++++++++++++++++++++++++++++++ include/hashtable.h | 71 ++++++++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 hashtable.c create mode 100644 include/hashtable.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f8f6769..6ac2f99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ set(SOURCES wlgol.c tkeyboard.c tpointer.c + hashtable.c ${CMAKE_CURRENT_BINARY_DIR}/xdg-shell.c ) diff --git a/hashtable.c b/hashtable.c new file mode 100644 index 0000000..4134e0c --- /dev/null +++ b/hashtable.c @@ -0,0 +1,130 @@ +// implementation of a hashtable + +#include +#include +#include + +#include "hashtable.h" + + +/** + * @brief Hash function for hashtable + * + * This function takes a string key and calculates a hash value. + * The hash value is used to determine the index in the hashtable + * where the key-value pair should be stored. + * + * @param key The string key to hash + * @return The calculated hash value + */ +static unsigned int hash(const char *key) +{ + unsigned int hash = 0; // Initialize hash value to 0 + + // Iterate over each character in the key string + while (*key) + { + // Calculate the hash value by multiplying the current hash value + // with 32 (2^5) and subtracting the current hash value. Then add the + // ASCII value of the current character. + hash = (hash << 5) - hash + *key++; + } + + // Return the calculated hash value + return hash; +} + +/** + * @brief Create a new hashtable + * + * This function creates a new hashtable with the specified size. + * It initializes the table with NULL entries. + * + * @param size The size of the hashtable + * @return A pointer to the newly created hashtable + */ +hashtable *hashtable_new(int size) +{ + // Allocate memory for the hashtable + hashtable *h = malloc(sizeof(hashtable)); + + // Set the size of the hashtable + h->size = size; + + // Allocate memory for the entry pointers + h->table = malloc(sizeof(entry *) * size); + + // Initialize all entries to NULL + for (int i = 0; i < size; i++) + { + h->table[i] = NULL; + } + + // Return the newly created hashtable + return h; +} + + +// hashtable_insert +void hashtable_insert(hashtable *h, const char *key, void *value) { + + // Calculate the index using the hash function + int index = hash(key) % h->size; + + // Create a new entry + entry *e = malloc(sizeof(entry)); + e->key = key; + e->value = value; + e->next = NULL; + + // Insert the entry at the beginning of the linked list + e->next = h->table[index]; + h->table[index] = e; + + return; +} + + +// hashtable_lookup +void *hashtable_lookup(hashtable *h, const char *key) { + + // Calculate the index using the hash function + int index = hash(key) % h->size; + + // Traverse the linked list at the index + entry *e = h->table[index]; + while (e != NULL) { + if (strcmp(e->key, key) == 0) { + return e->value; + } + e = e->next; + } + + // Return NULL if the key is not found + return NULL; +} + + +// hashtable_remove +void hashtable_remove(hashtable *h, const char *key) { + + // Calculate the index using the hash function + int index = hash(key) % h->size; + + // Traverse the linked list at the index + entry *e = h->table[index]; + entry *prev = NULL; + while (e != NULL) { + if (strcmp(e->key, key) == 0) { + if (prev == NULL) { + h->table[index] = e->next; + } else { + prev->next = e->next; + } + free(e); + return; + } + prev = e; + e = e->next; + } +} diff --git a/include/hashtable.h b/include/hashtable.h new file mode 100644 index 0000000..2fc59ea --- /dev/null +++ b/include/hashtable.h @@ -0,0 +1,71 @@ +#ifndef HASHTABLE_H +#define HASHTABLE_H + +#include +#include + +// entry in the hashtable +typedef struct entry +{ + const char *key; + void *value; + struct entry *next; +} entry; + +// hashtable +typedef struct +{ + int size; + entry **table; +} hashtable; + +/** + * @brief Create a new hashtable + * + * This function creates a new hashtable with the specified size. + * It initializes the table with NULL entries. + * + * @param size The size of the hashtable + * @return A pointer to the newly created hashtable + */ +hashtable *hashtable_new(int size); + +/** + * @brief Insert a new key-value pair into the hashtable + * + * This function inserts a new key-value pair into the hashtable. + * It calculates the index using the hash function and inserts the + * key-value pair at the beginning of the linked list at that index. + * + * @param h Pointer to the hashtable + * @param key Pointer to the key + * @param value Pointer to the value + */ +void hashtable_insert(hashtable *h, const char *key, void *value); + +/** + * @brief Get the value associated with a key from the hashtable + * + * This function takes a hashtable and a key as input and returns the + * value associated with the key. If the key is not found in the + * hashtable, it returns NULL. + * + * @param h Pointer to the hashtable + * @param key Pointer to the key + * @return Pointer to the value associated with the key, or NULL if not found + */ +void *hashtable_lookup(hashtable *h, const char *key); + +/** + * @brief Remove a key-value pair from the hashtable + * + * This function removes a key-value pair from the hashtable. + * It calculates the index using the hash function and traverses + * the linked list at that index. If the key is found, it removes + * the corresponding entry from the linked list and frees the memory. + * + * @param h Pointer to the hashtable + * @param key Pointer to the key to remove + */ +void hashtable_remove(hashtable *h, const char *key); +#endif -- 2.45.1