diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 6479e5d..e536ac5 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -133,60 +133,102 @@ namespace boost namespace detail // selectors for choosing stream character type { - template - struct stream_char - { - typedef char type; - }; + template + struct stream_char + { + typedef char type; + }; #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct stream_char< std::basic_string > - { - typedef CharT type; - }; + template + struct stream_char< std::basic_string > + { + typedef CharT type; + }; #endif #ifndef BOOST_LCAST_NO_WCHAR_T #ifndef BOOST_NO_INTRINSIC_WCHAR_T - template<> - struct stream_char - { - typedef wchar_t type; - }; + template<> + struct stream_char + { + typedef wchar_t type; + }; #endif - template<> - struct stream_char - { - typedef wchar_t type; - }; + template<> + struct stream_char + { + typedef wchar_t type; + }; - template<> - struct stream_char - { - typedef wchar_t type; - }; + template<> + struct stream_char + { + typedef wchar_t type; + }; #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template<> - struct stream_char - { - typedef wchar_t type; - }; + template<> + struct stream_char + { + typedef wchar_t type; + }; #endif #endif + +#ifndef BOOST_NO_CHAR16_T + + template<> + struct stream_char + { + typedef char16_t type; + }; + + template<> + struct stream_char + { + typedef char16_t type; + }; + + template<> + struct stream_char + { + typedef char16_t type; + }; + +#endif + +#ifndef BOOST_NO_CHAR32_T + + template<> + struct stream_char + { + typedef char32_t type; + }; + + template<> + struct stream_char + { + typedef char32_t type; + }; + + template<> + struct stream_char + { + typedef char32_t type; + }; + +#endif + template struct widest_char { - typedef TargetChar type; - }; - - template<> - struct widest_char - { - typedef wchar_t type; + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< + (sizeof(TargetChar) > sizeof(SourceChar)) + , TargetChar + , SourceChar >::type type; }; } @@ -231,8 +273,7 @@ namespace boost namespace detail // lcast_src_length { // Return max. length of string representation of Source; - template< class CharT // A result of widest_char transformation. - , class Source // Source type of lexical_cast. + template< class Source // Source type of lexical_cast. > struct lcast_src_length { @@ -269,20 +310,12 @@ namespace boost BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256); #endif }; - -#define BOOST_LCAST_DEF1(CharT, T) \ - template<> struct lcast_src_length \ +// TODO: FIX for char16_t, char32_t, we can ignore CharT +#define BOOST_LCAST_DEF(T) \ + template<> struct lcast_src_length \ : lcast_src_length_integral \ { static void check_coverage() {} }; -#ifdef BOOST_LCAST_NO_WCHAR_T -#define BOOST_LCAST_DEF(T) BOOST_LCAST_DEF1(char, T) -#else -#define BOOST_LCAST_DEF(T) \ - BOOST_LCAST_DEF1(char, T) \ - BOOST_LCAST_DEF1(wchar_t, T) -#endif - BOOST_LCAST_DEF(short) BOOST_LCAST_DEF(unsigned short) BOOST_LCAST_DEF(int) @@ -298,7 +331,6 @@ namespace boost #endif #undef BOOST_LCAST_DEF -#undef BOOST_LCAST_DEF1 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION // Helper for floating point types. @@ -324,49 +356,26 @@ namespace boost }; template<> - struct lcast_src_length + struct lcast_src_length : lcast_src_length_floating { static void check_coverage() {} }; template<> - struct lcast_src_length + struct lcast_src_length : lcast_src_length_floating { static void check_coverage() {} }; template<> - struct lcast_src_length + struct lcast_src_length : lcast_src_length_floating { static void check_coverage() {} }; -#ifndef BOOST_LCAST_NO_WCHAR_T - template<> - struct lcast_src_length - : lcast_src_length_floating - { - static void check_coverage() {} - }; - - template<> - struct lcast_src_length - : lcast_src_length_floating - { - static void check_coverage() {} - }; - - template<> - struct lcast_src_length - : lcast_src_length_floating - { - static void check_coverage() {} - }; - -#endif // #ifndef BOOST_LCAST_NO_WCHAR_T #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION } @@ -397,6 +406,32 @@ namespace boost BOOST_STATIC_CONSTANT(wchar_t, c_decimal_separator = L'.'); }; #endif + +#ifndef BOOST_NO_CHAR16_T + template<> + struct lcast_char_constants + { + BOOST_STATIC_CONSTANT(char16_t, zero = u'0'); + BOOST_STATIC_CONSTANT(char16_t, minus = u'-'); + BOOST_STATIC_CONSTANT(char16_t, plus = u'+'); + BOOST_STATIC_CONSTANT(char16_t, lowercase_e = u'e'); + BOOST_STATIC_CONSTANT(char16_t, capital_e = u'E'); + BOOST_STATIC_CONSTANT(char16_t, c_decimal_separator = u'.'); + }; +#endif + +#ifndef BOOST_NO_CHAR32_T + template<> + struct lcast_char_constants + { + BOOST_STATIC_CONSTANT(char32_t, zero = U'0'); + BOOST_STATIC_CONSTANT(char32_t, minus = U'-'); + BOOST_STATIC_CONSTANT(char32_t, plus = U'+'); + BOOST_STATIC_CONSTANT(char32_t, lowercase_e = U'e'); + BOOST_STATIC_CONSTANT(char32_t, capital_e = U'E'); + BOOST_STATIC_CONSTANT(char32_t, c_decimal_separator = U'.'); + }; +#endif } namespace detail // lcast_to_unsigned @@ -1553,28 +1588,38 @@ namespace boost template struct is_char_or_wchar { + private: #ifndef BOOST_LCAST_NO_WCHAR_T - BOOST_STATIC_CONSTANT(bool, value = - ( - ::boost::type_traits::ice_or< - is_same< T, char >::value, - is_same< T, wchar_t >::value, - is_same< T, unsigned char >::value, - is_same< T, signed char >::value - >::value - ) - ); + typedef wchar_t wchar_t_if_supported; #else + typedef char wchar_t_if_supported; +#endif + +#ifndef BOOST_NO_CHAR16_T + typedef char16_t char16_t_if_supported; +#else + typedef char char16_t_if_supported; +#endif + +#ifndef BOOST_NO_CHAR32_T + typedef char32_t char32_t_if_supported; +#else + typedef char char32_t_if_supported; +#endif + public: + BOOST_STATIC_CONSTANT(bool, value = ( ::boost::type_traits::ice_or< is_same< T, char >::value, + is_same< T, wchar_t_if_supported >::value, + is_same< T, char16_t_if_supported >::value, + is_same< T, char32_t_if_supported >::value, is_same< T, unsigned char >::value, is_same< T, signed char >::value >::value ) ); -#endif }; template @@ -1658,7 +1703,7 @@ namespace boost , BOOST_DEDUCED_TYPENAME detail::stream_char::type >::type char_type; - typedef detail::lcast_src_length lcast_src_length; + 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(); diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index f07926b..47381cd 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -100,6 +100,13 @@ void test_wallocator(); #endif void test_char_types_conversions(); void operators_overload_test(); +#ifndef BOOST_NO_CHAR16_T +void test_char16_conversions(); +#endif +#ifndef BOOST_NO_CHAR32_T +void test_char32_conversions(); +#endif + unit_test::test_suite *init_unit_test_suite(int, char *[]) { @@ -142,6 +149,12 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) suite->add(BOOST_TEST_CASE(&test_char_types_conversions)); suite->add(BOOST_TEST_CASE(&operators_overload_test)); +#ifndef BOOST_NO_CHAR16_T + suite->add(BOOST_TEST_CASE(&test_char16_conversions)); +#endif +#ifndef BOOST_NO_CHAR32_T + suite->add(BOOST_TEST_CASE(&test_char32_conversions)); +#endif return suite; } @@ -582,7 +595,7 @@ void test_conversion_from_integral_to_string(CharT) // Test values around zero: if(limits::is_signed) - for(t = -counter; t < static_cast(counter); ++t) + for(t = static_cast(-counter); t < static_cast(counter); ++t) BOOST_CHECK(lexical_cast(t) == to_str(t)); // Test values around 100, 1000, 10000, ... @@ -679,7 +692,7 @@ void test_conversion_from_string_to_integral(CharT) // Test values around zero: if(limits::is_signed) - for(t = -counter; t < static_cast(counter); ++t) + for(t = static_cast(-counter); t < static_cast(counter); ++t) BOOST_CHECK(lexical_cast(to_str(t)) == t); // Test values around 100, 1000, 10000, ... @@ -990,3 +1003,20 @@ void operators_overload_test() (void)boost::lexical_cast(foo); } + +#ifndef BOOST_NO_CHAR16_T +void test_char16_conversions() +{ + BOOST_CHECK(u"100" == lexical_cast(u"100")); + BOOST_CHECK(u"1" == lexical_cast(u'1')); +} +#endif + +#ifndef BOOST_NO_CHAR32_T +void test_char32_conversions() +{ + BOOST_CHECK(U"100" == lexical_cast(U"100")); + BOOST_CHECK(U"1" == lexical_cast(U'1')); +} +#endif +