diff --git a/engine/NBCore/Errors.hpp b/engine/NBCore/Errors.hpp index 1f636f6..e406347 100644 --- a/engine/NBCore/Errors.hpp +++ b/engine/NBCore/Errors.hpp @@ -1,11 +1,11 @@ #pragma once -#include #ifndef _NB_ERROR #define _NB_ERROR #include -#include +#include #include +#include #include #include "TypeTraits.hpp" #include @@ -34,44 +34,89 @@ typedef std::unordered_map ErrorCodeMap; template using has_type = decltype(T::type); -template -struct NBErrorWhatString; +template +class ErrorBase; -class ErrorBase_what_str_impl : public std::exception { +template<> +class ErrorBase : public std::exception { public: - virtual std::string what_str_impl() const = 0; - virtual std::wstring what_wstr_impl() const = 0; -}; - -template -class ErrorBase : public ErrorBase_what_str_impl { -public: - ErrorBase(const ErrorBase&) = default; - ErrorBase& operator=(const ErrorBase&) = delete; - - template - inline const StringType what_str() const noexcept { - return NBErrorWhatString::what(*this); - } - - virtual const char* what() const noexcept override final { - const std::string& ret = what_str(); - return ret.c_str(); - } - - static const std::string type; - static const ErrorCodeMap ErrorMessages; - const unsigned int code; const std::string msg; const std::shared_ptr trace; const bool traceIsNBError; + virtual inline std::string str() const noexcept = 0; + + virtual const char* what() const noexcept override final { + const std::string& ret = str(); + return ret.c_str(); + } + protected: - ErrorBase() = delete; + template < + typename TraceType = std::exception, + std::enable_if_t, bool> = true + > + ErrorBase( + const unsigned int& code_, + const std::string& msg_, + const std::shared_ptr trace_, + const unsigned int& line_, + std::string filename_ + ) noexcept : + code(code_), + msg(msg_), + trace{std::dynamic_pointer_cast(trace_)}, + traceIsNBError( trace_ ? is_detected::value : false) + { + static_assert(std::is_base_of::value, + "`trace_` must be a pointer to a child object of std::exception." + ); + } +}; + +template +class ErrorBase : public ErrorBase { + using Base = ErrorBase; +public: + ErrorBase(const ErrorBase&) = default; + ErrorBase& operator=(const ErrorBase&) = delete; + + virtual inline std::string str() const noexcept override { + std::string ret = msg; + if (trace) { + const std::string replace = nb::NEWLINE+" "; + std::string trace_msg; + if (traceIsNBError) { + trace_msg = std::static_pointer_cast(trace)->str(); + trace_msg = std::string(std::string_view(trace_msg).substr( + 0, trace_msg.length()-nb::NEWLINE.length() + )); + } else { + trace_msg = std::string(trace->what()); + } + ret += replace + "Trace: " + find_and_replace( + trace_msg, + nb::NEWLINE, + replace + ); + } + return ret + nb::NEWLINE; + } + + static const std::string type; + static const ErrorCodeMap ErrorMessages; + + using Base::code; + using Base::msg; + using Base::trace; + using Base::traceIsNBError; + +protected: + using Base::Base; template < - typename TraceType=std::exception, + typename TraceType = std::exception, std::enable_if_t, bool> = true > ErrorBase( @@ -80,12 +125,13 @@ protected: const TraceType* trace_=nullptr, unsigned int line_=0, std::string filename_="" - ) noexcept : - code(code_), - msg(msg_), - trace{trace_ ? std::make_shared(*trace_) : nullptr}, - traceIsNBError( trace_ ? is_detected::value : false) - { + ) : Base( + code_, + msg_, + trace_ ? std::make_shared(*trace_) : nullptr, + line_, + filename_ + ) { static_assert(std::is_same, decltype(ErrorType::ErrorMessages)>::value, "const std::unordered_map ErrorMessages must be " "a class member." @@ -97,9 +143,6 @@ protected: static_assert(std::is_same::value, "const std::string type must be a class member." ); - static_assert(std::is_base_of::value, - "`trace_` must be a pointer to a child object of std::exception." - ); } template < @@ -159,55 +202,12 @@ protected: line_, filename_ ) {} - - std::string what_str_impl() const override final { return what_str(); } - std::wstring what_wstr_impl() const override final { return what_str(); } }; template const std::string ErrorBase::type = ErrorType::type; template const ErrorCodeMap ErrorBase::ErrorMessages = ErrorType::ErrorMessages; -template -struct NBErrorWhatString { - inline static const std::wstring what(const ErrorBase& err) noexcept { - std::wstring ret = nb::str_to_wstr(err.msg); - const std::wstring replace = nb::WNEWLINE + L"┗-"; - if (err.trace) { - std::wstring trace_msg; - if (err.traceIsNBError) { - // How can I access - trace_msg = std::static_pointer_cast(err.trace)->what_wstr_impl(); - } else { - trace_msg = nb::str_to_wstr(std::string(err.trace->what())); - } - trace_msg = find_and_replace(trace_msg, L"┗", L"-"); - ret += replace + find_and_replace( - trace_msg, - nb::WNEWLINE, - replace - ); - } - return ret; - } -}; - -template -struct NBErrorWhatString { - inline static const std::string what(const ErrorBase& err) noexcept { - std::string ret = err.msg; - const std::string replace = nb::NEWLINE+" "; - if (err.trace) { - ret += replace + find_and_replace( - std::string(err.trace->what()), - nb::NEWLINE, - replace - ); - } - return ret; - } -}; - template class Error; @@ -221,6 +221,7 @@ public: template Error(Args... T) : Base(T...) {} + using Base::str; using Base::what; using Base::code; using Base::msg; @@ -242,6 +243,7 @@ public: GENERAL, UNDEFINED, BADERRORCODE }; + using Base::str; using Base::what; using Base::code; using Base::msg; diff --git a/engine/NBCore/TypeTraits.hpp b/engine/NBCore/TypeTraits.hpp index a1e7502..5277159 100644 --- a/engine/NBCore/TypeTraits.hpp +++ b/engine/NBCore/TypeTraits.hpp @@ -37,11 +37,6 @@ template < > using is_detected = typename detail::detector::value; -template -void stream(Stream& s, Args&&... args) { - (s << ... << args); -} - /*template inline typename std::enable_if::type ForEach(std::tuple&, Func) {} diff --git a/engine/NBCore/Utils.hpp b/engine/NBCore/Utils.hpp index 96194d3..01d6dac 100644 --- a/engine/NBCore/Utils.hpp +++ b/engine/NBCore/Utils.hpp @@ -1,16 +1,16 @@ #pragma once -#include -#include #ifndef _NB_CORE_TYPES #define _NB_CORE_TYPES +#include #include +#include namespace nb { #ifdef _NB_TARGET_WINDOWS - const std::string NEWLINE = "\r\n"; - const std::wstring WNEWLINE = L"\r\n"; + const std::string NEWLINE = "\n"; + const std::wstring WNEWLINE = L"\n"; #endif // _NB_TARGET_WINDOWS #ifdef _NB_TARGET_LINUX const std::string NEWLINE = "\n"; @@ -18,14 +18,14 @@ namespace nb { #endif // _NB_TARGET_LINUX template -std::enable_if_t, std::wstring> str_to_wstr(const T& in) { +std::enable_if_t, std::wstring> str_to_wstr(T in) { std::string str(in); std::wstring ret(str.begin(), str.end()); return ret; } template -std::enable_if_t, std::string> wstr_to_str(const T& in) { +std::enable_if_t, std::string> wstr_to_str(T in) { std::wstring wstr(in); std::size_t wstrlen = wstr.length(); char* c_str= new char[wstrlen]; @@ -35,11 +35,25 @@ std::enable_if_t, std::string> wst return ret; } +template +void stream(Stream& s, Args&&... args); + +template +void stream(Stream& s, Args&&... args) { + (s << ... << args); +} + +template +void term(Args&&... args) { stream(std::cout, args..., nb::NEWLINE); } + +template +void wterm(Args&&... args) { stream(std::wcout, args..., nb::WNEWLINE); } + template T find_and_replace( - const A& original, - const B& find, - const C& replace + A original, + B find, + C replace ) { const T& original_t = T(original); const T& find_t = T(find); @@ -50,10 +64,8 @@ T find_and_replace( std::size_t find_len = find_t.length(); std::size_t replace_len = replace_t.length(); std::size_t currpos = 0; - std::size_t lastpos = 0; while(true) { - lastpos = currpos; - currpos = original_t.find(find_t, lastpos); + currpos = ret.find(find_t, currpos); if (currpos == T::npos) { break; } diff --git a/engine/NBCore/tests/testErrors.cpp b/engine/NBCore/tests/testErrors.cpp index 6c778b7..81187be 100644 --- a/engine/NBCore/tests/testErrors.cpp +++ b/engine/NBCore/tests/testErrors.cpp @@ -3,9 +3,8 @@ #include #include "Errors.hpp" -#include #include -#include "TypeTraits.hpp" +#include "Utils.hpp" using namespace nb; @@ -36,12 +35,6 @@ const ErrorCodeMap TestError::ErrorMessages{ TEST(ErrorTest, Test) { - auto err = TestError(0, TestError(1)); - nb::stream(std::cout, - "len string: ", err.what_str().length(), "\n", - "len wstring: ", err.what_str().length(), "\n" - ); - nb::stream(std::wcout, - err.what_str(), L"\n" - ); + auto err = TestError(0, TestError(1, TestError(2, TestError(3, TestError(2))))); + ASSERT_STREQ(err.what(), "Hey!\n Trace: How\n Trace: You\n Trace: Doin\n Trace: You\n"); } \ No newline at end of file diff --git a/engine/NBCore/tests/testUtils.cpp b/engine/NBCore/tests/testUtils.cpp index f9188a1..e097788 100644 --- a/engine/NBCore/tests/testUtils.cpp +++ b/engine/NBCore/tests/testUtils.cpp @@ -1,4 +1,3 @@ -#include #define CODE_ERROR_LOCATIONS #include