text_formatter.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <array>
  5. #include <cstdio>
  6. #ifdef _WIN32
  7. #include <windows.h>
  8. #endif
  9. #include "common/assert.h"
  10. #include "common/common_funcs.h"
  11. #include "common/logging/backend.h"
  12. #include "common/logging/log.h"
  13. #include "common/logging/text_formatter.h"
  14. #include "common/string_util.h"
  15. namespace Log {
  16. // TODO(bunnei): This should be moved to a generic path manipulation library
  17. const char* TrimSourcePath(const char* path, const char* root) {
  18. const char* p = path;
  19. while (*p != '\0') {
  20. const char* next_slash = p;
  21. while (*next_slash != '\0' && *next_slash != '/' && *next_slash != '\\') {
  22. ++next_slash;
  23. }
  24. bool is_src = Common::ComparePartialString(p, next_slash, root);
  25. p = next_slash;
  26. if (*p != '\0') {
  27. ++p;
  28. }
  29. if (is_src) {
  30. path = p;
  31. }
  32. }
  33. return path;
  34. }
  35. void FormatLogMessage(const Entry& entry, char* out_text, size_t text_len) {
  36. unsigned int time_seconds = static_cast<unsigned int>(entry.timestamp.count() / 1000000);
  37. unsigned int time_fractional = static_cast<unsigned int>(entry.timestamp.count() % 1000000);
  38. const char* class_name = GetLogClassName(entry.log_class);
  39. const char* level_name = GetLevelName(entry.log_level);
  40. snprintf(out_text, text_len, "[%4u.%06u] %s <%s> %s: %s", time_seconds, time_fractional,
  41. class_name, level_name, TrimSourcePath(entry.location.c_str()), entry.message.c_str());
  42. }
  43. void PrintMessage(const Entry& entry) {
  44. std::array<char, 4 * 1024> format_buffer;
  45. FormatLogMessage(entry, format_buffer.data(), format_buffer.size());
  46. fputs(format_buffer.data(), stderr);
  47. fputc('\n', stderr);
  48. }
  49. void PrintColoredMessage(const Entry& entry) {
  50. #ifdef _WIN32
  51. static HANDLE console_handle = GetStdHandle(STD_ERROR_HANDLE);
  52. CONSOLE_SCREEN_BUFFER_INFO original_info = {0};
  53. GetConsoleScreenBufferInfo(console_handle, &original_info);
  54. WORD color = 0;
  55. switch (entry.log_level) {
  56. case Level::Trace: // Grey
  57. color = FOREGROUND_INTENSITY;
  58. break;
  59. case Level::Debug: // Cyan
  60. color = FOREGROUND_GREEN | FOREGROUND_BLUE;
  61. break;
  62. case Level::Info: // Bright gray
  63. color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
  64. break;
  65. case Level::Warning: // Bright yellow
  66. color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
  67. break;
  68. case Level::Error: // Bright red
  69. color = FOREGROUND_RED | FOREGROUND_INTENSITY;
  70. break;
  71. case Level::Critical: // Bright magenta
  72. color = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
  73. break;
  74. case Level::Count:
  75. UNREACHABLE();
  76. }
  77. SetConsoleTextAttribute(console_handle, color);
  78. #else
  79. #define ESC "\x1b"
  80. const char* color = "";
  81. switch (entry.log_level) {
  82. case Level::Trace: // Grey
  83. color = ESC "[1;30m";
  84. break;
  85. case Level::Debug: // Cyan
  86. color = ESC "[0;36m";
  87. break;
  88. case Level::Info: // Bright gray
  89. color = ESC "[0;37m";
  90. break;
  91. case Level::Warning: // Bright yellow
  92. color = ESC "[1;33m";
  93. break;
  94. case Level::Error: // Bright red
  95. color = ESC "[1;31m";
  96. break;
  97. case Level::Critical: // Bright magenta
  98. color = ESC "[1;35m";
  99. break;
  100. case Level::Count:
  101. UNREACHABLE();
  102. }
  103. fputs(color, stderr);
  104. #endif
  105. PrintMessage(entry);
  106. #ifdef _WIN32
  107. SetConsoleTextAttribute(console_handle, original_info.wAttributes);
  108. #else
  109. fputs(ESC "[0m", stderr);
  110. #undef ESC
  111. #endif
  112. }
  113. } // namespace Log