#include "logger.h" #include #include #include #include #include #include #include #ifndef WIN32 #include #endif #define LOG_BUFFER_SIZE 4096 thread_local std::unique_ptr log_buffer{nullptr, nullptr}; std::mutex target_file_lock; std::unique_ptr file_stream; void logger::log_raw(logger::level::value level, const char* format, ...) { if(!log_buffer) log_buffer = std::unique_ptr((char*) malloc(LOG_BUFFER_SIZE), ::free); va_list arg_lst; va_start(arg_lst, format); auto result = vsnprintf(log_buffer.get(), LOG_BUFFER_SIZE, format, arg_lst); va_end(arg_lst); { std::lock_guard lock(target_file_lock); if(result < 0) { fprintf(stdout, "failed to format log message (%d)\n", result); if(file_stream) *file_stream << "failed to format log message (" << result << ")\n"; } else { fprintf(stdout, "[%d] ", level); fwrite(log_buffer.get(), result, 1, stdout); fprintf(stdout, "\n"); if(file_stream) { *file_stream << "[" << level << "] "; file_stream->write(log_buffer.get(), result); *file_stream << "\n"; } } } } void logger::flush() { std::lock_guard lock(target_file_lock); if(file_stream) { file_stream->flush(); } } bool logger::pipe_file(const std::string_view &target) { auto handle = std::make_unique(std::string(target.data(), target.size()), std::ofstream::app | std::ofstream::out); if(!handle->good()) return false; file_stream = std::move(handle); return true; }