#pragma once #include "cru/common/base.hpp" #include "cru/common/format.hpp" #include #include #include namespace cru::log { enum class LogLevel { Debug, Info, Warn, Error }; struct ILoggerSource : Interface { // Write the s. LogLevel is just a helper. It has no effect on the content to // write. virtual void Write(LogLevel level, const std::wstring_view& s) = 0; }; class StdioLoggerSource : public ILoggerSource { public: StdioLoggerSource() = default; CRU_DELETE_COPY(StdioLoggerSource) CRU_DELETE_MOVE(StdioLoggerSource) ~StdioLoggerSource() = default; void Write(LogLevel level, const std::wstring_view& s) override { if (level == LogLevel::Error) { std::wcerr << s; } else { std::wcout << s; } } }; class Logger : public Object { public: static Logger* GetInstance(); public: Logger() = default; CRU_DELETE_COPY(Logger) CRU_DELETE_MOVE(Logger) ~Logger() override; public: void AddSource(ILoggerSource* source); void RemoveSource(ILoggerSource* source); public: void Log(LogLevel level, const std::wstring_view& s); template void Debug(const std::wstring_view& format, TArgs&&... args) { #ifdef CRU_DEBUG Log(LogLevel::Debug, util::Format(format, std::forward(args)...)); #endif } template void Info(const std::wstring_view& format, TArgs&&... args) { Log(LogLevel::Info, util::Format(format, std::forward(args)...)); } template void Warn(const std::wstring_view& format, TArgs&&... args) { Log(LogLevel::Warn, util::Format(format, std::forward(args)...)); } template void Error(const std::wstring_view& format, TArgs&&... args) { Log(LogLevel::Error, util::Format(format, std::forward(args)...)); } public: std::list sources_; }; template void Debug(const std::wstring_view& format, TArgs&&... args) { #ifdef CRU_DEBUG Logger::GetInstance()->Log( LogLevel::Debug, util::Format(format, std::forward(args)...)); #endif } template void Info(const std::wstring_view& format, TArgs&&... args) { Logger::GetInstance()->Log( LogLevel::Info, util::Format(format, std::forward(args)...)); } template void Warn(const std::wstring_view& format, TArgs&&... args) { Logger::GetInstance()->Log( LogLevel::Warn, util::Format(format, std::forward(args)...)); } template void Error(const std::wstring_view& format, TArgs&&... args) { Logger::GetInstance()->Log( LogLevel::Error, util::Format(format, std::forward(args)...)); } } // namespace cru::log