From ae8305f32494dbef3d972e84eb85dc89d16aac61 Mon Sep 17 00:00:00 2001 From: Mateo de Mayo Date: Wed, 20 Jul 2022 11:39:29 -0300 Subject: [PATCH] u/deque: Add generic wrapper for std::deque --- src/xrt/auxiliary/util/CMakeLists.txt | 2 + src/xrt/auxiliary/util/u_deque.cpp | 61 +++++++++++++++++++++++++++ src/xrt/auxiliary/util/u_deque.h | 35 +++++++++++++++ tests/CMakeLists.txt | 1 + tests/tests_deque.cpp | 59 ++++++++++++++++++++++++++ 5 files changed, 158 insertions(+) create mode 100644 src/xrt/auxiliary/util/u_deque.cpp create mode 100644 src/xrt/auxiliary/util/u_deque.h create mode 100644 tests/tests_deque.cpp diff --git a/src/xrt/auxiliary/util/CMakeLists.txt b/src/xrt/auxiliary/util/CMakeLists.txt index 1c2ed3670..7503e2930 100644 --- a/src/xrt/auxiliary/util/CMakeLists.txt +++ b/src/xrt/auxiliary/util/CMakeLists.txt @@ -17,6 +17,8 @@ add_library( u_builders.h u_debug.c u_debug.h + u_deque.cpp + u_deque.h u_device.c u_device.h u_distortion.c diff --git a/src/xrt/auxiliary/util/u_deque.cpp b/src/xrt/auxiliary/util/u_deque.cpp new file mode 100644 index 000000000..28baa49fe --- /dev/null +++ b/src/xrt/auxiliary/util/u_deque.cpp @@ -0,0 +1,61 @@ +// Copyright 2022, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Expose std::deque to C + * @author Mateo de Mayo + * @ingroup aux_util + */ + +#include "u_deque.h" +#include "util/u_time.h" +#include + +using std::deque; + +#define U_DEQUE_IMPLEMENTATION(TYPE) \ + u_deque_##TYPE u_deque_##TYPE##_create() \ + { \ + u_deque_##TYPE ud{new deque}; \ + return ud; \ + } \ + \ + void u_deque_##TYPE##_push_back(u_deque_##TYPE ud, TYPE e) \ + { \ + deque *d = static_cast *>(ud.ptr); \ + d->push_back(e); \ + } \ + \ + bool u_deque_##TYPE##_pop_front(u_deque_##TYPE ud, TYPE *e) \ + { \ + deque *d = static_cast *>(ud.ptr); \ + bool pop = !d->empty(); \ + if (pop) { \ + *e = d->front(); \ + d->erase(d->begin()); \ + } \ + return pop; \ + } \ + \ + TYPE u_deque_##TYPE##_at(u_deque_##TYPE ud, size_t i) \ + { \ + deque *d = static_cast *>(ud.ptr); \ + return d->at(i); \ + } \ + \ + size_t u_deque_##TYPE##_size(u_deque_##TYPE ud) \ + { \ + deque *d = static_cast *>(ud.ptr); \ + return d->size(); \ + } \ + \ + void u_deque_##TYPE##_destroy(u_deque_##TYPE *ud) \ + { \ + deque *d = static_cast *>(ud->ptr); \ + delete d; \ + ud->ptr = nullptr; \ + } + +extern "C" { +U_DEQUE_IMPLEMENTATION(timepoint_ns) +} diff --git a/src/xrt/auxiliary/util/u_deque.h b/src/xrt/auxiliary/util/u_deque.h new file mode 100644 index 000000000..44295413b --- /dev/null +++ b/src/xrt/auxiliary/util/u_deque.h @@ -0,0 +1,35 @@ +// Copyright 2022, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Expose std::deque to C + * @author Mateo de Mayo + * @ingroup aux_util + */ + +#pragma once + +#include "util/u_time.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define U_DEQUE_DECLARATION(TYPE) \ + struct u_deque_##TYPE \ + { \ + void *ptr; \ + }; \ + struct u_deque_##TYPE u_deque_##TYPE##_create(); \ + void u_deque_##TYPE##_push_back(struct u_deque_##TYPE ud, TYPE e); \ + bool u_deque_##TYPE##_pop_front(struct u_deque_##TYPE ud, TYPE *e); \ + TYPE u_deque_##TYPE##_at(struct u_deque_##TYPE ud, size_t i); \ + size_t u_deque_##TYPE##_size(struct u_deque_##TYPE wrap); \ + void u_deque_##TYPE##_destroy(struct u_deque_##TYPE *ud); + +U_DEQUE_DECLARATION(timepoint_ns) + +#ifdef __cplusplus +} +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7607270c4..848725659 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -11,6 +11,7 @@ endif() set(tests tests_cxx_wrappers + tests_deque tests_generic_callbacks tests_history_buf tests_id_ringbuffer diff --git a/tests/tests_deque.cpp b/tests/tests_deque.cpp new file mode 100644 index 000000000..8372dcf08 --- /dev/null +++ b/tests/tests_deque.cpp @@ -0,0 +1,59 @@ +// Copyright 2022, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Test u_deque C interface. + * @author Mateo de Mayo + */ + +#include "catch/catch.hpp" +#include "util/u_deque.h" + +TEST_CASE("u_deque") +{ + SECTION("Test interface generated from macros") + { + struct u_deque_timepoint_ns dt = u_deque_timepoint_ns_create(); + CHECK(dt.ptr != NULL); + + constexpr timepoint_ns A = 11111111; + constexpr timepoint_ns B = 22222222; + constexpr timepoint_ns C = 33333333; + timepoint_ns elem = 0; + + CHECK(!u_deque_timepoint_ns_pop_front(dt, &elem)); + CHECK(elem == 0); + + u_deque_timepoint_ns_push_back(dt, C); + u_deque_timepoint_ns_push_back(dt, A); + + CHECK(u_deque_timepoint_ns_pop_front(dt, &elem)); + CHECK(elem == C); + CHECK(u_deque_timepoint_ns_size(dt) == 1); + + u_deque_timepoint_ns_push_back(dt, B); + u_deque_timepoint_ns_push_back(dt, C); + + timepoint_ns a = u_deque_timepoint_ns_at(dt, 0); + timepoint_ns b = u_deque_timepoint_ns_at(dt, 1); + timepoint_ns c = u_deque_timepoint_ns_at(dt, 2); + + CHECK(a == A); + CHECK(b == B); + CHECK(c == C); + + CHECK(u_deque_timepoint_ns_size(dt) == 3); + + CHECK(u_deque_timepoint_ns_pop_front(dt, &elem)); + CHECK(elem == A); + CHECK(u_deque_timepoint_ns_pop_front(dt, &elem)); + CHECK(elem == B); + CHECK(u_deque_timepoint_ns_pop_front(dt, &elem)); + CHECK(elem == C); + + CHECK(u_deque_timepoint_ns_size(dt) == 0); + + u_deque_timepoint_ns_destroy(&dt); + CHECK(dt.ptr == NULL); + } +}