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

Last change on this file was 349, checked in by DHERBOMEZ Gérald, 9 years ago

build of the trunk (release 0.2.x) under Linux Mint 17.2

File size: 12.2 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 //BOOST_DELETED_FUNCTION(FormatSeverityWithColorsTerminal())
306 FormatSeverityWithColorsTerminal() = delete;
307};
308
309template< typename T, typename FallbackPolicyT, typename CharT = char, template< typename > class ActorT = boost::phoenix::actor >
310class FormatSeverityWithColorsActor
311 : public ActorT< FormatSeverityWithColorsTerminal< T, FallbackPolicyT, CharT > >
312{
313public:
314 //! Attribute value type
315 typedef T value_type;
316 //! Character type
317 typedef CharT char_type;
318 //! Fallback policy
319 typedef FallbackPolicyT fallback_policy;
320 //! Base terminal type
321 typedef FormatSeverityWithColorsTerminal< value_type, fallback_policy, char_type > terminal_type;
322 //! Formatter function
323 typedef typename terminal_type::formatter_function_type formatter_function_type;
324
325 //! Base actor type
326 typedef ActorT< terminal_type > base_type;
327
328public:
329 //! Initializing constructor
330 explicit FormatSeverityWithColorsActor(base_type const& act)
331 : base_type(act)
332 {
333 }
334};
335
336template< typename AttributeValueT >
337/*BOOST_FORCEINLINE*/ FormatSeverityWithColorsActor< AttributeValueT, boost::log::fallback_to_none >
338formatSeverityWithColors(boost::log::attribute_name const& name, bool restoreDefault = false)
339{
340 using boost::log::fallback_to_none;
341 typedef FormatSeverityWithColorsActor< AttributeValueT, fallback_to_none > actor_type;
342 typedef typename actor_type::terminal_type terminal_type;
343 typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), restoreDefault) }};
344 return actor_type(act);
345}
346
347template< typename DescriptorT, template< typename > class ActorT, typename CharT >
348/*BOOST_FORCEINLINE*/ FormatSeverityWithColorsActor< typename DescriptorT::value_type, boost::log::fallback_to_none, CharT, ActorT >
349formatSeverityWithColors(boost::log::expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, bool restoreDefault = false)
350{
351 using boost::log::fallback_to_none;
352 typedef FormatSeverityWithColorsActor< typename DescriptorT::value_type, fallback_to_none, CharT, ActorT > actor_type;
353 typedef typename actor_type::terminal_type terminal_type;
354 typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), restoreDefault) }};
355 return actor_type(act);
356}
357
358template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT>
359/*BOOST_FORCEINLINE*/ FormatSeverityWithColorsActor< T, FallbackPolicyT, char, ActorT >
360formatSeverityWithColors(boost::log::expressions::attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, bool restoreDefault = false)
361{
362 typedef FormatSeverityWithColorsActor< T, FallbackPolicyT, char, ActorT > actor_type;
363 typedef typename actor_type::terminal_type terminal_type;
364 typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), restoreDefault) }};
365 return actor_type(act);
366}
367
368} // namespace pacpus
369
370#endif // defined(PACPUS_LOG_COLORED_OUTPUT)
371
372#endif // COLORSEVERITYFORMATTER_HPP
Note: See TracBrowser for help on using the repository browser.