From b2f7c91f6a9f8fe2ea2066e5b376b9e58ec7d3e5 Mon Sep 17 00:00:00 2001 From: Nicholas Chambers Date: Fri, 18 May 2018 09:01:02 -0500 Subject: [PATCH] Add the basic codebase to the repository --- include/hashmap.h | 20 +++++++++ include/linkedlist.h | 16 ++++++++ include/node.h | 14 +++++++ src/hashmap.c | 98 ++++++++++++++++++++++++++++++++++++++++++++ src/linkedlist.c | 41 ++++++++++++++++++ src/node.c | 23 +++++++++++ 6 files changed, 212 insertions(+) create mode 100644 include/hashmap.h create mode 100644 include/linkedlist.h create mode 100644 include/node.h create mode 100644 src/hashmap.c create mode 100644 src/linkedlist.c create mode 100644 src/node.c diff --git a/include/hashmap.h b/include/hashmap.h new file mode 100644 index 0000000..dc2b118 --- /dev/null +++ b/include/hashmap.h @@ -0,0 +1,20 @@ +#ifndef __HASHMAP_HASHMAP_H +#define __HASHMAP_HASHMAP_H + +#include + +#define BUCKET_SIZE 64 + +struct hashmap { + struct ll buckets[BUCKET_SIZE]; +}; + +struct hashmap new_map(); +void insert_map(struct hashmap *map, const char *key, const char *value); +const char *lookup_map(struct hashmap *map, const char *key); +int exists_map(struct hashmap *map, const char *key); +const char *remove_map(struct hashmap *map, const char *key); +void foreach_map(struct hashmap *map, void (*cb)(const char *key, const char *value)); +void print_map(struct hashmap *map); + +#endif diff --git a/include/linkedlist.h b/include/linkedlist.h new file mode 100644 index 0000000..622c0f5 --- /dev/null +++ b/include/linkedlist.h @@ -0,0 +1,16 @@ +#ifndef __HASHMAP_LINKEDLIST_H +#define __HASHMAP_LINKEDLIST_H + +#include + +struct ll { + struct node *list; + struct node *head; + struct node *tail; +}; + +struct new_ll(); +void insert_ll(struct ll *list, const char *key, const char *value); +void remove_ll(struct ll *list, struct node *link); + +#endif diff --git a/include/node.h b/include/node.h new file mode 100644 index 0000000..c3456f5 --- /dev/null +++ b/include/node.h @@ -0,0 +1,14 @@ +#ifndef __HASHMAP_NODE_H +#define __HASHMAP_NODE_H + +struct node { + struct node *next; + struct node *prev; + const char *key; + const char *value; +}; + +struct node *new_node(const char *key, const char *value); +struct node *insert_node(struct node *entry, const char *key, const char *value); + +#endif diff --git a/src/hashmap.c b/src/hashmap.c new file mode 100644 index 0000000..d7e2bde --- /dev/null +++ b/src/hashmap.c @@ -0,0 +1,98 @@ +#include + +struct hashmap new_map() { + struct hashmap new; + + for(int count = 0; count < BUCKET_SIZE; ++count) { + new.buckets[count] = new_ll(); + } + + return new; +} + +static unsigned int hash_map(const char *str) { + unsigned int val = 0, high; + + while (*str) { + val = ( val << 4 ) + *str++; + + if((high = val & 0xF0000000) != 0) { + val ^= high >> 24; + } + + val &= ~high; + } + + return val % BUCKET_SIZE; +} + +void insert_map(struct hashmap *map, const char *key, const char *value) { + if(key == NULL) { + return; + } + + int index = hash_map(key); + + for(struct node *iter = map->buckets[index].head; iter != NULL; iter = iter->next) { + if(strcmp(iter->key, key) == 0) { + iter->value = value; + return; + } + } + + insert_ll(&map->buckets[index], key, value); +} + +const char *lookup_map(struct hashmap *map, const char *key) { + if(key == NULL) { + return NULL; + } + + int index = hash_map(key); + + for(struct node *iter = map->buckets[index].head; iter != NULL; iter = iter->next) { + if(strcmp(iter->key, key) == 0) { + return iter->value; + } + } + + return NULL; +} + +int exists_map(struct hashmap *map, const char *key) { + return lookup_map(map, key) != NULL; +} + +const char *remove_map(struct hashmap *map, const char *key) { + if(key == NULL) { + return NULL; + } + + int index = hash_map(key); + + for(struct node *iter = map->buckets[index].head; iter != NULL; iter = iter->next) { + if(strcmp(iter->key, key) == 0) { + const char *value = iter->value; + remove_ll(&map->buckets[index], iter); + return value; + } + } + + return NULL; +} + +void foreach_map(struct hashmap *map, void (*cb)(const char *key, const char *value)) { + for(int count = 0; count < BUCKET_SIZE; ++count) { + for(struct node *iter = map->buckets[count].head; iter != NULL; iter = iter->next) { + cb(iter->key, iter->value); + } + } +} + +static void print_value_map(const char *key, const char *value) { + printf("%s: %s\n", key, value); +} + +void print_map(struct hashmap *map) { + foreach_map(map, &print_value_map); +} diff --git a/src/linkedlist.c b/src/linkedlist.c new file mode 100644 index 0000000..38ec049 --- /dev/null +++ b/src/linkedlist.c @@ -0,0 +1,41 @@ +#include + +struct ll new_ll() { + struct ll new; + new.list = NULL; + new.head = NULL; + new.tail = NULL; + return new; +} + +void insert_ll(struct ll *list, const char *key, const char *value) { + list->list = insert_node(list->tail, key, value); + list->tail = list->list; + + if(list->head == NULL) { + list->head = list->list; + } +} + +void remove_ll(struct ll *list, struct node *link) { + if(link == list->head && link == list->tail) { + list->head = NULL; + list->tail = NULL; + } else if(link == list->head) { + list->head = list->head->next; + list->head->prev = NULL; + } else if(link == list->tail) { + list->tail = list->tail->prev; + list->tail->next = NULL; + } else { + link->prev->next = link->next; + link->next->prev = link->prev; + } + + link->next = NULL; + link->prev = NULL; + link->key = NULL; + link->value = NULL; + free(link); + link = NULL; +} diff --git a/src/node.c b/src/node.c new file mode 100644 index 0000000..14ce831 --- /dev/null +++ b/src/node.c @@ -0,0 +1,23 @@ +#include +#include + +struct node *new_node(const char *key, const char *value) { + struct node *new = calloc(1, sizeof(struct node)); + new->next = NULL; + new->prev = NULL; + new->key = key; + new->value = value; + return new; +} + +struct node *insert_node(struct node *entry, const char *key, const char *value) { + struct node *insert = new_node(key, value); + insert->prev = entry; + + if(entry != NULL) { + insert->next = entry->next; + entry->next = insert; + } + + return insert; +}