From f60b98472923669d0e98bd7de5b138f7a0402105 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Wed, 3 Apr 2019 23:34:39 +0200 Subject: [PATCH] added dlist --- CMakeLists.txt | 2 + lib/webfuse/core/dlist.c | 87 ++++++++++++++++++++++++++++++++++++++++ lib/webfuse/core/dlist.h | 59 +++++++++++++++++++++++++++ test/test_dlist.cc | 49 ++++++++++++++++++++++ 4 files changed, 197 insertions(+) create mode 100644 lib/webfuse/core/dlist.c create mode 100644 lib/webfuse/core/dlist.h create mode 100644 test/test_dlist.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index bb499ed..d0d8488 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ set(EXTRA_CFLAGS # libwebfuse-core add_library(webfuse-core STATIC + lib/webfuse/core/dlist.c lib/webfuse/core/message.c lib/webfuse/core/message_queue.c lib/webfuse/core/status.c @@ -273,6 +274,7 @@ add_executable(alltests test/msleep.cc test/mock_authenticator.cc test/test_container_of.cc + test/test_dlist.cc test/test_response_parser.cc test/test_server.cc test/test_timepoint.cc diff --git a/lib/webfuse/core/dlist.c b/lib/webfuse/core/dlist.c new file mode 100644 index 0000000..74b9c31 --- /dev/null +++ b/lib/webfuse/core/dlist.c @@ -0,0 +1,87 @@ +#include "webfuse/core/dlist.h" +#include "webfuse/core/util.h" +#include + +void wf_dlist_init( + struct wf_dlist * list) +{ + list->first = NULL; +} + +static void wf_dlist_item_cleanup_default( + struct wf_dlist_item * WF_UNUSED_PARAM(item), + void * WF_UNUSED_PARAM(user_data)) +{ + // empty +} + +void wf_dlist_cleanup( + struct wf_dlist * list, + wf_dlist_item_cleanup_fn * cleanup, + void * user_data) +{ + wf_dlist_item_cleanup_fn * effective_cleanup = (NULL != cleanup) ? cleanup : &wf_dlist_item_cleanup_default; + struct wf_dlist_item * item = list->first; + + while (NULL != item) + { + struct wf_dlist_item * next = item->next; + effective_cleanup(item, user_data); + item = next; + } + + list->first = NULL; +} + +void wf_dlist_prepend( + struct wf_dlist * list, + struct wf_dlist_item * item) +{ + if (NULL != list->first) + { + list->first->prev = item; + } + + item->prev = NULL; + item->next = list->first; + list->first = item; +} + +void wf_dlist_remove( + struct wf_dlist * list, + struct wf_dlist_item * item) +{ + if (NULL != item->prev) + { + item->prev->next = item->next; + } + + if (NULL != item->next) + { + item->next->prev = item->prev; + } + + if (list->first == item) + { + list->first = item->next; + } +} + +struct wf_dlist_item * wf_dlist_find_first( + struct wf_dlist * list, + wf_dlist_item_predicate_fn * predicate, + void * user_data) +{ + struct wf_dlist_item * item = list->first; + + while (NULL != item) + { + if (predicate(item, user_data)) + { + break; + } + item = item->next; + } + + return item; +} diff --git a/lib/webfuse/core/dlist.h b/lib/webfuse/core/dlist.h new file mode 100644 index 0000000..8866bd8 --- /dev/null +++ b/lib/webfuse/core/dlist.h @@ -0,0 +1,59 @@ +#ifndef WF_DLIST_H +#define WF_DLIST_H + +#ifndef __cplusplus +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wf_dlist_item +{ + struct wf_dlist_item * prev; + struct wf_dlist_item * next; +}; + +struct wf_dlist +{ + struct wf_dlist_item * first; +}; + +typedef void wf_dlist_item_cleanup_fn( + struct wf_dlist_item * item, + void * user_data); + +typedef bool wf_dlist_item_predicate_fn( + struct wf_dlist_item * item, + void * user_data); + + +extern void wf_dlist_init( + struct wf_dlist * list); + +extern void wf_dlist_cleanup( + struct wf_dlist * list, + wf_dlist_item_cleanup_fn * cleanup, + void * user_data); + +extern void wf_dlist_prepend( + struct wf_dlist * list, + struct wf_dlist_item * item); + +extern void wf_dlist_remove( + struct wf_dlist * list, + struct wf_dlist_item * item); + +extern struct wf_dlist_item * wf_dlist_find_first( + struct wf_dlist * list, + wf_dlist_item_predicate_fn * predicate, + void * user_data); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/test_dlist.cc b/test/test_dlist.cc new file mode 100644 index 0000000..031be1d --- /dev/null +++ b/test/test_dlist.cc @@ -0,0 +1,49 @@ +#include +#include "webfuse/core/dlist.h" +#include "webfuse/core/container_of.h" + +namespace +{ + struct Item + { + wf_dlist_item item; + char value; + }; +} + +TEST(DList, prepend) +{ + struct wf_dlist list; + wf_dlist_init(&list); + ASSERT_EQ(nullptr, list.first); + + Item a; + a.value = 'a'; + wf_dlist_prepend(&list, &a.item); + ASSERT_EQ(&a.item, list.first); + ASSERT_EQ(nullptr, a.item.next); + ASSERT_EQ(nullptr, a.item.prev); + + Item b; + b.value = 'b'; + wf_dlist_prepend(&list, &b.item); + ASSERT_EQ(&b.item, list.first); + ASSERT_EQ(&a.item, b.item.next); + ASSERT_EQ(nullptr, b.item.prev); + ASSERT_EQ(nullptr, a.item.next); + ASSERT_EQ(&b.item, a.item.prev); + + Item c; + c.value = 'c'; + wf_dlist_prepend(&list, &c.item); + ASSERT_EQ(&c.item, list.first); + ASSERT_EQ(&b.item, c.item.next); + ASSERT_EQ(nullptr, c.item.prev); + ASSERT_EQ(&a.item, b.item.next); + ASSERT_EQ(&c.item, b.item.prev); + ASSERT_EQ(nullptr, a.item.next); + ASSERT_EQ(&b.item, a.item.prev); + + wf_dlist_cleanup(&list, nullptr, nullptr); + ASSERT_EQ(nullptr, list.first); +} \ No newline at end of file