1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. |
2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) |
3 | |
4 | #pragma once |
5 | |
6 | #ifndef SPDLOG_HEADER_ONLY |
7 | # include <spdlog/sinks/ansicolor_sink.h> |
8 | #endif |
9 | |
10 | #include <spdlog/pattern_formatter.h> |
11 | #include <spdlog/details/os.h> |
12 | |
13 | namespace spdlog { |
14 | namespace sinks { |
15 | |
16 | template<typename ConsoleMutex> |
17 | SPDLOG_INLINE ansicolor_sink<ConsoleMutex>::ansicolor_sink(FILE *target_file, color_mode mode) |
18 | : target_file_(target_file) |
19 | , mutex_(ConsoleMutex::mutex()) |
20 | , formatter_(details::make_unique<spdlog::pattern_formatter>()) |
21 | |
22 | { |
23 | set_color_mode(mode); |
24 | colors_[level::trace] = to_string_(white); |
25 | colors_[level::debug] = to_string_(cyan); |
26 | colors_[level::info] = to_string_(green); |
27 | colors_[level::warn] = to_string_(yellow_bold); |
28 | colors_[level::err] = to_string_(red_bold); |
29 | colors_[level::critical] = to_string_(bold_on_red); |
30 | colors_[level::off] = to_string_(reset); |
31 | } |
32 | |
33 | template<typename ConsoleMutex> |
34 | SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_color(level::level_enum color_level, string_view_t color) |
35 | { |
36 | std::lock_guard<mutex_t> lock(mutex_); |
37 | colors_[static_cast<size_t>(color_level)] = to_string_(color); |
38 | } |
39 | |
40 | template<typename ConsoleMutex> |
41 | SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::log(const details::log_msg &msg) |
42 | { |
43 | // Wrap the originally formatted message in color codes. |
44 | // If color is not supported in the terminal, log as is instead. |
45 | std::lock_guard<mutex_t> lock(mutex_); |
46 | msg.color_range_start = 0; |
47 | msg.color_range_end = 0; |
48 | memory_buf_t formatted; |
49 | formatter_->format(msg, formatted); |
50 | if (should_do_colors_ && msg.color_range_end > msg.color_range_start) |
51 | { |
52 | // before color range |
53 | print_range_(formatted, 0, msg.color_range_start); |
54 | // in color range |
55 | print_ccode_(colors_[static_cast<size_t>(msg.level)]); |
56 | print_range_(formatted, msg.color_range_start, msg.color_range_end); |
57 | print_ccode_(reset); |
58 | // after color range |
59 | print_range_(formatted, msg.color_range_end, formatted.size()); |
60 | } |
61 | else // no color |
62 | { |
63 | print_range_(formatted, 0, formatted.size()); |
64 | } |
65 | fflush(target_file_); |
66 | } |
67 | |
68 | template<typename ConsoleMutex> |
69 | SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::flush() |
70 | { |
71 | std::lock_guard<mutex_t> lock(mutex_); |
72 | fflush(target_file_); |
73 | } |
74 | |
75 | template<typename ConsoleMutex> |
76 | SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_pattern(const std::string &pattern) |
77 | { |
78 | std::lock_guard<mutex_t> lock(mutex_); |
79 | formatter_ = std::unique_ptr<spdlog::formatter>(new pattern_formatter(pattern)); |
80 | } |
81 | |
82 | template<typename ConsoleMutex> |
83 | SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) |
84 | { |
85 | std::lock_guard<mutex_t> lock(mutex_); |
86 | formatter_ = std::move(sink_formatter); |
87 | } |
88 | |
89 | template<typename ConsoleMutex> |
90 | SPDLOG_INLINE bool ansicolor_sink<ConsoleMutex>::should_color() |
91 | { |
92 | return should_do_colors_; |
93 | } |
94 | |
95 | template<typename ConsoleMutex> |
96 | SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_color_mode(color_mode mode) |
97 | { |
98 | switch (mode) |
99 | { |
100 | case color_mode::always: |
101 | should_do_colors_ = true; |
102 | return; |
103 | case color_mode::automatic: |
104 | should_do_colors_ = details::os::in_terminal(target_file_) && details::os::is_color_terminal(); |
105 | return; |
106 | case color_mode::never: |
107 | should_do_colors_ = false; |
108 | return; |
109 | default: |
110 | should_do_colors_ = false; |
111 | } |
112 | } |
113 | |
114 | template<typename ConsoleMutex> |
115 | SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::print_ccode_(const string_view_t &color_code) |
116 | { |
117 | fwrite(color_code.data(), sizeof(char), color_code.size(), target_file_); |
118 | } |
119 | |
120 | template<typename ConsoleMutex> |
121 | SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::print_range_(const memory_buf_t &formatted, size_t start, size_t end) |
122 | { |
123 | fwrite(formatted.data() + start, sizeof(char), end - start, target_file_); |
124 | } |
125 | |
126 | template<typename ConsoleMutex> |
127 | SPDLOG_INLINE std::string ansicolor_sink<ConsoleMutex>::to_string_(const string_view_t &sv) |
128 | { |
129 | return std::string(sv.data(), sv.size()); |
130 | } |
131 | |
132 | // ansicolor_stdout_sink |
133 | template<typename ConsoleMutex> |
134 | SPDLOG_INLINE ansicolor_stdout_sink<ConsoleMutex>::ansicolor_stdout_sink(color_mode mode) |
135 | : ansicolor_sink<ConsoleMutex>(stdout, mode) |
136 | {} |
137 | |
138 | // ansicolor_stderr_sink |
139 | template<typename ConsoleMutex> |
140 | SPDLOG_INLINE ansicolor_stderr_sink<ConsoleMutex>::ansicolor_stderr_sink(color_mode mode) |
141 | : ansicolor_sink<ConsoleMutex>(stderr, mode) |
142 | {} |
143 | |
144 | } // namespace sinks |
145 | } // namespace spdlog |
146 | |