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

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

Fixed: Linux compilation problem

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