From 5e0dfc420709a16b14635801bae79caf80b1bdef Mon Sep 17 00:00:00 2001 From: Altanis <38045884+CoderSudaWuda@users.noreply.github.com> Date: Tue, 29 Nov 2022 21:50:01 -0500 Subject: [PATCH 01/18] Create an implementation of a generic list #2 --- include/lib/list.h | 3 +- src/lib/list.c | 90 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/include/lib/list.h b/include/lib/list.h index 95c6b44..92d7601 100644 --- a/include/lib/list.h +++ b/include/lib/list.h @@ -6,7 +6,8 @@ /** Data structure for a generic list */ struct list { - //TODO + /** The initial node of the list */ + struct node* next; }; /** Initializes a new list */ diff --git a/src/lib/list.c b/src/lib/list.c index cbb429b..e6709fc 100644 --- a/src/lib/list.c +++ b/src/lib/list.c @@ -1,2 +1,90 @@ -#include "lib/list.h" +#include "lib/list.h" // struct list +#include "stdlib/stdalloc.h" // malloc, free +#include "stdlib/stdtypes.h" // bool +/** Structure of a node */ +struct node { + /** The data that a node points to */ + void* data; + /** A pointer to the next node in the list */ + struct node* next; +}; + +void list_init(struct list* l) { + l->next = NULL; +} + +void list_free(struct list* l) { + struct node* n = l->next; + while (n) { + struct node* next = n->next; + free(n); + n = next; + } +} + +void list_add(struct list* l, void* elm) { + struct node* n = malloc(sizeof(struct node)); + n->data = elm; + n->next = l->next; + l->next = n; +} + +void list_remove(struct list* l, void* elm) { + struct node* n = l->next; + struct node* prev = NULL; + while (n) { + if (n->data == elm) { + if (prev) { + prev->next = n->next; + } else { + l->next = n->next; + } + free(n); + return; + } + prev = n; + n = n->next; + } +} + +void list_clear(struct list* l) { + struct node* n = l->next; + while (n) { + struct node* next = n->next; + free(n->data); + free(n); + n = next; + } + l->next = NULL; +} + +bool list_contains(struct list* l, void* elm) { + struct node* n = l->next; + while (n) { + if (n->data == elm) { + return true; + } + n = n->next; + } + return false; +} + +size_t list_size(struct list* l) { + size_t size = 0; + struct node* n = l->next; + while (n) { + size++; + n = n->next; + } + return size; +} + +void list_to_array(struct list* l, void **buffer, size_t size) { + struct node* n = l->next; + size_t i = 0; + while (n && i < size) { + buffer[i++] = n->data; + n = n->next; + } +} \ No newline at end of file From 173c52455d44cd874584c9483177c0bb6b3f959a Mon Sep 17 00:00:00 2001 From: CoderSudaWuda <38045884+CoderSudaWuda@users.noreply.github.com> Date: Mon, 12 Dec 2022 13:52:20 -0500 Subject: [PATCH 02/18] chore: identify head of list, fix: remove freeing data --- include/lib/list.h | 18 +++++++++--------- src/lib/list.c | 23 +++++++++++------------ 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/include/lib/list.h b/include/lib/list.h index 92d7601..681ce15 100644 --- a/include/lib/list.h +++ b/include/lib/list.h @@ -7,31 +7,31 @@ /** Data structure for a generic list */ struct list { /** The initial node of the list */ - struct node* next; + struct node* head; }; /** Initializes a new list */ -void list_init(struct list *l); +void list_init(struct list* l); /** Frees the list from memory */ -void list_free(struct list *l); +void list_free(struct list* l); /** Adds the given element to the list */ -void list_add(struct list *l, void *elm); +void list_add(struct list* l, void* elm); /** Removes the given element from the list */ -void list_remove(struct list *l, void *elm); +void list_remove(struct list* l, void* elm); /** Removes all elements from the list */ -void list_clear(struct list *l); +void list_clear(struct list* l); /** Returns true if the element is in the list, false otherwise */ -bool list_contains(struct list *l, void *elm); +bool list_contains(struct list* l, void* elm); /** Returns the number of elements in the list */ -size_t list_size(struct list *l); +size_t list_size(struct list* l); /** Places the first size number of elements of the list into the given array */ -void list_to_array(struct list *l, void **buffer, size_t size); +void list_to_array(struct list* l, void** buffer, size_t size); #endif //_LIST_H_ \ No newline at end of file diff --git a/src/lib/list.c b/src/lib/list.c index e6709fc..d88b4ba 100644 --- a/src/lib/list.c +++ b/src/lib/list.c @@ -11,11 +11,11 @@ struct node { }; void list_init(struct list* l) { - l->next = NULL; + l->head = NULL; } void list_free(struct list* l) { - struct node* n = l->next; + struct node* n = l->head; while (n) { struct node* next = n->next; free(n); @@ -26,19 +26,19 @@ void list_free(struct list* l) { void list_add(struct list* l, void* elm) { struct node* n = malloc(sizeof(struct node)); n->data = elm; - n->next = l->next; - l->next = n; + n->next = l->head; + l->head = n; } void list_remove(struct list* l, void* elm) { - struct node* n = l->next; + struct node* n = l->head; struct node* prev = NULL; while (n) { if (n->data == elm) { if (prev) { prev->next = n->next; } else { - l->next = n->next; + l->head = n->next; } free(n); return; @@ -49,18 +49,17 @@ void list_remove(struct list* l, void* elm) { } void list_clear(struct list* l) { - struct node* n = l->next; + struct node* n = l->head; while (n) { struct node* next = n->next; - free(n->data); free(n); n = next; } - l->next = NULL; + l->head = NULL; } bool list_contains(struct list* l, void* elm) { - struct node* n = l->next; + struct node* n = l->head; while (n) { if (n->data == elm) { return true; @@ -72,7 +71,7 @@ bool list_contains(struct list* l, void* elm) { size_t list_size(struct list* l) { size_t size = 0; - struct node* n = l->next; + struct node* n = l->head; while (n) { size++; n = n->next; @@ -81,7 +80,7 @@ size_t list_size(struct list* l) { } void list_to_array(struct list* l, void **buffer, size_t size) { - struct node* n = l->next; + struct node* n = l->head; size_t i = 0; while (n && i < size) { buffer[i++] = n->data; From 8e0d0d803e59d364bbca2605fd44e34fda3c3c8e Mon Sep 17 00:00:00 2001 From: Altanis <38045884+Altanis@users.noreply.github.com> Date: Sun, 25 Dec 2022 23:20:40 -0500 Subject: [PATCH 03/18] Create an implementation of a generic map --- include/lib/map.h | 25 ++++++++++++++++--------- include/stdlib/stdtypes.h | 1 + src/lib/map.c | 23 +++++++++++++++++++++++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/include/lib/map.h b/include/lib/map.h index 5027ee7..fd57a9d 100644 --- a/include/lib/map.h +++ b/include/lib/map.h @@ -4,24 +4,31 @@ #include "stdlib/stdtypes.h" -/** Data structure for a generic map */ +/** Structures for a generic map. */ +struct entry { + void* key; + void* value; +}; + struct map { - //TODO + struct entry* table; + uint64_t used; + uint64_t size; }; -/** Initializes a new hashtable */ -void map_init(struct map *m); +/** Initializes a new hashmap. Returns `-1` if not allocated. */ +int map_init(struct map *m, uint64_t size); -/** Frees the hashtable from memory */ +/** Frees the hashtable from memory. */ void map_free(struct map *m); -/** Adds the key/value pair to the hashtable */ +/** Adds the key/value pair to the hashtable. */ void map_put(struct map *m, void *key, void *value); -/** Gets the value associated with the specified key */ +/** Gets the value associated with the specified key. Returns NULL if it doesn't exist. */ void *map_get(struct map *m, void *key); -/** Returns true if the hashtable contains the key, false otherwise */ -bool map_contains(struct map *m, void *key); +/** Hash function for strings. */ +uint64_t fnv_1a(char *str); #endif //_MAP_H_ \ No newline at end of file diff --git a/include/stdlib/stdtypes.h b/include/stdlib/stdtypes.h index 55547bc..42ab53c 100644 --- a/include/stdlib/stdtypes.h +++ b/include/stdlib/stdtypes.h @@ -7,6 +7,7 @@ /** Size type */ typedef unsigned int size_t; +typedef unsigned long long uint64_t; #define NULL (void *) 0 diff --git a/src/lib/map.c b/src/lib/map.c index eee6ea4..45d3746 100644 --- a/src/lib/map.c +++ b/src/lib/map.c @@ -1,2 +1,25 @@ #include "lib/map.h" +int map_init(struct map* m, uint64_t size) { + m->table = calloc(size, sizeof(struct map)); + m->size = size; + + /** Ensure map was allocated. */ + if (m->table == NULL) return -1; + else return 0; +} + +void map_free(struct map* m) { + free(m->table); +} + +void map_put(struct map* m, void* key, void* value) { + uint64_t idx = fnv_1a(key) % m->size; + m->table[idx].key = key; + m->table[idx].value = value; + m->used++; +} + +void* map_get(struct map* m, void* key) { + return m->table[fnv_1a(key) % m->size].value; +} \ No newline at end of file From ed0eac56eeeca0e41cedcb195b78700013fcbcb3 Mon Sep 17 00:00:00 2001 From: Altanis <38045884+Altanis@users.noreply.github.com> Date: Sun, 25 Dec 2022 23:54:46 -0500 Subject: [PATCH 04/18] Include fnv_1a algorithm --- src/lib/map.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/lib/map.c b/src/lib/map.c index 45d3746..42e563b 100644 --- a/src/lib/map.c +++ b/src/lib/map.c @@ -22,4 +22,16 @@ void map_put(struct map* m, void* key, void* value) { void* map_get(struct map* m, void* key) { return m->table[fnv_1a(key) % m->size].value; -} \ No newline at end of file +} + +uint64_t fnv_1a(char *str) { + size_t len = strlen(str); + uint64_t hash = 0xCBF29CE484222325; + + for (size_t i = len; i--;) { + hash ^= str[i]; + hash *= 0x00000100000001B3; + } + + return hash; +} From 2d192ff8a15940a4f63b9e3c45f55fb1a0277876 Mon Sep 17 00:00:00 2001 From: Altanis <38045884+Altanis@users.noreply.github.com> Date: Mon, 26 Dec 2022 16:37:35 -0500 Subject: [PATCH 05/18] fix: remove chance of collision, implement generic, fix format --- include/lib/map.h | 15 +++++++------ src/lib/map.c | 55 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/include/lib/map.h b/include/lib/map.h index fd57a9d..ddf4a36 100644 --- a/include/lib/map.h +++ b/include/lib/map.h @@ -6,12 +6,12 @@ /** Structures for a generic map. */ struct entry { - void* key; - void* value; + void *key; + void *value; }; struct map { - struct entry* table; + struct entry *table; uint64_t used; uint64_t size; }; @@ -23,10 +23,13 @@ int map_init(struct map *m, uint64_t size); void map_free(struct map *m); /** Adds the key/value pair to the hashtable. */ -void map_put(struct map *m, void *key, void *value); +int map_put(struct map *m, void *key, void *value, uint64_t size); -/** Gets the value associated with the specified key. Returns NULL if it doesn't exist. */ -void *map_get(struct map *m, void *key); +/** Gets the value associated with the specified key. */ +void *map_get(struct map *m, void *key, uint64_t size); + +/** Checks if key exists in hashmap. */ +bool map_contains(struct map *m, void *key, uint64_t size); /** Hash function for strings. */ uint64_t fnv_1a(char *str); diff --git a/src/lib/map.c b/src/lib/map.c index 42e563b..3e81695 100644 --- a/src/lib/map.c +++ b/src/lib/map.c @@ -1,6 +1,18 @@ #include "lib/map.h" -int map_init(struct map* m, uint64_t size) { +uint64_t fnv_1a(char *str) { + size_t len = strlen(str); + uint64_t hash = 0xCBF29CE484222325; + + for (size_t i = len; i--;) { + hash ^= str[i]; + hash *= 0x00000100000001B3; + } + + return hash; +} + +int map_init(struct map *m, uint64_t size) { m->table = calloc(size, sizeof(struct map)); m->size = size; @@ -9,29 +21,42 @@ int map_init(struct map* m, uint64_t size) { else return 0; } -void map_free(struct map* m) { +void map_free(struct map *m) { free(m->table); } -void map_put(struct map* m, void* key, void* value) { +int map_put(struct map *m, void *k, void *value, uint64_t size) { + char *key = k; uint64_t idx = fnv_1a(key) % m->size; + + if (m->table[idx].key != NULL) { + if (m->used == m->size) return -1; + + while (1) { + idx = (idx + 1) % m->size; + if (m->table[idx].key == NULL || memcmp(key, m->table[idx].key, size) == 0) break; + } + } + m->table[idx].key = key; m->table[idx].value = value; m->used++; -} -void* map_get(struct map* m, void* key) { - return m->table[fnv_1a(key) % m->size].value; + return 0; } -uint64_t fnv_1a(char *str) { - size_t len = strlen(str); - uint64_t hash = 0xCBF29CE484222325; - - for (size_t i = len; i--;) { - hash ^= str[i]; - hash *= 0x00000100000001B3; - } +void *map_get(struct map *m, void *k, uint64_t size) { + char *key = k; + uint64_t idx = fnv_1a(key) % m->size; - return hash; + if (m->table[idx].key == NULL) return NULL; + while (1) { + if (m->table[idx].key == NULL) return NULL; + if (memcmp(key, m->table[idx].key, size) == 0) return m->table[idx].value; + idx = (idx + 1) % m->size; + } } + +bool map_contains(struct map *m, void *k, uint64_t size) { + return map_get(m, k, size) != NULL; +} \ No newline at end of file From 950db036625e5f6667d513a2836e6280ae464c52 Mon Sep 17 00:00:00 2001 From: Altanis <38045884+Altanis@users.noreply.github.com> Date: Mon, 26 Dec 2022 17:29:17 -0500 Subject: [PATCH 06/18] fix chances of undefined behavior, more mem efficient --- include/lib/map.h | 14 +++++++------- src/lib/map.c | 38 ++++++++++++++++++-------------------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/include/lib/map.h b/include/lib/map.h index ddf4a36..23d6137 100644 --- a/include/lib/map.h +++ b/include/lib/map.h @@ -12,26 +12,26 @@ struct entry { struct map { struct entry *table; - uint64_t used; - uint64_t size; + size_t used; + size_t size; }; /** Initializes a new hashmap. Returns `-1` if not allocated. */ -int map_init(struct map *m, uint64_t size); +int map_init(struct map *m, size_t size); /** Frees the hashtable from memory. */ void map_free(struct map *m); /** Adds the key/value pair to the hashtable. */ -int map_put(struct map *m, void *key, void *value, uint64_t size); +int map_put(struct map *m, void *key, void *value, size_t size); /** Gets the value associated with the specified key. */ -void *map_get(struct map *m, void *key, uint64_t size); +void *map_get(struct map *m, void *key, size_t size); /** Checks if key exists in hashmap. */ -bool map_contains(struct map *m, void *key, uint64_t size); +bool map_contains(struct map *m, void *key, size_t size); /** Hash function for strings. */ -uint64_t fnv_1a(char *str); +size_t fnv_1a(char *str); #endif //_MAP_H_ \ No newline at end of file diff --git a/src/lib/map.c b/src/lib/map.c index 3e81695..df9cff8 100644 --- a/src/lib/map.c +++ b/src/lib/map.c @@ -1,18 +1,17 @@ #include "lib/map.h" -uint64_t fnv_1a(char *str) { - size_t len = strlen(str); - uint64_t hash = 0xCBF29CE484222325; +size_t fnv_1a(char *ptr, size_t size) { + size_t hash = 0x811C9DC5; - for (size_t i = len; i--;) { - hash ^= str[i]; - hash *= 0x00000100000001B3; + for (;size--;) { + hash ^= ptr[size]; + hash *= 0x01000193; } return hash; } -int map_init(struct map *m, uint64_t size) { +int map_init(struct map *m, size_t size) { m->table = calloc(size, sizeof(struct map)); m->size = size; @@ -25,15 +24,14 @@ void map_free(struct map *m) { free(m->table); } -int map_put(struct map *m, void *k, void *value, uint64_t size) { - char *key = k; - uint64_t idx = fnv_1a(key) % m->size; +int map_put(struct map *m, void *key, void *value, size_t size) { + size_t idx = fnv_1a(key, size) % m->size; + size_t start = idx; if (m->table[idx].key != NULL) { - if (m->used == m->size) return -1; - while (1) { - idx = (idx + 1) % m->size; + idx = (++idx) % m->size; + if (idx == start) return -1; if (m->table[idx].key == NULL || memcmp(key, m->table[idx].key, size) == 0) break; } } @@ -45,18 +43,18 @@ int map_put(struct map *m, void *k, void *value, uint64_t size) { return 0; } -void *map_get(struct map *m, void *k, uint64_t size) { - char *key = k; - uint64_t idx = fnv_1a(key) % m->size; +void *map_get(struct map *m, void *key, size_t size) { + size_t idx = fnv_1a(key, size) % m->size; if (m->table[idx].key == NULL) return NULL; - while (1) { - if (m->table[idx].key == NULL) return NULL; + while (m->table[idx].key != NULL) { if (memcmp(key, m->table[idx].key, size) == 0) return m->table[idx].value; - idx = (idx + 1) % m->size; + idx = (++idx) % m->size; } + + return NULL; } -bool map_contains(struct map *m, void *k, uint64_t size) { +bool map_contains(struct map *m, void *k, size_t size) { return map_get(m, k, size) != NULL; } \ No newline at end of file From be4c70e36827f2db52ea9d152a683c5bb040c932 Mon Sep 17 00:00:00 2001 From: Altanis <38045884+Altanis@users.noreply.github.com> Date: Tue, 27 Dec 2022 10:43:50 -0500 Subject: [PATCH 07/18] fix: remove wasteful mem allocation --- src/lib/map.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/map.c b/src/lib/map.c index df9cff8..62c5d4a 100644 --- a/src/lib/map.c +++ b/src/lib/map.c @@ -12,7 +12,7 @@ size_t fnv_1a(char *ptr, size_t size) { } int map_init(struct map *m, size_t size) { - m->table = calloc(size, sizeof(struct map)); + m->table = calloc(size, sizeof(struct entry)); m->size = size; /** Ensure map was allocated. */ @@ -57,4 +57,4 @@ void *map_get(struct map *m, void *key, size_t size) { bool map_contains(struct map *m, void *k, size_t size) { return map_get(m, k, size) != NULL; -} \ No newline at end of file +} From 523024133606b6449e5c66e074c7be7b12b262af Mon Sep 17 00:00:00 2001 From: Altanis <38045884+Altanis@users.noreply.github.com> Date: Tue, 27 Dec 2022 14:41:03 -0500 Subject: [PATCH 08/18] docs: explain struct properties --- include/lib/map.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/lib/map.h b/include/lib/map.h index 23d6137..c12d00b 100644 --- a/include/lib/map.h +++ b/include/lib/map.h @@ -6,13 +6,18 @@ /** Structures for a generic map. */ struct entry { + /** The key associated with the entry. */ void *key; + /** The value associated with the entry. */ void *value; }; struct map { + /** Table which holds all entries. */ struct entry *table; + /** Amount of space used. */ size_t used; + /** Maximum space to allocate for entries */ size_t size; }; @@ -34,4 +39,4 @@ bool map_contains(struct map *m, void *key, size_t size); /** Hash function for strings. */ size_t fnv_1a(char *str); -#endif //_MAP_H_ \ No newline at end of file +#endif //_MAP_H_ From d372bd1b2d02ce1ef4051e749580b01623efe203 Mon Sep 17 00:00:00 2001 From: Altanis <38045884+Altanis@users.noreply.github.com> Date: Tue, 27 Dec 2022 20:35:16 -0500 Subject: [PATCH 09/18] fix: make more peformant --- src/lib/map.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/lib/map.c b/src/lib/map.c index 62c5d4a..e56e8d7 100644 --- a/src/lib/map.c +++ b/src/lib/map.c @@ -28,12 +28,11 @@ int map_put(struct map *m, void *key, void *value, size_t size) { size_t idx = fnv_1a(key, size) % m->size; size_t start = idx; - if (m->table[idx].key != NULL) { - while (1) { - idx = (++idx) % m->size; - if (idx == start) return -1; - if (m->table[idx].key == NULL || memcmp(key, m->table[idx].key, size) == 0) break; - } + + while (m->table[idx].key != NULL) { + idx = (++idx) % m->size; + if (idx == start) return -1; + if (memcmp(key, m->table[idx].key, size) == 0) break; } m->table[idx].key = key; From a44fd7f99eba17c4f79468e80af2c8165cd77198 Mon Sep 17 00:00:00 2001 From: CoderSudaWuda <38045884+CoderSudaWuda@users.noreply.github.com> Date: Wed, 18 Jan 2023 08:32:44 -0500 Subject: [PATCH 10/18] feat: implement calloc --- src/stdlib/stdalloc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/stdlib/stdalloc.c b/src/stdlib/stdalloc.c index cbf4b31..0fbcd35 100644 --- a/src/stdlib/stdalloc.c +++ b/src/stdlib/stdalloc.c @@ -16,6 +16,15 @@ void *malloc(size_t size) { return heap_malloc(current_heap, size); } +void *calloc(size_t _NumOfElements, size_t _SizeOfElements) { + void* buffer = malloc(_NumOfElements * _SizeOfElements); + + if (buffer == NULL) return NULL; + + memset(buffer, 0, _NumOfElements * _SizeOfElements); + return buffer; +} + void *realloc(void *p, size_t size) { return heap_realloc(current_heap, p, size); } From 134c345f4a43a47f2fe4ce2625562aba0a726d12 Mon Sep 17 00:00:00 2001 From: CoderSudaWuda <38045884+CoderSudaWuda@users.noreply.github.com> Date: Wed, 18 Jan 2023 08:35:16 -0500 Subject: [PATCH 11/18] fix: add import for memset --- src/stdlib/stdalloc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stdlib/stdalloc.c b/src/stdlib/stdalloc.c index 0fbcd35..aee160c 100644 --- a/src/stdlib/stdalloc.c +++ b/src/stdlib/stdalloc.c @@ -1,4 +1,5 @@ #include "stdlib/stdalloc.h" +#include "stdlib/stdstr.h" #include "alloc/heapalloc.h" From 18a5762439bde2324d49284ce11316549c437902 Mon Sep 17 00:00:00 2001 From: CoderSudaWuda <38045884+CoderSudaWuda@users.noreply.github.com> Date: Wed, 18 Jan 2023 08:47:18 -0500 Subject: [PATCH 12/18] fixes --- include/lib/map.h | 15 ++------------- include/stdlib/stdhash.h | 4 ++++ include/stdlib/stdtypes.h | 1 + src/lib/map.c | 28 +++++++++++++++------------- src/stdlib/stdhash.c | 12 ++++++++++++ 5 files changed, 34 insertions(+), 26 deletions(-) create mode 100644 include/stdlib/stdhash.h create mode 100644 src/stdlib/stdhash.c diff --git a/include/lib/map.h b/include/lib/map.h index c12d00b..6031684 100644 --- a/include/lib/map.h +++ b/include/lib/map.h @@ -4,14 +4,6 @@ #include "stdlib/stdtypes.h" -/** Structures for a generic map. */ -struct entry { - /** The key associated with the entry. */ - void *key; - /** The value associated with the entry. */ - void *value; -}; - struct map { /** Table which holds all entries. */ struct entry *table; @@ -22,13 +14,13 @@ struct map { }; /** Initializes a new hashmap. Returns `-1` if not allocated. */ -int map_init(struct map *m, size_t size); +void map_init(struct map *m); /** Frees the hashtable from memory. */ void map_free(struct map *m); /** Adds the key/value pair to the hashtable. */ -int map_put(struct map *m, void *key, void *value, size_t size); +void map_put(struct map *m, void *key, void *value, size_t size); /** Gets the value associated with the specified key. */ void *map_get(struct map *m, void *key, size_t size); @@ -36,7 +28,4 @@ void *map_get(struct map *m, void *key, size_t size); /** Checks if key exists in hashmap. */ bool map_contains(struct map *m, void *key, size_t size); -/** Hash function for strings. */ -size_t fnv_1a(char *str); - #endif //_MAP_H_ diff --git a/include/stdlib/stdhash.h b/include/stdlib/stdhash.h new file mode 100644 index 0000000..e4841ed --- /dev/null +++ b/include/stdlib/stdhash.h @@ -0,0 +1,4 @@ +#include + +/** FNV-1A hash for generic map. */ +size_t fnv_1a(char *str, size_t size); \ No newline at end of file diff --git a/include/stdlib/stdtypes.h b/include/stdlib/stdtypes.h index 42ab53c..7115061 100644 --- a/include/stdlib/stdtypes.h +++ b/include/stdlib/stdtypes.h @@ -7,6 +7,7 @@ /** Size type */ typedef unsigned int size_t; +/** Unsigned 64 bit integer */ typedef unsigned long long uint64_t; #define NULL (void *) 0 diff --git a/src/lib/map.c b/src/lib/map.c index e56e8d7..e242a2b 100644 --- a/src/lib/map.c +++ b/src/lib/map.c @@ -1,22 +1,24 @@ #include "lib/map.h" +#include "stdlib/stdhash.h" +#include "stdlib/stdalloc.h" -size_t fnv_1a(char *ptr, size_t size) { - size_t hash = 0x811C9DC5; +/** Structures for a generic map. */ +struct entry { + /** The key associated with the entry. */ + void *key; + /** The value associated with the entry. */ + void *value; +}; - for (;size--;) { - hash ^= ptr[size]; - hash *= 0x01000193; - } +void map_init(struct map *m) { + /** Default 1MB of data. */ + size_t size = 1024 * 1024; - return hash; -} - -int map_init(struct map *m, size_t size) { m->table = calloc(size, sizeof(struct entry)); m->size = size; /** Ensure map was allocated. */ - if (m->table == NULL) return -1; + if (m->table == NULL) return NULL; else return 0; } @@ -24,14 +26,14 @@ void map_free(struct map *m) { free(m->table); } -int map_put(struct map *m, void *key, void *value, size_t size) { +void map_put(struct map *m, void *key, void *value, size_t size) { size_t idx = fnv_1a(key, size) % m->size; size_t start = idx; while (m->table[idx].key != NULL) { idx = (++idx) % m->size; - if (idx == start) return -1; + if (idx == start) return NULL; if (memcmp(key, m->table[idx].key, size) == 0) break; } diff --git a/src/stdlib/stdhash.c b/src/stdlib/stdhash.c new file mode 100644 index 0000000..8ddab5d --- /dev/null +++ b/src/stdlib/stdhash.c @@ -0,0 +1,12 @@ +#include + +size_t fnv_1a(char *ptr, size_t size) { + size_t hash = 0x811C9DC5; + + for (;size--;) { + hash ^= ptr[size]; + hash *= 0x01000193; + } + + return hash; +} \ No newline at end of file From 8a8cf4383874c9d7bff900d1673b2b26a35fa7d9 Mon Sep 17 00:00:00 2001 From: Altanis <38045884+Altanis@users.noreply.github.com> Date: Wed, 18 Jan 2023 08:48:58 -0500 Subject: [PATCH 13/18] fix: remove NULL return --- src/lib/map.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib/map.c b/src/lib/map.c index e242a2b..960d587 100644 --- a/src/lib/map.c +++ b/src/lib/map.c @@ -16,10 +16,6 @@ void map_init(struct map *m) { m->table = calloc(size, sizeof(struct entry)); m->size = size; - - /** Ensure map was allocated. */ - if (m->table == NULL) return NULL; - else return 0; } void map_free(struct map *m) { From a1a7685e573223f6ef24f24aebb33189b73ce605 Mon Sep 17 00:00:00 2001 From: Altanis <38045884+Altanis@users.noreply.github.com> Date: Tue, 23 Jul 2024 00:55:11 -0400 Subject: [PATCH 14/18] implement map_resize --- include/lib/map.h | 5 ++--- src/lib/map.c | 13 +++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/include/lib/map.h b/include/lib/map.h index 6031684..367bfe2 100644 --- a/include/lib/map.h +++ b/include/lib/map.h @@ -15,16 +15,15 @@ struct map { /** Initializes a new hashmap. Returns `-1` if not allocated. */ void map_init(struct map *m); - +/** Resizes the hashmap. */ +void map_resize(struct map *m, double resize_factor); /** Frees the hashtable from memory. */ void map_free(struct map *m); /** Adds the key/value pair to the hashtable. */ void map_put(struct map *m, void *key, void *value, size_t size); - /** Gets the value associated with the specified key. */ void *map_get(struct map *m, void *key, size_t size); - /** Checks if key exists in hashmap. */ bool map_contains(struct map *m, void *key, size_t size); diff --git a/src/lib/map.c b/src/lib/map.c index 960d587..81c4942 100644 --- a/src/lib/map.c +++ b/src/lib/map.c @@ -18,26 +18,31 @@ void map_init(struct map *m) { m->size = size; } +void map_resize(struct map *m, double resize_factor) { + m->size *= resize_factor; + m->table = realloc(m->table, m->size * resize_factor); +} + void map_free(struct map *m) { free(m->table); } void map_put(struct map *m, void *key, void *value, size_t size) { + if (m->used * 2 >= m->size) { + map_resize(m, 2); + } + size_t idx = fnv_1a(key, size) % m->size; size_t start = idx; - while (m->table[idx].key != NULL) { idx = (++idx) % m->size; - if (idx == start) return NULL; if (memcmp(key, m->table[idx].key, size) == 0) break; } m->table[idx].key = key; m->table[idx].value = value; m->used++; - - return 0; } void *map_get(struct map *m, void *key, size_t size) { From ee0842b5ef270dadc49107e51d603ed0398d05c0 Mon Sep 17 00:00:00 2001 From: Altanis <38045884+Altanis@users.noreply.github.com> Date: Tue, 23 Jul 2024 00:56:23 -0400 Subject: [PATCH 15/18] oops --- src/lib/map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/map.c b/src/lib/map.c index 81c4942..9b288bb 100644 --- a/src/lib/map.c +++ b/src/lib/map.c @@ -20,7 +20,7 @@ void map_init(struct map *m) { void map_resize(struct map *m, double resize_factor) { m->size *= resize_factor; - m->table = realloc(m->table, m->size * resize_factor); + m->table = realloc(m->table, m->size * sizeof(struct entry)); } void map_free(struct map *m) { From 0c85e0c231a1c3594163551a097aaf17fe483871 Mon Sep 17 00:00:00 2001 From: Altanis <38045884+Altanis@users.noreply.github.com> Date: Tue, 23 Jul 2024 01:04:16 -0400 Subject: [PATCH 16/18] ensure `used` field is zeroed out --- src/lib/map.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/map.c b/src/lib/map.c index 9b288bb..d9e78e7 100644 --- a/src/lib/map.c +++ b/src/lib/map.c @@ -15,6 +15,7 @@ void map_init(struct map *m) { size_t size = 1024 * 1024; m->table = calloc(size, sizeof(struct entry)); + m->used = 0; m->size = size; } From fa73edf4129ac833b1438f4c69c21848989349a0 Mon Sep 17 00:00:00 2001 From: Altanis <38045884+Altanis@users.noreply.github.com> Date: Tue, 23 Jul 2024 01:08:00 -0400 Subject: [PATCH 17/18] resolve merge conflict --- include/stdlib/stdtypes.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/stdlib/stdtypes.h b/include/stdlib/stdtypes.h index 7115061..2324d21 100644 --- a/include/stdlib/stdtypes.h +++ b/include/stdlib/stdtypes.h @@ -5,12 +5,16 @@ #ifndef _STDTYPES_H_ #define _STDTYPES_H_ +#ifndef USER /** Size type */ typedef unsigned int size_t; /** Unsigned 64 bit integer */ typedef unsigned long long uint64_t; - -#define NULL (void *) 0 +/** nullptr */ +#define NULL (void*)0 +#else +#include +#endif enum bool_e { false = 0, From 69d364c32152b2b2d7bb317394e4d510c4ba0cff Mon Sep 17 00:00:00 2001 From: Altanis <38045884+Altanis@users.noreply.github.com> Date: Tue, 23 Jul 2024 01:10:42 -0400 Subject: [PATCH 18/18] oops --- include/stdlib/stdtypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/stdlib/stdtypes.h b/include/stdlib/stdtypes.h index 2324d21..4ad774f 100644 --- a/include/stdlib/stdtypes.h +++ b/include/stdlib/stdtypes.h @@ -11,7 +11,7 @@ typedef unsigned int size_t; /** Unsigned 64 bit integer */ typedef unsigned long long uint64_t; /** nullptr */ -#define NULL (void*)0 +#define NULL (void *) 0 #else #include #endif