This commit is contained in:
2025-02-04 15:03:27 +02:00
parent 69811ba0f2
commit 049b901278
10 changed files with 312 additions and 70 deletions

View File

@@ -6,28 +6,28 @@
#include <stdlib.h>
#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

View File

@@ -5,17 +5,18 @@
#include "mcutil/mcutil.h"
#include <stddef.h>
#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

View File

@@ -0,0 +1,136 @@
#ifndef _H_MCU_COLLECT_TYPED_HASH_MAP
#define _H_MCU_COLLECT_TYPED_HASH_MAP
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#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

View File

View File

@@ -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"); \
} \
}