// %pacpus:license{ // This file is part of the PACPUS framework distributed under the // CECILL-C License, Version 1.0. // %pacpus:license} /// @version $Id: Log.cpp 76 2013-01-10 17:05:10Z kurdejma $ /// @file /// @author Marek Kurdej /// @date 2013-11-28 /// @version $Id$ /// @copyright Copyright (c) UTC/CNRS Heudiasyc 2006 - 2013. All rights reserved. /// @brief Color logger output depending on severity level. /// /// Detailed description. #ifndef COLORSEVERITYFORMATTER_HPP #define COLORSEVERITYFORMATTER_HPP #if defined(PACPUS_LOG_COLORED_OUTPUT) #include #include #include #include #include #include // could use Boost.Predef with Boost >= 1.55 #if defined(WIN32) || defined(_WINDOWS) # define PACPUS_OS_WINDOWS 1 #elif defined(__unix) || defined(__unix__) # define PACPUS_OS_UNIX 1 # if defined(__linux) || defined(__linux__) # define PACPUS_OS_LINUX 1 # endif #elif defined(__APPLE__) || defined(__MACH__) || defined(Macintosh) || defined(macintosh) # define PACPUS_OS_MACOS 1 #else // unknown system #endif #if defined(PACPUS_OS_WINDOWS) # include #endif namespace pacpus { enum Color { COLOR_DEFAULT, COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE }; Color getColor(SeverityLevel const& sev) { if (sev >= error) { return COLOR_RED; } else if (sev >= warning) { return COLOR_YELLOW; } else if (sev >= info) { return COLOR_WHITE; //COLOR_GREEN; } return COLOR_DEFAULT; } #if defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) // Returns the character attribute for the given color. WORD getColorAttribute(Color color) { switch (color) { case COLOR_BLACK: return 0; case COLOR_RED: return FOREGROUND_RED; case COLOR_GREEN: return FOREGROUND_GREEN; case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; case COLOR_BLUE: return FOREGROUND_BLUE; case COLOR_MAGENTA: return FOREGROUND_RED | FOREGROUND_BLUE; case COLOR_CYAN: return FOREGROUND_GREEN | FOREGROUND_BLUE; case COLOR_WHITE: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; default: return 0; } } #else /// @returns the ANSI color code for the given color. COLOR_DEFAULT is /// an invalid input. std::string getAnsiColorCode(Color color) { const char* kEscapeSequence = "\033["; // const char* kBackground = ""; const char* kFontRegular = "0;"; // const char* kFontBold = "1;"; // const char* kFontWeak = "2;"; // const char* kFontStrong = "3;"; // const char* kFontUnderline = "4;"; std::stringstream ss; ss << kEscapeSequence << kFontRegular; switch (color) { case COLOR_BLACK: ss << "30"; break; case COLOR_RED: ss << "31"; break; case COLOR_GREEN: ss << "32"; break; case COLOR_YELLOW: ss << "33"; break; case COLOR_BLUE: ss << "34"; break; case COLOR_MAGENTA: ss << "35"; break; case COLOR_CYAN: ss << "36"; break; case COLOR_WHITE: ss << "37"; break; default: return ""; }; const char* kPostfix = "m"; ss << kPostfix; return ss.str(); } std::string getAnsiColorCodeRestoreDefault() { return "\033[0m"; } #endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) template < typename CharT > struct ColorFormatter { #if defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) ColorFormatter() : mStreamHandle(GetStdHandle(STD_OUTPUT_HANDLE)) { } #endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) void operator()(boost::log::basic_formatting_ostream& strm, SeverityLevel const& sev) { #if defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) // Gets the current text color. CONSOLE_SCREEN_BUFFER_INFO bufferInfo; GetConsoleScreenBufferInfo(mStreamHandle, &bufferInfo); mSavedConsoleBufferInfo = bufferInfo.wAttributes; // We need to flush the stream buffers into the console before each // SetConsoleTextAttribute call lest it affect the text that is already // printed but has not yet reached the console. fflush(stdout); SetConsoleTextAttribute(mStreamHandle, getColorAttribute(getColor(sev)) | FOREGROUND_INTENSITY); #else strm << getAnsiColorCode(getColor(sev)).c_str(); #endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) } #if defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) const HANDLE mStreamHandle; WORD mSavedConsoleBufferInfo; #endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) }; template < typename CharT > struct DefaultFormatter { #if defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) DefaultFormatter() //(WORD savedConsoleBufferInfo) : mStreamHandle(GetStdHandle(STD_OUTPUT_HANDLE)) //, mSavedConsoleBufferInfo(savedConsoleBufferInfo) , mSavedConsoleBufferInfo(getColorAttribute(COLOR_WHITE) | FOREGROUND_INTENSITY) // FIXME: restore old value, not just reset { } #endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) void operator()(boost::log::basic_formatting_ostream& strm, SeverityLevel const& /*sev*/) { #if defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) fflush(stdout); // Restores the text color. SetConsoleTextAttribute(mStreamHandle, mSavedConsoleBufferInfo); #else strm << getAnsiColorCodeRestoreDefault().c_str(); #endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) } #if defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) const HANDLE mStreamHandle; WORD mSavedConsoleBufferInfo; #endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) }; template< typename T, typename FallbackPolicyT, typename CharT > class FormatSeverityWithColorsTerminal { public: //! Internal typedef for type categorization typedef void _is_boost_log_terminal; //! Attribute value type typedef T value_type; //! Fallback policy typedef FallbackPolicyT fallback_policy; //! Character type typedef CharT char_type; //! String type typedef std::basic_string< char_type > string_type; //! Formatting stream type typedef boost::log::basic_formatting_ostream< char_type > stream_type; //! Formatter function typedef boost::log::aux::light_function< void (stream_type&, value_type const&) > formatter_function_type; //! Function result type typedef string_type result_type; typedef boost::log::attribute_name attribute_name; private: //! Attribute value visitor invoker typedef boost::log::value_visitor_invoker< value_type, fallback_policy > visitor_invoker_type; private: //! Attribute name attribute_name m_name; //! Formattr function formatter_function_type m_formatter; //! Attribute value visitor invoker visitor_invoker_type m_visitor_invoker; public: //! Initializing constructor FormatSeverityWithColorsTerminal(attribute_name const& name, fallback_policy const& fallback, bool restoreDefault) : m_name(name) //, m_formatter(formatter_generator::parse(format)) , m_visitor_invoker(fallback) { if (restoreDefault) { //#if defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) // m_formatter = formatter_function_type(DefaultFormatter()); //#else // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) m_formatter = formatter_function_type(DefaultFormatter()); //#endif // defined(PACPUS_OS_WINDOWS) && !defined(PACPUS_OS_WINDOWS_MOBILE) } else { m_formatter = formatter_function_type(ColorFormatter()); } } //! Copy constructor FormatSeverityWithColorsTerminal(FormatSeverityWithColorsTerminal const& that) : m_name(that.m_name), m_formatter(that.m_formatter), m_visitor_invoker(that.m_visitor_invoker) { } //! Invokation operator template< typename ContextT > result_type operator() (ContextT const& ctx) { using namespace boost; using boost::log::binder1st; string_type str; stream_type strm(str); m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type&, stream_type& >(m_formatter, strm)); strm.flush(); return boost::move(str); } //! Invokation operator template< typename ContextT > result_type operator() (ContextT const& ctx) const { using namespace boost; using boost::log::binder1st; string_type str; stream_type strm(str); m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< formatter_function_type const&, stream_type& >(m_formatter, strm)); strm.flush(); return boost::move(str); } BOOST_DELETED_FUNCTION(FormatSeverityWithColorsTerminal()) }; template< typename T, typename FallbackPolicyT, typename CharT = char, template< typename > class ActorT = boost::phoenix::actor > class FormatSeverityWithColorsActor : public ActorT< FormatSeverityWithColorsTerminal< T, FallbackPolicyT, CharT > > { public: //! Attribute value type typedef T value_type; //! Character type typedef CharT char_type; //! Fallback policy typedef FallbackPolicyT fallback_policy; //! Base terminal type typedef FormatSeverityWithColorsTerminal< value_type, fallback_policy, char_type > terminal_type; //! Formatter function typedef typename terminal_type::formatter_function_type formatter_function_type; //! Base actor type typedef ActorT< terminal_type > base_type; public: //! Initializing constructor explicit FormatSeverityWithColorsActor(base_type const& act) : base_type(act) { } }; template< typename AttributeValueT > /*BOOST_FORCEINLINE*/ FormatSeverityWithColorsActor< AttributeValueT, boost::log::fallback_to_none > formatSeverityWithColors(boost::log::attribute_name const& name, bool restoreDefault = false) { using boost::log::fallback_to_none; typedef FormatSeverityWithColorsActor< AttributeValueT, fallback_to_none > actor_type; typedef typename actor_type::terminal_type terminal_type; typename actor_type::base_type act = {{ terminal_type(name, fallback_to_none(), restoreDefault) }}; return actor_type(act); } template< typename DescriptorT, template< typename > class ActorT, typename CharT > /*BOOST_FORCEINLINE*/ FormatSeverityWithColorsActor< typename DescriptorT::value_type, boost::log::fallback_to_none, CharT, ActorT > formatSeverityWithColors(boost::log::expressions::attribute_keyword< DescriptorT, ActorT > const& keyword, bool restoreDefault = false) { using boost::log::fallback_to_none; typedef FormatSeverityWithColorsActor< typename DescriptorT::value_type, fallback_to_none, CharT, ActorT > actor_type; typedef typename actor_type::terminal_type terminal_type; typename actor_type::base_type act = {{ terminal_type(keyword.get_name(), fallback_to_none(), restoreDefault) }}; return actor_type(act); } template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT> /*BOOST_FORCEINLINE*/ FormatSeverityWithColorsActor< T, FallbackPolicyT, char, ActorT > formatSeverityWithColors(boost::log::expressions::attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, bool restoreDefault = false) { typedef FormatSeverityWithColorsActor< T, FallbackPolicyT, char, ActorT > actor_type; typedef typename actor_type::terminal_type terminal_type; typename actor_type::base_type act = {{ terminal_type(placeholder.get_name(), placeholder.get_fallback_policy(), restoreDefault) }}; return actor_type(act); } } // namespace pacpus #endif // defined(PACPUS_LOG_COLORED_OUTPUT) #endif // COLORSEVERITYFORMATTER_HPP