Update
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
|
||||
136
include/mcutil/collect/typed_hash_map.h
Normal file
136
include/mcutil/collect/typed_hash_map.h
Normal 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
|
||||
0
include/mcutil/collect/typed_vec.h
Normal file
0
include/mcutil/collect/typed_vec.h
Normal 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"); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user