From 6134a66c71d2d94e7acc48b973fee9a721e9b1fc Mon Sep 17 00:00:00 2001 From: NaifBanana <30419422+NaifBanana@users.noreply.github.com> Date: Sat, 27 Dec 2025 03:24:20 -0600 Subject: [PATCH] Made some changes to logger and picked a new direction to chase smart text concept --- include/Errors.hpp | 39 ++++----- include/Logger.hpp | 113 +++++++++++++++++++++------ include/SmartStreams.hpp | 92 ++++++++++++++++++++++ src/NBCoreUtils/Logger.cpp | 87 --------------------- tests/ErrorTest/main.cpp | 9 ++- tests/SmartStreamTest/CMakeLists.txt | 5 ++ tests/SmartStreamTest/main.cpp | 25 ++++++ 7 files changed, 237 insertions(+), 133 deletions(-) create mode 100644 include/SmartStreams.hpp delete mode 100644 src/NBCoreUtils/Logger.cpp create mode 100644 tests/SmartStreamTest/CMakeLists.txt create mode 100644 tests/SmartStreamTest/main.cpp diff --git a/include/Errors.hpp b/include/Errors.hpp index 7ba07f0..a893b9b 100644 --- a/include/Errors.hpp +++ b/include/Errors.hpp @@ -8,13 +8,21 @@ #include #include +#ifndef THROW_WITH_INFO + #ifdef CODE_ERROR_LOCATIONS + #define THROW_WITH_INFO(type, ...) throw type(__VA_ARGS__, __LINE__, __FILE__) + #else + #define THROW_WITH_INFO(type, ...) throw type(__VA_ARGS__) + #endif // CODE_ERROR_LOCATIONS +#endif // THROW_WITH_INFO + #ifndef THROW -#ifdef CODE_ERROR_LOCATIONS -#define THROW(type, ...) throw type(__VA_ARGS__, __LINE__, __FILE__) -#else -#define THROW(type, ...) throw type(__VA_ARGS__) -#endif -#endif + #ifdef LOGGING + #define THROW_WTIH_INFO(type, ...) throw type(__VA_ARGS__, __LINE__, __FILE__) + #else + #define THROW(...) THROW_WITH_INFO(__VA_ARGS__) + #endif // LOGGING +#endif // THROW namespace nb { @@ -73,7 +81,7 @@ protected: ); _msg += std::string(ErrorType::type); - _msg += "." + std::to_string(_code); + _msg += "[" + std::to_string(_code) + "]"; if (line && filename.size()) { _msg += " in \'" + filename + "\':" + std::to_string(line); } @@ -91,7 +99,7 @@ protected: 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; + _msg += "\n Trace - " + what_msg; } unsigned int _code; @@ -105,9 +113,6 @@ public: }; using ErrorBase::ErrorBase; - //Error(unsigned int code) : ErrorBase(code, ErrorBase::lookup(code)) {} - //Error(unsigned int code, const std::exception& trace, unsigned int line=0, const std::string& filename="") - // : ErrorBase(code, ErrorBase::lookup(code), trace, line, filename) {} friend ErrorBase; @@ -117,18 +122,6 @@ protected: }; -/* -template -ErrorBase::ErrorBase( - unsigned int code, - std::string msg, - const std::exception& trace, - unsigned int line, - std::string filename -) noexcept - : ErrorBase(code, msg, std::make_shared(trace), line, filename) {} - */ - template std::string ErrorBase::lookup(unsigned int code) { for (auto kv : ErrorType::ErrorMessages) { diff --git a/include/Logger.hpp b/include/Logger.hpp index a551107..09608b3 100644 --- a/include/Logger.hpp +++ b/include/Logger.hpp @@ -2,12 +2,12 @@ #ifndef _NB_LOGGER #define _NB_LOGGER +#include #include #include #include #include -#include "SmartStreams.hpp" #include "ThreadSafeQueue.hpp" namespace nb { @@ -23,42 +23,111 @@ struct LogEvent{ const std::string msg; }; -template -class Logger { typedef std::string (*LogProcessFunction)(const LoggerTimePoint&, const std::string&); -typedef std::unordered_map LogProcessFunctionMap; +typedef std::unordered_map LogProcessFunctionMap; + +template +class Logger { public: - Logger(); + Logger(StreamType& stream) : _ostream(&stream) {} bool isRunning() const; unsigned int count() const; bool run(); bool stop(); - LogEvent popProcess(); - LogEvent popDelete(); - void flush(); - void deleteAll(); - void msg(const std::string&, uint8_t lvl=0); - void warn(const std::string&, uint8_t lvl=1); - void warn(const std::exception&, uint8_t lvl=1); - void error(const std::string&, uint8_t lvl=0xFF); - void error(const std::exception&, uint8_t lvl=0xFF); + LogEvent pop(); + void flush() { + while(_queue.size()) { + pop(); + } + } + void deleteAll() { + _queue.empty(); + } + void msg(const std::string& _msg, uint8_t lvl=0) { + _queue.push(LogEvent{std::chrono::system_clock::now(), lvl, _msg}); + } + void warn(const std::string& _msg, uint8_t lvl=1) { + msg(_msg, lvl); + } + void warn(const std::exception& _err, uint8_t lvl=1) { + msg(_err.what(), lvl); + } + void error(const std::string& _msg, uint8_t lvl=0xFF) { + msg(_msg, lvl); + } + void error(const std::exception& _err, uint8_t lvl=0xFF) { + msg(_err.what(), lvl); + } - protected: - virtual void process(const LogEvent&); + virtual void process(const LogEvent& event) { + uint8_t lvl = event.lvl; + try { + *_ostream << _function_map.at(lvl)(event.time, event.msg).c_str(); + } catch (std::out_of_range e) { + *_ostream << _function_map.at(0)(event.time, event.msg).c_str(); + //*_ostream << event.msg; + } + *_ostream << "\n"; + } - const LogProcessFunctionMap _function_map; + static const LogProcessFunctionMap _function_map; ThreadsafeQueue _queue; - T* _ostream; - // std::condition_variable _cond; - // mutable std::mutex _mutex; - mutable std::mutex _runningMutex; - bool _running; + StreamType* const _ostream; + std::atomic _running; std::shared_ptr _runningThread = nullptr; }; +template +const LogProcessFunctionMap Logger::_function_map = { + {0, [](const LoggerTimePoint& tp, const std::string& msg){ + return msg; + }} +}; + +template +bool Logger::isRunning() const { + return _running && bool(_runningThread); +} + +template +unsigned int Logger::count() const { + return _queue.size(); +} + +template +bool Logger::run() { + if (!isRunning()) { + _runningThread = std::make_shared([&]{ + while(this->isRunning()) { + this->flush(); + } + }); + } + return isRunning(); +} + +template +bool Logger::stop() { + if (isRunning()) { + _running = false; + _runningThread->join(); + _runningThread = nullptr; + flush(); + } + return isRunning(); +} + +template +LogEvent Logger::pop() { + std::shared_ptr event; + _queue.pop(event); + process(*event); + return *event; +} + } // namespace nb #endif // _NB_LOGGER \ No newline at end of file diff --git a/include/SmartStreams.hpp b/include/SmartStreams.hpp new file mode 100644 index 0000000..e5fcd14 --- /dev/null +++ b/include/SmartStreams.hpp @@ -0,0 +1,92 @@ +#pragma once +#ifndef _NB_SMARTSTREAM +#define _NB_SMARTSTREAM + +#include +#include +#include +#include +#include + +namespace nb { + +using RGB = std::array; + +std::string toANSI(const RGB& color) { + return "\x1b[38;2;"+std::to_string(color[0])+";"+std::to_string(color[1])+ + ";"+std::to_string(color[2])+"m"; +} + +std::string toANSI(const unsigned int& color) { + return "\x1b[38;5;"+std::to_string(color)+"m"; +} + +template +struct SmartText { + SmartText(const U& val) : msg(val) {} + + const U msg; + + template + void process(std::basic_ostream& stream) const; +}; + +template +struct SmartText { + template + SmartText(char const(&val) [N]) : msg(val) {} + SmartText(const std::string& val) : msg(val) {} + SmartText(const char* val) : msg(val) {} + + const std::string msg; + + template + void process(std::basic_ostream& stream) const; +}; + +template +template +void SmartText::process(std::basic_ostream& stream) const { + if (std::is_void::value) { + stream << msg; + } else { + static_cast(this)->process(stream); + } +} + +template +std::basic_ostream& operator<<(std::basic_ostream& stream, const SmartText& smt) { + if (std::is_void::value) { + stream << smt.msg; + } else { + static_cast(&smt)->process(stream); + } + return stream; +} + +template +struct TerminalColor : public SmartText> { + typedef SmartText> Base; + using Base::msg; + + explicit TerminalColor(unsigned int color, const U& val) + : Base(val), colorSequence(toANSI(color)) { } + explicit TerminalColor(const RGB& color, const U& val) + : Base(val), colorSequence(toANSI(color)) { } + + const std::string colorSequence; + + template + void process(std::basic_ostream& stream) const { + if (&stream == &std::cout) { + stream << colorSequence << msg << "\x1b[0m"; + } else { + stream << msg; + } + } +}; + + +} + +#endif // _NB_SMARTSTREAM \ No newline at end of file diff --git a/src/NBCoreUtils/Logger.cpp b/src/NBCoreUtils/Logger.cpp deleted file mode 100644 index e6ba3fb..0000000 --- a/src/NBCoreUtils/Logger.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "Logger.hpp" - -namespace nb { - -template -bool Logger<>::isRunning() const { - std::lock_guard lock(_runningMutex); - return _running; -} - -unsigned int Logger::count() const { - return _queue.size(); -} - -bool Logger::run() { - std::lock_guard lock(_runningMutex); - if (!_running) { - _runningThread = std::make_shared([&]{ - while(this->_running) { - this->flush(); - } - }); - } - return _running; -} - -bool Logger::stop() { - std::lock_guard lock(_runningMutex); - _running = false; - _runningThread->join(); - return _running; -} - -void Logger::process(const LogEvent& event) { - uint8_t lvl = event.lvl; - try { - _ostream << _function_map.at(lvl)(event.time, event.msg).c_str(); - } catch (std::out_of_range e) { - _ostream << _function_map[0](event.time, event.msg).c_str(); - } -} - -LogEvent Logger::popProcess() { - std::shared_ptr event; - _queue.pop(event); - process(*event); - return *event; -} - -LogEvent Logger::popDelete() { - std::shared_ptr event; - _queue.pop(event); - process(*event); - return *event; -} - -void Logger::flush() { - while(_queue.size()) { - popProcess(); - } -} - -void Logger::deleteAll() { - _queue.empty(); -} - -void Logger::msg(const std::string& _msg, uint8_t lvl) { - _queue.push(LogEvent{std::chrono::system_clock::now(), lvl, _msg}); -} - -void Logger::warn(const std::string& _msg, uint8_t lvl) { - msg(_msg, lvl); -} - -void Logger::warn(const std::exception& _err, uint8_t lvl) { - msg(_err.what(), lvl); -} - -void Logger::error(const std::string& _msg, uint8_t lvl) { - msg(_msg, lvl); -} - -void Logger::error(const std::exception& _err, uint8_t lvl) { - msg(_err.what(), lvl); -} - -} diff --git a/tests/ErrorTest/main.cpp b/tests/ErrorTest/main.cpp index ef71f51..7b0885b 100644 --- a/tests/ErrorTest/main.cpp +++ b/tests/ErrorTest/main.cpp @@ -2,6 +2,7 @@ #include "Errors.hpp" #include +#include "Logger.hpp" using namespace nb; @@ -40,7 +41,13 @@ int main() { THROW(TestError, TestError::ErrorCodes::A, e); } } catch(const std::exception& e) { - THROW(Error, Error::ErrorCodes::UNDEFINED, e); + // THROW(Error, Error::ErrorCodes::UNDEFINED, e); + Logger log(std::cout); + std::cout << "Logger is starting: " << log.run() << std::endl; + std::cout << "Logger is running: " << log.isRunning() << std::endl; + log.error(e); + log.stop(); + std::cout << "Logger is running: " << log.isRunning() << std::endl; } return 0; diff --git a/tests/SmartStreamTest/CMakeLists.txt b/tests/SmartStreamTest/CMakeLists.txt new file mode 100644 index 0000000..5aca423 --- /dev/null +++ b/tests/SmartStreamTest/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.26.0) +project(gtest_Graphics VERSION 0.1.0 LANGUAGES C CXX) + +add_executable(SmartStreamTest main.cpp) +target_link_libraries(SmartStreamTest NBCore) \ No newline at end of file diff --git a/tests/SmartStreamTest/main.cpp b/tests/SmartStreamTest/main.cpp new file mode 100644 index 0000000..35608cf --- /dev/null +++ b/tests/SmartStreamTest/main.cpp @@ -0,0 +1,25 @@ + +#include +#include +#include + + +#include "SmartStreams.hpp" + + + +int main() { + + auto test = nb::TerminalColor(9, 2030); + + std::cout << test; + + std::ofstream file; + file.open("test.txt"); + if (file.is_open()) { + file << test; + } + file.close(); + + return 0; +} \ No newline at end of file