From 98d24e04f408e86a8cf6675b5fff93c902bf3960 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 27 May 2011 04:22:18 +0000 Subject: [PATCH] Fixes #5564. Adds tests on #5564 and more tests on #5557 [SVN r72203] --- include/boost/lexical_cast.hpp | 138 ++++++++++++++++++++++++++++----- lexical_cast.htm | 1 + lexical_cast_test.cpp | 54 +++++++++++++ 3 files changed, 174 insertions(+), 19 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 6875b16..d185852 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -247,13 +247,42 @@ namespace boost static void check_coverage() {} }; - // No specializations for: - // lcast_src_length - // lcast_src_length - // lcast_src_length - // lcast_src_length - // lcast_src_length - // lcast_src_length + template<> + struct lcast_src_length + { + BOOST_STATIC_CONSTANT(std::size_t, value = 1); + static void check_coverage() {} + }; + template<> + struct lcast_src_length + { + BOOST_STATIC_CONSTANT(std::size_t, value = 1); + static void check_coverage() {} + }; + template<> + struct lcast_src_length + { + BOOST_STATIC_CONSTANT(std::size_t, value = 1); + static void check_coverage() {} + }; + template<> + struct lcast_src_length + { + BOOST_STATIC_CONSTANT(std::size_t, value = 1); + static void check_coverage() {} + }; + template<> + struct lcast_src_length + { + BOOST_STATIC_CONSTANT(std::size_t, value = 1); + static void check_coverage() {} + }; + template<> + struct lcast_src_length + { + BOOST_STATIC_CONSTANT(std::size_t, value = 1); + static void check_coverage() {} + }; #ifndef BOOST_LCAST_NO_WCHAR_T template<> @@ -821,9 +850,13 @@ namespace boost bool operator<<(bool); bool operator<<(char); + bool operator<<(unsigned char); + bool operator<<(signed char); #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) bool operator<<(wchar_t); #endif + bool operator<<(unsigned char const*); + bool operator<<(signed char const*); bool operator<<(CharT const*); bool operator<<(short); bool operator<<(int); @@ -1050,6 +1083,8 @@ namespace boost } bool operator>>(CharT&); + bool operator>>(unsigned char&); + bool operator>>(signed char&); #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // This #if is in sync with lcast_streambuf_for_target @@ -1091,6 +1126,34 @@ namespace boost return true; } + template + inline bool lexical_stream_limited_src::operator<<( + unsigned char ch) + { + return ((*this) << static_cast(ch)); + } + + template + inline bool lexical_stream_limited_src::operator<<( + signed char ch) + { + return ((*this) << static_cast(ch)); + } + + template + inline bool lexical_stream_limited_src::operator<<( + unsigned char const* ch) + { + return ((*this) << reinterpret_cast(ch)); + } + + template + inline bool lexical_stream_limited_src::operator<<( + signed char const* ch) + { + return ((*this) << reinterpret_cast(ch)); + } + #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) template inline bool lexical_stream_limited_src::operator<<( @@ -1256,6 +1319,34 @@ namespace boost return ok; } + template + inline bool lexical_stream_limited_src::operator>>( + unsigned char& output) + { + BOOST_STATIC_ASSERT( sizeof(CharT) == sizeof(unsigned char) ); + bool const ok = (finish - start == 1); + if(ok) { + CharT out; + Traits::assign(out, *start); + output = static_cast(out); + } + return ok; + } + + template + inline bool lexical_stream_limited_src::operator>>( + signed char& output) + { + BOOST_STATIC_ASSERT( sizeof(CharT) == sizeof(signed char) ); + bool const ok = (finish - start == 1); + if(ok) { + CharT out; + Traits::assign(out, *start); + output = static_cast(out); + } + return ok; + } + #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template inline bool lexical_stream_limited_src::operator>>( @@ -1312,13 +1403,9 @@ namespace boost struct lcast_streambuf_for_target { BOOST_STATIC_CONSTANT(bool, value = - ( - ::boost::type_traits::ice_or< - ::boost::type_traits::ice_not< is_integral::value >::value, - is_same::value, - is_same::value - >::value - ) + ( + ::boost::type_traits::ice_not< is_integral::value >::value + ) ); }; @@ -1472,16 +1559,29 @@ namespace boost ); }; + /* + * is_xchar_to_xchar::value is true, when + * Target and Souce are the same char types, or when + * Target and Souce are char types of the same size. + */ template struct is_xchar_to_xchar { BOOST_STATIC_CONSTANT(bool, value = - ( - ::boost::type_traits::ice_and< - is_same::value, - is_char_or_wchar::value + ( + ::boost::type_traits::ice_or< + ::boost::type_traits::ice_and< + is_same::value, + is_char_or_wchar::value + >::value, + ::boost::type_traits::ice_and< + ::boost::type_traits::ice_eq< sizeof(char),sizeof(Target)>::value, + ::boost::type_traits::ice_eq< sizeof(char),sizeof(Source)>::value, + is_char_or_wchar::value, + is_char_or_wchar::value + >::value >::value - ) + ) ); }; diff --git a/lexical_cast.htm b/lexical_cast.htm index 3372618..03625b4 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -267,6 +267,7 @@ Eliminate an overhead of std::locale if your program runs in the "C

