diff --git a/engine/NBCore/CMakeLists.txt b/engine/NBCore/CMakeLists.txt index 2260d5a..b457870 100644 --- a/engine/NBCore/CMakeLists.txt +++ b/engine/NBCore/CMakeLists.txt @@ -1,6 +1,6 @@ toAbsolutePath(NB_CORE_SOURCE ./src/Errors.cpp - ./src/Logger.cpp +# ./src/Logger.cpp ./src/Processes.cpp ./src/Utils.cpp ) diff --git a/engine/NBCore/Errors.hpp b/engine/NBCore/Errors.hpp index 49bedd1..6517341 100644 --- a/engine/NBCore/Errors.hpp +++ b/engine/NBCore/Errors.hpp @@ -1,4 +1,5 @@ #pragma once +#include #ifndef _NB_ERROR #define _NB_ERROR @@ -6,10 +7,11 @@ #include #include #include +#include "TypeTraits.hpp" #include #include "Utils.hpp" -#ifndef THROW_WITH_INFO +/* #ifndef THROW_WITH_INFO #ifdef CODE_ERROR_LOCATIONS #define THROW_WITH_INFO(type, ...) throw type(__VA_ARGS__, __LINE__, __FILE__) #else @@ -23,30 +25,43 @@ #else #define THROW(...) THROW_WITH_INFO(__VA_ARGS__) #endif // LOGGING -#endif // THROW +#endif // THROW */ namespace nb { typedef std::unordered_map ErrorCodeMap; +template +using has_type = decltype(T::type); + +template +struct NBErrorWhatString; + +class ErrorBase_what_str_impl : public std::exception { + template + T what_str() const; + + template <> + virtual std::wstring what_str() const; + + template<> + virtual std::string what_str() const; +}; + template -class ErrorBase : public std::exception { +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 { - std::string ret = this->msg; - const std::string replace = nb::NEWLINE + "\t"; - if (trace) { - ret += replace + find_and_replace( - std::string(trace->what()), - nb::NEWLINE, - replace - ); - } - const std::string& ret_ref = ret; - return ret_ref.c_str(); + const std::string& ret = what_str(); + return ret.c_str(); } static const std::string type; @@ -54,7 +69,8 @@ public: const unsigned int code; const std::string msg; - const std::exception* trace; + const std::shared_ptr trace; + const bool traceIsNBError; protected: ErrorBase() = delete; @@ -72,7 +88,8 @@ protected: ) noexcept : code(code_), msg(msg_), - trace{static_cast(trace_ ? new TraceType(*trace_) : nullptr) } + trace{trace_ ? std::make_shared(*trace_) : nullptr}, + traceIsNBError( trace_ ? is_detected::value : false) { static_assert(std::is_same, decltype(ErrorType::ErrorMessages)>::value, "const std::unordered_map ErrorMessages must be " @@ -148,19 +165,58 @@ protected: filename_ ) {} + std::string (ErrorBase::*_trace_what_str)(); + std::wstring (ErrorBase::*_trace_what_wstr)(); }; template const std::string ErrorBase::type = ErrorType::type; template const ErrorCodeMap ErrorBase::ErrorMessages = ErrorType::ErrorMessages; -class DefaultError {DefaultError() = default;}; +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) { + trace_msg = std::static_pointer_cast(err.trace)->template what_str(); + } 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 +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; template<> -class Error; +class Error; template class Error : public ErrorBase { @@ -180,8 +236,8 @@ public: }; template<> -class Error : public ErrorBase> { - using Base = ErrorBase>; +class Error : public ErrorBase> { + using Base = ErrorBase>; public: using Base::Base; Error() : Base(0) {} diff --git a/engine/NBCore/TypeTraits.hpp b/engine/NBCore/TypeTraits.hpp index 5226e94..a1e7502 100644 --- a/engine/NBCore/TypeTraits.hpp +++ b/engine/NBCore/TypeTraits.hpp @@ -6,7 +6,43 @@ namespace nb { -template +namespace detail { + template < + class Default, + class AlwaysVoid, + template class Op, + class... Args + > + struct detector { + using value = std::false_type; + using type = Default; + }; + + template < + class Default, + template class Op, + class... Args + > + struct detector>, Op, Args...> { + using value = std::true_type; + using type = Op; + }; +} // namespace detail + +struct NoneType{}; + +template < + template class Op, + class... Args +> +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) {} @@ -68,7 +104,7 @@ struct PackIsSameType { template struct PackIsSameType { const bool value = std::is_base_of::value && PackIsSameType::value; -}; +};*/ } // namespace nb diff --git a/engine/NBCore/Utils.hpp b/engine/NBCore/Utils.hpp index e51d3f5..96194d3 100644 --- a/engine/NBCore/Utils.hpp +++ b/engine/NBCore/Utils.hpp @@ -4,40 +4,33 @@ #ifndef _NB_CORE_TYPES #define _NB_CORE_TYPES -#include -#include #include namespace nb { #ifdef _NB_TARGET_WINDOWS - const std::string NEWLINE; - const std::wstring WNEWLINE; + const std::string NEWLINE = "\r\n"; + const std::wstring WNEWLINE = L"\r\n"; #endif // _NB_TARGET_WINDOWS #ifdef _NB_TARGET_LINUX - const std::string NEWLINE; - const std::wstring WNEWLINE; + const std::string NEWLINE = "\n"; + const std::wstring WNEWLINE = L"\n"; #endif // _NB_TARGET_LINUX template -std::enable_if_t, std::wstring> str_to_wstr(const T& str) { - std::mbstate_t state = std::mbstate_t(); - const char* cstr = std::string(str).c_str(); - std::size_t wlen = 1 + std::mbsrtowcs(nullptr, &cstr, 0, &state); - wchar_t* c_wstr= new wchar_t[wlen]; - std::mbsrtowcs(c_wstr, &cstr, wlen, &state); - std::wstring ret(c_wstr, wlen); - delete[] c_wstr; +std::enable_if_t, std::wstring> str_to_wstr(const 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& wstr) { - const wchar_t* c_wstr = std::wstring(wstr).c_str(); - std::size_t strlen = 1 + std::wcstombs(nullptr, c_wstr, 0); - char* c_str= new char[strlen]; - std::wcstombs(c_str, c_wstr, strlen); - std::string ret(c_str, strlen); +std::enable_if_t, std::string> wstr_to_str(const T& in) { + std::wstring wstr(in); + std::size_t wstrlen = wstr.length(); + char* c_str= new char[wstrlen]; + std::wcstombs(c_str, wstr.c_str(), wstrlen); + std::string ret(c_str, wstrlen); delete[] c_str; return ret; } diff --git a/engine/NBCore/src/Errors.cpp b/engine/NBCore/src/Errors.cpp index 952f772..43b6227 100644 --- a/engine/NBCore/src/Errors.cpp +++ b/engine/NBCore/src/Errors.cpp @@ -1,10 +1,11 @@ #include "Errors.hpp" +#include "TypeTraits.hpp" namespace nb { -const std::string Error::type = "nb::Error"; +const std::string Error::type = "nb::Error"; -const ErrorCodeMap Error::ErrorMessages = { +const ErrorCodeMap Error::ErrorMessages = { {Error::Codes::GENERAL, "General std::exception."}, {Error::Codes::UNDEFINED, "Undefined / general error."}, {Error::Codes::BADERRORCODE, "Unrecognized error code."} diff --git a/engine/NBCore/src/Utils.cpp b/engine/NBCore/src/Utils.cpp index f94f897..336d3b6 100644 --- a/engine/NBCore/src/Utils.cpp +++ b/engine/NBCore/src/Utils.cpp @@ -1,14 +1,8 @@ -#include -#include #include - #include "Utils.hpp" -#ifdef _NB_TARGET_WINDOWS - const std::string NEWLINE("\r\n"); - const std::wstring WNEWLINE(L"\r\n"); -#endif // _NB_TARGET_WINDOWS -#ifdef _NB_TARGET_LINUX - const std::string NEWLINE("\n"); - const std::wstring WNEWLINE(L"\n"); -#endif // _NB_TARGET_LINUX +template<> +std::wstring nb::str_to_wstr(const std::string& in) { + std::wstring ret(in.begin(), in.end()); + return ret; +} diff --git a/engine/NBCore/tests/testErrors.cpp b/engine/NBCore/tests/testErrors.cpp index 6b1c21f..6c778b7 100644 --- a/engine/NBCore/tests/testErrors.cpp +++ b/engine/NBCore/tests/testErrors.cpp @@ -1,8 +1,11 @@ #define CODE_ERROR_LOCATIONS -#include "Errors.hpp" #include + +#include "Errors.hpp" #include +#include +#include "TypeTraits.hpp" using namespace nb; @@ -33,5 +36,12 @@ const ErrorCodeMap TestError::ErrorMessages{ TEST(ErrorTest, Test) { - std::cout << TestError(0, TestError(1, TestError(2))).what(); + 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" + ); } \ No newline at end of file diff --git a/engine/NBCore/tests/testUtils.cpp b/engine/NBCore/tests/testUtils.cpp index 042e7a0..f9188a1 100644 --- a/engine/NBCore/tests/testUtils.cpp +++ b/engine/NBCore/tests/testUtils.cpp @@ -4,6 +4,7 @@ #include #include +#include "TypeTraits.hpp" #include "Utils.hpp" namespace nb { @@ -112,5 +113,37 @@ TEST(UtilsTest, TestStrToWstr) { ); } +struct A { bool x(); }; +struct B { bool y(); }; +struct C { bool x(); bool y; }; +struct D : C {}; + +template +using has_x = decltype(T::x); + +template +using has_y = decltype(T::y); + +TEST(UtilsTest, TestIsDetected) { + auto ret = is_detected::value; + ASSERT_TRUE(ret); + ret = is_detected::value; + ASSERT_FALSE(ret); + + ret = is_detected::value; + ASSERT_TRUE(ret); + ret = is_detected::value; + ASSERT_FALSE(ret); + + ret = is_detected::value; + ASSERT_TRUE(ret); + ret = is_detected::value; + ASSERT_TRUE(ret); + + ret = is_detected::value; + ASSERT_TRUE(ret); + ret = is_detected::value; + ASSERT_TRUE(ret); +} } // namespace nb \ No newline at end of file