Adds the sdi_toolBox library (temporary version)
This commit is contained in:
531
sdi_toolBox_1.0.x/toolBox/sdi_toolBox/logs/reLog.h
Normal file
531
sdi_toolBox_1.0.x/toolBox/sdi_toolBox/logs/reLog.h
Normal file
@@ -0,0 +1,531 @@
|
||||
/*
|
||||
{{copyright}}
|
||||
*/
|
||||
|
||||
/*
|
||||
{{version}}
|
||||
*/
|
||||
|
||||
/*
|
||||
{{license}}
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../console/ansi.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN // Disable windows mess
|
||||
# endif
|
||||
# ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# include <Windows.h>
|
||||
# undef GetMessage // To avoid conflict with other libraries
|
||||
#endif
|
||||
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <source_location>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
/*
|
||||
* Usage :
|
||||
*
|
||||
* {
|
||||
* int value = 42;
|
||||
* std::string user = "Alice";
|
||||
*
|
||||
* // Usage example:
|
||||
* LogMessage() << "System ready" << std::endl;
|
||||
* LogDebug() << "Checking configuration file..." << std::endl;
|
||||
* LogInfo() << "User " << user << " logged in. (Value: " << value << ")" << std::endl;
|
||||
* LogWarning() << "Device connection lost..." << std::endl;
|
||||
* LogError() << "Failed to connect to server on port " << 8080 << "!" << std::endl;
|
||||
* LogComm() << "<< 0123456789" << std::endl;
|
||||
* LogDev() << "<< 0123456789" << std::endl;
|
||||
* }
|
||||
*/
|
||||
|
||||
namespace sdi_toolBox::logs
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
enum class LogLevel : uint8_t
|
||||
{
|
||||
None,
|
||||
Dev,
|
||||
Comm,
|
||||
Debug,
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
Message,
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------
|
||||
class ReLog
|
||||
{
|
||||
public:
|
||||
struct Log
|
||||
{
|
||||
LogLevel level;
|
||||
std::chrono::system_clock::time_point timestamp;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
using ColorLogMap = std::map<LogLevel, std::string>;
|
||||
using VisibleLogMap = std::map<LogLevel, bool>;
|
||||
static VisibleLogMap getVisibleLogMap(); // Return the map of visible log messages
|
||||
static void setVisibleLogMap(const VisibleLogMap &logMap); // Define the map of visible log messages
|
||||
|
||||
static ReLog &systemInit(const std::filesystem::path &filepath = ""); // Initialize log system
|
||||
static ReLog &getInstance(); // Gets singleton instance
|
||||
|
||||
public:
|
||||
virtual ~ReLog() = default; // Default destructor
|
||||
ReLog(const ReLog &obj) = delete; // Copy constructor
|
||||
ReLog(ReLog &&obj) noexcept = delete; // Move constructor
|
||||
ReLog &operator=(const ReLog &obj) = delete; // Copy assignment operator
|
||||
ReLog &operator=(ReLog &&obj) noexcept = delete; // Move assignment operator
|
||||
|
||||
void openFile(const std::filesystem::path &filepath); // Open or create log file
|
||||
void closeFile(); // Close log file
|
||||
|
||||
void log(const Log &log); // Core log method
|
||||
|
||||
void printColorTest() const; // Print the different configurations and colors on the terminal
|
||||
|
||||
protected:
|
||||
ReLog(); // Default constructor
|
||||
|
||||
bool m_vtModeEnabled = false;
|
||||
|
||||
std::mutex m_mtx;
|
||||
std::ofstream m_file;
|
||||
|
||||
static inline ColorLogMap m_colorLogMap;
|
||||
static inline VisibleLogMap m_visibleLogMap;
|
||||
|
||||
private:
|
||||
void enableVTMode();
|
||||
|
||||
static void init(); // Settings initialization
|
||||
|
||||
static std::string createLogMessage(const Log &log, const bool isFile = false); // Print log messages
|
||||
void printDate();
|
||||
|
||||
void saveToFile(const std::string &message); // Save log messages in file
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
|
||||
/* --- */
|
||||
|
||||
//--------------------------------------------------------------
|
||||
/* Return the map of visible log messages */
|
||||
inline ReLog::VisibleLogMap ReLog::getVisibleLogMap()
|
||||
{
|
||||
return m_visibleLogMap;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Define the map of visible log messages */
|
||||
inline void ReLog::setVisibleLogMap(const VisibleLogMap &logMap)
|
||||
{
|
||||
m_visibleLogMap = logMap;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Initialize log system */
|
||||
inline ReLog &ReLog::systemInit(const std::filesystem::path &filepath)
|
||||
{
|
||||
auto &logSystem = getInstance();
|
||||
|
||||
// Post initialization
|
||||
if (!filepath.empty())
|
||||
logSystem.openFile(filepath);
|
||||
logSystem.printDate();
|
||||
return logSystem;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Gets singleton instance */
|
||||
inline ReLog &ReLog::getInstance()
|
||||
{
|
||||
static ReLog instance;
|
||||
return instance;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Constructor */
|
||||
inline ReLog::ReLog()
|
||||
{
|
||||
// Initialization
|
||||
init();
|
||||
enableVTMode();
|
||||
|
||||
// Test on debug mode
|
||||
#ifdef DEBUG
|
||||
// printColorTest();
|
||||
#endif
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Open or create log file */
|
||||
inline void ReLog::openFile(const std::filesystem::path &filepath)
|
||||
{
|
||||
std::lock_guard lock(m_mtx);
|
||||
|
||||
m_file = std::ofstream(filepath, std::ofstream::out | std::ofstream::app | std::ofstream::binary);
|
||||
if (!m_file)
|
||||
throw std::runtime_error("unable to open log file");
|
||||
m_file << "\n-----------------------------------------------------------------" << std::endl;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Close log file */
|
||||
inline void ReLog::closeFile()
|
||||
{
|
||||
std::lock_guard lock(m_mtx);
|
||||
|
||||
if (m_file.is_open())
|
||||
m_file.close();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Core log method */
|
||||
inline void ReLog::log(const Log &log)
|
||||
{
|
||||
std::lock_guard lock(m_mtx);
|
||||
|
||||
const auto termMessage = createLogMessage(log);
|
||||
if (!termMessage.empty())
|
||||
{
|
||||
if (log.level == LogLevel::Error)
|
||||
std::cerr << termMessage << std::endl;
|
||||
else
|
||||
std::cout << termMessage << std::endl;
|
||||
}
|
||||
|
||||
const auto fileMessage = createLogMessage(log, true);
|
||||
if (!fileMessage.empty())
|
||||
saveToFile(fileMessage);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Print the different configurations and colors on the terminal */
|
||||
inline void ReLog::printColorTest() const
|
||||
{
|
||||
const auto coutTest = [&](const auto &color, const std::string &label)
|
||||
{
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, sdi_toolBox::console::ANSI::EscapeCommand::UNDERLINE) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, sdi_toolBox::console::ANSI::EscapeCommand::DIM | sdi_toolBox::console::ANSI::EscapeCommand::UNDERLINE) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, sdi_toolBox::console::ANSI::EscapeCommand::LIGHT | sdi_toolBox::console::ANSI::EscapeCommand::UNDERLINE) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, sdi_toolBox::console::ANSI::EscapeCommand::LIGHT) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, sdi_toolBox::console::ANSI::EscapeCommand::BLINK) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, sdi_toolBox::console::ANSI::EscapeCommand::BRIGHT) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, sdi_toolBox::console::ANSI::EscapeCommand::DIM) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, sdi_toolBox::console::ANSI::EscapeCommand::REVERSE) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << " | ";
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::Black) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::Red) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::Green) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::Yellow) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::Blue) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::Magenta) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::Cyan) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::White) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << " | ";
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::Black, sdi_toolBox::console::ANSI::EscapeCommand::LIGHT) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::Red, sdi_toolBox::console::ANSI::EscapeCommand::LIGHT) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::Green, sdi_toolBox::console::ANSI::EscapeCommand::LIGHT) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::Yellow, sdi_toolBox::console::ANSI::EscapeCommand::LIGHT) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::Blue, sdi_toolBox::console::ANSI::EscapeCommand::LIGHT) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::Magenta, sdi_toolBox::console::ANSI::EscapeCommand::LIGHT) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::Cyan, sdi_toolBox::console::ANSI::EscapeCommand::LIGHT) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << sdi_toolBox::console::ANSI::EscapeCommand::get(color, 0, sdi_toolBox::console::ANSI::EscapeCommand::Color::White, sdi_toolBox::console::ANSI::EscapeCommand::LIGHT) << label << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
std::cout << std::endl;
|
||||
};
|
||||
coutTest(sdi_toolBox::console::ANSI::EscapeCommand::Color::Black, " B ");
|
||||
coutTest(sdi_toolBox::console::ANSI::EscapeCommand::Color::Red, " R ");
|
||||
coutTest(sdi_toolBox::console::ANSI::EscapeCommand::Color::Green, " G ");
|
||||
coutTest(sdi_toolBox::console::ANSI::EscapeCommand::Color::Yellow, " Y ");
|
||||
coutTest(sdi_toolBox::console::ANSI::EscapeCommand::Color::Blue, " B ");
|
||||
coutTest(sdi_toolBox::console::ANSI::EscapeCommand::Color::Magenta, " M ");
|
||||
coutTest(sdi_toolBox::console::ANSI::EscapeCommand::Color::Cyan, " C ");
|
||||
coutTest(sdi_toolBox::console::ANSI::EscapeCommand::Color::White, " W ");
|
||||
std::cout << std::endl;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
inline void ReLog::enableVTMode()
|
||||
{
|
||||
if (m_vtModeEnabled)
|
||||
return;
|
||||
|
||||
m_vtModeEnabled = false;
|
||||
|
||||
// 1. Get the handle to the standard output
|
||||
const HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (hOut == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
// 2. Get the current console mode
|
||||
DWORD dwMode = 0;
|
||||
if (!GetConsoleMode(hOut, &dwMode))
|
||||
return;
|
||||
|
||||
// 3. Set the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag (using bitwise OR)
|
||||
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
|
||||
// 4. Apply the new console mode
|
||||
if (!SetConsoleMode(hOut, dwMode)) // This is often the point of failure on older Windows versions (pre-Win10 v1511)
|
||||
return;
|
||||
|
||||
m_vtModeEnabled = true;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Settings initialization */
|
||||
inline void ReLog::init()
|
||||
{
|
||||
m_colorLogMap[LogLevel::None] = sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
m_colorLogMap[LogLevel::Dev] = sdi_toolBox::console::ANSI::EscapeCommand::get(sdi_toolBox::console::ANSI::EscapeCommand::Color::Green, sdi_toolBox::console::ANSI::EscapeCommand::DIM);
|
||||
m_colorLogMap[LogLevel::Comm] = sdi_toolBox::console::ANSI::EscapeCommand::get(sdi_toolBox::console::ANSI::EscapeCommand::Color::Magenta);
|
||||
m_colorLogMap[LogLevel::Debug] = sdi_toolBox::console::ANSI::EscapeCommand::get(sdi_toolBox::console::ANSI::EscapeCommand::Color::Yellow, sdi_toolBox::console::ANSI::EscapeCommand::DIM);
|
||||
m_colorLogMap[LogLevel::Info] = sdi_toolBox::console::ANSI::EscapeCommand::get(sdi_toolBox::console::ANSI::EscapeCommand::Color::White);
|
||||
m_colorLogMap[LogLevel::Warning] = sdi_toolBox::console::ANSI::EscapeCommand::get(sdi_toolBox::console::ANSI::EscapeCommand::Color::Yellow);
|
||||
m_colorLogMap[LogLevel::Error] = sdi_toolBox::console::ANSI::EscapeCommand::get(sdi_toolBox::console::ANSI::EscapeCommand::Color::Red, sdi_toolBox::console::ANSI::EscapeCommand::LIGHT | sdi_toolBox::console::ANSI::EscapeCommand::BRIGHT);
|
||||
m_colorLogMap[LogLevel::Message] = sdi_toolBox::console::ANSI::EscapeCommand::get(sdi_toolBox::console::ANSI::EscapeCommand::Color::White, sdi_toolBox::console::ANSI::EscapeCommand::LIGHT);
|
||||
|
||||
m_visibleLogMap[LogLevel::Dev] = true;
|
||||
m_visibleLogMap[LogLevel::Comm] = true;
|
||||
m_visibleLogMap[LogLevel::Debug] = true;
|
||||
m_visibleLogMap[LogLevel::Info] = true;
|
||||
m_visibleLogMap[LogLevel::Warning] = true;
|
||||
m_visibleLogMap[LogLevel::Error] = true;
|
||||
m_visibleLogMap[LogLevel::Message] = true;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Print log messages */
|
||||
inline std::string ReLog::createLogMessage(const Log &log, const bool isFile)
|
||||
{
|
||||
// Check if the message should be visible or not
|
||||
if (m_visibleLogMap.contains(log.level) && m_visibleLogMap[log.level] == false)
|
||||
return "";
|
||||
|
||||
std::ostringstream stream;
|
||||
|
||||
// Prepare message color
|
||||
const auto levelStyle = (m_colorLogMap.contains(log.level)) ? m_colorLogMap[log.level] : sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
const auto messageStyle = (!isFile) ? levelStyle : "";
|
||||
|
||||
if (!log.message.empty())
|
||||
{
|
||||
switch (log.level)
|
||||
{
|
||||
case LogLevel::Error:
|
||||
stream << messageStyle << "[E] ";
|
||||
break;
|
||||
case LogLevel::Warning:
|
||||
stream << messageStyle << "[W] ";
|
||||
break;
|
||||
case LogLevel::Info:
|
||||
stream << messageStyle << "[I] ";
|
||||
break;
|
||||
case LogLevel::Debug:
|
||||
stream << messageStyle << "[D] ";
|
||||
break;
|
||||
case LogLevel::Comm:
|
||||
stream << messageStyle << "[C] ";
|
||||
break;
|
||||
case LogLevel::Dev:
|
||||
stream << messageStyle << "[-] ";
|
||||
break;
|
||||
case LogLevel::Message:
|
||||
default:;
|
||||
stream << messageStyle;
|
||||
break;
|
||||
}
|
||||
|
||||
if (log.level != LogLevel::Message)
|
||||
{
|
||||
const auto local_tz = std::chrono::current_zone();
|
||||
const auto local_time = std::chrono::zoned_time(local_tz, log.timestamp);
|
||||
stream << std::format("{0:%T} - ", local_time);
|
||||
}
|
||||
}
|
||||
|
||||
// Print message
|
||||
stream << log.message;
|
||||
|
||||
// Reset style
|
||||
if (!messageStyle.empty())
|
||||
stream << sdi_toolBox::console::ANSI::EscapeCommand::clear();
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
inline void ReLog::printDate()
|
||||
{
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
const auto local_tz = std::chrono::current_zone();
|
||||
const auto local_time = std::chrono::zoned_time(local_tz, now);
|
||||
|
||||
const Log logMessage{ .level = LogLevel::Info,
|
||||
.timestamp = now,
|
||||
.message = std::format("current date: {0:%F}", local_time) };
|
||||
log(logMessage);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Save log messages in file */
|
||||
inline void ReLog::saveToFile(const std::string &message)
|
||||
{
|
||||
// Remove escape sequences
|
||||
std::string messageResult;
|
||||
bool in_escape_sequence = false;
|
||||
|
||||
constexpr char ANSI_ESCAPE_CHAR = '\x1b';
|
||||
for (const char c : message)
|
||||
{
|
||||
if (in_escape_sequence)
|
||||
{
|
||||
if (c == 'm')
|
||||
in_escape_sequence = false; // End of the escape sequence
|
||||
}
|
||||
else if (c == ANSI_ESCAPE_CHAR)
|
||||
in_escape_sequence = true; // Begin of the escape sequence
|
||||
else
|
||||
messageResult += c;
|
||||
}
|
||||
|
||||
if (m_file.is_open())
|
||||
m_file << messageResult << "\n";
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
|
||||
/* --- */
|
||||
|
||||
//--------------------------------------------------------------
|
||||
class ReLogStreamProxy
|
||||
{
|
||||
public:
|
||||
ReLogStreamProxy() = delete; // Constructor
|
||||
explicit ReLogStreamProxy(const LogLevel &level); // Constructor
|
||||
virtual ~ReLogStreamProxy(); // Destructor
|
||||
ReLogStreamProxy(ReLogStreamProxy &obj) = delete; // Copy constructor
|
||||
ReLogStreamProxy(ReLogStreamProxy &&obj) = delete; // Move constructor
|
||||
ReLogStreamProxy &operator=(const ReLogStreamProxy &obj) = delete; // Copy assignment operator
|
||||
ReLogStreamProxy &operator=(ReLogStreamProxy &&obj) = delete; // Move assignment operator
|
||||
|
||||
template<typename T>
|
||||
ReLogStreamProxy &operator<<(const T &data); // Overload for various data types (int, string, double, etc.)
|
||||
ReLogStreamProxy &operator<<(std::ostream &(*manip)(std::ostream &)); // Overload for std::endl and other manipulators
|
||||
|
||||
protected:
|
||||
LogLevel m_level;
|
||||
std::chrono::system_clock::time_point m_timestamp;
|
||||
std::stringstream m_buffer;
|
||||
|
||||
private:
|
||||
void flush(); // Pass the buffered content to the central Logger
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
/* Constructor */
|
||||
inline ReLogStreamProxy::ReLogStreamProxy(const LogLevel &level)
|
||||
{
|
||||
// Initialization
|
||||
m_level = level;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Destructor */
|
||||
inline ReLogStreamProxy::~ReLogStreamProxy()
|
||||
{
|
||||
if (!m_buffer.str().empty())
|
||||
flush();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Overload for various data types (int, string, double, etc.) */
|
||||
template<typename T>
|
||||
inline ReLogStreamProxy &ReLogStreamProxy::operator<<(const T &data)
|
||||
{
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
|
||||
if (m_buffer.str().empty())
|
||||
m_timestamp = now;
|
||||
|
||||
m_buffer << data;
|
||||
return *this;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Overload for std::endl and other manipulators */
|
||||
inline ReLogStreamProxy &ReLogStreamProxy::operator<<(std::ostream &(*manip)(std::ostream &))
|
||||
{
|
||||
if (manip == static_cast<std::ostream &(*)(std::ostream &)>(std::endl))
|
||||
{
|
||||
flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle other manipulators if necessary (e.g., std::hex)
|
||||
m_buffer << manip;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Pass the buffered content to the central Logger */
|
||||
inline void ReLogStreamProxy::flush()
|
||||
{
|
||||
// Pass the buffered content to the central Logger
|
||||
ReLog::getInstance().log(ReLog::Log{ .level = m_level,
|
||||
.timestamp = m_timestamp,
|
||||
.message = m_buffer.str() });
|
||||
|
||||
// Reset stream content
|
||||
m_buffer.str("");
|
||||
m_buffer.clear();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
} // namespace sdi_toolBox::logs
|
||||
|
||||
//--------------------------------------------------------------
|
||||
/*
|
||||
* User interface
|
||||
*/
|
||||
inline sdi_toolBox::logs::ReLogStreamProxy LogError()
|
||||
{
|
||||
return sdi_toolBox::logs::ReLogStreamProxy(sdi_toolBox::logs::LogLevel::Error);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
inline sdi_toolBox::logs::ReLogStreamProxy LogWarning()
|
||||
{
|
||||
return sdi_toolBox::logs::ReLogStreamProxy(sdi_toolBox::logs::LogLevel::Warning);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
inline sdi_toolBox::logs::ReLogStreamProxy LogInfo()
|
||||
{
|
||||
return sdi_toolBox::logs::ReLogStreamProxy(sdi_toolBox::logs::LogLevel::Info);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
inline sdi_toolBox::logs::ReLogStreamProxy LogDebug()
|
||||
{
|
||||
return sdi_toolBox::logs::ReLogStreamProxy(sdi_toolBox::logs::LogLevel::Debug);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
inline sdi_toolBox::logs::ReLogStreamProxy LogComm()
|
||||
{
|
||||
return sdi_toolBox::logs::ReLogStreamProxy(sdi_toolBox::logs::LogLevel::Comm);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
inline sdi_toolBox::logs::ReLogStreamProxy LogMessage()
|
||||
{
|
||||
return sdi_toolBox::logs::ReLogStreamProxy(sdi_toolBox::logs::LogLevel::Message);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
inline sdi_toolBox::logs::ReLogStreamProxy LogDev()
|
||||
{
|
||||
return sdi_toolBox::logs::ReLogStreamProxy(sdi_toolBox::logs::LogLevel::Dev);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
inline void LogCode(const std::string &msg = "", const std::source_location &location = std::source_location::current())
|
||||
{
|
||||
LogDev() << msg << ((!msg.empty()) ? " - " : "") << "(" << location.file_name() << " l." << location.line() << ")" << std::endl;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
Reference in New Issue
Block a user