From b330790bf9b2bae1083dd3244a32a23f14ae8cb8 Mon Sep 17 00:00:00 2001 From: Leonardo Vencovsky Date: Thu, 2 Feb 2023 09:57:15 +0100 Subject: [PATCH] Added list SAC and examples --- examples/dev_example.c | 69 +++++++++++++++++++++++++++++++++++ examples/sac_example.c | 57 +++++++++++++++++++++++++++++ src/cmc/cmc/list/code.h | 67 ++++++++++++++++++++++++++++++++++ src/cmc/cmc/list/ext/code.h | 52 +++++++++++++++++++++++++- src/cmc/cmc/list/ext/header.h | 6 +++ src/cmc/cmc/list/header.h | 6 +++ src/cmc/cmc/list/struct.h | 4 ++ src/cmc/cor/callbacks.h | 4 +- src/cmc/cor/core.h | 2 + src/cmc/cor/dev.h | 2 +- src/cmc/list.h | 4 ++ 11 files changed, 268 insertions(+), 5 deletions(-) create mode 100644 examples/dev_example.c create mode 100644 examples/sac_example.c diff --git a/examples/dev_example.c b/examples/dev_example.c new file mode 100644 index 0000000..bff14dc --- /dev/null +++ b/examples/dev_example.c @@ -0,0 +1,69 @@ +/* Shows an example of how to use CMC_DEV */ + +/** + * CMC_DEV is a macro that enables DEV mode. It comes with tracing of functions + * and other things that are printed in the terminal in order to debug the code. + * + * You can always compile this with -DCMC_DEV, but in this example we explicitly + * define it in the file. + * + * CMC_DEV uses the cmc/utl/log.h utility. Through it, you can customize the log + * levels and when to enable it. + */ +#define CMC_DEV +#define CMC_LOG_COLOR /* Optional */ + +#define V int +#define SNAME list +#define PFX l +#define CMC_EXT_ITER +#define CMC_EXT_STR +#include "cmc/list.h" + +#include "cmc/utl/futils.h" + +int main() +{ + struct list *list = l_new(32, &(struct list_fval){ .str = cmc_i32_str }); + + if (!list || l_flag(list) != CMC_FLAG_OK) + { +#ifdef CMC_DEV + cmc_log_error("error: %s", cmc_flags_to_str[l_flag(list)]); +#endif + return 1; + } + +#ifdef CMC_DEV + /* We don't want to debug this, so disable it for now */ + cmc_log_config.enabled = false; +#endif + + for (int i = 0; i < 100; i++) + { + if (!l_push_back(list, i)) + { + enum cmc_flags flag = l_flag(list); + fprintf(stderr, "%s : push_back failed\n", cmc_flags_to_str[flag]); + } + } + + /* Turn it back on on the operations that we actually care to debug */ +#ifdef CMC_DEV + cmc_log_config.enabled = true; +#endif + + for (struct list_iter it = l_iter_start(list); !l_iter_at_end(&it); l_iter_next(&it)) + { + int *val = l_iter_rvalue(&it); + + if (val != NULL) + *val *= 2; + } + + if (!l_print(list, stdout, "[", ", ", "]\n")) + return 2; + + // Free all of its resources + l_free(list); +} diff --git a/examples/sac_example.c b/examples/sac_example.c new file mode 100644 index 0000000..83c1722 --- /dev/null +++ b/examples/sac_example.c @@ -0,0 +1,57 @@ +/* Shows an example of how to use CMC_SAC */ + +/** + * CMC_SAC makes a data structure have a fixed size buffer to store data. + */ +#define CMC_SAC + +#define V int +#define SNAME list +#define PFX l +#define SIZE 100 /* This sets the buffer size */ +#define CMC_EXT_ITER +#define CMC_EXT_STR +#define CMC_EXT_INIT +#define CMC_EXT_SEQ +#include "cmc/list.h" + +#include "cmc/utl/futils.h" + +int main() +{ + struct list list = l_init(&(struct list_fval){ .str = cmc_i32_str }); + + if (l_flag(&list) != CMC_FLAG_OK) + return 1; + + for (int i = 1; i < 1000; i++) + { + if (!l_push_back(&list, i)) + { + if (l_flag(&list) == CMC_FLAG_FULL) + { + printf("List full, stopping...\n"); + break; + } + else + { + enum cmc_flags flag = l_flag(&list); + fprintf(stderr, "%s : push_back failed\n", cmc_flags_to_str[flag]); + } + } + } + + for (struct list_iter it = l_iter_start(&list); !l_iter_at_end(&it); l_iter_next(&it)) + { + int *val = l_iter_rvalue(&it); + + if (val != NULL) + *val *= 2; + } + + if (!l_print(&list, stdout, "[", ", ", "]\n")) + return 2; + + // Free all of its resources + l_release(list); +} diff --git a/src/cmc/cmc/list/code.h b/src/cmc/cmc/list/code.h index 7bb0630..a65a9ac 100644 --- a/src/cmc/cmc/list/code.h +++ b/src/cmc/cmc/list/code.h @@ -25,17 +25,30 @@ /* Implementation Detail Functions */ /* None */ +#ifdef CMC_SAC +struct SNAME *CMC_(PFX, _new)(struct CMC_DEF_FVAL(SNAME) * f_val) +#else struct SNAME *CMC_(PFX, _new)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val) +#endif { #ifdef CMC_DEV CMC_DEV_FCALL; #endif +#ifdef CMC_SAC + return CMC_(PFX, _new_custom)(f_val, NULL, NULL); +#else return CMC_(PFX, _new_custom)(capacity, f_val, NULL, NULL); +#endif } +#ifdef CMC_SAC +struct SNAME *CMC_(PFX, _new_custom)(struct CMC_DEF_FVAL(SNAME) * f_val, struct CMC_ALLOC_NODE_NAME *alloc, + struct CMC_CALLBACKS_NAME *callbacks) +#else struct SNAME *CMC_(PFX, _new_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val, struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks) +#endif { #ifdef CMC_DEV CMC_DEV_FCALL; @@ -43,8 +56,10 @@ struct SNAME *CMC_(PFX, _new_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) CMC_CALLBACKS_MAYBE_UNUSED(callbacks); +#ifndef CMC_SAC if (capacity < 1) return NULL; +#endif if (!f_val) return NULL; @@ -57,15 +72,23 @@ struct SNAME *CMC_(PFX, _new_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) if (!_list_) return NULL; +#ifdef CMC_SAC + memset(_list_->buffer, 0, sizeof(V) * SIZE); +#else _list_->buffer = alloc->calloc(capacity, sizeof(V)); +#endif +#ifndef CMC_SAC if (!_list_->buffer) { alloc->free(_list_); return NULL; } +#endif +#ifndef CMC_SAC _list_->capacity = capacity; +#endif _list_->count = 0; _list_->flag = CMC_FLAG_OK; _list_->f_val = f_val; @@ -87,7 +110,11 @@ void CMC_(PFX, _clear)(struct SNAME *_list_) _list_->f_val->free(_list_->buffer[i]); } +#ifdef CMC_SAC + memset(_list_->buffer, 0, sizeof(V) * SIZE); +#else memset(_list_->buffer, 0, sizeof(V) * _list_->capacity); +#endif _list_->count = 0; _list_->flag = CMC_FLAG_OK; @@ -105,7 +132,9 @@ void CMC_(PFX, _free)(struct SNAME *_list_) _list_->f_val->free(_list_->buffer[i]); } +#ifndef CMC_SAC _list_->alloc->free(_list_->buffer); +#endif _list_->alloc->free(_list_); } @@ -118,10 +147,14 @@ void CMC_(PFX, _customize)(struct SNAME *_list_, struct CMC_ALLOC_NODE_NAME *all CMC_CALLBACKS_MAYBE_UNUSED(callbacks); +#ifdef CMC_SAC + CMC_UNUSED_PARAM(alloc); +#else if (!alloc) _list_->alloc = &cmc_alloc_node_default; else _list_->alloc = alloc; +#endif CMC_CALLBACKS_ASSIGN(_list_, callbacks); @@ -136,8 +169,13 @@ bool CMC_(PFX, _push_front)(struct SNAME *_list_, V value) if (CMC_(PFX, _full)(_list_)) { +#ifdef CMC_SAC + _list_->flag = CMC_FLAG_FULL; + return false; +#else if (!CMC_(PFX, _resize)(_list_, _list_->count * 2)) return false; +#endif } if (!CMC_(PFX, _empty)(_list_)) @@ -169,8 +207,13 @@ bool CMC_(PFX, _push_at)(struct SNAME *_list_, V value, size_t index) if (CMC_(PFX, _full)(_list_)) { +#ifdef CMC_SAC + _list_->flag = CMC_FLAG_FULL; + return false; +#else if (!CMC_(PFX, _resize)(_list_, _list_->count * 2)) return false; +#endif } memmove(_list_->buffer + index + 1, _list_->buffer + index, (_list_->count - index) * sizeof(V)); @@ -192,8 +235,13 @@ bool CMC_(PFX, _push_back)(struct SNAME *_list_, V value) if (CMC_(PFX, _full)(_list_)) { +#ifdef CMC_SAC + _list_->flag = CMC_FLAG_FULL; + return false; +#else if (!CMC_(PFX, _resize)(_list_, _list_->count * 2)) return false; +#endif } _list_->buffer[_list_->count++] = value; @@ -436,7 +484,11 @@ bool CMC_(PFX, _full)(struct SNAME *_list_) CMC_DEV_FCALL; #endif +#ifdef CMC_SAC + return _list_->count >= SIZE; +#else return _list_->count >= _list_->capacity; +#endif } size_t CMC_(PFX, _count)(struct SNAME *_list_) @@ -454,7 +506,11 @@ bool CMC_(PFX, _fits)(struct SNAME *_list_, size_t size) CMC_DEV_FCALL; #endif +#ifdef CMC_SAC + return _list_->count + size <= SIZE; +#else return _list_->count + size <= _list_->capacity; +#endif } size_t CMC_(PFX, _capacity)(struct SNAME *_list_) @@ -463,7 +519,12 @@ size_t CMC_(PFX, _capacity)(struct SNAME *_list_) CMC_DEV_FCALL; #endif +#ifdef CMC_SAC + CMC_UNUSED_PARAM(_list_); + return SIZE; +#else return _list_->capacity; +#endif } int CMC_(PFX, _flag)(struct SNAME *_list_) @@ -475,6 +536,7 @@ int CMC_(PFX, _flag)(struct SNAME *_list_) return _list_->flag; } +#ifndef CMC_SAC bool CMC_(PFX, _resize)(struct SNAME *_list_, size_t capacity) { #ifdef CMC_DEV @@ -509,6 +571,7 @@ bool CMC_(PFX, _resize)(struct SNAME *_list_, size_t capacity) return true; } +#endif struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_list_) { @@ -516,7 +579,11 @@ struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_list_) CMC_DEV_FCALL; #endif +#ifdef CMC_SAC + struct SNAME *result = CMC_(PFX, _new_custom)(_list_->f_val, _list_->alloc, NULL); +#else struct SNAME *result = CMC_(PFX, _new_custom)(_list_->capacity, _list_->f_val, _list_->alloc, NULL); +#endif if (!result) { diff --git a/src/cmc/cmc/list/ext/code.h b/src/cmc/cmc/list/ext/code.h index e801405..50e51e3 100644 --- a/src/cmc/cmc/list/ext/code.h +++ b/src/cmc/cmc/list/ext/code.h @@ -30,17 +30,30 @@ */ #ifdef CMC_EXT_INIT +#ifdef CMC_SAC +struct SNAME CMC_(PFX, _init)(struct CMC_DEF_FVAL(SNAME) * f_val) +#else struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val) +#endif { #ifdef CMC_DEV CMC_DEV_FCALL; #endif +#ifdef CMC_SAC + return CMC_(PFX, _init_custom)(f_val, NULL, NULL); +#else return CMC_(PFX, _init_custom)(capacity, f_val, NULL, NULL); +#endif } +#ifdef CMC_SAC +struct SNAME CMC_(PFX, _init_custom)(struct CMC_DEF_FVAL(SNAME) * f_val, struct CMC_ALLOC_NODE_NAME *alloc, + struct CMC_CALLBACKS_NAME *callbacks) +#else struct SNAME CMC_(PFX, _init_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val, struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks) +#endif { #ifdef CMC_DEV CMC_DEV_FCALL; @@ -50,8 +63,10 @@ struct SNAME CMC_(PFX, _init_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) struct SNAME _list_ = { 0 }; +#ifndef CMC_SAC if (capacity < 1) return _list_; +#endif if (!f_val) return _list_; @@ -59,12 +74,18 @@ struct SNAME CMC_(PFX, _init_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) if (!alloc) alloc = &cmc_alloc_node_default; +#ifdef CMC_SAC + memset(_list_.buffer, 0, sizeof(V) * SIZE); +#else _list_.buffer = alloc->calloc(capacity, sizeof(V)); +#endif if (!_list_.buffer) return _list_; +#ifndef CMC_SAC _list_.capacity = capacity; +#endif _list_.count = 0; _list_.flag = CMC_FLAG_OK; _list_.f_val = f_val; @@ -86,7 +107,9 @@ void CMC_(PFX, _release)(struct SNAME _list_) _list_.f_val->free(_list_.buffer[i]); } +#ifndef CMC_SAC _list_.alloc->free(_list_.buffer); +#endif } #endif /* CMC_EXT_INIT */ @@ -358,8 +381,13 @@ bool CMC_(PFX, _seq_push_front)(struct SNAME *_list_, V *values, size_t size) if (!CMC_(PFX, _fits)(_list_, size)) { +#ifdef CMC_SAC + _list_->flag = CMC_FLAG_FULL; + return false; +#else if (!CMC_(PFX, _resize)(_list_, _list_->count + size)) return false; +#endif } memmove(_list_->buffer + size, _list_->buffer, _list_->count * sizeof(V)); @@ -399,8 +427,13 @@ bool CMC_(PFX, _seq_push_at)(struct SNAME *_list_, V *values, size_t size, size_ if (!CMC_(PFX, _fits)(_list_, size)) { +#ifdef CMC_SAC + _list_->flag = CMC_FLAG_FULL; + return false; +#else if (!CMC_(PFX, _resize)(_list_, _list_->count + size)) return false; +#endif } memmove(_list_->buffer + index + size, _list_->buffer + index, (_list_->count - index) * sizeof(V)); @@ -429,8 +462,13 @@ bool CMC_(PFX, _seq_push_back)(struct SNAME *_list_, V *values, size_t size) if (!CMC_(PFX, _fits)(_list_, size)) { +#ifdef CMC_SAC + _list_->flag = CMC_FLAG_FULL; + return false; +#else if (!CMC_(PFX, _resize)(_list_, _list_->count + size)) return false; +#endif } memcpy(_list_->buffer + _list_->count, values, size * sizeof(V)); @@ -495,7 +533,11 @@ struct SNAME *CMC_(PFX, _seq_sublist)(struct SNAME *_list_, size_t from, size_t size_t length = to - from + 1; +#ifdef CMC_SAC + struct SNAME *result = CMC_(PFX, _new_custom)(_list_->f_val, _list_->alloc, CMC_CALLBACKS_GET(_list_)); +#else struct SNAME *result = CMC_(PFX, _new_custom)(length, _list_->f_val, _list_->alloc, CMC_CALLBACKS_GET(_list_)); +#endif if (!result) { @@ -546,8 +588,14 @@ bool CMC_(PFX, _to_string)(struct SNAME *_list_, FILE *fptr) "f_val:%p, " "alloc:%p, " "callbacks:%p }", - CMC_TO_STRING(SNAME), CMC_TO_STRING(V), l_, l_->buffer, l_->capacity, l_->count, l_->flag, - l_->f_val, l_->alloc, CMC_CALLBACKS_GET(l_)); + CMC_TO_STRING(SNAME), CMC_TO_STRING(V), l_, l_->buffer, +#ifdef CMC_SAC + (size_t)SIZE +#else + l_->capacity +#endif + , + l_->count, l_->flag, l_->f_val, l_->alloc, CMC_CALLBACKS_GET(l_)); } bool CMC_(PFX, _print)(struct SNAME *_list_, FILE *fptr, const char *start, const char *separator, const char *end) diff --git a/src/cmc/cmc/list/ext/header.h b/src/cmc/cmc/list/ext/header.h index 7e2ffd2..7fa489f 100644 --- a/src/cmc/cmc/list/ext/header.h +++ b/src/cmc/cmc/list/ext/header.h @@ -30,9 +30,15 @@ */ #ifdef CMC_EXT_INIT +#ifdef CMC_SAC +struct SNAME CMC_(PFX, _init)(struct CMC_DEF_FVAL(SNAME) * f_val); +struct SNAME CMC_(PFX, _init_custom)(struct CMC_DEF_FVAL(SNAME) * f_val, struct CMC_ALLOC_NODE_NAME *alloc, + struct CMC_CALLBACKS_NAME *callbacks); +#else struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val); struct SNAME CMC_(PFX, _init_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val, struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks); +#endif void CMC_(PFX, _release)(struct SNAME _list_); #endif /* CMC_EXT_INIT */ diff --git a/src/cmc/cmc/list/header.h b/src/cmc/cmc/list/header.h index 84979ba..d9fb587 100644 --- a/src/cmc/cmc/list/header.h +++ b/src/cmc/cmc/list/header.h @@ -40,9 +40,15 @@ struct CMC_DEF_FVAL(SNAME) }; /* Collection Allocation and Deallocation */ +#ifdef CMC_SAC +struct SNAME *CMC_(PFX, _new)(struct CMC_DEF_FVAL(SNAME) * f_val); +struct SNAME *CMC_(PFX, _new_custom)(struct CMC_DEF_FVAL(SNAME) * f_val, struct CMC_ALLOC_NODE_NAME *alloc, + struct CMC_CALLBACKS_NAME *callbacks); +#else struct SNAME *CMC_(PFX, _new)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val); struct SNAME *CMC_(PFX, _new_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val, struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks); +#endif void CMC_(PFX, _clear)(struct SNAME *_list_); void CMC_(PFX, _free)(struct SNAME *_list_); /* Customization of Allocation and Callbacks */ diff --git a/src/cmc/cmc/list/struct.h b/src/cmc/cmc/list/struct.h index 25cb942..214a478 100644 --- a/src/cmc/cmc/list/struct.h +++ b/src/cmc/cmc/list/struct.h @@ -24,10 +24,14 @@ struct SNAME { +#ifdef CMC_SAC + V buffer[SIZE]; +#else /* Dynamic array of elements */ V *buffer; /* Current array capacity */ size_t capacity; +#endif /* Current amount of elements */ size_t count; /* Flags indicating errors or success */ diff --git a/src/cmc/cor/callbacks.h b/src/cmc/cor/callbacks.h index 90648b4..3a204af 100644 --- a/src/cmc/cor/callbacks.h +++ b/src/cmc/cor/callbacks.h @@ -44,8 +44,8 @@ #ifdef CMC_NO_CALLBACKS #define CMC_CALLBACKS_DECL -#define CMC_CALLBACKS_MAYBE_UNUSED(param) ((void)param) /* Prevent -Wunused-parameter */ -#define CMC_CALLBACKS_GET(ds) NULL /* Helps with compatibility */ +#define CMC_CALLBACKS_MAYBE_UNUSED(param) CMC_UNUSED_PARAM(param) /* Prevent -Wunused-parameter */ +#define CMC_CALLBACKS_GET(ds) NULL /* Helps with compatibility */ #define CMC_CALLBACKS_ASSIGN(ds, cb) #define CMC_CALLBACKS_CALL(ds, cb) diff --git a/src/cmc/cor/core.h b/src/cmc/cor/core.h index ef6bc2f..5acab77 100644 --- a/src/cmc/cor/core.h +++ b/src/cmc/cor/core.h @@ -63,6 +63,8 @@ #define CMC_UNUSED #endif +#define CMC_UNUSED_PARAM(param) ((void)param) + #define CMC__(A, B) A##B #define CMC_(A, B) CMC__(A, B) diff --git a/src/cmc/cor/dev.h b/src/cmc/cor/dev.h index 3e5958d..a91faa8 100644 --- a/src/cmc/cor/dev.h +++ b/src/cmc/cor/dev.h @@ -25,7 +25,7 @@ /** * dev.h * - * Creation Date: 24/05/2020 + * Creation Date: 01/02/2023 * * Authors: * Leonardo Vencovsky (https://github.com/LeoVen) diff --git a/src/cmc/list.h b/src/cmc/list.h index ed513b7..0bb39a6 100644 --- a/src/cmc/list.h +++ b/src/cmc/list.h @@ -70,6 +70,10 @@ #include "utl/log.h" #endif +#if defined(CMC_SAC) && !defined(SIZE) +#error "When using CMC_SAC, please also define SIZE" +#endif + /** * Used values * V - list data type