Made some changes to logger and picked a new direction to chase smart text concept

This commit is contained in:
NaifBanana 2025-12-27 03:24:20 -06:00
parent d2102e320a
commit 6134a66c71
7 changed files with 237 additions and 133 deletions

View File

@ -8,13 +8,21 @@
#include <type_traits>
#include <unordered_map>
#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<Error>::ErrorBase;
//Error(unsigned int code) : ErrorBase<Error>(code, ErrorBase<Error>::lookup(code)) {}
//Error(unsigned int code, const std::exception& trace, unsigned int line=0, const std::string& filename="")
// : ErrorBase<Error>(code, ErrorBase<Error>::lookup(code), trace, line, filename) {}
friend ErrorBase<Error>;
@ -117,18 +122,6 @@ protected:
};
/*
template<class ErrorType>
ErrorBase<ErrorType>::ErrorBase(
unsigned int code,
std::string msg,
const std::exception& trace,
unsigned int line,
std::string filename
) noexcept
: ErrorBase<ErrorType>(code, msg, std::make_shared<Error>(trace), line, filename) {}
*/
template<class ErrorType>
std::string ErrorBase<ErrorType>::lookup(unsigned int code) {
for (auto kv : ErrorType::ErrorMessages) {

View File

@ -2,12 +2,12 @@
#ifndef _NB_LOGGER
#define _NB_LOGGER
#include <atomic>
#include <chrono>
#include <ostream>
#include <thread>
#include <unordered_map>
#include "SmartStreams.hpp"
#include "ThreadSafeQueue.hpp"
namespace nb {
@ -23,42 +23,111 @@ struct LogEvent{
const std::string msg;
};
template<typename T>
class Logger {
typedef std::string (*LogProcessFunction)(const LoggerTimePoint&, const std::string&);
typedef std::unordered_map<uint8_t, LogProcessFunction> LogProcessFunctionMap;
typedef std::unordered_map<uint8_t, LogProcessFunction> LogProcessFunctionMap;
template<typename StreamType>
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<LogEvent> _queue;
T* _ostream;
// std::condition_variable _cond;
// mutable std::mutex _mutex;
mutable std::mutex _runningMutex;
bool _running;
StreamType* const _ostream;
std::atomic<bool> _running;
std::shared_ptr<std::thread> _runningThread = nullptr;
};
template <typename ST>
const LogProcessFunctionMap Logger<ST>::_function_map = {
{0, [](const LoggerTimePoint& tp, const std::string& msg){
return msg;
}}
};
template <typename ST>
bool Logger<ST>::isRunning() const {
return _running && bool(_runningThread);
}
template <typename ST>
unsigned int Logger<ST>::count() const {
return _queue.size();
}
template <typename ST>
bool Logger<ST>::run() {
if (!isRunning()) {
_runningThread = std::make_shared<std::thread>([&]{
while(this->isRunning()) {
this->flush();
}
});
}
return isRunning();
}
template <typename ST>
bool Logger<ST>::stop() {
if (isRunning()) {
_running = false;
_runningThread->join();
_runningThread = nullptr;
flush();
}
return isRunning();
}
template <typename ST>
LogEvent Logger<ST>::pop() {
std::shared_ptr<LogEvent> event;
_queue.pop(event);
process(*event);
return *event;
}
} // namespace nb
#endif // _NB_LOGGER

92
include/SmartStreams.hpp Normal file
View File

@ -0,0 +1,92 @@
#pragma once
#ifndef _NB_SMARTSTREAM
#define _NB_SMARTSTREAM
#include <array>
#include <iostream>
#include <string>
#include <type_traits>
#include <unordered_map>
namespace nb {
using RGB = std::array<unsigned char, 3>;
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 <typename U, typename Derived=void>
struct SmartText {
SmartText(const U& val) : msg(val) {}
const U msg;
template<typename C, typename T>
void process(std::basic_ostream<C,T>& stream) const;
};
template <typename Derived>
struct SmartText<std::string, Derived> {
template <std::size_t N>
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<typename C, typename T>
void process(std::basic_ostream<C,T>& stream) const;
};
template <typename U, typename Derived>
template <typename C, typename T>
void SmartText<U,Derived>::process(std::basic_ostream<C,T>& stream) const {
if (std::is_void<Derived>::value) {
stream << msg;
} else {
static_cast<Derived*>(this)->process(stream);
}
}
template<typename C, typename T, typename U, typename D>
std::basic_ostream<C, T>& operator<<(std::basic_ostream<C, T>& stream, const SmartText<U,D>& smt) {
if (std::is_void<D>::value) {
stream << smt.msg;
} else {
static_cast<const D*>(&smt)->process(stream);
}
return stream;
}
template <typename U>
struct TerminalColor : public SmartText<U, TerminalColor<U>> {
typedef SmartText<U, TerminalColor<U>> 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 <typename C, typename T>
void process(std::basic_ostream<C, T>& stream) const {
if (&stream == &std::cout) {
stream << colorSequence << msg << "\x1b[0m";
} else {
stream << msg;
}
}
};
}
#endif // _NB_SMARTSTREAM

View File

@ -1,87 +0,0 @@
#include "Logger.hpp"
namespace nb {
template<typename T>
bool Logger<>::isRunning() const {
std::lock_guard<std::mutex> lock(_runningMutex);
return _running;
}
unsigned int Logger::count() const {
return _queue.size();
}
bool Logger::run() {
std::lock_guard<std::mutex> lock(_runningMutex);
if (!_running) {
_runningThread = std::make_shared<std::thread>([&]{
while(this->_running) {
this->flush();
}
});
}
return _running;
}
bool Logger::stop() {
std::lock_guard<std::mutex> 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<LogEvent> event;
_queue.pop(event);
process(*event);
return *event;
}
LogEvent Logger::popDelete() {
std::shared_ptr<LogEvent> 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);
}
}

View File

@ -2,6 +2,7 @@
#include "Errors.hpp"
#include <iostream>
#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;

View File

@ -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)

View File

@ -0,0 +1,25 @@
#include <exception>
#include <iostream>
#include <fstream>
#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;
}