From 7d7b70e78bb6a3ec4e1752fed34717b3b80139c8 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 25 Jul 2015 23:58:02 +0300 Subject: [PATCH] The default formatter has been rewritten to avoid using Boost.Phoenix. This reduces compile times and binary sizes. It should also fix compilation with compilers not able to handle Boost.Phoenix (see #11200). Also, date/time format has changed. The default formatter will produce dates with numeric months instead of abbreviated month names (see #8839). The standard attribute value types supported by default parsed formatters now include char16_t and char32_t, when available. This required to add new code conversion routines. Added Boost.PP sequences with the standard types. These are used to generate the corresponding type sequences, which is faster to compile than doing this with Boost.MPL. --- include/boost/log/detail/code_conversion.hpp | 52 +++- .../boost/log/detail/is_character_type.hpp | 75 ++++++ .../utility/type_dispatch/date_time_types.hpp | 94 +++++-- .../utility/type_dispatch/standard_types.hpp | 122 ++++++--- src/code_conversion.cpp | 49 +++- src/default_filter_factory.cpp | 11 +- src/default_formatter_factory.cpp | 255 +++++++++++++++--- 7 files changed, 521 insertions(+), 137 deletions(-) create mode 100644 include/boost/log/detail/is_character_type.hpp diff --git a/include/boost/log/detail/code_conversion.hpp b/include/boost/log/detail/code_conversion.hpp index 4c39f9c..d4a01b9 100644 --- a/include/boost/log/detail/code_conversion.hpp +++ b/include/boost/log/detail/code_conversion.hpp @@ -16,9 +16,12 @@ #ifndef BOOST_LOG_DETAIL_CODE_CONVERSION_HPP_INCLUDED_ #define BOOST_LOG_DETAIL_CODE_CONVERSION_HPP_INCLUDED_ +#include #include #include +#include #include +#include #include #ifdef BOOST_HAS_PRAGMA_ONCE @@ -32,44 +35,65 @@ BOOST_LOG_OPEN_NAMESPACE namespace aux { //! The function converts one string to the character type of another -BOOST_LOG_API void code_convert(const wchar_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale()); +BOOST_LOG_API void code_convert_impl(const wchar_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale()); //! The function converts one string to the character type of another -BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::wstring& str2, std::locale const& loc = std::locale()); +BOOST_LOG_API void code_convert_impl(const char* str1, std::size_t len, std::wstring& str2, std::locale const& loc = std::locale()); // Note: MSVC 2015 (aka VC14) implement char16_t and char32_t types but not codecvt locale facets #if !defined(BOOST_MSVC) #if !defined(BOOST_NO_CXX11_CHAR16_T) //! The function converts one string to the character type of another -BOOST_LOG_API void code_convert(const char16_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale()); +BOOST_LOG_API void code_convert_impl(const char16_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale()); //! The function converts one string to the character type of another -BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::u16string& str2, std::locale const& loc = std::locale()); +BOOST_LOG_API void code_convert_impl(const char* str1, std::size_t len, std::u16string& str2, std::locale const& loc = std::locale()); +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert_impl(const char16_t* str1, std::size_t len, std::wstring& str2, std::locale const& loc = std::locale()); #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) //! The function converts one string to the character type of another -BOOST_LOG_API void code_convert(const char32_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale()); +BOOST_LOG_API void code_convert_impl(const char32_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale()); //! The function converts one string to the character type of another -BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::u32string& str2, std::locale const& loc = std::locale()); +BOOST_LOG_API void code_convert_impl(const char* str1, std::size_t len, std::u32string& str2, std::locale const& loc = std::locale()); +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert_impl(const char32_t* str1, std::size_t len, std::wstring& str2, std::locale const& loc = std::locale()); +#endif +#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_CHAR32_T) +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert_impl(const char16_t* str1, std::size_t len, std::u32string& str2, std::locale const& loc = std::locale()); +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert_impl(const char32_t* str1, std::size_t len, std::u16string& str2, std::locale const& loc = std::locale()); #endif #endif // !defined(BOOST_MSVC) //! The function converts one string to the character type of another -template< typename CharT, typename SourceTraitsT, typename SourceAllocatorT, typename TargetTraitsT, typename TargetAllocatorT > -inline void code_convert(std::basic_string< CharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< CharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& = std::locale()) +template< typename SourceCharT, typename SourceTraitsT, typename SourceAllocatorT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT > +inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) == sizeof(TargetCharT) >::type +code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& = std::locale()) { - str2.append(str1.c_str(), str1.size()); + str2.append(reinterpret_cast< const TargetCharT* >(str1.c_str()), str1.size()); } //! The function converts one string to the character type of another -template< typename CharT, typename TargetTraitsT, typename TargetAllocatorT > -inline void code_convert(const CharT* str1, std::size_t len, std::basic_string< CharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& = std::locale()) +template< typename SourceCharT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT > +inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) == sizeof(TargetCharT) >::type +code_convert(const SourceCharT* str1, std::size_t len, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& = std::locale()) { - str2.append(str1, len); + str2.append(reinterpret_cast< const TargetCharT* >(str1), len); } //! The function converts one string to the character type of another template< typename SourceCharT, typename SourceTraitsT, typename SourceAllocatorT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT > -inline void code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& loc = std::locale()) +inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) != sizeof(TargetCharT) >::type +code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& loc = std::locale()) { - aux::code_convert(str1.c_str(), str1.size(), str2, loc); + aux::code_convert_impl(str1.c_str(), str1.size(), str2, loc); +} + +//! The function converts one string to the character type of another +template< typename SourceCharT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT > +inline typename boost::enable_if_c< is_character_type< SourceCharT >::value && is_character_type< TargetCharT >::value && sizeof(SourceCharT) != sizeof(TargetCharT) >::type +code_convert(const SourceCharT* str1, std::size_t len, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& loc = std::locale()) +{ + aux::code_convert_impl(str1, len, str2, loc); } //! The function converts the passed string to the narrow-character encoding diff --git a/include/boost/log/detail/is_character_type.hpp b/include/boost/log/detail/is_character_type.hpp new file mode 100644 index 0000000..29f7dcc --- /dev/null +++ b/include/boost/log/detail/is_character_type.hpp @@ -0,0 +1,75 @@ +/* + * 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 is_character_type.hpp + * \author Andrey Semashev + * \date 25.07.2015 + * + * The header defines \c is_character_type trait which checks if the type is one of the character types + */ + +#ifndef BOOST_LOG_DETAIL_IS_CHARACTER_TYPE_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_IS_CHARACTER_TYPE_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +template< typename T > +struct is_character_type +{ + static BOOST_CONSTEXPR_OR_CONST bool value = false; +}; + +template< > +struct is_character_type< char > +{ + static BOOST_CONSTEXPR_OR_CONST bool value = true; +}; + +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) +template< > +struct is_character_type< wchar_t > +{ + static BOOST_CONSTEXPR_OR_CONST bool value = true; +}; +#endif + +#if !defined(BOOST_NO_CXX11_CHAR16_T) +template< > +struct is_character_type< char16_t > +{ + static BOOST_CONSTEXPR_OR_CONST bool value = true; +}; +#endif + +#if !defined(BOOST_NO_CXX11_CHAR32_T) +template< > +struct is_character_type< char32_t > +{ + static BOOST_CONSTEXPR_OR_CONST bool value = true; +}; +#endif + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include + +#endif // BOOST_LOG_DETAIL_IS_CHARACTER_TYPE_HPP_INCLUDED_ diff --git a/include/boost/log/utility/type_dispatch/date_time_types.hpp b/include/boost/log/utility/type_dispatch/date_time_types.hpp index 36c9265..38e6a46 100644 --- a/include/boost/log/utility/type_dispatch/date_time_types.hpp +++ b/include/boost/log/utility/type_dispatch/date_time_types.hpp @@ -17,9 +17,7 @@ #include #include -#include -#include -#include +#include #include #include #include @@ -34,29 +32,73 @@ namespace boost { BOOST_LOG_OPEN_NAMESPACE +//! Boost.Preprocessor sequence of the standard C date/time types +#define BOOST_LOG_NATIVE_DATE_TIME_TYPES()\ + (std::time_t)(std::tm) + +//! Boost.Preprocessor sequence of the standard C date types +#define BOOST_LOG_NATIVE_DATE_TYPES()\ + BOOST_LOG_NATIVE_DATE_TIME_TYPES() + +//! Boost.Preprocessor sequence of the Boost date/time types +#define BOOST_LOG_BOOST_DATE_TIME_TYPES()\ + (boost::posix_time::ptime)(boost::local_time::local_date_time) + +//! Boost.Preprocessor sequence of date/time types +#define BOOST_LOG_DATE_TIME_TYPES()\ + BOOST_LOG_NATIVE_DATE_TIME_TYPES()BOOST_LOG_BOOST_DATE_TIME_TYPES()\ + +//! Boost.Preprocessor sequence of the Boost date types +#define BOOST_LOG_BOOST_DATE_TYPES()\ + BOOST_LOG_BOOST_DATE_TIME_TYPES()(boost::gregorian::date) + +//! Boost.Preprocessor sequence of date types +#define BOOST_LOG_DATE_TYPES()\ + BOOST_LOG_NATIVE_DATE_TYPES()BOOST_LOG_BOOST_DATE_TYPES() + + +//! Boost.Preprocessor sequence of the standard time duration types +#define BOOST_LOG_NATIVE_TIME_DURATION_TYPES()\ + (double) /* result of difftime() */ + +//! Boost.Preprocessor sequence of the Boost time duration types +#define BOOST_LOG_BOOST_TIME_DURATION_TYPES()\ + (boost::posix_time::time_duration)(boost::gregorian::date_duration) + +//! Boost.Preprocessor sequence of time duration types +#define BOOST_LOG_TIME_DURATION_TYPES()\ + BOOST_LOG_NATIVE_TIME_DURATION_TYPES()BOOST_LOG_BOOST_TIME_DURATION_TYPES() + + +//! Boost.Preprocessor sequence of the Boost time period types +#define BOOST_LOG_BOOST_TIME_PERIOD_TYPES()\ + (boost::posix_time::time_period)(boost::local_time::local_time_period)(boost::gregorian::date_period) + +//! Boost.Preprocessor sequence of time period types +#define BOOST_LOG_TIME_PERIOD_TYPES()\ + BOOST_LOG_BOOST_TIME_PERIOD_TYPES() + + /*! * An MPL-sequence of natively supported date and time types of attributes */ typedef mpl::vector< - std::time_t, - std::tm + BOOST_PP_SEQ_ENUM(BOOST_LOG_NATIVE_DATE_TIME_TYPES()) > native_date_time_types; /*! * An MPL-sequence of Boost date and time types of attributes */ typedef mpl::vector< - posix_time::ptime, - local_time::local_date_time + BOOST_PP_SEQ_ENUM(BOOST_LOG_BOOST_DATE_TIME_TYPES()) > boost_date_time_types; /*! * An MPL-sequence with the complete list of the supported date and time types */ -typedef mpl::copy< - boost_date_time_types, - mpl::back_inserter< native_date_time_types > ->::type date_time_types; +typedef mpl::vector< + BOOST_PP_SEQ_ENUM(BOOST_LOG_DATE_TIME_TYPES()) +> date_time_types; /*! * An MPL-sequence of natively supported date types of attributes @@ -66,18 +108,16 @@ typedef native_date_time_types native_date_types; /*! * An MPL-sequence of Boost date types of attributes */ -typedef mpl::push_back< - boost_date_time_types, - gregorian::date ->::type boost_date_types; +typedef mpl::vector< + BOOST_PP_SEQ_ENUM(BOOST_LOG_BOOST_DATE_TYPES()) +> boost_date_types; /*! * An MPL-sequence with the complete list of the supported date types */ -typedef mpl::copy< - boost_date_types, - mpl::back_inserter< native_date_types > ->::type date_types; +typedef mpl::vector< + BOOST_PP_SEQ_ENUM(BOOST_LOG_DATE_TYPES()) +> date_types; /*! * An MPL-sequence of natively supported time types @@ -96,32 +136,28 @@ typedef date_time_types time_types; * An MPL-sequence of natively supported time duration types of attributes */ typedef mpl::vector< - double // result of difftime + BOOST_PP_SEQ_ENUM(BOOST_LOG_NATIVE_TIME_DURATION_TYPES()) > native_time_duration_types; /*! * An MPL-sequence of Boost time duration types of attributes */ typedef mpl::vector< - posix_time::time_duration, - gregorian::date_duration + BOOST_PP_SEQ_ENUM(BOOST_LOG_BOOST_TIME_DURATION_TYPES()) > boost_time_duration_types; /*! * An MPL-sequence with the complete list of the supported time duration types */ -typedef mpl::copy< - boost_time_duration_types, - mpl::back_inserter< native_time_duration_types > ->::type time_duration_types; +typedef mpl::vector< + BOOST_PP_SEQ_ENUM(BOOST_LOG_TIME_DURATION_TYPES()) +> time_duration_types; /*! * An MPL-sequence of Boost time duration types of attributes */ typedef mpl::vector< - posix_time::time_period, - local_time::local_time_period, - gregorian::date_period + BOOST_PP_SEQ_ENUM(BOOST_LOG_BOOST_TIME_PERIOD_TYPES()) > boost_time_period_types; /*! diff --git a/include/boost/log/utility/type_dispatch/standard_types.hpp b/include/boost/log/utility/type_dispatch/standard_types.hpp index a437f6f..dbdfe43 100644 --- a/include/boost/log/utility/type_dispatch/standard_types.hpp +++ b/include/boost/log/utility/type_dispatch/standard_types.hpp @@ -17,8 +17,10 @@ #include #include -#include -#include +#include // needed to use mpl::vector sizes greater than 20 even when the default BOOST_MPL_LIMIT_VECTOR_SIZE is not set +#include +#include +#include #include #include #include @@ -31,70 +33,108 @@ namespace boost { BOOST_LOG_OPEN_NAMESPACE +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) +#define BOOST_LOG_AUX_STANDARD_TYPE_WCHAR_T() (wchar_t) +#else +#define BOOST_LOG_AUX_STANDARD_TYPE_WCHAR_T() +#endif + +#if !defined(BOOST_NO_CXX11_CHAR16_T) +#define BOOST_LOG_AUX_STANDARD_TYPE_CHAR16_T() (char16_t) +#else +#define BOOST_LOG_AUX_STANDARD_TYPE_CHAR16_T() +#endif + +#if !defined(BOOST_NO_CXX11_CHAR32_T) +#define BOOST_LOG_AUX_STANDARD_TYPE_CHAR32_T() (char32_t) +#else +#define BOOST_LOG_AUX_STANDARD_TYPE_CHAR32_T() +#endif + +//! Boost.Preprocessor sequence of character types +#define BOOST_LOG_STANDARD_CHAR_TYPES()\ + (char)BOOST_LOG_AUX_STANDARD_TYPE_WCHAR_T()BOOST_LOG_AUX_STANDARD_TYPE_CHAR16_T()BOOST_LOG_AUX_STANDARD_TYPE_CHAR32_T() + +#if defined(BOOST_HAS_LONG_LONG) +#define BOOST_LOG_AUX_STANDARD_LONG_LONG_TYPES() (long long)(unsigned long long) +#else +#define BOOST_LOG_AUX_STANDARD_LONG_LONG_TYPES() +#endif + +//! Boost.Preprocessor sequence of integral types +#define BOOST_LOG_STANDARD_INTEGRAL_TYPES()\ + (bool)(signed char)(unsigned char)(short)(unsigned short)(int)(unsigned int)(long)(unsigned long)BOOST_LOG_AUX_STANDARD_LONG_LONG_TYPES()\ + BOOST_LOG_STANDARD_CHAR_TYPES() + +//! Boost.Preprocessor sequence of floating point types +#define BOOST_LOG_STANDARD_FLOATING_POINT_TYPES()\ + (float)(double)(long double) + +//! Boost.Preprocessor sequence of arithmetic types +#define BOOST_LOG_STANDARD_ARITHMETIC_TYPES()\ + BOOST_LOG_STANDARD_INTEGRAL_TYPES()BOOST_LOG_STANDARD_FLOATING_POINT_TYPES() + +#if defined(BOOST_LOG_USE_CHAR) +#define BOOST_LOG_AUX_STANDARD_STRING_TYPES() (std::string)(boost::log::string_literal) +#else +#define BOOST_LOG_AUX_STANDARD_STRING_TYPES() +#endif + +#if defined(BOOST_LOG_USE_WCHAR_T) +#define BOOST_LOG_AUX_STANDARD_WSTRING_TYPES() (std::wstring)(boost::log::wstring_literal) +#else +#define BOOST_LOG_AUX_STANDARD_WSTRING_TYPES() +#endif + +//! Boost.Preprocessor sequence of string types +#define BOOST_LOG_STANDARD_STRING_TYPES()\ + BOOST_LOG_AUX_STANDARD_STRING_TYPES()BOOST_LOG_AUX_STANDARD_WSTRING_TYPES() + +//! Boost.Preprocessor sequence of the default attribute value types supported by the library +#define BOOST_LOG_DEFAULT_ATTRIBUTE_VALUE_TYPES()\ + BOOST_LOG_STANDARD_ARITHMETIC_TYPES()BOOST_LOG_STANDARD_STRING_TYPES() + + /*! * An MPL-sequence of integral types of attributes, supported by default */ typedef mpl::vector< - bool, - char, -#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) - wchar_t, -#endif - signed char, - unsigned char, - short, - unsigned short, - int, - unsigned int, - long, - unsigned long -#if defined(BOOST_HAS_LONG_LONG) - , long long - , unsigned long long -#endif // defined(BOOST_HAS_LONG_LONG) + BOOST_PP_SEQ_ENUM(BOOST_LOG_STANDARD_INTEGRAL_TYPES()) > integral_types; /*! * An MPL-sequence of FP types of attributes, supported by default */ typedef mpl::vector< - float, - double, - long double + BOOST_PP_SEQ_ENUM(BOOST_LOG_STANDARD_FLOATING_POINT_TYPES()) > floating_point_types; /*! * An MPL-sequence of all numeric types of attributes, supported by default */ -typedef mpl::copy< - floating_point_types, - mpl::back_inserter< integral_types > ->::type numeric_types; +typedef mpl::vector< + BOOST_PP_SEQ_ENUM(BOOST_LOG_STANDARD_ARITHMETIC_TYPES()) +> arithmetic_types; + +//! Deprecated alias +typedef arithmetic_types numeric_types; /*! * An MPL-sequence of string types of attributes, supported by default */ typedef mpl::vector< -#ifdef BOOST_LOG_USE_CHAR - std::string, - string_literal -#ifdef BOOST_LOG_USE_WCHAR_T - , -#endif -#endif -#ifdef BOOST_LOG_USE_WCHAR_T - std::wstring, - wstring_literal -#endif + BOOST_PP_SEQ_ENUM(BOOST_LOG_STANDARD_STRING_TYPES()) > string_types; /*! * An MPL-sequence of all attribute value types that are supported by the library by default. */ -typedef mpl::copy< - string_types, - mpl::back_inserter< numeric_types > ->::type default_attribute_types; +typedef BOOST_PP_CAT(mpl::vector, BOOST_PP_SEQ_SIZE(BOOST_LOG_DEFAULT_ATTRIBUTE_VALUE_TYPES()))< + BOOST_PP_SEQ_ENUM(BOOST_LOG_DEFAULT_ATTRIBUTE_VALUE_TYPES()) +> default_attribute_value_types; + +//! Deprecated alias +typedef default_attribute_value_types default_attribute_types; BOOST_LOG_CLOSE_NAMESPACE // namespace log diff --git a/src/code_conversion.cpp b/src/code_conversion.cpp index c4288fe..0b615dd 100644 --- a/src/code_conversion.cpp +++ b/src/code_conversion.cpp @@ -13,6 +13,7 @@ * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. */ +#include #include #include #include @@ -114,13 +115,13 @@ inline void code_convert(const SourceCharT* begin, const SourceCharT* end, std:: } //! The function converts one string to the character type of another -BOOST_LOG_API void code_convert(const wchar_t* str1, std::size_t len, std::string& str2, std::locale const& loc) +BOOST_LOG_API void code_convert_impl(const wchar_t* str1, std::size_t len, std::string& str2, std::locale const& loc) { code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(loc)); } //! The function converts one string to the character type of another -BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::wstring& str2, std::locale const& loc) +BOOST_LOG_API void code_convert_impl(const char* str1, std::size_t len, std::wstring& str2, std::locale const& loc) { code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(loc)); } @@ -131,33 +132,69 @@ BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::wstring& #if !defined(BOOST_NO_CXX11_CHAR16_T) //! The function converts one string to the character type of another -BOOST_LOG_API void code_convert(const char16_t* str1, std::size_t len, std::string& str2, std::locale const& loc) +BOOST_LOG_API void code_convert_impl(const char16_t* str1, std::size_t len, std::string& str2, std::locale const& loc) { code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< char16_t, char, std::mbstate_t > >(loc)); } //! The function converts one string to the character type of another -BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::u16string& str2, std::locale const& loc) +BOOST_LOG_API void code_convert_impl(const char* str1, std::size_t len, std::u16string& str2, std::locale const& loc) { code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< char16_t, char, std::mbstate_t > >(loc)); } +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert_impl(const char16_t* str1, std::size_t len, std::wstring& str2, std::locale const& loc) +{ + std::string temp_str; + code_convert(str1, str1 + len, temp_str, std::use_facet< std::codecvt< char16_t, char, std::mbstate_t > >(loc)); + code_convert(temp_str.c_str(), temp_str.c_str() + temp_str.size(), str2, std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(loc)); +} + #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) //! The function converts one string to the character type of another -BOOST_LOG_API void code_convert(const char32_t* str1, std::size_t len, std::string& str2, std::locale const& loc) +BOOST_LOG_API void code_convert_impl(const char32_t* str1, std::size_t len, std::string& str2, std::locale const& loc) { code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< char32_t, char, std::mbstate_t > >(loc)); } //! The function converts one string to the character type of another -BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::u32string& str2, std::locale const& loc) +BOOST_LOG_API void code_convert_impl(const char* str1, std::size_t len, std::u32string& str2, std::locale const& loc) { code_convert(str1, str1 + len, str2, std::use_facet< std::codecvt< char32_t, char, std::mbstate_t > >(loc)); } +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert_impl(const char32_t* str1, std::size_t len, std::wstring& str2, std::locale const& loc) +{ + std::string temp_str; + code_convert(str1, str1 + len, temp_str, std::use_facet< std::codecvt< char32_t, char, std::mbstate_t > >(loc)); + code_convert(temp_str.c_str(), temp_str.c_str() + temp_str.size(), str2, std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(loc)); +} + +#endif + +#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_CHAR32_T) + +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert_impl(const char16_t* str1, std::size_t len, std::u32string& str2, std::locale const& loc) +{ + std::string temp_str; + code_convert(str1, str1 + len, temp_str, std::use_facet< std::codecvt< char16_t, char, std::mbstate_t > >(loc)); + code_convert(temp_str.c_str(), temp_str.c_str() + temp_str.size(), str2, std::use_facet< std::codecvt< char32_t, char, std::mbstate_t > >(loc)); +} + +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert_impl(const char32_t* str1, std::size_t len, std::u16string& str2, std::locale const& loc) +{ + std::string temp_str; + code_convert(str1, str1 + len, temp_str, std::use_facet< std::codecvt< char32_t, char, std::mbstate_t > >(loc)); + code_convert(temp_str.c_str(), temp_str.c_str() + temp_str.size(), str2, std::use_facet< std::codecvt< char16_t, char, std::mbstate_t > >(loc)); +} + #endif #endif // !defined(BOOST_MSVC) diff --git a/src/default_filter_factory.cpp b/src/default_filter_factory.cpp index b87f929..5182ae0 100644 --- a/src/default_filter_factory.cpp +++ b/src/default_filter_factory.cpp @@ -16,8 +16,8 @@ #if !defined(BOOST_LOG_WITHOUT_SETTINGS_PARSERS) && !defined(BOOST_LOG_WITHOUT_DEFAULT_FACTORIES) #include -#include -#include +#include +#include #include #include #include @@ -181,10 +181,9 @@ private: const numeric_type m_numeric_operand; }; -typedef mpl::copy< - log::string_types, - mpl::back_inserter< log::floating_point_types > ->::type floating_point_and_string_types; +typedef mpl::vector< + BOOST_PP_SEQ_ENUM(BOOST_LOG_STANDARD_FLOATING_POINT_TYPES()BOOST_LOG_STANDARD_STRING_TYPES()) +> floating_point_and_string_types; } // namespace diff --git a/src/default_formatter_factory.cpp b/src/default_formatter_factory.cpp index 983d576..66474f4 100644 --- a/src/default_formatter_factory.cpp +++ b/src/default_formatter_factory.cpp @@ -5,7 +5,7 @@ * http://www.boost.org/LICENSE_1_0.txt) */ /*! - * \file default_formatter_factory.hpp + * \file default_formatter_factory.cpp * \author Andrey Semashev * \date 14.07.2013 * @@ -15,25 +15,24 @@ #if !defined(BOOST_LOG_WITHOUT_SETTINGS_PARSERS) && !defined(BOOST_LOG_WITHOUT_DEFAULT_FACTORIES) -#undef BOOST_MPL_LIMIT_VECTOR_SIZE -#define BOOST_MPL_LIMIT_VECTOR_SIZE 50 - +#include +#include #include -#include -#include -#include -#include -#include -#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 @@ -48,38 +47,212 @@ 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::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); + int res = boost::log::aux::snprintf(buf + len, sizeof(buf) - len, ".%06u", static_cast< unsigned int >(value.time_of_day().total_microseconds() % 1000000)); + if (res > 0) + 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 = total_useconds / (60ull * 1000000ull) % 60ull; + unsigned int seconds = total_useconds / 1000000ull % 60ull; + unsigned int useconds = total_useconds % 1000000ull; + char buf[64]; + int len = boost::log::aux::snprintf(buf, sizeof(buf), "%02llu:%02u:%02u.%06u", hours, minutes, seconds, useconds); + if (len > 0) + m_strm.write(buf, len); + } + 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::special_values::not_a_date_time: + m_strm << "not-a-date-time"; + break; + case boost::date_time::special_values::pos_infin: + m_strm << "+infinity"; + break; + case boost::date_time::special_values::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 - typedef mpl::copy< - // We have to exclude std::time_t since it's an integral type and will conflict with one of the standard types - boost_time_period_types, - mpl::back_inserter< - mpl::copy< - boost_time_duration_types, - mpl::back_inserter< boost_date_time_types > - >::type - > - >::type time_related_types; - - typedef mpl::copy< - mpl::copy< - mpl::vector< - attributes::named_scope_list, -#if !defined(BOOST_LOG_NO_THREADS) - log::aux::thread::id, -#endif - log::aux::process::id - >, - mpl::back_inserter< time_related_types > - >::type, - mpl::back_inserter< default_attribute_types > - >::type supported_types; - - return formatter_type(expressions::stream << expressions::attr< supported_types::type >(name)); + return formatter_type(default_formatter< CharT >(name)); } // Explicitly instantiate factory implementation