From 474f71a0d0463d5b58d37078758571be90d09e5f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 14:11:20 +0000 Subject: [PATCH 1/4] Initial plan From 6990ba5dd978f0042c4e971dfb0f2d5aca091b33 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 14:14:56 +0000 Subject: [PATCH 2/4] Implement dmlist_find_next function with tests Co-authored-by: JohnAmadis <17320783+JohnAmadis@users.noreply.github.com> --- include/dmlist.h | 12 +++++++++ src/dmlist.c | 38 ++++++++++++++++++++++++++++ tests/test_simple.c | 61 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 110 insertions(+), 1 deletion(-) diff --git a/include/dmlist.h b/include/dmlist.h index 80aeff6..6a0d3b9 100644 --- a/include/dmlist.h +++ b/include/dmlist.h @@ -143,6 +143,18 @@ DMOD_BUILTIN_API( dmlist, 1.0, void, _clear, ( dmlist_context_t* ctx ) ); */ DMOD_BUILTIN_API( dmlist, 1.0, void*, _find, ( dmlist_context_t* ctx, const void* data, dmlist_compare_func_t compare_func ) ); +/** + * @brief Find the next occurrence of an element in the list. + * + * @param ctx Pointer to the list context. + * @param last_found Pointer to the last found data (NULL to start from beginning). + * @param data Pointer to the data to find. + * @param compare_func Comparison function to use. + * + * @return Pointer to the found data, or NULL if not found. + */ +DMOD_BUILTIN_API( dmlist, 1.0, void*, _find_next, ( dmlist_context_t* ctx, const void* last_found, const void* data, dmlist_compare_func_t compare_func ) ); + /** * @brief Remove an element from the list. * diff --git a/src/dmlist.c b/src/dmlist.c index 6a135cb..7c10853 100644 --- a/src/dmlist.c +++ b/src/dmlist.c @@ -301,6 +301,44 @@ DMOD_INPUT_API_DECLARATION( dmlist, 1.0, void*, _find, ( dmlist_context_t* ctx, return NULL; } +DMOD_INPUT_API_DECLARATION( dmlist, 1.0, void*, _find_next, ( dmlist_context_t* ctx, const void* last_found, const void* data, dmlist_compare_func_t compare_func ) ) +{ + if( ctx == NULL || compare_func == NULL ) + { + return NULL; + } + + dmlist_node_t* current = ctx->head; + + // If last_found is not NULL, find the node containing it and start from the next one + if( last_found != NULL ) + { + // Find the node containing last_found + while( current != NULL ) + { + if( current->data == last_found ) + { + // Start from the next node + current = current->next; + break; + } + current = current->next; + } + } + + // Search for the data starting from current + while( current != NULL ) + { + if( compare_func( current->data, data ) == 0 ) + { + return current->data; + } + current = current->next; + } + + return NULL; +} + DMOD_INPUT_API_DECLARATION( dmlist, 1.0, bool, _remove, ( dmlist_context_t* ctx, const void* data, dmlist_compare_func_t compare_func ) ) { if( ctx == NULL || compare_func == NULL ) diff --git a/tests/test_simple.c b/tests/test_simple.c index 1eca0bf..bbbf8c8 100644 --- a/tests/test_simple.c +++ b/tests/test_simple.c @@ -97,7 +97,66 @@ int main(void) { } TEST_PASS(); - // Test 10: Destroy + // Test 10: Find and find_next + printf("Find and Find Next: "); + // Add values with duplicates + int val4 = 10; + int val5 = 20; + int val6 = 10; + int val7 = 30; + int val8 = 10; + dmlist_push_back(list, &val4); + dmlist_push_back(list, &val5); + dmlist_push_back(list, &val6); + dmlist_push_back(list, &val7); + dmlist_push_back(list, &val8); + + // Comparison function for integers + int compare_int(const void* a, const void* b) { + const int* ia = (const int*)a; + const int* ib = (const int*)b; + return *ia - *ib; + } + + // Find first occurrence of 10 + int search_val = 10; + int* found1 = (int*)dmlist_find_next(list, NULL, &search_val, compare_int); + if(found1 == NULL || *found1 != 10 || found1 != &val4) { + TEST_FAIL(); + return 1; + } + + // Find second occurrence of 10 + int* found2 = (int*)dmlist_find_next(list, found1, &search_val, compare_int); + if(found2 == NULL || *found2 != 10 || found2 != &val6) { + TEST_FAIL(); + return 1; + } + + // Find third occurrence of 10 + int* found3 = (int*)dmlist_find_next(list, found2, &search_val, compare_int); + if(found3 == NULL || *found3 != 10 || found3 != &val8) { + TEST_FAIL(); + return 1; + } + + // Try to find fourth occurrence (should return NULL) + int* found4 = (int*)dmlist_find_next(list, found3, &search_val, compare_int); + if(found4 != NULL) { + TEST_FAIL(); + return 1; + } + + // Test with NULL last_found should behave like find + int* found_from_start = (int*)dmlist_find_next(list, NULL, &search_val, compare_int); + if(found_from_start == NULL || found_from_start != &val4) { + TEST_FAIL(); + return 1; + } + + TEST_PASS(); + + // Test 11: Destroy printf("Destroy: "); dmlist_destroy(list); TEST_PASS(); From 036fd794cd6978cb4bb923b2721d1a34e1b16d2a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 14:17:01 +0000 Subject: [PATCH 3/4] Address code review feedback: move compare function to file scope and validate last_found Co-authored-by: JohnAmadis <17320783+JohnAmadis@users.noreply.github.com> --- src/dmlist.c | 8 ++++++++ tests/test_simple.c | 22 +++++++++++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/dmlist.c b/src/dmlist.c index 7c10853..65b64b6 100644 --- a/src/dmlist.c +++ b/src/dmlist.c @@ -313,6 +313,7 @@ DMOD_INPUT_API_DECLARATION( dmlist, 1.0, void*, _find_next, ( dmlist_context_t* // If last_found is not NULL, find the node containing it and start from the next one if( last_found != NULL ) { + bool found_last = false; // Find the node containing last_found while( current != NULL ) { @@ -320,10 +321,17 @@ DMOD_INPUT_API_DECLARATION( dmlist, 1.0, void*, _find_next, ( dmlist_context_t* { // Start from the next node current = current->next; + found_last = true; break; } current = current->next; } + + // If last_found was not in the list, return NULL + if( !found_last ) + { + return NULL; + } } // Search for the data starting from current diff --git a/tests/test_simple.c b/tests/test_simple.c index bbbf8c8..ff37e45 100644 --- a/tests/test_simple.c +++ b/tests/test_simple.c @@ -5,6 +5,13 @@ #define TEST_PASS() printf("PASS\n") #define TEST_FAIL() printf("FAIL\n") +// Comparison function for integers +static int compare_int(const void* a, const void* b) { + const int* ia = (const int*)a; + const int* ib = (const int*)b; + return *ia - *ib; +} + int main(void) { printf("=== Simple DMLIST Test ===\n"); @@ -111,13 +118,6 @@ int main(void) { dmlist_push_back(list, &val7); dmlist_push_back(list, &val8); - // Comparison function for integers - int compare_int(const void* a, const void* b) { - const int* ia = (const int*)a; - const int* ib = (const int*)b; - return *ia - *ib; - } - // Find first occurrence of 10 int search_val = 10; int* found1 = (int*)dmlist_find_next(list, NULL, &search_val, compare_int); @@ -154,6 +154,14 @@ int main(void) { return 1; } + // Test with invalid last_found (not in list) should return NULL + int external_val = 99; + int* found_invalid = (int*)dmlist_find_next(list, &external_val, &search_val, compare_int); + if(found_invalid != NULL) { + TEST_FAIL(); + return 1; + } + TEST_PASS(); // Test 11: Destroy From ac66e8cdb3ecd27e2e3531fcb53e35c076799ec3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Dec 2025 14:24:16 +0000 Subject: [PATCH 4/4] Refactor dmlist_find to be a wrapper for dmlist_find_next Co-authored-by: JohnAmadis <17320783+JohnAmadis@users.noreply.github.com> --- src/dmlist.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/dmlist.c b/src/dmlist.c index 65b64b6..5f3b996 100644 --- a/src/dmlist.c +++ b/src/dmlist.c @@ -283,22 +283,7 @@ DMOD_INPUT_API_DECLARATION( dmlist, 1.0, void, _clear, ( dmlist_context_t* ctx ) DMOD_INPUT_API_DECLARATION( dmlist, 1.0, void*, _find, ( dmlist_context_t* ctx, const void* data, dmlist_compare_func_t compare_func ) ) { - if( ctx == NULL || compare_func == NULL ) - { - return NULL; - } - - dmlist_node_t* current = ctx->head; - while( current != NULL ) - { - if( compare_func( current->data, data ) == 0 ) - { - return current->data; - } - current = current->next; - } - - return NULL; + return dmlist_find_next( ctx, NULL, data, compare_func ); } DMOD_INPUT_API_DECLARATION( dmlist, 1.0, void*, _find_next, ( dmlist_context_t* ctx, const void* last_found, const void* data, dmlist_compare_func_t compare_func ) )