/* * Copyright Andrey Semashev 2007 - 2015. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) */ /*! * \file default_formatter_factory.cpp * \author Andrey Semashev * \date 14.07.2013 * * \brief This header is the Boost.Log library implementation, see the library documentation * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. */ #if !defined(BOOST_LOG_WITHOUT_SETTINGS_PARSERS) && !defined(BOOST_LOG_WITHOUT_DEFAULT_FACTORIES) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if !defined(BOOST_LOG_NO_THREADS) #include #endif #include #include "default_formatter_factory.hpp" #include namespace boost { BOOST_LOG_OPEN_NAMESPACE namespace aux { #if !defined(BOOST_LOG_NO_THREADS) #define BOOST_LOG_AUX_THREAD_ID_TYPE() (boost::log::aux::thread::id) #else #define BOOST_LOG_AUX_THREAD_ID_TYPE() #endif #define BOOST_LOG_AUX_LOG_ATTRIBUTE_VALUE_TYPES()\ (boost::log::trivial::severity_level)\ (boost::log::attributes::named_scope_list)\ (boost::log::aux::process::id)\ BOOST_LOG_AUX_THREAD_ID_TYPE() // The list of the attribute value types supported by the default formatter. Note that we have to exclude std::time_t // as it is an integral type, as well as double from the native time duration types - these are part of arithmetic types already. #define BOOST_LOG_AUX_LOG_DEFAULT_VALUE_TYPES()\ BOOST_LOG_DEFAULT_ATTRIBUTE_VALUE_TYPES()\ (std::tm)\ BOOST_LOG_BOOST_DATE_TYPES()\ BOOST_LOG_BOOST_TIME_DURATION_TYPES()\ BOOST_LOG_BOOST_TIME_PERIOD_TYPES()\ BOOST_LOG_AUX_LOG_ATTRIBUTE_VALUE_TYPES() BOOST_LOG_ANONYMOUS_NAMESPACE { //! The default formatter generated by the default formatter factory template< typename CharT > class default_formatter { public: typedef void result_type; private: //! Attribute value visitor struct visitor { typedef void result_type; explicit visitor(basic_formatting_ostream< CharT >& strm) : m_strm(strm) { } template< typename T > void operator() (T const& value) const { m_strm << value; } void operator() (std::tm const& value) const { char buf[32]; std::size_t len = std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &value); m_strm.write(buf, len); } void operator() (boost::posix_time::ptime const& value) const { if (!value.is_special()) { std::tm t = boost::posix_time::to_tm(value); char buf[32]; std::size_t len = std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &t); std::size_t size = sizeof(buf) - len; int res = boost::log::aux::snprintf(buf + len, size, ".%.6u", static_cast< unsigned int >(value.time_of_day().total_microseconds() % 1000000)); if (res < 0) buf[len] = '\0'; else if (static_cast< std::size_t >(res) >= size) len += size - 1; else len += res; m_strm.write(buf, len); } else { format_special_date_time(value); } } void operator() (boost::local_time::local_date_time const& value) const { if (!value.is_special()) { this->operator()(value.local_time()); m_strm << ' ' << value.zone_as_posix_string(); } else { format_special_date_time(value); } } void operator() (boost::gregorian::date const& value) const { if (!value.is_special()) { std::tm t = boost::gregorian::to_tm(value); char buf[32]; std::size_t len = std::strftime(buf, sizeof(buf), "%Y-%m-%d", &t); m_strm.write(buf, len); } else { format_special_date_time(value.as_special()); } } void operator() (boost::posix_time::time_duration const& value) const { if (!value.is_special()) { boost::posix_time::time_duration val = value; if (val.is_negative()) { m_strm << '-'; val = -val; } unsigned long long total_useconds = value.total_microseconds(); unsigned long long hours = total_useconds / (3600ull * 1000000ull); unsigned int minutes = static_cast< unsigned int >(total_useconds / (60ull * 1000000ull) % 60ull); unsigned int seconds = static_cast< unsigned int >(total_useconds / 1000000ull % 60ull); unsigned int useconds = static_cast< unsigned int >(total_useconds % 1000000ull); char buf[64]; int len = boost::log::aux::snprintf(buf, sizeof(buf), "%.2llu:%.2u:%.2u.%.6u", hours, minutes, seconds, useconds); if (len > 0) { unsigned int size = static_cast< unsigned int >(len) >= sizeof(buf) ? static_cast< unsigned int >(sizeof(buf)) : static_cast< unsigned int >(len); m_strm.write(buf, size); } } else { format_special_date_time(value); } } void operator() (boost::gregorian::date_duration const& value) const { if (!value.is_special()) { m_strm << value.get_rep().as_number(); } else { format_special_date_time(value.get_rep().as_special()); } } template< typename PointRepT, typename DurationRepT > void operator() (boost::date_time::period< PointRepT, DurationRepT > const& value) const { m_strm << '['; this->operator()(value.begin()); m_strm << '/'; this->operator()(value.last()); m_strm << ']'; } private: template< typename T > void format_special_date_time(T const& value) const { if (value.is_not_a_date_time()) m_strm << "not-a-date-time"; else if (value.is_pos_infinity()) m_strm << "+infinity"; else if (value.is_neg_infinity()) m_strm << "-infinity"; } void format_special_date_time(boost::date_time::special_values value) const { switch (value) { case boost::date_time::not_a_date_time: m_strm << "not-a-date-time"; break; case boost::date_time::pos_infin: m_strm << "+infinity"; break; case boost::date_time::neg_infin: m_strm << "-infinity"; break; default: break; } } private: basic_formatting_ostream< CharT >& m_strm; }; public: explicit default_formatter(attribute_name name) : m_attribute_name(name) { } result_type operator() (record_view const& rec, basic_formatting_ostream< CharT >& strm) const { typedef BOOST_PP_CAT(mpl::vector, BOOST_PP_SEQ_SIZE(BOOST_LOG_AUX_LOG_DEFAULT_VALUE_TYPES()))< BOOST_PP_SEQ_ENUM(BOOST_LOG_AUX_LOG_DEFAULT_VALUE_TYPES()) > value_types; boost::log::visit< value_types >(m_attribute_name, rec, visitor(strm)); } private: const attribute_name m_attribute_name; }; } // namespace //! The callback for equality relation filter template< typename CharT > typename default_formatter_factory< CharT >::formatter_type default_formatter_factory< CharT >::create_formatter(attribute_name const& name, args_map const& args) { // No user-defined factory, shall use the most generic formatter we can ever imagine at this point return formatter_type(default_formatter< CharT >(name)); } // Explicitly instantiate factory implementation #ifdef BOOST_LOG_USE_CHAR template class default_formatter_factory< char >; #endif #ifdef BOOST_LOG_USE_WCHAR_T template class default_formatter_factory< wchar_t >; #endif } // namespace aux BOOST_LOG_CLOSE_NAMESPACE // namespace log } // namespace boost #include #endif // !defined(BOOST_LOG_WITHOUT_SETTINGS_PARSERS) && !defined(BOOST_LOG_WITHOUT_DEFAULT_FACTORIES)