From 049b901278c50307076c435416b473f62b724e93 Mon Sep 17 00:00:00 2001 From: MCorange Date: Tue, 4 Feb 2025 15:03:27 +0200 Subject: [PATCH] Update --- BUILDING.md | 21 +++ Makefile | 10 +- .../collect/{hash_map.h => gen_hash_map.h} | 24 ++-- include/mcutil/collect/gen_vec.h | 15 +- include/mcutil/collect/typed_hash_map.h | 136 ++++++++++++++++++ include/mcutil/collect/typed_vec.h | 0 include/mcutil/test.h | 13 +- src/collect/{hash_map.c => gen_hash_map.c} | 48 ++++--- src/collect/gen_vec.c | 32 +++-- test.c | 83 ++++++++++- 10 files changed, 312 insertions(+), 70 deletions(-) create mode 100644 BUILDING.md rename include/mcutil/collect/{hash_map.h => gen_hash_map.h} (51%) create mode 100644 include/mcutil/collect/typed_hash_map.h create mode 100644 include/mcutil/collect/typed_vec.h rename src/collect/{hash_map.c => gen_hash_map.c} (56%) diff --git a/BUILDING.md b/BUILDING.md new file mode 100644 index 0000000..1952563 --- /dev/null +++ b/BUILDING.md @@ -0,0 +1,21 @@ +# Building + +You can build this in several different ways: + +You can run the make file and have a static library of this lib. + +You can compile the library directly into your program: + +```c +// Run this to comile: +// $ gcc -o main main.c -I$MCUTIL_PATH/include +// Only do this ***once*** +#define MCUTIL_IMPLEMENTATION +#include + +int main(int argc, char** argv) { + mcu_hash_map_t hm = {0}; + + return 0; +} + diff --git a/Makefile b/Makefile index e5baebb..333e4b3 100644 --- a/Makefile +++ b/Makefile @@ -2,14 +2,12 @@ OUTD ?= ./build -CC = gcc -LD = gcc +CC = clang +LD = clang AR = ar -# -fblocks -CCARGS = -fpic -Wall -O3 -Wall -I include -LDARGS = -# -lBlocksRuntime +CCARGS = -fpic -Wall -O3 -Wall -I include -fblocks +LDARGS = -lBlocksRuntime srcs = $(wildcard src/**/*.c) $(wildcard src/*.c) objs = $(patsubst src/%.c,$(OUTD)/obj/%.o,$(srcs)) diff --git a/include/mcutil/collect/hash_map.h b/include/mcutil/collect/gen_hash_map.h similarity index 51% rename from include/mcutil/collect/hash_map.h rename to include/mcutil/collect/gen_hash_map.h index 6d24601..0a282e8 100644 --- a/include/mcutil/collect/hash_map.h +++ b/include/mcutil/collect/gen_hash_map.h @@ -6,28 +6,28 @@ #include #include "mcutil/mcutil.h" -typedef struct mcu_hash_map_node_s { +typedef struct mcu_gen_hm_node_s { uint8_t key[16]; void* value; - struct mcu_hash_map_node_s* next; -} mcu_hash_map_node_t; + struct mcu_gen_hm_node_s* next; +} mcu_gen_hm_node_t; -typedef struct mcu_hash_map_s { - mcu_hash_map_node_t* nodes; -} mcu_hash_map_t; +typedef struct mcu_gen_hm_s { + mcu_gen_hm_node_t* nodes; +} mcu_gen_hm_t; #define mcu_hm_insert(hm, key, value) _mcu_hm_insert((hm), (key), (const size_t)sizeof(key), (value)); #define mcu_hm_get(hm, key) _mcu_hm_insert((hm), (key), (const size_t)sizeof(key)); #define mcu_hm_remove(hm, key) _mcu_hm_insert((hm), (key), (const size_t)sizeof(key)); -MCU_API mcu_hash_map_t mcu_hm_new(); -MCU_API void _mcu_hm_insert(mcu_hash_map_t* hm, const void* key, const size_t key_len, const void* value); -MCU_API void* _mcu_hm_get (mcu_hash_map_t* hm, const void* key, const size_t key_len); -MCU_API void* _mcu_hm_remove(mcu_hash_map_t* hm, const void* key, const size_t key_len); +MCU_API mcu_gen_hm_t mcu_hm_new(); +MCU_API void _mcu_hm_insert(mcu_gen_hm_t* hm, const void* key, const size_t key_len, const void* value); +MCU_API void* _mcu_hm_get (mcu_gen_hm_t* hm, const void* key, const size_t key_len); +MCU_API void* _mcu_hm_remove(mcu_gen_hm_t* hm, const void* key, const size_t key_len); /// Frees the hashmap but not the pointers inside the values -MCU_API void mcu_free(mcu_hash_map_t* hm); +MCU_API void mcu_free(mcu_gen_hm_t* hm); /// Frees the hashmap and the pointers inside the values -MCU_API void mcu_free_all(mcu_hash_map_t* hm); +MCU_API void mcu_free_all(mcu_gen_hm_t* hm); #endif // _H_MCU_COLLECT_HASH_MAP diff --git a/include/mcutil/collect/gen_vec.h b/include/mcutil/collect/gen_vec.h index a549a42..c621f51 100644 --- a/include/mcutil/collect/gen_vec.h +++ b/include/mcutil/collect/gen_vec.h @@ -5,17 +5,18 @@ #include "mcutil/mcutil.h" #include -#define MCU_GEN_VEC_INITIAL_SIZE 32 -typedef struct gen_vec_s { +typedef struct mcu_gen_vec_s { void** inner; size_t count; size_t capacity; -} gen_vec_t; +} mcu_gen_vec_t; -MCU_API void mcu_gen_vec_insert_front(gen_vec_t* gv, void* data); -MCU_API void mcu_gen_vec_insert_back(gen_vec_t* gv, void* data); -MCU_API void* mcu_gen_vec_remove_back(gen_vec_t *gv); -MCU_API void* mcu_gen_vec_remove_front(gen_vec_t *gv); + +MCU_API void mcu_gen_vec_init(mcu_gen_vec_t* gv); +MCU_API void mcu_gen_vec_insert_front(mcu_gen_vec_t* gv, void* data); +MCU_API void mcu_gen_vec_insert_back(mcu_gen_vec_t* gv, void* data); +MCU_API void* mcu_gen_vec_remove_back(mcu_gen_vec_t *gv); +MCU_API void* mcu_gen_vec_remove_front(mcu_gen_vec_t *gv); #endif diff --git a/include/mcutil/collect/typed_hash_map.h b/include/mcutil/collect/typed_hash_map.h new file mode 100644 index 0000000..786af41 --- /dev/null +++ b/include/mcutil/collect/typed_hash_map.h @@ -0,0 +1,136 @@ +#ifndef _H_MCU_COLLECT_TYPED_HASH_MAP +#define _H_MCU_COLLECT_TYPED_HASH_MAP + +#include +#include +#include +#include "mcutil/mcutil.h" + +#define MCU_TYPED_HM_DEFINE(name_prefix, key_t, value_t) \ +typedef struct name_prefix##_hm_node_s { \ + uint8_t key_hash[16]; \ + key_t key; \ + value_t value; \ + struct mcu_hash_map_node_s* next; \ +} name_prefix##_hm_node_t; \ + \ +typedef struct name_prefix##_hm_s { \ + name_prefix##_hm_node_t* nodes; \ +} name_prefix##_hm_t; + + +#define MCU_TYPED_HM_IMPL(pfx, key_t, value_t) \ +MCU_API pfx##_hm_t mcu_hm_new() { \ + return (pfx##_hm_t){ \ + .nodes = MCU_ALLOC(sizeof(pfx##_hm_t)), \ + }; \ +} \ + \ +MCU_API void pfx##_hm_insert( \ + pfx##_hm_t* hm, \ + const key_t* key, \ + const value_t* value) { \ + assert(hm && "HashMap ptr is null"); \ + mcu_md5_context ctx = {0}; \ + mcu_md5_init(&ctx); \ + mcu_md5_digest(&ctx, (void*)key, sizeof(key_t)); \ + uint8_t key_res[16]; \ + mcu_md5_output(&ctx, key_res); \ + \ + if (!(hm)->nodes) \ + (hm)->nodes = MCU_ALLOC(sizeof(pfx##_hm_node_t)); \ + \ + pfx##_hm_node_t* node = hm->nodes; \ + while (true) { \ + if (!node->next) { \ + node->next = MCU_ALLOC(sizeof(pfx##_hm_node_t));\ + node->next->next = NULL; \ + node->next->key = key; \ + memcpy(node->next->key_hash, key_res, 16); \ + node->next->value = (void*)value; \ + return; \ + } \ + node = node->next; \ + } \ +} \ + \ +MCU_API void* pfx##_hm_get( \ + pfx##_hm_t* hm, \ + const key_t key, \ + ) { \ + assert(hm && "HashMap ptr is null"); \ + mcu_md5_context ctx = {0}; \ + mcu_md5_init(&ctx); \ + mcu_md5_digest(&ctx, (void*)key, sizeof(key_t)); \ + uint8_t key_res[16]; \ + mcu_md5_output(&ctx, key_res); \ + \ + if (!(hm)->nodes) \ + (hm)->nodes = MCU_ALLOC(sizeof(pfx##_hm_node_t)); \ + pfx##_hm_node_t* node = hm->nodes; \ + while (true) { \ + if (memcmp(node->key, key_res, 16) == 0) { \ + return node->value; \ + } else { \ + if (!node->next) return NULL; \ + node = node->next; \ + } \ + } \ +} \ + \ +MCU_API void* pfx##_hm_remove( \ + pfx##_hm_t* hm, \ + const key_t key, \ + const size_t key_len \ + ) { \ + assert(hm && "HashMap ptr is null"); \ + mcu_md5_context ctx = {0}; \ + mcu_md5_init(&ctx); \ + mcu_md5_digest(&ctx, (void*)key, sizeof(key_t)); \ + uint8_t key_res[16]; \ + mcu_md5_output(&ctx, key_res); \ + \ + if (!(hm)->nodes) \ + (hm)->nodes = MCU_ALLOC(sizeof(pfx##_hm_node_t)); \ + \ + pfx##_hm_node_t* node = hm->nodes; \ + pfx##_hm_node_t* prev = hm->nodes; \ + while (true) { \ + if (memcmp(node->key, key_res, 16) == 0) { \ + void* val = node->value; \ + prev->next = node->next; \ + return val; \ + } else { \ + if (!node->next) return NULL; \ + prev = node; \ + node = node->next; \ + } \ + } \ +} \ + \ +MCU_API void pfx##_hm_free(pfx##_hm_t* hm) { \ + assert(hm && "HashMap ptr is null"); \ + pfx##_hm_node_t* node = hm->nodes; \ + if (!node) return; \ + \ + while (true) { \ + if (node->next) return; \ + MCU_FREE(node); \ + node = node->next; \ + } \ +} \ + \ +MCU_API void pfx##_hm_free_all(pfx##_hm_t* hm) { \ + assert(hm && "HashMap ptr is null"); \ + pfx##_hm_node_t* node = hm->nodes; \ + if (!node) return; \ + while (true) { \ + if (node->next) return; \ + MCU_FREE(node); \ + MCU_FREE(node->value); \ + MCU_FREE(node->key); \ + node = node->next; \ + } \ +} + +#endif // _H_MCU_COLLECT_TYPED_HASH_MAP diff --git a/include/mcutil/collect/typed_vec.h b/include/mcutil/collect/typed_vec.h new file mode 100644 index 0000000..e69de29 diff --git a/include/mcutil/test.h b/include/mcutil/test.h index 9287490..76bb8ac 100644 --- a/include/mcutil/test.h +++ b/include/mcutil/test.h @@ -7,22 +7,21 @@ typedef struct mcu_test_case_s { int (*test_fn)(void); // If `test_fn` returns non zero, it will get the (ret_val - 1) value of this array, // if this is null it will show up as `(none)`, so return 1 for the first error type. - const char* error_types[]; + char** error_types; } mcu_test_case_t; #define RUN_TEST_CASES(cases) \ for (size_t i = 0; i < sizeof(cases)/sizeof(mcu_test_case_t); i++) { \ mcu_test_case_t* test_case = &(cases)[i]; \ + printf("(%s): ", test_case->short_name); \ int ret = (test_case->test_fn)(); \ - if (!ret) { \ - printf("(%s): FAIL - Returned non zero (%d)\n", \ - test_case->short_name, ret); \ - printf("(%s): REASON: %s\n", \ - test_case->short_name, test_case->error_types[ret-1]); \ + if (ret) { \ + printf("FAIL - Returned non zero (%d)\n", ret); \ + printf("REASON: %s\n", test_case->error_types[ret]); \ exit(1); \ } else { \ - printf("(%s): FAIL\n", test_case->short_name); \ + printf("PASS\n"); \ } \ } diff --git a/src/collect/hash_map.c b/src/collect/gen_hash_map.c similarity index 56% rename from src/collect/hash_map.c rename to src/collect/gen_hash_map.c index d562885..78cb799 100644 --- a/src/collect/hash_map.c +++ b/src/collect/gen_hash_map.c @@ -1,4 +1,5 @@ -#include "mcutil/collect/hash_map.h" +#include "mcutil/collect/gen_hash_map.h" +#include #include #include #include @@ -7,23 +8,28 @@ #include "mcutil/mcutil.h" #include "mcutil/hash/md5.h" -MCU_API mcu_hash_map_t mcu_hm_new() { - return (mcu_hash_map_t){ - .nodes = MCU_ALLOC(sizeof(mcu_hash_map_node_t)), +#define CREATE_HM_NODES_IF_NULL(hm) { if (!(hm)->nodes) (hm)->nodes = MCU_ALLOC(sizeof(mcu_gen_hm_node_t)); } + +MCU_API mcu_gen_hm_t mcu_hm_new() { + return (mcu_gen_hm_t){ + .nodes = MCU_ALLOC(sizeof(mcu_gen_hm_node_t)), }; } -MCU_API void _mcu_hm_insert(mcu_hash_map_t* hm, const void* key, const size_t key_len, const void* value) { +MCU_API void _mcu_hm_insert(mcu_gen_hm_t* hm, const void* key, const size_t key_len, const void* value) { + assert(hm && "HashMap ptr is null"); mcu_md5_context ctx = {0}; mcu_md5_init(&ctx); mcu_md5_digest(&ctx, (void*)key, key_len); uint8_t key_res[16]; mcu_md5_output(&ctx, key_res); - mcu_hash_map_node_t* node = hm->nodes; + CREATE_HM_NODES_IF_NULL(hm); + + mcu_gen_hm_node_t* node = hm->nodes; while (true) { if (!node->next) { - node->next = MCU_ALLOC(sizeof(mcu_hash_map_node_t)); + node->next = MCU_ALLOC(sizeof(mcu_gen_hm_node_t)); node->next->next = NULL; memcpy(node->next->key, key_res, 16); node->next->value = (void*)value; @@ -33,14 +39,16 @@ MCU_API void _mcu_hm_insert(mcu_hash_map_t* hm, const void* key, const size_t ke } } -MCU_API void* _mcu_hm_get(mcu_hash_map_t* hm, const void* key, const size_t key_len) { +MCU_API void* _mcu_hm_get(mcu_gen_hm_t* hm, const void* key, const size_t key_len) { + assert(hm && "HashMap ptr is null"); mcu_md5_context ctx = {0}; mcu_md5_init(&ctx); mcu_md5_digest(&ctx, (void*)key, key_len); uint8_t key_res[16]; mcu_md5_output(&ctx, key_res); - mcu_hash_map_node_t* node = hm->nodes; + CREATE_HM_NODES_IF_NULL(hm); + mcu_gen_hm_node_t* node = hm->nodes; while (true) { if (memcmp(node->key, key_res, 16) == 0) { return node->value; @@ -51,15 +59,18 @@ MCU_API void* _mcu_hm_get(mcu_hash_map_t* hm, const void* key, const size_t key_ } } -MCU_API void* _mcu_hm_remove(mcu_hash_map_t* hm, const void* key, const size_t key_len) { +MCU_API void* _mcu_hm_remove(mcu_gen_hm_t* hm, const void* key, const size_t key_len) { + assert(hm && "HashMap ptr is null"); mcu_md5_context ctx = {0}; mcu_md5_init(&ctx); mcu_md5_digest(&ctx, (void*)key, key_len); uint8_t key_res[16]; mcu_md5_output(&ctx, key_res); - mcu_hash_map_node_t* node = hm->nodes; - mcu_hash_map_node_t* prev = hm->nodes; + CREATE_HM_NODES_IF_NULL(hm); + + mcu_gen_hm_node_t* node = hm->nodes; + mcu_gen_hm_node_t* prev = hm->nodes; while (true) { if (memcmp(node->key, key_res, 16) == 0) { void* val = node->value; @@ -73,8 +84,11 @@ MCU_API void* _mcu_hm_remove(mcu_hash_map_t* hm, const void* key, const size_t k } } -MCU_API void mcu_free(mcu_hash_map_t* hm) { - mcu_hash_map_node_t* node = hm->nodes; +MCU_API void mcu_free(mcu_gen_hm_t* hm) { + assert(hm && "HashMap ptr is null"); + mcu_gen_hm_node_t* node = hm->nodes; + if (!node) return; + while (true) { if (node->next) return; MCU_FREE(node); @@ -82,8 +96,10 @@ MCU_API void mcu_free(mcu_hash_map_t* hm) { } } -MCU_API void mcu_free_all(mcu_hash_map_t* hm) { - mcu_hash_map_node_t* node = hm->nodes; +MCU_API void mcu_free_all(mcu_gen_hm_t* hm) { + assert(hm && "HashMap ptr is null"); + mcu_gen_hm_node_t* node = hm->nodes; + if (!node) return; while (true) { if (node->next) return; MCU_FREE(node); diff --git a/src/collect/gen_vec.c b/src/collect/gen_vec.c index 7ee6bcb..b2052a8 100644 --- a/src/collect/gen_vec.c +++ b/src/collect/gen_vec.c @@ -1,17 +1,20 @@ +#include #include #include #include #include "mcutil/mcutil.h" #include "mcutil/collect/gen_vec.h" -MCU_API void mcu_gen_vec_init(gen_vec_t* gv) { +#define MCU_GEN_VEC_INITIAL_SIZE 32 + +MCU_API void mcu_gen_vec_init(mcu_gen_vec_t* gv) { gv->inner = MCU_ALLOC(sizeof(void*)*MCU_GEN_VEC_INITIAL_SIZE); gv->capacity = MCU_GEN_VEC_INITIAL_SIZE; } -MCU_API void mcu_gen_vec_insert_front(gen_vec_t* gv, void* data) { - assert(gv && "Null ptr passed as gen_vec_t"); +MCU_API void mcu_gen_vec_insert_front(mcu_gen_vec_t* gv, void* data) { + assert(gv && "Null ptr passed as mcu_gen_vec_t"); if (!gv->inner) mcu_gen_vec_init(gv); if (gv->count == gv->capacity) { gv->inner = MCU_REALLOC(gv->inner, (gv->capacity * sizeof(void*)) * 2); @@ -23,34 +26,33 @@ MCU_API void mcu_gen_vec_insert_front(gen_vec_t* gv, void* data) { memcpy(tmp, gv->inner, count); memcpy(gv->inner + sizeof(void*), tmp, count); gv->inner[0] = data; + gv->count += 1; MCU_FREE(tmp); } -MCU_API void mcu_gen_vec_insert_back(gen_vec_t* gv, void* data) { - assert(gv && "Null ptr passed as gen_vec_t"); +MCU_API void mcu_gen_vec_insert_back(mcu_gen_vec_t* gv, void* data) { + assert(gv && "Null ptr passed as mcu_gen_vec_t"); if (!gv->inner) mcu_gen_vec_init(gv); if (gv->count == gv->capacity) { - gv->inner = MCU_REALLOC(gv->inner, (gv->capacity * sizeof(void*)) * 2); + gv->inner = MCU_REALLOC(gv->inner, (gv->capacity * 2) * sizeof(void*)); gv->capacity *= 2; } gv->inner[gv->count++] = data; } -MCU_API void* mcu_gen_vec_remove_back(gen_vec_t *gv) { - assert(gv && "Null ptr passed as gen_vec_t"); +MCU_API void* mcu_gen_vec_remove_back(mcu_gen_vec_t *gv) { + assert(gv && "Null ptr passed as mcu_gen_vec_t"); if (gv->count == 0) return NULL; return gv->inner[gv->count--]; } -MCU_API void* mcu_gen_vec_remove_front(gen_vec_t *gv) { - assert(gv && "Null ptr passed as gen_vec_t"); +MCU_API void* mcu_gen_vec_remove_front(mcu_gen_vec_t *gv) { + assert(gv && "Null ptr passed as mcu_gen_vec_t"); if (gv->count == 0) return NULL; void* data = gv->inner[0]; - size_t count = sizeof(void*)*gv->count; - void* tmp = MCU_ALLOC(count); - memcpy(tmp, gv->inner, count); - memcpy(gv->inner - sizeof(void*), tmp, count); - MCU_FREE(tmp); + for (int i = 0; i < gv->count; i++) { + gv->inner[i] = gv->inner[i + 1]; + } gv->count--; return data; } diff --git a/test.c b/test.c index b2badeb..17b02cb 100644 --- a/test.c +++ b/test.c @@ -1,13 +1,82 @@ -#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -int main(void) { - int a = 1; - mcu_result_t good = Ok(&a); - mcu_result_t bad = Err("Owo?"); - mcu_result_unwrap(good); - mcu_result_unwrap(bad); +#define GEN_VEC_ERR_BAD_ORDER 1 +const char* gen_vec_error_t[] = { + [GEN_VEC_ERR_BAD_ORDER] = "Returned items in bad order", +}; + +int test_gen_vec() { + char* a = malloc(2); + char* b = malloc(2); + char* c = malloc(2); + char* d = malloc(2); + memcpy(a, "A", 2); + memcpy(b, "B", 2); + memcpy(c, "C", 2); + memcpy(d, "D", 2); + + // C A B D + mcu_gen_vec_t vec = {0}; + mcu_gen_vec_init(&vec); + + mcu_gen_vec_insert_front(&vec, (void*)a); + mcu_gen_vec_insert_back(&vec, (void*)b); + mcu_gen_vec_insert_front(&vec, (void*)c); + mcu_gen_vec_insert_back(&vec, (void*)d); + + + printf("\nAr: %s\n", (char*) vec.inner[0]); + printf("Br: %s\n", (char*) vec.inner[1]); + printf("Cr: %s\n", (char*) vec.inner[2]); + printf("Dr: %s\n", (char*) vec.inner[3]); + + char* res_d = mcu_gen_vec_remove_back(&vec); + char* res_c = mcu_gen_vec_remove_front(&vec); + char* res_b = mcu_gen_vec_remove_back(&vec); + char* res_a = mcu_gen_vec_remove_front(&vec); + + + printf("A: %s\n", res_a); + printf("B: %s\n", res_b); + printf("C: %s\n", res_c); + printf("D: %s\n", res_d); + if (( + strcmp(res_a, "A") || + strcmp(res_b, "B") || + strcmp(res_c, "C") || + strcmp(res_d, "D") + )) { + return GEN_VEC_ERR_BAD_ORDER; + } + return 0; +} + + + + + +mcu_test_case_t cases[] = { + { + .short_name="GEN_VEC", + .test_fn=test_gen_vec, + .error_types = (char**)gen_vec_error_t, + } +}; + +int main(void) { + RUN_TEST_CASES(cases); return 0; }