source: pacpusframework/trunk/src/PacpusLib/ColorSeverityFormatter.hpp@ 239

Last change on this file since 239 was 239, checked in by Marek Kurdej, 11 years ago

Added: possibility to use color log output (needs more testing).

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