Changes

May 2011:

    +
  • Better performance and less memory usage for unsigned char and signed char conversions.
  • Better performance and less memory usage for conversions to arithmetic types.
  • Better performance and less memory usage for conversions from arithmetic type to arithmetic type.
  • Directly construct Target from Source on some conversions (like conversions from string to string, from char array to string, from char to char and others).
  • diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index f366eb2..75d12ff 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -95,6 +95,7 @@ void test_wtraits(); void test_allocator(); void test_wallocator(); #endif +void test_char_types_conversions(); unit_test::test_suite *init_unit_test_suite(int, char *[]) { @@ -137,6 +138,8 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) suite->add(BOOST_TEST_CASE(&test_wallocator)); #endif + suite->add(BOOST_TEST_CASE(&test_char_types_conversions)); + return suite; } @@ -730,6 +733,12 @@ void test_conversion_from_to_integral() BOOST_CHECK(lexical_cast("+1") == static_cast(1) ); BOOST_CHECK(lexical_cast("+9") == static_cast(9) ); + BOOST_CHECK(lexical_cast("+10") == static_cast(10) ); + BOOST_CHECK(lexical_cast("+90") == static_cast(90) ); + BOOST_CHECK_THROW(lexical_cast("++1"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("-+9"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("--1"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("+-9"), bad_lexical_cast); // test_conversion_from_to_integral_for_locale typedef std::numpunct numpunct; @@ -785,6 +794,11 @@ void test_conversion_from_to_float() BOOST_CHECK_CLOSE(lexical_cast("+1"), 1, std::numeric_limits::epsilon() ); BOOST_CHECK_CLOSE(lexical_cast("+9"), 9, std::numeric_limits::epsilon()*9 ); + + BOOST_CHECK_THROW(lexical_cast("++1"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("-+9"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("--1"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("+-9"), bad_lexical_cast); } void test_conversion_from_to_short() @@ -923,3 +937,43 @@ void test_wallocator() #endif +#include +void test_char_types_conversions() +{ + const char c_arr[] = "Test array of chars"; + const unsigned char uc_arr[] = "Test array of chars"; + const signed char sc_arr[] = "Test array of chars"; + + BOOST_CHECK(boost::lexical_cast(c_arr) == std::string(c_arr)); + BOOST_CHECK(boost::lexical_cast(uc_arr) == std::string(c_arr)); + BOOST_CHECK(boost::lexical_cast(sc_arr) == std::string(c_arr)); + + BOOST_CHECK(boost::lexical_cast(c_arr[0]) == c_arr[0]); + BOOST_CHECK(boost::lexical_cast(uc_arr[0]) == c_arr[0]); + BOOST_CHECK(boost::lexical_cast(sc_arr[0]) == c_arr[0]); + + BOOST_CHECK(boost::lexical_cast(c_arr[0]) == uc_arr[0]); + BOOST_CHECK(boost::lexical_cast(uc_arr[0]) == uc_arr[0]); + BOOST_CHECK(boost::lexical_cast(sc_arr[0]) == uc_arr[0]); + + BOOST_CHECK(boost::lexical_cast(c_arr[0]) == sc_arr[0]); + BOOST_CHECK(boost::lexical_cast(uc_arr[0]) == sc_arr[0]); + BOOST_CHECK(boost::lexical_cast(sc_arr[0]) == sc_arr[0]); + +#ifndef BOOST_LCAST_NO_WCHAR_T + const wchar_t wc_arr[]=L"Test array of chars"; + + BOOST_CHECK(boost::lexical_cast(wc_arr) == std::wstring(wc_arr)); + BOOST_CHECK(boost::lexical_cast(c_arr) == std::wstring(wc_arr)); + + BOOST_CHECK(boost::lexical_cast(sc_arr) != std::wstring(wc_arr) ); + BOOST_CHECK(boost::lexical_cast(uc_arr) != std::wstring(wc_arr) ); + + BOOST_CHECK(boost::lexical_cast(c_arr[0]) == wc_arr[0]); + BOOST_CHECK(boost::lexical_cast(wc_arr[0]) == wc_arr[0]); + + BOOST_CHECK_THROW(boost::lexical_cast(uc_arr[0]), bad_lexical_cast); + BOOST_CHECK_THROW(boost::lexical_cast(sc_arr[0]), bad_lexical_cast); + +#endif +}