2 * Copyright Andrey Semashev 2007 - 2015.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
8 * \file default_formatter_factory.cpp
9 * \author Andrey Semashev
12 * \brief This header is the Boost.Log library implementation, see the library documentation
13 * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
16 #if !defined(BOOST_LOG_WITHOUT_SETTINGS_PARSERS) && !defined(BOOST_LOG_WITHOUT_DEFAULT_FACTORIES)
18 #include <boost/log/detail/setup_config.hpp>
21 #include <boost/mpl/vector.hpp>
22 #include <boost/mpl/vector/vector40.hpp>
23 #include <boost/preprocessor/cat.hpp>
24 #include <boost/preprocessor/seq/enum.hpp>
25 #include <boost/preprocessor/seq/size.hpp>
26 #include <boost/date_time/special_defs.hpp>
27 #include <boost/date_time/gregorian/gregorian_types.hpp>
28 #include <boost/date_time/local_time/local_time_types.hpp>
29 #include <boost/date_time/posix_time/posix_time_types.hpp>
30 #include <boost/log/attributes/attribute_name.hpp>
31 #include <boost/log/attributes/value_visitation.hpp>
32 #include <boost/log/utility/type_dispatch/standard_types.hpp>
33 #include <boost/log/utility/type_dispatch/date_time_types.hpp>
34 #include <boost/log/utility/string_literal.hpp>
35 #include <boost/log/utility/formatting_ostream.hpp>
36 #include <boost/log/detail/code_conversion.hpp>
37 #include <boost/log/detail/snprintf.hpp>
38 #include <boost/log/detail/process_id.hpp>
39 #if !defined(BOOST_LOG_NO_THREADS)
40 #include <boost/log/detail/thread_id.hpp>
42 #include <boost/log/attributes/named_scope.hpp>
43 #include "default_formatter_factory.hpp"
44 #include <boost/log/detail/header.hpp>
48 BOOST_LOG_OPEN_NAMESPACE
52 #if !defined(BOOST_LOG_NO_THREADS)
53 #define BOOST_LOG_AUX_THREAD_ID_TYPE() (boost::log::aux::thread::id)
55 #define BOOST_LOG_AUX_THREAD_ID_TYPE()
58 #define BOOST_LOG_AUX_LOG_ATTRIBUTE_VALUE_TYPES()\
59 (boost::log::attributes::named_scope_list)(boost::log::aux::process::id)BOOST_LOG_AUX_THREAD_ID_TYPE()
61 // The list of the attribute value types supported by the default formatter. Note that we have to exclude std::time_t
62 // as it is an integral type, as well as double from the native time duration types - these are part of arithmetic types already.
63 #define BOOST_LOG_AUX_LOG_DEFAULT_VALUE_TYPES()\
64 BOOST_LOG_DEFAULT_ATTRIBUTE_VALUE_TYPES()\
66 BOOST_LOG_BOOST_DATE_TYPES()\
67 BOOST_LOG_BOOST_TIME_DURATION_TYPES()\
68 BOOST_LOG_BOOST_TIME_PERIOD_TYPES()\
69 BOOST_LOG_AUX_LOG_ATTRIBUTE_VALUE_TYPES()
71 BOOST_LOG_ANONYMOUS_NAMESPACE
{
73 //! The default formatter generated by the default formatter factory
74 template< typename CharT
>
75 class default_formatter
78 typedef void result_type
;
81 //! Attribute value visitor
84 typedef void result_type
;
86 explicit visitor(basic_formatting_ostream
< CharT
>& strm
) : m_strm(strm
)
90 template< typename T
>
91 void operator() (T
const& value
) const
96 void operator() (std::tm
const& value
) const
99 std::size_t len
= std::strftime(buf
, sizeof(buf
), "%Y-%m-%d %H:%M:%S", &value
);
100 m_strm
.write(buf
, len
);
103 void operator() (boost::posix_time::ptime
const& value
) const
105 if (!value
.is_special())
107 std::tm t
= boost::posix_time::to_tm(value
);
109 std::size_t len
= std::strftime(buf
, sizeof(buf
), "%Y-%m-%d %H:%M:%S", &t
);
110 std::size_t size
= sizeof(buf
) - len
;
111 int res
= boost::log::aux::snprintf(buf
+ len
, size
, ".%.6u", static_cast< unsigned int >(value
.time_of_day().total_microseconds() % 1000000));
114 else if (static_cast< std::size_t >(res
) >= size
)
119 m_strm
.write(buf
, len
);
123 format_special_date_time(value
);
127 void operator() (boost::local_time::local_date_time
const& value
) const
129 if (!value
.is_special())
131 this->operator()(value
.local_time());
132 m_strm
<< ' ' << value
.zone_as_posix_string();
136 format_special_date_time(value
);
140 void operator() (boost::gregorian::date
const& value
) const
142 if (!value
.is_special())
144 std::tm t
= boost::gregorian::to_tm(value
);
146 std::size_t len
= std::strftime(buf
, sizeof(buf
), "%Y-%m-%d", &t
);
147 m_strm
.write(buf
, len
);
151 format_special_date_time(value
.as_special());
155 void operator() (boost::posix_time::time_duration
const& value
) const
157 if (!value
.is_special())
159 boost::posix_time::time_duration val
= value
;
160 if (val
.is_negative())
165 unsigned long long total_useconds
= value
.total_microseconds();
166 unsigned long long hours
= total_useconds
/ (3600ull * 1000000ull);
167 unsigned int minutes
= static_cast< unsigned int >(total_useconds
/ (60ull * 1000000ull) % 60ull);
168 unsigned int seconds
= static_cast< unsigned int >(total_useconds
/ 1000000ull % 60ull);
169 unsigned int useconds
= static_cast< unsigned int >(total_useconds
% 1000000ull);
171 int len
= boost::log::aux::snprintf(buf
, sizeof(buf
), "%.2llu:%.2u:%.2u.%.6u", hours
, minutes
, seconds
, useconds
);
174 unsigned int size
= static_cast< unsigned int >(len
) >= sizeof(buf
) ? static_cast< unsigned int >(sizeof(buf
)) : static_cast< unsigned int >(len
);
175 m_strm
.write(buf
, size
);
180 format_special_date_time(value
);
184 void operator() (boost::gregorian::date_duration
const& value
) const
186 if (!value
.is_special())
188 m_strm
<< value
.get_rep().as_number();
192 format_special_date_time(value
.get_rep().as_special());
196 template< typename PointRepT
, typename DurationRepT
>
197 void operator() (boost::date_time::period
< PointRepT
, DurationRepT
> const& value
) const
200 this->operator()(value
.begin());
202 this->operator()(value
.last());
207 template< typename T
>
208 void format_special_date_time(T
const& value
) const
210 if (value
.is_not_a_date_time())
211 m_strm
<< "not-a-date-time";
212 else if (value
.is_pos_infinity())
213 m_strm
<< "+infinity";
214 else if (value
.is_neg_infinity())
215 m_strm
<< "-infinity";
218 void format_special_date_time(boost::date_time::special_values value
) const
222 case boost::date_time::not_a_date_time
:
223 m_strm
<< "not-a-date-time";
225 case boost::date_time::pos_infin
:
226 m_strm
<< "+infinity";
228 case boost::date_time::neg_infin
:
229 m_strm
<< "-infinity";
237 basic_formatting_ostream
< CharT
>& m_strm
;
241 explicit default_formatter(attribute_name name
) : m_attribute_name(name
)
245 result_type
operator() (record_view
const& rec
, basic_formatting_ostream
< CharT
>& strm
) const
247 typedef BOOST_PP_CAT(mpl::vector
, BOOST_PP_SEQ_SIZE(BOOST_LOG_AUX_LOG_DEFAULT_VALUE_TYPES()))<
248 BOOST_PP_SEQ_ENUM(BOOST_LOG_AUX_LOG_DEFAULT_VALUE_TYPES())
251 boost::log::visit
< value_types
>(m_attribute_name
, rec
, visitor(strm
));
255 const attribute_name m_attribute_name
;
260 //! The callback for equality relation filter
261 template< typename CharT
>
262 typename default_formatter_factory
< CharT
>::formatter_type
263 default_formatter_factory
< CharT
>::create_formatter(attribute_name
const& name
, args_map
const& args
)
265 // No user-defined factory, shall use the most generic formatter we can ever imagine at this point
266 return formatter_type(default_formatter
< CharT
>(name
));
269 // Explicitly instantiate factory implementation
270 #ifdef BOOST_LOG_USE_CHAR
271 template class default_formatter_factory
< char >;
273 #ifdef BOOST_LOG_USE_WCHAR_T
274 template class default_formatter_factory
< wchar_t >;
279 BOOST_LOG_CLOSE_NAMESPACE
// namespace log
283 #include <boost/log/detail/footer.hpp>
285 #endif // !defined(BOOST_LOG_WITHOUT_SETTINGS_PARSERS) && !defined(BOOST_LOG_WITHOUT_DEFAULT_FACTORIES)