/** * @file formatter.h * @author Harold Bruintjes <h.bruintjes@cs.rwth-aachen.de> * * Implementation of Formatter classes */ #pragma once #include <chrono> #include <ctime> #include <iomanip> #include <sstream> #include <cstring> //strrchr namespace l3pp { namespace detail { /** * Internal function to get wall-time */ inline static std::chrono::system_clock::time_point GetStartTime() { static std::chrono::system_clock::time_point startTime = std::chrono::system_clock::now(); return startTime; } } inline void Formatter::initialize() { // Init wall-time detail::GetStartTime(); } inline std::string Formatter::format(EntryContext const& context, std::string const& msg) const { std::stringstream stream; stream << context.level << " - " << msg << '\n'; return stream.str(); } template<Field field, int Width, Justification j, char Fill> inline void FieldStr<field, Width, j, Fill>::stream(std::ostream& os, EntryContext const& context, std::string const& msg) const { os << std::setw(Width); os << std::setfill(Fill); switch(j) { case Justification::LEFT: os << std::left; case Justification::RIGHT: os << std::right; } switch(field) { case Field::FileName: #ifdef _WIN32 os << strrchr(context.filename, '\\')+1; #else os << strrchr(context.filename, '/')+1; #endif break; case Field::FilePath: os << context.filename; break; case Field::Line: os << context.line; break; case Field::Function: os << context.funcname; break; case Field::LoggerName: os << context.logger->getName(); break; case Field::Message: os << msg; break; case Field::LogLevel: os << context.level; break; case Field::WallTime: auto runtime = context.timestamp - detail::GetStartTime(); os << std::chrono::duration_cast<std::chrono::milliseconds>(runtime).count(); break; } } inline void TimeStr::stream(std::ostream& os, EntryContext const& context, std::string const&) const { auto time = std::chrono::system_clock::to_time_t(context.timestamp); auto timeinfo = localtime (&time); #if __GNUC__ >= 5 || __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 7) || _MSC_VER >= 1700 //TODO: Need better way to detect thing os << std::put_time(timeinfo, formatStr.c_str()); #else char buffer[1024]; if (strftime(buffer, 1024, formatStr.c_str(), timeinfo)) { os << buffer; } #endif } template<typename ... Formatters> inline std::string TemplateFormatter<Formatters...>::format(EntryContext const& context, std::string const& msg) const { std::stringstream stream; formatTuple<0>(context, msg, stream); return stream.str(); } }