diff options
| author | Dan Engelbrecht <[email protected]> | 2023-04-28 16:42:01 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-04-28 16:42:01 +0200 |
| commit | 6a44e6c95031179d29fca433851219eef402d71e (patch) | |
| tree | 870acc699f3d13ea177dbf6eae79cbd0fc78a905 | |
| parent | 0.2.8-pre0 (diff) | |
| download | zen-6a44e6c95031179d29fca433851219eef402d71e.tar.xz zen-6a44e6c95031179d29fca433851219eef402d71e.zip | |
add customization of assert implementation (#263)
* add customization of assert implementation
| -rw-r--r-- | zencore/include/zencore/zencore.h | 63 | ||||
| -rw-r--r-- | zencore/zencore.cpp | 50 |
2 files changed, 86 insertions, 27 deletions
diff --git a/zencore/include/zencore/zencore.h b/zencore/include/zencore/zencore.h index db089d9ea..5bcd77239 100644 --- a/zencore/include/zencore/zencore.h +++ b/zencore/include/zencore/zencore.h @@ -249,38 +249,47 @@ namespace zen AssertException(const char* Msg) : std::logic_error(Msg) {} }; + struct AssertImpl + { + static void ZEN_FORCENOINLINE ZEN_DEBUG_SECTION ExecAssert + [[noreturn]] (const char* Filename, int LineNumber, const char* FunctionName, const char* Msg) + { + CurrentAssertImpl->OnAssert(Filename, LineNumber, FunctionName, Msg); + throw AssertException{Msg}; + } + + protected: + virtual void ZEN_FORCENOINLINE ZEN_DEBUG_SECTION OnAssert(const char* Filename, + int LineNumber, + const char* FunctionName, + const char* Msg) + { + (void(Filename)); + (void(LineNumber)); + (void(FunctionName)); + (void(Msg)); + } + static AssertImpl DefaultAssertImpl; + static AssertImpl* CurrentAssertImpl; + }; + } // namespace zen -template<typename RetType = void, class InnerType, typename... ArgTypes> -RetType ZEN_FORCENOINLINE ZEN_DEBUG_SECTION -DispatchAssert(InnerType&& Inner, ArgTypes const&... Args) -{ - return Inner(Args...); -} - -#define ZEN_ASSERT(x, ...) \ - do \ - { \ - if (x) [[unlikely]] \ - break; \ - struct Impl \ - { \ - static void ZEN_FORCENOINLINE ZEN_DEBUG_SECTION ExecThrow [[noreturn]] () { throw ::zen::AssertException{#x}; } \ - }; \ - Impl::ExecThrow(); \ +#define ZEN_ASSERT(x, ...) \ + do \ + { \ + if (x) [[unlikely]] \ + break; \ + zen::AssertImpl::ExecAssert(__FILE__, __LINE__, __FUNCTION__, #x); \ } while (false) #ifndef NDEBUG -# define ZEN_ASSERT_SLOW(x, ...) \ - do \ - { \ - if (x) [[unlikely]] \ - break; \ - struct Impl \ - { \ - static void ZEN_FORCENOINLINE ZEN_DEBUG_SECTION ExecThrow [[noreturn]] () { throw ::zen::AssertException{#x}; } \ - }; \ - Impl::ExecThrow(); \ +# define ZEN_ASSERT_SLOW(x, ...) \ + do \ + { \ + if (x) [[unlikely]] \ + break; \ + zen::AssertImpl::ExecAssert(__FILE__, __LINE__, __FUNCTION__, #x); \ } while (false) #else # define ZEN_ASSERT_SLOW(x, ...) diff --git a/zencore/zencore.cpp b/zencore/zencore.cpp index 8b45d273d..2a7c5755e 100644 --- a/zencore/zencore.cpp +++ b/zencore/zencore.cpp @@ -33,6 +33,9 @@ namespace zen { +AssertImpl AssertImpl::DefaultAssertImpl; +AssertImpl* AssertImpl::CurrentAssertImpl = &AssertImpl::DefaultAssertImpl; + ////////////////////////////////////////////////////////////////////////// bool @@ -120,6 +123,53 @@ zencore_forcelinktests() zen::usonpackage_forcelink(); zen::crypto_forcelink(); } +} // namespace zen + +# include <zencore/testing.h> + +namespace zen { + +TEST_CASE("Assert.Default") +{ + bool A = true; + bool B = false; + CHECK_THROWS_WITH(ZEN_ASSERT(A == B), "A == B"); +} + +TEST_CASE("Assert.Custom") +{ + struct MyAssertImpl : AssertImpl + { + ZEN_FORCENOINLINE ZEN_DEBUG_SECTION MyAssertImpl() : PrevAssertImpl(CurrentAssertImpl) { CurrentAssertImpl = this; } + virtual ZEN_FORCENOINLINE ZEN_DEBUG_SECTION ~MyAssertImpl() { CurrentAssertImpl = PrevAssertImpl; } + virtual void ZEN_FORCENOINLINE ZEN_DEBUG_SECTION OnAssert(const char* Filename, + int LineNumber, + const char* FunctionName, + const char* Msg) + { + AssertFileName = Filename; + Line = LineNumber; + FuncName = FunctionName; + Message = Msg; + } + AssertImpl* PrevAssertImpl; + + const char* AssertFileName = nullptr; + int Line = -1; + const char* FuncName = nullptr; + const char* Message = nullptr; + }; + + MyAssertImpl MyAssert; + bool A = true; + bool B = false; + CHECK_THROWS_WITH(ZEN_ASSERT(A == B), "A == B"); + CHECK(MyAssert.AssertFileName != nullptr); + CHECK(MyAssert.Line != -1); + CHECK(MyAssert.FuncName != nullptr); + CHECK(strcmp(MyAssert.Message, "A == B") == 0); +} + #endif } // namespace zen |