Initial commit list
generic linked list
This commit is contained in:
124
src/util/list.c
Normal file
124
src/util/list.c
Normal file
@@ -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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
59
src/util/list.h
Normal file
59
src/util/list.h
Normal file
@@ -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 <stdbool.h>
|
||||
|
||||
#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 */
|
||||
@@ -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})
|
||||
|
||||
74
tests/util/test_list.cpp
Normal file
74
tests/util/test_list.cpp
Normal file
@@ -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 <boost/test/unit_test.hpp>
|
||||
|
||||
#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()
|
||||
Reference in New Issue
Block a user