diff --git a/src/util/list.c b/src/util/list.c index 4bd8791..1fe3fbc 100644 --- a/src/util/list.c +++ b/src/util/list.c @@ -6,7 +6,7 @@ Description: Generic list https://gist.github.com/pseudomuto/6334796#file-list-c Accessed: April 9, 2019 - Authors: David Muto, Modified by Michael E. Tryby + Authors: David Muto, Michael Tryby Copyright: see AUTHORS License: see LICENSE Last Updated: 04/09/2019 @@ -27,6 +27,21 @@ #include "list.h" +typedef struct list_node_s { + void *data; + struct list_node_s *next; +} list_node_t; + + +typedef struct list_s { + int logicalLength; + size_t elementSize; + list_node_t *head; + list_node_t *tail; + freeFunction freeFn; +} list_t; + + list_t *create_list(size_t elementSize, freeFunction freeFn) { list_t *list; @@ -59,7 +74,7 @@ void delete_list(list_t *list) void prepend_list(list_t *list, void *element) { - list_node_t *node = malloc(sizeof(list_node_t)); + list_node_t *node = malloc(sizeof(list_node_t)); node->data = malloc(list->elementSize); memcpy(node->data, element, list->elementSize); @@ -99,7 +114,7 @@ void for_each_list(list_t *list, listIterator iterator) list_node_t *node = list->head; bool result = true; while(node != NULL && result) { - result = iterator(node->data); + result = iterator(node); node = node->next; } } @@ -127,7 +142,7 @@ void *head_list(list_t *list, bool removeFromList) } // Now element points to data formerly pointed to by node. Caller // is responsible for freeing both pointer to data and data. - return element; + return element; } void *tail_list(list_t *list) @@ -144,10 +159,36 @@ void *tail_list(list_t *list) // Pointer to element data gets returned. Caller is responsible // for freeing pointer to data. - return element; + return element; } int size_list(list_t *list) { return list->logicalLength; } + +void *get_data(list_node_t *lnode) +{ + return lnode->data; +} + + +// +// Iterator operations +// http://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)Iterators.html +// Accessed on April 11, 2019 +// +list_node_t *first_list(list_t *list) +{ + return list->head; +} + +bool done_list(list_node_t *lnode) +{ + return lnode != NULL; +} + +list_node_t *next_list(list_node_t *lnode) +{ + return lnode->next; +} diff --git a/src/util/list.h b/src/util/list.h index 7ac11b6..fe6ffc7 100644 --- a/src/util/list.h +++ b/src/util/list.h @@ -6,7 +6,7 @@ Description: Generic list https://gist.github.com/pseudomuto/6334796#file-list-h Accessed: April 9, 2019 - Authors: David Muto, Modified by Michael E. Tryby + Authors: David Muto, Michael Tryby Copyright: see AUTHORS License: see LICENSE Last Updated: 04/09/2019 @@ -23,24 +23,13 @@ extern "C" { #endif -// a common function used to free malloc'd objects + +// Forward declarations +typedef struct list_node_s list_node_t; +typedef struct list_s list_t; + typedef void(*freeFunction)(void *); -typedef bool(*listIterator)(void *); - - -typedef struct list_node_s { - void *data; - struct list_node_s *next; -} list_node_t; - - -typedef struct { - int logicalLength; - size_t elementSize; - list_node_t *head; - list_node_t *tail; - freeFunction freeFn; -} list_t; +typedef bool(*listIterator)(list_node_t *); /** @@ -70,6 +59,12 @@ void append_list(list_t *list, void *element); */ int size_list(list_t *list); +/** +@brief Returns pointer to list node's data. +*/ +void *get_data(list_node_t *lnode); + + /** @brief Calls the supplied iterator function with the data element of each node (iterates over the list). @@ -87,6 +82,22 @@ void *head_list(list_t *list, bool removeFromList); void *tail_list(list_t *list); +/** +@brief Returns list head node. +*/ +list_node_t *first_list(list_t *list); + +/** +@brief Returns true if end of list false otherwise. +*/ +bool done_list(list_node_t *lnode); + +/** +@brief Returns next node in the list. +*/ +list_node_t *next_list(list_node_t *lnode); + + #if defined(__cplusplus) } #endif diff --git a/tests/util/test_list.cpp b/tests/util/test_list.cpp index 34f27e7..aee21fc 100644 --- a/tests/util/test_list.cpp +++ b/tests/util/test_list.cpp @@ -28,24 +28,16 @@ boost::test_tools::predicate_result check_string(std::string test, std::string r return false; } +int *get_int_data(list_node_t *lnode) { + return (int *)get_data(lnode); +} -bool iterate_int(void *data) +bool iterate_int(list_node_t *lnode) { - printf("Found value: %d\n", *(int *)data); + printf("Found value: %d\n", *get_int_data(lnode)); return true; } -bool iterate_string(void *data) -{ - char *string = *(char **)data; - printf("Found string value: %s\n", string); - return true; -} - -void free_string(void *data) -{ - free(*(char **)data); -} BOOST_AUTO_TEST_SUITE(test_list) @@ -76,6 +68,23 @@ BOOST_AUTO_TEST_CASE(test_int_list){ delete_list(list); } + +inline char *get_string_data(list_node_t *lnode) +{ + return *(char **)get_data(lnode); +} + +bool iterate_string(list_node_t *lnode) +{ + printf("Found string value: %s\n", get_string_data(lnode)); + return true; +} + +void free_string(void *data) +{ + free(*(char **)data); +} + struct FixtureStrings{ FixtureStrings() { list = NULL; @@ -134,7 +143,7 @@ typedef struct test_data_s { char *name; } test_data_t; -test_data_t *create_test_data(int number, char *name){ +test_data_t *create_test_data(int number, const char *name){ test_data_t *data = (test_data_t *)malloc(sizeof(test_data_t)); data->num = number; @@ -156,9 +165,14 @@ void delete_test_data(void *data) { free(test_data); } -bool iterate_test_data(void *data) +inline test_data_t *get_test_data(list_node_t *lnode) { - test_data_t *test_data = *(test_data_t **)data; + return *(test_data_t **)get_data(lnode); +} + +bool iterate_test_data(list_node_t *lnode) +{ + test_data_t *test_data = get_test_data(lnode); printf("Found number: %i name: %s\n", test_data->num, test_data->name); return true; @@ -186,10 +200,10 @@ BOOST_AUTO_TEST_CASE(test_struct_list){ //for_each_list(list, iterate_test_data); - // Expose list abstraction and loop over it list_node_t *lnode; - for (lnode = list->head; lnode != NULL; lnode = lnode->next) { - test_data_t *test_data = *(test_data_t **)lnode->data; + // Iterate over list while maintaining containment of abstraction + for (lnode = first_list(list); done_list(lnode); lnode = next_list(lnode)) { + test_data_t *test_data = get_test_data(lnode); printf("Found number: %i name: %s\n", test_data->num, test_data->name); }