File indexing completed on 2025-01-18 09:52:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_TEST_UTILS_SETCOLOR_HPP
0016 #define BOOST_TEST_UTILS_SETCOLOR_HPP
0017
0018
0019 #include <boost/test/detail/config.hpp>
0020
0021 #include <boost/core/ignore_unused.hpp>
0022 #include <boost/core/snprintf.hpp>
0023
0024
0025 #include <iostream>
0026 #include <cstdio>
0027 #include <cassert>
0028
0029 #include <boost/test/detail/suppress_warnings.hpp>
0030
0031 #ifdef _WIN32
0032 #include <windows.h>
0033
0034 #if defined(__MINGW32__) && !defined(COMMON_LVB_UNDERSCORE)
0035
0036 #define COMMON_LVB_UNDERSCORE 0x8000
0037 #endif
0038 #endif
0039
0040
0041
0042 namespace boost {
0043 namespace unit_test {
0044 namespace utils {
0045
0046
0047
0048
0049
0050 struct term_attr { enum _ {
0051 NORMAL = 0,
0052 BRIGHT = 1,
0053 DIM = 2,
0054 UNDERLINE = 4,
0055 BLINK = 5,
0056 REVERSE = 7,
0057 CROSSOUT = 9
0058 }; };
0059
0060
0061
0062
0063
0064 struct term_color { enum _ {
0065 BLACK = 0,
0066 RED = 1,
0067 GREEN = 2,
0068 YELLOW = 3,
0069 BLUE = 4,
0070 MAGENTA = 5,
0071 CYAN = 6,
0072 WHITE = 7,
0073 ORIGINAL = 9
0074 }; };
0075
0076
0077
0078
0079
0080 #ifndef _WIN32
0081 class setcolor {
0082 public:
0083 typedef int state;
0084
0085
0086 explicit setcolor( bool is_color_output = false,
0087 term_attr::_ attr = term_attr::NORMAL,
0088 term_color::_ fg = term_color::ORIGINAL,
0089 term_color::_ bg = term_color::ORIGINAL,
0090 state* = NULL)
0091 : m_is_color_output(is_color_output)
0092 {
0093 #ifdef BOOST_MSVC
0094 m_command_size = std::sprintf( m_control_command,
0095 #else
0096 m_command_size = boost::core::snprintf( m_control_command, sizeof(m_control_command),
0097 #endif
0098 "%c[%c;3%c;4%cm",
0099 0x1B,
0100 static_cast<char>(attr + '0'),
0101 static_cast<char>(fg + '0'),
0102 static_cast<char>(bg + '0'));
0103 }
0104
0105 explicit setcolor(bool is_color_output,
0106 state* )
0107 : m_is_color_output(is_color_output)
0108 {
0109 #ifdef BOOST_MSVC
0110 m_command_size = std::sprintf( m_control_command,
0111 #else
0112 m_command_size = boost::core::snprintf(m_control_command, sizeof(m_control_command),
0113 #endif
0114 "%c[%c;3%c;4%cm",
0115 0x1B,
0116 static_cast<char>(term_attr::NORMAL + '0'),
0117 static_cast<char>(term_color::ORIGINAL + '0'),
0118 static_cast<char>(term_color::ORIGINAL + '0'));
0119 }
0120
0121 friend std::ostream&
0122 operator<<( std::ostream& os, setcolor const& sc )
0123 {
0124 if (sc.m_is_color_output && (&os == &std::cout || &os == &std::cerr)) {
0125 return os.write( sc.m_control_command, sc.m_command_size );
0126 }
0127 return os;
0128 }
0129
0130 private:
0131
0132 bool m_is_color_output;
0133 char m_control_command[13];
0134 int m_command_size;
0135 };
0136
0137 #else
0138
0139 class setcolor {
0140
0141 protected:
0142 void set_console_color(std::ostream& os, WORD *attributes = NULL) const {
0143 if (!m_is_color_output || m_state_saved) {
0144 return;
0145 }
0146 DWORD console_type;
0147 if (&os == &std::cout) {
0148 console_type = STD_OUTPUT_HANDLE;
0149 }
0150 else if (&os == &std::cerr) {
0151 console_type = STD_ERROR_HANDLE;
0152 }
0153 else {
0154 return;
0155 }
0156 HANDLE hConsole = GetStdHandle(console_type);
0157
0158 if(hConsole == INVALID_HANDLE_VALUE || hConsole == NULL )
0159 return;
0160
0161 state console_attributes;
0162 if(attributes != NULL || (m_restore_state && m_s)) {
0163 if (attributes != NULL) {
0164 console_attributes = *attributes;
0165 }
0166 else {
0167 console_attributes = *m_s;
0168 *m_s = state();
0169 }
0170 SetConsoleTextAttribute(hConsole, console_attributes);
0171 return;
0172 }
0173
0174 CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
0175 GetConsoleScreenBufferInfo(hConsole, &consoleInfo);
0176 console_attributes = consoleInfo.wAttributes;
0177
0178 if (!m_state_saved && m_s) {
0179 assert(!m_restore_state);
0180
0181
0182 *m_s = console_attributes;
0183 m_state_saved = true;
0184 }
0185
0186 WORD fg_attr = 0;
0187 switch(m_fg)
0188 {
0189 case term_color::WHITE:
0190 fg_attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
0191 break;
0192 case term_color::BLACK:
0193 fg_attr = 0;
0194 break;
0195 case term_color::RED:
0196 fg_attr = FOREGROUND_RED;
0197 break;
0198 case term_color::GREEN:
0199 fg_attr = FOREGROUND_GREEN;
0200 break;
0201 case term_color::CYAN:
0202 fg_attr = FOREGROUND_GREEN | FOREGROUND_BLUE;
0203 break;
0204 case term_color::MAGENTA:
0205 fg_attr = FOREGROUND_RED | FOREGROUND_BLUE;
0206 break;
0207 case term_color::BLUE:
0208 fg_attr = FOREGROUND_BLUE;
0209 break;
0210 case term_color::YELLOW:
0211 fg_attr = FOREGROUND_RED | FOREGROUND_GREEN;
0212 break;
0213 case term_color::ORIGINAL:
0214 default:
0215 fg_attr = console_attributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
0216 break;
0217 }
0218
0219 WORD bg_attr = 0;
0220 switch(m_bg)
0221 {
0222 case term_color::BLACK:
0223 bg_attr = 0;
0224 break;
0225 case term_color::WHITE:
0226 bg_attr = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
0227 break;
0228 case term_color::RED:
0229 bg_attr = BACKGROUND_RED;
0230 break;
0231 case term_color::GREEN:
0232 bg_attr = BACKGROUND_GREEN;
0233 break;
0234 case term_color::BLUE:
0235 bg_attr = BACKGROUND_BLUE;
0236 break;
0237 case term_color::ORIGINAL:
0238 default:
0239 bg_attr = console_attributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
0240 break;
0241 }
0242
0243 WORD text_attr = 0;
0244 switch(m_attr)
0245 {
0246 case term_attr::BRIGHT:
0247 text_attr = FOREGROUND_INTENSITY;
0248 break;
0249 case term_attr::UNDERLINE:
0250 text_attr = COMMON_LVB_UNDERSCORE;
0251 break;
0252 default:
0253 break;
0254 }
0255
0256 SetConsoleTextAttribute(hConsole, fg_attr | bg_attr | text_attr);
0257 return;
0258 }
0259
0260 public:
0261 typedef WORD state;
0262
0263
0264 explicit setcolor(
0265 bool is_color_output = false,
0266 term_attr::_ attr = term_attr::NORMAL,
0267 term_color::_ fg = term_color::ORIGINAL,
0268 term_color::_ bg = term_color::ORIGINAL,
0269 state* s = NULL)
0270 : m_is_color_output(is_color_output)
0271 , m_attr(attr)
0272 , m_fg(fg)
0273 , m_bg(bg)
0274 , m_s(s)
0275 , m_restore_state(false)
0276 , m_state_saved(false)
0277 {}
0278
0279 explicit setcolor(
0280 bool is_color_output,
0281 state* s)
0282 : m_is_color_output(is_color_output)
0283 , m_attr(term_attr::NORMAL)
0284 , m_fg(term_color::ORIGINAL)
0285 , m_bg(term_color::ORIGINAL)
0286 , m_s(s)
0287 , m_restore_state(true)
0288 , m_state_saved(false)
0289 {}
0290
0291 friend std::ostream&
0292 operator<<( std::ostream& os, setcolor const& sc )
0293 {
0294 sc.set_console_color(os);
0295 return os;
0296 }
0297
0298 private:
0299 bool m_is_color_output;
0300 term_attr::_ m_attr;
0301 term_color::_ m_fg;
0302 term_color::_ m_bg;
0303 state* m_s;
0304
0305
0306 bool m_restore_state;
0307
0308 mutable bool m_state_saved;
0309 };
0310
0311 #endif
0312
0313
0314
0315
0316 struct scope_setcolor {
0317 scope_setcolor()
0318 : m_os( 0 )
0319 , m_state()
0320 , m_is_color_output(false)
0321 {}
0322
0323 explicit scope_setcolor(
0324 bool is_color_output,
0325 std::ostream& os,
0326 term_attr::_ attr = term_attr::NORMAL,
0327 term_color::_ fg = term_color::ORIGINAL,
0328 term_color::_ bg = term_color::ORIGINAL )
0329 : m_os( &os )
0330 , m_is_color_output(is_color_output)
0331 {
0332 os << setcolor(is_color_output, attr, fg, bg, &m_state);
0333 }
0334
0335 ~scope_setcolor()
0336 {
0337 if (m_os) {
0338 *m_os << setcolor(m_is_color_output, &m_state);
0339 }
0340 }
0341 private:
0342 scope_setcolor(const scope_setcolor& r);
0343 scope_setcolor& operator=(const scope_setcolor& r);
0344
0345 std::ostream* m_os;
0346 setcolor::state m_state;
0347 bool m_is_color_output;
0348 };
0349
0350
0351 #define BOOST_TEST_SCOPE_SETCOLOR( is_color_output, os, attr, color ) \
0352 utils::scope_setcolor const sc(is_color_output, os, utils::attr, utils::color); \
0353 boost::ignore_unused( sc ) \
0354
0355
0356 }
0357 }
0358 }
0359
0360 #include <boost/test/detail/enable_warnings.hpp>
0361
0362 #endif