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

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

Minor: refactored code in ColorSeverityFormatter.hpp

File size: 12.4 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
90#else
91
92/// @returns the ANSI color code for the given color. COLOR_DEFAULT is
93/// an invalid input.
94std::string getAnsiColorCode(Color color)
95{
96 const char* kEscapeSequence = "\033[";
97// const char* kBackground = "";
98 const char* kFontRegular = "0;";
99// const char* kFontBold = "1;";
100// const char* kFontWeak = "2;";
101// const char* kFontStrong = "3;";
102// const char* kFontUnderline = "4;";
103
104 std::stringstream ss;
105 ss << kEscapeSequence << kFontRegular;
106
107 switch (color) {
108 case COLOR_BLACK: ss << "30"; break;
109 case COLOR_RED: ss << "31"; break;
110 case COLOR_GREEN: ss << "32"; break;
111 case COLOR_YELLOW: ss << "33"; break;
112 case COLOR_BLUE: ss << "34"; break;
113 case COLOR_MAGENTA: ss << "35"; break;
114 case COLOR_CYAN: ss << "36"; break;
115 case COLOR_WHITE: ss << "37"; break;
116 default: return "";
117 };
118
119 const char* kPostfix = "m";
120 ss << kPostfix;
121
122 return ss.str();
123}
124
125std::string getAnsiColorCodeRestoreDefault()
126{
127 return "\033[0m";
128}
129
130#endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE)
131
132template < typename CharT >
133struct ColorFormatter
134{
135#if defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE)
136 ColorFormatter()
137 : mStreamHandle(GetStdHandle(STD_OUTPUT_HANDLE))
138 {
139 }
140#endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE)
141
142 void operator()(boost::log::basic_formatting_ostream<CharT>& strm, SeverityLevel const& sev)
143 {
144#if defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE)
145 // Gets the current text color.
146 CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
147 GetConsoleScreenBufferInfo(mStreamHandle, &bufferInfo);
148 mSavedConsoleBufferInfo = bufferInfo.wAttributes;
149
150 // We need to flush the stream buffers into the console before each
151 // SetConsoleTextAttribute call lest it affect the text that is already
152 // printed but has not yet reached the console.
153 fflush(stdout);
154 SetConsoleTextAttribute(mStreamHandle, getColorAttribute(getColor(sev)) | FOREGROUND_INTENSITY);
155#else
156 strm << getAnsiColorCode(getColor(sev)).c_str();
157#endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE)
158 }
159
160#if defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE)
161 const HANDLE mStreamHandle;
162 WORD mSavedConsoleBufferInfo;
163#endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE)
164};
165
166template < typename CharT >
167struct DefaultFormatter
168{
169#if defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE)
170 DefaultFormatter() //(WORD savedConsoleBufferInfo)
171 : mStreamHandle(GetStdHandle(STD_OUTPUT_HANDLE))
172 //, mSavedConsoleBufferInfo(savedConsoleBufferInfo)
173 , mSavedConsoleBufferInfo(getColorAttribute(COLOR_WHITE) | FOREGROUND_INTENSITY) // FIXME: restore old value, not just reset
174 {
175 }
176#endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE)
177
178 void operator()(boost::log::basic_formatting_ostream<CharT>& strm, SeverityLevel const& /*sev*/)
179 {
180#if defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE)
181 fflush(stdout);
182 // Restores the text color.
183 SetConsoleTextAttribute(mStreamHandle, mSavedConsoleBufferInfo);
184#else
185 strm << getAnsiColorCodeRestoreDefault().c_str();
186#endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE)
187 }
188
189#if defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE)
190 const HANDLE mStreamHandle;
191 WORD mSavedConsoleBufferInfo;
192#endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE)
193};
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.