From 53a63e61db7b8e59048c2b30a39155e64539cb8a Mon Sep 17 00:00:00 2001 From: Eric-Paul Ickhorn Date: Wed, 31 Jan 2024 00:58:11 +0100 Subject: [PATCH] General codebase improvements and a fix for a bug in the tag registry --- action.bash | 3 + build_tests.bash | 3 +- core/exports/maintree/maintree.h | 68 +++++++++---------- core/inc-c/tag_registry.h | 2 +- core/src-c/state.c | 4 ++ core/src-c/tag_registry.c | 32 ++++++--- core/tests/interface/entity-creation/main.c | 10 ++- .../internal/basic-tag-registry-usage/main.c | 33 ++++++++- core/tests/internal/entity-lookup/main.c | 16 +++-- 9 files changed, 113 insertions(+), 58 deletions(-) diff --git a/action.bash b/action.bash index 73071fa..e16b2c4 100755 --- a/action.bash +++ b/action.bash @@ -133,6 +133,9 @@ case $1 in "b" | "build-dependencies") build_dependencies ;; + "t" | "test") + ./build_tests.bash + ;; "h" | "help") echo "Known Actions:" echo "[ d | dbg | debug ]: Build in the debug profile; build with debug symbols." diff --git a/build_tests.bash b/build_tests.bash index 4cebf35..ba76658 100755 --- a/build_tests.bash +++ b/build_tests.bash @@ -4,6 +4,7 @@ cd $(dirname "$(pwd)/$0") REPOSITORY_FOLDER=$(pwd) MAIN_OBJECTS_FOLDER="$REPOSITORY_FOLDER/.build/objects/" +CC_OPTIONS="-g3 -Wall -Wextra -Wpedantic" DEFAULT_INCLUDE_PATHS=" -I .build/depends/libRR/Core/core/exports/ -I .build/depends/libRR/Core/platform/exports/ @@ -55,7 +56,7 @@ function compile_single_test() { get_include_path_configuration $TEST_PATH get_linkage_path_configuration $TEST_PATH - gcc -g3 -o $TEST_PATH/$TEST_NAME.elf $TEST_PATH/*.c $LINKAGE_PATHS $INCLUDE_STATEMENTS + gcc $CC_OPTIONS -o $TEST_PATH/$TEST_NAME.elf $TEST_PATH/*.c $LINKAGE_PATHS $INCLUDE_STATEMENTS } function compile_all_tests_of_module() { diff --git a/core/exports/maintree/maintree.h b/core/exports/maintree/maintree.h index f136ccf..1e1e6c6 100644 --- a/core/exports/maintree/maintree.h +++ b/core/exports/maintree/maintree.h @@ -6,14 +6,14 @@ #include #include -typedef void * MtEntity; +typedef void MtEntity; /// @brief: An MtTask is a piece of functionality with an own state/context which will be executed on the same thread or set of threads. -typedef void * MtTask; -typedef void * MtState; +typedef void MtTask; +typedef void MtState; -typedef void (*MtEffectorFn) (MtEntity entity, void *userdata, usz_t invocation_id); -typedef void (*MtTaskMainFn) (MtTask task, void *userdata); +typedef void (*MtEffectorFn) (MtEntity *entity, void *userdata, usz_t invocation_id); +typedef void (*MtTaskMainFn) (MtTask *task, void *userdata); typedef struct { @@ -27,18 +27,18 @@ typedef struct -MtState mt_initialize(char *app_name); -void mt_cleanup(MtState state); -void mt_start(MtState state); +MtState * mt_initialize(char *app_name); +void mt_cleanup(MtState *state); +void mt_start(MtState *state); -MtEntity mt_summon(MtState state); -void mt_drop(MtEntity entity); +MtEntity * mt_summon(MtState *state); +void mt_drop(MtEntity *entity); -void mt_add_create_effector(MtState state, char *effector_name, MtEffectorFn function, void *userdata); -void mt_add_delete_effector(MtState state, char *effector_name, MtEffectorFn function, void *userdata); -void mt_add_entity_effector(MtState state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, void *userdata); -void mt_add_tick_effector(MtState state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, void *userdata); -void mt_remove_effector(MtState state, const char *effector_name); +void mt_add_create_effector(MtState *state, char *effector_name, MtEffectorFn function, void *userdata); +void mt_add_delete_effector(MtState *state, char *effector_name, MtEffectorFn function, void *userdata); +void mt_add_entity_effector(MtState *state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, void *userdata); +void mt_add_tick_effector(MtState *state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, void *userdata); +void mt_remove_effector(MtState *state, const char *effector_name); /// @brief Adds a tick effector which only acts upon entitys with certain tags. /// @param state The state in which the tick effector should reside. @@ -46,29 +46,29 @@ void mt_remove_effector(MtState state, const char *effector_name); /// @param ticks_delta The wanted number of ticks between two invocations of the effector. /// @param function The function to call for an entity if it contains all necessary tags. /// @param tag_names A nullpointer-terminated list of tag-ids that must be present in an entity for that entity to be effected. -void mt_add_tagged_tick_effector(MtState state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, char **tag_names); +void mt_add_tagged_tick_effector(MtState *state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, char **tag_names); -void mt_tag_i64(MtEntity entity, char *name, i64_t integer); -void mt_tag_f64(MtEntity entity, char *name, f64_t real); -void mt_tag_str(MtEntity entity, char *name, char *string); -void mt_tag_ptr(MtEntity entity, char *name, void *pointer); -void mt_tag_vec2(MtEntity entity, char *name, rr_vec2f_s vector); -void mt_tag_vec3(MtEntity entity, char *name, rr_vec3f_s vector); -void mt_tag_vec4(MtEntity entity, char *name, rr_vec4f_s vector); +void mt_tag_i64(MtEntity *entity, char *name, i64_t integer); +void mt_tag_f64(MtEntity *entity, char *name, f64_t real); +void mt_tag_str(MtEntity *entity, char *name, char *string); +void mt_tag_ptr(MtEntity *entity, char *name, void *pointer); +void mt_tag_vec2(MtEntity *entity, char *name, rr_vec2f_s vector); +void mt_tag_vec3(MtEntity *entity, char *name, rr_vec3f_s vector); +void mt_tag_vec4(MtEntity *entity, char *name, rr_vec4f_s vector); -void mt_untag(MtEntity entity, char *name); +void mt_untag(MtEntity *entity, char *name); -i64_t mt_get_i64_tag(MtEntity entity, char *name); -f64_t mt_get_f64_tag(MtEntity entity, char *name); -char * mt_get_str_tag(MtEntity entity, char *name); -void * mt_get_ptr_tag(MtEntity entity, char *name); -rr_vec2f_s mt_get_vec2_tag(MtEntity entity, char *name); -rr_vec3f_s mt_get_vec3_tag(MtEntity entity, char *name); -rr_vec4f_s mt_get_vec4_tag(MtEntity entity, char *name); +i64_t mt_get_i64_tag(MtEntity *entity, char *name); +f64_t mt_get_f64_tag(MtEntity *entity, char *name); +char * mt_get_str_tag(MtEntity *entity, char *name); +void * mt_get_ptr_tag(MtEntity *entity, char *name); +rr_vec2f_s mt_get_vec2_tag(MtEntity *entity, char *name); +rr_vec3f_s mt_get_vec3_tag(MtEntity *entity, char *name); +rr_vec4f_s mt_get_vec4_tag(MtEntity *entity, char *name); -MtTask mt_create_task(MtState state, MtTaskCreationInfo creation_info); -void mt_delete_task(MtTask task); +MtTask mt_create_task(MtState *state, MtTaskCreationInfo creation_info); +void mt_delete_task(MtTask *task); -void mt_task_remove_effector(MtTask task, const char *effector_name); +void mt_task_remove_effector(MtTask *task, const char *effector_name); #endif // MAINTREE_H diff --git a/core/inc-c/tag_registry.h b/core/inc-c/tag_registry.h index 6d11242..835a7d9 100644 --- a/core/inc-c/tag_registry.h +++ b/core/inc-c/tag_registry.h @@ -37,7 +37,7 @@ struct MtTagCollection u32_t capacity; u32_t usage; - /// @brief An array of indices for the tag-registry's 'entries'-array. + /// @brief An array of indices into the tag-registry's 'entries'-array. u32_t *tag_indices; }; diff --git a/core/src-c/state.c b/core/src-c/state.c index 507bd5f..07be5cc 100644 --- a/core/src-c/state.c +++ b/core/src-c/state.c @@ -5,6 +5,10 @@ MtState * mt_initialize(char *app_name) { + if(app_name == NULL) + { + app_name = "Unnamed Application"; + } usz_t len_app_name = rr_measure_string(app_name); MtState *state = malloc(sizeof(struct MtState)); diff --git a/core/src-c/tag_registry.c b/core/src-c/tag_registry.c index fa60b57..91ee5bb 100644 --- a/core/src-c/tag_registry.c +++ b/core/src-c/tag_registry.c @@ -82,9 +82,28 @@ u32_t mt_tag_label_to_hash(const char *tag_label, usz_t range) MtTagEntry * mt_create_tag_hash_entry(MtTagRegistry *registry, const char *tag_label) { + // Create a new entry in the flat array of entries + + usz_t entry_index = registry->num_entries; + MtTagEntry *entry = ®istry->entries[entry_index]; + ++registry->num_entries; + + usz_t len_tag_label = rr_measure_string(tag_label); + + // TODO: There MUST be an arena allocator for this! + entry->label = malloc(len_tag_label + 1); + rr_memcopy(entry->label, tag_label, len_tag_label+1); + + entry->identifier = registry->next_identifier; + ++registry->next_identifier; + + // Create an entry in the lookup structure + u32_t collection_index = mt_tag_label_to_hash(tag_label, registry->num_collections); MtTagCollection *collection = ®istry->collections[collection_index]; + // Resize the collection to be larger if needed + if(collection->usage >= collection->capacity) { collection->capacity *= 2; @@ -94,19 +113,10 @@ MtTagEntry * mt_create_tag_hash_entry(MtTagRegistry *registry, const char *tag_l collection->tag_indices = realloc(collection->tag_indices, sizeof(u32_t) * collection->capacity); rr_memset(&collection->tag_indices[collection->usage], collection->capacity - collection->usage, 0x00); } - MtTagEntry *entry = ®istry->entries[collection->tag_indices[collection->usage]]; - ++registry->num_entries; + + collection->tag_indices[collection->usage] = entry_index; ++collection->usage; - usz_t len_tag_label = rr_measure_string(tag_label); - - // TODO: There must be an arena allocator for this! - entry->label = malloc(len_tag_label + 1); - rr_memcopy(entry->label, tag_label, len_tag_label+1); - - entry->identifier = registry->next_identifier; - ++registry->next_identifier; - return entry; } diff --git a/core/tests/interface/entity-creation/main.c b/core/tests/interface/entity-creation/main.c index 4ad1c9a..cfd694a 100644 --- a/core/tests/interface/entity-creation/main.c +++ b/core/tests/interface/entity-creation/main.c @@ -1,9 +1,13 @@ #include +#include -int main(int argc, char **argv) +int main() { - MtState state = mt_initialize("Interface Test");; - MtEntity entity = mt_summon(state); + MtState *state = mt_initialize("Interface Test");; + MtEntity* entity = mt_summon(state); mt_drop(entity); mt_cleanup(state); + puts("The program reached the end; this test is considered as passed. SUCCESS!"); + puts("Note: A memory leak check utility should be used to verify the success."); + return 0; } diff --git a/core/tests/internal/basic-tag-registry-usage/main.c b/core/tests/internal/basic-tag-registry-usage/main.c index ff75892..94f4642 100644 --- a/core/tests/internal/basic-tag-registry-usage/main.c +++ b/core/tests/internal/basic-tag-registry-usage/main.c @@ -2,14 +2,43 @@ #include #include -int main(int argc, char **argv) +int main() { MtTagRegistry tag_registry = mt_create_tag_registry(NULL); u32_t some_tag = mt_get_tag_id(&tag_registry, "some_tag"); + u32_t another_tag = mt_get_tag_id(&tag_registry, "another_tag"); + u32_t theres_more = mt_get_tag_id(&tag_registry, "there's more"); if(some_tag != mt_get_tag_id(&tag_registry, "some_tag")) { - puts("Inconsistent returned tag identifiers."); + puts("Inconsistently returned tag identifier in test subject 1. ERROR!"); + mt_delete_tag_registry(tag_registry); + return -1; + } + if(another_tag != mt_get_tag_id(&tag_registry, "another_tag")) + { + puts("Inconsistently returned tag identifier in test subject 2. ERROR!"); + mt_delete_tag_registry(tag_registry); + return -1; + } + if(theres_more != mt_get_tag_id(&tag_registry, "there's more")) + { + puts("Inconsistently returned tag identifier in test subject 3. ERROR!"); + mt_delete_tag_registry(tag_registry); + return -1; + } + if(some_tag == theres_more) + { + puts("Tags are being duplicated in test subject 4. ERROR!"); + mt_delete_tag_registry(tag_registry); + return -1; + } + if(some_tag == another_tag) + { + puts("Tags are being duplicated in test subject 5. ERROR!"); + mt_delete_tag_registry(tag_registry); + return -1; } mt_delete_tag_registry(tag_registry); + puts("The identifier which is returned for a tag name is consistent. SUCCESS!"); return 0; } diff --git a/core/tests/internal/entity-lookup/main.c b/core/tests/internal/entity-lookup/main.c index 9269386..1f3b406 100644 --- a/core/tests/internal/entity-lookup/main.c +++ b/core/tests/internal/entity-lookup/main.c @@ -3,17 +3,21 @@ #include -int main(int argc, char **argv) +int main() { MtState *state = mt_initialize("Interface Test");; MtEntity *entity = mt_summon(state); MtEntity *looked_up_entity = mt_get_entity(state, entity->identifier); if(entity != looked_up_entity) - printf("Failed looking up entity; the pointers don't match:\nOriginal: %p\nLooked Up: %p\n", entity, looked_up_entity); - else - puts("The entity which was looked up from the identifier does match the original. SUCCESS!"); - + { + printf("Failed looking up entity; the pointers don't match:\nOriginal: %p\nLooked Up: %p\nERROR!", (void *) entity, (void *) looked_up_entity); + mt_drop(entity); + mt_cleanup(state); + return -1; + } + puts("The entity which was looked up from the identifier does match the original. SUCCESS!"); mt_drop(entity); mt_cleanup(state); -} \ No newline at end of file + return 0; +}