You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
2.6 KiB

  1. /**
  2. * @file formatter.h
  3. * @author Harold Bruintjes <h.bruintjes@cs.rwth-aachen.de>
  4. *
  5. * Implementation of Formatter classes
  6. */
  7. #pragma once
  8. #include <chrono>
  9. #include <ctime>
  10. #include <iomanip>
  11. #include <sstream>
  12. #include <cstring> //strrchr
  13. namespace l3pp {
  14. namespace detail {
  15. /**
  16. * Internal function to get wall-time
  17. */
  18. inline static std::chrono::system_clock::time_point GetStartTime() {
  19. static std::chrono::system_clock::time_point startTime = std::chrono::system_clock::now();
  20. return startTime;
  21. }
  22. }
  23. inline void Formatter::initialize() {
  24. // Init wall-time
  25. detail::GetStartTime();
  26. }
  27. inline std::string Formatter::format(EntryContext const& context, std::string const& msg) const {
  28. std::stringstream stream;
  29. stream << context.level << " - " << msg << '\n';
  30. return stream.str();
  31. }
  32. template<Field field, int Width, Justification j, char Fill>
  33. inline void FieldStr<field, Width, j, Fill>::stream(std::ostream& os, EntryContext const& context, std::string const& msg) const {
  34. os << std::setw(Width);
  35. os << std::setfill(Fill);
  36. switch(j) {
  37. case Justification::LEFT:
  38. os << std::left;
  39. case Justification::RIGHT:
  40. os << std::right;
  41. }
  42. switch(field) {
  43. case Field::FileName:
  44. #ifdef _WIN32
  45. os << strrchr(context.filename, '\\')+1;
  46. #else
  47. os << strrchr(context.filename, '/')+1;
  48. #endif
  49. break;
  50. case Field::FilePath:
  51. os << context.filename;
  52. break;
  53. case Field::Line:
  54. os << context.line;
  55. break;
  56. case Field::Function:
  57. os << context.funcname;
  58. break;
  59. case Field::LoggerName:
  60. os << context.logger->getName();
  61. break;
  62. case Field::Message:
  63. os << msg;
  64. break;
  65. case Field::LogLevel:
  66. os << context.level;
  67. break;
  68. case Field::WallTime:
  69. auto runtime = context.timestamp - detail::GetStartTime();
  70. os << std::chrono::duration_cast<std::chrono::milliseconds>(runtime).count();
  71. break;
  72. }
  73. }
  74. inline void TimeStr::stream(std::ostream& os, EntryContext const& context, std::string const&) const {
  75. auto time = std::chrono::system_clock::to_time_t(context.timestamp);
  76. auto timeinfo = localtime (&time);
  77. #if __GNUC__ >= 5 || __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 7) || _MSC_VER >= 1700
  78. //TODO: Need better way to detect thing
  79. os << std::put_time(timeinfo, formatStr.c_str());
  80. #else
  81. char buffer[1024];
  82. if (strftime(buffer, 1024, formatStr.c_str(), timeinfo)) {
  83. os << buffer;
  84. }
  85. #endif
  86. }
  87. template<typename ... Formatters>
  88. inline std::string TemplateFormatter<Formatters...>::format(EntryContext const& context, std::string const& msg) const {
  89. std::stringstream stream;
  90. formatTuple<0>(context, msg, stream);
  91. return stream.str();
  92. }
  93. }