From e3cd0ca7faf1e42400676890a39cb75722bc4b1d Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 2 Jul 2012 18:30:21 +0000 Subject: [PATCH] Optimizations for boost and std array (refs #7065) [SVN r79230] --- include/boost/lexical_cast.hpp | 177 ++++++++++++++++++-- test/Jamfile.v2 | 1 + test/lexical_cast_arrays_test.cpp | 260 ++++++++++++++++++++++++++++++ 3 files changed, 421 insertions(+), 17 deletions(-) create mode 100644 test/lexical_cast_arrays_test.cpp diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index a9550d5..33ef84b 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -138,6 +138,12 @@ namespace boost #include #include + +#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) +#include +#endif + +#include #include #include #include @@ -224,42 +230,56 @@ namespace boost { typedef char type; }; - template + template struct stream_char { typedef BOOST_DEDUCED_TYPENAME stream_char::type type; }; - template + template struct stream_char { typedef BOOST_DEDUCED_TYPENAME stream_char::type type; }; - template + template struct stream_char > { typedef BOOST_DEDUCED_TYPENAME stream_char::type type; }; - template + template struct stream_char > { typedef BOOST_DEDUCED_TYPENAME stream_char::type type; }; - template + template struct stream_char< std::basic_string > { typedef CharT type; }; - template + template struct stream_char< ::boost::container::basic_string > { typedef CharT type; }; + template + struct stream_char > + { + typedef BOOST_DEDUCED_TYPENAME stream_char::type type; + }; + +#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) + template + struct stream_char > + { + typedef BOOST_DEDUCED_TYPENAME stream_char::type type; + }; +#endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) + #if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T) template<> struct stream_char @@ -1259,7 +1279,6 @@ namespace boost { return true; } -#ifndef BOOST_LCAST_NO_WCHAR_T template bool shl_char_array(T const* str) { @@ -1268,7 +1287,13 @@ namespace boost { "Use boost::locale instead" ); return shl_input_streamable(str); } -#endif + + bool shl_char_array_limited(CharT const* str, std::size_t max_size) + { + start = const_cast(str); + finish = std::find(start, start + max_size, static_cast(0)); + return true; + } template bool shl_input_streamable(InputStreamable& input) @@ -1494,8 +1519,58 @@ namespace boost { return shl_real_type(static_cast(val), start, finish); #endif } + + template + bool operator<<(boost::array const& input) + { return shl_char_array_limited(input.begin(), N); } - template + template + bool operator<<(boost::array const& input) + { return ((*this) << reinterpret_cast const& >(input)); } + + template + bool operator<<(boost::array const& input) + { return ((*this) << reinterpret_cast const& >(input)); } + + template + bool operator<<(boost::array const& input) + { return shl_char_array_limited(input.begin(), N); } + + template + bool operator<<(boost::array const& input) + { return ((*this) << reinterpret_cast const& >(input)); } + + template + bool operator<<(boost::array const& input) + { return ((*this) << reinterpret_cast const& >(input)); } + +#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) + template + bool operator<<(std::array const& input) + { return shl_char_array_limited(input.begin(), N); } + + template + bool operator<<(std::array const& input) + { return ((*this) << reinterpret_cast const& >(input)); } + + template + bool operator<<(std::array const& input) + { return ((*this) << reinterpret_cast const& >(input)); } + + template + bool operator<<(std::array const& input) + { return shl_char_array_limited(input.begin(), N); } + + template + bool operator<<(std::array const& input) + { return ((*this) << reinterpret_cast const& >(input)); } + + template + bool operator<<(std::array const& input) + { return ((*this) << reinterpret_cast const& >(input)); } +#endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) + + template bool operator<<(const InStreamable& input) { return shl_input_streamable(input); } /************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/ @@ -1674,6 +1749,70 @@ namespace boost { template bool operator>>(::boost::container::basic_string& str) { str.assign(start, finish); return true; } + + private: + template + bool shr_std_array(ArrayT& output, boost::mpl::bool_ /*is_T_char_tag*/) + { + using namespace std; + const std::size_t size = finish - start; + if (size > N - 1) { // `-1` because we need to store \0 at the end + return false; + } + + memcpy(output.begin(), start, size * sizeof(CharT)); + *(output.begin() + size) = static_cast(0); + return true; + } + + template + bool shr_std_array(ArrayT& output, boost::mpl::bool_ /*is_T_char_tag*/) + { + return shr_using_base_class(output); // Array consist of non character types or unmatching character type + } + public: + + template + bool operator>>(boost::array& output) + { + typedef boost::mpl::bool_ tag_type; + return shr_std_array(output, tag_type()); + } + + template + bool operator>>(boost::array& output) + { + return ((*this) >> reinterpret_cast& >(output)); + } + + template + bool operator>>(boost::array& output) + { + return ((*this) >> reinterpret_cast& >(output)); + } + +#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) + template + bool operator>>(std::array& output) + { + typedef boost::mpl::bool_ tag_type; + return shr_std_array(output, tag_type()); + } + + template + bool operator>>(std::array& output) + { + return ((*this) >> reinterpret_cast& >(output)); + } + + template + bool operator>>(std::array& in) + { + return ((*this) >> reinterpret_cast& >(output)); + } +#endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) + + /* * case "-0" || "0" || "+0" : output = false; return true; * case "1" || "+1": output = true; return true; @@ -1937,11 +2076,6 @@ namespace boost { "Your compiler does not have full support for char32_t" ); #endif - 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(); - typedef BOOST_DEDUCED_TYPENAME ::boost::detail::deduce_char_traits< char_type, Target, Source >::type traits; @@ -1959,20 +2093,29 @@ namespace boost { ::boost::detail::is_char_or_wchar::value > is_source_input_optimized_t; + // Target type must be default constructible + Target result; + // If we have an optimized conversion for // Source, we do not need to construct stringbuf. const bool requires_stringbuf = ::boost::type_traits::ice_or< is_string_widening_required_t::value, ::boost::type_traits::ice_not< is_source_input_optimized_t::value >::value >::value; + + typedef detail::lexical_stream_limited_src interpreter_type; - detail::lexical_stream_limited_src - interpreter(buf, buf + src_len); + 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); - Target result; // Disabling ADL, by directly specifying operators. if(!(interpreter.operator <<(arg) && interpreter.operator >>(result))) BOOST_LCAST_THROW_BAD_CAST(Source, Target); + return result; } }; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f8ee0d3..474f689 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -47,5 +47,6 @@ test-suite conversion gcc-4.7:-fno-exceptions ] [ run lexical_cast_iterator_range_test.cpp ] + [ run lexical_cast_arrays_test.cpp ] ; diff --git a/test/lexical_cast_arrays_test.cpp b/test/lexical_cast_arrays_test.cpp new file mode 100644 index 0000000..c9213f4 --- /dev/null +++ b/test/lexical_cast_arrays_test.cpp @@ -0,0 +1,260 @@ +// Testing boost::lexical_cast with boost::container::string. +// +// 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 + +void testing_boost_array_output_conversion(); +void testing_std_array_output_conversion(); + +void testing_boost_array_input_conversion(); +void testing_std_array_input_conversion(); + +using namespace boost; + +boost::unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test::test_suite *suite = + BOOST_TEST_SUITE("Testing boost::lexical_cast with boost::array and std::array"); + + suite->add(BOOST_TEST_CASE(testing_boost_array_output_conversion)); + suite->add(BOOST_TEST_CASE(testing_std_array_output_conversion)); + suite->add(BOOST_TEST_CASE(testing_boost_array_input_conversion)); + suite->add(BOOST_TEST_CASE(testing_std_array_input_conversion)); + + return suite; +} + +template