1 // Copyright 2015 Google Inc. All rights reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #include "colorprint.h"
25 #include "internal_macros.h"
27 #ifdef BENCHMARK_OS_WINDOWS
32 #endif // BENCHMARK_OS_WINDOWS
36 #ifdef BENCHMARK_OS_WINDOWS
37 typedef WORD PlatformColorCode
;
39 typedef const char* PlatformColorCode
;
42 PlatformColorCode
GetPlatformColorCode(LogColor color
) {
43 #ifdef BENCHMARK_OS_WINDOWS
46 return FOREGROUND_RED
;
48 return FOREGROUND_GREEN
;
50 return FOREGROUND_RED
| FOREGROUND_GREEN
;
52 return FOREGROUND_BLUE
;
54 return FOREGROUND_BLUE
| FOREGROUND_RED
;
56 return FOREGROUND_BLUE
| FOREGROUND_GREEN
;
57 case COLOR_WHITE
: // fall through to default
85 std::string
FormatString(const char* msg
, va_list args
) {
86 // we might need a second shot at this, so pre-emptivly make a copy
88 va_copy(args_cp
, args
);
90 std::size_t size
= 256;
92 auto ret
= vsnprintf(local_buff
, size
, msg
, args_cp
);
96 // currently there is no error handling for failure, so this is hack.
99 if (ret
== 0) // handle empty expansion
101 else if (static_cast<size_t>(ret
) < size
)
104 // we did not provide a long enough buffer on our first attempt.
105 size
= (size_t)ret
+ 1; // + 1 for the null byte
106 std::unique_ptr
<char[]> buff(new char[size
]);
107 ret
= vsnprintf(buff
.get(), size
, msg
, args
);
108 CHECK(ret
> 0 && ((size_t)ret
) < size
);
113 std::string
FormatString(const char* msg
, ...) {
116 auto tmp
= FormatString(msg
, args
);
121 void ColorPrintf(std::ostream
& out
, LogColor color
, const char* fmt
, ...) {
124 ColorPrintf(out
, color
, fmt
, args
);
128 void ColorPrintf(std::ostream
& out
, LogColor color
, const char* fmt
,
130 #ifdef BENCHMARK_OS_WINDOWS
131 ((void)out
); // suppress unused warning
133 const HANDLE stdout_handle
= GetStdHandle(STD_OUTPUT_HANDLE
);
135 // Gets the current text color.
136 CONSOLE_SCREEN_BUFFER_INFO buffer_info
;
137 GetConsoleScreenBufferInfo(stdout_handle
, &buffer_info
);
138 const WORD old_color_attrs
= buffer_info
.wAttributes
;
140 // We need to flush the stream buffers into the console before each
141 // SetConsoleTextAttribute call lest it affect the text that is already
142 // printed but has not yet reached the console.
144 SetConsoleTextAttribute(stdout_handle
,
145 GetPlatformColorCode(color
) | FOREGROUND_INTENSITY
);
149 // Restores the text color.
150 SetConsoleTextAttribute(stdout_handle
, old_color_attrs
);
152 const char* color_code
= GetPlatformColorCode(color
);
153 if (color_code
) out
<< FormatString("\033[0;3%sm", color_code
);
154 out
<< FormatString(fmt
, args
) << "\033[m";
158 bool IsColorTerminal() {
159 #if BENCHMARK_OS_WINDOWS
160 // On Windows the TERM variable is usually not set, but the
161 // console there does support colors.
162 return 0 != _isatty(_fileno(stdout
));
164 // On non-Windows platforms, we rely on the TERM variable. This list of
165 // supported TERM values is copied from Google Test:
166 // <https://github.com/google/googletest/blob/master/googletest/src/gtest.cc#L2925>.
167 const char* const SUPPORTED_TERM_VALUES
[] = {
168 "xterm", "xterm-color", "xterm-256color",
169 "screen", "screen-256color", "tmux",
170 "tmux-256color", "rxvt-unicode", "rxvt-unicode-256color",
174 const char* const term
= getenv("TERM");
176 bool term_supports_color
= false;
177 for (const char* candidate
: SUPPORTED_TERM_VALUES
) {
178 if (term
&& 0 == strcmp(term
, candidate
)) {
179 term_supports_color
= true;
184 return 0 != isatty(fileno(stdout
)) && term_supports_color
;
185 #endif // BENCHMARK_OS_WINDOWS
188 } // end namespace benchmark