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..5f3b996 100644 --- a/src/dmlist.c +++ b/src/dmlist.c @@ -282,6 +282,11 @@ 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 ) ) +{ + 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 ) ) { if( ctx == NULL || compare_func == NULL ) { @@ -289,6 +294,32 @@ DMOD_INPUT_API_DECLARATION( dmlist, 1.0, void*, _find, ( dmlist_context_t* ctx, } 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 ) + { + bool found_last = false; + // Find the node containing last_found + while( current != NULL ) + { + if( current->data == last_found ) + { + // 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 while( current != NULL ) { if( compare_func( current->data, data ) == 0 ) diff --git a/tests/test_simple.c b/tests/test_simple.c index 1eca0bf..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"); @@ -97,7 +104,67 @@ 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); + + // 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 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 printf("Destroy: "); dmlist_destroy(list); TEST_PASS();