|
|
@ -6,33 +6,51 @@ |
|
|
|
#include <thread> |
|
|
|
#include <string_view> |
|
|
|
#include <cmath> |
|
|
|
#include <filesystem> |
|
|
|
#include <fstream> |
|
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
|
|
// Private functions Prototypes
|
|
|
|
// Internal functions Prototypes
|
|
|
|
// Global State
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
|
|
#ifdef __cplusplus |
|
|
|
extern "C" { |
|
|
|
#endif |
|
|
|
const char* _orca_log_level_to_string(const ORCA_LOG_LEVEL* level); |
|
|
|
bool _orca_logfile_open(void); |
|
|
|
void _orca_logfile_close(void); |
|
|
|
#ifdef __cplusplus |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
namespace Orca { |
|
|
|
namespace Utils { |
|
|
|
std::atomic<int> termsize_x = 120; |
|
|
|
std::string _to_termcol(const ORCA_LOG_COLOR& col); |
|
|
|
std::string _decorate_three_lines(std::string_view msg, char decoration = '-'); |
|
|
|
std::string _decorate_centered(std::string_view msg, char decoration = '-'); |
|
|
|
} // namespace Utils
|
|
|
|
namespace Log { |
|
|
|
std::mutex _mtx_log{}; |
|
|
|
std::atomic<ORCA_LOG_LEVEL> _log_level{ ORCA_LOG_LEVEL_NONE }; |
|
|
|
std::atomic<ORCA_LOG_COLOR> _log_color{ ORCA_LOG_COLOR_WHITE }; |
|
|
|
namespace Backend { |
|
|
|
void _log_stderr(std::string_view msg, ORCA_LOG_COLOR col = ORCA_LOG_COLOR_DEFAULT); |
|
|
|
void _log_file(std::string_view msg); |
|
|
|
} |
|
|
|
} // namespace Log
|
|
|
|
void _dispatcher(std::string_view msg, ORCA_LOG_COLOR col = ORCA_LOG_COLOR_DEFAULT); |
|
|
|
namespace Console { |
|
|
|
std::mutex _mtx_stdout{}; |
|
|
|
void _write_stdout(std::string_view msg, ORCA_LOG_COLOR col = ORCA_LOG_COLOR_DEFAULT); |
|
|
|
std::mutex _mtx_stderr{}; |
|
|
|
void _write_stderr(std::string_view msg, ORCA_LOG_COLOR col = ORCA_LOG_COLOR_DEFAULT); |
|
|
|
} // namespace Console
|
|
|
|
namespace Logfile { |
|
|
|
std::recursive_mutex _mtx_path{}; |
|
|
|
std::filesystem::path _path{ "orca.log" }; |
|
|
|
std::recursive_mutex _mtx_stream{}; |
|
|
|
std::ofstream _stream{}; |
|
|
|
std::atomic<bool> _clear_on_open{ true }; |
|
|
|
void _write(std::string_view msg); |
|
|
|
} // namespace Logfile
|
|
|
|
} // namespace Backend
|
|
|
|
} // namespace Log
|
|
|
|
} // namespace Orca
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
|
@ -41,55 +59,81 @@ namespace Orca { |
|
|
|
#ifdef __cplusplus |
|
|
|
extern "C" { |
|
|
|
#endif |
|
|
|
void orca_log_level_set(ORCA_LOG_LEVEL level) |
|
|
|
{ |
|
|
|
Orca::Log::_log_level = level; |
|
|
|
} |
|
|
|
|
|
|
|
ORCA_LOG_LEVEL orca_log_level_get(void) |
|
|
|
{ |
|
|
|
return Orca::Log::_log_level; |
|
|
|
} |
|
|
|
|
|
|
|
void orca_log_set_level(ORCA_LOG_LEVEL level) |
|
|
|
void orca_log_logfile_path_set(const char* path) |
|
|
|
{ |
|
|
|
Orca::Log::_log_level.store(level); |
|
|
|
std::lock_guard<std::recursive_mutex> l{ Orca::Log::Backend::Logfile::_mtx_path }; |
|
|
|
std::lock_guard<std::recursive_mutex> l2{ Orca::Log::Backend::Logfile::_mtx_stream }; |
|
|
|
Orca::Log::Backend::Logfile::_path = path; |
|
|
|
if (Orca::Log::Backend::Logfile::_stream.is_open()) { |
|
|
|
Orca::Log::Backend::Logfile::_stream.close(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ORCA_LOG_LEVEL orca_log_get_level() |
|
|
|
void orca_log_logfile_path_get(const char** path) |
|
|
|
{ |
|
|
|
return Orca::Log::_log_level.load(); |
|
|
|
std::lock_guard<std::recursive_mutex> l{ Orca::Log::Backend::Logfile::_mtx_path }; |
|
|
|
*path = Orca::Log::Backend::Logfile::_path.c_str(); |
|
|
|
} |
|
|
|
|
|
|
|
void orca_log_set_color(ORCA_LOG_COLOR col) |
|
|
|
void orca_log_color_set(ORCA_LOG_COLOR col) |
|
|
|
{ |
|
|
|
if (col == ORCA_LOG_COLOR_DEFAULT) { |
|
|
|
col = ORCA_LOG_COLOR_RESET; |
|
|
|
} |
|
|
|
Orca::Log::_log_color.store(col); |
|
|
|
Orca::Log::_log_color = col; |
|
|
|
} |
|
|
|
|
|
|
|
ORCA_LOG_COLOR orca_log_get_color() |
|
|
|
ORCA_LOG_COLOR orca_log_color_get(void) |
|
|
|
{ |
|
|
|
return Orca::Log::_log_color.load(); |
|
|
|
return Orca::Log::_log_color; |
|
|
|
} |
|
|
|
|
|
|
|
void orca_log_logfile_clear_on_open_set(bool clear) |
|
|
|
{ |
|
|
|
Orca::Log::Backend::Logfile::_clear_on_open = clear; |
|
|
|
} |
|
|
|
|
|
|
|
bool orca_log_logfile_clear_on_open_get(void) |
|
|
|
{ |
|
|
|
return Orca::Log::Backend::Logfile::_clear_on_open; |
|
|
|
} |
|
|
|
|
|
|
|
void orca_log(const char* msg) |
|
|
|
{ |
|
|
|
Orca::Log::Backend::_log_stderr(msg, Orca::Log::_log_color.load()); |
|
|
|
Orca::Log::Backend::_dispatcher(msg, Orca::Log::_log_color); |
|
|
|
} |
|
|
|
|
|
|
|
void orca_log_h1(const char* msg) |
|
|
|
{ |
|
|
|
Orca::Log::Backend::_log_stderr( |
|
|
|
Orca::Log::Backend::_dispatcher( |
|
|
|
Orca::Utils::_decorate_three_lines(msg, '='), |
|
|
|
Orca::Log::_log_color.load()); |
|
|
|
Orca::Log::_log_color); |
|
|
|
} |
|
|
|
|
|
|
|
void orca_log_h2(const char* msg) |
|
|
|
{ |
|
|
|
Orca::Log::Backend::_log_stderr( |
|
|
|
Orca::Log::Backend::_dispatcher( |
|
|
|
"\n" + Orca::Utils::_decorate_centered(msg, '='), |
|
|
|
Orca::Log::_log_color.load()); |
|
|
|
Orca::Log::_log_color); |
|
|
|
} |
|
|
|
|
|
|
|
void orca_log_h3(const char* msg) |
|
|
|
{ |
|
|
|
Orca::Log::Backend::_log_stderr(Orca::Utils::_decorate_centered(msg, '-'), Orca::Log::_log_color.load()); |
|
|
|
Orca::Log::Backend::_dispatcher( |
|
|
|
Orca::Utils::_decorate_centered(msg, '-'), |
|
|
|
Orca::Log::_log_color); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void _orca_log_for_macro( |
|
|
|
ORCA_LOG_LEVEL level, |
|
|
|
const char* file, |
|
|
@ -98,7 +142,6 @@ extern "C" { |
|
|
|
const char* fmt, |
|
|
|
...) |
|
|
|
{ |
|
|
|
std::lock_guard<std::mutex> l{ Orca::Log::_mtx_log }; |
|
|
|
if (level > Orca::Log::_log_level) { |
|
|
|
return; |
|
|
|
} |
|
|
@ -124,7 +167,7 @@ extern "C" { |
|
|
|
} |
|
|
|
} |
|
|
|
free(msg_fmtd); |
|
|
|
Orca::Log::log(msg); |
|
|
|
Orca::Log::Backend::_dispatcher(msg); |
|
|
|
va_end(var_args); |
|
|
|
} |
|
|
|
|
|
|
@ -145,6 +188,38 @@ extern "C" { |
|
|
|
return "invalid log level"; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
bool _orca_logfile_open(void) |
|
|
|
{ |
|
|
|
std::lock_guard<std::recursive_mutex> l{ Orca::Log::Backend::Logfile::_mtx_stream }; |
|
|
|
std::lock_guard<std::recursive_mutex> l2{ Orca::Log::Backend::Logfile::_mtx_path }; |
|
|
|
|
|
|
|
if (Orca::Log::Backend::Logfile::_stream.is_open()) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
// Append or clear
|
|
|
|
unsigned int openmode = std::ios::app; |
|
|
|
if (Orca::Log::Backend::Logfile::_clear_on_open) { |
|
|
|
openmode = std::ios::out | std::ios::trunc; |
|
|
|
} |
|
|
|
|
|
|
|
Orca::Log::Backend::Logfile::_stream.open(Orca::Log::Backend::Logfile::_path, openmode); |
|
|
|
if (Orca::Log::Backend::Logfile::_stream.fail()) { |
|
|
|
// TODO: Where to log error
|
|
|
|
std::cerr << "LOGFILE ERROR" << std::endl; |
|
|
|
Orca::Log::Backend::Logfile::_stream.clear(); |
|
|
|
return false; |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
void _orca_logfile_close(void) |
|
|
|
{ |
|
|
|
std::lock_guard<std::recursive_mutex> l{ Orca::Log::Backend::Logfile::_mtx_stream }; |
|
|
|
Orca::Log::Backend::Logfile::_stream.close(); |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef __cplusplus |
|
|
|
} |
|
|
|
#endif |
|
|
@ -158,25 +233,27 @@ namespace Orca { |
|
|
|
// for C++ some functions are just wrappers for the
|
|
|
|
// C linkage functions
|
|
|
|
// to be nicely available in the namespace
|
|
|
|
// C linkage functions are mutexed and therefore
|
|
|
|
// wrapped here even if otherwise trivial
|
|
|
|
|
|
|
|
void set_level(ORCA_LOG_LEVEL level) |
|
|
|
{ |
|
|
|
::orca_log_set_level(level); |
|
|
|
::orca_log_level_set(level); |
|
|
|
} |
|
|
|
|
|
|
|
ORCA_LOG_LEVEL get_level() |
|
|
|
{ |
|
|
|
return ::orca_log_get_level(); |
|
|
|
return ::orca_log_level_get(); |
|
|
|
} |
|
|
|
|
|
|
|
void set_color(ORCA_LOG_COLOR col) |
|
|
|
{ |
|
|
|
::orca_log_set_color(col); |
|
|
|
::orca_log_color_set(col); |
|
|
|
} |
|
|
|
|
|
|
|
ORCA_LOG_COLOR get_color() |
|
|
|
{ |
|
|
|
return ::orca_log_get_color(); |
|
|
|
return ::orca_log_color_get(); |
|
|
|
} |
|
|
|
|
|
|
|
void _log_for_macro( |
|
|
@ -191,54 +268,96 @@ namespace Orca { |
|
|
|
|
|
|
|
void log(std::string_view msg, ORCA_LOG_COLOR col) |
|
|
|
{ |
|
|
|
Backend::_log_stderr(msg, col); |
|
|
|
Backend::_dispatcher(msg, col); |
|
|
|
} |
|
|
|
|
|
|
|
void logH1(std::string_view msg, ORCA_LOG_COLOR col) |
|
|
|
{ |
|
|
|
Backend::_log_stderr(Utils::_decorate_three_lines(msg, '='), col); |
|
|
|
Backend::_dispatcher(Utils::_decorate_three_lines(msg, '='), col); |
|
|
|
} |
|
|
|
|
|
|
|
void logH2(std::string_view msg, ORCA_LOG_COLOR col) |
|
|
|
{ |
|
|
|
Backend::_log_stderr("\n" + Utils::_decorate_centered(msg, '='), col); |
|
|
|
Backend::_dispatcher("\n" + Utils::_decorate_centered(msg, '='), col); |
|
|
|
} |
|
|
|
|
|
|
|
void logH3(std::string_view msg, ORCA_LOG_COLOR col) |
|
|
|
{ |
|
|
|
Backend::_log_stderr(Utils::_decorate_centered(msg, '-'), col); |
|
|
|
Backend::_dispatcher(Utils::_decorate_centered(msg, '-'), col); |
|
|
|
} |
|
|
|
|
|
|
|
namespace Backend { |
|
|
|
// TODO: add file backend
|
|
|
|
void _log_stderr(std::string_view msg, ORCA_LOG_COLOR col) |
|
|
|
void _dispatcher(std::string_view msg, ORCA_LOG_COLOR col) |
|
|
|
{ |
|
|
|
std::lock_guard<std::mutex> l{ _mtx_raw_log }; |
|
|
|
std::cerr << Utils::_to_termcol(col) << msg |
|
|
|
<< Utils::_to_termcol(ORCA_LOG_COLOR_RESET) |
|
|
|
<< std::endl; //endl also flushes, but cerr is unbuffered anyways
|
|
|
|
_log_file(msg); |
|
|
|
Console::_write_stderr(msg, col); |
|
|
|
Logfile::_write(msg); |
|
|
|
} |
|
|
|
|
|
|
|
void _log_file(std::string_view msg) { |
|
|
|
std::lock_guard<std::mutex> l{ _mtx_backend_file }; |
|
|
|
std::filesystem::path path{ "logfile.log" }; |
|
|
|
|
|
|
|
std::ofstream ofs(path); |
|
|
|
ofs << msg << std::endl; |
|
|
|
ofs.close(); |
|
|
|
} |
|
|
|
} // namespace Backend
|
|
|
|
} // namespace Log
|
|
|
|
namespace Console { |
|
|
|
void _write_stdout(std::string_view msg, ORCA_LOG_COLOR col) |
|
|
|
{ |
|
|
|
std::lock_guard<std::mutex> l{ _mtx_stdout }; |
|
|
|
std::cerr << Utils::_to_termcol(col) << msg |
|
|
|
<< Utils::_to_termcol(ORCA_LOG_COLOR_RESET) |
|
|
|
<< std::endl; //endl also flushes, but cerr is unbuffered anyways
|
|
|
|
} |
|
|
|
void _write_stderr(std::string_view msg, ORCA_LOG_COLOR col) |
|
|
|
{ |
|
|
|
std::lock_guard<std::mutex> l{ _mtx_stderr }; |
|
|
|
std::cerr << Utils::_to_termcol(col) << msg |
|
|
|
<< Utils::_to_termcol(ORCA_LOG_COLOR_RESET) |
|
|
|
<< std::endl; //endl also flushes, but cerr is unbuffered anyways
|
|
|
|
} |
|
|
|
} // namespace Console
|
|
|
|
|
|
|
|
namespace Logfile { |
|
|
|
void _write(std::string_view msg) |
|
|
|
{ |
|
|
|
std::lock_guard<std::recursive_mutex> l{ _mtx_stream }; |
|
|
|
if (!_orca_logfile_open()) { |
|
|
|
std::cerr << "ERROR: Logfile open failed" << std::endl; |
|
|
|
} else { |
|
|
|
_stream << msg << std::endl; |
|
|
|
if (_stream.fail()) { |
|
|
|
std::cerr << "ERROR: Logfile Write failed" << std::endl; |
|
|
|
_stream.clear(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void set_path(const std::filesystem::path& path) |
|
|
|
{ |
|
|
|
::orca_log_logfile_path_set(path.c_str()); |
|
|
|
} |
|
|
|
|
|
|
|
const std::filesystem::path& get_path() |
|
|
|
{ |
|
|
|
std::lock_guard<std::recursive_mutex> l{ Orca::Log::Backend::Logfile::_mtx_path }; |
|
|
|
return Orca::Log::Backend::Logfile::_path; |
|
|
|
} |
|
|
|
|
|
|
|
void set_clear_on_open(bool clear) |
|
|
|
{ |
|
|
|
::orca_log_logfile_clear_on_open_set(clear); |
|
|
|
} |
|
|
|
|
|
|
|
bool get_clear_on_open() |
|
|
|
{ |
|
|
|
return ::orca_log_logfile_clear_on_open_get(); |
|
|
|
} |
|
|
|
|
|
|
|
} // namespace Logfile
|
|
|
|
} // namespace Backend
|
|
|
|
} // namespace Log
|
|
|
|
|
|
|
|
|
|
|
|
namespace Utils { |
|
|
|
int termsize_x = 120; |
|
|
|
|
|
|
|
std::string _to_termcol(const ORCA_LOG_COLOR& col) |
|
|
|
{ |
|
|
|
switch (col) { |
|
|
|
case ORCA_LOG_COLOR_DEFAULT: |
|
|
|
// Caution: Make sure Orca::Log::_log_color can
|
|
|
|
// NEVER be set to ORCA_LOG_COLOR_DEFAULT
|
|
|
|
return _to_termcol(Orca::Log::_log_color); |
|
|
|
case ORCA_LOG_COLOR_RESET: |
|
|
|
return "\033[0m"; |
|
|
@ -298,7 +417,7 @@ namespace Orca { |
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
|
|
std::ostream& operator<<(std::ostream& o, const ORCA_LOG_LEVEL* level) |
|
|
|
{ |
|
|
|
return o << std::string_view (_orca_log_level_to_string(level)); |
|
|
|
return o << std::string_view(_orca_log_level_to_string(level)); |
|
|
|
} |
|
|
|
|
|
|
|
// Stuff like that would be fucking handy
|
|
|
|