From 30f0def02adb98ac1003e30a53417cc6ce10d596 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Tue, 9 Apr 2019 14:26:33 -0400 Subject: [PATCH] Initial commit list generic linked list --- README.md | 2 +- src/util/list.c | 124 ++++++++++++++++++++++++++++++++++++++ src/util/list.h | 59 ++++++++++++++++++ tests/util/CMakeLists.txt | 8 ++- tests/util/test_list.cpp | 74 +++++++++++++++++++++++ 5 files changed, 265 insertions(+), 2 deletions(-) create mode 100644 src/util/list.c create mode 100644 src/util/list.h create mode 100644 tests/util/test_list.cpp diff --git a/README.md b/README.md index 5e5949e..56dc1fa 100755 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ EPANET {#epanet-readme} ## For EPANET-related questions and discussion -For community discussion, FAQ, and roadmapping of the project, go to the [Community Forum](http://community.wateranalytics.org/category/epanet). +For community discussion, FAQ, and roadmapping of the project, go to the [Community Forum](http://community.wateranalytics.org/category/epanet). ## What is on this Repository? The EPANET Library is a pressurized pipe network hydraulic and water quality analysis toolkit written in C. If you are interested in using/extending EPANET for academic, personal, or commercial use, then you've come to the right place. diff --git a/src/util/list.c b/src/util/list.c new file mode 100644 index 0000000..ad36c65 --- /dev/null +++ b/src/util/list.c @@ -0,0 +1,124 @@ +// +// Author: David Muto +// https://gist.github.com/pseudomuto/6334796#file-list-c +// +// Modified by: +// Michael E. Tryby +// US EPA ORD +// +// Accessed on: April 9, 2019 +// + + +#include +#include +#include + +#include "list.h" + + +list_t *create_list(int elementSize, freeFunction freeFn) +{ + list_t *list; + list = (list_t *)calloc(1, sizeof(list_t)); + + assert(elementSize > 0); + list->logicalLength = 0; + list->elementSize = elementSize; + list->head = list->tail = NULL; + list->freeFn = freeFn; + return list; +} + +void delete_list(list_t *list) +{ + listNode *current; + while(list->head != NULL) { + current = list->head; + list->head = current->next; + + if (list->freeFn) { + list->freeFn(current->data); + } + + free(current->data); + free(current); + } + + free(list); +} + +void prepend_list(list_t *list, void *element) +{ + listNode *node = malloc(sizeof(listNode)); + node->data = malloc(list->elementSize); + memcpy(node->data, element, list->elementSize); + + node->next = list->head; + list->head = node; + + // first node? + if(!list->tail) { + list->tail = list->head; + } + + list->logicalLength++; +} + +void append_list(list_t *list, void *element) +{ + listNode *node = malloc(sizeof(listNode)); + node->data = malloc(list->elementSize); + node->next = NULL; + + memcpy(node->data, element, list->elementSize); + + if(list->logicalLength == 0) { + list->head = list->tail = node; + } else { + list->tail->next = node; + list->tail = node; + } + + list->logicalLength++; +} + +void for_each_list(list_t *list, listIterator iterator) +{ + assert(iterator != NULL); + + listNode *node = list->head; + bool result = true; + while(node != NULL && result) { + result = iterator(node->data); + node = node->next; + } +} + +void head_list(list_t *list, void *element, bool removeFromList) +{ + assert(list->head != NULL); + + listNode *node = list->head; + memcpy(element, node->data, list->elementSize); + + if(removeFromList) { + list->head = node->next; + list->logicalLength--; + + free(node->data); + free(node); + } +} + +void tail_list(list_t *list, void *element) +{ + assert(list->tail != NULL); + listNode *node = list->tail; + memcpy(element, node->data, list->elementSize); +} + +int size_list(list_t *list) +{ + return list->logicalLength; +} diff --git a/src/util/list.h b/src/util/list.h new file mode 100644 index 0000000..f19b7d4 --- /dev/null +++ b/src/util/list.h @@ -0,0 +1,59 @@ +// +// Author: David Muto +// https://gist.github.com/pseudomuto/6334796#file-list-h +// +// Modified by: +// Michael E. Tryby +// US EPA ORD +// +// Accessed on: April 9, 2019 +// + + +#ifndef LIST_H +#define LIST_H + + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +// a common function used to free malloc'd objects +typedef void(*freeFunction)(void *); +typedef bool (*listIterator)(void *); + + +typedef struct _listNode { + void *data; + struct _listNode *next; +} listNode; + + +typedef struct { + int logicalLength; + int elementSize; + listNode *head; + listNode *tail; + freeFunction freeFn; +} list_t; + + +list_t *create_list(int elementSize, freeFunction freeFn); +void delete_list(list_t *list); + +void prepend_list(list_t *list, void *element); +void append_list(list_t *list, void *element); +int size_list(list_t *list); + +void for_each_list(list_t *list, listIterator iterator); +void head_list(list_t *list, void *element, bool removeFromList); +void tail_list(list_t *list, void *element); + + +#if defined(__cplusplus) +} +#endif + +#endif /* LIST_H */ diff --git a/tests/util/CMakeLists.txt b/tests/util/CMakeLists.txt index 0bd4a43..59463e9 100644 --- a/tests/util/CMakeLists.txt +++ b/tests/util/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -add_executable(test_errormanager ./test_errormanager.cpp +add_executable(test_errormanager ./test_errormanager.cpp ../../src/util/errormanager.c) target_include_directories(test_errormanager PUBLIC ../../src/) target_link_libraries(test_errormanager ${Boost_LIBRARIES}) @@ -18,3 +18,9 @@ add_executable(test_filemanager ./test_filemanager.cpp ../../src/util/cstr_helper.c) target_include_directories(test_filemanager PUBLIC ../../src/) target_link_libraries(test_filemanager ${Boost_LIBRARIES}) + + +add_executable(test_list ./test_list.cpp + ../../src/util/list.c) +target_include_directories(test_list PUBLIC ../../src/) +target_link_libraries(test_list ${Boost_LIBRARIES}) diff --git a/tests/util/test_list.cpp b/tests/util/test_list.cpp new file mode 100644 index 0000000..346be50 --- /dev/null +++ b/tests/util/test_list.cpp @@ -0,0 +1,74 @@ +/* + ****************************************************************************** + Project: OWA EPANET + Version: 2.2 + Module: util/test_list.cpp + Description: Tests for util/list.c + Authors: see AUTHORS + Copyright: see AUTHORS + License: see LICENSE + Last Updated: 04/09/2019 + ****************************************************************************** +*/ + +#define BOOST_TEST_MODULE list + +#include + +#include "util/list.h" + + +bool iterate_int(void *data) +{ + printf("Found value: %d\n", *(int *)data); + return true; +} + + +BOOST_AUTO_TEST_SUITE(test_list) + + +BOOST_AUTO_TEST_CASE(test_create_delete) { + + list_t *list; + list = create_list(sizeof(int), NULL); + + delete_list(list); +} + + +struct Fixture{ + Fixture() { + list = NULL; + + list = create_list(sizeof(int), NULL); + } + ~Fixture() { + delete_list(list); + } + list_t *list; +}; + + +BOOST_FIXTURE_TEST_CASE(test_list_append, Fixture){ + +int i, numbers = 10; + + for(i = 1; i <= numbers; i++) { + append_list(list, &i); + } + BOOST_CHECK(size_list(list) == 10); +} + +BOOST_FIXTURE_TEST_CASE(test_list_foreach, Fixture) { + + int i, numbers = 10; + + for (i = 1; i <= numbers; i++) { + append_list(list, &i); + } + + for_each_list(list, iterate_int); +} + +BOOST_AUTO_TEST_SUITE_END()