From 0fca9b77e373fc5316fd0e6c4e8ed79501a202c8 Mon Sep 17 00:00:00 2001 From: TheoryOfNekomata Date: Wed, 15 Feb 2023 07:53:55 +0800 Subject: [PATCH] Update linked list implementation Use node pointers instead of duplicating the find function logic. --- src/packages/game/data/IZ_list.c | 25 +++++++++---------------- src/packages/game/data/IZ_list.h | 2 +- src/packages/game/data/README.md | 4 +++- src/packages/game/data/data.test.c | 7 ++++--- src/packages/game/memory/IZ_pool.c | 2 +- 5 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/packages/game/data/IZ_list.c b/src/packages/game/data/IZ_list.c index 3f82626..66da775 100644 --- a/src/packages/game/data/IZ_list.c +++ b/src/packages/game/data/IZ_list.c @@ -1,9 +1,5 @@ #include "IZ_list.h" -bool IZ_ListFindFilterAlwaysTrue(IZ_ListNode** _node, u64 _index, IZ_List* _list) { - return true; -} - /** * Initializes a list. * @param list - The list to initialize. @@ -20,10 +16,9 @@ void IZ_ListInitialize(IZ_List* list) { */ void IZ_ListTeardown(IZ_List* list) { while (list->root) { - IZ_ListDeleteFirstNode(list, IZ_ListFindFilterAlwaysTrue); + IZ_ListDeleteNode(list, &list->root); } - list->iterator = NULL; - list->length = 0; + IZ_free(list); } /** @@ -54,30 +49,28 @@ IZ_ListNode** IZ_ListAppendNode(IZ_List* list, void* node_value) { /** * Deletes the first node in the list that matches the filter. * @param list - The list to delete from. - * @param filter - The filter to use to find the node to delete. + * @param node - The node to delete. */ -void IZ_ListDeleteFirstNode(IZ_List* list, IZ_ListFindPredicate filter) { - if (!(list && list->root)) { +void IZ_ListDeleteNode(IZ_List* list, IZ_ListNode** node) { + if (!(list && list->root && node)) { // should we raise warnings here? return; } // FIXME Teardown having problems here list->iterator = &list->root; - IZ_ListNode* previous_node = NULL; - u64 index = 0; + IZ_ListNode** previous_node = NULL; do { - if (!filter(list->iterator, index, list)) { - previous_node = *list->iterator; + if (list->iterator != node) { + previous_node = list->iterator; list->iterator = &((*list->iterator)->next); - index += 1; // we haven't found the node we're looking for, go to the next one continue; } if (previous_node) { // this is not the first node in the list - previous_node->next = (*list->iterator)->next; + (*previous_node)->next = (*list->iterator)->next; } else { // this is the first node, set it as new root list->root = (*list->iterator)->next; diff --git a/src/packages/game/data/IZ_list.h b/src/packages/game/data/IZ_list.h index df7c50b..cb5d8db 100644 --- a/src/packages/game/data/IZ_list.h +++ b/src/packages/game/data/IZ_list.h @@ -57,7 +57,7 @@ IZ_ListNode** IZ_ListAppendNode(IZ_List*, void*); /** * Deletes the first node in the list that matches the filter. */ -void IZ_ListDeleteFirstNode(IZ_List*, IZ_ListFindPredicate); +void IZ_ListDeleteNode(IZ_List*, IZ_ListNode**); /** * Finds the first node in the list that matches the filter. diff --git a/src/packages/game/data/README.md b/src/packages/game/data/README.md index 9dd7ac9..aebc806 100644 --- a/src/packages/game/data/README.md +++ b/src/packages/game/data/README.md @@ -38,8 +38,10 @@ int main() { printf("Found node with value 2!\n"); } + ListNode* delete_node; + delete_node = IZ_ListFindFirstNode(&list, &FindNodeWithValueOne); // deletions are done only on one node at a time - IZ_ListDeleteFirstNode(&list, &FindNodeWithValueOne); + IZ_ListDeleteNode(&list, delete_node); // teardown takes care of de-allocating nodes and making sure data cannot be accessed sensibly anymore. IZ_ListTeardown(&list); diff --git a/src/packages/game/data/data.test.c b/src/packages/game/data/data.test.c index b5d94a5..8ce0cca 100644 --- a/src/packages/game/data/data.test.c +++ b/src/packages/game/data/data.test.c @@ -53,7 +53,7 @@ spec("data") { } it("removes all nodes from the list") { - mock_set_expected_calls(IZ_free, 3); + mock_set_expected_calls(IZ_free, 4); IZ_ListTeardown(&list); unsigned int expected_calls = mock_get_expected_calls(IZ_free); unsigned int actual_calls = mock_get_actual_calls(IZ_free); @@ -151,7 +151,7 @@ spec("data") { } } - describe("DeleteFirstNode") { + describe("DeleteNode") { static IZ_List list; before_each() { @@ -170,7 +170,8 @@ spec("data") { } it("removes first node satisfying the filter condition") { - IZ_ListDeleteFirstNode(&list, NodeExists); + IZ_ListNode** existing_node = IZ_ListFindFirstNode(&list, NodeExists); + IZ_ListDeleteNode(&list, existing_node); check( mock_is_called(IZ_free), diff --git a/src/packages/game/memory/IZ_pool.c b/src/packages/game/memory/IZ_pool.c index 42e6d9d..45f523f 100644 --- a/src/packages/game/memory/IZ_pool.c +++ b/src/packages/game/memory/IZ_pool.c @@ -43,7 +43,7 @@ bool IZ_PoolGetSameItem(IZ_ListNode** node, u64 _index, IZ_List* list) { } void IZ_PoolDeallocate(IZ_PoolItem* item) { - IZ_ListDeleteFirstNode(&item->pool->items, IZ_PoolGetSameItem); + IZ_ListDeleteNode(&item->pool->items, IZ_PoolGetSameItem); } void IZ_PoolTeardown(IZ_Pool* pool) {