diff --git a/engine/NBCore/CMakeLists.txt b/engine/NBCore/CMakeLists.txt index ee3a13b..76e9249 100644 --- a/engine/NBCore/CMakeLists.txt +++ b/engine/NBCore/CMakeLists.txt @@ -1,5 +1,5 @@ toAbsolutePath(NB_CORE_SOURCE - ./src/Errors.cpp + ./src/ErrorsImpl.cpp ./src/Logger.cpp ./src/Processes.cpp ./src/StringUtils.cpp @@ -10,6 +10,7 @@ toAbsolutePath(NB_CORE_INCLUDE ./ANSITerm.hpp ./DataSink.hpp ./Errors.hpp + ./ErrorsImpl.hpp ./Logger.hpp ./Processes.hpp ./StringUtils.hpp diff --git a/engine/NBCore/DataSink.hpp b/engine/NBCore/DataSink.hpp index d3c5d25..155c48a 100644 --- a/engine/NBCore/DataSink.hpp +++ b/engine/NBCore/DataSink.hpp @@ -72,11 +72,11 @@ template class MultithreadedDataProcessor : public BufferedDataProcessor, ProcessorType> { using Base = BufferedDataProcessor, ProcessorType>; -public: + public: ~MultithreadedDataProcessor() { type_ptr->stop(); } bool isRunning() const noexcept override { - return this->_running && (_runningThread!=nullptr); + return this->_running; } bool run() override { if (!type_ptr->isRunning()) { @@ -98,7 +98,7 @@ public: return !type_ptr->isRunning(); } -protected: + protected: using Base::Base; unsigned int count() const { diff --git a/engine/NBCore/Errors.hpp b/engine/NBCore/Errors.hpp index 89cc13b..8a6db60 100644 --- a/engine/NBCore/Errors.hpp +++ b/engine/NBCore/Errors.hpp @@ -2,281 +2,11 @@ #ifndef _NB_ERROR #define _NB_ERROR -#include -#include -#include -#include -#include - +#include "ErrorsImpl.hpp" #include "Logger.hpp" -#include "StringUtils.hpp" -#include "TypeTraits.hpp" namespace nb { -typedef std::unordered_map ErrorCodeMap; - -template -constexpr bool IsValidException_v = std::is_base_of_v; -template -using IsValidException = std::enable_if_t, bool>; - -template -class ErrorBase; - -template -class Error; - -template -constexpr bool IsValidNBError_v = std::is_base_of_v, T>; -template -using IsValidNBError = std::enable_if_t, bool>; - - -template<> -class ErrorBase { -public: - const unsigned int code; - const std::string msg; - const std::string type; - const std::shared_ptr trace; - const bool traceIsNBError; - - virtual std::string what() const noexcept = 0; - virtual std::shared_ptr make_shared() const noexcept = 0; - -protected: - template - ErrorBase(const ErrorBase& err) : ErrorBase(std::move(err)) {} - - template - ErrorBase(ErrorBase&& err) : ErrorBase( - err.code, - err.msg, - err.type, - (err.traceIsNBError) - ? static_cast(err.trace.get()) - : static_cast(err.trace.get()) - ) {} - - ErrorBase( - unsigned int code_, - std::string msg_, - std::string type_, - const std::exception* trace_ - ) noexcept : - code(code_), - msg(msg_), - type(type_), - trace{ trace_ ? - std::static_pointer_cast( - std::make_shared>(*trace_)) - : nullptr, - }, - traceIsNBError(false) - {} - - template, bool> = true> - ErrorBase( - unsigned int code_, - std::string msg_, - std::string type_, - const T* trace_ - ) noexcept : - code(code_), - msg(msg_), - type(type_), - trace{trace_ ? trace_->make_shared() : nullptr}, - traceIsNBError(true) - {} -}; - - -template -class ErrorBase : public ErrorBase { -private: - using Base = ErrorBase; - void inline check_asserts() { - 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 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." - ); - } - -public: - template - ErrorBase(const ErrorBase& cpy) : Base(cpy) { check_asserts(); } - - virtual std::shared_ptr make_shared() const noexcept override { - return std::static_pointer_cast( - std::make_shared(*this) - ); - } - - virtual std::string what() const noexcept override { - std::string ret = msg; - if (trace) { - std::string trace_msg; - if (traceIsNBError) { - trace_msg = std::static_pointer_cast(trace)->what(); - } else { - trace_msg = std::string(std::static_pointer_cast(trace)->what()); - } - ret += nb::NEWLINE + indent_strblock( - trace_msg, - nb::TABOVER, - nb::TABOVER+"Trace: " - ); - } - return ret; - } - - static const std::string type; - static const ErrorCodeMap ErrorMessages; - - using Base::code; - using Base::msg; - using Base::trace; - using Base::traceIsNBError; - - friend ErrorType; - friend Error; - -protected: - using Base::Base; - - template - ErrorBase( - unsigned int code_, - std::string msg_, - std::string type_, - const T* trace_ - ) : Base( - code_, - msg_, - type_, - trace_ - ) { check_asserts(); } -}; -template -const std::string ErrorBase::type = ErrorType::type; -template -const ErrorCodeMap ErrorBase::ErrorMessages = ErrorType::ErrorMessages; - - -template -class Error : public ErrorBase { - using Base = ErrorBase; -public: - template - Error( - unsigned int code_, - const T& trace_ - ) noexcept : Base( - code_, - ErrorType::ErrorMessages.at(code_), - ErrorType::type, - &trace_ - ) {} - - template - Error( - std::string msg_, - const ErrorBase& trace_ - ) noexcept : Base( - 0, - msg_, - ErrorType::type, - &trace_ - ) {} - - Error( - std::string msg_, - const std::exception& trace_ - ) noexcept : Base( - 0, - msg_, - ErrorType::type, - &trace_ - ) {} - - Error(unsigned int code_) noexcept : Base( - code_, - ErrorType::ErrorMessages.at(code_), - ErrorType::type, - NULLPTR - ) {} - - Error(std::string msg_) noexcept : Base( - 0, - msg_, - ErrorType::type, - NULLPTR - ) {} - - using Base::what; - using Base::code; - using Base::msg; - using Base::trace; - using Base::traceIsNBError; - using Base::type; - using Base::ErrorMessages; - -protected: - using Base::Base; - -}; - - -template<> -class Error : public ErrorBase> { - using Base = ErrorBase>; -public: - using Base::Base; - - Error(unsigned int code_=1) noexcept : Base( - code_, - ErrorMessages.at(code_), - type, - NULLPTR - ) {} - - Error(const std::exception& err) : Base( - Codes::STANDARD, - std::string(err.what()), - "std::exception", - nullptr - ) {} - - Error(std::string msg_) noexcept : Base( - Codes::UNDEFINED, - msg_, - type, - NULLPTR - ) {} - - enum Codes : unsigned int { - STANDARD, UNDEFINED - }; - - using Base::what; - - using Base::code; - using Base::msg; - using Base::trace; - using Base::traceIsNBError; - static const std::string type; - static const ErrorCodeMap ErrorMessages; -}; -} // namespace nb - #ifdef _NB_AUTOLOG #ifdef _NB_CODE_ERROR_LOCATIONS #ifndef LOG @@ -303,10 +33,11 @@ public: #ifndef THROW #ifdef _NB_AUTOLOG - #define THROW(args...) ERROR(args); throw args + #define THROW(args...) ERROR(args); nb::logger.stop(); throw args #else #define THROW(args...) throw args #endif // _NB_CODE_ERROR_LOCATIONS #endif // THROW +} // namespace nb #endif // _NB_ERROR \ No newline at end of file diff --git a/engine/NBCore/ErrorsImpl.hpp b/engine/NBCore/ErrorsImpl.hpp new file mode 100644 index 0000000..c5b8589 --- /dev/null +++ b/engine/NBCore/ErrorsImpl.hpp @@ -0,0 +1,175 @@ +#pragma once +#ifndef _NB_ERRORS_IMPL +#define _NB_ERRORS_IMPL + +#include +#include +#include +#include +#include + +#include "StringUtils.hpp" +#include "TypeTraits.hpp" + +namespace nb { + +typedef std::unordered_map ErrorCodeMap; + +template +class Error; + +class ErrorBase { + protected: + + public: + const unsigned int code; + const std::string msg; + const std::string type; + const std::shared_ptr trace; + + ErrorBase(const ErrorBase&) = default; + ErrorBase(const std::exception&) noexcept; + virtual std::string what() const noexcept { + std::string ret = msg; + if (trace) { + std::string trace_msg = msg; + ret += nb::NEWLINE + indent_strblock( + trace_msg, + nb::TABOVER, + nb::TABOVER+"Trace: " + ); + } + return ret; + } + + protected: + ErrorBase( + unsigned int code_, + std::string msg_, + std::string type_, + std::shared_ptr trace_ +) noexcept : + code(code_), + msg(msg_), + type(type_), + trace{trace_} +{} +}; + +template +class Error : public ErrorBase { + private: + void inline check_asserts() { + static_assert(std::is_same::value, + "const std::unordered_map ErrorMessages must be " + "a class member." + ); + 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." + ); + } + + protected: + using ErrorBase::ErrorBase; + + public: + Error( + unsigned int code_, + const ErrorBase& trace_ + ) noexcept : ErrorBase( + code_, + ErrorType::ErrorMessages.at(code_), + ErrorType::type, + std::make_shared(trace_) + ) { check_asserts(); } + + Error( + std::string msg_, + const ErrorBase& trace_ + ) noexcept : ErrorBase( + 0, + msg_, + ErrorType::type, + std::make_shared(trace_) + ) { check_asserts(); } + + Error(unsigned int code_) noexcept : ErrorBase( + code_, + ErrorType::ErrorMessages.at(code_), + ErrorType::type, + nullptr + ) { check_asserts(); } + + Error(std::string msg_) noexcept : ErrorBase( + 0, + msg_, + ErrorType::type, + nullptr + ) { check_asserts(); } + + Error( + unsigned int code_, + const std::string& note_, + const ErrorBase& trace_ + ) noexcept : ErrorBase( + code_, + ErrorType::ErrorMessages.at(code_) + " (" + note_ + ")", + ErrorType::type, + std::make_shared(trace_) + ) { check_asserts(); } + + Error(unsigned int code_, const std::string& note_) noexcept : ErrorBase( + code_, + ErrorType::ErrorMessages.at(code_) + " (" + note_ + ")", + ErrorType::type, + nullptr + ) { check_asserts(); } + + using ErrorBase::what; + using ErrorBase::code; + using ErrorBase::msg; + using ErrorBase::trace; + using ErrorBase::type; +}; + + +template<> +class Error : public Error> { + using Base = Error>; + + public: + using Base::Base; + + Error(unsigned int code_=1) noexcept : Base(code_) {} + + Error(const std::exception& err) : Base( + Codes::STANDARD, + std::string(err.what()), + "std::exception", + nullptr + ) {} + + // fix + Error(std::string msg_) noexcept : Base( + Codes::UNDEFINED, + msg_ + ) {} + + enum Codes : unsigned int { + STANDARD, UNDEFINED + }; + + using Base::what; + using Base::code; + using Base::msg; + using Base::trace; + static const std::string type; + static const ErrorCodeMap ErrorMessages; +}; +} // namespace nb + +#endif // _NB_ERRORS_IMPL \ No newline at end of file diff --git a/engine/NBCore/Logger.hpp b/engine/NBCore/Logger.hpp index 2d64198..f4e79be 100644 --- a/engine/NBCore/Logger.hpp +++ b/engine/NBCore/Logger.hpp @@ -9,13 +9,13 @@ #include #include "DataSink.hpp" +#include "ErrorsImpl.hpp" #include "Processes.hpp" #include "ThreadSafeQueue.hpp" #include "TypeTraits.hpp" namespace nb { -template class ErrorBase; typedef std::chrono::time_point< @@ -32,7 +32,8 @@ class LoggerBase using StreamType = ST; using LoggerType = Logger; using Base = MultithreadedDataProcessor; -public: + + public: bool run() override { if (!static_cast(this)->isRunning()) { this->_running = true; @@ -45,7 +46,9 @@ public: } return static_cast(this)->isRunning(); } -protected: + using Base::flush; + + protected: LoggerBase() = default; StreamType _ostream; @@ -73,7 +76,33 @@ public: ~DebugLogger() { static_cast(this)->stop(); } + template void log( + U val, + std::string file="", + unsigned int line=0 + ) { static_cast(this)->write_message(val, 0x00, file, line); } + + template + void warn( + U val, + uint8_t lvl=0x01, + std::string file="", + unsigned int line=0 + ) { static_cast(this)->write_message(val, lvl, file, line); } + + void error( + const ErrorBase& val, + std::string file="", + unsigned int line=0 + ) { + static_cast(this)->write_message(val, 0xFF, file, line); + static_cast(this)->flush(); + } + + protected: + std::vector _ostream; + void write_message( std::string msg, uint8_t lvl=0x00, std::string file="", @@ -91,56 +120,24 @@ public: } template - void log( + void write_message( char const(&msg) [N], uint8_t lvl=0x00, std::string file="", unsigned int line=0 ) { - static_cast(this)->log(std::string(msg), lvl, file, line); + static_cast(this)->write_message(std::string(msg), lvl, file, line); } - template - void log( - const ErrorBase& err, - uint8_t lvl=0xFF, + void write_message( + const ErrorBase& err, + uint8_t lvl=0x00, std::string file="", unsigned int line=0 ) { - static_cast(this)->log(err.what(), lvl, file, line); + static_cast(this)->write_message(err.what(), lvl, file, line); } - template - std::enable_if_t, void> log( - const T& err, - uint8_t lvl=0xFF, - std::string file="", - unsigned int line=0 - ) { - static_cast(this)->log(std::string(err.what()), lvl, file, line); - } - - template - void warn( - U val, - uint8_t lvl=0x01, - std::string file="", - unsigned int line=0 - ) { static_cast(this)->log(val, lvl, file, line); } - - template - void error( - U val, - std::string file="", - unsigned int line=0 - ) { - static_cast(this)->log(val, 0xFF, file, line); - static_cast(this)->flush(); - } - -protected: - std::vector _ostream; - }; class DefaultDebugLogger : public DebugLogger { @@ -150,7 +147,7 @@ class DefaultDebugLogger : public DebugLogger { template struct LogRow; -public: + public: using Base::Base; ~DefaultDebugLogger() { stop(); } @@ -166,6 +163,8 @@ protected: bool process(const LogEvent& msg); }; +extern const bool LOGGER_RUNNING; + #ifndef _NB_NO_LOGGER extern DefaultDebugLogger logger; #endif // _NB_NO_LOGGER diff --git a/engine/NBCore/Utils.hpp b/engine/NBCore/Utils.hpp index b7a477d..76ae1ed 100644 --- a/engine/NBCore/Utils.hpp +++ b/engine/NBCore/Utils.hpp @@ -9,6 +9,12 @@ namespace nb { +template +using SharedVector = std::vector>; + +template +using RValueVector = std::vector; + using ByteVector = std::vector; class ObjectManagerError : public Error { @@ -25,6 +31,38 @@ class ObjectManagerError : public Error { static const ErrorCodeMap ErrorMessages; }; +template +ByteVector vectorToBytes(const std::vector& vec) { + unsigned int num_bytes = vec.size() * sizeof(T); + ByteVector ret(num_bytes); + memcpy(ret.data(), vec.data(), num_bytes); + return ret; +} + +template +ByteVector concatVectorBytes(const std::vector& vec1, const std::vector& vec2) { + ByteVector vec1_raw = vectorToBytes(vec1); + ByteVector vec2_raw = vectorToBytes(vec2); + unsigned int vec1_raw_size = vec1_raw.size(); + unsigned int vec2_raw_size = vec2_raw.size(); + ByteVector ret(vec1_raw_size + vec2_raw_size); + memcpy(ret.data(), vec1_raw.data(), vec1_raw_size); + memcpy(ret.data() + vec1_raw_size, vec2_raw.data(), vec2_raw_size); + return ret; +} + +template +std::vector bytesToVector(const ByteVector& vec) { + if (vec.size() % sizeof(T) != 0) { + THROW(std::runtime_error("Data size does not align to std::vector<" + std::string(typeid(T).name()) + ">.")); + } + unsigned int num_elmts = vec.size() / sizeof(T); + std::vector ret(num_elmts); + memcpy(ret.data(), vec.data(), vec.size()); + + return ret; +} + template class ThreadsafeObjectLock; diff --git a/engine/NBCore/src/Errors.cpp b/engine/NBCore/src/Errors.cpp deleted file mode 100644 index e5b22fa..0000000 --- a/engine/NBCore/src/Errors.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "Errors.hpp" -#include "TypeTraits.hpp" - -namespace nb { - -const std::string Error<>::type = "nb::Error"; - -const ErrorCodeMap Error::ErrorMessages = { - {Error::Codes::STANDARD, "std::exception"}, - {Error::Codes::UNDEFINED, "Error"} -}; - -} diff --git a/engine/NBCore/src/ErrorsImpl.cpp b/engine/NBCore/src/ErrorsImpl.cpp new file mode 100644 index 0000000..a36b110 --- /dev/null +++ b/engine/NBCore/src/ErrorsImpl.cpp @@ -0,0 +1,16 @@ +#include "ErrorsImpl.hpp" + +namespace nb { + +const std::string Error<>::type = "nb::Error"; +const ErrorCodeMap Error<>::ErrorMessages = { + {Error::Codes::STANDARD, "std::exception"}, + {Error::Codes::UNDEFINED, "Error"} +}; + +//ErrorBase:: + +ErrorBase::ErrorBase(const std::exception& exception_) noexcept +: ErrorBase(Error(exception_)) {} + +} diff --git a/engine/NBCore/src/Logger.cpp b/engine/NBCore/src/Logger.cpp index 8af8796..70c8ff8 100644 --- a/engine/NBCore/src/Logger.cpp +++ b/engine/NBCore/src/Logger.cpp @@ -33,6 +33,6 @@ static bool RUN_LOGGER(nb::DefaultDebugLogger& log) { return log.run(); } -static const bool LOGGER_RUNNING = RUN_LOGGER(logger); +const bool LOGGER_RUNNING = RUN_LOGGER(logger); } // namespace nb \ No newline at end of file