From 82f02896c92bf4c552bd511e7a1679df9b8b36b1 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sun, 17 Mar 2024 13:24:16 -0500 Subject: [PATCH] [turbine] Cleanup type safety code for application data --- .../turbine/include/turbine/context.hpp | 54 ++++++++++++++++--- src/olympic/turbine/src/gba/context.cpp | 14 ++--- src/olympic/turbine/src/gba/context.hpp | 2 +- src/olympic/turbine/src/glfw/context.cpp | 14 ++--- src/olympic/turbine/src/glfw/context.hpp | 2 +- 5 files changed, 54 insertions(+), 32 deletions(-) diff --git a/src/olympic/turbine/include/turbine/context.hpp b/src/olympic/turbine/include/turbine/context.hpp index 14a6dc2e..05f39b76 100644 --- a/src/olympic/turbine/include/turbine/context.hpp +++ b/src/olympic/turbine/include/turbine/context.hpp @@ -39,20 +39,57 @@ inline ox::FileSystem *rom(Context &ctx) noexcept { struct WrapBase { virtual ~WrapBase() = default; + virtual WrapBase *copyTo(ox::Span s) noexcept = 0; + virtual operator bool() const noexcept = 0; }; template struct Wrap: public WrapBase { T *data{}; + Wrap(T *pData) noexcept: data(pData) { + } + WrapBase *copyTo(ox::Span s) noexcept override { + oxAssert(s.size() >= sizeof(Wrap), "too small buffer"); + return new(s.data()) Wrap{data}; + } + operator bool() const noexcept override { + return data != nullptr; + } }; -void setApplicationDataRaw(Context &ctx, void *applicationData) noexcept; +class WrapPtr { + private: + WrapBase *m_wrapPtr{}; + ox::Array m_wrapData; + public: + template + inline WrapPtr &operator=(T *ptr) noexcept { + m_wrapPtr = new(m_wrapData.data()) Wrap(ptr); + return *this; + } + inline WrapPtr &operator=(WrapBase &ptr) noexcept { + if (ptr) { + m_wrapPtr = ptr.copyTo(m_wrapData); + } else { + m_wrapPtr = nullptr; + } + return *this; + } + inline operator bool() const noexcept { + return m_wrapPtr && *m_wrapPtr; + } + [[nodiscard]] + inline WrapBase *getWrapBase() const noexcept { + return m_wrapPtr; + } +}; + +void setApplicationDataRaw(Context &ctx, WrapBase &applicationData) noexcept; template void setApplicationData(Context &ctx, T *applicationData) noexcept { - Wrap w; - w.data = applicationData; - setApplicationDataRaw(ctx, &w); + Wrap w(applicationData); + setApplicationDataRaw(ctx, w); } [[nodiscard]] @@ -61,13 +98,14 @@ WrapBase *applicationDataRaw(Context &ctx) noexcept; template [[nodiscard]] T *applicationData(Context &ctx) noexcept { + auto const raw = applicationDataRaw(ctx); #ifdef OX_BARE_METAL - return static_cast*>(applicationDataRaw(ctx))->data; + auto const out = static_cast*>(raw); #else - auto const out = dynamic_cast*>(applicationDataRaw(ctx)); - oxAssert(out, "Cast failed - wrong type"); - return out->data; + auto const out = dynamic_cast*>(raw); #endif + oxAssert(out || !raw, "Cast failed - wrong type"); + return out->data; } void setKeyEventHandler(Context &ctx, KeyEventHandler h) noexcept; diff --git a/src/olympic/turbine/src/gba/context.cpp b/src/olympic/turbine/src/gba/context.cpp index 38c79d51..5b5f1330 100644 --- a/src/olympic/turbine/src/gba/context.cpp +++ b/src/olympic/turbine/src/gba/context.cpp @@ -18,20 +18,12 @@ keel::Context &keelCtx(Context &ctx) noexcept { return ctx.keelCtx; } -void setApplicationDataRaw(Context &ctx, void const*applicationData) noexcept { - if (applicationData) { - ctx.applicationData.emplace(); - memcpy(&ctx.applicationData.value(), applicationData, sizeof(Wrap)); - } else { - ctx.applicationData.reset(); - } +void setApplicationDataRaw(Context &ctx, WrapBase &applicationData) noexcept { + ctx.applicationData = applicationData; } WrapBase *applicationDataRaw(Context &ctx) noexcept { - if (!ctx.applicationData) { - return nullptr; - } - return std::bit_cast(&*ctx.applicationData); + return ctx.applicationData.getWrapBase(); } } diff --git a/src/olympic/turbine/src/gba/context.hpp b/src/olympic/turbine/src/gba/context.hpp index 1dda711e..02b05209 100644 --- a/src/olympic/turbine/src/gba/context.hpp +++ b/src/olympic/turbine/src/gba/context.hpp @@ -17,7 +17,7 @@ class Context { UpdateHandler updateHandler = [](Context&) -> int {return 0;}; keel::Context keelCtx; KeyEventHandler keyEventHandler = nullptr; - ox::Optional> applicationData; + WrapPtr applicationData; // GBA impl data ///////////////////////////////////////////////////////// bool running = true; diff --git a/src/olympic/turbine/src/glfw/context.cpp b/src/olympic/turbine/src/glfw/context.cpp index ea051dd9..30db3183 100644 --- a/src/olympic/turbine/src/glfw/context.cpp +++ b/src/olympic/turbine/src/glfw/context.cpp @@ -20,20 +20,12 @@ keel::Context &keelCtx(Context &ctx) noexcept { return ctx.keelCtx; } -void setApplicationDataRaw(Context &ctx, void *applicationData) noexcept { - if (applicationData) { - ctx.applicationData.emplace(); - memcpy(&ctx.applicationData.value(), applicationData, sizeof(Wrap)); - } else { - ctx.applicationData.reset(); - } +void setApplicationDataRaw(Context &ctx, WrapBase &applicationData) noexcept { + ctx.applicationData = applicationData; } WrapBase *applicationDataRaw(Context &ctx) noexcept { - if (!ctx.applicationData) { - return nullptr; - } - return std::bit_cast(&*ctx.applicationData); + return ctx.applicationData.getWrapBase(); } } diff --git a/src/olympic/turbine/src/glfw/context.hpp b/src/olympic/turbine/src/glfw/context.hpp index 19716242..21d420ec 100644 --- a/src/olympic/turbine/src/glfw/context.hpp +++ b/src/olympic/turbine/src/glfw/context.hpp @@ -16,7 +16,7 @@ class Context { UpdateHandler updateHandler = [](Context&) -> int {return 0;}; keel::Context keelCtx; KeyEventHandler keyEventHandler = nullptr; - ox::Optional> applicationData; + WrapPtr applicationData; // GLFW impl data //////////////////////////////////////////////////////// int uninterruptedRefreshes = 3;