diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 4cb4041..1b40e1e 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -504,6 +504,45 @@ namespace boost { }; } + namespace detail // array_to_pointer_decay + { + template + struct array_to_pointer_decay + { + typedef T type; + }; + + template + struct array_to_pointer_decay + { + typedef const T * type; + }; + } + + namespace detail // is_this_float_conversion_optimized + { + // this metafunction evaluates to true, if we have optimized comnversion + // from Float type to Char array. + // Must be in sync with lexical_stream_limited_src::shl_real_type(...) + template + struct is_this_float_conversion_optimized + { + typedef boost::type_traits::ice_and< + boost::is_float::value, +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__) + boost::type_traits::ice_or< + boost::type_traits::ice_eq::value, + boost::is_same::value + >::value +#else + boost::type_traits::ice_eq::value +#endif + > result_type; + + BOOST_STATIC_CONSTANT(bool, value = (result_type::value) ); + }; + } + namespace detail // lcast_src_length { // Return max. length of string representation of Source; @@ -613,6 +652,64 @@ namespace boost { #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION } + namespace detail // lexical_cast_stream_traits + { + template + struct lexical_cast_stream_traits { + typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay::type src; + typedef BOOST_DEDUCED_TYPENAME boost::remove_cv::type no_cv_src; + + typedef boost::detail::deduce_source_char deduce_src_char_metafunc; + typedef BOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::type src_char_t; + typedef BOOST_DEDUCED_TYPENAME boost::detail::deduce_target_char::type target_char_t; + + typedef BOOST_DEDUCED_TYPENAME boost::detail::widest_char< + target_char_t, src_char_t + >::type char_type; + +#if !defined(BOOST_NO_CHAR16_T) && defined(BOOST_NO_UNICODE_LITERALS) + BOOST_STATIC_ASSERT_MSG(( !boost::is_same::value + && !boost::is_same::value), + "Your compiler does not have full support for char16_t" ); +#endif +#if !defined(BOOST_NO_CHAR32_T) && defined(BOOST_NO_UNICODE_LITERALS) + BOOST_STATIC_ASSERT_MSG(( !boost::is_same::value + && !boost::is_same::value), + "Your compiler does not have full support for char32_t" ); +#endif + + typedef BOOST_DEDUCED_TYPENAME boost::detail::deduce_char_traits< + char_type, Target, no_cv_src + >::type traits; + + typedef boost::type_traits::ice_and< + boost::is_same::value, // source is not a wide character based type + boost::type_traits::ice_ne::value, // target type is based on wide character + boost::type_traits::ice_not< + boost::detail::is_char_or_wchar::value // single character widening is optimized + >::value // and does not requires stringbuffer + > is_string_widening_required_t; + + typedef boost::type_traits::ice_not< boost::type_traits::ice_or< + boost::is_integral::value, + boost::detail::is_this_float_conversion_optimized::value, + boost::detail::is_char_or_wchar< + BOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::stage1_type // if we did not get character type at stage1 + >::value // then we have no optimization for that type + >::value > is_source_input_not_optimized_t; + + // If we have an optimized conversion for + // Source, we do not need to construct stringbuf. + BOOST_STATIC_CONSTANT(bool, requires_stringbuf = + (boost::type_traits::ice_or< + is_string_widening_required_t::value, is_source_input_not_optimized_t::value + >::value) + ); + + typedef boost::detail::lcast_src_length len_t; + }; + } + namespace detail // '0', '+' and '-' constants { template < typename Char > struct lcast_char_constants; @@ -2040,18 +2137,6 @@ namespace boost { namespace detail { - template - struct array_to_pointer_decay - { - typedef T type; - }; - - template - struct array_to_pointer_decay - { - typedef const T * type; - }; - template struct is_stdstring { @@ -2115,28 +2200,6 @@ namespace boost { ); }; - - // this metafunction evaluates to true, if we have optimized comnversion - // from Float type to Char array. - // Must be in sync with lexical_stream_limited_src::shl_real_type(...) - template - struct is_this_float_conversion_optimized - { - typedef boost::type_traits::ice_and< - boost::is_float::value, -#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__) - boost::type_traits::ice_or< - boost::type_traits::ice_eq::value, - boost::is_same::value - >::value -#else - boost::type_traits::ice_eq::value -#endif - > result_type; - - BOOST_STATIC_CONSTANT(bool, value = (result_type::value) ); - }; - template struct is_char_array_to_stdstring { @@ -2178,67 +2241,21 @@ namespace boost { { static inline Target lexical_cast_impl(const Source& arg) { - typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay::type src; - typedef BOOST_DEDUCED_TYPENAME boost::remove_cv::type no_cv_src; + typedef lexical_cast_stream_traits stream_trait; - typedef boost::detail::deduce_source_char deduce_src_char_metafunc; - typedef BOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::type src_char_t; - typedef BOOST_DEDUCED_TYPENAME boost::detail::deduce_target_char::type target_char_t; - - typedef BOOST_DEDUCED_TYPENAME boost::detail::widest_char< - target_char_t, src_char_t - >::type char_type; - -#if !defined(BOOST_NO_CHAR16_T) && defined(BOOST_NO_UNICODE_LITERALS) - BOOST_STATIC_ASSERT_MSG(( !boost::is_same::value - && !boost::is_same::value), - "Your compiler does not have full support for char16_t" ); -#endif -#if !defined(BOOST_NO_CHAR32_T) && defined(BOOST_NO_UNICODE_LITERALS) - BOOST_STATIC_ASSERT_MSG(( !boost::is_same::value - && !boost::is_same::value), - "Your compiler does not have full support for char32_t" ); -#endif - - typedef BOOST_DEDUCED_TYPENAME boost::detail::deduce_char_traits< - char_type, Target, no_cv_src - >::type traits; - - typedef boost::type_traits::ice_and< - boost::is_same::value, // source is not a wide character based type - boost::type_traits::ice_ne::value, // target type is based on wide character - boost::type_traits::ice_not< - boost::detail::is_char_or_wchar::value // single character widening is optimized - >::value // and does not requires stringbuffer - > is_string_widening_required_t; - - typedef boost::type_traits::ice_not< boost::type_traits::ice_or< - boost::is_integral::value, - boost::detail::is_this_float_conversion_optimized::value, - boost::detail::is_char_or_wchar< - BOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::stage1_type // if we did not get character type at stage1 - >::value // then we have no optimization for that type - >::value > is_source_input_not_optimized_t; + typedef detail::lexical_stream_limited_src< + BOOST_DEDUCED_TYPENAME stream_trait::char_type, + BOOST_DEDUCED_TYPENAME stream_trait::traits, + stream_trait::requires_stringbuf + > interpreter_type; // Target type must be default constructible - Target result; + Target result; - // If we have an optimized conversion for - // Source, we do not need to construct stringbuf. - BOOST_STATIC_CONSTANT(bool, requires_stringbuf = - (boost::type_traits::ice_or< - is_string_widening_required_t::value, is_source_input_not_optimized_t::value - >::value) - ); - - typedef detail::lexical_stream_limited_src interpreter_type; + BOOST_DEDUCED_TYPENAME stream_trait::char_type buf[stream_trait::len_t::value + 1]; + stream_trait::len_t::check_coverage(); - typedef detail::lcast_src_length lcast_src_length; - std::size_t const src_len = lcast_src_length::value; - char_type buf[src_len + 1]; - lcast_src_length::check_coverage(); - - interpreter_type interpreter(buf, buf + src_len); + interpreter_type interpreter(buf, buf + stream_trait::len_t::value + 1); // Disabling ADL, by directly specifying operators. if(!(interpreter.operator <<(arg) && interpreter.operator >>(result))) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 633368f..ea13e64 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -50,5 +50,6 @@ test-suite conversion [ run lexical_cast_arrays_test.cpp ] [ run lexical_cast_integral_types_test.cpp ] [ run lexical_cast_stream_detection_test.cpp ] + [ run lexical_cast_stream_traits_test.cpp ] ; diff --git a/test/lexical_cast_stream_traits_test.cpp b/test/lexical_cast_stream_traits_test.cpp new file mode 100644 index 0000000..8db47a1 --- /dev/null +++ b/test/lexical_cast_stream_traits_test.cpp @@ -0,0 +1,155 @@ +// Unit test for boost::lexical_cast. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Antony Polukhin, 2012. +// +// 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). + +#include + +#include + +#include + +template +static void test_optimized_types_to_string_const() +{ + namespace de = boost::detail; + typedef de::lexical_cast_stream_traits trait_1; + BOOST_CHECK(!trait_1::is_source_input_not_optimized_t::value); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK(!trait_1::is_string_widening_required_t::value); + BOOST_CHECK(!trait_1::is_source_input_not_optimized_t::value); + + typedef de::lexical_cast_stream_traits trait_2; + BOOST_CHECK(!trait_2::is_source_input_not_optimized_t::value); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK(!trait_2::is_string_widening_required_t::value); + BOOST_CHECK(!trait_2::is_source_input_not_optimized_t::value); + + typedef de::lexical_cast_stream_traits trait_3; + BOOST_CHECK(!trait_3::is_source_input_not_optimized_t::value); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK((boost::is_same::value)); + + BOOST_CHECK((boost::detail::is_char_or_wchar::value != trait_3::is_string_widening_required_t::value)); + + BOOST_CHECK(!trait_3::is_source_input_not_optimized_t::value); +} + + +template +static void test_optimized_types_to_string() +{ + test_optimized_types_to_string_const(); + + namespace de = boost::detail; + typedef de::lexical_cast_stream_traits trait_4; + BOOST_CHECK(!trait_4::is_source_input_not_optimized_t::value); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK(!trait_4::is_string_widening_required_t::value); + BOOST_CHECK(!trait_4::is_source_input_not_optimized_t::value); + + typedef de::lexical_cast_stream_traits trait_5; + BOOST_CHECK(!trait_5::is_source_input_not_optimized_t::value); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK(!trait_5::is_string_widening_required_t::value); + BOOST_CHECK(!trait_5::is_source_input_not_optimized_t::value); + + typedef de::lexical_cast_stream_traits trait_6; + BOOST_CHECK(!trait_6::is_source_input_not_optimized_t::value); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK((boost::is_same::value)); + BOOST_CHECK(!trait_6::is_string_widening_required_t::value); +} + +void test_metafunctions() +{ + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + +#if defined(BOOST_HAS_LONG_LONG) + test_optimized_types_to_string(); + test_optimized_types_to_string(); +#elif defined(BOOST_HAS_MS_INT64) + test_optimized_types_to_string(); + test_optimized_types_to_string<__int64>(); +#endif + + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string(); + test_optimized_types_to_string >(); + test_optimized_types_to_string >(); + test_optimized_types_to_string >(); + test_optimized_types_to_string >(); + test_optimized_types_to_string >(); + test_optimized_types_to_string >(); + test_optimized_types_to_string >(); + test_optimized_types_to_string >(); + test_optimized_types_to_string >(); + + test_optimized_types_to_string_const >(); + test_optimized_types_to_string_const >(); + test_optimized_types_to_string_const >(); + test_optimized_types_to_string_const >(); + test_optimized_types_to_string_const >(); + test_optimized_types_to_string_const >(); + test_optimized_types_to_string_const >(); + test_optimized_types_to_string_const >(); + test_optimized_types_to_string_const >(); + +#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) + test_optimized_types_to_string >(); + test_optimized_types_to_string >(); + test_optimized_types_to_string >(); + test_optimized_types_to_string >(); + test_optimized_types_to_string >(); + test_optimized_types_to_string >(); + + test_optimized_types_to_string_const >(); + test_optimized_types_to_string_const >(); + test_optimized_types_to_string_const >(); + test_optimized_types_to_string_const >(); + test_optimized_types_to_string_const >(); + test_optimized_types_to_string_const >(); +#endif +} + +boost::unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + boost::unit_test::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast traits tests"); + suite->add(BOOST_TEST_CASE(&test_metafunctions)); + return suite; +} +