💿🐜 Antkeeper source code https://antkeeper.com
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.

230 lines
4.6 KiB

  1. /*
  2. * Copyright (C) 2023 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "logger.hpp"
  20. #include "utility/timestamp.hpp"
  21. #include <iostream>
  22. #if defined(_WIN32)
  23. #define WIN32_LEAN_AND_MEAN
  24. #include <windows.h>
  25. #endif
  26. namespace debug {
  27. logger::logger():
  28. os(&std::cout),
  29. auto_newline(true),
  30. timestamp_enabled(true),
  31. indent("| "),
  32. log_prefix(std::string()),
  33. log_postfix(std::string()),
  34. warning_prefix(std::string()),
  35. warning_postfix(std::string()),
  36. error_prefix(std::string()),
  37. error_postfix(std::string()),
  38. success_prefix(std::string()),
  39. success_postfix(std::string())
  40. {}
  41. logger::~logger()
  42. {}
  43. void logger::redirect(std::ostream* stream)
  44. {
  45. os = stream;
  46. }
  47. void logger::log(const std::string& text)
  48. {
  49. if (os)
  50. {
  51. std::string message = "";
  52. // Prepend timestamp
  53. if (timestamp_enabled)
  54. {
  55. message += timestamp();
  56. message += ": ";
  57. }
  58. // Prepend indentation
  59. for (std::size_t i = 0; i < tasks.size(); ++i)
  60. message += indent;
  61. // Append text
  62. message += (log_prefix + text + log_postfix);
  63. // Append newline
  64. if (auto_newline)
  65. message += "\n";
  66. // Add message to log history
  67. const std::lock_guard<std::mutex> history_lock(history_mutex);
  68. history += message;
  69. // Output message
  70. (*os) << message;
  71. // Flush output stream
  72. os->flush();
  73. }
  74. }
  75. void logger::warning(const std::string& text)
  76. {
  77. #if defined(_WIN32)
  78. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN);
  79. #endif
  80. log(warning_prefix + text + warning_postfix);
  81. #if defined(_WIN32)
  82. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
  83. #endif
  84. }
  85. void logger::error(const std::string& text)
  86. {
  87. #if defined(_WIN32)
  88. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  89. #endif
  90. log(error_prefix + text + error_postfix);
  91. #if defined(_WIN32)
  92. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
  93. #endif
  94. }
  95. void logger::success(const std::string& text)
  96. {
  97. /*
  98. #if defined(_WIN32)
  99. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
  100. #endif
  101. */
  102. log(success_prefix + text + success_postfix);
  103. /*
  104. #if defined(_WIN32)
  105. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
  106. #endif
  107. */
  108. }
  109. void logger::set_auto_newline(bool enabled)
  110. {
  111. auto_newline = enabled;
  112. }
  113. void logger::set_timestamp(bool enabled)
  114. {
  115. timestamp_enabled = enabled;
  116. }
  117. void logger::set_indent(const std::string& indent)
  118. {
  119. this->indent = indent;
  120. }
  121. void logger::set_log_prefix(const std::string& prefix)
  122. {
  123. log_prefix = prefix;
  124. }
  125. void logger::set_log_postfix(const std::string& postfix)
  126. {
  127. log_postfix = postfix;
  128. }
  129. void logger::set_warning_prefix(const std::string& prefix)
  130. {
  131. warning_prefix = prefix;
  132. }
  133. void logger::set_warning_postfix(const std::string& postfix)
  134. {
  135. warning_postfix = postfix;
  136. }
  137. void logger::set_error_prefix(const std::string& prefix)
  138. {
  139. error_prefix = prefix;
  140. }
  141. void logger::set_error_postfix(const std::string& postfix)
  142. {
  143. error_postfix = postfix;
  144. }
  145. void logger::set_success_prefix(const std::string& prefix)
  146. {
  147. success_prefix = prefix;
  148. }
  149. void logger::set_success_postfix(const std::string& postfix)
  150. {
  151. success_postfix = postfix;
  152. }
  153. void logger::push_task(const std::string& description)
  154. {
  155. std::string message = description + " {";
  156. if (!auto_newline)
  157. message += "\n";
  158. log(message);
  159. tasks.push(description);
  160. }
  161. void logger::pop_task(int status, std::string error)
  162. {
  163. if (tasks.empty())
  164. {
  165. return;
  166. }
  167. std::string message = "} => ";
  168. tasks.pop();
  169. if (status == EXIT_SUCCESS)
  170. {
  171. message += "success";
  172. if (!auto_newline)
  173. message += "\n";
  174. success(message);
  175. }
  176. else
  177. {
  178. message += "failure";
  179. if (!error.empty())
  180. message += " (" + error + ")";
  181. if (!auto_newline)
  182. message += "\n";
  183. this->error(message);
  184. }
  185. }
  186. } // namespace debug