From 126862748e840d760c96df2b8fdb97697b249500 Mon Sep 17 00:00:00 2001 From: NaifBanana <30419422+NaifBanana@users.noreply.github.com> Date: Mon, 6 Apr 2026 02:22:28 -0500 Subject: [PATCH] Made errors mostly work as hoped --- CMakeLists.txt | 3 +- engine/NBCore/ANSITerm.hpp | 6 - engine/NBCore/CMakeLists.txt | 8 +- engine/NBCore/Errors.hpp | 225 +++++++++++++++++--------- engine/NBCore/Types.hpp | 25 --- engine/NBCore/Utils.hpp | 45 ++++++ engine/NBCore/src/Errors.cpp | 11 +- engine/NBCore/src/Processes.cpp | 1 - engine/NBCore/src/Utils.cpp | 23 +++ engine/NBCore/tests/CMakeLists.txt | 5 +- engine/NBCore/tests/testErrors.cpp | 31 ++-- engine/NBCore/tests/testProcesses.cpp | 2 - engine/NBCore/tests/testUtils.cpp | 41 +++++ 13 files changed, 284 insertions(+), 142 deletions(-) delete mode 100644 engine/NBCore/Types.hpp create mode 100644 engine/NBCore/Utils.hpp create mode 100644 engine/NBCore/src/Utils.cpp create mode 100644 engine/NBCore/tests/testUtils.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f60158..65af2c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,13 +48,12 @@ if(NB_BUILD_TESTS) include(FetchContent) FetchContent_Declare( gtest - URL https://github.com/google/googletest/archive/refs/tags/release-1.12.1.zip + URL https://github.com/google/googletest/archive/refs/heads/main.zip ) if (WIN32) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(gtest) endif() - include(GoogleTest) set(GTEST_COLOR ON) set(GLFW_BUILD_TESTS ON CACHE BOOL "" FORCE) endif() diff --git a/engine/NBCore/ANSITerm.hpp b/engine/NBCore/ANSITerm.hpp index b74ee7b..b729bac 100644 --- a/engine/NBCore/ANSITerm.hpp +++ b/engine/NBCore/ANSITerm.hpp @@ -2,16 +2,10 @@ #ifndef _NB_ANSI_TERM #define _NB_ANSI_TERM -#include -#include -#include #include #include -#include #include -#include "TypeTraits.hpp" - /* ----------- TECH DEBT ------------ Idk wtf to do here. This was originally to allow me to print diff --git a/engine/NBCore/CMakeLists.txt b/engine/NBCore/CMakeLists.txt index 6b105df..2260d5a 100644 --- a/engine/NBCore/CMakeLists.txt +++ b/engine/NBCore/CMakeLists.txt @@ -1,9 +1,8 @@ -include_directories(./.) - toAbsolutePath(NB_CORE_SOURCE ./src/Errors.cpp - ./src/Processes.cpp ./src/Logger.cpp + ./src/Processes.cpp + ./src/Utils.cpp ) toAbsolutePath(NB_CORE_INCLUDE @@ -15,6 +14,7 @@ toAbsolutePath(NB_CORE_INCLUDE ./ThreadsafeQueue.hpp ./Types.hpp ./TypeTraits.hpp + ./Utils.hpp ) set(NB_CORE_SOURCE ${NB_CORE_SOURCE} PARENT_SCOPE) @@ -22,6 +22,8 @@ set(NB_CORE_INCLUDE ${NB_CORE_INCLUDE} PARENT_SCOPE) add_library(NBCore ${NB_CORE_SOURCE}) +target_include_directories(NBCore PUBLIC ./.) + if (NB_BUILD_TESTS) add_subdirectory(./tests) endif() \ No newline at end of file diff --git a/engine/NBCore/Errors.hpp b/engine/NBCore/Errors.hpp index a893b9b..49bedd1 100644 --- a/engine/NBCore/Errors.hpp +++ b/engine/NBCore/Errors.hpp @@ -3,10 +3,11 @@ #define _NB_ERROR #include -#include +#include #include #include #include +#include "Utils.hpp" #ifndef THROW_WITH_INFO #ifdef CODE_ERROR_LOCATIONS @@ -31,109 +32,173 @@ typedef std::unordered_map ErrorCodeMap; template class ErrorBase : public std::exception { public: - ErrorBase( - const unsigned int code, - unsigned int line=0, - std::string filename="" - ) noexcept : ErrorBase( - code, - ErrorBase::lookup(code), - line, - filename - ) {} - ErrorBase( - const unsigned int code, - const std::exception& trace, - unsigned int line=0, - std::string filename="" - ) noexcept : ErrorBase( - code, - ErrorBase::lookup(code), - trace, - line, - filename - ) {} + ErrorBase(const ErrorBase&) = default; + ErrorBase& operator=(const ErrorBase&) = delete; - static std::string lookup(unsigned int); - unsigned int code() const noexcept { - return static_cast(this)->_code; - }; - virtual const char* what() const noexcept override final { return _msg.c_str(); }; + 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(); + } + + static const std::string type; + static const ErrorCodeMap ErrorMessages; + + const unsigned int code; + const std::string msg; + const std::exception* trace; protected: - ErrorBase() = default; + ErrorBase() = delete; + + template < + typename TraceType=std::exception, + std::enable_if_t, bool> = true + > ErrorBase( - const unsigned int code, - std::string msg, - unsigned int line=0, - std::string filename="" - ) noexcept : _code{code}, _msg{""} { + const unsigned int code_, + std::string msg_, + const TraceType* trace_=nullptr, + unsigned int line_=0, + std::string filename_="" + ) noexcept : + code(code_), + msg(msg_), + trace{static_cast(trace_ ? new TraceType(*trace_) : nullptr) } + { static_assert(std::is_same, decltype(ErrorType::ErrorMessages)>::value, "const std::unordered_map ErrorMessages must be " "a class member." ); - static_assert(std::is_enum_v, "enum ErrorCodes must be a class member."); - static_assert(std::is_same, unsigned int>::value, - "enum ErrorCodes must be of underlying type unsigned int." + static_assert(std::is_enum_v, "enum Codes must be a class member."); + static_assert(std::is_same, unsigned int>::value, + "enum Codes must be of underlying type unsigned int." ); static_assert(std::is_same::value, "const std::string type must be a class member." ); - - _msg += std::string(ErrorType::type); - _msg += "[" + std::to_string(_code) + "]"; - if (line && filename.size()) { - _msg += " in \'" + filename + "\':" + std::to_string(line); - } - _msg += "\n " + msg; - } - ErrorBase( - const unsigned int code, - std::string msg, - const std::exception& trace, - unsigned int line=0, - std::string filename="" - ) noexcept : ErrorBase(code, msg, line, filename) { - std::string what_msg(trace.what()); - std::string::size_type newline_pos=-1; - while((newline_pos=what_msg.find("\n", newline_pos+1))!= std::string::npos) { - what_msg.replace(newline_pos, 1, "\n "); - } - _msg += "\n Trace - " + what_msg; + static_assert(std::is_base_of::value, + "`trace_` must be a pointer to a child object of std::exception." + ); } - - unsigned int _code; - std::string _msg; + + template < + typename TraceType, + std::enable_if_t, bool> = true + > + ErrorBase( + const unsigned int& code_, + const TraceType& trace_, + unsigned int line_=0, + std::string filename_="" + ) noexcept : ErrorBase( + code_, + ErrorType::ErrorMessages.at(code_), + &trace_, + line_, + filename_ + ) {} + + template < + typename TraceType, + std::enable_if_t, bool> = true + > + ErrorBase( + const std::string& msg_, + const TraceType& trace_, + unsigned int line_=0, + std::string filename_="" + ) noexcept : ErrorBase( + 0, + msg_, + &trace_, + line_, + filename_ + ) {} + + ErrorBase( + const unsigned int& code_, + unsigned int line_=0, + std::string filename_="" + ) noexcept : ErrorBase( + code_, + ErrorType::ErrorMessages.at(code_), + static_cast(nullptr), + line_, + filename_ + ) {} + + ErrorBase( + const std::string& msg_, + unsigned int line_=0, + std::string filename_="" + ) noexcept : ErrorBase( + 0, + msg_, + nullptr, + line_, + filename_ + ) {} + +}; +template +const std::string ErrorBase::type = ErrorType::type; +template +const ErrorCodeMap ErrorBase::ErrorMessages = ErrorType::ErrorMessages; + +class DefaultError {DefaultError() = default;}; + +template +class Error; + +template<> +class Error; + +template +class Error : public ErrorBase { + using Base = ErrorBase; +public: + template + Error(Args... T) : Base(T...) {} + + using Base::what; + using Base::code; + using Base::msg; + using Base::trace; + using Base::type; + using Base::ErrorMessages; + + friend ErrorBase; }; -class Error : public ErrorBase { +template<> +class Error : public ErrorBase> { + using Base = ErrorBase>; public: - enum ErrorCodes : unsigned int { + using Base::Base; + Error() : Base(0) {} + + enum Codes : unsigned int { GENERAL, UNDEFINED, BADERRORCODE }; - using ErrorBase::ErrorBase; + using Base::what; + using Base::code; + using Base::msg; + using Base::trace; - friend ErrorBase; - -protected: static const std::string type; static const ErrorCodeMap ErrorMessages; - }; -template -std::string ErrorBase::lookup(unsigned int code) { - for (auto kv : ErrorType::ErrorMessages) { - if (kv.first==code) { - return std::string(kv.second); - } - } - - throw Error(Error::ErrorCodes::BADERRORCODE); -} - } // namespace nb - #endif // _NB_ERROR \ No newline at end of file diff --git a/engine/NBCore/Types.hpp b/engine/NBCore/Types.hpp deleted file mode 100644 index 293bdb5..0000000 --- a/engine/NBCore/Types.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#ifndef _NB_CORE_TYPES -#define _NB_CORE_TYPES - -#include - -namespace nb { - -template -T swapEndian(const T& val) { - T ret; - const int size = sizeof(T); - auto retLoc = static_cast(&ret); - auto valLoc = static_cast(&val); - - for (int i = 0; i < size; ++i) { - memcpy(retLoc+i, valLoc+(size-i-1), 1); - } - return ret; -} - -using ByteVector = std::vector; - -} // namespace nb -#endif // _NB_CORE_TYPES \ No newline at end of file diff --git a/engine/NBCore/Utils.hpp b/engine/NBCore/Utils.hpp new file mode 100644 index 0000000..3151183 --- /dev/null +++ b/engine/NBCore/Utils.hpp @@ -0,0 +1,45 @@ +#pragma once +#ifndef _NB_CORE_TYPES +#define _NB_CORE_TYPES + +#include +#include +#include + +namespace nb { + +#ifdef _NB_TARGET_WINDOWS + const std::string NEWLINE("\r\n"); +#endif // _NB_TARGET_WINDOWS +#ifdef _NB_TARGET_LINUX + const std::string NEWLINE("\n"); +#endif // _NB_TARGET_LINUX + +template +struct ConstexprMap { + template + constexpr ConstexprMap(Input inp) : _data{inp} {} + +protected: + const std::array, N> _data; +}; + +/* template +T swap_endian(const T& val) { + T ret; + const int size = sizeof(T); + auto retLoc = static_cast(&ret); + auto valLoc = static_cast(&val); + + for (int i = 0; i < size; ++i) { + memcpy(retLoc+i, valLoc+(size-i-1), 1); + } + return ret; +} */ + +std::string find_and_replace(const std::string& original, const std::string& find, const std::string& replace); + +// using ByteVector = std::vector; + +} // namespace nb +#endif // _NB_CORE_TYPES \ No newline at end of file diff --git a/engine/NBCore/src/Errors.cpp b/engine/NBCore/src/Errors.cpp index 544346a..952f772 100644 --- a/engine/NBCore/src/Errors.cpp +++ b/engine/NBCore/src/Errors.cpp @@ -2,11 +2,12 @@ namespace nb { -const std::string Error::type = "Error"; -const ErrorCodeMap Error::ErrorMessages = { - {ErrorCodes::GENERAL, "General std::exception."}, - {ErrorCodes::UNDEFINED, "Undefined / general error."}, - {ErrorCodes::BADERRORCODE, "Unrecognized error code."} +const std::string Error::type = "nb::Error"; + +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/Processes.cpp b/engine/NBCore/src/Processes.cpp index dabf222..744d96d 100644 --- a/engine/NBCore/src/Processes.cpp +++ b/engine/NBCore/src/Processes.cpp @@ -7,7 +7,6 @@ #endif // _NB_TARGET_LINUX #include "Processes.hpp" -#include "Types.hpp" namespace nb { diff --git a/engine/NBCore/src/Utils.cpp b/engine/NBCore/src/Utils.cpp new file mode 100644 index 0000000..f060189 --- /dev/null +++ b/engine/NBCore/src/Utils.cpp @@ -0,0 +1,23 @@ +#include +#include "Utils.hpp" + + +std::string nb::find_and_replace(const std::string& original, const std::string& find, const std::string& replace) { + std::string ret = original; + + std::size_t find_len = find.length(); + std::size_t replace_len = replace.length(); + std::size_t currpos = 0; + std::size_t lastpos = 0; + while(true) { + lastpos = currpos; + currpos = original.find(find, lastpos); + if (currpos == std::string::npos) { + break; + } + ret = ret.erase(currpos, find_len); + ret = ret.insert(currpos, replace); + currpos += replace_len; + } + return ret; +} \ No newline at end of file diff --git a/engine/NBCore/tests/CMakeLists.txt b/engine/NBCore/tests/CMakeLists.txt index d3ad479..02c31c7 100644 --- a/engine/NBCore/tests/CMakeLists.txt +++ b/engine/NBCore/tests/CMakeLists.txt @@ -4,8 +4,9 @@ if (NB_BUILD_TESTS) enable_testing() include(GoogleTest) add_executable(TestCore - testErrors.cpp - testProcesses.cpp + ./testErrors.cpp + #./testProcesses.cpp + ./testUtils.cpp ) target_link_libraries(TestCore NBCore diff --git a/engine/NBCore/tests/testErrors.cpp b/engine/NBCore/tests/testErrors.cpp index 7d79ee9..6b1c21f 100644 --- a/engine/NBCore/tests/testErrors.cpp +++ b/engine/NBCore/tests/testErrors.cpp @@ -3,36 +3,35 @@ #include "Errors.hpp" #include #include -#include -#include "Logger.hpp" using namespace nb; -class TestError : public ErrorBase { +class TestError : public Error { + using Base = Error; public: - using ErrorBase::ErrorBase; + using Base::Base; + using Base::what; + using Base::code; + using Base::msg; + using Base::trace; - enum ErrorCodes : unsigned int { + enum Codes : unsigned int { A, B, C, D }; + static const std::string type; - static const ErrorCodeMap ErrorMessages; + static const nb::ErrorCodeMap ErrorMessages; }; const std::string TestError::type="TestError"; const ErrorCodeMap TestError::ErrorMessages{ - {TestError::ErrorCodes::A, "Hey!"}, - {TestError::ErrorCodes::B, "How"}, - {TestError::ErrorCodes::C, "You"}, - {TestError::ErrorCodes::D, "Doin"} + {TestError::Codes::A, "Hey!"}, + {TestError::Codes::B, "How"}, + {TestError::Codes::C, "You"}, + {TestError::Codes::D, "Doin"} }; TEST(ErrorTest, Test) { - EXPECT_EQ(1, 1); - - std::stringstream sstream; - - ASSERT_TRUE(nb::logger.isRunning()); - nb::logger.log("Hey!"); + std::cout << TestError(0, TestError(1, TestError(2))).what(); } \ No newline at end of file diff --git a/engine/NBCore/tests/testProcesses.cpp b/engine/NBCore/tests/testProcesses.cpp index 3e220b8..cee1e90 100644 --- a/engine/NBCore/tests/testProcesses.cpp +++ b/engine/NBCore/tests/testProcesses.cpp @@ -1,8 +1,6 @@ #define CODE_ERROR_LOCATIONS #include - -#include #include "Processes.hpp" #include diff --git a/engine/NBCore/tests/testUtils.cpp b/engine/NBCore/tests/testUtils.cpp new file mode 100644 index 0000000..1ef1969 --- /dev/null +++ b/engine/NBCore/tests/testUtils.cpp @@ -0,0 +1,41 @@ +#define CODE_ERROR_LOCATIONS + +#include "Utils.hpp" +#include + +namespace nb { + +TEST(UtilsTest, Test) { + ASSERT_STREQ( + find_and_replace("Jeff", "e", "efe").c_str(), + "Jefeff" + ); + + auto tmp = find_and_replace("Naif", "a", "afa"); + ASSERT_STREQ( + find_and_replace(tmp, "i", "ifi").c_str(), + "Nafaifif" + ); + + tmp = find_and_replace("aeiou", "a", "afa"); + tmp = find_and_replace(tmp, "e", "efe"); + tmp = find_and_replace(tmp, "i", "ifi"); + tmp = find_and_replace(tmp, "o", "ofo"); + tmp = find_and_replace(tmp, "u", "ufu"); + ASSERT_STREQ( + tmp.c_str(), + "afaefeifiofoufu" + ); + + tmp = find_and_replace(tmp, "afa", "a"); + tmp = find_and_replace(tmp, "efe", "e"); + tmp = find_and_replace(tmp, "ifi", "i"); + tmp = find_and_replace(tmp, "ofo", "o"); + tmp = find_and_replace(tmp, "ufu", "u"); + ASSERT_STREQ( + tmp.c_str(), + "aeiou" + ); +} + +} // namespace nb \ No newline at end of file