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