Update
This commit is contained in:
parent
69811ba0f2
commit
049b901278
21
BUILDING.md
Normal file
21
BUILDING.md
Normal file
|
@ -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 <mcutil/mcutil.h>
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
mcu_hash_map_t hm = {0};
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
10
Makefile
10
Makefile
|
@ -2,14 +2,12 @@
|
||||||
|
|
||||||
OUTD ?= ./build
|
OUTD ?= ./build
|
||||||
|
|
||||||
CC = gcc
|
CC = clang
|
||||||
LD = gcc
|
LD = clang
|
||||||
AR = ar
|
AR = ar
|
||||||
|
|
||||||
# -fblocks
|
CCARGS = -fpic -Wall -O3 -Wall -I include -fblocks
|
||||||
CCARGS = -fpic -Wall -O3 -Wall -I include
|
LDARGS = -lBlocksRuntime
|
||||||
LDARGS =
|
|
||||||
# -lBlocksRuntime
|
|
||||||
|
|
||||||
srcs = $(wildcard src/**/*.c) $(wildcard src/*.c)
|
srcs = $(wildcard src/**/*.c) $(wildcard src/*.c)
|
||||||
objs = $(patsubst src/%.c,$(OUTD)/obj/%.o,$(srcs))
|
objs = $(patsubst src/%.c,$(OUTD)/obj/%.o,$(srcs))
|
||||||
|
|
|
@ -6,28 +6,28 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "mcutil/mcutil.h"
|
#include "mcutil/mcutil.h"
|
||||||
|
|
||||||
typedef struct mcu_hash_map_node_s {
|
typedef struct mcu_gen_hm_node_s {
|
||||||
uint8_t key[16];
|
uint8_t key[16];
|
||||||
void* value;
|
void* value;
|
||||||
struct mcu_hash_map_node_s* next;
|
struct mcu_gen_hm_node_s* next;
|
||||||
} mcu_hash_map_node_t;
|
} mcu_gen_hm_node_t;
|
||||||
|
|
||||||
typedef struct mcu_hash_map_s {
|
typedef struct mcu_gen_hm_s {
|
||||||
mcu_hash_map_node_t* nodes;
|
mcu_gen_hm_node_t* nodes;
|
||||||
} mcu_hash_map_t;
|
} 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_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_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));
|
#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 mcu_gen_hm_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_insert(mcu_gen_hm_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_get (mcu_gen_hm_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 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
|
/// 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
|
/// 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
|
#endif // _H_MCU_COLLECT_HASH_MAP
|
|
@ -5,17 +5,18 @@
|
||||||
#include "mcutil/mcutil.h"
|
#include "mcutil/mcutil.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define MCU_GEN_VEC_INITIAL_SIZE 32
|
|
||||||
|
|
||||||
typedef struct gen_vec_s {
|
typedef struct mcu_gen_vec_s {
|
||||||
void** inner;
|
void** inner;
|
||||||
size_t count;
|
size_t count;
|
||||||
size_t capacity;
|
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_init(mcu_gen_vec_t* gv);
|
||||||
MCU_API void* mcu_gen_vec_remove_back(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_remove_front(gen_vec_t *gv);
|
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
|
#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);
|
int (*test_fn)(void);
|
||||||
// If `test_fn` returns non zero, it will get the (ret_val - 1) value of this array,
|
// 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.
|
// 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;
|
} mcu_test_case_t;
|
||||||
|
|
||||||
|
|
||||||
#define RUN_TEST_CASES(cases) \
|
#define RUN_TEST_CASES(cases) \
|
||||||
for (size_t i = 0; i < sizeof(cases)/sizeof(mcu_test_case_t); i++) { \
|
for (size_t i = 0; i < sizeof(cases)/sizeof(mcu_test_case_t); i++) { \
|
||||||
mcu_test_case_t* test_case = &(cases)[i]; \
|
mcu_test_case_t* test_case = &(cases)[i]; \
|
||||||
|
printf("(%s): ", test_case->short_name); \
|
||||||
int ret = (test_case->test_fn)(); \
|
int ret = (test_case->test_fn)(); \
|
||||||
if (!ret) { \
|
if (ret) { \
|
||||||
printf("(%s): FAIL - Returned non zero (%d)\n", \
|
printf("FAIL - Returned non zero (%d)\n", ret); \
|
||||||
test_case->short_name, ret); \
|
printf("REASON: %s\n", test_case->error_types[ret]); \
|
||||||
printf("(%s): REASON: %s\n", \
|
|
||||||
test_case->short_name, test_case->error_types[ret-1]); \
|
|
||||||
exit(1); \
|
exit(1); \
|
||||||
} else { \
|
} else { \
|
||||||
printf("(%s): FAIL\n", test_case->short_name); \
|
printf("PASS\n"); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "mcutil/collect/hash_map.h"
|
#include "mcutil/collect/gen_hash_map.h"
|
||||||
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -7,23 +8,28 @@
|
||||||
#include "mcutil/mcutil.h"
|
#include "mcutil/mcutil.h"
|
||||||
#include "mcutil/hash/md5.h"
|
#include "mcutil/hash/md5.h"
|
||||||
|
|
||||||
MCU_API mcu_hash_map_t mcu_hm_new() {
|
#define CREATE_HM_NODES_IF_NULL(hm) { if (!(hm)->nodes) (hm)->nodes = MCU_ALLOC(sizeof(mcu_gen_hm_node_t)); }
|
||||||
return (mcu_hash_map_t){
|
|
||||||
.nodes = MCU_ALLOC(sizeof(mcu_hash_map_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_context ctx = {0};
|
||||||
mcu_md5_init(&ctx);
|
mcu_md5_init(&ctx);
|
||||||
mcu_md5_digest(&ctx, (void*)key, key_len);
|
mcu_md5_digest(&ctx, (void*)key, key_len);
|
||||||
uint8_t key_res[16];
|
uint8_t key_res[16];
|
||||||
mcu_md5_output(&ctx, key_res);
|
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) {
|
while (true) {
|
||||||
if (!node->next) {
|
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;
|
node->next->next = NULL;
|
||||||
memcpy(node->next->key, key_res, 16);
|
memcpy(node->next->key, key_res, 16);
|
||||||
node->next->value = (void*)value;
|
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_context ctx = {0};
|
||||||
mcu_md5_init(&ctx);
|
mcu_md5_init(&ctx);
|
||||||
mcu_md5_digest(&ctx, (void*)key, key_len);
|
mcu_md5_digest(&ctx, (void*)key, key_len);
|
||||||
uint8_t key_res[16];
|
uint8_t key_res[16];
|
||||||
mcu_md5_output(&ctx, key_res);
|
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) {
|
while (true) {
|
||||||
if (memcmp(node->key, key_res, 16) == 0) {
|
if (memcmp(node->key, key_res, 16) == 0) {
|
||||||
return node->value;
|
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_context ctx = {0};
|
||||||
mcu_md5_init(&ctx);
|
mcu_md5_init(&ctx);
|
||||||
mcu_md5_digest(&ctx, (void*)key, key_len);
|
mcu_md5_digest(&ctx, (void*)key, key_len);
|
||||||
uint8_t key_res[16];
|
uint8_t key_res[16];
|
||||||
mcu_md5_output(&ctx, key_res);
|
mcu_md5_output(&ctx, key_res);
|
||||||
|
|
||||||
mcu_hash_map_node_t* node = hm->nodes;
|
CREATE_HM_NODES_IF_NULL(hm);
|
||||||
mcu_hash_map_node_t* prev = hm->nodes;
|
|
||||||
|
mcu_gen_hm_node_t* node = hm->nodes;
|
||||||
|
mcu_gen_hm_node_t* prev = hm->nodes;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (memcmp(node->key, key_res, 16) == 0) {
|
if (memcmp(node->key, key_res, 16) == 0) {
|
||||||
void* val = node->value;
|
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_API void mcu_free(mcu_gen_hm_t* hm) {
|
||||||
mcu_hash_map_node_t* node = hm->nodes;
|
assert(hm && "HashMap ptr is null");
|
||||||
|
mcu_gen_hm_node_t* node = hm->nodes;
|
||||||
|
if (!node) return;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (node->next) return;
|
if (node->next) return;
|
||||||
MCU_FREE(node);
|
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_API void mcu_free_all(mcu_gen_hm_t* hm) {
|
||||||
mcu_hash_map_node_t* node = hm->nodes;
|
assert(hm && "HashMap ptr is null");
|
||||||
|
mcu_gen_hm_node_t* node = hm->nodes;
|
||||||
|
if (!node) return;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (node->next) return;
|
if (node->next) return;
|
||||||
MCU_FREE(node);
|
MCU_FREE(node);
|
|
@ -1,17 +1,20 @@
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "mcutil/mcutil.h"
|
#include "mcutil/mcutil.h"
|
||||||
#include "mcutil/collect/gen_vec.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->inner = MCU_ALLOC(sizeof(void*)*MCU_GEN_VEC_INITIAL_SIZE);
|
||||||
gv->capacity = 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) {
|
MCU_API void mcu_gen_vec_insert_front(mcu_gen_vec_t* gv, void* data) {
|
||||||
assert(gv && "Null ptr passed as gen_vec_t");
|
assert(gv && "Null ptr passed as mcu_gen_vec_t");
|
||||||
if (!gv->inner) mcu_gen_vec_init(gv);
|
if (!gv->inner) mcu_gen_vec_init(gv);
|
||||||
if (gv->count == gv->capacity) {
|
if (gv->count == gv->capacity) {
|
||||||
gv->inner = MCU_REALLOC(gv->inner, (gv->capacity * sizeof(void*)) * 2);
|
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(tmp, gv->inner, count);
|
||||||
memcpy(gv->inner + sizeof(void*), tmp, count);
|
memcpy(gv->inner + sizeof(void*), tmp, count);
|
||||||
gv->inner[0] = data;
|
gv->inner[0] = data;
|
||||||
|
gv->count += 1;
|
||||||
MCU_FREE(tmp);
|
MCU_FREE(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
MCU_API void mcu_gen_vec_insert_back(gen_vec_t* gv, void* data) {
|
MCU_API void mcu_gen_vec_insert_back(mcu_gen_vec_t* gv, void* data) {
|
||||||
assert(gv && "Null ptr passed as gen_vec_t");
|
assert(gv && "Null ptr passed as mcu_gen_vec_t");
|
||||||
if (!gv->inner) mcu_gen_vec_init(gv);
|
if (!gv->inner) mcu_gen_vec_init(gv);
|
||||||
if (gv->count == gv->capacity) {
|
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->capacity *= 2;
|
||||||
}
|
}
|
||||||
gv->inner[gv->count++] = data;
|
gv->inner[gv->count++] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
MCU_API void* mcu_gen_vec_remove_back(gen_vec_t *gv) {
|
MCU_API void* mcu_gen_vec_remove_back(mcu_gen_vec_t *gv) {
|
||||||
assert(gv && "Null ptr passed as gen_vec_t");
|
assert(gv && "Null ptr passed as mcu_gen_vec_t");
|
||||||
if (gv->count == 0) return NULL;
|
if (gv->count == 0) return NULL;
|
||||||
return gv->inner[gv->count--];
|
return gv->inner[gv->count--];
|
||||||
}
|
}
|
||||||
|
|
||||||
MCU_API void* mcu_gen_vec_remove_front(gen_vec_t *gv) {
|
MCU_API void* mcu_gen_vec_remove_front(mcu_gen_vec_t *gv) {
|
||||||
assert(gv && "Null ptr passed as gen_vec_t");
|
assert(gv && "Null ptr passed as mcu_gen_vec_t");
|
||||||
if (gv->count == 0) return NULL;
|
if (gv->count == 0) return NULL;
|
||||||
void* data = gv->inner[0];
|
void* data = gv->inner[0];
|
||||||
size_t count = sizeof(void*)*gv->count;
|
for (int i = 0; i < gv->count; i++) {
|
||||||
void* tmp = MCU_ALLOC(count);
|
gv->inner[i] = gv->inner[i + 1];
|
||||||
memcpy(tmp, gv->inner, count);
|
}
|
||||||
memcpy(gv->inner - sizeof(void*), tmp, count);
|
|
||||||
MCU_FREE(tmp);
|
|
||||||
gv->count--;
|
gv->count--;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
83
test.c
83
test.c
|
@ -1,13 +1,82 @@
|
||||||
#include <mcutil/test.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <mcutil/test.h>
|
||||||
|
#include <mcutil/iter.h>
|
||||||
|
#include <mcutil/lambda.h>
|
||||||
|
#include <mcutil/result.h>
|
||||||
|
#include <mcutil/hash/md5.h>
|
||||||
|
#include <mcutil/collect/str.h>
|
||||||
|
#include <mcutil/collect/gen_vec.h>
|
||||||
|
#include <mcutil/collect/gen_hash_map.h>
|
||||||
|
#include <mcutil/collect/typed_vec.h>
|
||||||
|
#include <mcutil/collect/typed_hash_map.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user