source: pacpusframework/branches/0.2.x/src/PacpusLib/ColorSeverityFormatter.hpp@ 357

Last change on this file since 357 was 357, checked in by cerichar, 10 years ago

compilation on Windows 10 64 bits, visual 2012, Qt 5.5, boost 1.54

File size: 12.1 KB
Line 
1// %pacpus:license{
2// This file is part of the PACPUS framework distributed under the
3// CECILL-C License, Version 1.0.
4// %pacpus:license}
5/// @version $Id: Log.cpp 76 2013-01-10 17:05:10Z kurdejma $
6/// @file
7/// @author Marek Kurdej <firstname.surname@utc.fr>
8/// @date 2013-11-28
9/// @version $Id$
10/// @copyright Copyright (c) UTC/CNRS Heudiasyc 2006 - 2013. All rights reserved.
11/// @brief Color logger output depending on severity level.
12///
13/// Detailed description.
14
15#ifndef COLORSEVERITYFORMATTER_HPP
16#define COLORSEVERITYFORMATTER_HPP
17
18#if defined(PACPUS_LOG_COLORED_OUTPUT)
19
20#include <Pacpus/predef/os.h>
21
22#include <boost/assert.hpp>
23#include <boost/log/attributes/attribute_name.hpp>
24#include <boost/log/attributes/fallback_policy.hpp>
25#include <boost/log/attributes/value_visitation.hpp>
26#include <boost/log/expressions.hpp>
27#include <boost/log/utility/functional/bind.hpp>
28#include <cstdlib>
29#include <sstream>
30#include <string>
31
32#if PACPUS_OS_WINDOWS
33# include <Windows.h>
34#endif
35
36namespace pacpus
37{
38
39enum Color {
40 COLOR_DEFAULT,
41 COLOR_BLACK,
42 COLOR_RED,
43 COLOR_GREEN,
44 COLOR_YELLOW,
45 COLOR_BLUE,
46 COLOR_MAGENTA,
47 COLOR_CYAN,
48 COLOR_WHITE
49};
50
51Color getColor(SeverityLevel const& sev)
52{
53 if (sev >= error) {
54 return COLOR_RED;
55 } else if (sev >= warning) {
56 return COLOR_YELLOW;
57 } else if (sev >= info) {
58 return COLOR_WHITE; //COLOR_GREEN;
59 }
60 return COLOR_DEFAULT;
61}
62
63#if PACPUS_OS_WINDOWS
64
65// Returns the character attribute for the given color.
66WORD getColorAttribute(Color color)
67{
68 switch (color) {
69 case COLOR_BLACK: return 0;
70 case COLOR_RED: return FOREGROUND_RED;
71 case COLOR_GREEN: return FOREGROUND_GREEN;
72 case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
73 case COLOR_BLUE: return FOREGROUND_BLUE;
74 case COLOR_MAGENTA: return FOREGROUND_RED | FOREGROUND_BLUE;
75 case COLOR_CYAN: return FOREGROUND_GREEN | FOREGROUND_BLUE;
76 case COLOR_WHITE: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
77 case COLOR_DEFAULT: return 0;
78 default:
79 BOOST_ASSERT(false && "wrong Color enum value");
80 return 0;
81 }
82}
83
84#else
85
86/// @returns the ANSI color code for the given color. COLOR_DEFAULT is
87/// an invalid input.
88std::string getAnsiColorCode(Color color)
89{
90 const char* kEscapeSequence = "\033[";
91// const char* kBackground = "";
92 const char* kFontRegular = "0;";
93// const char* kFontBold = "1;";
94// const char* kFontWeak = "2;";
95// const char* kFontStrong = "3;";
96// const char* kFontUnderline = "4;";
97
98 std::stringstream ss;
99 ss << kEscapeSequence << kFontRegular;
100
101 switch (color) {
102 case COLOR_BLACK: ss << "30"; break;
103 case COLOR_RED: ss << "31"; break;
104 case COLOR_GREEN: ss << "32"; break;
105 case COLOR_YELLOW: ss << "33"; break;
106 case COLOR_BLUE: ss << "34"; break;
107 case COLOR_MAGENTA: ss << "35"; break;
108 case COLOR_CYAN: ss << "36"; break;
109 case COLOR_WHITE: ss << "37"; break;
110 default: return "";
111 };
112
113 const char* kPostfix = "m";
114 ss << kPostfix;
115
116 return ss.str();
117}
118
119std::string getAnsiColorCodeRestoreDefault()
120{
121 return "\033[0m";
122}
123
124#endif // PACPUS_OS_WINDOWS
125
126bool shouldUseColor(bool stdoutIsTty)
127{
128#if PACPUS_OS_WINDOWS // && !PACPUS_OS_WINDOWS_MOBILE
129 return true;
130#else
131 // On non-Windows platforms, we rely on the TERM variable.
132 std::string const term = std::getenv("TERM");
133 const bool termSupportsColor = (term == "xterm")
134 || (term == "xterm-color")
135 || (term == "xterm-256color")
136 || (term == "screen")
137 || (term == "linux")
138 || (term == "cygwin");
139 return stdoutIsTty && termSupportsColor;
140#endif // PACPUS_OS_WINDOWS
141}
142
143template < typename CharT >
144struct ColorFormatter
145{
146 ColorFormatter()
147#if PACPUS_OS_WINDOWS
148 : mStreamHandle(GetStdHandle(STD_OUTPUT_HANDLE))
149#endif // PACPUS_OS_WINDOWS
150 {
151 mShouldUseColor = shouldUseColor(/*stdoutIsTty*/ true);
152 }
153
154 void operator()(boost::log::basic_formatting_ostream<CharT>& strm, SeverityLevel const& sev)
155 {
156 if (!mShouldUseColor) {
157 return;
158 }
159#if PACPUS_OS_WINDOWS
160 // Gets the current text color.
161 CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
162 GetConsoleScreenBufferInfo(mStreamHandle, &bufferInfo);
163 mSavedConsoleBufferInfo = bufferInfo.wAttributes;
164
165 // We need to flush the stream buffers into the console before each
166 // SetConsoleTextAttribute call lest it affect the text that is already
167 // printed but has not yet reached the console.
168 fflush(stdout);
169 SetConsoleTextAttribute(mStreamHandle, getColorAttribute(getColor(sev)) | FOREGROUND_INTENSITY);
170#else
171 strm << getAnsiColorCode(getColor(sev)).c_str();
172#endif // PACPUS_OS_WINDOWS
173 }
174
175 bool mShouldUseColor;
176#if PACPUS_OS_WINDOWS
177 const HANDLE mStreamHandle;
178 WORD mSavedConsoleBufferInfo;
179#endif // PACPUS_OS_WINDOWS
180};
181
182template < typename CharT >
183struct DefaultFormatter
184{
185 DefaultFormatter()
186#if PACPUS_OS_WINDOWS
187 //DefaultFormatter(WORD savedConsoleBufferInfo)
188 : mStreamHandle(GetStdHandle(STD_OUTPUT_HANDLE))
189 //, mSavedConsoleBufferInfo(savedConsoleBufferInfo)
190 , mSavedConsoleBufferInfo(getColorAttribute(COLOR_WHITE)) // FIXME: restore old value, not just reset
191#endif // PACPUS_OS_WINDOWS
192 {
193 mShouldUseColor = shouldUseColor(/*stdoutIsTty*/ true);
194 }
195
196 void operator()(boost::log::basic_formatting_ostream<CharT>& strm, SeverityLevel const& /*sev*/)
197 {
198 if (!mShouldUseColor) {
199 return;
200 }
201#if PACPUS_OS_WINDOWS
202 fflush(stdout);
203 // Restores the text color.
204 SetConsoleTextAttribute(mStreamHandle, mSavedConsoleBufferInfo);
205#else
206 strm << getAnsiColorCodeRestoreDefault().c_str();
207#endif // PACPUS_OS_WINDOWS
208 }
209
210 bool mShouldUseColor;
211#if PACPUS_OS_WINDOWS
212 const HANDLE mStreamHandle;
213 WORD mSavedConsoleBufferInfo;
214#endif // PACPUS_OS_WINDOWS
215};
216
217template< typename T, typename FallbackPolicyT, typename CharT >
218class FormatSeverityWithColorsTerminal
219{
220public:
221 //! Internal typedef for type categorization
222 typedef void _is_boost_log_terminal;
223
224 //! Attribute value type
225 typedef T value_type;
226 //! Fallback policy
227 typedef FallbackPolicyT fallback_policy;
228 //! Character type
229 typedef CharT char_type;
230 //! String type
231 typedef std::basic_string< char_type > string_type;
232 //! Formatting stream type
233 typedef boost::log::basic_formatting_ostream< char_type > stream_type;
234
235 //! Formatter function
236 typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type;
237
238 //! Function result type
239 typedef string_type result_type;
240
241 typedef boost::log::attribute_name attribute_name;
242
243private:
244 //! Attribute value visitor invoker
245 typedef boost::log::value_visitor_invoker< value_type, fallback_policy > visitor_invoker_type;
246
247private:
248 //! Attribute name
249 attribute_name m_name;
250 //! Formattr function
251 formatter_function_type m_formatter;
252 //! Attribute value visitor invoker
253 visitor_invoker_type m_visitor_invoker;
254
255public:
256 //! Initializing constructor
257 FormatSeverityWithColorsTerminal(attribute_name const& name, fallback_policy const& fallback, bool restoreDefault)
258 : m_name(name)
259 //, m_formatter(formatter_generator::parse(format))
260 , m_visitor_invoker(fallback)
261 {
262 if (restoreDefault) {
263//#if PACPUS_OS_WINDOWS
264// m_formatter = formatter_function_type(DefaultFormatter<char_type>());
265//#else // PACPUS_OS_WINDOWS
266 m_formatter = formatter_function_type(DefaultFormatter<char_type>());
267//#endif // PACPUS_OS_WINDOWS
268 } else {
269 m_formatter = formatter_function_type(ColorFormatter<char_type>());
270 }
271 }
272
273 //! Copy constructor
274 FormatSeverityWithColorsTerminal(FormatSeverityWithColorsTerminal const& that) :
275 m_name(that.m_name), m_formatter(that.m_formatter), m_visitor_invoker(that.m_visitor_invoker)
276 {
277 }
278
279 //! Invokation operator
280 template< typename ContextT >
281 result_type operator() (ContextT const& ctx)
282 {
283 using namespace boost;
284 using boost::log::binder1st;
285 string_type str;
286 stream_type strm(str);
287 m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type&, stream_type& >(m_formatter, strm));
288 strm.flush();
289 return boost::move(str);
290 }
291
292 //! Invokation operator
293 template< typename ContextT >
294 result_type operator() (ContextT const& ctx) const
295 {
296 using namespace boost;
297 using boost::log::binder1st;
298 string_type str;
299 stream_type strm(str);
300 m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type const&, stream_type& >(m_formatter, strm));
301 strm.flush();
302 return boost::move(str);
303 }
304
305};
306
307template< typename T, typename FallbackPolicyT, typename CharT = char, template< typename > class ActorT = boost::phoenix::actor >
308class FormatSeverityWithColorsActor
309 : public ActorT< FormatSeverityWithColorsTerminal< T, FallbackPolicyT, CharT > >
310{
311public:
312 //! Attribute value type
313 typedef T value_type;
314 //! Character type
315 typedef CharT char_type;
316 //! Fallback policy
317 typedef FallbackPolicyT fallback_policy;
318 //! Base terminal type
319 typedef FormatSeverityWithColorsTerminal< value_type, fallback_policy, char_type > terminal_type;
320 //! Formatter function
321 typedef typename terminal_type::formatter_function_type formatter_function_type;
322
323 //! Base actor type
324 typedef ActorT< terminal_type > base_type;
325
326public:
327 //! Initializing constructor
328 explicit FormatSeverityWithColorsActor(base_type const& act)
329 : base_type(act)
330 {
331 }
332};
333
334template< typename AttributeValueT >
335/*BOOST_FORCEINLINE*/ FormatSeverityWithColorsActor< AttributeValueT, boost::log::fallback_to_none >
336formatSeverityWithColors(boost::log::attribute_name const& name, bool restoreDefault = false)
337{
338 using boost::log::fallback_to_none;
339 typedef FormatSeverityWithColorsActor< AttributeValueT, fallback_to_none > actor_type;
340 typedef typename actor_type::terminal_type terminal_type;
341 typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), restoreDefault) }};
342 return actor_type(act);
343}
344
345template< typename DescriptorT, template< typename > class ActorT, typename CharT >
346/*BOOST_FORCEINLINE*/ FormatSeverityWithColorsActor< typename DescriptorT::value_type, boost::log::fallback_to_none, CharT, ActorT >
347formatSeverityWithColors(boost::log::expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, bool restoreDefault = false)
348{
349 using boost::log::fallback_to_none;
350 typedef FormatSeverityWithColorsActor< typename DescriptorT::value_type, fallback_to_none, CharT, ActorT > actor_type;
351 typedef typename actor_type::terminal_type terminal_type;
352 typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), restoreDefault) }};
353 return actor_type(act);
354}
355
356template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT>
357/*BOOST_FORCEINLINE*/ FormatSeverityWithColorsActor< T, FallbackPolicyT, char, ActorT >
358formatSeverityWithColors(boost::log::expressions::attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, bool restoreDefault = false)
359{
360 typedef FormatSeverityWithColorsActor< T, FallbackPolicyT, char, ActorT > actor_type;
361 typedef typename actor_type::terminal_type terminal_type;
362 typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), restoreDefault) }};
363 return actor_type(act);
364}
365
366} // namespace pacpus
367
368#endif // defined(PACPUS_LOG_COLORED_OUTPUT)
369
370#endif // COLORSEVERITYFORMATTER_HPP
Note: See TracBrowser for help on using the repository browser.