From b7f739bbfcd37538987d5f4f19b34842f53e43fd Mon Sep 17 00:00:00 2001 From: Ulysse Cura Date: Mon, 3 Aug 2026 19:14:29 +0200 Subject: [PATCH] Added a linked list exit function for reserved elements and documented unsafe functions. --- src/asset_manager.c | 4 +- src/ecs.c | 4 +- src/headers/linked_list.h | 67 ++++++++++++++++++++------------- src/linked_list.c | 78 +++++++++++++++++++++++++++------------ 4 files changed, 99 insertions(+), 54 deletions(-) diff --git a/src/asset_manager.c b/src/asset_manager.c index 12235d8..066a817 100644 --- a/src/asset_manager.c +++ b/src/asset_manager.c @@ -104,8 +104,8 @@ int asset_manager_exit(asset_manager_t *asset_manager) { assert("Asset manager cannot be NULL" && asset_manager); - if(linked_list_clear(&asset_manager->assets_header_defs)) return EXIT_FAILURE; - if(linked_list_clear(&asset_manager->assets)) return EXIT_FAILURE; + if(linked_list_exit(&asset_manager->assets_header_defs)) return EXIT_FAILURE; + if(linked_list_exit(&asset_manager->assets)) return EXIT_FAILURE; if(fclose(asset_manager->asset_file)) { diff --git a/src/ecs.c b/src/ecs.c index dc867a1..c0c65b5 100644 --- a/src/ecs.c +++ b/src/ecs.c @@ -76,7 +76,7 @@ inline int destroy_entity(entity_t *entity) return EXIT_FAILURE; } - if(linked_list_clear(&entity->components)) return EXIT_FAILURE; + if(linked_list_exit(&entity->components)) return EXIT_FAILURE; return EXIT_SUCCESS; } @@ -225,7 +225,7 @@ inline int entity_manager_exit(entity_manager_t *entity_manager) { assert("Entity manager cannot be NULL" && entity_manager); - if(linked_list_clear(&entity_manager->entities)) return EXIT_FAILURE; + if(linked_list_exit(&entity_manager->entities)) return EXIT_FAILURE; debug_printf("Exited entity manager."); diff --git a/src/headers/linked_list.h b/src/headers/linked_list.h index 82f8524..030342b 100644 --- a/src/headers/linked_list.h +++ b/src/headers/linked_list.h @@ -103,6 +103,30 @@ typedef struct linked_list_t { size_t target_max_size; } linked_list_t; +/** + * @brief Create an elem to insert in a linked list. The data pointer is allocated. + * If there is an element available in reserved list then it will be used. + * The element returned is filled with garbage memory. + * + * @param linked_list Pointer to an linked list + * @param ... Arguments to pass to the allocator + * + * @return pointer to initialised elem, NULL on error. +*/ +elem_t *create_elem(linked_list_t *linked_list, ...); + +/** + * @brief Destroy the given element and its data. + * May move the element into the reserved list for future use depending on target size of the list. + * This function makes the given element unsafe to use. + * + * @param linked_list Pointer to a linked list + * @param elem Pointer to an element + * + * @return EXIT_SUCCESS, EXIT_FAILURE on error. +*/ +int destroy_elem(linked_list_t *linked_list, elem_t *elem); + /** * @brief Init a linked list. * @@ -112,6 +136,16 @@ typedef struct linked_list_t { */ void linked_list_init(linked_list_t *linked_list, size_t data_size, const allocator_t allocator, const deleter_t deleter); +/** + * @brief Clear the given linked list and free reserved elements, do nothing on error. + * This function makes the given linked list unsafe to use. + * + * @brief linked_list Pointer to a linked list + * + * @return EXIT_SUCCESS, EXIT_FAILURE on error. +*/ +int linked_list_exit(linked_list_t *linked_list); + /** * @brief Pre-allocate elements for a target size. * If you want n more elements in your list, then you want linked_list.size + n target_size. @@ -124,26 +158,14 @@ void linked_list_init(linked_list_t *linked_list, size_t data_size, const alloca int linked_list_reserve(linked_list_t *linked_list, size_t target_size); /** - * @brief Create an elem to insert in a linked list. The data pointer is allocated. - * If there is an element available in reserved list then it will be used. + * @brief Clear the given linked list, do nothing on error. + * May move the elements into the reserved list for future use depending on target size of the list. * - * @param linked_list Pointer to an linked list - * @param ... Arguments to pass to the allocator - * - * @return pointer to initialised elem, NULL on error. -*/ -elem_t *create_elem(linked_list_t *linked_list, ...); - -/** - * @brief Destroy the given element and its data. - * May move the element into the reserved list for future use depending on target size of the list. - * - * @param linked_list Pointer to a linked list - * @param elem Pointer to an element + * @brief linked_list Pointer to a linked list * * @return EXIT_SUCCESS, EXIT_FAILURE on error. */ -int destroy_elem(linked_list_t *linked_list, elem_t *elem); +int linked_list_clear(linked_list_t *linked_list); /** * @brief Insert an element from the back in a linked list, do nothing on error. @@ -167,6 +189,7 @@ int linked_list_push_front(linked_list_t *linked_list, elem_t *elem); /** * @brief Remove and return the last element in the given linked list, do nothing on error. + * The element returned have unsafe `next` and `prev` pointers. * * @param linked_list Pointer to a linked list * @@ -176,6 +199,7 @@ elem_t *linked_list_pop_back(linked_list_t *linked_list); /** * @brief Remove and return the first element in the given linked list, do nothing on error. + * The element returned have unsafe `next` and `prev` pointers. * * @param linked_list Pointer to a linked list * @@ -183,16 +207,6 @@ elem_t *linked_list_pop_back(linked_list_t *linked_list); */ elem_t *linked_list_pop_front(linked_list_t *linked_list); -/** - * @brief Clear the given linked list, do nothing on error. - * May move the elements into the reserved list for future use depending on target size of the list. - * - * @brief linked_list Pointer to a linked list - * - * @return EXIT_SUCCESS, EXIT_FAILURE on error. -*/ -int linked_list_clear(linked_list_t *linked_list); - /** * @brief Insert element at the given index in the linked list, do nothing on error. * @@ -217,6 +231,7 @@ elem_t *linked_list_get(const linked_list_t *linked_list, size_t index); /** * @brief Remove the given elem in the linked list, do nothing on error. * May move the elements into the reserved list for future use depending on target size of the list. + * This function makes the given element unsafe to use. * * @param linked_list Pointer to a linked list * @param elem Element to remove diff --git a/src/linked_list.c b/src/linked_list.c index db8e170..4e1d2b7 100644 --- a/src/linked_list.c +++ b/src/linked_list.c @@ -90,6 +90,60 @@ void linked_list_init(linked_list_t *linked_list, const size_t data_size, const linked_list->target_max_size = 0; } +int linked_list_exit(linked_list_t *linked_list) +{ + assert("Linked list cannot be NULL" && linked_list); + + elem_t *current_elem = linked_list->first; + elem_t *tmp; + + while(current_elem) + { + tmp = current_elem; + + current_elem = current_elem->next; + + if(destroy_elem(linked_list, tmp)) return EXIT_FAILURE; + } + + current_elem = linked_list->reserved; + + while(current_elem) + { + tmp = current_elem; + + current_elem = current_elem->next; + + if(destroy_elem(linked_list, tmp)) return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +int linked_list_clear(linked_list_t *linked_list) +{ + assert("Linked list cannot be NULL" && linked_list); + + elem_t *current_elem = linked_list->first; + elem_t *tmp; + + while(current_elem) + { + tmp = current_elem; + + current_elem = current_elem->next; + + if(destroy_elem(linked_list, tmp)) return EXIT_FAILURE; + } + + linked_list->first = NULL; + linked_list->last = NULL; + + linked_list->size = 0; + + return EXIT_SUCCESS; +} + int linked_list_reserve(linked_list_t *linked_list, size_t target_max_size) { assert("Linked list cannot be NULL" && linked_list); @@ -216,30 +270,6 @@ elem_t *linked_list_pop_front(linked_list_t *linked_list) return elem; } -int linked_list_clear(linked_list_t *linked_list) -{ - assert("Linked list cannot be NULL" && linked_list); - - elem_t *current_elem = linked_list->first; - elem_t *tmp; - - while(current_elem) - { - tmp = current_elem; - - current_elem = current_elem->next; - - if(destroy_elem(linked_list, tmp)) return EXIT_FAILURE; - } - - linked_list->first = NULL; - linked_list->last = NULL; - - linked_list->size = 0; - - return EXIT_SUCCESS; -} - inline bool linked_list_is_empty(const linked_list_t *linked_list) { assert("Linked list cannot be NULL" && linked_list);