From d436099477357c94d04a4338480e60eee23d61fb Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Thu, 13 Apr 2006 20:52:28 +0000 Subject: [PATCH 001/242] Code size optimization [SVN r33694] --- include/boost/lexical_cast.hpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 926b95e..ce6668b 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef BOOST_NO_STRINGSTREAM #include @@ -209,19 +210,25 @@ namespace boost { typedef const T * type; }; + + template + Target lexical_cast( + BOOST_DEDUCED_TYPENAME boost::call_traits::value_type arg) + { + detail::lexical_stream interpreter; + Target result; + + if(!(interpreter << arg && interpreter >> result)) + throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); + return result; + } } template - Target lexical_cast(const Source &arg) + inline Target lexical_cast(const Source &arg) { typedef typename detail::array_to_pointer_decay::type NewSource; - - detail::lexical_stream interpreter; - Target result; - - if(!(interpreter << arg && interpreter >> result)) - throw_exception(bad_lexical_cast(typeid(NewSource), typeid(Target))); - return result; + return detail::lexical_cast(arg); } #else From aac8fcb4b666c0357227725de28c1759841751f8 Mon Sep 17 00:00:00 2001 From: Gennaro Prota Date: Thu, 27 Jul 2006 10:27:37 +0000 Subject: [PATCH 002/242] boost guidelines (mainly from inspect tool: tabs, license reference text, etc.) [SVN r34752] --- include/boost/implicit_cast.hpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/include/boost/implicit_cast.hpp b/include/boost/implicit_cast.hpp index 2593cb4..27e1639 100755 --- a/include/boost/implicit_cast.hpp +++ b/include/boost/implicit_cast.hpp @@ -23,13 +23,22 @@ inline T implicit_cast (typename mpl::identity::type x) { //template //void implicit_cast (...); -// Macro for when you need a constant expression (Gennaro Prota) -#define BOOST_IMPLICIT_CAST(dst_type, expr) \ - ( sizeof( implicit_cast(expr) ) \ - , \ - static_cast(expr) \ - ) - } // namespace boost + + +// Macro for when you need a constant expression. +// Note that 'expr' is evaluated at most once, though +// it appears three times (provided by Gennaro Prota; see +// http://lists.boost.org/Archives/boost/2004/05/65687.php) +// +#define BOOST_IMPLICIT_CAST(dest_type, expr) \ + ( static_cast( \ + sizeof(boost::implicit_cast(expr)) ? \ + (expr) : (expr) \ + ) \ + ) /**/ + + + #endif // IMPLICIT_CAST_DWA200356_HPP From e6c83d0665ef21bf6b92365931a6913e936d87b1 Mon Sep 17 00:00:00 2001 From: Gennaro Prota Date: Tue, 1 Aug 2006 20:36:14 +0000 Subject: [PATCH 003/242] =?UTF-8?q?with=20apologies=20to=20Terje,=20change?= =?UTF-8?q?d=20'=C3=B8'=20in=20'o',=20to=20stick=20to=20the=20basic=20sour?= =?UTF-8?q?ce=20character=20set=20(non-basic=20chars=20should=20be=20handl?= =?UTF-8?q?ed=20in=20phase=201,=20but=20some=20users=20report=20compile=20?= =?UTF-8?q?failures=20due=20to=20them)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [SVN r34800] --- include/boost/lexical_cast.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index ce6668b..28258fe 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -8,7 +8,7 @@ // // what: lexical_cast custom keyword cast // who: contributed by Kevlin Henney, -// enhanced with contributions from Terje Slettebų, +// enhanced with contributions from Terje Slettebo, // with additional fixes and suggestions from Gennaro Prota, // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, // and other Boosters From c5bc634015d81b415cad66d8697a4819e142fb7d Mon Sep 17 00:00:00 2001 From: Gennaro Prota Date: Tue, 1 Aug 2006 22:37:38 +0000 Subject: [PATCH 004/242] some "rewording" to avoid spurious level 4 warnings with VC7.1 and VC8 [SVN r34801] --- include/boost/lexical_cast.hpp | 43 +++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 28258fe..bb45719 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -136,10 +136,21 @@ namespace boost { stream.unsetf(std::ios::skipws); - if(std::numeric_limits::is_specialized) - stream.precision(std::numeric_limits::digits10 + 1); - else if(std::numeric_limits::is_specialized) - stream.precision(std::numeric_limits::digits10 + 1); + // The odd style used below is to avoid spurious compiler + // warnings about using is_specialized as a (constant) + // conditional expression + + typedef std::numeric_limits t; + typedef std::numeric_limits s; + + bool setup_target = t::is_specialized; + if (setup_target) + stream.precision(t::digits10 + 1); + else + ((s::is_specialized) && + stream.precision(s::digits10 + 1)); + + } ~lexical_stream() { @@ -215,12 +226,26 @@ namespace boost Target lexical_cast( BOOST_DEDUCED_TYPENAME boost::call_traits::value_type arg) { - detail::lexical_stream interpreter; - Target result; - if(!(interpreter << arg && interpreter >> result)) - throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); - return result; + detail::lexical_stream interpreter; + + // The original form, reproduced below, is more elegant + // but yields a spurious C4701 warning ("possible use of + // "result" before initialization") with VC7.1 (/W4). +// +// Target result; +// +// if(!(interpreter << arg && interpreter >> result)) +// throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); +// return result; + + if(interpreter << arg) { + Target result; + if (interpreter >> result) + return result; + } + throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); + return Target(); // never reached } } From 795b7e18099e11c35bb693503d74b3d30576cdda Mon Sep 17 00:00:00 2001 From: Gennaro Prota Date: Sat, 5 Aug 2006 22:45:53 +0000 Subject: [PATCH 005/242] there seems to be no reasonable form which avoids warnings with all compilers; so let's use a clear style and filter explicitly the VC warning [SVN r34820] --- include/boost/lexical_cast.hpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index bb45719..38ec6af 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -136,20 +136,21 @@ namespace boost { stream.unsetf(std::ios::skipws); - // The odd style used below is to avoid spurious compiler - // warnings about using is_specialized as a (constant) - // conditional expression +#if (defined _MSC_VER) +# pragma warning( push ) + // conditional expression is constant +# pragma warning( disable : 4127 ) typedef std::numeric_limits t; typedef std::numeric_limits s; - bool setup_target = t::is_specialized; - if (setup_target) - stream.precision(t::digits10 + 1); - else - ((s::is_specialized) && - stream.precision(s::digits10 + 1)); + if(t::is_specialized) + stream.precision(1 + t::digits10); + else if(s::is_specialized) + stream.precision(1 + s::digits10); +# pragma warning( pop ) +#endif } ~lexical_stream() From 0743b5982c65bc8c9874876930080cf5cece4916 Mon Sep 17 00:00:00 2001 From: Gennaro Prota Date: Sun, 6 Aug 2006 12:31:44 +0000 Subject: [PATCH 006/242] added slash to boost url fixed silly error in #if/#endif logic of the previous edit improved comment about code never reached removed "All rights reserved" [SVN r34822] --- include/boost/lexical_cast.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 38ec6af..41d80bf 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -3,7 +3,7 @@ // Boost lexical_cast.hpp header -------------------------------------------// // -// See http://www.boost.org for most recent version including documentation. +// See http://www.boost.org/ for most recent version including documentation. // See end of this header for rights and permissions. // // what: lexical_cast custom keyword cast @@ -140,6 +140,7 @@ namespace boost # pragma warning( push ) // conditional expression is constant # pragma warning( disable : 4127 ) +#endif typedef std::numeric_limits t; typedef std::numeric_limits s; @@ -149,6 +150,7 @@ namespace boost else if(s::is_specialized) stream.precision(1 + s::digits10); +#if (defined _MSC_VER) # pragma warning( pop ) #endif @@ -246,7 +248,7 @@ namespace boost return result; } throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); - return Target(); // never reached + return Target(); // normally never reached (throw_exception) } } @@ -275,7 +277,7 @@ namespace boost #endif } -// Copyright Kevlin Henney, 2000-2005. All rights reserved. +// Copyright Kevlin Henney, 2000-2005. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at From 453555619e329af3bc416e1a7bd4ee2698403f6d Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Mon, 7 Aug 2006 20:36:23 +0000 Subject: [PATCH 007/242] New test cases for forthcoming fast lexical_cast [SVN r34847] --- lexical_cast_test.cpp | 255 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 4182942..31ad2ec 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -3,6 +3,7 @@ // See http://www.boost.org for most recent version, including documentation. // // Copyright Terje Slettebų and Kevlin Henney, 2005. +// Copyright Alexander Nasonov, 2006. // // Distributed under the Boost // Software License, Version 1.0. (See accompanying file @@ -29,6 +30,18 @@ #define DISABLE_WIDE_CHAR_SUPPORT #endif +#if (defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)) \ + && !(defined(BOOST_MSVC) && BOOST_MSVC < 1300) +#define LCAST_TEST_LONGLONG +#endif + +// Test all 65536 values if true: +bool const lcast_test_small_integral_types_completely = false; + +// LCAST_INTEGRAL_TEST_COUNTER: use when testing all values of an integral +// types is not possible. Max. portable value is 32767. +#define LCAST_INTEGRAL_TEST_COUNTER 1000 + using namespace boost; void test_conversion_to_char(); @@ -44,6 +57,16 @@ void test_conversion_from_wstring(); void test_conversion_to_wstring(); void test_bad_lexical_cast(); void test_no_whitespace_stripping(); +void test_conversion_from_short(); +void test_conversion_from_ushort(); +void test_conversion_from_int(); +void test_conversion_from_uint(); +void test_conversion_from_long(); +void test_conversion_from_ulong(); +#ifdef LCAST_TEST_LONGLONG +void test_conversion_from_longlong(); +void test_conversion_from_ulonglong(); +#endif unit_test::test_suite *init_unit_test_suite(int, char *[]) { @@ -64,6 +87,17 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) #endif suite->add(BOOST_TEST_CASE(test_bad_lexical_cast)); suite->add(BOOST_TEST_CASE(test_no_whitespace_stripping)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_short)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_ushort)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_int)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_uint)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_ulong)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_long)); + #ifdef LCAST_TEST_LONGLONG + suite->add(BOOST_TEST_CASE(&test_conversion_from_longlong)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_ulonglong)); + #endif + return suite; } @@ -318,3 +352,224 @@ void test_no_whitespace_stripping() BOOST_CHECK_THROW(lexical_cast(" 123"), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast("123 "), bad_lexical_cast); } + +template +std::basic_string to_str(T t) +{ + std::basic_ostringstream o; + o << t; + return o.str(); +} + +template +void test_conversion_from_integral_to_char(CharT zero) +{ + BOOST_CHECK(lexical_cast(static_cast(0)) == zero + 0); + BOOST_CHECK(lexical_cast(static_cast(1)) == zero + 1); + BOOST_CHECK(lexical_cast(static_cast(2)) == zero + 2); + BOOST_CHECK(lexical_cast(static_cast(3)) == zero + 3); + BOOST_CHECK(lexical_cast(static_cast(4)) == zero + 4); + BOOST_CHECK(lexical_cast(static_cast(5)) == zero + 5); + BOOST_CHECK(lexical_cast(static_cast(6)) == zero + 6); + BOOST_CHECK(lexical_cast(static_cast(7)) == zero + 7); + BOOST_CHECK(lexical_cast(static_cast(8)) == zero + 8); + BOOST_CHECK(lexical_cast(static_cast(9)) == zero + 9); + + BOOST_CHECK_THROW(lexical_cast(static_cast(10)), bad_lexical_cast); + + T t = std::numeric_limits::max(); + BOOST_CHECK_THROW(lexical_cast(t), bad_lexical_cast); +} + +template +void test_conversion_from_integral_to_integral() +{ + T t = 0; + BOOST_CHECK(lexical_cast(t) == t); + + t = 32767; + BOOST_CHECK(lexical_cast(t) == t); + BOOST_CHECK(lexical_cast(t) == t); + BOOST_CHECK(lexical_cast(t) == t); + BOOST_CHECK(lexical_cast(t) == t); + BOOST_CHECK(lexical_cast(t) == t); + BOOST_CHECK(lexical_cast(t) == t); + + t = std::numeric_limits::max(); + BOOST_CHECK(lexical_cast(t) == t); + + t = std::numeric_limits::min(); + BOOST_CHECK(lexical_cast(t) == t); +} + +template +void test_conversion_from_integral_to_string(CharT) +{ + typedef std::numeric_limits limits; + typedef std::basic_string string_type; + + T t; + + t = limits::min(); + BOOST_CHECK(lexical_cast(t) == to_str(t)); + + t = limits::max(); + BOOST_CHECK(lexical_cast(t) == to_str(t)); + + if(limits::digits <= 16 && lcast_test_small_integral_types_completely) + for(t = 1 + limits::min(); t != limits::max(); ++t) + BOOST_CHECK(lexical_cast(t) == to_str(t)); + else + { + T const min_val = limits::min(); + T const max_val = limits::max(); + int const counter = LCAST_INTEGRAL_TEST_COUNTER < max_val / 2 ? + LCAST_INTEGRAL_TEST_COUNTER : max_val / 2; + + int i; + + // Test values around min: + t = min_val; + for(i = 0; i < counter; ++i, ++t) + BOOST_CHECK(lexical_cast(t) == to_str(t)); + + // Test values around max: + t = max_val; + for(i = 0; i < counter; ++i, --t) + BOOST_CHECK(lexical_cast(t) == to_str(t)); + + // Test values around zero: + if(limits::is_signed) + for(t = -counter; t < counter; ++t) + BOOST_CHECK(lexical_cast(t) == to_str(t)); + + // Test values around 100, 1000, 10000, ... + T ten_power = 100; + for(i = 2; i <= limits::digits10; ++i, ten_power *= 10) + { + // I believe that (ten_power + 100) never overflows + for(t = ten_power - 100; t != ten_power + 100; ++t) + BOOST_CHECK(lexical_cast(t) == to_str(t)); + } + } +} + +template +void test_conversion_from_integral_for_locale() +{ + test_conversion_from_integral_to_integral(); + test_conversion_from_integral_to_string('0'); +#ifndef DISABLE_WIDE_CHAR_SUPPORT + test_conversion_from_integral_to_string(L'0'); +#endif +} + +struct restore_oldloc +{ + std::locale oldloc; + ~restore_oldloc() { std::locale::global(oldloc); } +}; + +template +void test_conversion_from_integral() +{ + char const zero = '0'; + signed char const szero = '0'; + unsigned char const uzero = '0'; + test_conversion_from_integral_to_char(zero); + test_conversion_from_integral_to_char(szero); + test_conversion_from_integral_to_char(uzero); +#ifndef DISABLE_WIDE_CHAR_SUPPORT + wchar_t const wzero = L'0'; + test_conversion_from_integral_to_char(wzero); +#endif + + // test_conversion_from_integral_for_locale + + typedef std::numpunct numpunct; + + restore_oldloc guard; + std::locale const& oldloc = guard.oldloc; + + std::string grouping1 = BOOST_USE_FACET(numpunct, oldloc).grouping(); + std::string grouping2(grouping1); + + test_conversion_from_integral_for_locale(); + + try + { + std::locale newloc(""); + std::locale::global(newloc); + + grouping2 = BOOST_USE_FACET(numpunct, newloc).grouping(); + } + catch(std::exception const& ex) + { + std::string msg("Failed to set system locale: "); + msg += ex.what(); + BOOST_TEST_MESSAGE(msg); + } + + if(grouping1 != grouping2) + test_conversion_from_integral_for_locale(); + + if(grouping1.empty() && grouping2.empty()) + BOOST_TEST_MESSAGE("Formatting with thousands_sep has not been tested"); +} + +void test_conversion_from_short() +{ + test_conversion_from_integral(); +} + +void test_conversion_from_ushort() +{ + test_conversion_from_integral(); +} + +void test_conversion_from_int() +{ + test_conversion_from_integral(); +} + +void test_conversion_from_uint() +{ + test_conversion_from_integral(); +} + +void test_conversion_from_ulong() +{ + test_conversion_from_integral(); +} + +void test_conversion_from_long() +{ + test_conversion_from_integral(); +} + +#if defined(BOOST_HAS_LONG_LONG) + +void test_conversion_from_longlong() +{ + test_conversion_from_integral(); +} + +void test_conversion_from_ulonglong() +{ + test_conversion_from_integral(); +} + +#elif defined(LCAST_TEST_LONGLONG) + +void test_conversion_from_longlong() +{ + test_conversion_from_integral<__int64>(); +} + +void test_conversion_from_ulonglong() +{ + test_conversion_from_integral(); +} + +#endif + From 425e7cb36790813c84f12facbc5868c7b21577a1 Mon Sep 17 00:00:00 2001 From: Gennaro Prota Date: Wed, 9 Aug 2006 20:18:06 +0000 Subject: [PATCH 008/242] removed BOOST_IMPLICIT_CAST; it was committed by mistake, has no unit tests, and is not released by the author under the Boost Software License [SVN r34857] --- include/boost/implicit_cast.hpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/include/boost/implicit_cast.hpp b/include/boost/implicit_cast.hpp index 27e1639..5b1cd92 100755 --- a/include/boost/implicit_cast.hpp +++ b/include/boost/implicit_cast.hpp @@ -26,19 +26,4 @@ inline T implicit_cast (typename mpl::identity::type x) { } // namespace boost - -// Macro for when you need a constant expression. -// Note that 'expr' is evaluated at most once, though -// it appears three times (provided by Gennaro Prota; see -// http://lists.boost.org/Archives/boost/2004/05/65687.php) -// -#define BOOST_IMPLICIT_CAST(dest_type, expr) \ - ( static_cast( \ - sizeof(boost::implicit_cast(expr)) ? \ - (expr) : (expr) \ - ) \ - ) /**/ - - - #endif // IMPLICIT_CAST_DWA200356_HPP From ae431bacf8074abc4e508f215c8745618c7de084 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Tue, 22 Aug 2006 20:40:31 +0000 Subject: [PATCH 009/242] Better coverage [SVN r34925] --- lexical_cast_test.cpp | 67 ++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 31ad2ec..ca209fc 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -38,9 +38,9 @@ // Test all 65536 values if true: bool const lcast_test_small_integral_types_completely = false; -// LCAST_INTEGRAL_TEST_COUNTER: use when testing all values of an integral +// lcast_integral_test_counter: use when testing all values of an integral // types is not possible. Max. portable value is 32767. -#define LCAST_INTEGRAL_TEST_COUNTER 1000 +int const lcast_integral_test_counter=1000; using namespace boost; @@ -201,6 +201,9 @@ void test_conversion_to_bool() void test_conversion_to_string() { + char buf[] = "hello"; + char* str = buf; + BOOST_CHECK_EQUAL(str, lexical_cast(str)); BOOST_CHECK_EQUAL("A", lexical_cast('A')); BOOST_CHECK_EQUAL(" ", lexical_cast(' ')); BOOST_CHECK_EQUAL("123", lexical_cast(123)); @@ -273,6 +276,8 @@ void test_conversion_to_wchar_t() #if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) BOOST_CHECK_EQUAL(L'1', lexical_cast(1)); BOOST_CHECK_EQUAL(L'0', lexical_cast(0)); + BOOST_CHECK_EQUAL(L'1', lexical_cast('1')); + BOOST_CHECK_EQUAL(L'0', lexical_cast('0')); BOOST_CHECK_THROW(lexical_cast(123), bad_lexical_cast); BOOST_CHECK_EQUAL(L'1', lexical_cast(1.0)); BOOST_CHECK_EQUAL(L'0', lexical_cast(0.0)); @@ -314,6 +319,9 @@ void test_conversion_from_wstring() void test_conversion_to_wstring() { #ifndef DISABLE_WIDE_CHAR_SUPPORT + wchar_t buf[] = L"hello"; + wchar_t* str = buf; + BOOST_CHECK(str == lexical_cast(str)); BOOST_CHECK(L"123" == lexical_cast(123)); BOOST_CHECK(L"1.23" == lexical_cast(1.23)); BOOST_CHECK(L"1.111111111" == lexical_cast(1.111111111)); @@ -322,6 +330,7 @@ void test_conversion_to_wstring() #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) BOOST_CHECK(L"A" == lexical_cast(L'A')); BOOST_CHECK(L" " == lexical_cast(L' ')); + BOOST_CHECK(L"A" == lexical_cast('A')); #endif BOOST_CHECK(L"Test" == lexical_cast(L"Test")); BOOST_CHECK(L" " == lexical_cast(L" ")); @@ -353,32 +362,56 @@ void test_no_whitespace_stripping() BOOST_CHECK_THROW(lexical_cast("123 "), bad_lexical_cast); } +// Replace "-,999" with "-999". +template +std::basic_string to_str_gcc_workaround(std::basic_string str) +{ + std::locale loc; + std::numpunct const& np = BOOST_USE_FACET(std::numpunct, loc); + + if(np.grouping().empty()) + return str; + + CharT prefix[3] = { + boost::detail::lcast_char_constants::minus, + np.thousands_sep(), + CharT() + }; + + if(str.find(prefix) != 0) + return str; + + prefix[1] = CharT(); // "-," -> "-" + str.replace(0, 2, prefix); + return str; +} + template std::basic_string to_str(T t) { std::basic_ostringstream o; o << t; - return o.str(); + return to_str_gcc_workaround(o.str()); } template void test_conversion_from_integral_to_char(CharT zero) { - BOOST_CHECK(lexical_cast(static_cast(0)) == zero + 0); - BOOST_CHECK(lexical_cast(static_cast(1)) == zero + 1); - BOOST_CHECK(lexical_cast(static_cast(2)) == zero + 2); - BOOST_CHECK(lexical_cast(static_cast(3)) == zero + 3); - BOOST_CHECK(lexical_cast(static_cast(4)) == zero + 4); - BOOST_CHECK(lexical_cast(static_cast(5)) == zero + 5); - BOOST_CHECK(lexical_cast(static_cast(6)) == zero + 6); - BOOST_CHECK(lexical_cast(static_cast(7)) == zero + 7); - BOOST_CHECK(lexical_cast(static_cast(8)) == zero + 8); - BOOST_CHECK(lexical_cast(static_cast(9)) == zero + 9); + BOOST_CHECK(lexical_cast(static_cast(0)) == zero + 0); + BOOST_CHECK(lexical_cast(static_cast(1)) == zero + 1); + BOOST_CHECK(lexical_cast(static_cast(2)) == zero + 2); + BOOST_CHECK(lexical_cast(static_cast(3)) == zero + 3); + BOOST_CHECK(lexical_cast(static_cast(4)) == zero + 4); + BOOST_CHECK(lexical_cast(static_cast(5)) == zero + 5); + BOOST_CHECK(lexical_cast(static_cast(6)) == zero + 6); + BOOST_CHECK(lexical_cast(static_cast(7)) == zero + 7); + BOOST_CHECK(lexical_cast(static_cast(8)) == zero + 8); + BOOST_CHECK(lexical_cast(static_cast(9)) == zero + 9); - BOOST_CHECK_THROW(lexical_cast(static_cast(10)), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(static_cast(10)), bad_lexical_cast); T t = std::numeric_limits::max(); - BOOST_CHECK_THROW(lexical_cast(t), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(t), bad_lexical_cast); } template @@ -423,8 +456,8 @@ void test_conversion_from_integral_to_string(CharT) { T const min_val = limits::min(); T const max_val = limits::max(); - int const counter = LCAST_INTEGRAL_TEST_COUNTER < max_val / 2 ? - LCAST_INTEGRAL_TEST_COUNTER : max_val / 2; + int const counter = lcast_integral_test_counter < max_val / 2 ? + lcast_integral_test_counter : max_val / 2; int i; From c17002aa73598ddb7f7543da469741e039993eaa Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Wed, 23 Aug 2006 19:47:56 +0000 Subject: [PATCH 010/242] get rid of lexical_cast.hpp impl details in the test [SVN r34932] --- lexical_cast_test.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index ca209fc..8f9601f 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -368,20 +368,17 @@ std::basic_string to_str_gcc_workaround(std::basic_string str) { std::locale loc; std::numpunct const& np = BOOST_USE_FACET(std::numpunct, loc); + std::ctype const& ct = BOOST_USE_FACET(std::ctype, loc); if(np.grouping().empty()) return str; - CharT prefix[3] = { - boost::detail::lcast_char_constants::minus, - np.thousands_sep(), - CharT() - }; + CharT prefix[3] = { ct.widen('-'), np.thousands_sep(), CharT() }; if(str.find(prefix) != 0) return str; - prefix[1] = CharT(); // "-," -> "-" + prefix[1] = CharT(); str.replace(0, 2, prefix); return str; } From 2fca4d02a12a483d5e38fce79719437fc87f6f95 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Fri, 25 Aug 2006 20:34:57 +0000 Subject: [PATCH 011/242] Optimization for many combinations of types [SVN r34950] --- include/boost/lexical_cast.hpp | 646 ++++++++++++++++++++++++++++++++- 1 file changed, 631 insertions(+), 15 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 41d80bf..8c903bb 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -11,17 +11,22 @@ // enhanced with contributions from Terje Slettebo, // with additional fixes and suggestions from Gennaro Prota, // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// and other Boosters -// when: November 2000, March 2003, June 2005 +// Alexander Nasonov and other Boosters +// when: November 2000, March 2003, June 2005, June 2006 +#include #include +#include +#include #include #include #include #include +#include #include #include #include +#include #ifdef BOOST_NO_STRINGSTREAM #include @@ -80,8 +85,8 @@ namespace boost typedef char type; }; - #ifndef DISABLE_WIDE_CHAR_SUPPORT -#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) +#ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef BOOST_NO_INTRINSIC_WCHAR_T template<> struct stream_char { @@ -106,7 +111,7 @@ namespace boost { typedef wchar_t type; }; - #endif +#endif template struct widest_char @@ -120,7 +125,325 @@ namespace boost typedef wchar_t type; }; } - + + namespace detail // lcast_src_length + { + // Return max. length of string representation of Source; + // 0 if unlimited (with exceptions for some types, see below). + // Values with limited string representation are placed to + // the buffer locally defined in lexical_cast function. + // 1 is returned for few types such as CharT const* or + // std::basic_string that already have an internal + // buffer ready to be reused by lexical_stream_limited_src. + // Each specialization should have a correspondent operator<< + // defined in lexical_stream_limited_src. + template< class CharT // A result of widest_char transformation. + , class Source // Source type of lexical_cast. + > + struct lcast_src_length + { + BOOST_STATIC_CONSTANT(std::size_t, value = 0); + // To check coverage, build the test with + // bjam --v2 profile optimization=off + 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() {} + }; + + // No specializations for: + // lcast_src_length + // lcast_src_length + // lcast_src_length + // lcast_src_length + // lcast_src_length + // lcast_src_length + +#ifndef DISABLE_WIDE_CHAR_SUPPORT + 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_NO_INTRINSIC_WCHAR_T + template<> + struct lcast_src_length + { + BOOST_STATIC_CONSTANT(std::size_t, value = 1); + static void check_coverage() {} + }; +#endif +#endif + + 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 DISABLE_WIDE_CHAR_SUPPORT + 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() {} + }; +#endif + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct lcast_src_length< CharT, std::basic_string > + { + BOOST_STATIC_CONSTANT(std::size_t, value = 1); + static void check_coverage() {} + }; +#else + template<> + struct lcast_src_length< char, std::basic_string > + { + BOOST_STATIC_CONSTANT(std::size_t, value = 1); + static void check_coverage() {} + }; + +#ifndef DISABLE_WIDE_CHAR_SUPPORT + template<> + struct lcast_src_length< wchar_t, std::basic_string > + { + BOOST_STATIC_CONSTANT(std::size_t, value = 1); + static void check_coverage() {} + }; +#endif +#endif + + // Helper for integral types. + // Notes on length calculation: + // Max length for 32bit int with grouping "\1" and thousands_sep ',': + // "-2,1,4,7,4,8,3,6,4,7" + // ^ - is_signed + // ^ - 1 digit not counted by digits10 + // ^^^^^^^^^^^^^^^^^^ - digits10 * 2 + // + // Constant is_specialized is used instead of constant 1 + // to prevent buffer overflow in a rare case when + // doesn't add missing specialization for + // numeric_limits for some integral type T. + // When is_specialized is false, the whole expression is 0. + template + struct lcast_src_length_integral + { +#if !defined(__BORLANDC__) || __BORLANDC__ >= 0x581 + BOOST_STATIC_CONSTANT(std::size_t, value = + std::numeric_limits::is_signed + + std::numeric_limits::is_specialized + // == 1 + std::numeric_limits::digits10 * 2 + ); +#else + BOOST_STATIC_CONSTANT(std::size_t, value = 156); // 256bit integers +#endif + }; + +#define BOOST_AUX_LEXICAL_CAST_DEF1(CharT, T) template<> \ + struct lcast_src_length : lcast_src_length_integral \ + { static void check_coverage() {} }; + +#ifdef DISABLE_WIDE_CHAR_SUPPORT +#define BOOST_AUX_LEXICAL_CAST_DEF(T) BOOST_AUX_LEXICAL_CAST_DEF1(char, T) +#else +#define BOOST_AUX_LEXICAL_CAST_DEF(T) \ + BOOST_AUX_LEXICAL_CAST_DEF1(char, T) \ + BOOST_AUX_LEXICAL_CAST_DEF1(wchar_t, T) +#endif + + BOOST_AUX_LEXICAL_CAST_DEF(short) + BOOST_AUX_LEXICAL_CAST_DEF(unsigned short) + BOOST_AUX_LEXICAL_CAST_DEF(int) + BOOST_AUX_LEXICAL_CAST_DEF(unsigned int) + BOOST_AUX_LEXICAL_CAST_DEF(long) + BOOST_AUX_LEXICAL_CAST_DEF(unsigned long) +#if defined(BOOST_HAS_LONG_LONG) + BOOST_AUX_LEXICAL_CAST_DEF(boost::ulong_long_type) + BOOST_AUX_LEXICAL_CAST_DEF(boost::long_long_type ) +#elif defined(BOOST_HAS_MS_INT64) + BOOST_AUX_LEXICAL_CAST_DEF(unsigned __int64) + BOOST_AUX_LEXICAL_CAST_DEF( __int64) +#endif + +#undef BOOST_AUX_LEXICAL_CAST_DEF +#undef BOOST_AUX_LEXICAL_CAST_DEF1 + + } + + namespace detail // '0' and '-' constants + { + template struct lcast_char_constants; + + template<> + struct lcast_char_constants + { + BOOST_STATIC_CONSTANT(char, zero = '0'); + BOOST_STATIC_CONSTANT(char, minus = '-'); + }; + +#ifndef DISABLE_WIDE_CHAR_SUPPORT + template<> + struct lcast_char_constants + { + BOOST_STATIC_CONSTANT(wchar_t, zero = L'0'); + BOOST_STATIC_CONSTANT(wchar_t, minus = L'-'); + }; +#endif + } + + namespace detail // public access to basic_streambuf::setg + { + template + class lexical_streambuf : public std::basic_streambuf + { + public: + void setbuf(CharT* start, CharT* finish) + { + this->setg(start, start, finish); + } + }; + } + + namespace detail // lcast_to_unsigned + { +#if (defined _MSC_VER) +# pragma warning( push ) +// C4146: unary minus operator applied to unsigned type, result still unsigned +# pragma warning( disable : 4146 ) +#endif + + inline unsigned int lcast_to_unsigned(int value) + { + unsigned int uval = value; + return value < 0 ? -uval : uval; + } + + inline unsigned long lcast_to_unsigned(long value) + { + unsigned long uval = value; + return value < 0 ? -uval : uval; + } + +#if defined(BOOST_HAS_LONG_LONG) + inline boost::ulong_long_type lcast_to_unsigned(boost::long_long_type v) + { + boost::ulong_long_type uval = v; + return v < 0 ? -uval : uval; + } +#elif defined(BOOST_HAS_MS_INT64) + inline unsigned __int64 lcast_to_unsigned(__int64 value) + { + unsigned __int64 uval = value; + return value < 0 ? -uval : uval; + } +#endif + +#if (defined _MSC_VER) +# pragma warning( pop ) // C4146: unary minus operator applied to unsigned type, result still unsigned +#endif + } + + namespace detail // lcast_put_unsigned + { + // I'd personally put lcast_put_unsigned in .cpp file if not + // boost practice for header-only libraries (Alexander Nasonov). + template + CharT* lcast_put_unsigned(T n, CharT* finish) + { + typedef std::numpunct numpunct; + + CharT thousands_sep = 0; + +#if !defined(MEASURE_LEXICAL_CAST_PERFORMANCE_WITHOUT_LOCALE_OVERHEAD) + std::locale loc; + numpunct const& np = BOOST_USE_FACET(numpunct, loc); + std::string const& grouping = np.grouping(); + std::string::size_type const grouping_size = grouping.size(); + + if(grouping_size) + thousands_sep = np.thousands_sep(); +#else // dead branch in production code + char const* grouping = ""; + std::size_t grouping_size = 0; +#endif + + std::string::size_type group = 0; // current group number + char last_grp_size = grouping[0] <= 0 ? CHAR_MAX : grouping[0]; + // a) Since grouping is const, grouping[grouping.size()] returns 0. + // b) It's safe to assume here and below that CHAR_MAX + // is equivalent to unlimited grouping: +#if !defined(__BORLANDC__) || __BORLANDC__ >= 0x581 + BOOST_STATIC_ASSERT(std::numeric_limits::digits10 < CHAR_MAX); +#endif + + char left = last_grp_size; + + do + { + if(left == 0) + { + ++group; + if(group < grouping_size) + { + char const grp_size = grouping[group]; + last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size; + } + + left = last_grp_size; + --finish; + *finish = thousands_sep; + } + + --left; + --finish; + int const digit = n % 10; + int const cdigit = digit + lcast_char_constants::zero; + *finish = static_cast(cdigit); + n /= 10; + } while(n); + + return finish; + } + } + namespace detail // stream wrapper for handling lexical conversions { template @@ -132,7 +455,7 @@ namespace boost typename stream_char::type>::type char_type; public: - lexical_stream() + lexical_stream(char_type* = 0, char_type* = 0) { stream.unsetf(std::ios::skipws); @@ -186,13 +509,13 @@ namespace boost #if defined(BOOST_NO_STRINGSTREAM) stream << '\0'; #endif - output = stream.str(); + stream.str().swap(output); return true; } #ifndef DISABLE_WIDE_CHAR_SUPPORT bool operator>>(std::wstring &output) { - output = stream.str(); + stream.str().swap(output); return true; } #endif @@ -207,6 +530,281 @@ namespace boost }; } + namespace detail // optimized stream wrapper + { + // String representation of Source has an upper limit. + template + class lexical_stream_limited_src + { + // A string representation of Source is written to [start, finish). + // Currently, it is assumed that [start, finish) is big enough + // to hold a string representation of any Source value. + CharT* start; + CharT* finish; + + private: + + static void widen_and_assign(char*p, char ch) + { + *p = ch; + } + +#ifndef DISABLE_WIDE_CHAR_SUPPORT + static void widen_and_assign(wchar_t* p, char ch) + { + std::locale loc; + *p = BOOST_USE_FACET(std::ctype, loc).widen(ch); + } + + static void widen_and_assign(wchar_t* p, wchar_t ch) + { + *p = ch; + } + + static void widen_and_assign(char*, wchar_t ch); // undefined +#endif + + // Undefined: + lexical_stream_limited_src(lexical_stream_limited_src const&); + void operator=(lexical_stream_limited_src const&); + + public: + + lexical_stream_limited_src(CharT* start, CharT* finish) + : start(start) + , finish(finish) + {} + + public: // output + + template + bool operator<<(std::basic_string const& str) + { + start = const_cast(str.data()); + finish = start + str.length(); + return true; + } + + bool operator<<(bool); + bool operator<<(char); +#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) + bool operator<<(wchar_t); +#endif + bool operator<<(CharT const*); + bool operator<<(short); + bool operator<<(int); + bool operator<<(long); + bool operator<<(unsigned short); + bool operator<<(unsigned int); + bool operator<<(unsigned long); +#if defined(BOOST_HAS_LONG_LONG) + bool operator<<(boost::ulong_long_type); + bool operator<<(boost::long_long_type ); +#elif defined(BOOST_HAS_MS_INT64) + bool operator<<(unsigned __int64); + bool operator<<( __int64); +#endif + + public: // input + + template + bool operator>>(InputStreamable& output) + { +#if (defined _MSC_VER) +# pragma warning( push ) + // conditional expression is constant +# pragma warning( disable : 4127 ) +#endif + if(is_pointer::value) + return false; + + lexical_streambuf sb; + sb.setbuf(start, finish); + + std::basic_istream stream(&sb); + stream.unsetf(std::ios::skipws); + + typedef std::numeric_limits limits; + + if(limits::is_specialized) + stream.precision(limits::digits10 + 1); +#if (defined _MSC_VER) +# pragma warning( pop ) +#endif + return stream >> output && + stream.get() == +#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) + // GCC 2.9x lacks std::char_traits<>::eof(). + // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 + // configurations, which do provide std::char_traits<>::eof(). + + EOF; +#else + std::char_traits::eof(); +#endif + } + + bool operator>>(CharT&); + bool operator>>(std::string&); + + #ifndef DISABLE_WIDE_CHAR_SUPPORT + bool operator>>(std::wstring&); + #endif + }; + + template + inline bool lexical_stream_limited_src::operator<<(bool value) + { + *start = value + lcast_char_constants::zero; + finish = start + 1; + return true; + } + + template + inline bool lexical_stream_limited_src::operator<<(char ch) + { + widen_and_assign(start, ch); + finish = start + 1; + return true; + } + +#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) + template + inline bool lexical_stream_limited_src::operator<<(wchar_t ch) + { + widen_and_assign(start, ch); + finish = start + 1; + return true; + } +#endif + + template + inline bool lexical_stream_limited_src::operator<<(short n) + { + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + if(n < 0) + *--start = lcast_char_constants::minus; + return true; + } + + template + inline bool lexical_stream_limited_src::operator<<(int n) + { + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + if(n < 0) + *--start = lcast_char_constants::minus; + return true; + } + + template + inline bool lexical_stream_limited_src::operator<<(long n) + { + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + if(n < 0) + *--start = lcast_char_constants::minus; + return true; + } + +#if defined(BOOST_HAS_LONG_LONG) + template + inline bool lexical_stream_limited_src::operator<<( + boost::long_long_type n) + { + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + if(n < 0) + *--start = lcast_char_constants::minus; + return true; + } +#elif defined(BOOST_HAS_MS_INT64) + template + inline bool lexical_stream_limited_src::operator<<(__int64 n) + { + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + if(n < 0) + *--start = lcast_char_constants::minus; + return true; + } +#endif + + template + inline bool lexical_stream_limited_src::operator<<( + unsigned short n) + { + start = lcast_put_unsigned(+n, finish); + return true; + } + + template + inline bool lexical_stream_limited_src::operator<<( + unsigned int n) + { + start = lcast_put_unsigned(n, finish); + return true; + } + + template + inline bool lexical_stream_limited_src::operator<<( + unsigned long n) + { + start = lcast_put_unsigned(n, finish); + return true; + } + +#if defined(BOOST_HAS_LONG_LONG) + template + inline bool lexical_stream_limited_src::operator<<( + boost::ulong_long_type n) + { + start = lcast_put_unsigned(n, finish); + return true; + } +#elif defined(BOOST_HAS_MS_INT64) + template + inline bool lexical_stream_limited_src::operator<<( + unsigned __int64 n) + { + start = lcast_put_unsigned(n, finish); + return true; + } +#endif + + template + inline bool lexical_stream_limited_src::operator<<( + CharT const* str) + { + start = const_cast(str); + finish = start + std::char_traits::length(str); + return true; + } + + template + inline bool lexical_stream_limited_src::operator>>(CharT& output) + { + bool const ok = (finish - start == 1); + if(ok) + output = *start; + return ok; + } + + template + inline bool lexical_stream_limited_src::operator>>( + std::string& str) + { + str.assign(start, finish); + return true; + } + + #ifndef DISABLE_WIDE_CHAR_SUPPORT + template + inline bool lexical_stream_limited_src::operator>>( + std::wstring& str) + { + str.assign(start, finish); + return true; + } + #endif + } + #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // call-by-const reference version @@ -225,12 +823,20 @@ namespace boost typedef const T * type; }; - template + template< typename Target + , typename Source + , bool Unlimited // string representation of Source is unlimited + , typename CharT + > Target lexical_cast( - BOOST_DEDUCED_TYPENAME boost::call_traits::value_type arg) + BOOST_DEDUCED_TYPENAME boost::call_traits::value_type arg, + CharT* buf, std::size_t src_len) { - - detail::lexical_stream interpreter; + BOOST_DEDUCED_TYPENAME mpl::if_c< + Unlimited + , detail::lexical_stream + , detail::lexical_stream_limited_src + >::type interpreter(buf, buf + src_len); // The original form, reproduced below, is more elegant // but yields a spurious C4701 warning ("possible use of @@ -255,8 +861,18 @@ namespace boost template inline Target lexical_cast(const Source &arg) { - typedef typename detail::array_to_pointer_decay::type NewSource; - return detail::lexical_cast(arg); + typedef typename detail::array_to_pointer_decay::type src; + + typedef typename detail::widest_char< + typename detail::stream_char::type + , typename detail::stream_char::type + >::type char_type; + + 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(); + return detail::lexical_cast(arg, buf, src_len); } #else From e797b095905a43d8a8dab73e744d7fd7f004492d Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sat, 26 Aug 2006 17:22:33 +0000 Subject: [PATCH 012/242] tabs replaced with 4 spaces [SVN r34965] --- include/boost/lexical_cast.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 8c903bb..5ea43c0 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -434,8 +434,8 @@ namespace boost --left; --finish; - int const digit = n % 10; - int const cdigit = digit + lcast_char_constants::zero; + int const digit = n % 10; + int const cdigit = digit + lcast_char_constants::zero; *finish = static_cast(cdigit); n /= 10; } while(n); From a7436ebacb83c027bc8dc86ac7b2913998fe3f9d Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Mon, 28 Aug 2006 17:00:44 +0000 Subject: [PATCH 013/242] setbuf renamed to lcast_setbuf to get rid of virtual function override warning [SVN r34984] --- include/boost/lexical_cast.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 5ea43c0..e8ac499 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -335,7 +335,7 @@ namespace boost class lexical_streambuf : public std::basic_streambuf { public: - void setbuf(CharT* start, CharT* finish) + void lcast_setbuf(CharT* start, CharT* finish) { this->setg(start, start, finish); } @@ -619,7 +619,7 @@ namespace boost return false; lexical_streambuf sb; - sb.setbuf(start, finish); + sb.lcast_setbuf(start, finish); std::basic_istream stream(&sb); stream.unsetf(std::ios::skipws); From a2c7ddf5d90287ccfdf52740417e59aa186ffb5a Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Wed, 11 Oct 2006 19:13:30 +0000 Subject: [PATCH 014/242] no more gcc warnings [SVN r35560] --- lexical_cast_test.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 8f9601f..506e975 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -417,13 +417,15 @@ void test_conversion_from_integral_to_integral() T t = 0; BOOST_CHECK(lexical_cast(t) == t); - t = 32767; - BOOST_CHECK(lexical_cast(t) == t); - BOOST_CHECK(lexical_cast(t) == t); - BOOST_CHECK(lexical_cast(t) == t); - BOOST_CHECK(lexical_cast(t) == t); - BOOST_CHECK(lexical_cast(t) == t); - BOOST_CHECK(lexical_cast(t) == t); + // Next two variables are used to supress warnings. + int st = 32767; unsigned int ut = st; + t = st; + BOOST_CHECK(lexical_cast(t) == st); + BOOST_CHECK(lexical_cast(t) == ut); + BOOST_CHECK(lexical_cast(t) == st); + BOOST_CHECK(lexical_cast(t) == ut); + BOOST_CHECK(lexical_cast(t) == st); + BOOST_CHECK(lexical_cast(t) == ut); t = std::numeric_limits::max(); BOOST_CHECK(lexical_cast(t) == t); @@ -453,10 +455,11 @@ void test_conversion_from_integral_to_string(CharT) { T const min_val = limits::min(); T const max_val = limits::max(); - int const counter = lcast_integral_test_counter < max_val / 2 ? - lcast_integral_test_counter : max_val / 2; + T const half_max_val = max_val / 2; + T const cnt = lcast_integral_test_counter; // to supress warnings + unsigned int const counter = cnt < half_max_val ? cnt : half_max_val; - int i; + unsigned int i; // Test values around min: t = min_val; @@ -470,12 +473,12 @@ void test_conversion_from_integral_to_string(CharT) // Test values around zero: if(limits::is_signed) - for(t = -counter; t < counter; ++t) + for(t = -counter; t < static_cast(counter); ++t) BOOST_CHECK(lexical_cast(t) == to_str(t)); // Test values around 100, 1000, 10000, ... T ten_power = 100; - for(i = 2; i <= limits::digits10; ++i, ten_power *= 10) + for(int e = 2; e <= limits::digits10; ++e, ten_power *= 10) { // I believe that (ten_power + 100) never overflows for(t = ten_power - 100; t != ten_power + 100; ++t) From ee7ea0011cf0ce1b21e2214ada7910e766406ff4 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Wed, 11 Oct 2006 19:19:07 +0000 Subject: [PATCH 015/242] Calculate/set stream precision for lexical_cast. May be useful for other libraries as well. [SVN r35561] --- include/boost/detail/lcast_precision.hpp | 113 +++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 include/boost/detail/lcast_precision.hpp diff --git a/include/boost/detail/lcast_precision.hpp b/include/boost/detail/lcast_precision.hpp new file mode 100644 index 0000000..49345d5 --- /dev/null +++ b/include/boost/detail/lcast_precision.hpp @@ -0,0 +1,113 @@ +// Copyright Alexander Nasonov & Paul A. Bristow 2006. + +// Use, modification and distribution are subject to 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) + +#ifndef BOOST_DETAIL_LCAST_SET_PRECISION_HPP_INCLUDED +#define BOOST_DETAIL_LCAST_SET_PRECISION_HPP_INCLUDED + +#include +#include +#include + +#include +#include + +#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#include +#define BOOST_DETAIL_LCAST_ASSERT(cond) BOOST_ASSERT(cond) +#else +#include +#define BOOST_DETAIL_LCAST_ASSERT(cond) BOOST_STATIC_ASSERT(cond) +// Remember, static_cast is evaluated even inside dead branches. +#endif + +namespace boost { namespace detail { + +#ifdef _MSC_VER +#pragma warning (push) +// conditional expression is constant (stream precision) +#pragma warning (disable : 4127) +#endif + +template +inline std::streamsize lcast_get_precision() +{ + typedef std::numeric_limits limits; + + bool const is_floating = limits::is_specialized && !limits::is_exact; + if(is_floating) + { // Includes all built-in floating-point types, float, double ... + // and UDT types for which digits (significand bits) is defined (not zero) + + bool const is_specialized_binary = is_floating && + limits::radix == 2 && limits::digits > 0; + bool const is_specialized_decimal = is_floating && + limits::radix == 10 && limits::digits10 > 0; + std::streamsize const precision_maxarg = + integer_traits::const_max; + if(is_specialized_binary) + { // Floating-point types with + // limist::digits defined by the specialization. + + unsigned long const digits = limits::digits; + unsigned long const precision = 2UL + digits * 30103UL / 100000UL; + // unsigned long is selected because it is at least 32-bits + // and thus ULONG_MAX / 30103UL is big enough for all types. + BOOST_DETAIL_LCAST_ASSERT(!is_specialized_binary || + digits < ULONG_MAX / 30103UL && + precision > limits::digits10 + 0UL && + precision <= precision_maxarg + 0UL + ); + return precision; + } + else if(is_specialized_decimal) + { // Decimal Floating-point type, most likely a User Defined Type + // rather than a real floating-point hardware type. + unsigned int const precision = limits::digits10 + 1U; + BOOST_DETAIL_LCAST_ASSERT(!is_specialized_decimal || + precision <= precision_maxarg + 0UL + ); + return precision; + } + } + + // Integral type (for which precision has no effect) + // or type T for which limits is NOT specialized, + // so assume stream precision remains the default 6 decimal digits. + // Warning: if your User-defined Floating-point type T is NOT specialized, + // then you may lose accuracy by only using 6 decimal digits. + // To avoid this, you need to specialize T with either + // radix == 2 and digits == the number of significand bits, + // OR + // radix = 10 and digits10 == the number of decimal digits. + + return 6; +} // template bool lcast_set_precision(std::ios_base& stream) + +template +inline void lcast_set_precision(std::ios_base& stream) +{ + stream.precision(lcast_get_precision()); +} + +template +inline void lcast_set_precision(std::ios_base& stream) +{ + std::streamsize const s = lcast_get_precision(); + std::streamsize const t = lcast_get_precision(); + stream.precision(s > t ? s : t); +} + +#ifdef _MSC_VER +#pragma warning (pop) +#endif + +}} + +#undef BOOST_DETAIL_LCAST_ASSERT + +#endif // BOOST_DETAIL_LCAST_SET_PRECISION_HPP_INCLUDED + From 115ad05af522ac1df1ddf97c41d2ec0d65830f41 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Wed, 11 Oct 2006 19:43:54 +0000 Subject: [PATCH 016/242] Set precision correctly for builtin and UDT floating types. [SVN r35562] --- include/boost/detail/lcast_precision.hpp | 10 +++++----- include/boost/lexical_cast.hpp | 24 +++--------------------- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/include/boost/detail/lcast_precision.hpp b/include/boost/detail/lcast_precision.hpp index 49345d5..085c569 100644 --- a/include/boost/detail/lcast_precision.hpp +++ b/include/boost/detail/lcast_precision.hpp @@ -5,8 +5,8 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_DETAIL_LCAST_SET_PRECISION_HPP_INCLUDED -#define BOOST_DETAIL_LCAST_SET_PRECISION_HPP_INCLUDED +#ifndef BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED +#define BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED #include #include @@ -28,7 +28,7 @@ namespace boost { namespace detail { #ifdef _MSC_VER #pragma warning (push) -// conditional expression is constant (stream precision) +// conditional expression is constant #pragma warning (disable : 4127) #endif @@ -85,7 +85,7 @@ inline std::streamsize lcast_get_precision() // radix = 10 and digits10 == the number of decimal digits. return 6; -} // template bool lcast_set_precision(std::ios_base& stream) +} template inline void lcast_set_precision(std::ios_base& stream) @@ -109,5 +109,5 @@ inline void lcast_set_precision(std::ios_base& stream) #undef BOOST_DETAIL_LCAST_ASSERT -#endif // BOOST_DETAIL_LCAST_SET_PRECISION_HPP_INCLUDED +#endif // BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index e8ac499..8b88bad 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #ifdef BOOST_NO_STRINGSTREAM #include @@ -458,25 +459,7 @@ namespace boost lexical_stream(char_type* = 0, char_type* = 0) { stream.unsetf(std::ios::skipws); - -#if (defined _MSC_VER) -# pragma warning( push ) - // conditional expression is constant -# pragma warning( disable : 4127 ) -#endif - - typedef std::numeric_limits t; - typedef std::numeric_limits s; - - if(t::is_specialized) - stream.precision(1 + t::digits10); - else if(s::is_specialized) - stream.precision(1 + s::digits10); - -#if (defined _MSC_VER) -# pragma warning( pop ) -#endif - + lcast_set_precision(stream); } ~lexical_stream() { @@ -626,8 +609,7 @@ namespace boost typedef std::numeric_limits limits; - if(limits::is_specialized) - stream.precision(limits::digits10 + 1); + lcast_set_precision(stream); #if (defined _MSC_VER) # pragma warning( pop ) #endif From 04de824eadae9f8d78bf62331f0e92684d9ed952 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 12 Oct 2006 06:39:14 +0000 Subject: [PATCH 017/242] vc6 workaround: help the compiler to distinguish overloads [SVN r35566] --- include/boost/detail/lcast_precision.hpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/include/boost/detail/lcast_precision.hpp b/include/boost/detail/lcast_precision.hpp index 085c569..92c828a 100644 --- a/include/boost/detail/lcast_precision.hpp +++ b/include/boost/detail/lcast_precision.hpp @@ -23,6 +23,10 @@ #define BOOST_DETAIL_LCAST_ASSERT(cond) BOOST_STATIC_ASSERT(cond) // Remember, static_cast is evaluated even inside dead branches. #endif +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +# include +# include +#endif namespace boost { namespace detail { @@ -88,13 +92,21 @@ inline std::streamsize lcast_get_precision() } template -inline void lcast_set_precision(std::ios_base& stream) +inline void lcast_set_precision(std::ios_base& stream +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + , short = 0 +#endif +) { stream.precision(lcast_get_precision()); } template -inline void lcast_set_precision(std::ios_base& stream) +inline void lcast_set_precision(std::ios_base& stream +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + , long = 0 +#endif +) { std::streamsize const s = lcast_get_precision(); std::streamsize const t = lcast_get_precision(); From 0a605d1bb36a9e833a44d6706552f8bc51bf1ace Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Fri, 13 Oct 2006 17:34:56 +0000 Subject: [PATCH 018/242] Use qualified name to fix graph tests [SVN r35592] --- include/boost/detail/lcast_precision.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/lcast_precision.hpp b/include/boost/detail/lcast_precision.hpp index 92c828a..bbd73e8 100644 --- a/include/boost/detail/lcast_precision.hpp +++ b/include/boost/detail/lcast_precision.hpp @@ -51,7 +51,7 @@ inline std::streamsize lcast_get_precision() bool const is_specialized_decimal = is_floating && limits::radix == 10 && limits::digits10 > 0; std::streamsize const precision_maxarg = - integer_traits::const_max; + boost::integer_traits::const_max; if(is_specialized_binary) { // Floating-point types with // limist::digits defined by the specialization. From 4b1ca7bdf6616c8091c50cfbb8d0dc9731933da9 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Fri, 13 Oct 2006 19:40:03 +0000 Subject: [PATCH 019/242] round conversion of floating point types: T -> std::string -> T [SVN r35595] --- lexical_cast_test.cpp | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 506e975..436f599 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -67,6 +67,9 @@ void test_conversion_from_ulong(); void test_conversion_from_longlong(); void test_conversion_from_ulonglong(); #endif +void test_round_conversion_float(); +void test_round_conversion_double(); +void test_round_conversion_long_double(); unit_test::test_suite *init_unit_test_suite(int, char *[]) { @@ -97,6 +100,8 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) suite->add(BOOST_TEST_CASE(&test_conversion_from_longlong)); suite->add(BOOST_TEST_CASE(&test_conversion_from_ulonglong)); #endif + suite->add(BOOST_TEST_CASE(&test_round_conversion_float)); + suite->add(BOOST_TEST_CASE(&test_round_conversion_double)); return suite; } @@ -606,3 +611,42 @@ void test_conversion_from_ulonglong() #endif +template +void test_round_conversion() +{ + T v1 = std::numeric_limits::epsilon(); + std::string s1 = boost::lexical_cast(v1); + BOOST_CHECK(v1 == lexical_cast(s1)); + + T v2 = (std::numeric_limits::max)(); + std::string s2 = boost::lexical_cast(v2); + BOOST_CHECK(v2 == lexical_cast(s2)); + + T v3 = (std::numeric_limits::min)(); + std::string s3 = boost::lexical_cast(v3); + BOOST_CHECK(v3 == lexical_cast(s3)); + + T v4 = v2 / 137; + std::string s4 = boost::lexical_cast(v4); + BOOST_CHECK(v4 == lexical_cast(s4)); + + T v5 = v1 * 137; + std::string s5 = boost::lexical_cast(v5); + BOOST_CHECK(v5 == lexical_cast(s5)); +} + +void test_round_conversion_float() +{ + test_round_conversion(); +} + +void test_round_conversion_double() +{ + test_round_conversion(); +} + +void test_round_conversion_long_double() +{ + test_round_conversion(); +} + From 36db66bd125ebe79f6d75378318c5dfd3843645d Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Fri, 13 Oct 2006 20:43:14 +0000 Subject: [PATCH 020/242] Use metafunction (at compile-time), if possible; use run-time function only for broken libraries. [SVN r35596] --- include/boost/detail/lcast_precision.hpp | 93 +++++++++++++++++------- 1 file changed, 67 insertions(+), 26 deletions(-) diff --git a/include/boost/detail/lcast_precision.hpp b/include/boost/detail/lcast_precision.hpp index bbd73e8..5281e17 100644 --- a/include/boost/detail/lcast_precision.hpp +++ b/include/boost/detail/lcast_precision.hpp @@ -17,11 +17,8 @@ #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS #include -#define BOOST_DETAIL_LCAST_ASSERT(cond) BOOST_ASSERT(cond) #else #include -#define BOOST_DETAIL_LCAST_ASSERT(cond) BOOST_STATIC_ASSERT(cond) -// Remember, static_cast is evaluated even inside dead branches. #endif #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) # include @@ -30,29 +27,80 @@ namespace boost { namespace detail { -#ifdef _MSC_VER -#pragma warning (push) -// conditional expression is constant -#pragma warning (disable : 4127) +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +// Calculate an argument to pass to std::ios_base::precision from +// lexical_cast. See alternative implementation for broken standard +// libraries in lcast_get_precision below. Keep them in sync, please. +template +struct lcast_precision +{ + typedef std::numeric_limits limits; + + BOOST_STATIC_CONSTANT(bool, use_default_precision = + !limits::is_specialized || limits::is_exact + ); + + BOOST_STATIC_CONSTANT(bool, is_specialized_bin = + !use_default_precision && + limits::radix == 2 && limits::digits > 0 + ); + + BOOST_STATIC_CONSTANT(bool, is_specialized_dec = + !use_default_precision && + limits::radix == 10 && limits::digits10 > 0 + ); + + BOOST_STATIC_CONSTANT(std::streamsize, streamsize_max = + boost::integer_traits::const_max + ); + + BOOST_STATIC_CONSTANT(unsigned int, precision_dec = limits::digits10 + 1U); + + BOOST_STATIC_ASSERT(!is_specialized_dec || + precision_dec <= streamsize_max + 0UL + ); + + BOOST_STATIC_CONSTANT(unsigned long, precision_bin = + 2UL + limits::digits * 30103UL / 100000UL + ); + + BOOST_STATIC_ASSERT(!is_specialized_bin || + limits::digits + 0UL < ULONG_MAX / 30103UL && + precision_bin > limits::digits10 + 0UL && + precision_bin <= streamsize_max + 0UL + ); + + BOOST_STATIC_CONSTANT(std::streamsize, value = + is_specialized_bin ? precision_bin + : is_specialized_dec ? precision_dec : 6 + ); +}; #endif template inline std::streamsize lcast_get_precision() { +#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) + return lcast_precision::value; +#else // Follow lcast_precision algorithm at run-time: + typedef std::numeric_limits limits; - bool const is_floating = limits::is_specialized && !limits::is_exact; - if(is_floating) + bool const use_default_precision = + !limits::is_specialized || limits::is_exact; + + if(!use_default_precision) { // Includes all built-in floating-point types, float, double ... // and UDT types for which digits (significand bits) is defined (not zero) - bool const is_specialized_binary = is_floating && + bool const is_specialized_bin = limits::radix == 2 && limits::digits > 0; - bool const is_specialized_decimal = is_floating && + bool const is_specialized_dec = limits::radix == 10 && limits::digits10 > 0; - std::streamsize const precision_maxarg = - boost::integer_traits::const_max; - if(is_specialized_binary) + std::streamsize const streamsize_max = + (boost::integer_traits::max)(); + + if(is_specialized_bin) { // Floating-point types with // limist::digits defined by the specialization. @@ -60,20 +108,18 @@ inline std::streamsize lcast_get_precision() unsigned long const precision = 2UL + digits * 30103UL / 100000UL; // unsigned long is selected because it is at least 32-bits // and thus ULONG_MAX / 30103UL is big enough for all types. - BOOST_DETAIL_LCAST_ASSERT(!is_specialized_binary || + BOOST_ASSERT( digits < ULONG_MAX / 30103UL && precision > limits::digits10 + 0UL && - precision <= precision_maxarg + 0UL + precision <= streamsize_max + 0UL ); return precision; } - else if(is_specialized_decimal) + else if(is_specialized_dec) { // Decimal Floating-point type, most likely a User Defined Type // rather than a real floating-point hardware type. unsigned int const precision = limits::digits10 + 1U; - BOOST_DETAIL_LCAST_ASSERT(!is_specialized_decimal || - precision <= precision_maxarg + 0UL - ); + BOOST_ASSERT(precision <= streamsize_max + 0UL); return precision; } } @@ -89,6 +135,7 @@ inline std::streamsize lcast_get_precision() // radix = 10 and digits10 == the number of decimal digits. return 6; +#endif } template @@ -113,13 +160,7 @@ inline void lcast_set_precision(std::ios_base& stream stream.precision(s > t ? s : t); } -#ifdef _MSC_VER -#pragma warning (pop) -#endif - }} -#undef BOOST_DETAIL_LCAST_ASSERT - #endif // BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED From 2b069eb3a36ca5074959dd94f5db6126c244b589 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Fri, 13 Oct 2006 22:27:53 +0000 Subject: [PATCH 021/242] test_round_conversion_long_double added to testsuite despite that it fails on FreeBSD and OpenBSD [SVN r35600] --- lexical_cast_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 436f599..9e02078 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -102,6 +102,7 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) #endif suite->add(BOOST_TEST_CASE(&test_round_conversion_float)); suite->add(BOOST_TEST_CASE(&test_round_conversion_double)); + suite->add(BOOST_TEST_CASE(&test_round_conversion_long_double)); return suite; } From e9767dc4e88a84d5c6c4e1353a010d09ed5786ab Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sat, 14 Oct 2006 10:09:49 +0000 Subject: [PATCH 022/242] workarounds for test_round_conversion_long_double [SVN r35606] --- lexical_cast_test.cpp | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 9e02078..b8b4658 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -613,23 +613,26 @@ void test_conversion_from_ulonglong() #endif template -void test_round_conversion() +void test_round_conversion(bool use_min_max_values = true) { T v1 = std::numeric_limits::epsilon(); std::string s1 = boost::lexical_cast(v1); BOOST_CHECK(v1 == lexical_cast(s1)); - T v2 = (std::numeric_limits::max)(); - std::string s2 = boost::lexical_cast(v2); - BOOST_CHECK(v2 == lexical_cast(s2)); + if(use_min_max_values) + { + T v2 = (std::numeric_limits::max)(); + std::string s2 = boost::lexical_cast(v2); + BOOST_CHECK(v2 == lexical_cast(s2)); - T v3 = (std::numeric_limits::min)(); - std::string s3 = boost::lexical_cast(v3); - BOOST_CHECK(v3 == lexical_cast(s3)); + T v3 = (std::numeric_limits::min)(); + std::string s3 = boost::lexical_cast(v3); + BOOST_CHECK(v3 == lexical_cast(s3)); - T v4 = v2 / 137; - std::string s4 = boost::lexical_cast(v4); - BOOST_CHECK(v4 == lexical_cast(s4)); + T v4 = v2 / 137; + std::string s4 = boost::lexical_cast(v4); + BOOST_CHECK(v4 == lexical_cast(s4)); + } T v5 = v1 * 137; std::string s5 = boost::lexical_cast(v5); @@ -648,6 +651,12 @@ void test_round_conversion_double() void test_round_conversion_long_double() { +#if defined(BOOST_NO_STDLIB_CONFIG) test_round_conversion(); +#elif defined(__i386__) && defined(__OpenBSD__) + test_round_conversion(false); +#elif !defined(__i386__) || !defined(__FreeBSD__) + test_round_conversion(); +#endif } From d23f722228f204f35b2d7f5243526db69f9f0408 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sat, 14 Oct 2006 17:58:33 +0000 Subject: [PATCH 023/242] Corrected a typo in comments. [SVN r35611] --- include/boost/detail/lcast_precision.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/detail/lcast_precision.hpp b/include/boost/detail/lcast_precision.hpp index 5281e17..f8a3231 100644 --- a/include/boost/detail/lcast_precision.hpp +++ b/include/boost/detail/lcast_precision.hpp @@ -102,7 +102,7 @@ inline std::streamsize lcast_get_precision() if(is_specialized_bin) { // Floating-point types with - // limist::digits defined by the specialization. + // limits::digits defined by the specialization. unsigned long const digits = limits::digits; unsigned long const precision = 2UL + digits * 30103UL / 100000UL; From 4d69e9f2afca4e30de38ba49adf8422a1520b340 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Wed, 25 Oct 2006 06:41:21 +0000 Subject: [PATCH 024/242] VC6 workaround [SVN r35738] --- include/boost/detail/lcast_precision.hpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/include/boost/detail/lcast_precision.hpp b/include/boost/detail/lcast_precision.hpp index f8a3231..c7b5824 100644 --- a/include/boost/detail/lcast_precision.hpp +++ b/include/boost/detail/lcast_precision.hpp @@ -20,10 +20,6 @@ #else #include #endif -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) -# include -# include -#endif namespace boost { namespace detail { @@ -139,21 +135,13 @@ inline std::streamsize lcast_get_precision() } template -inline void lcast_set_precision(std::ios_base& stream -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) - , short = 0 -#endif -) +inline void lcast_set_precision(std::ios_base& stream, T* = 0) { stream.precision(lcast_get_precision()); } template -inline void lcast_set_precision(std::ios_base& stream -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) - , long = 0 -#endif -) +inline void lcast_set_precision(std::ios_base& stream, Source* = 0, Target* = 0) { std::streamsize const s = lcast_get_precision(); std::streamsize const t = lcast_get_precision(); From 663635d124905df405e33b23a85683bd5c804929 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Wed, 25 Oct 2006 06:43:44 +0000 Subject: [PATCH 025/242] Optimization for floating types (1.25 faster on gcc / FreeBSD 6.2). VC6 test is still broken. [SVN r35739] --- include/boost/lexical_cast.hpp | 335 +++++++++++++++++++++++++++------ 1 file changed, 276 insertions(+), 59 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 8b88bad..7008dc0 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -307,6 +307,76 @@ namespace boost #undef BOOST_AUX_LEXICAL_CAST_DEF #undef BOOST_AUX_LEXICAL_CAST_DEF1 +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +// This #if is in sync with lcast_precision + + // Helper for floating point types. + // -1.23456789e-123456 + // ^ sign + // ^ leading digit + // ^ decimal point + // ^^^^^^^^ lcast_precision::value + // ^ "e" + // ^ exponent sign + // ^^^^^^ exponent (assumed 6 or less digits) + // sign + leading digit + decimal point + "e" + exponent sign == 5 + template + struct lcast_src_length_floating + { + BOOST_STATIC_ASSERT( + std::numeric_limits::max_exponent10 <= 999999L && + std::numeric_limits::min_exponent10 >= -999999L + ); + BOOST_STATIC_CONSTANT(std::size_t, value = + 5 + lcast_precision::value + 6 + ); + }; + + 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() {} + }; + +#ifndef DISABLE_WIDE_CHAR_SUPPORT + 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 DISABLE_WIDE_CHAR_SUPPORT +#endif // #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS } namespace detail // '0' and '-' constants @@ -330,16 +400,16 @@ namespace boost #endif } - namespace detail // public access to basic_streambuf::setg + namespace detail // lexical_streambuf and lexical_streambuf_fake { template - class lexical_streambuf : public std::basic_streambuf + class lexical_streambuf : protected std::basic_streambuf + { + }; + + template + struct lexical_streambuf_fake { - public: - void lcast_setbuf(CharT* start, CharT* finish) - { - this->setg(start, start, finish); - } }; } @@ -411,7 +481,7 @@ namespace boost // a) Since grouping is const, grouping[grouping.size()] returns 0. // b) It's safe to assume here and below that CHAR_MAX // is equivalent to unlimited grouping: -#if !defined(__BORLANDC__) || __BORLANDC__ >= 0x581 +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS BOOST_STATIC_ASSERT(std::numeric_limits::digits10 < CHAR_MAX); #endif @@ -459,7 +529,7 @@ namespace boost lexical_stream(char_type* = 0, char_type* = 0) { stream.unsetf(std::ios::skipws); - lcast_set_precision(stream); + lcast_set_precision(stream, (Source*)0, (Target*)0); } ~lexical_stream() { @@ -516,8 +586,10 @@ namespace boost namespace detail // optimized stream wrapper { // String representation of Source has an upper limit. - template - class lexical_stream_limited_src + template< class CharT // a result of widest_char transformation + , class Base // lexical_streambuf or lexical_streambuf_fake + > + class lexical_stream_limited_src : protected Base { // A string representation of Source is written to [start, finish). // Currently, it is assumed that [start, finish) is big enough @@ -547,6 +619,17 @@ namespace boost static void widen_and_assign(char*, wchar_t ch); // undefined #endif + template + bool lcast_put(const OutputStreamable& input) + { + this->setp(start, finish); + std::basic_ostream stream(static_cast(this)); + lcast_set_precision(stream, (OutputStreamable*)0); + bool const result = !(stream << input).fail(); + finish = this->pptr(); + return result; + } + // Undefined: lexical_stream_limited_src(lexical_stream_limited_src const&); void operator=(lexical_stream_limited_src const&); @@ -587,9 +670,16 @@ namespace boost bool operator<<(unsigned __int64); bool operator<<( __int64); #endif + // These three operators use ostream and streambuf. + // lcast_streambuf_for_source::value is true. + bool operator<<(float); + bool operator<<(double); + bool operator<<(long double); public: // input + // Generic istream-based algorithm. + // lcast_streambuf_for_target::value is true. template bool operator>>(InputStreamable& output) { @@ -601,15 +691,10 @@ namespace boost if(is_pointer::value) return false; - lexical_streambuf sb; - sb.lcast_setbuf(start, finish); - - std::basic_istream stream(&sb); + this->setg(start, start, finish); + std::basic_istream stream(static_cast(this)); stream.unsetf(std::ios::skipws); - - typedef std::numeric_limits limits; - - lcast_set_precision(stream); + lcast_set_precision(stream, (InputStreamable*)0); #if (defined _MSC_VER) # pragma warning( pop ) #endif @@ -627,23 +712,37 @@ namespace boost } bool operator>>(CharT&); + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +// This #if is in sync with lcast_streambuf_for_target + bool operator>>(std::string&); - #ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef DISABLE_WIDE_CHAR_SUPPORT bool operator>>(std::wstring&); - #endif +#endif + +#else + template + bool operator>>(std::basic_string& str) + { + str.assign(start, finish); + return true; + } +#endif }; - template - inline bool lexical_stream_limited_src::operator<<(bool value) + template + inline bool lexical_stream_limited_src::operator<<( + bool value) { *start = value + lcast_char_constants::zero; finish = start + 1; return true; } - template - inline bool lexical_stream_limited_src::operator<<(char ch) + template + inline bool lexical_stream_limited_src::operator<<(char ch) { widen_and_assign(start, ch); finish = start + 1; @@ -651,8 +750,9 @@ namespace boost } #if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) - template - inline bool lexical_stream_limited_src::operator<<(wchar_t ch) + template + inline bool lexical_stream_limited_src::operator<<( + wchar_t ch) { widen_and_assign(start, ch); finish = start + 1; @@ -660,8 +760,8 @@ namespace boost } #endif - template - inline bool lexical_stream_limited_src::operator<<(short n) + template + inline bool lexical_stream_limited_src::operator<<(short n) { start = lcast_put_unsigned(lcast_to_unsigned(n), finish); if(n < 0) @@ -669,8 +769,8 @@ namespace boost return true; } - template - inline bool lexical_stream_limited_src::operator<<(int n) + template + inline bool lexical_stream_limited_src::operator<<(int n) { start = lcast_put_unsigned(lcast_to_unsigned(n), finish); if(n < 0) @@ -678,8 +778,8 @@ namespace boost return true; } - template - inline bool lexical_stream_limited_src::operator<<(long n) + template + inline bool lexical_stream_limited_src::operator<<(long n) { start = lcast_put_unsigned(lcast_to_unsigned(n), finish); if(n < 0) @@ -688,8 +788,8 @@ namespace boost } #if defined(BOOST_HAS_LONG_LONG) - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( boost::long_long_type n) { start = lcast_put_unsigned(lcast_to_unsigned(n), finish); @@ -698,8 +798,9 @@ namespace boost return true; } #elif defined(BOOST_HAS_MS_INT64) - template - inline bool lexical_stream_limited_src::operator<<(__int64 n) + template + inline bool lexical_stream_limited_src::operator<<( + __int64 n) { start = lcast_put_unsigned(lcast_to_unsigned(n), finish); if(n < 0) @@ -708,24 +809,24 @@ namespace boost } #endif - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( unsigned short n) { start = lcast_put_unsigned(+n, finish); return true; } - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( unsigned int n) { start = lcast_put_unsigned(n, finish); return true; } - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( unsigned long n) { start = lcast_put_unsigned(n, finish); @@ -733,16 +834,16 @@ namespace boost } #if defined(BOOST_HAS_LONG_LONG) - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( boost::ulong_long_type n) { start = lcast_put_unsigned(n, finish); return true; } #elif defined(BOOST_HAS_MS_INT64) - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( unsigned __int64 n) { start = lcast_put_unsigned(n, finish); @@ -750,8 +851,29 @@ namespace boost } #endif - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( + float val) + { + return this->lcast_put(val); + } + + template + inline bool lexical_stream_limited_src::operator<<( + double val) + { + return this->lcast_put(val); + } + + template + inline bool lexical_stream_limited_src::operator<<( + long double val) + { + return this->lcast_put(val); + } + + template + inline bool lexical_stream_limited_src::operator<<( CharT const* str) { start = const_cast(str); @@ -759,8 +881,9 @@ namespace boost return true; } - template - inline bool lexical_stream_limited_src::operator>>(CharT& output) + template + inline bool lexical_stream_limited_src::operator>>( + CharT& output) { bool const ok = (finish - start == 1); if(ok) @@ -768,23 +891,109 @@ namespace boost return ok; } - template - inline bool lexical_stream_limited_src::operator>>( +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + inline bool lexical_stream_limited_src::operator>>( std::string& str) { str.assign(start, finish); return true; } - #ifndef DISABLE_WIDE_CHAR_SUPPORT - template - inline bool lexical_stream_limited_src::operator>>( +#ifndef DISABLE_WIDE_CHAR_SUPPORT + template + inline bool lexical_stream_limited_src::operator>>( std::wstring& str) { str.assign(start, finish); return true; } - #endif +#endif +#endif + } + + namespace detail // lcast_streambuf_for_source + { + // Returns true if optimized stream wrapper uses ostream for formatting. + template + struct lcast_streambuf_for_source + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + + template<> + struct lcast_streambuf_for_source + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + template<> + struct lcast_streambuf_for_source + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + template<> + struct lcast_streambuf_for_source + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + } + + namespace detail // lcast_streambuf_for_target + { + // Returns true if optimized stream wrapper use istream for reading. + template + struct lcast_streambuf_for_target + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + template<> + struct lcast_streambuf_for_target + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + +#ifndef DISABLE_WIDE_CHAR_SUPPORT + template<> + struct lcast_streambuf_for_target + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; +#endif + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct lcast_streambuf_for_target< + std::basic_string > + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + +#ifndef DISABLE_WIDE_CHAR_SUPPORT + template + struct lcast_streambuf_for_target< + std::basic_string > + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; +#endif +#else + template<> + struct lcast_streambuf_for_target + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + +#ifndef DISABLE_WIDE_CHAR_SUPPORT + template<> + struct lcast_streambuf_for_target + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; +#endif +#endif } #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION @@ -814,10 +1023,17 @@ namespace boost BOOST_DEDUCED_TYPENAME boost::call_traits::value_type arg, CharT* buf, std::size_t src_len) { - BOOST_DEDUCED_TYPENAME mpl::if_c< + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< + lcast_streambuf_for_target::value || + lcast_streambuf_for_source::value + , lexical_streambuf + , lexical_streambuf_fake + >::type base; + + BOOST_DEDUCED_TYPENAME boost::mpl::if_c< Unlimited , detail::lexical_stream - , detail::lexical_stream_limited_src + , detail::lexical_stream_limited_src >::type interpreter(buf, buf + src_len); // The original form, reproduced below, is more elegant @@ -876,6 +1092,7 @@ namespace boost } // Copyright Kevlin Henney, 2000-2005. +// Copyright Alexander Nasonov, 2006. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at From 0f46451c1d5c12d5b57c4eb4d30e96f132a878cd Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Wed, 25 Oct 2006 21:08:50 +0000 Subject: [PATCH 026/242] One more VC6 workaround. [SVN r35747] --- include/boost/detail/lcast_precision.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/detail/lcast_precision.hpp b/include/boost/detail/lcast_precision.hpp index c7b5824..3124538 100644 --- a/include/boost/detail/lcast_precision.hpp +++ b/include/boost/detail/lcast_precision.hpp @@ -74,7 +74,7 @@ struct lcast_precision #endif template -inline std::streamsize lcast_get_precision() +inline std::streamsize lcast_get_precision(T* = 0) { #if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) return lcast_precision::value; @@ -143,8 +143,8 @@ inline void lcast_set_precision(std::ios_base& stream, T* = 0) template inline void lcast_set_precision(std::ios_base& stream, Source* = 0, Target* = 0) { - std::streamsize const s = lcast_get_precision(); - std::streamsize const t = lcast_get_precision(); + std::streamsize const s = lcast_get_precision((Source*)0); + std::streamsize const t = lcast_get_precision((Target*)0); stream.precision(s > t ? s : t); } From fb63ebd4cd32b1d2de78e727d24d244d8bd6a52b Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Fri, 27 Oct 2006 21:28:33 +0000 Subject: [PATCH 027/242] The test passed on VC6 [SVN r35755] --- lexical_cast_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index b8b4658..2f3dd45 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -518,7 +518,7 @@ void test_conversion_from_integral() test_conversion_from_integral_to_char(zero); test_conversion_from_integral_to_char(szero); test_conversion_from_integral_to_char(uzero); -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) wchar_t const wzero = L'0'; test_conversion_from_integral_to_char(wzero); #endif From ef439017ca62e6bbe43a179489eadd05e7ebd9db Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sat, 28 Oct 2006 10:22:30 +0000 Subject: [PATCH 028/242] Fixed: std::basic_streambuf > is an inaccessible base of boost::detail::lexical_streambuf [SVN r35759] --- include/boost/lexical_cast.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 7008dc0..b376363 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -403,7 +403,7 @@ namespace boost namespace detail // lexical_streambuf and lexical_streambuf_fake { template - class lexical_streambuf : protected std::basic_streambuf + class lexical_streambuf : public std::basic_streambuf { }; @@ -589,7 +589,7 @@ namespace boost template< class CharT // a result of widest_char transformation , class Base // lexical_streambuf or lexical_streambuf_fake > - class lexical_stream_limited_src : protected Base + class lexical_stream_limited_src : public Base { // A string representation of Source is written to [start, finish). // Currently, it is assumed that [start, finish) is big enough From c004fb5fc63fc513d3af0b508b42f39dae5d55a7 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sat, 28 Oct 2006 14:37:37 +0000 Subject: [PATCH 029/242] Fix the test built with off on vc-7_1 and vc-8_0 [SVN r35760] --- include/boost/lexical_cast.hpp | 2 +- lexical_cast_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index b376363..491774a 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -955,7 +955,7 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = false); }; -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) template<> struct lcast_streambuf_for_target { diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 2f3dd45..052a49c 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -498,7 +498,7 @@ void test_conversion_from_integral_for_locale() { test_conversion_from_integral_to_integral(); test_conversion_from_integral_to_string('0'); -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) test_conversion_from_integral_to_string(L'0'); #endif } From 67968d9b33576ebd6deaadb7a213db8ee9e01fc5 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sat, 28 Oct 2006 19:33:32 +0000 Subject: [PATCH 030/242] Separate test for round-tripping of floating point types. [SVN r35771] --- lexical_cast_test.cpp | 54 ---------------- test/Jamfile | 3 +- test/Jamfile.v2 | 3 +- test/lexical_cast_loopback_test.cpp | 98 +++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 56 deletions(-) create mode 100644 test/lexical_cast_loopback_test.cpp diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 052a49c..6ba26a3 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -67,9 +67,6 @@ void test_conversion_from_ulong(); void test_conversion_from_longlong(); void test_conversion_from_ulonglong(); #endif -void test_round_conversion_float(); -void test_round_conversion_double(); -void test_round_conversion_long_double(); unit_test::test_suite *init_unit_test_suite(int, char *[]) { @@ -100,9 +97,6 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) suite->add(BOOST_TEST_CASE(&test_conversion_from_longlong)); suite->add(BOOST_TEST_CASE(&test_conversion_from_ulonglong)); #endif - suite->add(BOOST_TEST_CASE(&test_round_conversion_float)); - suite->add(BOOST_TEST_CASE(&test_round_conversion_double)); - suite->add(BOOST_TEST_CASE(&test_round_conversion_long_double)); return suite; } @@ -612,51 +606,3 @@ void test_conversion_from_ulonglong() #endif -template -void test_round_conversion(bool use_min_max_values = true) -{ - T v1 = std::numeric_limits::epsilon(); - std::string s1 = boost::lexical_cast(v1); - BOOST_CHECK(v1 == lexical_cast(s1)); - - if(use_min_max_values) - { - T v2 = (std::numeric_limits::max)(); - std::string s2 = boost::lexical_cast(v2); - BOOST_CHECK(v2 == lexical_cast(s2)); - - T v3 = (std::numeric_limits::min)(); - std::string s3 = boost::lexical_cast(v3); - BOOST_CHECK(v3 == lexical_cast(s3)); - - T v4 = v2 / 137; - std::string s4 = boost::lexical_cast(v4); - BOOST_CHECK(v4 == lexical_cast(s4)); - } - - T v5 = v1 * 137; - std::string s5 = boost::lexical_cast(v5); - BOOST_CHECK(v5 == lexical_cast(s5)); -} - -void test_round_conversion_float() -{ - test_round_conversion(); -} - -void test_round_conversion_double() -{ - test_round_conversion(); -} - -void test_round_conversion_long_double() -{ -#if defined(BOOST_NO_STDLIB_CONFIG) - test_round_conversion(); -#elif defined(__i386__) && defined(__OpenBSD__) - test_round_conversion(false); -#elif !defined(__i386__) || !defined(__FreeBSD__) - test_round_conversion(); -#endif -} - diff --git a/test/Jamfile b/test/Jamfile index 8af8d65..20d8265 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -27,8 +27,9 @@ DEPENDS all : test ; : [ run implicit_cast.cpp ] [ compile-fail implicit_cast_fail.cpp ] [ run ../cast_test.cpp ] - [ run ../numeric_cast_test.cpp ] + [ run ../numeric_cast_test.cpp ] [ run ../lexical_cast_test.cpp ../../test/build/boost_unit_test_framework ] + [ run lexical_cast_loopback_test.cpp ../../test/build/boost_unit_test_framework ] ; } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 58ae133..1b89444 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -21,6 +21,7 @@ test-suite conversion [ run ../cast_test.cpp ] [ run ../numeric_cast_test.cpp ] [ run ../lexical_cast_test.cpp ../../test/build//boost_unit_test_framework ] + [ run lexical_cast_loopback_test.cpp ../../test/build//boost_unit_test_framework ] ; - \ No newline at end of file + diff --git a/test/lexical_cast_loopback_test.cpp b/test/lexical_cast_loopback_test.cpp new file mode 100644 index 0000000..cd058fe --- /dev/null +++ b/test/lexical_cast_loopback_test.cpp @@ -0,0 +1,98 @@ +// Unit test for boost::lexical_cast. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Alexander Nasonov, 2006. +// +// 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). +// +// Test round-tripping conversion FPT -> string -> FPT, +// where FPT is Floating Point Type. + +#include + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include +#include + +using namespace boost; + +void test_round_conversion_float(); +void test_round_conversion_double(); +void test_round_conversion_long_double(); + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test_framework::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast unit test"); + suite->add(BOOST_TEST_CASE(&test_round_conversion_float)); + suite->add(BOOST_TEST_CASE(&test_round_conversion_double)); + suite->add(BOOST_TEST_CASE(&test_round_conversion_long_double)); + + return suite; +} + +template +void test_round_conversion() +{ + T epsilon = std::numeric_limits::epsilon(); + std::string const epsilon_s = boost::lexical_cast(epsilon); + BOOST_CHECK(epsilon == lexical_cast(epsilon_s)); + + T max_ = (std::numeric_limits::max)(); + std::string const max_s = boost::lexical_cast(max_); + BOOST_CHECK(max_ == lexical_cast(max_s)); + + T min_ = (std::numeric_limits::min)(); + std::string const min_s = boost::lexical_cast(min_); + BOOST_CHECK(min_ == lexical_cast(min_s)); + + T max_div137 = max_ / 137; + std::string max_div137_s = boost::lexical_cast(max_div137); + BOOST_CHECK(max_div137 == lexical_cast(max_div137_s)); + + T epsilon_mult137 = epsilon * 137; + std::string epsilon_mult137_s(lexical_cast(epsilon_mult137)); + BOOST_CHECK(epsilon_mult137 == lexical_cast(epsilon_mult137_s)); + +} + +#if defined(BOOST_MSVC) +// See bug http://tinyurl.com/vhpvo +template +void test_msvc_magic_values() +{ + T magic_msvc = 0.00010000433948393407; + std::string magic_msvc_s = boost::lexical_cast(magic_msvc); + BOOST_CHECK(magic_msvc == lexical_cast(magic_msvc_s)); +} +#endif + +void test_round_conversion_float() +{ + test_round_conversion(); +} + +void test_round_conversion_double() +{ + test_round_conversion(); +#if defined(BOOST_MSVC) + test_msvc_magic_values(); +#endif +} + +void test_round_conversion_long_double() +{ + test_round_conversion(); +#if defined(BOOST_MSVC) + test_msvc_magic_values(); +#endif +} + From de6746d67a4dc014dd2313af52d61ea20a96610e Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Fri, 10 Nov 2006 19:09:56 +0000 Subject: [PATCH 031/242] Allow building of shared versions of some Boost.Test libraries. Adjust tests to use always use static linking to Boost.Test, since linking to the shared version requires test changes. Patch from Juergen Hunold. [SVN r35989] --- test/Jamfile.v2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 1b89444..0e59404 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -20,8 +20,8 @@ test-suite conversion [ compile-fail implicit_cast_fail.cpp ] [ run ../cast_test.cpp ] [ run ../numeric_cast_test.cpp ] - [ run ../lexical_cast_test.cpp ../../test/build//boost_unit_test_framework ] - [ run lexical_cast_loopback_test.cpp ../../test/build//boost_unit_test_framework ] + [ run ../lexical_cast_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run lexical_cast_loopback_test.cpp ../../test/build//boost_unit_test_framework/static ] ; From fcc28133c5fa60e978e825628439439ba8ed5387 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Wed, 20 Dec 2006 08:01:48 +0000 Subject: [PATCH 032/242] Presumably fix Boost.Test failures on Sun CC 5.3 (reported by Gennadiy Rozental) [SVN r36464] --- include/boost/detail/lcast_precision.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/detail/lcast_precision.hpp b/include/boost/detail/lcast_precision.hpp index 3124538..dad5dc6 100644 --- a/include/boost/detail/lcast_precision.hpp +++ b/include/boost/detail/lcast_precision.hpp @@ -135,13 +135,13 @@ inline std::streamsize lcast_get_precision(T* = 0) } template -inline void lcast_set_precision(std::ios_base& stream, T* = 0) +inline void lcast_set_precision(std::ios_base& stream, T*) { stream.precision(lcast_get_precision()); } template -inline void lcast_set_precision(std::ios_base& stream, Source* = 0, Target* = 0) +inline void lcast_set_precision(std::ios_base& stream, Source*, Target*) { std::streamsize const s = lcast_get_precision((Source*)0); std::streamsize const t = lcast_get_precision((Target*)0); From 2c41ed0473965bc4684f74b15cbbd9250b89216b Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Tue, 16 Jan 2007 21:03:47 +0000 Subject: [PATCH 033/242] Fix for [ 1358600 ] lexical_cast & pure virtual functions & VC 8 STL [SVN r36738] --- include/boost/lexical_cast.hpp | 2 +- test/Jamfile | 1 + test/Jamfile.v2 | 1 + test/lexical_cast_abstract_test.cpp | 61 +++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 test/lexical_cast_abstract_test.cpp diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 491774a..8a0266c 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1020,7 +1020,7 @@ namespace boost , typename CharT > Target lexical_cast( - BOOST_DEDUCED_TYPENAME boost::call_traits::value_type arg, + BOOST_DEDUCED_TYPENAME boost::call_traits::param_type arg, CharT* buf, std::size_t src_len) { typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< diff --git a/test/Jamfile b/test/Jamfile index 20d8265..e1bacb5 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -30,6 +30,7 @@ DEPENDS all : test ; [ run ../numeric_cast_test.cpp ] [ run ../lexical_cast_test.cpp ../../test/build/boost_unit_test_framework ] [ run lexical_cast_loopback_test.cpp ../../test/build/boost_unit_test_framework ] + [ run lexical_cast_abstract_test.cpp ../../test/build/boost_unit_test_framework ] ; } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0e59404..7108858 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -22,6 +22,7 @@ test-suite conversion [ run ../numeric_cast_test.cpp ] [ run ../lexical_cast_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_loopback_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run lexical_cast_abstract_test.cpp ../../test/build//boost_unit_test_framework/static ] ; diff --git a/test/lexical_cast_abstract_test.cpp b/test/lexical_cast_abstract_test.cpp new file mode 100644 index 0000000..207d3a5 --- /dev/null +++ b/test/lexical_cast_abstract_test.cpp @@ -0,0 +1,61 @@ +// Unit test for boost::lexical_cast. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Sergey Shandar 2005, Alexander Nasonov, 2007. +// +// 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). +// +// Test abstract class. Bug 1358600: +// http://sf.net/tracker/?func=detail&aid=1358600&group_id=7586&atid=107586 + +#include + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include +#include + +using namespace boost; + +void test_abstract(); + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test_framework::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast unit test"); + suite->add(BOOST_TEST_CASE(&test_abstract)); + + return suite; +} + +class A +{ +public: + virtual void out(std::ostream &) const = 0; +}; + +class B: public A +{ +public: + virtual void out(std::ostream &O) const { O << "B"; } +}; + +std::ostream &operator<<(std::ostream &O, const A &a) +{ + a.out(O); + return O; +}; + +void test_abstract() +{ + const A &a = B(); + BOOST_CHECK(boost::lexical_cast(a) == "B"); +} + From 986ec16eccae61113095f2472fa240fcf05fb29a Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Tue, 16 Jan 2007 21:53:27 +0000 Subject: [PATCH 034/242] Fix [ 1358600 ] lexical_cast & pure virtual functions & VC 8 STL [SVN r36739] --- include/boost/detail/lcast_precision.hpp | 29 ++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/include/boost/detail/lcast_precision.hpp b/include/boost/detail/lcast_precision.hpp index dad5dc6..9b785cd 100644 --- a/include/boost/detail/lcast_precision.hpp +++ b/include/boost/detail/lcast_precision.hpp @@ -15,6 +15,10 @@ #include #include +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) // VC++ 8.0 +#include +#endif + #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS #include #else @@ -23,6 +27,27 @@ namespace boost { namespace detail { +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) + +template struct lcast_msvc_limits; + +template +struct lcast_msvc_limits + : std::numeric_limits +{ +}; + +// Non-abstract class that does define a specialization of numeric_limits: +class lcast_msvc_without_limits {}; + +template +struct lcast_msvc_limits + : std::numeric_limits +{ +}; + +#endif // VC++ workaround + #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS // Calculate an argument to pass to std::ios_base::precision from // lexical_cast. See alternative implementation for broken standard @@ -30,7 +55,11 @@ namespace boost { namespace detail { template struct lcast_precision { +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) + typedef lcast_msvc_limits::value)> limits; +#else typedef std::numeric_limits limits; +#endif BOOST_STATIC_CONSTANT(bool, use_default_precision = !limits::is_specialized || limits::is_exact From cf477316edf1596e5ecd365efa3918394d22e070 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Tue, 16 Jan 2007 22:22:19 +0000 Subject: [PATCH 035/242] Documentation update for [ 1358600 ] lexical_cast & pure virtual functions & VC 8 STL [SVN r36740] --- lexical_cast.htm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lexical_cast.htm b/lexical_cast.htm index 949b70c..f55d741 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -160,7 +160,7 @@ void log_errno(int yoko) and an instance of the result type on the right.
  • - Both Source and Target are CopyConstructible [20.1.3]. + Target is CopyConstructible [20.1.3].
  • Target is DefaultConstructible, meaning that it is possible @@ -231,4 +231,4 @@ public:
    © Copyright Kevlin Henney, 2000–2005
    - \ No newline at end of file + From 209644c17783bc25b64b090d958e57b8929a18e6 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sat, 20 Jan 2007 13:16:40 +0000 Subject: [PATCH 036/242] Better fix for SF:1358600 [SVN r36762] --- include/boost/detail/lcast_precision.hpp | 45 +++++++++++------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/include/boost/detail/lcast_precision.hpp b/include/boost/detail/lcast_precision.hpp index 9b785cd..5bd96fd 100644 --- a/include/boost/detail/lcast_precision.hpp +++ b/include/boost/detail/lcast_precision.hpp @@ -15,7 +15,9 @@ #include #include -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) // VC++ 8.0 +#ifndef BOOST_NO_IS_ABSTRACT +// Fix for SF:1358600 - lexical_cast & pure virtual functions & VC 8 STL +#include #include #endif @@ -27,26 +29,7 @@ namespace boost { namespace detail { -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) - -template struct lcast_msvc_limits; - -template -struct lcast_msvc_limits - : std::numeric_limits -{ -}; - -// Non-abstract class that does define a specialization of numeric_limits: -class lcast_msvc_without_limits {}; - -template -struct lcast_msvc_limits - : std::numeric_limits -{ -}; - -#endif // VC++ workaround +class lcast_abstract_stub {}; #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS // Calculate an argument to pass to std::ios_base::precision from @@ -55,10 +38,14 @@ struct lcast_msvc_limits template struct lcast_precision { -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) - typedef lcast_msvc_limits::value)> limits; +#ifdef BOOST_NO_IS_ABSTRACT + typedef std::numeric_limits limits; // No fix for SF:1358600. #else - typedef std::numeric_limits limits; + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< + boost::is_abstract + , std::numeric_limits + , std::numeric_limits + >::type limits; #endif BOOST_STATIC_CONSTANT(bool, use_default_precision = @@ -109,7 +96,15 @@ inline std::streamsize lcast_get_precision(T* = 0) return lcast_precision::value; #else // Follow lcast_precision algorithm at run-time: - typedef std::numeric_limits limits; +#ifdef BOOST_NO_IS_ABSTRACT + typedef std::numeric_limits limits; // No fix for SF:1358600. +#else + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< + boost::is_abstract + , std::numeric_limits + , std::numeric_limits + >::type limits; +#endif bool const use_default_precision = !limits::is_specialized || limits::is_exact; From 42cb6d66cf2680700ebef3847d7f1cca3af44bb2 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sat, 20 Jan 2007 13:17:35 +0000 Subject: [PATCH 037/242] lexical_cast_noncopyable_test.cpp [SVN r36763] --- test/Jamfile | 1 + test/Jamfile.v2 | 1 + test/lexical_cast_noncopyable_test.cpp | 54 ++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 test/lexical_cast_noncopyable_test.cpp diff --git a/test/Jamfile b/test/Jamfile index e1bacb5..06f5ae8 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -31,6 +31,7 @@ DEPENDS all : test ; [ run ../lexical_cast_test.cpp ../../test/build/boost_unit_test_framework ] [ run lexical_cast_loopback_test.cpp ../../test/build/boost_unit_test_framework ] [ run lexical_cast_abstract_test.cpp ../../test/build/boost_unit_test_framework ] + [ run lexical_cast_noncopyable_test.cpp ../../test/build/boost_unit_test_framework ] ; } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7108858..af68510 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -23,6 +23,7 @@ test-suite conversion [ run ../lexical_cast_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_loopback_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_abstract_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run lexical_cast_noncopyable_test.cpp ../../test/build//boost_unit_test_framework/static ] ; diff --git a/test/lexical_cast_noncopyable_test.cpp b/test/lexical_cast_noncopyable_test.cpp new file mode 100644 index 0000000..6284b14 --- /dev/null +++ b/test/lexical_cast_noncopyable_test.cpp @@ -0,0 +1,54 @@ +// Unit test for boost::lexical_cast. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Alexander Nasonov, 2007. +// +// 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). +// +// Test that Source can be non-copyable. + +#include + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include +#include +#include + +using namespace boost; + +void test_noncopyable(); + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test_framework::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast unit test"); + suite->add(BOOST_TEST_CASE(&test_noncopyable)); + + return suite; +} + +class Noncopyable : private boost::noncopyable +{ +public: + Noncopyable() {} +}; + +inline std::ostream &operator<<(std::ostream &out, const Noncopyable&) +{ + return out << "Noncopyable"; +} + +void test_noncopyable() +{ + Noncopyable x; + BOOST_CHECK(boost::lexical_cast(x) == "Noncopyable"); +} + From 959b7ab0b47df8c31d26e9541cd5c6e5aad9c2ac Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Mon, 26 Feb 2007 17:27:26 +0000 Subject: [PATCH 038/242] Fixed a warning, when lexical cast is used to convert a boost::ulong_long_type to a string. [SVN r37082] --- include/boost/lexical_cast.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 8a0266c..c5f0343 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -505,7 +505,7 @@ namespace boost --left; --finish; - int const digit = n % 10; + int const digit = static_cast(n % 10); int const cdigit = digit + lcast_char_constants::zero; *finish = static_cast(cdigit); n /= 10; From f986e8e588e86ef3bba2989828767136791771be Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Wed, 28 Feb 2007 21:44:10 +0000 Subject: [PATCH 039/242] Get rid of Tru64 cxx warnings [SVN r37116] --- include/boost/lexical_cast.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index c5f0343..da8262e 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -505,7 +505,7 @@ namespace boost --left; --finish; - int const digit = static_cast(n % 10); + int const digit = static_cast(n % 10); int const cdigit = digit + lcast_char_constants::zero; *finish = static_cast(cdigit); n /= 10; From da5151abf6670ca4664380e7bd4556c25c154a5b Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sun, 20 May 2007 16:25:34 +0000 Subject: [PATCH 040/242] added: FAQ and References section, updated: Changes [SVN r37725] --- lexical_cast.htm | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/lexical_cast.htm b/lexical_cast.htm index f55d741..2a08541 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -20,6 +20,10 @@ lexical_cast
  • bad_lexical_cast
  • +
  • + Frequently Asked Questions
  • +
  • + References
  • Changes
  • @@ -192,7 +196,39 @@ public: failure.
    +

    Frequently Asked Questions

    +

    Q: Why does lexical_cast<int8_t>("127") throw bad_lexical_cast? +
    A: The type int8_t is a typedef to char or signed char. + Lexical conversion to these types is simply reading a byte from source but since the source has + more than one byte, the exception is thrown. +

    Please use other integer types such as int or short int. If bounds checking + is important, you can also call numeric_cast: + +

    numeric_cast<int8_t>(lexical_cast<int>("127"));
    + +

    Q: What does lexical_cast<std::string> of an int8_t or uint8_t not do what I expect? +
    A: As above, note that int8_t and uint8_t are actually chars and are formatted as such. To avoid this, cast to an integer type first: + +

    lexical_cast<std::string>(static_cast<int>(n));
    + +

    Q: The implementation always resets the ios_base::skipws flag of an underlying stream object. It breaks my operator>> that works only in presence of this flag. Can you remove code that resets the flag? +
    A: May be in a future version. There is no requirement in [N1973] to reset the flag but remember that [N1973] is not yet accepted by the committee. By the way, it's a great opportunity to make your operator>> conform to the standard. Read a good C++ book, study std::sentry and ios_state_saver. + +

    References

    +
      +
    • [N1973] Kevlin Henney, Beman Dawes, Lexical Conversion Library Proposal for TR2, + N1973. +
    • [Tuning] Alexander Nasonov, Fine Tuning for lexical_cast, + Overload #74, + August 2006.
    • +

    Changes

    +

    August, October 2006:

    +
      +
    • Better performance for many combinations of Source and Target + types. Refer to [Tuning] for more details. +
    • +

    June 2005:

    • Call-by-const reference for the parameters. This requires partial specialization From 9c1f3650f276880bf9837dca840c1d14ed3688a4 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Fri, 8 Jun 2007 19:59:40 +0000 Subject: [PATCH 041/242] Added BOOST_LEXICAL_CAST_ASSUME_C_LOCALE. [SVN r37950] --- include/boost/lexical_cast.hpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index da8262e..1cd23f7 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -459,21 +459,20 @@ namespace boost template CharT* lcast_put_unsigned(T n, CharT* finish) { - typedef std::numpunct numpunct; - CharT thousands_sep = 0; -#if !defined(MEASURE_LEXICAL_CAST_PERFORMANCE_WITHOUT_LOCALE_OVERHEAD) +#ifdef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE + char const* grouping = ""; + std::size_t const grouping_size = 0; +#else std::locale loc; + typedef std::numpunct numpunct; numpunct const& np = BOOST_USE_FACET(numpunct, loc); std::string const& grouping = np.grouping(); std::string::size_type const grouping_size = grouping.size(); if(grouping_size) thousands_sep = np.thousands_sep(); -#else // dead branch in production code - char const* grouping = ""; - std::size_t grouping_size = 0; #endif std::string::size_type group = 0; // current group number From b9a7ee6debe9cbbb701150d28f5af985a1d3b0f0 Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Wed, 8 Aug 2007 19:02:26 +0000 Subject: [PATCH 042/242] Remove V1 Jamfiles [SVN r38516] --- test/Jamfile | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 test/Jamfile diff --git a/test/Jamfile b/test/Jamfile deleted file mode 100644 index 06f5ae8..0000000 --- a/test/Jamfile +++ /dev/null @@ -1,37 +0,0 @@ -# Signals library - -# Copyright (C) 2001-2003 Douglas Gregor - -# Permission to copy, use, sell and distribute this software is granted -# provided this copyright notice appears in all copies. Permission to modify -# the code and to distribute modified code is granted provided this copyright -# notice appears in all copies, and a notice that the code was modified is -# included with the copyright notice. This software is provided "as is" -# without express or implied warranty, and with no claim as to its suitability -# for any purpose. - -# For more information, see http://www.boost.org/ - - -# Testing Jamfile autogenerated from XML source -subproject libs/conversion/test ; - -# bring in rules for testing -import testing ; - -# Make tests run by default. -DEPENDS all : test ; - -{ - test-suite conversion - : [ run implicit_cast.cpp ] - [ compile-fail implicit_cast_fail.cpp ] - [ run ../cast_test.cpp ] - [ run ../numeric_cast_test.cpp ] - [ run ../lexical_cast_test.cpp ../../test/build/boost_unit_test_framework ] - [ run lexical_cast_loopback_test.cpp ../../test/build/boost_unit_test_framework ] - [ run lexical_cast_abstract_test.cpp ../../test/build/boost_unit_test_framework ] - [ run lexical_cast_noncopyable_test.cpp ../../test/build/boost_unit_test_framework ] - ; -} - From 0d6a924f94ad0cefbdabfc09d6dd9376aef043d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20M=20L=C3=B3pez=20Mu=C3=B1oz?= Date: Thu, 18 Oct 2007 06:57:25 +0000 Subject: [PATCH 043/242] applied workaround for MSVC++ 6.5/7.0 problem with static constants inside templates, see http://lists.boost.org/Archives/boost/2007/10/128392.php [SVN r40146] --- include/boost/detail/lcast_precision.hpp | 12 +++++++++--- include/boost/lexical_cast.hpp | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/boost/detail/lcast_precision.hpp b/include/boost/detail/lcast_precision.hpp index 5bd96fd..ef23c8a 100644 --- a/include/boost/detail/lcast_precision.hpp +++ b/include/boost/detail/lcast_precision.hpp @@ -21,7 +21,13 @@ #include #endif -#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#if defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || \ + (defined(BOOST_MSVC) && (BOOST_MSVC<1310)) + +#define BOOST_LCAST_NO_COMPILE_TIME_PRECISION +#endif + +#ifdef BOOST_LCAST_NO_COMPILE_TIME_PRECISION #include #else #include @@ -31,7 +37,7 @@ namespace boost { namespace detail { class lcast_abstract_stub {}; -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION // Calculate an argument to pass to std::ios_base::precision from // lexical_cast. See alternative implementation for broken standard // libraries in lcast_get_precision below. Keep them in sync, please. @@ -92,7 +98,7 @@ struct lcast_precision template inline std::streamsize lcast_get_precision(T* = 0) { -#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) +#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION return lcast_precision::value; #else // Follow lcast_precision algorithm at run-time: diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 1cd23f7..8f40d47 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -307,7 +307,7 @@ namespace boost #undef BOOST_AUX_LEXICAL_CAST_DEF #undef BOOST_AUX_LEXICAL_CAST_DEF1 -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION // This #if is in sync with lcast_precision // Helper for floating point types. @@ -376,7 +376,7 @@ namespace boost }; #endif // #ifndef DISABLE_WIDE_CHAR_SUPPORT -#endif // #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION } namespace detail // '0' and '-' constants From e70cf014ad5c293ac192be41d7d9056ea52ed401 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Mon, 5 Nov 2007 22:22:48 +0000 Subject: [PATCH 044/242] #839 fixed: local variable shadow patch [SVN r40816] --- include/boost/lexical_cast.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 8f40d47..5a29e85 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -52,9 +52,9 @@ namespace boost { } bad_lexical_cast( - const std::type_info &source_type, - const std::type_info &target_type) : - source(&source_type), target(&target_type) + const std::type_info &source_type_arg, + const std::type_info &target_type_arg) : + source(&source_type_arg), target(&target_type_arg) { } const std::type_info &source_type() const From 726f188aa498f7a0e100013f0085a55c8fd68a16 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sat, 17 Nov 2007 20:13:16 +0000 Subject: [PATCH 045/242] // Add or correct comment identifying Boost library this header is associated with. [SVN r41173] --- include/boost/lexical_cast.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 5a29e85..4428275 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -3,7 +3,7 @@ // Boost lexical_cast.hpp header -------------------------------------------// // -// See http://www.boost.org/ for most recent version including documentation. +// See http://www.boost.org/libs/converston for documentation. // See end of this header for rights and permissions. // // what: lexical_cast custom keyword cast From 340f9b9e45c4fe43076cdf98997e57cf3d32d928 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Tue, 20 Nov 2007 16:52:43 +0000 Subject: [PATCH 046/242] fix warning in gcc-4.3 [SVN r41258] --- include/boost/detail/lcast_precision.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/detail/lcast_precision.hpp b/include/boost/detail/lcast_precision.hpp index ef23c8a..d40ca21 100644 --- a/include/boost/detail/lcast_precision.hpp +++ b/include/boost/detail/lcast_precision.hpp @@ -83,9 +83,9 @@ struct lcast_precision ); BOOST_STATIC_ASSERT(!is_specialized_bin || - limits::digits + 0UL < ULONG_MAX / 30103UL && + (limits::digits + 0UL < ULONG_MAX / 30103UL && precision_bin > limits::digits10 + 0UL && - precision_bin <= streamsize_max + 0UL + precision_bin <= streamsize_max + 0UL) ); BOOST_STATIC_CONSTANT(std::streamsize, value = From 2cc7aedd284d91f0eacca834c045dc4fc9ae42b5 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sat, 24 Nov 2007 15:22:52 +0000 Subject: [PATCH 047/242] minor changes [SVN r41331] --- include/boost/lexical_cast.hpp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 4428275..754aecf 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -267,14 +267,15 @@ namespace boost template struct lcast_src_length_integral { -#if !defined(__BORLANDC__) || __BORLANDC__ >= 0x581 +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS BOOST_STATIC_CONSTANT(std::size_t, value = std::numeric_limits::is_signed + std::numeric_limits::is_specialized + // == 1 std::numeric_limits::digits10 * 2 ); #else - BOOST_STATIC_CONSTANT(std::size_t, value = 156); // 256bit integers + BOOST_STATIC_CONSTANT(std::size_t, value = 156); + BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256); #endif }; @@ -400,14 +401,8 @@ namespace boost #endif } - namespace detail // lexical_streambuf and lexical_streambuf_fake + namespace detail // lexical_streambuf_fake { - template - class lexical_streambuf : public std::basic_streambuf - { - }; - - template struct lexical_streambuf_fake { }; @@ -448,7 +443,8 @@ namespace boost #endif #if (defined _MSC_VER) -# pragma warning( pop ) // C4146: unary minus operator applied to unsigned type, result still unsigned +# pragma warning( pop ) // C4146: unary minus operator applied to unsigned type, + // result still unsigned #endif } @@ -459,6 +455,9 @@ namespace boost template CharT* lcast_put_unsigned(T n, CharT* finish) { +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(!std::numeric_limits::is_signed); +#endif CharT thousands_sep = 0; #ifdef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE @@ -586,7 +585,7 @@ namespace boost { // String representation of Source has an upper limit. template< class CharT // a result of widest_char transformation - , class Base // lexical_streambuf or lexical_streambuf_fake + , class Base // lexical_streambuf_fake or basic_streambuf > class lexical_stream_limited_src : public Base { @@ -913,7 +912,7 @@ namespace boost namespace detail // lcast_streambuf_for_source { - // Returns true if optimized stream wrapper uses ostream for formatting. + // Returns true if optimized stream wrapper needs ostream for writing. template struct lcast_streambuf_for_source { @@ -941,7 +940,7 @@ namespace boost namespace detail // lcast_streambuf_for_target { - // Returns true if optimized stream wrapper use istream for reading. + // Returns true if optimized stream wrapper needs istream for reading. template struct lcast_streambuf_for_target { @@ -1025,8 +1024,8 @@ namespace boost typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< lcast_streambuf_for_target::value || lcast_streambuf_for_source::value - , lexical_streambuf - , lexical_streambuf_fake + , std::basic_streambuf + , lexical_streambuf_fake >::type base; BOOST_DEDUCED_TYPENAME boost::mpl::if_c< @@ -1091,7 +1090,7 @@ namespace boost } // Copyright Kevlin Henney, 2000-2005. -// Copyright Alexander Nasonov, 2006. +// Copyright Alexander Nasonov, 2006-2007. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at From 159b045ad79f163b3b03ee01fd358f70870611f2 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sun, 25 Nov 2007 22:28:16 +0000 Subject: [PATCH 048/242] Pass unsigned type to lcast_put_unsigned. [SVN r41385] --- include/boost/lexical_cast.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 754aecf..12a89f8 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -811,7 +811,7 @@ namespace boost inline bool lexical_stream_limited_src::operator<<( unsigned short n) { - start = lcast_put_unsigned(+n, finish); + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); return true; } From 05036d3ae16fedffe164b457e3bf7ab49241a063 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sun, 25 Nov 2007 23:08:50 +0000 Subject: [PATCH 049/242] Support for string with non-default char_traits and allocator. [SVN r41387] --- include/boost/lexical_cast.hpp | 260 +++++++++++++++++++++++---------- lexical_cast_test.cpp | 245 ++++++++++++++++++++++++------- 2 files changed, 375 insertions(+), 130 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 12a89f8..4f68452 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -86,6 +86,14 @@ namespace boost typedef char type; }; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct stream_char< std::basic_string > + { + typedef CharT type; + }; +#endif + #ifndef DISABLE_WIDE_CHAR_SUPPORT #ifndef BOOST_NO_INTRINSIC_WCHAR_T template<> @@ -107,11 +115,13 @@ namespace boost typedef wchar_t type; }; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template<> struct stream_char { typedef wchar_t type; }; +#endif #endif template @@ -127,6 +137,44 @@ namespace boost }; } + namespace detail // deduce_char_traits template + { +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct deduce_char_traits + { + typedef std::char_traits type; + }; + + template + struct deduce_char_traits< CharT + , std::basic_string + , Source + > + { + typedef Traits type; + }; + + template + struct deduce_char_traits< CharT + , Target + , std::basic_string + > + { + typedef Traits type; + }; + + template + struct deduce_char_traits< CharT + , std::basic_string + , std::basic_string + > + { + typedef Traits type; + }; +#endif + } + namespace detail // lcast_src_length { // Return max. length of string representation of Source; @@ -309,8 +357,6 @@ namespace boost #undef BOOST_AUX_LEXICAL_CAST_DEF1 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION -// This #if is in sync with lcast_precision - // Helper for floating point types. // -1.23456789e-123456 // ^ sign @@ -450,9 +496,7 @@ namespace boost namespace detail // lcast_put_unsigned { - // I'd personally put lcast_put_unsigned in .cpp file if not - // boost practice for header-only libraries (Alexander Nasonov). - template + template CharT* lcast_put_unsigned(T n, CharT* finish) { #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS @@ -482,6 +526,9 @@ namespace boost #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS BOOST_STATIC_ASSERT(std::numeric_limits::digits10 < CHAR_MAX); #endif + typedef typename Traits::int_type int_type; + CharT const czero = lcast_char_constants::zero; + int_type const zero = Traits::to_int_type(czero); char left = last_grp_size; @@ -498,14 +545,13 @@ namespace boost left = last_grp_size; --finish; - *finish = thousands_sep; + Traits::assign(*finish, thousands_sep); } --left; --finish; - int const digit = static_cast(n % 10); - int const cdigit = digit + lcast_char_constants::zero; - *finish = static_cast(cdigit); + int_type const digit = static_cast(n % 10U); + Traits::assign(*finish, Traits::to_char_type(zero + digit)); n /= 10; } while(n); @@ -515,7 +561,7 @@ namespace boost namespace detail // stream wrapper for handling lexical conversions { - template + template class lexical_stream { private: @@ -523,6 +569,8 @@ namespace boost typename stream_char::type, typename stream_char::type>::type char_type; + typedef Traits traits_type; + public: lexical_stream(char_type* = 0, char_type* = 0) { @@ -552,9 +600,12 @@ namespace boost EOF; #else - std::char_traits::eof(); + traits_type::eof(); #endif } + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + bool operator>>(std::string &output) { #if defined(BOOST_NO_STRINGSTREAM) @@ -570,13 +621,29 @@ namespace boost return true; } #endif + +#else + bool operator>>(std::basic_string& output) + { + stream.str().swap(output); + return true; + } + + template + bool operator>>(std::basic_string& out) + { + std::basic_string str(stream.str()); + out.assign(str.begin(), str.end()); + return true; + } +#endif private: #if defined(BOOST_NO_STRINGSTREAM) std::strstream stream; #elif defined(BOOST_NO_STD_LOCALE) std::stringstream stream; #else - std::basic_stringstream stream; + std::basic_stringstream stream; #endif }; } @@ -586,6 +653,7 @@ namespace boost // String representation of Source has an upper limit. template< class CharT // a result of widest_char transformation , class Base // lexical_streambuf_fake or basic_streambuf + , class Traits // usually char_traits > class lexical_stream_limited_src : public Base { @@ -599,19 +667,20 @@ namespace boost static void widen_and_assign(char*p, char ch) { - *p = ch; + Traits::assign(*p, ch); } #ifndef DISABLE_WIDE_CHAR_SUPPORT static void widen_and_assign(wchar_t* p, char ch) { std::locale loc; - *p = BOOST_USE_FACET(std::ctype, loc).widen(ch); + wchar_t w = BOOST_USE_FACET(std::ctype, loc).widen(ch); + Traits::assign(*p, w); } static void widen_and_assign(wchar_t* p, wchar_t ch) { - *p = ch; + Traits::assign(*p, ch); } static void widen_and_assign(char*, wchar_t ch); // undefined @@ -641,8 +710,8 @@ namespace boost public: // output - template - bool operator<<(std::basic_string const& str) + template + bool operator<<(std::basic_string const& str) { start = const_cast(str.data()); finish = start + str.length(); @@ -705,7 +774,7 @@ namespace boost EOF; #else - std::char_traits::eof(); + Traits::eof(); #endif } @@ -721,7 +790,7 @@ namespace boost #endif #else - template + template bool operator>>(std::basic_string& str) { str.assign(start, finish); @@ -730,17 +799,21 @@ namespace boost #endif }; - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( bool value) { - *start = value + lcast_char_constants::zero; + typedef typename Traits::int_type int_type; + CharT const czero = lcast_char_constants::zero; + int_type const zero = Traits::to_int_type(czero); + Traits::assign(*start, Traits::to_char_type(zero + value)); finish = start + 1; return true; } - template - inline bool lexical_stream_limited_src::operator<<(char ch) + template + inline bool lexical_stream_limited_src::operator<<( + char ch) { widen_and_assign(start, ch); finish = start + 1; @@ -748,8 +821,8 @@ namespace boost } #if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( wchar_t ch) { widen_and_assign(start, ch); @@ -758,140 +831,163 @@ namespace boost } #endif - template - inline bool lexical_stream_limited_src::operator<<(short n) + template + inline bool lexical_stream_limited_src::operator<<( + short n) { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); if(n < 0) - *--start = lcast_char_constants::minus; + { + --start; + CharT const minus = lcast_char_constants::minus; + Traits::assign(*start, minus); + } return true; } - template - inline bool lexical_stream_limited_src::operator<<(int n) + template + inline bool lexical_stream_limited_src::operator<<( + int n) { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); if(n < 0) - *--start = lcast_char_constants::minus; + { + --start; + CharT const minus = lcast_char_constants::minus; + Traits::assign(*start, minus); + } return true; } - template - inline bool lexical_stream_limited_src::operator<<(long n) + template + inline bool lexical_stream_limited_src::operator<<( + long n) { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); if(n < 0) - *--start = lcast_char_constants::minus; + { + --start; + CharT const minus = lcast_char_constants::minus; + Traits::assign(*start, minus); + } return true; } #if defined(BOOST_HAS_LONG_LONG) - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( boost::long_long_type n) { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); if(n < 0) - *--start = lcast_char_constants::minus; + { + --start; + CharT const minus = lcast_char_constants::minus; + Traits::assign(*start, minus); + } return true; } #elif defined(BOOST_HAS_MS_INT64) - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( __int64 n) { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); if(n < 0) - *--start = lcast_char_constants::minus; + { + --start; + CharT const minus = lcast_char_constants::minus; + Traits::assign(*start, minus); + } return true; } #endif - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( unsigned short n) { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); return true; } - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( unsigned int n) { - start = lcast_put_unsigned(n, finish); + start = lcast_put_unsigned(n, finish); return true; } - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( unsigned long n) { - start = lcast_put_unsigned(n, finish); + start = lcast_put_unsigned(n, finish); return true; } #if defined(BOOST_HAS_LONG_LONG) - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( boost::ulong_long_type n) { - start = lcast_put_unsigned(n, finish); + start = lcast_put_unsigned(n, finish); return true; } #elif defined(BOOST_HAS_MS_INT64) - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( unsigned __int64 n) { - start = lcast_put_unsigned(n, finish); + start = lcast_put_unsigned(n, finish); return true; } #endif - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( float val) { return this->lcast_put(val); } - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( double val) { return this->lcast_put(val); } - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( long double val) { return this->lcast_put(val); } - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( CharT const* str) { start = const_cast(str); - finish = start + std::char_traits::length(str); + finish = start + Traits::length(str); return true; } - template - inline bool lexical_stream_limited_src::operator>>( + template + inline bool lexical_stream_limited_src::operator>>( CharT& output) { bool const ok = (finish - start == 1); if(ok) - output = *start; + Traits::assign(output, *start); return ok; } #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - inline bool lexical_stream_limited_src::operator>>( + template + inline bool lexical_stream_limited_src::operator>>( std::string& str) { str.assign(start, finish); @@ -899,8 +995,8 @@ namespace boost } #ifndef DISABLE_WIDE_CHAR_SUPPORT - template - inline bool lexical_stream_limited_src::operator>>( + template + inline bool lexical_stream_limited_src::operator>>( std::wstring& str) { str.assign(start, finish); @@ -1021,6 +1117,12 @@ namespace boost BOOST_DEDUCED_TYPENAME boost::call_traits::param_type arg, CharT* buf, std::size_t src_len) { +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + typedef BOOST_DEDUCED_TYPENAME + deduce_char_traits::type traits; +#else + typedef std::char_traits traits; +#endif typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< lcast_streambuf_for_target::value || lcast_streambuf_for_source::value @@ -1030,8 +1132,8 @@ namespace boost BOOST_DEDUCED_TYPENAME boost::mpl::if_c< Unlimited - , detail::lexical_stream - , detail::lexical_stream_limited_src + , detail::lexical_stream + , detail::lexical_stream_limited_src >::type interpreter(buf, buf + src_len); // The original form, reproduced below, is more elegant diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 6ba26a3..04478e0 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -24,6 +24,9 @@ #include #include +#include +#include + #if defined(BOOST_NO_STRINGSTREAM) || \ defined(BOOST_NO_STD_WSTRING) || \ defined(BOOST_NO_STD_LOCALE) @@ -35,6 +38,16 @@ #define LCAST_TEST_LONGLONG #endif +template +struct my_traits : std::char_traits +{ +}; + +template +struct my_allocator : std::allocator +{ +}; + // Test all 65536 values if true: bool const lcast_test_small_integral_types_completely = false; @@ -57,15 +70,21 @@ void test_conversion_from_wstring(); void test_conversion_to_wstring(); void test_bad_lexical_cast(); void test_no_whitespace_stripping(); -void test_conversion_from_short(); -void test_conversion_from_ushort(); -void test_conversion_from_int(); -void test_conversion_from_uint(); -void test_conversion_from_long(); -void test_conversion_from_ulong(); +void test_conversion_from_to_short(); +void test_conversion_from_to_ushort(); +void test_conversion_from_to_int(); +void test_conversion_from_to_uint(); +void test_conversion_from_to_long(); +void test_conversion_from_to_ulong(); #ifdef LCAST_TEST_LONGLONG -void test_conversion_from_longlong(); -void test_conversion_from_ulonglong(); +void test_conversion_from_to_longlong(); +void test_conversion_from_to_ulonglong(); +#endif +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +void test_traits(); +void test_wtraits(); +void test_allocator(); +void test_wallocator(); #endif unit_test::test_suite *init_unit_test_suite(int, char *[]) @@ -87,15 +106,21 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) #endif suite->add(BOOST_TEST_CASE(test_bad_lexical_cast)); suite->add(BOOST_TEST_CASE(test_no_whitespace_stripping)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_short)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_ushort)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_int)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_uint)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_ulong)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_long)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_short)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ushort)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_int)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uint)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulong)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_long)); #ifdef LCAST_TEST_LONGLONG - suite->add(BOOST_TEST_CASE(&test_conversion_from_longlong)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_ulonglong)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_longlong)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulonglong)); + #endif + #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + suite->add(BOOST_TEST_CASE(&test_traits)); + suite->add(BOOST_TEST_CASE(&test_wtraits)); + suite->add(BOOST_TEST_CASE(&test_allocator)); + suite->add(BOOST_TEST_CASE(&test_wallocator)); #endif return suite; @@ -129,10 +154,15 @@ void test_conversion_to_int() BOOST_CHECK_EQUAL(0, lexical_cast('0')); BOOST_CHECK_THROW(lexical_cast('A'), bad_lexical_cast); BOOST_CHECK_EQUAL(1, lexical_cast(1)); + BOOST_CHECK_EQUAL(1, lexical_cast(1.0)); + BOOST_CHECK_EQUAL( (std::numeric_limits::max)(), lexical_cast((std::numeric_limits::max)())); - BOOST_CHECK_EQUAL(1, lexical_cast(1.0)); + + BOOST_CHECK_EQUAL( + (std::numeric_limits::min)(), + lexical_cast((std::numeric_limits::min)())); BOOST_CHECK_THROW(lexical_cast(1.23), bad_lexical_cast); @@ -407,7 +437,7 @@ void test_conversion_from_integral_to_char(CharT zero) BOOST_CHECK_THROW(lexical_cast(static_cast(10)), bad_lexical_cast); - T t = std::numeric_limits::max(); + T t = (std::numeric_limits::max)(); BOOST_CHECK_THROW(lexical_cast(t), bad_lexical_cast); } @@ -427,10 +457,10 @@ void test_conversion_from_integral_to_integral() BOOST_CHECK(lexical_cast(t) == st); BOOST_CHECK(lexical_cast(t) == ut); - t = std::numeric_limits::max(); + t = (std::numeric_limits::max)(); BOOST_CHECK(lexical_cast(t) == t); - t = std::numeric_limits::min(); + t = (std::numeric_limits::min)(); BOOST_CHECK(lexical_cast(t) == t); } @@ -442,19 +472,20 @@ void test_conversion_from_integral_to_string(CharT) T t; - t = limits::min(); + t = (limits::min)(); BOOST_CHECK(lexical_cast(t) == to_str(t)); - t = limits::max(); + t = (limits::max)(); BOOST_CHECK(lexical_cast(t) == to_str(t)); if(limits::digits <= 16 && lcast_test_small_integral_types_completely) - for(t = 1 + limits::min(); t != limits::max(); ++t) + // min and max have already been tested. + for(t = 1 + (limits::min)(); t != (limits::max)(); ++t) BOOST_CHECK(lexical_cast(t) == to_str(t)); else { - T const min_val = limits::min(); - T const max_val = limits::max(); + T const min_val = (limits::min)(); + T const max_val = (limits::max)(); T const half_max_val = max_val / 2; T const cnt = lcast_integral_test_counter; // to supress warnings unsigned int const counter = cnt < half_max_val ? cnt : half_max_val; @@ -480,20 +511,75 @@ void test_conversion_from_integral_to_string(CharT) T ten_power = 100; for(int e = 2; e <= limits::digits10; ++e, ten_power *= 10) { - // I believe that (ten_power + 100) never overflows + // ten_power + 100 probably never overflows for(t = ten_power - 100; t != ten_power + 100; ++t) BOOST_CHECK(lexical_cast(t) == to_str(t)); } } } +template +void test_conversion_from_string_to_integral(CharT) +{ + typedef std::numeric_limits limits; + + T t; + + t = (limits::min)(); + BOOST_CHECK(lexical_cast(to_str(t)) == t); + + t = (limits::max)(); + BOOST_CHECK(lexical_cast(to_str(t)) == t); + + if(limits::digits <= 16 && lcast_test_small_integral_types_completely) + // min and max have already been tested. + for(t = 1 + (limits::min)(); t != (limits::max)(); ++t) + BOOST_CHECK(lexical_cast(to_str(t)) == t); + else + { + T const min_val = (limits::min)(); + T const max_val = (limits::max)(); + T const half_max_val = max_val / 2; + T const cnt = lcast_integral_test_counter; // to supress warnings + unsigned int const counter = cnt < half_max_val ? cnt : half_max_val; + + unsigned int i; + + // Test values around min: + t = min_val; + for(i = 0; i < counter; ++i, ++t) + BOOST_CHECK(lexical_cast(to_str(t)) == t); + + // Test values around max: + t = max_val; + for(i = 0; i < counter; ++i, --t) + BOOST_CHECK(lexical_cast(to_str(t)) == t); + + // Test values around zero: + if(limits::is_signed) + for(t = -counter; t < static_cast(counter); ++t) + BOOST_CHECK(lexical_cast(to_str(t)) == t); + + // Test values around 100, 1000, 10000, ... + T ten_power = 100; + for(int e = 2; e <= limits::digits10; ++e, ten_power *= 10) + { + // ten_power + 100 probably never overflows + for(t = ten_power - 100; t != ten_power + 100; ++t) + BOOST_CHECK(lexical_cast(to_str(t)) == t); + } + } +} + template -void test_conversion_from_integral_for_locale() +void test_conversion_from_to_integral_for_locale() { test_conversion_from_integral_to_integral(); test_conversion_from_integral_to_string('0'); + test_conversion_from_string_to_integral('0'); #if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) test_conversion_from_integral_to_string(L'0'); + test_conversion_from_string_to_integral(L'0'); #endif } @@ -504,7 +590,7 @@ struct restore_oldloc }; template -void test_conversion_from_integral() +void test_conversion_from_to_integral() { char const zero = '0'; signed char const szero = '0'; @@ -517,7 +603,7 @@ void test_conversion_from_integral() test_conversion_from_integral_to_char(wzero); #endif - // test_conversion_from_integral_for_locale + // test_conversion_from_to_integral_for_locale typedef std::numpunct numpunct; @@ -527,7 +613,7 @@ void test_conversion_from_integral() std::string grouping1 = BOOST_USE_FACET(numpunct, oldloc).grouping(); std::string grouping2(grouping1); - test_conversion_from_integral_for_locale(); + test_conversion_from_to_integral_for_locale(); try { @@ -544,64 +630,121 @@ void test_conversion_from_integral() } if(grouping1 != grouping2) - test_conversion_from_integral_for_locale(); + test_conversion_from_to_integral_for_locale(); if(grouping1.empty() && grouping2.empty()) BOOST_TEST_MESSAGE("Formatting with thousands_sep has not been tested"); } -void test_conversion_from_short() +void test_conversion_from_to_short() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } -void test_conversion_from_ushort() +void test_conversion_from_to_ushort() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } -void test_conversion_from_int() +void test_conversion_from_to_int() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } -void test_conversion_from_uint() +void test_conversion_from_to_uint() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } -void test_conversion_from_ulong() +void test_conversion_from_to_ulong() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } -void test_conversion_from_long() +void test_conversion_from_to_long() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } #if defined(BOOST_HAS_LONG_LONG) -void test_conversion_from_longlong() +void test_conversion_from_to_longlong() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } -void test_conversion_from_ulonglong() +void test_conversion_from_to_ulonglong() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } #elif defined(LCAST_TEST_LONGLONG) -void test_conversion_from_longlong() +void test_conversion_from_to_longlong() { - test_conversion_from_integral<__int64>(); + test_conversion_from_to_integral<__int64>(); } -void test_conversion_from_ulonglong() +void test_conversion_from_to_ulonglong() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); +} + +#endif + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +void test_traits() +{ + typedef std::basic_string > my_string; + + my_string const s("s"); + BOOST_CHECK(boost::lexical_cast(s) == s[0]); + BOOST_CHECK(boost::lexical_cast(s) == s); + BOOST_CHECK(boost::lexical_cast(-1) == "-1"); +} + +void test_wtraits() +{ + typedef std::basic_string > my_string; + + my_string const s(L"s"); + BOOST_CHECK(boost::lexical_cast(s) == s[0]); + BOOST_CHECK(boost::lexical_cast(s) == s); + //BOOST_CHECK(boost::lexical_cast(-1) == L"-1"); + // Commented out because gcc 3.3 doesn't support this: + // basic_ostream > o; o << -1; +} + +void test_allocator() +{ + typedef std::basic_string< char + , std::char_traits + , my_allocator + > my_string; + + my_string s("s"); + BOOST_CHECK(boost::lexical_cast(s) == s[0]); + BOOST_CHECK(boost::lexical_cast(s) == "s"); + BOOST_CHECK(boost::lexical_cast(s) == s); + BOOST_CHECK(boost::lexical_cast(1) == "1"); + BOOST_CHECK(boost::lexical_cast("s") == s); + BOOST_CHECK(boost::lexical_cast(std::string("s")) == s); +} + +void test_wallocator() +{ + typedef std::basic_string< wchar_t + , std::char_traits + , my_allocator + > my_string; + + my_string s(L"s"); + BOOST_CHECK(boost::lexical_cast(s) == s[0]); + BOOST_CHECK(boost::lexical_cast(s) == L"s"); + BOOST_CHECK(boost::lexical_cast(s) == s); + BOOST_CHECK(boost::lexical_cast(1) == L"1"); + BOOST_CHECK(boost::lexical_cast(L"s") == s); + BOOST_CHECK(boost::lexical_cast(std::wstring(L"s")) == s); } #endif From ec8665d1149e07c23acc95146a6c99888ad22a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20M=20L=C3=B3pez=20Mu=C3=B1oz?= Date: Mon, 26 Nov 2007 11:52:03 +0000 Subject: [PATCH 050/242] added missing traits template arg to a lexical_stream instantiation [SVN r41394] --- include/boost/lexical_cast.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 4f68452..cb2fa50 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1180,7 +1180,13 @@ namespace boost template Target lexical_cast(Source arg) { - detail::lexical_stream interpreter; + typedef typename detail::widest_char< + BOOST_DEDUCED_TYPENAME detail::stream_char::type + , BOOST_DEDUCED_TYPENAME detail::stream_char::type + >::type char_type; + + typedef std::char_traits traits; + detail::lexical_stream interpreter; Target result; if(!(interpreter << arg && interpreter >> result)) From 69cf3b2766a907906962079239a47d39a347c29f Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Mon, 26 Nov 2007 21:29:04 +0000 Subject: [PATCH 051/242] Remove redundant BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION. [SVN r41406] --- include/boost/lexical_cast.hpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index cb2fa50..2794c86 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1117,12 +1117,9 @@ namespace boost BOOST_DEDUCED_TYPENAME boost::call_traits::param_type arg, CharT* buf, std::size_t src_len) { -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef BOOST_DEDUCED_TYPENAME deduce_char_traits::type traits; -#else - typedef std::char_traits traits; -#endif + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< lcast_streambuf_for_target::value || lcast_streambuf_for_source::value From 808f210c0d396d9c209b4a98ada1eb2ae64973c5 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Tue, 4 Dec 2007 21:49:51 +0000 Subject: [PATCH 052/242] Link to html version of [Tuning] and BOOST_LEXICAL_CAST_ASSUME_C_LOCALE synopsis [SVN r41703] --- lexical_cast.htm | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lexical_cast.htm b/lexical_cast.htm index 2a08541..6e38014 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -194,7 +194,18 @@ public: Exception used to indicate runtime lexical_cast failure. -
      + +
      +

      BOOST_LEXICAL_CAST_ASSUME_C_LOCALE

      +
      #define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
      +
      +or,
      +
      +g++ -DBOOST_LEXICAL_CAST_ASSUME_C_LOCALE ...  (gcc on Linux/Unix)
      +cl.exe /DBOOST_LEXICAL_CAST_ASSUME_C_LOCALE ... (Visual C++ on Windows)
      +
      +Eliminate an overhead of std::locale if your program runs in the "C" locale. If the option is set but a program runs in other locale, lexical_cast result is unspecified. +

      Frequently Asked Questions

      Q: Why does lexical_cast<int8_t>("127") throw bad_lexical_cast? @@ -219,7 +230,7 @@ public:

    • [N1973] Kevlin Henney, Beman Dawes, Lexical Conversion Library Proposal for TR2, N1973.
    • [Tuning] Alexander Nasonov, Fine Tuning for lexical_cast, - Overload #74, + Overload #74 (PDF), August 2006.

    Changes

    From 408cbf0dcb435dc38dc808ca441a3995338103d3 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sat, 15 Dec 2007 14:26:16 +0000 Subject: [PATCH 053/242] Correct misspelling of library name [SVN r42069] --- include/boost/lexical_cast.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 2794c86..44c7a66 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -3,7 +3,7 @@ // Boost lexical_cast.hpp header -------------------------------------------// // -// See http://www.boost.org/libs/converston for documentation. +// See http://www.boost.org/libs/conversion for documentation. // See end of this header for rights and permissions. // // what: lexical_cast custom keyword cast From 0ad888867f00c42e5c7f47748c2f976fc0208f49 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 10 Feb 2008 14:56:22 +0000 Subject: [PATCH 054/242] Link to people pages on the website, as they've been removed from the download. [SVN r43209] --- cast.htm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cast.htm b/cast.htm index 587d08a..cb8add6 100644 --- a/cast.htm +++ b/cast.htm @@ -120,10 +120,10 @@ void f( Fruit * fruit ) {

    polymorphic_cast was suggested by Bjarne Stroustrup in "The C++ Programming Language".
    polymorphic_downcast was contributed by Dave Abrahams.
    + "http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams.
    An old numeric_cast
    that was contributed by Kevlin Henney is now superseeded by the Boost Numeric Conversion Library

    + "http://www.boost.org/people/kevlin_henney.htm">Kevlin Henney is now superseeded by the Boost Numeric Conversion Library


    Revised From e1dbc6ef04c042c42fb676a94ad88b046de29ef0 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Wed, 16 Apr 2008 21:13:25 +0000 Subject: [PATCH 055/242] Use make_unsigned and get rid of gcc warnings when -DBOOST_LEXICAL_CAST_ASSUME_C_LOCALE [SVN r44474] --- include/boost/lexical_cast.hpp | 58 +++++++++++----------------------- 1 file changed, 18 insertions(+), 40 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 44c7a66..a1276d6 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -461,36 +462,16 @@ namespace boost // C4146: unary minus operator applied to unsigned type, result still unsigned # pragma warning( disable : 4146 ) #endif - - inline unsigned int lcast_to_unsigned(int value) + template + inline + BOOST_DEDUCED_TYPENAME make_unsigned::type lcast_to_unsigned(T value) { - unsigned int uval = value; - return value < 0 ? -uval : uval; + typedef BOOST_DEDUCED_TYPENAME make_unsigned::type result_type; + result_type uvalue = static_cast(value); + return value < 0 ? -uvalue : uvalue; } - - inline unsigned long lcast_to_unsigned(long value) - { - unsigned long uval = value; - return value < 0 ? -uval : uval; - } - -#if defined(BOOST_HAS_LONG_LONG) - inline boost::ulong_long_type lcast_to_unsigned(boost::long_long_type v) - { - boost::ulong_long_type uval = v; - return v < 0 ? -uval : uval; - } -#elif defined(BOOST_HAS_MS_INT64) - inline unsigned __int64 lcast_to_unsigned(__int64 value) - { - unsigned __int64 uval = value; - return value < 0 ? -uval : uval; - } -#endif - #if (defined _MSC_VER) -# pragma warning( pop ) // C4146: unary minus operator applied to unsigned type, - // result still unsigned +# pragma warning( pop ) #endif } @@ -502,22 +483,14 @@ namespace boost #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS BOOST_STATIC_ASSERT(!std::numeric_limits::is_signed); #endif - CharT thousands_sep = 0; -#ifdef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - char const* grouping = ""; - std::size_t const grouping_size = 0; -#else +#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE std::locale loc; typedef std::numpunct numpunct; numpunct const& np = BOOST_USE_FACET(numpunct, loc); std::string const& grouping = np.grouping(); std::string::size_type const grouping_size = grouping.size(); - - if(grouping_size) - thousands_sep = np.thousands_sep(); -#endif - + CharT thousands_sep = grouping_size ? np.thousands_sep() : 0; std::string::size_type group = 0; // current group number char last_grp_size = grouping[0] <= 0 ? CHAR_MAX : grouping[0]; // a) Since grouping is const, grouping[grouping.size()] returns 0. @@ -526,14 +499,17 @@ namespace boost #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS BOOST_STATIC_ASSERT(std::numeric_limits::digits10 < CHAR_MAX); #endif + + char left = last_grp_size; +#endif + typedef typename Traits::int_type int_type; CharT const czero = lcast_char_constants::zero; int_type const zero = Traits::to_int_type(czero); - char left = last_grp_size; - do { +#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE if(left == 0) { ++group; @@ -549,6 +525,8 @@ namespace boost } --left; +#endif + --finish; int_type const digit = static_cast(n % 10U); Traits::assign(*finish, Traits::to_char_type(zero + digit)); @@ -907,7 +885,7 @@ namespace boost inline bool lexical_stream_limited_src::operator<<( unsigned short n) { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + start = lcast_put_unsigned(n, finish); return true; } From ae5cbbbec84bd81369b475a787473498ffce5a86 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Wed, 7 May 2008 19:43:55 +0000 Subject: [PATCH 056/242] Fixes #1847 Can't compile without header, boost::lexical_cast problem [SVN r45201] --- include/boost/lexical_cast.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index a1276d6..fc3f742 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -30,6 +29,10 @@ #include #include +#ifndef BOOST_NO_STD_LOCALE +#include +#endif + #ifdef BOOST_NO_STRINGSTREAM #include #else @@ -485,6 +488,7 @@ namespace boost #endif #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE + // TODO: use BOOST_NO_STD_LOCALE std::locale loc; typedef std::numpunct numpunct; numpunct const& np = BOOST_USE_FACET(numpunct, loc); @@ -651,6 +655,7 @@ namespace boost #ifndef DISABLE_WIDE_CHAR_SUPPORT static void widen_and_assign(wchar_t* p, char ch) { + // TODO: use BOOST_NO_STD_LOCALE std::locale loc; wchar_t w = BOOST_USE_FACET(std::ctype, loc).widen(ch); Traits::assign(*p, w); From 0d258ff7b15bb7a41667fa7fed4b4f4c9c0ccacb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 21 May 2008 21:13:22 +0000 Subject: [PATCH 057/242] Largely pointless Borland 5.5.1 changes. :-) [SVN r45627] --- include/boost/lexical_cast.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index fc3f742..9fddb70 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #ifndef BOOST_NO_STD_LOCALE #include @@ -49,6 +51,12 @@ namespace boost { // exception used to indicate runtime lexical_cast failure class bad_lexical_cast : public std::bad_cast + +#if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 ) + // under bcc32 5.5.1 bad_cast doesn't derive from exception + , public std::exception +#endif + { public: bad_lexical_cast() : From ae273a3e7b47845f3ce5d87038895fdd9265e574 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 6 Aug 2008 15:28:17 +0000 Subject: [PATCH 058/242] Fix link to numeric conversion library. [SVN r48003] --- cast.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cast.htm b/cast.htm index cb8add6..a1580c3 100644 --- a/cast.htm +++ b/cast.htm @@ -123,7 +123,7 @@ void f( Fruit * fruit ) { "http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams.
    An old numeric_cast
    that was contributed by Kevlin Henney is now superseeded by the Boost Numeric Conversion Library

    + "http://www.boost.org/people/kevlin_henney.htm">Kevlin Henney is now superseeded by the Boost Numeric Conversion Library


    Revised From 27088539710fe2ca663a4874ef7c2317835f053e Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 28 Sep 2008 12:21:39 +0000 Subject: [PATCH 059/242] Clean up some link errors. [SVN r48987] --- lexical_cast.htm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lexical_cast.htm b/lexical_cast.htm index 6e38014..4bbdc8e 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -81,7 +81,7 @@ conversions, such as where precision or formatting need tighter control than is offered by the default behavior of lexical_cast, the conventional stringstream approach is recommended. Where the conversions are - numeric to numeric, numeric_cast + numeric to numeric, numeric_cast may offer more reasonable behavior than lexical_cast.

    For a good discussion of the options and issues involved in string-based @@ -213,9 +213,9 @@ Eliminate an overhead of std::locale if your program runs in the "C Lexical conversion to these types is simply reading a byte from source but since the source has more than one byte, the exception is thrown.

    Please use other integer types such as int or short int. If bounds checking - is important, you can also call numeric_cast: + is important, you can also call numeric_cast: -

    numeric_cast<int8_t>(lexical_cast<int>("127"));
    +
    numeric_cast<int8_t>(lexical_cast<int>("127"));

    Q: What does lexical_cast<std::string> of an int8_t or uint8_t not do what I expect?
    A: As above, note that int8_t and uint8_t are actually chars and are formatted as such. To avoid this, cast to an integer type first: From 33981b94005f90b2c317f4b4d189c8d21fa20cd3 Mon Sep 17 00:00:00 2001 From: Nicola Musatti Date: Mon, 6 Oct 2008 20:22:10 +0000 Subject: [PATCH 060/242] Patch from Ticket #2370 [SVN r49154] --- include/boost/lexical_cast.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 9fddb70..e23b082 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -472,6 +472,8 @@ namespace boost # pragma warning( push ) // C4146: unary minus operator applied to unsigned type, result still unsigned # pragma warning( disable : 4146 ) +#elif defined( __BORLANDC__ ) +# pragma option push -w-8041 #endif template inline @@ -483,6 +485,8 @@ namespace boost } #if (defined _MSC_VER) # pragma warning( pop ) +#elif defined( __BORLANDC__ ) +# pragma option pop #endif } From 2296357eaf6fa17c2c6c140a16ee84fa121b7154 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Fri, 10 Oct 2008 22:56:08 +0000 Subject: [PATCH 061/242] Fix #2299 (Patch to fix warnings in lexical_cast) [SVN r49261] --- include/boost/lexical_cast.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index e23b082..a4bd5cf 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -698,9 +698,9 @@ namespace boost public: - lexical_stream_limited_src(CharT* start, CharT* finish) - : start(start) - , finish(finish) + lexical_stream_limited_src(CharT* sta, CharT* fin) + : start(sta) + , finish(fin) {} public: // output From 6c5fd3e86de982ca212c80b7a6d28e15eb41458c Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Fri, 10 Oct 2008 23:16:10 +0000 Subject: [PATCH 062/242] Fix #2184 (Macro without BOOST_ prefix) [SVN r49262] --- include/boost/lexical_cast.hpp | 75 +++++++++++++++++----------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index a4bd5cf..bc678fa 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -44,7 +44,7 @@ #if defined(BOOST_NO_STRINGSTREAM) || \ defined(BOOST_NO_STD_WSTRING) || \ defined(BOOST_NO_STD_LOCALE) -#define DISABLE_WIDE_CHAR_SUPPORT +#define BOOST_LCAST_NO_WCHAR_T #endif namespace boost @@ -106,7 +106,7 @@ namespace boost }; #endif -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef BOOST_LCAST_NO_WCHAR_T #ifndef BOOST_NO_INTRINSIC_WCHAR_T template<> struct stream_char @@ -231,7 +231,7 @@ namespace boost // lcast_src_length // lcast_src_length -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef BOOST_LCAST_NO_WCHAR_T template<> struct lcast_src_length { @@ -270,7 +270,7 @@ namespace boost static void check_coverage() {} }; -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef BOOST_LCAST_NO_WCHAR_T template<> struct lcast_src_length { @@ -301,7 +301,7 @@ namespace boost static void check_coverage() {} }; -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef BOOST_LCAST_NO_WCHAR_T template<> struct lcast_src_length< wchar_t, std::basic_string > { @@ -339,34 +339,35 @@ namespace boost #endif }; -#define BOOST_AUX_LEXICAL_CAST_DEF1(CharT, T) template<> \ - struct lcast_src_length : lcast_src_length_integral \ +#define BOOST_LCAST_DEF1(CharT, T) \ + template<> struct lcast_src_length \ + : lcast_src_length_integral \ { static void check_coverage() {} }; -#ifdef DISABLE_WIDE_CHAR_SUPPORT -#define BOOST_AUX_LEXICAL_CAST_DEF(T) BOOST_AUX_LEXICAL_CAST_DEF1(char, T) +#ifdef BOOST_LCAST_NO_WCHAR_T +#define BOOST_LCAST_DEF(T) BOOST_LCAST_DEF1(char, T) #else -#define BOOST_AUX_LEXICAL_CAST_DEF(T) \ - BOOST_AUX_LEXICAL_CAST_DEF1(char, T) \ - BOOST_AUX_LEXICAL_CAST_DEF1(wchar_t, T) +#define BOOST_LCAST_DEF(T) \ + BOOST_LCAST_DEF1(char, T) \ + BOOST_LCAST_DEF1(wchar_t, T) #endif - BOOST_AUX_LEXICAL_CAST_DEF(short) - BOOST_AUX_LEXICAL_CAST_DEF(unsigned short) - BOOST_AUX_LEXICAL_CAST_DEF(int) - BOOST_AUX_LEXICAL_CAST_DEF(unsigned int) - BOOST_AUX_LEXICAL_CAST_DEF(long) - BOOST_AUX_LEXICAL_CAST_DEF(unsigned long) + BOOST_LCAST_DEF(short) + BOOST_LCAST_DEF(unsigned short) + BOOST_LCAST_DEF(int) + BOOST_LCAST_DEF(unsigned int) + BOOST_LCAST_DEF(long) + BOOST_LCAST_DEF(unsigned long) #if defined(BOOST_HAS_LONG_LONG) - BOOST_AUX_LEXICAL_CAST_DEF(boost::ulong_long_type) - BOOST_AUX_LEXICAL_CAST_DEF(boost::long_long_type ) + BOOST_LCAST_DEF(boost::ulong_long_type) + BOOST_LCAST_DEF(boost::long_long_type ) #elif defined(BOOST_HAS_MS_INT64) - BOOST_AUX_LEXICAL_CAST_DEF(unsigned __int64) - BOOST_AUX_LEXICAL_CAST_DEF( __int64) + BOOST_LCAST_DEF(unsigned __int64) + BOOST_LCAST_DEF( __int64) #endif -#undef BOOST_AUX_LEXICAL_CAST_DEF -#undef BOOST_AUX_LEXICAL_CAST_DEF1 +#undef BOOST_LCAST_DEF +#undef BOOST_LCAST_DEF1 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION // Helper for floating point types. @@ -412,7 +413,7 @@ namespace boost static void check_coverage() {} }; -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef BOOST_LCAST_NO_WCHAR_T template<> struct lcast_src_length : lcast_src_length_floating @@ -434,7 +435,7 @@ namespace boost static void check_coverage() {} }; -#endif // #ifndef DISABLE_WIDE_CHAR_SUPPORT +#endif // #ifndef BOOST_LCAST_NO_WCHAR_T #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION } @@ -449,7 +450,7 @@ namespace boost BOOST_STATIC_CONSTANT(char, minus = '-'); }; -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef BOOST_LCAST_NO_WCHAR_T template<> struct lcast_char_constants { @@ -608,7 +609,7 @@ namespace boost stream.str().swap(output); return true; } - #ifndef DISABLE_WIDE_CHAR_SUPPORT + #ifndef BOOST_LCAST_NO_WCHAR_T bool operator>>(std::wstring &output) { stream.str().swap(output); @@ -664,7 +665,7 @@ namespace boost Traits::assign(*p, ch); } -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef BOOST_LCAST_NO_WCHAR_T static void widen_and_assign(wchar_t* p, char ch) { // TODO: use BOOST_NO_STD_LOCALE @@ -715,7 +716,7 @@ namespace boost bool operator<<(bool); bool operator<<(char); -#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) bool operator<<(wchar_t); #endif bool operator<<(CharT const*); @@ -780,7 +781,7 @@ namespace boost bool operator>>(std::string&); -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef BOOST_LCAST_NO_WCHAR_T bool operator>>(std::wstring&); #endif @@ -815,7 +816,7 @@ namespace boost return true; } -#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) template inline bool lexical_stream_limited_src::operator<<( wchar_t ch) @@ -989,7 +990,7 @@ namespace boost return true; } -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef BOOST_LCAST_NO_WCHAR_T template inline bool lexical_stream_limited_src::operator>>( std::wstring& str) @@ -1044,7 +1045,7 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = false); }; -#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) template<> struct lcast_streambuf_for_target { @@ -1060,7 +1061,7 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = false); }; -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef BOOST_LCAST_NO_WCHAR_T template struct lcast_streambuf_for_target< std::basic_string > @@ -1075,7 +1076,7 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = false); }; -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef BOOST_LCAST_NO_WCHAR_T template<> struct lcast_streambuf_for_target { @@ -1196,5 +1197,5 @@ namespace boost // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#undef DISABLE_WIDE_CHAR_SUPPORT +#undef BOOST_LCAST_NO_WCHAR_T #endif From 4217a354f5c48ac557c162716a82a5ac6aed553f Mon Sep 17 00:00:00 2001 From: "Michael A. Jackson" Date: Sat, 1 Nov 2008 13:15:41 +0000 Subject: [PATCH 063/242] Continuing merge of CMake build system files into trunk with the encouragement of Doug Gregor [SVN r49510] --- CMakeLists.txt | 22 ++++++++++++++++++++++ test/CMakeLists.txt | 12 ++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..9006501 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,22 @@ +#---------------------------------------------------------------------------- +# This file was automatically generated from the original CMakeLists.txt file +# Add a variable to hold the headers for the library +set (lib_headers + +) + +# Add a library target to the build system +boost_library_project( + conversion + # SRCDIRS + TESTDIRS test + # HEADERS ${lib_headers} + # DOCDIRS + DESCRIPTION "Polymorphic and lexical casts" + # MODULARIZED + AUTHORS "David Abrahams " + "Kevlin Henney" + # MAINTAINERS +) + + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..38fbbdd --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,12 @@ +boost_test_run(implicit_cast) +boost_test_compile_fail(implicit_cast_fail) +boost_test_run(cast_test ../cast_test.cpp) +boost_test_run(numeric_cast_test ../numeric_cast_test.cpp) +boost_test_run( + lexical_cast_test + ../lexical_cast_test.cpp + DEPENDS boost_unit_test_framework +) + + + From b72cb10ae69867e11b54b0767e30c580795f79b4 Mon Sep 17 00:00:00 2001 From: "Michael A. Jackson" Date: Fri, 7 Nov 2008 17:02:56 +0000 Subject: [PATCH 064/242] Updating CMake files to latest trunk. Added dependency information for regression tests and a few new macros for internal use. [SVN r49627] --- test/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 38fbbdd..11227a8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,3 +1,5 @@ +boost_additional_test_dependencies(conversion BOOST_DEPENDS test detail numeric) + boost_test_run(implicit_cast) boost_test_compile_fail(implicit_cast_fail) boost_test_run(cast_test ../cast_test.cpp) From 5fa1edeee08222e13c20e5e08401b7b1e9c523b9 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Thu, 4 Dec 2008 22:59:27 +0000 Subject: [PATCH 065/242] Fixes #1220: lexical_cast requires RTTI [SVN r50123] --- include/boost/lexical_cast.hpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index bc678fa..0da0d3d 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -60,15 +60,21 @@ namespace boost { public: bad_lexical_cast() : - source(&typeid(void)), target(&typeid(void)) +#ifndef BOOST_NO_TYPEID + source(&typeid(void)), target(&typeid(void)) +#else + source(0), target(0) // this breaks getters +#endif { } + bad_lexical_cast( const std::type_info &source_type_arg, const std::type_info &target_type_arg) : source(&source_type_arg), target(&target_type_arg) { } + const std::type_info &source_type() const { return *source; @@ -77,6 +83,7 @@ namespace boost { return *target; } + virtual const char *what() const throw() { return "bad lexical cast: " @@ -1144,7 +1151,11 @@ namespace boost if (interpreter >> result) return result; } +#ifndef BOOST_NO_TYPEID throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); +#else + throw_exception(bad_lexical_cast()); +#endif return Target(); // normally never reached (throw_exception) } } @@ -1183,7 +1194,11 @@ namespace boost Target result; if(!(interpreter << arg && interpreter >> result)) +#ifndef BOOST_NO_TYPEID throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); +#else + throw_exception(bad_lexical_cast()); +#endif return result; } From fa4a95c1dd75fd66f19050ce19e309e08afc1a84 Mon Sep 17 00:00:00 2001 From: Gennadiy Rozental Date: Sat, 6 Jun 2009 09:38:47 +0000 Subject: [PATCH 066/242] avoid C style casts [SVN r53668] --- include/boost/lexical_cast.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 0da0d3d..f5d2724 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -577,7 +577,7 @@ namespace boost lexical_stream(char_type* = 0, char_type* = 0) { stream.unsetf(std::ios::skipws); - lcast_set_precision(stream, (Source*)0, (Target*)0); + lcast_set_precision(stream, static_cast(0), static_cast(0) ); } ~lexical_stream() { @@ -694,7 +694,7 @@ namespace boost { this->setp(start, finish); std::basic_ostream stream(static_cast(this)); - lcast_set_precision(stream, (OutputStreamable*)0); + lcast_set_precision(stream, static_cast(0)); bool const result = !(stream << input).fail(); finish = this->pptr(); return result; @@ -764,7 +764,7 @@ namespace boost this->setg(start, start, finish); std::basic_istream stream(static_cast(this)); stream.unsetf(std::ios::skipws); - lcast_set_precision(stream, (InputStreamable*)0); + lcast_set_precision(stream, static_cast(0)); #if (defined _MSC_VER) # pragma warning( pop ) #endif From 7b37688ca88280e069513915641379cff09abb9c Mon Sep 17 00:00:00 2001 From: Gennadiy Rozental Date: Sat, 6 Jun 2009 09:41:03 +0000 Subject: [PATCH 067/242] avoid C style casts [SVN r53670] --- include/boost/detail/lcast_precision.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/detail/lcast_precision.hpp b/include/boost/detail/lcast_precision.hpp index d40ca21..93abce1 100644 --- a/include/boost/detail/lcast_precision.hpp +++ b/include/boost/detail/lcast_precision.hpp @@ -173,8 +173,8 @@ inline void lcast_set_precision(std::ios_base& stream, T*) template inline void lcast_set_precision(std::ios_base& stream, Source*, Target*) { - std::streamsize const s = lcast_get_precision((Source*)0); - std::streamsize const t = lcast_get_precision((Target*)0); + std::streamsize const s = lcast_get_precision(static_cast(0)); + std::streamsize const t = lcast_get_precision(static_cast(0)); stream.precision(s > t ? s : t); } From a77fc4c0bb57fc97548bb9596902a98931107e44 Mon Sep 17 00:00:00 2001 From: "Troy D. Straszheim" Date: Sun, 26 Jul 2009 00:49:56 +0000 Subject: [PATCH 068/242] Copyrights on CMakeLists.txt to keep them from clogging up the inspect reports. This is essentially the same commit as r55095 on the release branch. [SVN r55159] --- CMakeLists.txt | 6 ++++++ test/CMakeLists.txt | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9006501..3badd19 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,9 @@ +# +# Copyright Troy D. Straszheim +# +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt +# #---------------------------------------------------------------------------- # This file was automatically generated from the original CMakeLists.txt file # Add a variable to hold the headers for the library diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 11227a8..7b10f31 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,3 +1,9 @@ +# +# Copyright Troy D. Straszheim +# +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt +# boost_additional_test_dependencies(conversion BOOST_DEPENDS test detail numeric) boost_test_run(implicit_cast) From 8582e255718cef7020a1616b70991b9687818d77 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sat, 12 Sep 2009 21:47:27 +0000 Subject: [PATCH 069/242] Fix #1791 (fix warning on MSVC warning level 4) and undo r34801 (some "rewording" to avoid spurious level 4 warnings with VC7.1 and VC8). [SVN r56158] --- include/boost/lexical_cast.hpp | 41 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index f5d2724..094caec 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -47,6 +47,13 @@ #define BOOST_LCAST_NO_WCHAR_T #endif +#ifdef BOOST_NO_TYPEID +#define BOOST_LCAST_THROW_BAD_CAST(S, T) throw_exception(bad_lexical_cast()) +#else +#define BOOST_LCAST_THROW_BAD_CAST(Source, Target) \ + throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))) +#endif + namespace boost { // exception used to indicate runtime lexical_cast failure @@ -1111,6 +1118,12 @@ namespace boost typedef const T * type; }; +#if (defined _MSC_VER) +# pragma warning( push ) +# pragma warning( disable : 4701 ) // possible use of ... before initialization +# pragma warning( disable : 4702 ) // unreachable code +#endif + template< typename Target , typename Source , bool Unlimited // string representation of Source is unlimited @@ -1136,28 +1149,14 @@ namespace boost , detail::lexical_stream_limited_src >::type interpreter(buf, buf + src_len); - // The original form, reproduced below, is more elegant - // but yields a spurious C4701 warning ("possible use of - // "result" before initialization") with VC7.1 (/W4). -// -// Target result; -// -// if(!(interpreter << arg && interpreter >> result)) -// throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); -// return result; - - if(interpreter << arg) { - Target result; - if (interpreter >> result) - return result; - } -#ifndef BOOST_NO_TYPEID - throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); -#else - throw_exception(bad_lexical_cast()); -#endif - return Target(); // normally never reached (throw_exception) + Target result; + if(!(interpreter << arg && interpreter >> result)) + BOOST_LCAST_THROW_BAD_CAST(Source, Target); + return result; } +#if (defined _MSC_VER) +# pragma warning( pop ) +#endif } template From c22d67140994347bfd5ff2b569aa4fdc5f028106 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sat, 12 Sep 2009 22:22:28 +0000 Subject: [PATCH 070/242] Fix #1847 (Can't compile without header, boost::lexical_cast problem). [SVN r56160] --- include/boost/lexical_cast.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 094caec..d7d9052 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -41,9 +41,7 @@ #include #endif -#if defined(BOOST_NO_STRINGSTREAM) || \ - defined(BOOST_NO_STD_WSTRING) || \ - defined(BOOST_NO_STD_LOCALE) +#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) #define BOOST_LCAST_NO_WCHAR_T #endif From b37f56f4781298742cb67f606368411e64eea954 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sun, 13 Sep 2009 14:48:27 +0000 Subject: [PATCH 071/242] Fix #2295 (Inconsistent behavior when using 64 bit integer types). [SVN r56170] --- lexical_cast_test.cpp | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 04478e0..4d3a9fe 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -21,6 +21,7 @@ #include +#include #include #include @@ -76,6 +77,7 @@ void test_conversion_from_to_int(); void test_conversion_from_to_uint(); void test_conversion_from_to_long(); void test_conversion_from_to_ulong(); +void test_conversion_from_to_intmax_t(); #ifdef LCAST_TEST_LONGLONG void test_conversion_from_to_longlong(); void test_conversion_from_to_ulonglong(); @@ -112,6 +114,7 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uint)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulong)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_long)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_intmax_t)); #ifdef LCAST_TEST_LONGLONG suite->add(BOOST_TEST_CASE(&test_conversion_from_to_longlong)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulonglong)); @@ -522,27 +525,38 @@ template void test_conversion_from_string_to_integral(CharT) { typedef std::numeric_limits limits; + typedef std::basic_string string_type; - T t; + string_type s; + string_type const zero = to_str(0); + string_type const nine = to_str(9); + T const min_val = (limits::min)(); + T const max_val = (limits::max)(); - t = (limits::min)(); - BOOST_CHECK(lexical_cast(to_str(t)) == t); + s = to_str(min_val); + BOOST_CHECK_EQUAL(lexical_cast(s), min_val); + if(limits::is_signed) + { + BOOST_CHECK_THROW(lexical_cast(s + zero), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(s + nine), bad_lexical_cast); + } - t = (limits::max)(); - BOOST_CHECK(lexical_cast(to_str(t)) == t); + s = to_str(max_val); + BOOST_CHECK_EQUAL(lexical_cast(s), max_val); + BOOST_CHECK_THROW(lexical_cast(s + zero), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(s + nine), bad_lexical_cast); if(limits::digits <= 16 && lcast_test_small_integral_types_completely) // min and max have already been tested. - for(t = 1 + (limits::min)(); t != (limits::max)(); ++t) + for(T t = 1 + min_val; t != max_val; ++t) BOOST_CHECK(lexical_cast(to_str(t)) == t); else { - T const min_val = (limits::min)(); - T const max_val = (limits::max)(); T const half_max_val = max_val / 2; T const cnt = lcast_integral_test_counter; // to supress warnings unsigned int const counter = cnt < half_max_val ? cnt : half_max_val; + T t; unsigned int i; // Test values around min: @@ -666,6 +680,11 @@ void test_conversion_from_to_long() test_conversion_from_to_integral(); } +void test_conversion_from_to_intmax_t() +{ + test_conversion_from_to_integral(); +} + #if defined(BOOST_HAS_LONG_LONG) void test_conversion_from_to_longlong() From 0aaa89042adf2fba6114494f9d84b3e817c9fcdf Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sun, 13 Sep 2009 14:58:34 +0000 Subject: [PATCH 072/242] Add a test for uintmax_t. [SVN r56171] --- lexical_cast_test.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 4d3a9fe..44b9b5f 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -78,6 +78,7 @@ void test_conversion_from_to_uint(); void test_conversion_from_to_long(); void test_conversion_from_to_ulong(); void test_conversion_from_to_intmax_t(); +void test_conversion_from_to_uintmax_t(); #ifdef LCAST_TEST_LONGLONG void test_conversion_from_to_longlong(); void test_conversion_from_to_ulonglong(); @@ -112,9 +113,10 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ushort)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_int)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uint)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulong)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_long)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulong)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_intmax_t)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uintmax_t)); #ifdef LCAST_TEST_LONGLONG suite->add(BOOST_TEST_CASE(&test_conversion_from_to_longlong)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulonglong)); @@ -670,21 +672,26 @@ void test_conversion_from_to_uint() test_conversion_from_to_integral(); } -void test_conversion_from_to_ulong() -{ - test_conversion_from_to_integral(); -} - void test_conversion_from_to_long() { test_conversion_from_to_integral(); } +void test_conversion_from_to_ulong() +{ + test_conversion_from_to_integral(); +} + void test_conversion_from_to_intmax_t() { test_conversion_from_to_integral(); } +void test_conversion_from_to_uintmax_t() +{ + test_conversion_from_to_integral(); +} + #if defined(BOOST_HAS_LONG_LONG) void test_conversion_from_to_longlong() From 78adbeaab1f048387e1d8ce6d434f6acb7dd7e24 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Tue, 15 Sep 2009 22:55:02 +0000 Subject: [PATCH 073/242] DISABLE_WIDE_CHAR_SUPPORT -> BOOST_LCAST_NO_WCHAR_T. [SVN r56228] --- lexical_cast_test.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 44b9b5f..81faa5c 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -28,12 +28,6 @@ #include #include -#if defined(BOOST_NO_STRINGSTREAM) || \ - defined(BOOST_NO_STD_WSTRING) || \ - defined(BOOST_NO_STD_LOCALE) -#define DISABLE_WIDE_CHAR_SUPPORT -#endif - #if (defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)) \ && !(defined(BOOST_MSVC) && BOOST_MSVC < 1300) #define LCAST_TEST_LONGLONG @@ -101,7 +95,7 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) suite->add(BOOST_TEST_CASE(test_conversion_from_to_wchar_t_alias)); suite->add(BOOST_TEST_CASE(test_conversion_to_pointer)); suite->add(BOOST_TEST_CASE(test_conversion_to_string)); - #ifndef DISABLE_WIDE_CHAR_SUPPORT + #ifndef BOOST_LCAST_NO_WCHAR_T suite->add(BOOST_TEST_CASE(test_conversion_from_wchar_t)); suite->add(BOOST_TEST_CASE(test_conversion_to_wchar_t)); suite->add(BOOST_TEST_CASE(test_conversion_from_wstring)); @@ -268,14 +262,14 @@ void test_conversion_from_to_wchar_t_alias() void test_conversion_to_pointer() { BOOST_CHECK_THROW(lexical_cast("Test"), bad_lexical_cast); - #ifndef DISABLE_WIDE_CHAR_SUPPORT + #ifndef BOOST_LCAST_NO_WCHAR_T BOOST_CHECK_THROW(lexical_cast("Test"), bad_lexical_cast); #endif } void test_conversion_from_wchar_t() { -#ifndef DISABLE_WIDE_CHAR_SUPPORT +#ifndef BOOST_LCAST_NO_WCHAR_T #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) BOOST_CHECK_EQUAL(1, lexical_cast(L'1')); BOOST_CHECK_THROW(lexical_cast(L'A'), bad_lexical_cast); @@ -308,7 +302,7 @@ void test_conversion_from_wchar_t() void test_conversion_to_wchar_t() { -#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) BOOST_CHECK_EQUAL(L'1', lexical_cast(1)); BOOST_CHECK_EQUAL(L'0', lexical_cast(0)); BOOST_CHECK_EQUAL(L'1', lexical_cast('1')); @@ -335,7 +329,7 @@ void test_conversion_to_wchar_t() void test_conversion_from_wstring() { - #ifndef DISABLE_WIDE_CHAR_SUPPORT + #ifndef BOOST_LCAST_NO_WCHAR_T BOOST_CHECK_EQUAL(123, lexical_cast(std::wstring(L"123"))); BOOST_CHECK_THROW( lexical_cast(std::wstring(L"")), bad_lexical_cast); @@ -353,7 +347,7 @@ void test_conversion_from_wstring() void test_conversion_to_wstring() { - #ifndef DISABLE_WIDE_CHAR_SUPPORT + #ifndef BOOST_LCAST_NO_WCHAR_T wchar_t buf[] = L"hello"; wchar_t* str = buf; BOOST_CHECK(str == lexical_cast(str)); @@ -593,7 +587,7 @@ void test_conversion_from_to_integral_for_locale() test_conversion_from_integral_to_integral(); test_conversion_from_integral_to_string('0'); test_conversion_from_string_to_integral('0'); -#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) test_conversion_from_integral_to_string(L'0'); test_conversion_from_string_to_integral(L'0'); #endif @@ -614,7 +608,7 @@ void test_conversion_from_to_integral() test_conversion_from_integral_to_char(zero); test_conversion_from_integral_to_char(szero); test_conversion_from_integral_to_char(uzero); -#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) wchar_t const wzero = L'0'; test_conversion_from_integral_to_char(wzero); #endif From 79a141ce9d68c71ff424be2caaba276de8c4a643 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Tue, 15 Sep 2009 23:38:21 +0000 Subject: [PATCH 074/242] Add new test libs/conversion/test/lexical_cast_vc8_bug_test.cpp. [SVN r56229] --- lexical_cast_test.cpp | 20 ++++++++--- test/Jamfile.v2 | 1 + test/lexical_cast_vc8_bug_test.cpp | 53 ++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 test/lexical_cast_vc8_bug_test.cpp diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 81faa5c..b61db0d 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -533,14 +533,26 @@ void test_conversion_from_string_to_integral(CharT) BOOST_CHECK_EQUAL(lexical_cast(s), min_val); if(limits::is_signed) { - BOOST_CHECK_THROW(lexical_cast(s + zero), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(s + nine), bad_lexical_cast); +#if defined(BOOST_MSVC) && BOOST_MSVC == 1400 + // VC++ 8.0 bug, see libs/conversion/test/lexical_cast_vc8_bug_test.cpp + if(sizeof(T) < sizeof(boost::intmax_t)) +#endif + { + BOOST_CHECK_THROW(lexical_cast(s + zero), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(s + nine), bad_lexical_cast); + } } s = to_str(max_val); BOOST_CHECK_EQUAL(lexical_cast(s), max_val); - BOOST_CHECK_THROW(lexical_cast(s + zero), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(s + nine), bad_lexical_cast); +#if defined(BOOST_MSVC) && BOOST_MSVC == 1400 + // VC++ 8.0 bug, see libs/conversion/test/lexical_cast_vc8_bug_test.cpp + if(sizeof(T) != sizeof(boost::intmax_t)) +#endif + { + BOOST_CHECK_THROW(lexical_cast(s + zero), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(s + nine), bad_lexical_cast); + } if(limits::digits <= 16 && lcast_test_small_integral_types_completely) // min and max have already been tested. diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index af68510..1fea2fb 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -24,6 +24,7 @@ test-suite conversion [ run lexical_cast_loopback_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_abstract_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_noncopyable_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run lexical_cast_vc8_bug_test.cpp ../../test/build//boost_unit_test_framework/static ] ; diff --git a/test/lexical_cast_vc8_bug_test.cpp b/test/lexical_cast_vc8_bug_test.cpp new file mode 100644 index 0000000..843bea8 --- /dev/null +++ b/test/lexical_cast_vc8_bug_test.cpp @@ -0,0 +1,53 @@ +#include +#include +#include +#include + +#include + +using namespace boost; + +// See also test_conversion_from_string_to_integral(CharT) +// in libs/conversion/lexical_cast_test.cpp +template +void test_too_long_number(CharT zero) +{ + typedef std::numeric_limits limits; + + std::basic_string s; + + std::basic_ostringstream o; + o << (limits::max)() << zero; + s = o.str(); + BOOST_CHECK_THROW(lexical_cast(s), bad_lexical_cast); + s[s.size()-1] += 9; // '0' -> '9' + BOOST_CHECK_THROW(lexical_cast(s), bad_lexical_cast); + + if(limits::is_signed) + { + std::basic_ostringstream o; + o << (limits::min)() << zero; + s = o.str(); + BOOST_CHECK_THROW(lexical_cast(s), bad_lexical_cast); + s[s.size()-1] += 9; // '0' -> '9' + BOOST_CHECK_THROW(lexical_cast(s), bad_lexical_cast); + } +} + +void test_vc8_bug() +{ + test_too_long_number('0'); + test_too_long_number('0'); +#if !defined(BOOST_LCAST_NO_WCHAR_T) + test_too_long_number(L'0'); + test_too_long_number(L'0'); +#endif +} + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test_framework::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast vc8 bug unit test"); + suite->add(BOOST_TEST_CASE(test_vc8_bug)); + return suite; +} From f5d825e77f3f6f02f3da9f78a5e4ec7614afd12f Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Tue, 15 Sep 2009 23:56:39 +0000 Subject: [PATCH 075/242] Decrease indent of #if and #endif lines and test string<->integral conversons when BOOST_NO_INTRINSIC_WCHAR_T is defined. [SVN r56232] --- lexical_cast_test.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index b61db0d..12e9deb 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -95,12 +95,12 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) suite->add(BOOST_TEST_CASE(test_conversion_from_to_wchar_t_alias)); suite->add(BOOST_TEST_CASE(test_conversion_to_pointer)); suite->add(BOOST_TEST_CASE(test_conversion_to_string)); - #ifndef BOOST_LCAST_NO_WCHAR_T +#ifndef BOOST_LCAST_NO_WCHAR_T suite->add(BOOST_TEST_CASE(test_conversion_from_wchar_t)); suite->add(BOOST_TEST_CASE(test_conversion_to_wchar_t)); suite->add(BOOST_TEST_CASE(test_conversion_from_wstring)); suite->add(BOOST_TEST_CASE(test_conversion_to_wstring)); - #endif +#endif suite->add(BOOST_TEST_CASE(test_bad_lexical_cast)); suite->add(BOOST_TEST_CASE(test_no_whitespace_stripping)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_short)); @@ -111,16 +111,16 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulong)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_intmax_t)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uintmax_t)); - #ifdef LCAST_TEST_LONGLONG +#ifdef LCAST_TEST_LONGLONG suite->add(BOOST_TEST_CASE(&test_conversion_from_to_longlong)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulonglong)); - #endif - #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +#endif +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION suite->add(BOOST_TEST_CASE(&test_traits)); suite->add(BOOST_TEST_CASE(&test_wtraits)); suite->add(BOOST_TEST_CASE(&test_allocator)); suite->add(BOOST_TEST_CASE(&test_wallocator)); - #endif +#endif return suite; } @@ -262,9 +262,9 @@ void test_conversion_from_to_wchar_t_alias() void test_conversion_to_pointer() { BOOST_CHECK_THROW(lexical_cast("Test"), bad_lexical_cast); - #ifndef BOOST_LCAST_NO_WCHAR_T +#ifndef BOOST_LCAST_NO_WCHAR_T BOOST_CHECK_THROW(lexical_cast("Test"), bad_lexical_cast); - #endif +#endif } void test_conversion_from_wchar_t() @@ -324,12 +324,12 @@ void test_conversion_to_wchar_t() lexical_cast(std::wstring(L"")), bad_lexical_cast); BOOST_CHECK_THROW( lexical_cast(std::wstring(L"Test")), bad_lexical_cast); - #endif +#endif } void test_conversion_from_wstring() { - #ifndef BOOST_LCAST_NO_WCHAR_T +#ifndef BOOST_LCAST_NO_WCHAR_T BOOST_CHECK_EQUAL(123, lexical_cast(std::wstring(L"123"))); BOOST_CHECK_THROW( lexical_cast(std::wstring(L"")), bad_lexical_cast); @@ -342,12 +342,12 @@ void test_conversion_from_wstring() lexical_cast(std::wstring(L"")), bad_lexical_cast); BOOST_CHECK_THROW( lexical_cast(std::wstring(L"Test")), bad_lexical_cast); - #endif +#endif } void test_conversion_to_wstring() { - #ifndef BOOST_LCAST_NO_WCHAR_T +#ifndef BOOST_LCAST_NO_WCHAR_T wchar_t buf[] = L"hello"; wchar_t* str = buf; BOOST_CHECK(str == lexical_cast(str)); @@ -367,7 +367,7 @@ void test_conversion_to_wstring() BOOST_CHECK(L"Test" == lexical_cast(std::wstring(L"Test"))); BOOST_CHECK(L" " == lexical_cast(std::wstring(L" "))); BOOST_CHECK(L"" == lexical_cast(std::wstring(L""))); - #endif +#endif } void test_bad_lexical_cast() @@ -599,7 +599,7 @@ void test_conversion_from_to_integral_for_locale() test_conversion_from_integral_to_integral(); test_conversion_from_integral_to_string('0'); test_conversion_from_string_to_integral('0'); -#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) +#if !defined(BOOST_LCAST_NO_WCHAR_T) test_conversion_from_integral_to_string(L'0'); test_conversion_from_string_to_integral(L'0'); #endif From febafb7cb885254b34c2d15875f8756521afaee0 Mon Sep 17 00:00:00 2001 From: "Troy D. Straszheim" Date: Sat, 17 Oct 2009 02:07:38 +0000 Subject: [PATCH 076/242] rm cmake from trunk. I'm not entirely sure this is necessary to satisfy the inspect script, but I'm not taking any chances, and it is easy to put back [SVN r56942] --- CMakeLists.txt | 28 ---------------------------- test/CMakeLists.txt | 20 -------------------- 2 files changed, 48 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 3badd19..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright Troy D. Straszheim -# -# Distributed under the Boost Software License, Version 1.0. -# See http://www.boost.org/LICENSE_1_0.txt -# -#---------------------------------------------------------------------------- -# This file was automatically generated from the original CMakeLists.txt file -# Add a variable to hold the headers for the library -set (lib_headers - -) - -# Add a library target to the build system -boost_library_project( - conversion - # SRCDIRS - TESTDIRS test - # HEADERS ${lib_headers} - # DOCDIRS - DESCRIPTION "Polymorphic and lexical casts" - # MODULARIZED - AUTHORS "David Abrahams " - "Kevlin Henney" - # MAINTAINERS -) - - diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt deleted file mode 100644 index 7b10f31..0000000 --- a/test/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# -# Copyright Troy D. Straszheim -# -# Distributed under the Boost Software License, Version 1.0. -# See http://www.boost.org/LICENSE_1_0.txt -# -boost_additional_test_dependencies(conversion BOOST_DEPENDS test detail numeric) - -boost_test_run(implicit_cast) -boost_test_compile_fail(implicit_cast_fail) -boost_test_run(cast_test ../cast_test.cpp) -boost_test_run(numeric_cast_test ../numeric_cast_test.cpp) -boost_test_run( - lexical_cast_test - ../lexical_cast_test.cpp - DEPENDS boost_unit_test_framework -) - - - From fce9ad4e1b45aa3dc9490de5d9e8ef6a9a0ac3f3 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Mon, 9 Nov 2009 12:27:54 +0000 Subject: [PATCH 077/242] Misc small fixes to suppress warnings. Code should now be clean with msvc /W4 and gcc /Wall /Wextra -pedantic with the exception of one deliberate warning in one test. [SVN r57510] --- lexical_cast_test.cpp | 7 +++++++ numeric_cast_test.cpp | 2 +- test/implicit_cast.cpp | 6 ++++++ test/implicit_cast_fail.cpp | 2 ++ test/lexical_cast_abstract_test.cpp | 2 +- 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 12e9deb..a994d13 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -11,6 +11,13 @@ // // Note: The unit test no longer compile on MSVC 6, but lexical_cast itself works for it. +// +// We need this #define before any #includes: otherwise msvc will emit warnings +// deep within std::string, resulting from our (perfectly legal) use of basic_string +// with a custom traits class: +// +#define _SCL_SECURE_NO_WARNINGS + #include #if defined(__INTEL_COMPILER) diff --git a/numeric_cast_test.cpp b/numeric_cast_test.cpp index 0b5bcde..51393b9 100644 --- a/numeric_cast_test.cpp +++ b/numeric_cast_test.cpp @@ -28,7 +28,7 @@ using namespace boost; using std::cout; -int test_main( int argc, char * argv[] ) +int test_main( int , char * [] ) { # ifdef NDEBUG diff --git a/test/implicit_cast.cpp b/test/implicit_cast.cpp index e18e17a..8c3bc52 100644 --- a/test/implicit_cast.cpp +++ b/test/implicit_cast.cpp @@ -28,5 +28,11 @@ int main() type f = check_return(boost::implicit_cast("hello")); type z = check_return(boost::implicit_cast(foo("hello"))); + + // warning supression: + (void)x; + (void)f; + (void)z; + return boost::report_errors(); } diff --git a/test/implicit_cast_fail.cpp b/test/implicit_cast_fail.cpp index 80143da..a7867a1 100644 --- a/test/implicit_cast_fail.cpp +++ b/test/implicit_cast_fail.cpp @@ -19,4 +19,6 @@ struct foo int test_main(int, char*[]) { foo x = implicit_cast("foobar"); + (void)x; // warning suppression. + return 0; } diff --git a/test/lexical_cast_abstract_test.cpp b/test/lexical_cast_abstract_test.cpp index 207d3a5..4b92e49 100644 --- a/test/lexical_cast_abstract_test.cpp +++ b/test/lexical_cast_abstract_test.cpp @@ -51,7 +51,7 @@ std::ostream &operator<<(std::ostream &O, const A &a) { a.out(O); return O; -}; +} void test_abstract() { From 5c1dc5388c92353de3c949499ebf2ab12d0b20b2 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sat, 13 Feb 2010 01:24:34 +0000 Subject: [PATCH 078/242] Use BOOST_LCAST_THROW_BAD_CAST consistently. [SVN r59664] --- include/boost/lexical_cast.hpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index d7d9052..91f6ec4 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1149,7 +1149,7 @@ namespace boost Target result; if(!(interpreter << arg && interpreter >> result)) - BOOST_LCAST_THROW_BAD_CAST(Source, Target); + BOOST_LCAST_THROW_BAD_CAST(Source, Target); return result; } #if (defined _MSC_VER) @@ -1191,11 +1191,7 @@ namespace boost Target result; if(!(interpreter << arg && interpreter >> result)) -#ifndef BOOST_NO_TYPEID - throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); -#else - throw_exception(bad_lexical_cast()); -#endif + BOOST_LCAST_THROW_BAD_CAST(Source, Target); return result; } From 2cfa78ab4070bf806fae6f35788654b8e5a2fb39 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Mon, 7 Jun 2010 22:58:42 +0000 Subject: [PATCH 079/242] Apply the patch from #4119. Fixes #4119. [SVN r62529] --- include/boost/lexical_cast.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 91f6ec4..aab5bb9 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -55,7 +55,13 @@ namespace boost { // exception used to indicate runtime lexical_cast failure - class bad_lexical_cast : public std::bad_cast + class bad_lexical_cast : + // workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0 +#if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS + public std::exception +#else + public std::bad_cast +#endif #if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 ) // under bcc32 5.5.1 bad_cast doesn't derive from exception From 00b609b498c12ebbfa4789ddcde7d741abee3d33 Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Fri, 11 Jun 2010 16:12:39 +0000 Subject: [PATCH 080/242] Supress MSVC /Wp64 warnings. Fixes #4184 [SVN r62806] --- include/boost/lexical_cast.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index aab5bb9..f3f42bb 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1126,6 +1126,7 @@ namespace boost # pragma warning( push ) # pragma warning( disable : 4701 ) // possible use of ... before initialization # pragma warning( disable : 4702 ) // unreachable code +# pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int' #endif template< typename Target From c28efea0b3dba58b100e41bec54a4ca005a81306 Mon Sep 17 00:00:00 2001 From: Alexander Nasonov Date: Sun, 5 Sep 2010 00:02:25 +0000 Subject: [PATCH 081/242] Fix an access to grouping[grouping.size()]. AFAIK, this is valid for const strings but STLport (when _STLP_DEBUG is defined) doesn't like it. The problem reported by Bogdan Dragu. [SVN r65279] --- include/boost/lexical_cast.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index f3f42bb..fdc5898 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -527,11 +527,10 @@ namespace boost std::string::size_type const grouping_size = grouping.size(); CharT thousands_sep = grouping_size ? np.thousands_sep() : 0; std::string::size_type group = 0; // current group number - char last_grp_size = grouping[0] <= 0 ? CHAR_MAX : grouping[0]; - // a) Since grouping is const, grouping[grouping.size()] returns 0. - // b) It's safe to assume here and below that CHAR_MAX - // is equivalent to unlimited grouping: + char last_grp_size = + grouping_size == 0 || grouping[0] <= 0 ? CHAR_MAX : grouping[0]; #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + // Check that ulimited group is unreachable: BOOST_STATIC_ASSERT(std::numeric_limits::digits10 < CHAR_MAX); #endif From e41ef929d2f48b705b246883a4430140cdcd02f3 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 12 May 2011 17:21:07 +0000 Subject: [PATCH 082/242] FIx #5536 [SVN r71901] --- lexical_cast.htm | 70 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/lexical_cast.htm b/lexical_cast.htm index 4bbdc8e..efc7219 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -196,38 +196,60 @@ public: failure.


    + + -

    Frequently Asked Questions

    -

    Q: Why does lexical_cast<int8_t>("127") throw bad_lexical_cast? -
    A: The type int8_t is a typedef to char or signed char. +

    Frequently Asked Questions

    + + + + + + + + + + + + + + + + + + + + + + + + +
    Question:Why does lexical_cast<int8_t>("127") throw bad_lexical_cast?
    Answer:The type int8_t is a typedef to char or signed char. Lexical conversion to these types is simply reading a byte from source but since the source has more than one byte, the exception is thrown. -

    Please use other integer types such as int or short int. If bounds checking + Please use other integer types such as int or short int. If bounds checking is important, you can also call numeric_cast: -

    numeric_cast<int8_t>(lexical_cast<int>("127"));
    +
    Question:What does lexical_cast<std::string> of an int8_t or uint8_t not do what I expect?
    Answer:As above, note that int8_t and uint8_t are actually chars and are formatted as such. To avoid this, cast to an integer type first: +
    lexical_cast<std::string>(static_cast<int>(n));
    +
    Question:The implementation always resets the ios_base::skipws flag of an underlying stream object. It breaks my operator>> that works only in presence of this flag. Can you remove code that resets the flag?
    Answer:May be in a future version. There is no requirement in [N1973] to reset the flag but remember that [N1973] is not yet accepted by the committee. By the way, it's a great opportunity to make your operator>> conform to the standard. Read a good C++ book, study std::sentry and ios_state_saver. +
    -

    Q: What does lexical_cast<std::string> of an int8_t or uint8_t not do what I expect? -
    A: As above, note that int8_t and uint8_t are actually chars and are formatted as such. To avoid this, cast to an integer type first: - -

    lexical_cast<std::string>(static_cast<int>(n));
    - -

    Q: The implementation always resets the ios_base::skipws flag of an underlying stream object. It breaks my operator>> that works only in presence of this flag. Can you remove code that resets the flag? -
    A: May be in a future version. There is no requirement in [N1973] to reset the flag but remember that [N1973] is not yet accepted by the committee. By the way, it's a great opportunity to make your operator>> conform to the standard. Read a good C++ book, study std::sentry and ios_state_saver. - -

    References

    +

    References

      -
    • [N1973] Kevlin Henney, Beman Dawes, Lexical Conversion Library Proposal for TR2, +
    • [N1973] Kevlin Henney, Beman Dawes, Lexical Conversion Library Proposal for TR2, N1973.
    • [Tuning] Alexander Nasonov, Fine Tuning for lexical_cast, Overload #74 (PDF), @@ -276,6 +298,12 @@ Eliminate an overhead of std::locale if your program runs in the "C


      -
      © Copyright Kevlin Henney, 2000–2005
      +
      Copyright © Kevlin Henney, 2000-2005
      +
      Copyright © Alexander Nasonov, 2006-2010
      +
      Copyright © Antony Polukhin, 2011
      +
      + 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) +
      From 266ebbcb882b0399e29147112944ad58b02d8a76 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 13 May 2011 17:31:16 +0000 Subject: [PATCH 083/242] Added documentation on the feature, described in ticket. Fixed 5494 [SVN r71922] --- lexical_cast.htm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lexical_cast.htm b/lexical_cast.htm index efc7219..5457a33 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -245,6 +245,15 @@ Eliminate an overhead of std::locale if your program runs in the "C May be in a future version. There is no requirement in [N1973] to reset the flag but remember that [N1973] is not yet accepted by the committee. By the way, it's a great opportunity to make your operator>> conform to the standard. Read a good C++ book, study std::sentry and ios_state_saver. + + Question: + Why std::cout << boost::lexical_cast<unsigned int>("-1"); does not throw, but outputs 4294967295? + + + Answer: + boost::lexical_cast has the behavior of stringstream, which uses num_get functions of std::locale to convert numbers. If we look at the [22.2.2.1.2] of Programming languages — C++, we'll see, that num_get uses the rules of scanf for conversions. And in the C99 standard for unsigned input value minus sign is optional, so if a negative number is read, no errors will arise and the result will be the two's complement. + +

      References

      From 95360b5df6959f691eefa12c0b6c84471e73b24c Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 15 May 2011 15:31:01 +0000 Subject: [PATCH 084/242] Fixes #5417. Fixes #4397 More tests (for conversions to float types, for conversions of negative values to unsigned integers) [SVN r71958] --- include/boost/lexical_cast.hpp | 282 +++++++++++++++++++++++++++++++-- lexical_cast.htm | 5 + lexical_cast_test.cpp | 83 +++++++++- 3 files changed, 356 insertions(+), 14 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index fdc5898..7a4a5ee 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -11,8 +11,8 @@ // enhanced with contributions from Terje Slettebo, // with additional fixes and suggestions from Gennaro Prota, // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov and other Boosters -// when: November 2000, March 2003, June 2005, June 2006 +// Alexander Nasonov, Antony Polukhin and other Boosters +// when: November 2000, March 2003, June 2005, June 2006, March 2011 #include #include @@ -20,12 +20,18 @@ #include #include #include +#include #include #include #include #include #include +#include +#include +#include +#include #include +#include #include #include #include @@ -1161,23 +1167,272 @@ namespace boost #if (defined _MSC_VER) # pragma warning( pop ) #endif + + template + struct is_stdstring + { + BOOST_STATIC_CONSTANT(bool, value = false ); + }; + + template + struct is_stdstring< std::basic_string > + { + BOOST_STATIC_CONSTANT(bool, value = true ); + }; + + template + struct is_char_or_wchar + { +#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 + ) + ); +#else + BOOST_STATIC_CONSTANT(bool, value = + ( + ::boost::type_traits::ice_or< + is_same< T, char >::value, + is_same< T, unsigned char >::value, + is_same< T, signed char >::value + >::value + ) + ); +#endif + }; + + template + struct is_arithmetic_and_not_xchars + { + BOOST_STATIC_CONSTANT(bool, value = + ( + ::boost::type_traits::ice_and< + is_arithmetic::value, + is_arithmetic::value, + ::boost::type_traits::ice_not< + detail::is_char_or_wchar::value + >::value, + ::boost::type_traits::ice_not< + detail::is_char_or_wchar::value + >::value + >::value + ) + ); + }; + + template + struct is_xchar_to_xchar + { + BOOST_STATIC_CONSTANT(bool, value = + ( + ::boost::type_traits::ice_and< + is_same::value, + is_char_or_wchar::value + >::value + ) + ); + }; + + template + struct is_char_array_to_stdstring + { + BOOST_STATIC_CONSTANT(bool, value = false ); + }; + + template + struct is_char_array_to_stdstring< std::basic_string, CharT* > + { + BOOST_STATIC_CONSTANT(bool, value = true ); + }; + + template + struct is_char_array_to_stdstring< std::basic_string, const CharT* > + { + BOOST_STATIC_CONSTANT(bool, value = true ); + }; + + template + struct lexical_cast_do_cast + { + static inline Target lexical_cast_impl(const Source &arg) + { + typedef typename detail::array_to_pointer_decay::type src; + + typedef typename detail::widest_char< + typename detail::stream_char::type + , typename detail::stream_char::type + >::type char_type; + + 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(); + return detail::lexical_cast(arg, buf, src_len); + } + }; + + template + struct lexical_cast_copy + { + static inline Source lexical_cast_impl(const Source &arg) + { + return arg; + } + }; + + class precision_loss_error : public boost::numeric::bad_numeric_cast + { + public: + virtual const char * what() const throw() + { return "bad numeric conversion: precision loss error"; } + }; + + template + struct throw_on_precision_loss + { + typedef boost::numeric::Trunc Rounder; + typedef S source_type ; + + typedef typename mpl::if_< is_arithmetic,S,S const&>::type argument_type ; + + static source_type nearbyint ( argument_type s ) + { + source_type orig_div_round = s / Rounder::nearbyint(s); + + if ( (orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > std::numeric_limits::epsilon() ) + BOOST_THROW_EXCEPTION( precision_loss_error() ); + return s ; + } + + typedef typename Rounder::round_style round_style; + } ; + + template + struct lexical_cast_dynamic_num_not_ignoring_minus + { + static inline Target lexical_cast_impl(const Source &arg) + { + try{ + typedef boost::numeric::converter< + Target, + Source, + boost::numeric::conversion_traits, + boost::numeric::def_overflow_handler, + throw_on_precision_loss + > Converter ; + + return Converter::convert(arg); + } catch(...) { + BOOST_LCAST_THROW_BAD_CAST(Source, Target); + } + } + }; + + template + struct lexical_cast_dynamic_num_ignoring_minus + { + static inline Target lexical_cast_impl(const Source &arg) + { + try{ + typedef boost::numeric::converter< + Target, + Source, + boost::numeric::conversion_traits, + boost::numeric::def_overflow_handler, + throw_on_precision_loss + > Converter ; + + bool has_minus = ( arg < 0); + if ( has_minus ) { + return static_cast(-Converter::convert(-arg)); + } else { + return Converter::convert(arg); + } + } catch(...) { + BOOST_LCAST_THROW_BAD_CAST(Source, Target); + } + } + }; + + /* + * lexical_cast_dynamic_num follows the rules: + * 1) If Source can be converted to Target without precision loss and + * without overflows, then assign Source to Target and return + * + * 2) If Source is less than 0 and Target is an unsigned integer, + * then negate Source, check the requirements of rule 1) and if + * successful, assign static_casted Source to Target and return + * + * 3) Otherwise throw a bad_lexical_cast exception + * + * + * Rule 2) required because boost::lexical_cast has the behavior of + * stringstream, which uses the rules of scanf for conversions. And + * in the C99 standard for unsigned input value minus sign is + * optional, so if a negative number is read, no errors will arise + * and the result will be the two's complement. + */ + template + struct lexical_cast_dynamic_num + { + static inline Target lexical_cast_impl(const Source &arg) + { + typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< + ::boost::type_traits::ice_and< + ::boost::type_traits::ice_or< + ::boost::is_signed::value, + ::boost::is_float::value + >::value, + ::boost::type_traits::ice_not< + is_same::value + >::value, + ::boost::type_traits::ice_not< + is_same::value + >::value, + ::boost::is_unsigned::value + >::value, + lexical_cast_dynamic_num_ignoring_minus, + lexical_cast_dynamic_num_not_ignoring_minus + >::type caster_type; + + return caster_type::lexical_cast_impl(arg); + } + }; } template inline Target lexical_cast(const Source &arg) { - typedef typename detail::array_to_pointer_decay::type src; + typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay::type src; - typedef typename detail::widest_char< - typename detail::stream_char::type - , typename detail::stream_char::type - >::type char_type; + typedef BOOST_DEDUCED_TYPENAME ::boost::type_traits::ice_or< + detail::is_xchar_to_xchar::value, + detail::is_char_array_to_stdstring::value, + ::boost::type_traits::ice_and< + is_same::value, + detail::is_stdstring::value + >::value + > do_copy_type; - 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(); - return detail::lexical_cast(arg, buf, src_len); + typedef BOOST_DEDUCED_TYPENAME detail::is_arithmetic_and_not_xchars do_copy_with_dynamic_check_type; + + typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< + do_copy_type::value, + detail::lexical_cast_copy, + BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< + do_copy_with_dynamic_check_type::value, + detail::lexical_cast_dynamic_num, + detail::lexical_cast_do_cast + >::type + >::type caster_type; + + return caster_type::lexical_cast_impl(arg); } #else @@ -1205,7 +1460,8 @@ namespace boost } // Copyright Kevlin Henney, 2000-2005. -// Copyright Alexander Nasonov, 2006-2007. +// Copyright Alexander Nasonov, 2006-2010. +// Copyright Antony Polukhin, 2011. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/lexical_cast.htm b/lexical_cast.htm index 5457a33..268684e 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -265,6 +265,11 @@ Eliminate an overhead of std::locale if your program runs in the "C August 2006.

    Changes

    +

    May 2011:

    +
      +
    • Better performance 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).
    • +

    August, October 2006:

    • Better performance for many combinations of Source and Target diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index a994d13..3f0991b 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -2,7 +2,7 @@ // // See http://www.boost.org for most recent version, including documentation. // -// Copyright Terje Slettebų and Kevlin Henney, 2005. +// Copyright Terje Sletteb and Kevlin Henney, 2005. // Copyright Alexander Nasonov, 2006. // // Distributed under the Boost @@ -84,6 +84,9 @@ void test_conversion_from_to_uintmax_t(); void test_conversion_from_to_longlong(); void test_conversion_from_to_ulonglong(); #endif +void test_conversion_from_to_float(); +void test_conversion_from_to_double(); +void test_conversion_from_to_long_double(); #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION void test_traits(); void test_wtraits(); @@ -122,6 +125,9 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) suite->add(BOOST_TEST_CASE(&test_conversion_from_to_longlong)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulonglong)); #endif + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_float)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_double)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_long_double)); #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION suite->add(BOOST_TEST_CASE(&test_traits)); suite->add(BOOST_TEST_CASE(&test_wtraits)); @@ -447,6 +453,24 @@ void test_conversion_from_integral_to_char(CharT zero) BOOST_CHECK_THROW(lexical_cast(t), bad_lexical_cast); } +template +void test_conversion_from_char_to_integral(CharT zero) +{ + BOOST_CHECK(lexical_cast( static_cast(zero + 0)) == static_cast(0) ); + BOOST_CHECK(lexical_cast( static_cast(zero + 1)) == static_cast(1) ); + BOOST_CHECK(lexical_cast( static_cast(zero + 2)) == static_cast(2) ); + BOOST_CHECK(lexical_cast( static_cast(zero + 3)) == static_cast(3) ); + BOOST_CHECK(lexical_cast( static_cast(zero + 4)) == static_cast(4) ); + BOOST_CHECK(lexical_cast( static_cast(zero + 5)) == static_cast(5) ); + BOOST_CHECK(lexical_cast( static_cast(zero + 6)) == static_cast(6) ); + BOOST_CHECK(lexical_cast( static_cast(zero + 7)) == static_cast(7) ); + BOOST_CHECK(lexical_cast( static_cast(zero + 8)) == static_cast(8) ); + BOOST_CHECK(lexical_cast( static_cast(zero + 9)) == static_cast(9) ); + + BOOST_CHECK_THROW(lexical_cast( static_cast(zero + 10)), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast( static_cast(zero - 1)), bad_lexical_cast); +} + template void test_conversion_from_integral_to_integral() { @@ -625,13 +649,36 @@ void test_conversion_from_to_integral() signed char const szero = '0'; unsigned char const uzero = '0'; test_conversion_from_integral_to_char(zero); + test_conversion_from_char_to_integral(zero); test_conversion_from_integral_to_char(szero); + test_conversion_from_char_to_integral(szero); test_conversion_from_integral_to_char(uzero); + test_conversion_from_char_to_integral(uzero); #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) wchar_t const wzero = L'0'; test_conversion_from_integral_to_char(wzero); + test_conversion_from_char_to_integral(wzero); #endif + BOOST_CHECK(lexical_cast("-1") == static_cast(-1)); + BOOST_CHECK(lexical_cast("-9") == static_cast(-9)); + BOOST_CHECK(lexical_cast(-1) == static_cast(-1)); + BOOST_CHECK(lexical_cast(-9) == static_cast(-9)); + + BOOST_CHECK_THROW(lexical_cast("-1.0"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("-9.0"), bad_lexical_cast); + BOOST_CHECK(lexical_cast(-1.0) == static_cast(-1)); + BOOST_CHECK(lexical_cast(-9.0) == static_cast(-9)); + + BOOST_CHECK(lexical_cast(static_cast(1)) == static_cast(1)); + BOOST_CHECK(lexical_cast(static_cast(9)) == static_cast(9)); + BOOST_CHECK_THROW(lexical_cast(1.1f), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(1.1), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(1.1L), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(1.0001f), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(1.0001), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(1.0001L), bad_lexical_cast); + // test_conversion_from_to_integral_for_locale typedef std::numpunct numpunct; @@ -665,6 +712,27 @@ void test_conversion_from_to_integral() BOOST_TEST_MESSAGE("Formatting with thousands_sep has not been tested"); } +template +void test_conversion_from_to_float() +{ + char const zero = '0'; + signed char const szero = '0'; + unsigned char const uzero = '0'; + test_conversion_from_integral_to_char(zero); + test_conversion_from_char_to_integral(zero); + test_conversion_from_integral_to_char(szero); + test_conversion_from_char_to_integral(szero); + test_conversion_from_integral_to_char(uzero); + test_conversion_from_char_to_integral(uzero); +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) + wchar_t const wzero = L'0'; + test_conversion_from_integral_to_char(wzero); + test_conversion_from_char_to_integral(wzero); +#endif + + test_conversion_from_integral_to_integral(); +} + void test_conversion_from_to_short() { test_conversion_from_to_integral(); @@ -717,6 +785,19 @@ void test_conversion_from_to_ulonglong() test_conversion_from_to_integral(); } +void test_conversion_from_to_float() +{ + test_conversion_from_to_float(); +} +void test_conversion_from_to_double() +{ + test_conversion_from_to_float(); +} +void test_conversion_from_to_long_double() +{ + test_conversion_from_to_float(); +} + #elif defined(LCAST_TEST_LONGLONG) void test_conversion_from_to_longlong() From dc9b364d6f3033712a93cae14d15ca3736dd39da Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 20 May 2011 17:11:53 +0000 Subject: [PATCH 085/242] Fixes #5417. Much better performance on casts to integral types. Adds more tests for overflow detection. Workaround for bugs of vc8 (lexical_cast_vc8_bug_test.cpp now passes) Fixes some inspection errors. [SVN r72056] --- include/boost/lexical_cast.hpp | 228 ++++++++++++++++++++++++++--- lexical_cast.htm | 5 +- lexical_cast_test.cpp | 93 ++++++++---- test/lexical_cast_vc8_bug_test.cpp | 14 ++ 4 files changed, 296 insertions(+), 44 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 7a4a5ee..00d0c4c 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -577,6 +577,84 @@ namespace boost } } + namespace detail // lcast_ret_unsigned + { + template + inline bool lcast_ret_unsigned(T& value, const CharT* const begin, const CharT* end) + { +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(!std::numeric_limits::is_signed); +#endif + typedef typename Traits::int_type int_type; + CharT const czero = lcast_char_constants::zero; + --end; + value = 0; + + if ( *end < czero || *end >= czero + 10 || begin > end) + return false; + value = *end - czero; + --end; + T multiplier = 1; + +#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE + // TODO: use BOOST_NO_STD_LOCALE + std::locale loc; + typedef std::numpunct numpunct; + numpunct const& np = BOOST_USE_FACET(numpunct, loc); + std::string const& grouping = np.grouping(); + std::string::size_type const grouping_size = grouping.size(); + + /* According to [22.2.2.1.2] of Programming languages — C++ we MUST check for correct grouping */ + if (grouping_size) + { + unsigned char current_grouping = 0; + CharT const thousands_sep = grouping_size ? np.thousands_sep() : 0; + char remained = grouping[current_grouping] - 1; + + for(;end>=begin; --end) + { + if (remained) { + T const new_sub_value = multiplier * 10 * (*end - czero); + + if (*end < czero || *end >= czero + 10 + /* detecting overflow */ + || new_sub_value/10 != multiplier * (*end - czero) + || static_cast((std::numeric_limits::max)()-new_sub_value) < value + ) + return false; + + value += new_sub_value; + multiplier *= 10; + --remained; + } else { + if ( !Traits::eq(*end, thousands_sep) || begin == end ) return false; + if (current_grouping < grouping_size-1 ) ++current_grouping; + remained = grouping[current_grouping]; + } + } + } else +#endif + { + while ( begin <= end ) + { + T const new_sub_value = multiplier * 10 * (*end - czero); + + if (*end < czero || *end >= czero + 10 + /* detecting overflow */ + || new_sub_value/10 != multiplier * (*end - czero) + || static_cast((std::numeric_limits::max)()-new_sub_value) < value + ) + return false; + + value += new_sub_value; + multiplier *= 10; + --end; + } + } + return true; + } + } + namespace detail // stream wrapper for handling lexical conversions { template @@ -762,8 +840,130 @@ namespace boost bool operator<<(double); bool operator<<(long double); + private: + + template + bool input_operator_helper_unsigned(Type& output) + { + CharT const minus = lcast_char_constants::minus; + bool const has_minus = Traits::eq(minus,*start); + bool const succeed = lcast_ret_unsigned(output, has_minus ? start+1 : start, finish); +#if (defined _MSC_VER) +# pragma warning( push ) +// C4146: unary minus operator applied to unsigned type, result still unsigned +# pragma warning( disable : 4146 ) +#elif defined( __BORLANDC__ ) +# pragma option push -w-8041 +#endif + if (has_minus) output = static_cast(-output); +#if (defined _MSC_VER) +# pragma warning( pop ) +#elif defined( __BORLANDC__ ) +# pragma option pop +#endif + return succeed; + } + + template + bool input_operator_helper_signed(Type& output) + { + CharT const minus = lcast_char_constants::minus; + typedef BOOST_DEDUCED_TYPENAME make_unsigned::type utype; + utype out_tmp =0; + bool const has_minus = Traits::eq(minus,*start); + bool succeed = lcast_ret_unsigned(out_tmp, has_minus ? start+1 : start, finish); + if (has_minus) { +#if (defined _MSC_VER) +# pragma warning( push ) +// C4146: unary minus operator applied to unsigned type, result still unsigned +# pragma warning( disable : 4146 ) +#elif defined( __BORLANDC__ ) +# pragma option push -w-8041 +#endif + utype const comp_val = static_cast(-(std::numeric_limits::min)()); + succeed = succeed && out_tmp<=comp_val; + output = -out_tmp; +#if (defined _MSC_VER) +# pragma warning( pop ) +#elif defined( __BORLANDC__ ) +# pragma option pop +#endif + } else { + utype const comp_val = static_cast((std::numeric_limits::max)()); + succeed = succeed && out_tmp<=comp_val; + output = out_tmp; + } + return succeed; + } + public: // input + bool operator>>(unsigned short& output) + { + return input_operator_helper_unsigned(output); + } + + bool operator>>(unsigned int& output) + { + return input_operator_helper_unsigned(output); + } + + bool operator>>(unsigned long int& output) + { + return input_operator_helper_unsigned(output); + } + + bool operator>>(short& output) + { + return input_operator_helper_signed(output); + } + + bool operator>>(int& output) + { + return input_operator_helper_signed(output); + } + + bool operator>>(long int& output) + { + return input_operator_helper_signed(output); + } + + +#if defined(BOOST_HAS_LONG_LONG) + bool operator>>( boost::ulong_long_type& output) + { + return input_operator_helper_unsigned(output); + } + + bool operator>>(boost::long_long_type& output) + { + return input_operator_helper_signed(output); + } + +#elif defined(BOOST_HAS_MS_INT64) + bool operator>>(unsigned __int64& output) + { + return input_operator_helper_unsigned(output); + } + + bool operator>>(__int64& output) + { + return input_operator_helper_signed(output); + } + +#endif + + bool operator>>(bool& output) + { + output = (start[0] == lcast_char_constants::zero + 1); + return finish-start==1 + && ( + start[0] == lcast_char_constants::zero + || start[0] == lcast_char_constants::zero + 1 + ); + } + + // Generic istream-based algorithm. // lcast_streambuf_for_target::value is true. template @@ -1059,23 +1259,17 @@ namespace boost template struct lcast_streambuf_for_target { - BOOST_STATIC_CONSTANT(bool, value = true); + 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 + ) + ); }; - template<> - struct lcast_streambuf_for_target - { - BOOST_STATIC_CONSTANT(bool, value = false); - }; - -#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) - template<> - struct lcast_streambuf_for_target - { - BOOST_STATIC_CONSTANT(bool, value = false); - }; -#endif - #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct lcast_streambuf_for_target< @@ -1328,7 +1522,7 @@ namespace boost > Converter ; return Converter::convert(arg); - } catch(...) { + } catch( ::boost::numeric::bad_numeric_cast const& ) { BOOST_LCAST_THROW_BAD_CAST(Source, Target); } } @@ -1354,7 +1548,7 @@ namespace boost } else { return Converter::convert(arg); } - } catch(...) { + } catch( ::boost::numeric::bad_numeric_cast const& ) { BOOST_LCAST_THROW_BAD_CAST(Source, Target); } } diff --git a/lexical_cast.htm b/lexical_cast.htm index 268684e..3372618 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -267,7 +267,8 @@ Eliminate an overhead of std::locale if your program runs in the "C

      Changes

      May 2011:

        -
      • Better performance for conversions from arithmetic type to arithmetic type.
      • +
      • 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).

      August, October 2006:

      @@ -317,7 +318,7 @@ Eliminate an overhead of std::locale if your program runs in the "C
      Copyright © Antony Polukhin, 2011
      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 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
      diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 3f0991b..317c3fd 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -4,6 +4,7 @@ // // Copyright Terje Sletteb and Kevlin Henney, 2005. // Copyright Alexander Nasonov, 2006. +// Copyright Antony Polukhin, 2011. // // Distributed under the Boost // Software License, Version 1.0. (See accompanying file @@ -32,6 +33,7 @@ #include #include +#include #include #include @@ -235,6 +237,14 @@ void test_conversion_to_bool() BOOST_CHECK_EQUAL(false, lexical_cast("0")); BOOST_CHECK_EQUAL(true, lexical_cast(std::string("1"))); BOOST_CHECK_EQUAL(false, lexical_cast(std::string("0"))); + + BOOST_CHECK_THROW(lexical_cast(1.0001L), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(2), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(2u), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(-1), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(-2), bad_lexical_cast); + + BOOST_CHECK_THROW( lexical_cast(std::string("")), bad_lexical_cast); BOOST_CHECK_THROW( @@ -564,25 +574,46 @@ void test_conversion_from_string_to_integral(CharT) BOOST_CHECK_EQUAL(lexical_cast(s), min_val); if(limits::is_signed) { -#if defined(BOOST_MSVC) && BOOST_MSVC == 1400 - // VC++ 8.0 bug, see libs/conversion/test/lexical_cast_vc8_bug_test.cpp - if(sizeof(T) < sizeof(boost::intmax_t)) -#endif - { - BOOST_CHECK_THROW(lexical_cast(s + zero), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(s + nine), bad_lexical_cast); - } + BOOST_CHECK_THROW(lexical_cast(s + zero), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(s + nine), bad_lexical_cast); } s = to_str(max_val); BOOST_CHECK_EQUAL(lexical_cast(s), max_val); -#if defined(BOOST_MSVC) && BOOST_MSVC == 1400 - // VC++ 8.0 bug, see libs/conversion/test/lexical_cast_vc8_bug_test.cpp - if(sizeof(T) != sizeof(boost::intmax_t)) -#endif { BOOST_CHECK_THROW(lexical_cast(s + zero), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(s + nine), bad_lexical_cast); + + s = to_str(max_val); + for (int i =1; i <=10; ++i) { + s[s.size()-1] += 1; + BOOST_CHECK_THROW(lexical_cast( s ), bad_lexical_cast); + } + + s = to_str(max_val); + std::locale loc; + typedef std::numpunct numpunct; + if ( BOOST_USE_FACET(numpunct, loc).grouping().empty() ) { + // Following tests work well for locale C + BOOST_CHECK_EQUAL(lexical_cast(to_str(0)+s), max_val); + BOOST_CHECK_EQUAL(lexical_cast(to_str(0)+to_str(0)+s), max_val); + BOOST_CHECK_EQUAL(lexical_cast(to_str(0)+to_str(0)+to_str(0)+s), max_val); + } + + for (int i =1; i <=256; ++i) { + BOOST_CHECK_THROW(lexical_cast( to_str(i)+s ), bad_lexical_cast); + } + + typedef BOOST_DEDUCED_TYPENAME boost::integral_promotion::type promoted; + if ( !(boost::is_same::value) ) + { + promoted prom = max_val; + s = to_str(max_val); + for (int i =1; i <=256; ++i) { + BOOST_CHECK_THROW(lexical_cast( to_str(prom+i) ), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast( to_str(i)+s ), bad_lexical_cast); + } + } } if(limits::digits <= 16 && lcast_test_small_integral_types_completely) @@ -627,6 +658,18 @@ void test_conversion_from_string_to_integral(CharT) template void test_conversion_from_to_integral_for_locale() { + std::locale current_locale; + typedef std::numpunct numpunct; + numpunct const& np = BOOST_USE_FACET(numpunct, current_locale); + if ( !np.grouping().empty() ) + { + BOOST_CHECK_THROW( + lexical_cast( std::string("100") + np.thousands_sep() + np.thousands_sep() + "0" ) + , bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast( std::string("100") + np.thousands_sep() ), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast( np.thousands_sep() + std::string("100") ), bad_lexical_cast); + } + test_conversion_from_integral_to_integral(); test_conversion_from_integral_to_string('0'); test_conversion_from_string_to_integral('0'); @@ -773,18 +816,6 @@ void test_conversion_from_to_uintmax_t() test_conversion_from_to_integral(); } -#if defined(BOOST_HAS_LONG_LONG) - -void test_conversion_from_to_longlong() -{ - test_conversion_from_to_integral(); -} - -void test_conversion_from_to_ulonglong() -{ - test_conversion_from_to_integral(); -} - void test_conversion_from_to_float() { test_conversion_from_to_float(); @@ -798,7 +829,19 @@ void test_conversion_from_to_long_double() test_conversion_from_to_float(); } -#elif defined(LCAST_TEST_LONGLONG) +#if defined(BOOST_HAS_LONG_LONG) + +void test_conversion_from_to_longlong() +{ + test_conversion_from_to_integral(); +} + +void test_conversion_from_to_ulonglong() +{ + test_conversion_from_to_integral(); +} + +#elif defined(BOOST_HAS_MS_INT64) void test_conversion_from_to_longlong() { diff --git a/test/lexical_cast_vc8_bug_test.cpp b/test/lexical_cast_vc8_bug_test.cpp index 843bea8..151e4f8 100644 --- a/test/lexical_cast_vc8_bug_test.cpp +++ b/test/lexical_cast_vc8_bug_test.cpp @@ -1,3 +1,17 @@ +// Unit test for boost::lexical_cast. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Alexander Nasonov, 2007. +// +// 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). +// +// This tests now must pass on vc8, because lexical_cast +// implementation has changed and it does not use stringstream for casts +// to integral types + #include #include #include From 920e36f6ba7ef26d1a80902b84cfeaa94cd03a0a Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 22 May 2011 11:35:00 +0000 Subject: [PATCH 086/242] Fixes #5557. Adds tests on #5557 [SVN r72071] --- include/boost/lexical_cast.hpp | 79 ++++++++++++++++++++++++++++------ lexical_cast_test.cpp | 11 +++++ 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 00d0c4c..6875b16 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -463,7 +463,7 @@ namespace boost #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION } - namespace detail // '0' and '-' constants + namespace detail // '0', '+' and '-' constants { template struct lcast_char_constants; @@ -472,6 +472,7 @@ namespace boost { BOOST_STATIC_CONSTANT(char, zero = '0'); BOOST_STATIC_CONSTANT(char, minus = '-'); + BOOST_STATIC_CONSTANT(char, plus = '+'); }; #ifndef BOOST_LCAST_NO_WCHAR_T @@ -480,6 +481,7 @@ namespace boost { BOOST_STATIC_CONSTANT(wchar_t, zero = L'0'); BOOST_STATIC_CONSTANT(wchar_t, minus = L'-'); + BOOST_STATIC_CONSTANT(wchar_t, plus = L'+'); }; #endif } @@ -604,7 +606,9 @@ namespace boost std::string const& grouping = np.grouping(); std::string::size_type const grouping_size = grouping.size(); - /* According to [22.2.2.1.2] of Programming languages — C++ we MUST check for correct grouping */ + /* According to [22.2.2.1.2] of Programming languages - C++ + * we MUST check for correct grouping + */ if (grouping_size) { unsigned char current_grouping = 0; @@ -846,8 +850,20 @@ namespace boost bool input_operator_helper_unsigned(Type& output) { CharT const minus = lcast_char_constants::minus; - bool const has_minus = Traits::eq(minus,*start); - bool const succeed = lcast_ret_unsigned(output, has_minus ? start+1 : start, finish); + CharT const plus = lcast_char_constants::plus; + bool has_minus = false; + + /* We won`t use `start' any more, so no need in decrementing it after */ + if ( Traits::eq(minus,*start) ) + { + ++start; + has_minus = true; + } else if ( Traits::eq( plus, *start ) ) + { + ++start; + } + + bool const succeed = lcast_ret_unsigned(output, start, finish); #if (defined _MSC_VER) # pragma warning( push ) // C4146: unary minus operator applied to unsigned type, result still unsigned @@ -868,10 +884,22 @@ namespace boost bool input_operator_helper_signed(Type& output) { CharT const minus = lcast_char_constants::minus; + CharT const plus = lcast_char_constants::plus; typedef BOOST_DEDUCED_TYPENAME make_unsigned::type utype; utype out_tmp =0; - bool const has_minus = Traits::eq(minus,*start); - bool succeed = lcast_ret_unsigned(out_tmp, has_minus ? start+1 : start, finish); + bool has_minus = false; + + /* We won`t use `start' any more, so no need in decrementing it after */ + if ( Traits::eq(minus,*start) ) + { + ++start; + has_minus = true; + } else if ( Traits::eq(plus, *start) ) + { + ++start; + } + + bool succeed = lcast_ret_unsigned(out_tmp, start, finish); if (has_minus) { #if (defined _MSC_VER) # pragma warning( push ) @@ -953,14 +981,38 @@ namespace boost #endif + /* + * case "-0" || "0" || "+0" : output = false; return true; + * case "1" || "+1": output = true; return true; + * default: return false; + */ bool operator>>(bool& output) { - output = (start[0] == lcast_char_constants::zero + 1); - return finish-start==1 - && ( - start[0] == lcast_char_constants::zero - || start[0] == lcast_char_constants::zero + 1 - ); + CharT const zero = lcast_char_constants::zero; + CharT const plus = lcast_char_constants::plus; + CharT const minus = lcast_char_constants::minus; + + switch(finish-start) + { + case 1: + output = Traits::eq(start[0], zero+1); + return output || Traits::eq(start[0], zero ); + case 2: + if ( Traits::eq( plus, *start) ) + { + ++start; + output = Traits::eq(start[0], zero +1); + return output || Traits::eq(start[0], zero ); + } else + { + output = false; + return Traits::eq( minus, *start) + && Traits::eq( zero, start[1]); + } + default: + output = false; // Suppress warning about uninitalized variable + return false; + } } @@ -1614,7 +1666,8 @@ namespace boost >::value > do_copy_type; - typedef BOOST_DEDUCED_TYPENAME detail::is_arithmetic_and_not_xchars do_copy_with_dynamic_check_type; + typedef BOOST_DEDUCED_TYPENAME + detail::is_arithmetic_and_not_xchars do_copy_with_dynamic_check_type; typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< do_copy_type::value, diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 317c3fd..f366eb2 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -249,6 +249,12 @@ void test_conversion_to_bool() lexical_cast(std::string("")), bad_lexical_cast); BOOST_CHECK_THROW( lexical_cast(std::string("Test")), bad_lexical_cast); + + BOOST_CHECK(lexical_cast("+1") == true ); + BOOST_CHECK(lexical_cast("+0") == false ); + BOOST_CHECK(lexical_cast("-0") == false ); + BOOST_CHECK_THROW(lexical_cast("--0"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("-+-0"), bad_lexical_cast); } void test_conversion_to_string() @@ -722,6 +728,8 @@ void test_conversion_from_to_integral() BOOST_CHECK_THROW(lexical_cast(1.0001), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(1.0001L), bad_lexical_cast); + BOOST_CHECK(lexical_cast("+1") == static_cast(1) ); + BOOST_CHECK(lexical_cast("+9") == static_cast(9) ); // test_conversion_from_to_integral_for_locale typedef std::numpunct numpunct; @@ -774,6 +782,9 @@ void test_conversion_from_to_float() #endif test_conversion_from_integral_to_integral(); + + BOOST_CHECK_CLOSE(lexical_cast("+1"), 1, std::numeric_limits::epsilon() ); + BOOST_CHECK_CLOSE(lexical_cast("+9"), 9, std::numeric_limits::epsilon()*9 ); } void test_conversion_from_to_short() From 98d24e04f408e86a8cf6675b5fff93c902bf3960 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 27 May 2011 04:22:18 +0000 Subject: [PATCH 087/242] 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 +} From b0b1ce9453445af00649f6ec7beee5d0beb5edf9 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 27 May 2011 18:19:38 +0000 Subject: [PATCH 088/242] Fixes #5576, adds performance section to the lexical_cast documentation, fixes misprint in tests/ [SVN r72224] --- include/boost/lexical_cast.hpp | 73 +++++++++++++++++++--------------- lexical_cast.htm | 34 +++++++++++++++- lexical_cast_test.cpp | 1 - 3 files changed, 74 insertions(+), 34 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index d185852..c1b083b 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -555,6 +555,10 @@ namespace boost BOOST_STATIC_ASSERT(!std::numeric_limits::is_signed); #endif + typedef typename Traits::int_type int_type; + CharT const czero = lcast_char_constants::zero; + int_type const zero = Traits::to_int_type(czero); + #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE // TODO: use BOOST_NO_STD_LOCALE std::locale loc; @@ -562,47 +566,54 @@ namespace boost numpunct const& np = BOOST_USE_FACET(numpunct, loc); std::string const& grouping = np.grouping(); std::string::size_type const grouping_size = grouping.size(); - CharT thousands_sep = grouping_size ? np.thousands_sep() : 0; - std::string::size_type group = 0; // current group number - char last_grp_size = - grouping_size == 0 || grouping[0] <= 0 ? CHAR_MAX : grouping[0]; + + if ( grouping_size && grouping[0] > 0 ) + { + #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS // Check that ulimited group is unreachable: BOOST_STATIC_ASSERT(std::numeric_limits::digits10 < CHAR_MAX); #endif + CharT thousands_sep = np.thousands_sep(); + std::string::size_type group = 0; // current group number + char last_grp_size = grouping[0]; + char left = last_grp_size; - char left = last_grp_size; -#endif - - typedef typename Traits::int_type int_type; - CharT const czero = lcast_char_constants::zero; - int_type const zero = Traits::to_int_type(czero); - - do - { -#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - if(left == 0) + do { - ++group; - if(group < grouping_size) + if(left == 0) { - char const grp_size = grouping[group]; - last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size; + ++group; + if(group < grouping_size) + { + char const grp_size = grouping[group]; + last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size; + } + + left = last_grp_size; + --finish; + Traits::assign(*finish, thousands_sep); } - left = last_grp_size; + --left; + --finish; - Traits::assign(*finish, thousands_sep); - } + int_type const digit = static_cast(n % 10U); + Traits::assign(*finish, Traits::to_char_type(zero + digit)); + n /= 10; + } while(n); - --left; + } else #endif - - --finish; - int_type const digit = static_cast(n % 10U); - Traits::assign(*finish, Traits::to_char_type(zero + digit)); - n /= 10; - } while(n); + { + do + { + --finish; + int_type const digit = static_cast(n % 10U); + Traits::assign(*finish, Traits::to_char_type(zero + digit)); + n /= 10; + } while(n); + } return finish; } @@ -638,10 +649,10 @@ namespace boost /* According to [22.2.2.1.2] of Programming languages - C++ * we MUST check for correct grouping */ - if (grouping_size) + if (grouping_size && grouping[0] > 0) { unsigned char current_grouping = 0; - CharT const thousands_sep = grouping_size ? np.thousands_sep() : 0; + CharT const thousands_sep = np.thousands_sep(); char remained = grouping[current_grouping] - 1; for(;end>=begin; --end) diff --git a/lexical_cast.htm b/lexical_cast.htm index 03625b4..2292d2a 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -26,6 +26,8 @@ References
      • Changes
      • +
      • + Performance

      Motivation

      @@ -87,7 +89,7 @@ For a good discussion of the options and issues involved in string-based formatting, including comparison of stringstream, lexical_cast, and others, see Herb Sutter's article, - The String Formatters of Manor Farm. + The String Formatters of Manor Farm. Also, take a look at the Performance section.


      Examples

      @@ -267,6 +269,7 @@ Eliminate an overhead of std::locale if your program runs in the "C

      Changes

      May 2011:

        +
      • Optimizations for "C" and other locales without number grouping.
      • 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.
      • @@ -313,7 +316,34 @@ Eliminate an overhead of std::locale if your program runs in the "C


      - + +

      Performance

      +This table shows the execution speed for 100000 iterations in milliseconds of the following code blocks: + + + + + + + + + + + + + + + + + + + + +
      From->To target = lexical_cast<Target>(source); std::stringstream ss;
      ss << source;
      ss >> target;
      ss << source;
      ss >> target;
      ss.str(std::string());
      ss.clear();
      sscanf( (const char*)source, <...>, &target);
      OR
      sprintf( (char*)buffer, <...>, source);
      + target = buffer;
      string->char<191710
      string->int71152318
      string->unsigned int71172217
      string->bool<11041910
      string->float851726033
      char->string71051612
      int->string151312117
      unsigned int->string141252117
      bool->string71222412
      float->string12422311548
      char*->string912320---
      int->int<112026---
      float->float<1262142---
      + +Fastest results are highlitened with green. +
      Copyright © Kevlin Henney, 2000-2005
      Copyright © Alexander Nasonov, 2006-2010
      Copyright © Antony Polukhin, 2011
      diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 75d12ff..f88017f 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -937,7 +937,6 @@ void test_wallocator() #endif -#include void test_char_types_conversions() { const char c_arr[] = "Test array of chars"; From ccaa3059e88a1acc7bbac40343a491c0d69cef8d Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 27 May 2011 18:32:57 +0000 Subject: [PATCH 089/242] Improved english and documentation design for #5576. [SVN r72225] --- lexical_cast.htm | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lexical_cast.htm b/lexical_cast.htm index 2292d2a..7929dd4 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -318,15 +318,11 @@ Eliminate an overhead of std::locale if your program runs in the "C

      Performance

      -This table shows the execution speed for 100000 iterations in milliseconds of the following code blocks: +This table shows the execution time in milliseconds for 100000 calls of the following string formatters: - - - - + From cd0167d6b8bc3cadab3b674e7f5304d8322c77d8 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 31 May 2011 20:46:37 +0000 Subject: [PATCH 090/242] Fixes #5585 and adds test on it [SVN r72315] --- include/boost/lexical_cast.hpp | 28 ++++++++++++++++++++++++---- lexical_cast_test.cpp | 3 +++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index c1b083b..ddd7398 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -654,6 +654,7 @@ namespace boost unsigned char current_grouping = 0; CharT const thousands_sep = np.thousands_sep(); char remained = grouping[current_grouping] - 1; + bool shall_we_return = true; for(;end>=begin; --end) { @@ -671,12 +672,31 @@ namespace boost multiplier *= 10; --remained; } else { - if ( !Traits::eq(*end, thousands_sep) || begin == end ) return false; - if (current_grouping < grouping_size-1 ) ++current_grouping; - remained = grouping[current_grouping]; + if ( !Traits::eq(*end, thousands_sep) ) //|| begin == end ) return false; + { + /* + * According to Programming languages - C++ + * Digit grouping is checked. That is, the positions of discarded + * separators is examined for consistency with + * use_facet >(loc ).grouping() + * + * BUT what if there is no separators at all and grouping() + * is not empty? Well, we have no extraced separators, so we + * won`t check them for consistency. This will allow us to + * work with "C" locale from other locales + */ + shall_we_return = false; + break; + } else { + if ( begin == end ) return false; + if (current_grouping < grouping_size-1 ) ++current_grouping; + remained = grouping[current_grouping]; + } } } - } else + + if (shall_we_return) return true; + } #endif { while ( begin <= end ) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index f88017f..f20994e 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -677,6 +677,9 @@ void test_conversion_from_to_integral_for_locale() , bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast( std::string("100") + np.thousands_sep() ), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast( np.thousands_sep() + std::string("100") ), bad_lexical_cast); + + // Exception must not be thrown, when we are using no separators at all + BOOST_CHECK( lexical_cast("10000") == static_cast(10000) ); } test_conversion_from_integral_to_integral(); From 6a8c22d5c31df22424cbcfcb7b56ea4cb3643ce8 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 6 Jul 2011 15:43:04 +0000 Subject: [PATCH 091/242] Partial fix for #5660. Better performance and less memory usage for conversions to float type (and to double type, if sizeof(double) < sizeof(long double)). New test suits. Documentation update. [SVN r72925] --- include/boost/lexical_cast.hpp | 318 ++++++++++++++- lexical_cast.htm | 4 + lexical_cast_test.cpp | 65 +-- test/Jamfile.v2 | 2 + test/lexical_cast_float_types_test.cpp | 527 +++++++++++++++++++++++++ test/lexical_cast_loopback_test.cpp | 6 - test/lexical_cast_wchars_test.cpp | 56 +++ 7 files changed, 918 insertions(+), 60 deletions(-) create mode 100755 test/lexical_cast_float_types_test.cpp create mode 100755 test/lexical_cast_wchars_test.cpp diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index ddd7398..d9b73af 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1,6 +1,12 @@ #ifndef BOOST_LEXICAL_CAST_INCLUDED #define BOOST_LEXICAL_CAST_INCLUDED +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + // Boost lexical_cast.hpp header -------------------------------------------// // // See http://www.boost.org/libs/conversion for documentation. @@ -502,6 +508,9 @@ namespace boost BOOST_STATIC_CONSTANT(char, zero = '0'); BOOST_STATIC_CONSTANT(char, minus = '-'); BOOST_STATIC_CONSTANT(char, plus = '+'); + BOOST_STATIC_CONSTANT(char, lowercase_e = 'e'); + BOOST_STATIC_CONSTANT(char, capital_e = 'E'); + BOOST_STATIC_CONSTANT(char, c_decimal_separator = '.'); }; #ifndef BOOST_LCAST_NO_WCHAR_T @@ -511,6 +520,9 @@ namespace boost BOOST_STATIC_CONSTANT(wchar_t, zero = L'0'); BOOST_STATIC_CONSTANT(wchar_t, minus = L'-'); BOOST_STATIC_CONSTANT(wchar_t, plus = L'+'); + BOOST_STATIC_CONSTANT(wchar_t, lowercase_e = L'e'); + BOOST_STATIC_CONSTANT(wchar_t, capital_e = L'E'); + BOOST_STATIC_CONSTANT(wchar_t, c_decimal_separator = L'.'); }; #endif } @@ -646,7 +658,7 @@ namespace boost std::string const& grouping = np.grouping(); std::string::size_type const grouping_size = grouping.size(); - /* According to [22.2.2.1.2] of Programming languages - C++ + /* According to Programming languages - C++ * we MUST check for correct grouping */ if (grouping_size && grouping[0] > 0) @@ -719,6 +731,246 @@ namespace boost } } + namespace detail // lcast_ret_float + { + template + struct mantissa_holder_type + { + /* Can not be used with this type */ + }; + + template <> + struct mantissa_holder_type + { + typedef unsigned int type; + }; + + template <> + struct mantissa_holder_type + { +#if defined(BOOST_HAS_LONG_LONG) + typedef boost::ulong_long_type type; +#elif defined(BOOST_HAS_MS_INT64) + typedef unsigned __int64 type; +#endif + }; + + template + inline bool lcast_ret_float(T& value, const CharT* begin, const CharT* end) + { + +#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE + // TODO: use BOOST_NO_STD_LOCALE + std::locale loc; + typedef std::numpunct numpunct; + numpunct const& np = BOOST_USE_FACET(numpunct, loc); + std::string const& grouping = np.grouping(); + std::string::size_type const grouping_size = grouping.size(); + CharT const thousands_sep = grouping_size ? np.thousands_sep() : 0; + CharT const decimal_point = np.decimal_point(); + bool found_grouping = false; + unsigned int last_grouping_pos = grouping_size - 1; +#else + CharT const decimal_point = lcast_char_constants::c_decimal_separator; +#endif + + CharT const czero = lcast_char_constants::zero; + CharT const minus = lcast_char_constants::minus; + CharT const plus = lcast_char_constants::plus; + CharT const capital_e = lcast_char_constants::capital_e; + CharT const lowercase_e = lcast_char_constants::lowercase_e; + + value = 0.0; + + typedef typename Traits::int_type int_type; + typedef BOOST_DEDUCED_TYPENAME mantissa_holder_type::type mantissa_type; + int_type const zero = Traits::to_int_type(czero); + if (begin == end) return false; + + /* Getting the plus/minus sign */ + bool has_minus = false; + if ( *begin == minus ) { + ++ begin; + has_minus = true; + if (begin == end) return false; + } else if ( *begin == plus ) { + ++begin; + if (begin == end) return false; + } + + if ( *begin < czero || *begin >= czero + 10 ) { + return false; + } + + + bool found_decimal = false; + int pow_of_10 = 0; + mantissa_type mantissa=0; + bool is_mantissa_full = false; + + char length_since_last_delim = 0; + + while ( begin != end ) + { + if (found_decimal) { + /* We allow no thousand_separators after decimal point */ + + mantissa_type tmp_mantissa = mantissa * 10u; + if ( *begin == lowercase_e || *begin == capital_e ) break; + if ( *begin < czero || *begin >= czero + 10 ) return false; + if ( is_mantissa_full + || tmp_mantissa / 10u != mantissa + || (std::numeric_limits::max)()-(*begin - zero) < tmp_mantissa + ) { + is_mantissa_full = true; + ++ begin; + continue; + } + + -- pow_of_10; + mantissa = tmp_mantissa; + mantissa += *begin - zero; + } else { + + if (*begin >= czero && *begin < czero + 10) { + + /* Checking for mantissa overflow. If overflow will + * occur, them we only increase multiplyer + */ + mantissa_type tmp_mantissa = mantissa * 10u; + if( !is_mantissa_full + && tmp_mantissa / 10u == mantissa + && (std::numeric_limits::max)()-(*begin - zero) >= tmp_mantissa + ) + { + mantissa = tmp_mantissa; + mantissa += *begin - zero; + } else + { + is_mantissa_full = true; + ++ pow_of_10; + } + + ++ length_since_last_delim; + } else if ( *begin == decimal_point || *begin == lowercase_e || *begin == capital_e) { +#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE + /* If ( we need to check grouping + * and ( grouping missmatches + * or grouping position is incorrect + * or we are using the grouping position 0 twice + * ) + * ) then return error + */ + if( grouping_size && found_grouping + && ( + length_since_last_delim != grouping[0] + || last_grouping_pos>1 + || (last_grouping_pos==0 && grouping_size>1) + ) + ) return false; +#endif + + if(*begin == decimal_point){ + ++ begin; + found_decimal = true; + continue; + }else break; + } +#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE + else if (grouping_size && *begin == thousands_sep){ + if(found_grouping) + { + /* It is not he first time, when we find thousands separator, + * so we need to chek, is the distance between two groupings + * equal to grouping[last_grouping_pos] */ + + if (length_since_last_delim != grouping[last_grouping_pos] ) + { + if (!last_grouping_pos) return false; + else + { + -- last_grouping_pos; + if (length_since_last_delim != grouping[last_grouping_pos]) return false; + } + } else + /* We are calling the grouping[0] twice, when grouping size is more than 1 */ + if (grouping_size>1u && last_grouping_pos+1 grouping[last_grouping_pos] ) return false; + } + + length_since_last_delim = 0; + ++ begin; + + /* Delimiter at the end '100,' */ + if (begin == end) return false; + continue; + } +#endif + else return false; + } + + ++begin; + } + + // Exponent found + if ( begin != end && ( *begin == lowercase_e || *begin == capital_e ) ) { + ++ begin; + if ( begin == end ) return false; + + bool exp_has_minus = false; + if( *begin == minus ) { + exp_has_minus = true; + ++ begin; + if ( begin == end ) return false; + } else if (*begin == plus ) { + ++ begin; + if ( begin == end ) return false; + } + + int exp_pow_of_10 = 0; + while ( begin != end ) + { + if ( *begin < czero + || *begin >= czero + 10 + || exp_pow_of_10 * 10 < exp_pow_of_10) /* Overflows are checked lower more precisely*/ + return false; + + exp_pow_of_10 *= 10; + exp_pow_of_10 += *begin - zero; + ++ begin; + }; + + if ( exp_pow_of_10 ) { + /* Overflows are checked lower */ + if ( exp_has_minus ) { + pow_of_10 -= exp_pow_of_10; + } else { + pow_of_10 += exp_pow_of_10; + } + } + } + + /* We need a more accurate algorithm... We can not use current algorithm + * with long doubles (and with doubles if sizeof(double)==sizeof(long double)). + */ + long double result = std::pow(10.0L, pow_of_10) * mantissa; + value = ( has_minus ? -1 * result : result); + + if ( value > (std::numeric_limits::max)() // is it +inf + || value < -(std::numeric_limits::max)() // is it -inf + || value != value) // is it NaN + return false; + + return true; + } + } + namespace detail // stream wrapper for handling lexical conversions { template @@ -1079,12 +1331,54 @@ namespace boost } } + bool operator>>(float& output) + { + return lcast_ret_float(output,start,finish); + } + +#if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64) + private: + // we need workaround + bool no_long_double_80bit_realization_workaround(double& output, int) { + return convert_using_base_class(output); + } + + // we do not need a workaround + bool no_long_double_80bit_realization_workaround(double& output,char) { + return lcast_ret_float(output,start,finish); + } + public: + + bool operator>>(double& output) + { + /* + * Some compilers implement long double as double. In that case these types have + * same size, same precision, same max and min values... And it means, + * that current implementation of lcast_ret_float cannot be used for type + * double, because it will give a big precision loss. + * */ + boost::mpl::if_c< + ::boost::type_traits::ice_eq< sizeof(double), sizeof(long double) >::value, + int, + char + >::type dummy = 0; + + return no_long_double_80bit_realization_workaround(output, dummy); + } +#endif // Generic istream-based algorithm. // lcast_streambuf_for_target::value is true. template bool operator>>(InputStreamable& output) { + return convert_using_base_class(output); + } + + private: + template + bool convert_using_base_class(InputStreamable& output) + { #if (defined _MSC_VER) # pragma warning( push ) // conditional expression is constant @@ -1112,6 +1406,7 @@ namespace boost Traits::eof(); #endif } + public: bool operator>>(CharT&); bool operator>>(unsigned char&); @@ -1433,11 +1728,30 @@ namespace boost template struct lcast_streambuf_for_target { +#if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64) BOOST_STATIC_CONSTANT(bool, value = ( - ::boost::type_traits::ice_not< is_integral::value >::value + ::boost::type_traits::ice_or< + ::boost::type_traits::ice_not< is_arithmetic::value >::value, + is_same::value, + ::boost::type_traits::ice_and< + is_same::value, + ::boost::type_traits::ice_eq::value + >::value + >::value ) ); +#else + BOOST_STATIC_CONSTANT(bool, value = + ( + ::boost::type_traits::ice_or< + ::boost::type_traits::ice_not< is_arithmetic::value >::value, + is_same::value, + is_same::value + >::value + ) + ); +#endif }; #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION diff --git a/lexical_cast.htm b/lexical_cast.htm index 7929dd4..7a1fee5 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -267,6 +267,10 @@ Eliminate an overhead of std::locale if your program runs in the "C August 2006.

      Changes

      +

      July 2011:

      +
        +
      • Better performance and less memory usage for conversions to float type (and to double type, if sizeof(double)<sizeof(long double)).
      • +

      May 2011:

      • Optimizations for "C" and other locales without number grouping.
      • diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index f20994e..cdf42fe 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -86,9 +86,6 @@ void test_conversion_from_to_uintmax_t(); void test_conversion_from_to_longlong(); void test_conversion_from_to_ulonglong(); #endif -void test_conversion_from_to_float(); -void test_conversion_from_to_double(); -void test_conversion_from_to_long_double(); #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION void test_traits(); void test_wtraits(); @@ -128,9 +125,6 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) suite->add(BOOST_TEST_CASE(&test_conversion_from_to_longlong)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulonglong)); #endif - suite->add(BOOST_TEST_CASE(&test_conversion_from_to_float)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_to_double)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_to_long_double)); #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION suite->add(BOOST_TEST_CASE(&test_traits)); suite->add(BOOST_TEST_CASE(&test_wtraits)); @@ -679,7 +673,7 @@ void test_conversion_from_to_integral_for_locale() BOOST_CHECK_THROW(lexical_cast( np.thousands_sep() + std::string("100") ), bad_lexical_cast); // Exception must not be thrown, when we are using no separators at all - BOOST_CHECK( lexical_cast("10000") == static_cast(10000) ); + BOOST_CHECK( lexical_cast("30000") == static_cast(30000) ); } test_conversion_from_integral_to_integral(); @@ -775,35 +769,6 @@ void test_conversion_from_to_integral() BOOST_TEST_MESSAGE("Formatting with thousands_sep has not been tested"); } -template -void test_conversion_from_to_float() -{ - char const zero = '0'; - signed char const szero = '0'; - unsigned char const uzero = '0'; - test_conversion_from_integral_to_char(zero); - test_conversion_from_char_to_integral(zero); - test_conversion_from_integral_to_char(szero); - test_conversion_from_char_to_integral(szero); - test_conversion_from_integral_to_char(uzero); - test_conversion_from_char_to_integral(uzero); -#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) - wchar_t const wzero = L'0'; - test_conversion_from_integral_to_char(wzero); - test_conversion_from_char_to_integral(wzero); -#endif - - test_conversion_from_integral_to_integral(); - - 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() { test_conversion_from_to_integral(); @@ -844,19 +809,6 @@ void test_conversion_from_to_uintmax_t() test_conversion_from_to_integral(); } -void test_conversion_from_to_float() -{ - test_conversion_from_to_float(); -} -void test_conversion_from_to_double() -{ - test_conversion_from_to_float(); -} -void test_conversion_from_to_long_double() -{ - test_conversion_from_to_float(); -} - #if defined(BOOST_HAS_LONG_LONG) void test_conversion_from_to_longlong() @@ -966,16 +918,25 @@ void test_char_types_conversions() 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(wc_arr[0]) == wc_arr[0]); + + // Following tests depend on realization of std::locale. + // All we need to know, is that this functions must compile + BOOST_CHECK(boost::lexical_cast(c_arr[0]) == wc_arr[0]); 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 } + + + + + + + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 1fea2fb..9517c63 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -25,6 +25,8 @@ test-suite conversion [ run lexical_cast_abstract_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_noncopyable_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_vc8_bug_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run lexical_cast_wchars_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run lexical_cast_float_types_test.cpp ../../test/build//boost_unit_test_framework/static ] ; diff --git a/test/lexical_cast_float_types_test.cpp b/test/lexical_cast_float_types_test.cpp new file mode 100755 index 0000000..442ed3b --- /dev/null +++ b/test/lexical_cast_float_types_test.cpp @@ -0,0 +1,527 @@ +// Unit test for boost::lexical_cast. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Antony Polukhin, 2011. +// +// 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 + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include + +#include +#include +#include + +void test_conversion_from_to_float(); +void test_conversion_from_to_double(); +void test_conversion_from_to_long_double(); + +using namespace boost; + + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test_framework::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast float types unit test"); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_float)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_double)); + suite->add(BOOST_TEST_CASE(&test_conversion_from_to_long_double)); + + return suite; +} + + +// Replace "-,999" with "-999". +template +std::basic_string to_str_gcc_workaround(std::basic_string str) +{ + std::locale loc; + std::numpunct const& np = BOOST_USE_FACET(std::numpunct, loc); + std::ctype const& ct = BOOST_USE_FACET(std::ctype, loc); + + if(np.grouping().empty()) + return str; + + CharT prefix[3] = { ct.widen('-'), np.thousands_sep(), CharT() }; + + if(str.find(prefix) != 0) + return str; + + prefix[1] = CharT(); + str.replace(0, 2, prefix); + return str; +} + +template +std::basic_string to_str(T t) +{ + std::basic_ostringstream o; + o << t; + return to_str_gcc_workaround(o.str()); +} + + +template +void test_conversion_from_to_float_for_locale() +{ + std::locale current_locale; + typedef std::numpunct numpunct; + numpunct const& np = BOOST_USE_FACET(numpunct, current_locale); + if ( !np.grouping().empty() ) + { + BOOST_CHECK_THROW( + lexical_cast( std::string("100") + np.thousands_sep() + np.thousands_sep() + "0" ) + , bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast( std::string("100") + np.thousands_sep() ), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast( np.thousands_sep() + std::string("100") ), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast( std::string("1") + np.thousands_sep() + np.decimal_point() + "e10" ), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast( std::string("1e10") + np.thousands_sep() ), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast( std::string("1") + np.thousands_sep() + "e10" ), bad_lexical_cast); + + BOOST_CHECK_CLOSE(lexical_cast( to_str< char >(100000) ), 100000, (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE(lexical_cast( to_str< char >(10000000u) ), 10000000u, (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE(lexical_cast( to_str< char >(100) ), 100, (std::numeric_limits::epsilon()*100) ); +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) + BOOST_CHECK_CLOSE(lexical_cast( to_str< wchar_t >(100000) ), 100000, (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE(lexical_cast( to_str< wchar_t >(10000000u) ), 10000000u, (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE(lexical_cast( to_str< wchar_t >(100) ), 100, (std::numeric_limits::epsilon()*100) ); +#endif + // Exception must not be thrown, when we are using no separators at all + BOOST_CHECK_CLOSE( lexical_cast("30000"), static_cast(30000), (std::numeric_limits::epsilon()*100) ); + } +} + + + + +/* + * Converts char* [and wchar_t] to float number type and checks, that generated + * number is in interval [base_value-epsilon, base_value+epsilon]. + */ +#ifndef BOOST_LCAST_NO_WCHAR_T +#define CHECK_CLOSE_ABS_DIFF(VAL,PREFIX) \ + converted_val = lexical_cast(#VAL); \ + BOOST_CHECK_CLOSE( (VAL ## L? VAL ## L : std::numeric_limits::epsilon()), \ + (converted_val ? converted_val : std::numeric_limits::epsilon()), \ + std::numeric_limits::epsilon() * 100 \ + ); \ + BOOST_CHECK_EQUAL(converted_val, lexical_cast(L## #VAL) ); + +#else +#define CHECK_CLOSE_ABS_DIFF(VAL,TYPE) \ + converted_val = lexical_cast(#VAL); \ + BOOST_CHECK_CLOSE( (VAL ## L? VAL ## L : std::numeric_limits::epsilon()), \ + (converted_val ? converted_val : std::numeric_limits::epsilon()), \ + std::numeric_limits::epsilon() * 100 \ + ); +#endif + +template +void test_converion_to_float_types() +{ + typedef TestType test_t; + test_t converted_val; + + BOOST_CHECK_CLOSE(1.0, lexical_cast('1'), (std::numeric_limits::epsilon())); + BOOST_CHECK_EQUAL(0.0, lexical_cast('0')); + + unsigned char const uc_one = '1'; + unsigned char const uc_zero ='0'; + BOOST_CHECK_CLOSE(1.0, lexical_cast(uc_one), (std::numeric_limits::epsilon())); + BOOST_CHECK_EQUAL(0.0, lexical_cast(uc_zero)); + + signed char const sc_one = '1'; + signed char const sc_zero ='0'; + BOOST_CHECK_CLOSE(1.0, lexical_cast(sc_one), (std::numeric_limits::epsilon())); + BOOST_CHECK_EQUAL(0.0, lexical_cast(sc_zero)); + + BOOST_CHECK_CLOSE(1e34L, lexical_cast( "10000000000000000000000000000000000"), (std::numeric_limits::epsilon()*100) ); + +// VC failes the next test +// BOOST_CHECK_CLOSE(1e-35L, lexical_cast("0.00000000000000000000000000000000001"), (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE( + 0.1111111111111111111111111111111111111111111111111111111111111111111111111L + , lexical_cast("0.1111111111111111111111111111111111111111111111111111111111111111111111111") + , (std::numeric_limits::epsilon()*100) ); + + CHECK_CLOSE_ABS_DIFF(1,test_t); + BOOST_CHECK_EQUAL(0,lexical_cast("0")); + CHECK_CLOSE_ABS_DIFF(-1,test_t); + + CHECK_CLOSE_ABS_DIFF(1.0, test_t); + CHECK_CLOSE_ABS_DIFF(0.0, test_t); + CHECK_CLOSE_ABS_DIFF(-1.0,test_t); + + CHECK_CLOSE_ABS_DIFF(1e1, test_t); + CHECK_CLOSE_ABS_DIFF(0e1, test_t); + CHECK_CLOSE_ABS_DIFF(-1e1,test_t); + + CHECK_CLOSE_ABS_DIFF(1.0e1, test_t); + CHECK_CLOSE_ABS_DIFF(0.0e1, test_t); + CHECK_CLOSE_ABS_DIFF(-1.0e1,test_t); + + CHECK_CLOSE_ABS_DIFF(1e-1, test_t); + CHECK_CLOSE_ABS_DIFF(0e-1, test_t); + CHECK_CLOSE_ABS_DIFF(-1e-1,test_t); + + CHECK_CLOSE_ABS_DIFF(1.0e-1, test_t); + CHECK_CLOSE_ABS_DIFF(0.0e-1, test_t); + CHECK_CLOSE_ABS_DIFF(-1.0e-1,test_t); + + CHECK_CLOSE_ABS_DIFF(1E1, test_t); + CHECK_CLOSE_ABS_DIFF(0E1, test_t); + CHECK_CLOSE_ABS_DIFF(-1E1,test_t); + + CHECK_CLOSE_ABS_DIFF(1.0E1, test_t); + CHECK_CLOSE_ABS_DIFF(0.0E1, test_t); + CHECK_CLOSE_ABS_DIFF(-1.0E1,test_t); + + CHECK_CLOSE_ABS_DIFF(1E-1, test_t); + CHECK_CLOSE_ABS_DIFF(0E-1, test_t); + CHECK_CLOSE_ABS_DIFF(-1E-1,test_t); + + CHECK_CLOSE_ABS_DIFF(1.0E-1, test_t); + CHECK_CLOSE_ABS_DIFF(0.0E-1, test_t); + CHECK_CLOSE_ABS_DIFF(-1.0E-1, test_t); + + + + CHECK_CLOSE_ABS_DIFF(10.0, test_t); + CHECK_CLOSE_ABS_DIFF(00.0, test_t); + CHECK_CLOSE_ABS_DIFF(-10.0,test_t); + + CHECK_CLOSE_ABS_DIFF(10e1, test_t); + CHECK_CLOSE_ABS_DIFF(00e1, test_t); + CHECK_CLOSE_ABS_DIFF(-10e1,test_t); + + CHECK_CLOSE_ABS_DIFF(10.0e1, test_t); + CHECK_CLOSE_ABS_DIFF(00.0e1, test_t); + CHECK_CLOSE_ABS_DIFF(-10.0e1,test_t); + + CHECK_CLOSE_ABS_DIFF(10e-1, test_t); + CHECK_CLOSE_ABS_DIFF(00e-1, test_t); + CHECK_CLOSE_ABS_DIFF(-10e-1,test_t); + + CHECK_CLOSE_ABS_DIFF(10.0e-1, test_t); + CHECK_CLOSE_ABS_DIFF(00.0e-1, test_t); + CHECK_CLOSE_ABS_DIFF(-10.0e-1,test_t); + + CHECK_CLOSE_ABS_DIFF(10E1, test_t); + CHECK_CLOSE_ABS_DIFF(00E1, test_t); + CHECK_CLOSE_ABS_DIFF(-10E1,test_t); + + CHECK_CLOSE_ABS_DIFF(10.0E1, test_t); + CHECK_CLOSE_ABS_DIFF(00.0E1, test_t); + CHECK_CLOSE_ABS_DIFF(-10.0E1,test_t); + + CHECK_CLOSE_ABS_DIFF(10E-1, test_t); + CHECK_CLOSE_ABS_DIFF(00E-1, test_t); + CHECK_CLOSE_ABS_DIFF(-10E-1,test_t); + + CHECK_CLOSE_ABS_DIFF(10.0E-1, test_t); + CHECK_CLOSE_ABS_DIFF(00.0E-1, test_t); + CHECK_CLOSE_ABS_DIFF(-10.0E-1, test_t); + + CHECK_CLOSE_ABS_DIFF(-10101.0E-011, test_t); + CHECK_CLOSE_ABS_DIFF(-10101093, test_t); + CHECK_CLOSE_ABS_DIFF(10101093, test_t); + +// BOOST_CHECK(lexical_cast("-inf") == -std::numeric_limits::infinity() ); +// BOOST_CHECK(lexical_cast("-INF") == -std::numeric_limits::infinity() ); +// BOOST_CHECK(lexical_cast("+inf") == std::numeric_limits::infinity() ); +// BOOST_CHECK(lexical_cast("infinity") == std::numeric_limits::infinity() ); +// +// BOOST_CHECK(lexical_cast("nan") == std::numeric_limits::quiet_NaN() ); +// BOOST_CHECK(lexical_cast("NaN") == std::numeric_limits::quiet_NaN() ); + + BOOST_CHECK_THROW(lexical_cast("-inf"), bad_lexical_cast ); + BOOST_CHECK_THROW(lexical_cast("-INF"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("+inf"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("infinity"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("nan"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("NaN"), bad_lexical_cast); + + + BOOST_CHECK_THROW(lexical_cast("-1.e"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("-1.E"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("1.e"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("1.E"), bad_lexical_cast); + + BOOST_CHECK_THROW(lexical_cast("1.0e"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("1.0E"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("10E"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("10e"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("1.0e-"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("1.0E-"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("10E-"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("10e-"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("e1"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("e-1"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("e-"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(".e"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(".11111111111111111111111111111111111111111111111111111111111111111111ee"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(".11111111111111111111111111111111111111111111111111111111111111111111e-"), bad_lexical_cast); + + BOOST_CHECK_THROW(lexical_cast("-B"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("0xB"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("0x0"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("--1.0"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("1.0e--1"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("1.0.0"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("1e1e1"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("1.0e-1e-1"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(" 1.0"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("1.0 "), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(""), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("-"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast('\0'), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast('-'), bad_lexical_cast); +} + +template +void test_float_typess_for_overflows() +{ + typedef T test_t; + test_t minvalue = (std::numeric_limits::min)(); + std::string s_min_value = lexical_cast(minvalue); + BOOST_CHECK_CLOSE(minvalue, lexical_cast(minvalue), (std::numeric_limits::epsilon()*100)); + BOOST_CHECK_CLOSE(minvalue, lexical_cast(s_min_value), (std::numeric_limits::epsilon()*100)); + + test_t maxvalue = (std::numeric_limits::max)(); + std::string s_max_value = lexical_cast(maxvalue); + BOOST_CHECK_CLOSE(maxvalue, lexical_cast(maxvalue), (std::numeric_limits::epsilon()*100)); + BOOST_CHECK_CLOSE(maxvalue, lexical_cast(s_max_value), (std::numeric_limits::epsilon()*100)); + + BOOST_CHECK_THROW(lexical_cast(s_max_value+"1"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(s_max_value+"9"), bad_lexical_cast); + + // VC9 can fail the fllowing tests on floats and doubles when using stingstream... + BOOST_CHECK_THROW(lexical_cast("1"+s_max_value), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("9"+s_max_value), bad_lexical_cast); + + if ( is_same::value ) + { + BOOST_CHECK_THROW(lexical_cast( (std::numeric_limits::max)() ), bad_lexical_cast); + BOOST_CHECK( + (std::numeric_limits::min)() - std::numeric_limits::epsilon() + <= lexical_cast( (std::numeric_limits::min)() ) + && lexical_cast( (std::numeric_limits::min)() ) + <= (std::numeric_limits::min)() + std::numeric_limits::epsilon() + ); + } + + if ( sizeof(test_t) < sizeof(long double) ) + { + BOOST_CHECK_THROW(lexical_cast( (std::numeric_limits::max)() ), bad_lexical_cast); + BOOST_CHECK( + (std::numeric_limits::min)() - std::numeric_limits::epsilon() + <= lexical_cast( (std::numeric_limits::min)() ) + && lexical_cast( (std::numeric_limits::min)() ) + <= (std::numeric_limits::min)() + std::numeric_limits::epsilon() + ); + } +} + +#undef CHECK_CLOSE_ABS_DIFF + +#define TEST_TO_FROM_CAST_AROUND_TYPED(VAL,STRING_TYPE) \ + test_value = VAL + std::numeric_limits::epsilon() * i ; \ + converted_val = lexical_cast( lexical_cast(test_value) ); \ + BOOST_CHECK_CLOSE( \ + test_value, \ + converted_val, \ + std::numeric_limits::epsilon()*100 \ + ); + +/* + * For interval [ from_mult*epsilon+VAL, to_mult*epsilon+VAL ], converts float type + * numbers to string[wstring] and then back to float type, then compares initial + * values and generated. + * Step is epsilon + */ +#ifndef BOOST_LCAST_NO_WCHAR_T +# define TEST_TO_FROM_CAST_AROUND(VAL) \ + for(i=from_mult; i<=to_mult; ++i) { \ + TEST_TO_FROM_CAST_AROUND_TYPED(VAL, std::string) \ + TEST_TO_FROM_CAST_AROUND_TYPED(VAL, std::wstring) \ + } +#else +# define TEST_TO_FROM_CAST_AROUND(VAL) \ + for(i=from_mult; i<=to_mult; ++i) { \ + TEST_TO_FROM_CAST_AROUND_TYPED(VAL, std::string) \ + } +#endif + +template +void test_converion_from_to_float_types() +{ + typedef TestType test_t; + test_t test_value; + test_t converted_val; + + int i; + int from_mult = -50; + int to_mult = 50; + + TEST_TO_FROM_CAST_AROUND( 0.0 ); + +// TEST_TO_FROM_CAST_AROUND( std::numeric_limits::infinity() ); +// TEST_TO_FROM_CAST_AROUND( -std::numeric_limits::infinity() ); +// TEST_TO_FROM_CAST_AROUND( std::numeric_limits::quiet_NaN() ); + + long double val1; + for(val1 = 1.0e-10L; val1 < 1e11; val1*=10 ) + TEST_TO_FROM_CAST_AROUND( val1 ); + + long double val2; + for(val2 = -1.0e-10L; val2 > -1e11; val2*=10 ) + TEST_TO_FROM_CAST_AROUND( val2 ); + + from_mult = -100; + to_mult = 0; + TEST_TO_FROM_CAST_AROUND( (std::numeric_limits::max)() ); + + from_mult = 0; + to_mult = 100; + TEST_TO_FROM_CAST_AROUND( (std::numeric_limits::min)() ); +} + +#undef TEST_TO_FROM_CAST_AROUND +#undef TEST_TO_FROM_CAST_AROUND_TYPED + + +template +void test_conversion_from_float_to_char(CharT zero) +{ + BOOST_CHECK(lexical_cast(static_cast(0)) == zero + 0); + BOOST_CHECK(lexical_cast(static_cast(1)) == zero + 1); + BOOST_CHECK(lexical_cast(static_cast(2)) == zero + 2); + BOOST_CHECK(lexical_cast(static_cast(3)) == zero + 3); + BOOST_CHECK(lexical_cast(static_cast(4)) == zero + 4); + BOOST_CHECK(lexical_cast(static_cast(5)) == zero + 5); + BOOST_CHECK(lexical_cast(static_cast(6)) == zero + 6); + BOOST_CHECK(lexical_cast(static_cast(7)) == zero + 7); + BOOST_CHECK(lexical_cast(static_cast(8)) == zero + 8); + BOOST_CHECK(lexical_cast(static_cast(9)) == zero + 9); + + BOOST_CHECK_THROW(lexical_cast(static_cast(10)), bad_lexical_cast); + + T t = (std::numeric_limits::max)(); + BOOST_CHECK_THROW(lexical_cast(t), bad_lexical_cast); +} + +template +void test_conversion_from_char_to_float(CharT zero) +{ + BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 0)), static_cast(0), (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 1)), static_cast(1), (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 2)), static_cast(2), (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 3)), static_cast(3), (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 4)), static_cast(4), (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 5)), static_cast(5), (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 6)), static_cast(6), (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 7)), static_cast(7), (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 8)), static_cast(8), (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 9)), static_cast(9), (std::numeric_limits::epsilon()*100) ); + + BOOST_CHECK_THROW(lexical_cast( static_cast(zero + 10)), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast( static_cast(zero - 1)), bad_lexical_cast); +} + +struct restore_oldloc +{ + std::locale oldloc; + ~restore_oldloc() { std::locale::global(oldloc); } +}; + +template +void test_conversion_from_to_float() +{ char const zero = '0'; + signed char const szero = '0'; + unsigned char const uzero = '0'; + test_conversion_from_float_to_char(zero); + test_conversion_from_char_to_float(zero); + test_conversion_from_float_to_char(szero); + test_conversion_from_char_to_float(szero); + test_conversion_from_float_to_char(uzero); + test_conversion_from_char_to_float(uzero); + #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) + wchar_t const wzero = L'0'; + test_conversion_from_float_to_char(wzero); + test_conversion_from_char_to_float(wzero); + #endif + + 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); + + test_converion_to_float_types(); + test_float_typess_for_overflows(); + test_converion_from_to_float_types(); + + + typedef std::numpunct numpunct; + + restore_oldloc guard; + std::locale const& oldloc = guard.oldloc; + + std::string grouping1 = BOOST_USE_FACET(numpunct, oldloc).grouping(); + std::string grouping2(grouping1); + + test_conversion_from_to_float_for_locale(); + + try + { + std::locale newloc(""); + std::locale::global(newloc); + + grouping2 = BOOST_USE_FACET(numpunct, newloc).grouping(); + } + catch(std::exception const& ex) + { + std::string msg("Failed to set system locale: "); + msg += ex.what(); + BOOST_TEST_MESSAGE(msg); + } + + if(grouping1 != grouping2) + test_conversion_from_to_float_for_locale(); + + if(grouping1.empty() && grouping2.empty()) + BOOST_TEST_MESSAGE("Formatting with thousands_sep has not been tested"); +} + + +void test_conversion_from_to_float() +{ + test_conversion_from_to_float(); +} +void test_conversion_from_to_double() +{ + test_conversion_from_to_float(); +} +void test_conversion_from_to_long_double() +{ + test_conversion_from_to_float(); +} + + + + + + + diff --git a/test/lexical_cast_loopback_test.cpp b/test/lexical_cast_loopback_test.cpp index cd058fe..5787996 100644 --- a/test/lexical_cast_loopback_test.cpp +++ b/test/lexical_cast_loopback_test.cpp @@ -64,7 +64,6 @@ void test_round_conversion() } -#if defined(BOOST_MSVC) // See bug http://tinyurl.com/vhpvo template void test_msvc_magic_values() @@ -73,7 +72,6 @@ void test_msvc_magic_values() std::string magic_msvc_s = boost::lexical_cast(magic_msvc); BOOST_CHECK(magic_msvc == lexical_cast(magic_msvc_s)); } -#endif void test_round_conversion_float() { @@ -83,16 +81,12 @@ void test_round_conversion_float() void test_round_conversion_double() { test_round_conversion(); -#if defined(BOOST_MSVC) test_msvc_magic_values(); -#endif } void test_round_conversion_long_double() { test_round_conversion(); -#if defined(BOOST_MSVC) test_msvc_magic_values(); -#endif } diff --git a/test/lexical_cast_wchars_test.cpp b/test/lexical_cast_wchars_test.cpp new file mode 100755 index 0000000..547f226 --- /dev/null +++ b/test/lexical_cast_wchars_test.cpp @@ -0,0 +1,56 @@ +// Unit test for boost::lexical_cast. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Antony Polukhin, 2011. +// +// 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 + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include + +#include +#include +#include + +using namespace boost; + +void test_char_types_conversions() +{ +#ifndef BOOST_LCAST_NO_WCHAR_T + 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"; + const wchar_t wc_arr[] =L"Test array of chars"; + + // Following tests depend on realization of std::locale + // and pass for popular compilers and STL realizations + BOOST_CHECK(boost::lexical_cast(c_arr[0]) == wc_arr[0]); + 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_THROW(boost::lexical_cast(uc_arr[0]), boost::bad_lexical_cast); + BOOST_CHECK_THROW(boost::lexical_cast(sc_arr[0]), boost::bad_lexical_cast); +#endif + BOOST_CHECK(1); +} + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test_framework::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast char<->wchar_t unit test"); + suite->add(BOOST_TEST_CASE(&test_char_types_conversions)); + + return suite; +} From 0e2235dc75a588e60e22859e683ab177d480e2eb Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 7 Jul 2011 11:31:25 +0000 Subject: [PATCH 092/242] Fixes #5675. Adds tests on #5675. Updates #5660. Updates performance section of documentation [SVN r72954] --- include/boost/lexical_cast.hpp | 14 ++++++++------ lexical_cast.htm | 2 +- test/lexical_cast_float_types_test.cpp | 8 +++++++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index d9b73af..044354f 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -798,12 +798,8 @@ namespace boost if (begin == end) return false; } - if ( *begin < czero || *begin >= czero + 10 ) { - return false; - } - - bool found_decimal = false; + bool found_number_before_exp = false; int pow_of_10 = 0; mantissa_type mantissa=0; bool is_mantissa_full = false; @@ -830,6 +826,8 @@ namespace boost -- pow_of_10; mantissa = tmp_mantissa; mantissa += *begin - zero; + + found_number_before_exp = true; } else { if (*begin >= czero && *begin < czero + 10) { @@ -851,6 +849,7 @@ namespace boost ++ pow_of_10; } + found_number_before_exp = true; ++ length_since_last_delim; } else if ( *begin == decimal_point || *begin == lowercase_e || *begin == capital_e) { #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE @@ -874,7 +873,10 @@ namespace boost ++ begin; found_decimal = true; continue; - }else break; + }else { + if (!found_number_before_exp) return false; + break; + } } #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE else if (grouping_size && *begin == thousands_sep){ diff --git a/lexical_cast.htm b/lexical_cast.htm index 7a1fee5..2079a0f 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -331,7 +331,7 @@ This table shows the execution time in milliseconds for 100000 calls of the foll
      - + diff --git a/test/lexical_cast_float_types_test.cpp b/test/lexical_cast_float_types_test.cpp index 442ed3b..66f6d67 100755 --- a/test/lexical_cast_float_types_test.cpp +++ b/test/lexical_cast_float_types_test.cpp @@ -194,7 +194,9 @@ void test_converion_to_float_types() CHECK_CLOSE_ABS_DIFF(0.0E-1, test_t); CHECK_CLOSE_ABS_DIFF(-1.0E-1, test_t); - + CHECK_CLOSE_ABS_DIFF(.0E-1, test_t); + CHECK_CLOSE_ABS_DIFF(.0E-1, test_t); + CHECK_CLOSE_ABS_DIFF(-.0E-1, test_t); CHECK_CLOSE_ABS_DIFF(10.0, test_t); CHECK_CLOSE_ABS_DIFF(00.0, test_t); @@ -235,6 +237,10 @@ void test_converion_to_float_types() CHECK_CLOSE_ABS_DIFF(-10101.0E-011, test_t); CHECK_CLOSE_ABS_DIFF(-10101093, test_t); CHECK_CLOSE_ABS_DIFF(10101093, test_t); + + CHECK_CLOSE_ABS_DIFF(-.34, test_t); + CHECK_CLOSE_ABS_DIFF(.34, test_t); + CHECK_CLOSE_ABS_DIFF(.34e10, test_t); // BOOST_CHECK(lexical_cast("-inf") == -std::numeric_limits::infinity() ); // BOOST_CHECK(lexical_cast("-INF") == -std::numeric_limits::infinity() ); From fff0066392bfbb4cebb6f1366ea301e7bc74ae15 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 7 Jul 2011 16:04:32 +0000 Subject: [PATCH 093/242] Fixes #5676. Tests for float types are now more accurate [SVN r72955] --- lexical_cast_test.cpp | 17 +++--- test/lexical_cast_float_types_test.cpp | 72 +++++++++++++------------- 2 files changed, 45 insertions(+), 44 deletions(-) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index cdf42fe..62449ea 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -197,17 +197,18 @@ void test_conversion_to_int() void test_conversion_to_double() { - BOOST_CHECK_CLOSE(1.0, lexical_cast('1'), (std::numeric_limits::epsilon())); + BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast('1'), (std::numeric_limits::epsilon())); BOOST_CHECK_THROW(lexical_cast('A'), bad_lexical_cast); - BOOST_CHECK_CLOSE(1.0, lexical_cast(1), (std::numeric_limits::epsilon())); - BOOST_CHECK_CLOSE(1.23, lexical_cast(1.23), (std::numeric_limits::epsilon())); - BOOST_CHECK_CLOSE(1.234567890, 1.234567890, std::numeric_limits::epsilon()); - BOOST_CHECK_CLOSE(1.0, lexical_cast(true), (std::numeric_limits::epsilon())); - BOOST_CHECK_CLOSE(0.0, lexical_cast(false), (std::numeric_limits::epsilon())); - BOOST_CHECK_CLOSE(1.23, lexical_cast("1.23"), (std::numeric_limits::epsilon())); + BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast(1), (std::numeric_limits::epsilon())); + BOOST_CHECK_CLOSE_FRACTION(1.23, lexical_cast(1.23), (std::numeric_limits::epsilon())); + BOOST_CHECK_CLOSE_FRACTION(1.234567890, lexical_cast(1.234567890), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE_FRACTION(1.234567890, lexical_cast("1.234567890"), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast(true), (std::numeric_limits::epsilon())); + BOOST_CHECK_CLOSE_FRACTION(0.0, lexical_cast(false), (std::numeric_limits::epsilon())); + BOOST_CHECK_CLOSE_FRACTION(1.23, lexical_cast("1.23"), (std::numeric_limits::epsilon())); BOOST_CHECK_THROW(lexical_cast(""), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast("Test"), bad_lexical_cast); - BOOST_CHECK_CLOSE(1.23, lexical_cast(std::string("1.23")), (std::numeric_limits::epsilon())); + BOOST_CHECK_CLOSE_FRACTION(1.23, lexical_cast(std::string("1.23")), (std::numeric_limits::epsilon())); BOOST_CHECK_THROW( lexical_cast(std::string("")), bad_lexical_cast); BOOST_CHECK_THROW( diff --git a/test/lexical_cast_float_types_test.cpp b/test/lexical_cast_float_types_test.cpp index 66f6d67..10074d4 100755 --- a/test/lexical_cast_float_types_test.cpp +++ b/test/lexical_cast_float_types_test.cpp @@ -88,16 +88,16 @@ void test_conversion_from_to_float_for_locale() BOOST_CHECK_THROW(lexical_cast( std::string("1e10") + np.thousands_sep() ), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast( std::string("1") + np.thousands_sep() + "e10" ), bad_lexical_cast); - BOOST_CHECK_CLOSE(lexical_cast( to_str< char >(100000) ), 100000, (std::numeric_limits::epsilon()*100) ); - BOOST_CHECK_CLOSE(lexical_cast( to_str< char >(10000000u) ), 10000000u, (std::numeric_limits::epsilon()*100) ); - BOOST_CHECK_CLOSE(lexical_cast( to_str< char >(100) ), 100, (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( to_str< char >(100000) ), 100000, (std::numeric_limits::epsilon()) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( to_str< char >(10000000u) ), 10000000u, (std::numeric_limits::epsilon()) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( to_str< char >(100) ), 100, (std::numeric_limits::epsilon()) ); #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) - BOOST_CHECK_CLOSE(lexical_cast( to_str< wchar_t >(100000) ), 100000, (std::numeric_limits::epsilon()*100) ); - BOOST_CHECK_CLOSE(lexical_cast( to_str< wchar_t >(10000000u) ), 10000000u, (std::numeric_limits::epsilon()*100) ); - BOOST_CHECK_CLOSE(lexical_cast( to_str< wchar_t >(100) ), 100, (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( to_str< wchar_t >(100000) ), 100000, (std::numeric_limits::epsilon()) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( to_str< wchar_t >(10000000u) ), 10000000u, (std::numeric_limits::epsilon()) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( to_str< wchar_t >(100) ), 100, (std::numeric_limits::epsilon()) ); #endif // Exception must not be thrown, when we are using no separators at all - BOOST_CHECK_CLOSE( lexical_cast("30000"), static_cast(30000), (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE_FRACTION( lexical_cast("30000"), static_cast(30000), (std::numeric_limits::epsilon()) ); } } @@ -111,18 +111,18 @@ void test_conversion_from_to_float_for_locale() #ifndef BOOST_LCAST_NO_WCHAR_T #define CHECK_CLOSE_ABS_DIFF(VAL,PREFIX) \ converted_val = lexical_cast(#VAL); \ - BOOST_CHECK_CLOSE( (VAL ## L? VAL ## L : std::numeric_limits::epsilon()), \ + BOOST_CHECK_CLOSE_FRACTION( (VAL ## L? VAL ## L : std::numeric_limits::epsilon()), \ (converted_val ? converted_val : std::numeric_limits::epsilon()), \ - std::numeric_limits::epsilon() * 100 \ + std::numeric_limits::epsilon() \ ); \ BOOST_CHECK_EQUAL(converted_val, lexical_cast(L## #VAL) ); #else #define CHECK_CLOSE_ABS_DIFF(VAL,TYPE) \ converted_val = lexical_cast(#VAL); \ - BOOST_CHECK_CLOSE( (VAL ## L? VAL ## L : std::numeric_limits::epsilon()), \ + BOOST_CHECK_CLOSE_FRACTION( (VAL ## L? VAL ## L : std::numeric_limits::epsilon()), \ (converted_val ? converted_val : std::numeric_limits::epsilon()), \ - std::numeric_limits::epsilon() * 100 \ + std::numeric_limits::epsilon() \ ); #endif @@ -132,27 +132,27 @@ void test_converion_to_float_types() typedef TestType test_t; test_t converted_val; - BOOST_CHECK_CLOSE(1.0, lexical_cast('1'), (std::numeric_limits::epsilon())); + BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast('1'), (std::numeric_limits::epsilon())); BOOST_CHECK_EQUAL(0.0, lexical_cast('0')); unsigned char const uc_one = '1'; unsigned char const uc_zero ='0'; - BOOST_CHECK_CLOSE(1.0, lexical_cast(uc_one), (std::numeric_limits::epsilon())); + BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast(uc_one), (std::numeric_limits::epsilon())); BOOST_CHECK_EQUAL(0.0, lexical_cast(uc_zero)); signed char const sc_one = '1'; signed char const sc_zero ='0'; - BOOST_CHECK_CLOSE(1.0, lexical_cast(sc_one), (std::numeric_limits::epsilon())); + BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast(sc_one), (std::numeric_limits::epsilon())); BOOST_CHECK_EQUAL(0.0, lexical_cast(sc_zero)); - BOOST_CHECK_CLOSE(1e34L, lexical_cast( "10000000000000000000000000000000000"), (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE_FRACTION(1e34L, lexical_cast( "10000000000000000000000000000000000"), (std::numeric_limits::epsilon()) ); // VC failes the next test -// BOOST_CHECK_CLOSE(1e-35L, lexical_cast("0.00000000000000000000000000000000001"), (std::numeric_limits::epsilon()*100) ); - BOOST_CHECK_CLOSE( +// BOOST_CHECK_CLOSE_FRACTION(1e-35L, lexical_cast("0.00000000000000000000000000000000001"), (std::numeric_limits::epsilon()) ); + BOOST_CHECK_CLOSE_FRACTION( 0.1111111111111111111111111111111111111111111111111111111111111111111111111L , lexical_cast("0.1111111111111111111111111111111111111111111111111111111111111111111111111") - , (std::numeric_limits::epsilon()*100) ); + , (std::numeric_limits::epsilon()) ); CHECK_CLOSE_ABS_DIFF(1,test_t); BOOST_CHECK_EQUAL(0,lexical_cast("0")); @@ -300,13 +300,13 @@ void test_float_typess_for_overflows() typedef T test_t; test_t minvalue = (std::numeric_limits::min)(); std::string s_min_value = lexical_cast(minvalue); - BOOST_CHECK_CLOSE(minvalue, lexical_cast(minvalue), (std::numeric_limits::epsilon()*100)); - BOOST_CHECK_CLOSE(minvalue, lexical_cast(s_min_value), (std::numeric_limits::epsilon()*100)); + BOOST_CHECK_CLOSE_FRACTION(minvalue, lexical_cast(minvalue), (std::numeric_limits::epsilon())); + BOOST_CHECK_CLOSE_FRACTION(minvalue, lexical_cast(s_min_value), (std::numeric_limits::epsilon())); test_t maxvalue = (std::numeric_limits::max)(); std::string s_max_value = lexical_cast(maxvalue); - BOOST_CHECK_CLOSE(maxvalue, lexical_cast(maxvalue), (std::numeric_limits::epsilon()*100)); - BOOST_CHECK_CLOSE(maxvalue, lexical_cast(s_max_value), (std::numeric_limits::epsilon()*100)); + BOOST_CHECK_CLOSE_FRACTION(maxvalue, lexical_cast(maxvalue), (std::numeric_limits::epsilon())); + BOOST_CHECK_CLOSE_FRACTION(maxvalue, lexical_cast(s_max_value), (std::numeric_limits::epsilon())); BOOST_CHECK_THROW(lexical_cast(s_max_value+"1"), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(s_max_value+"9"), bad_lexical_cast); @@ -343,10 +343,10 @@ void test_float_typess_for_overflows() #define TEST_TO_FROM_CAST_AROUND_TYPED(VAL,STRING_TYPE) \ test_value = VAL + std::numeric_limits::epsilon() * i ; \ converted_val = lexical_cast( lexical_cast(test_value) ); \ - BOOST_CHECK_CLOSE( \ + BOOST_CHECK_CLOSE_FRACTION( \ test_value, \ converted_val, \ - std::numeric_limits::epsilon()*100 \ + std::numeric_limits::epsilon() \ ); /* @@ -429,16 +429,16 @@ void test_conversion_from_float_to_char(CharT zero) template void test_conversion_from_char_to_float(CharT zero) { - BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 0)), static_cast(0), (std::numeric_limits::epsilon()*100) ); - BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 1)), static_cast(1), (std::numeric_limits::epsilon()*100) ); - BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 2)), static_cast(2), (std::numeric_limits::epsilon()*100) ); - BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 3)), static_cast(3), (std::numeric_limits::epsilon()*100) ); - BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 4)), static_cast(4), (std::numeric_limits::epsilon()*100) ); - BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 5)), static_cast(5), (std::numeric_limits::epsilon()*100) ); - BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 6)), static_cast(6), (std::numeric_limits::epsilon()*100) ); - BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 7)), static_cast(7), (std::numeric_limits::epsilon()*100) ); - BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 8)), static_cast(8), (std::numeric_limits::epsilon()*100) ); - BOOST_CHECK_CLOSE(lexical_cast( static_cast(zero + 9)), static_cast(9), (std::numeric_limits::epsilon()*100) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( static_cast(zero + 0)), static_cast(0), (std::numeric_limits::epsilon()) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( static_cast(zero + 1)), static_cast(1), (std::numeric_limits::epsilon()) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( static_cast(zero + 2)), static_cast(2), (std::numeric_limits::epsilon()) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( static_cast(zero + 3)), static_cast(3), (std::numeric_limits::epsilon()) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( static_cast(zero + 4)), static_cast(4), (std::numeric_limits::epsilon()) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( static_cast(zero + 5)), static_cast(5), (std::numeric_limits::epsilon()) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( static_cast(zero + 6)), static_cast(6), (std::numeric_limits::epsilon()) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( static_cast(zero + 7)), static_cast(7), (std::numeric_limits::epsilon()) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( static_cast(zero + 8)), static_cast(8), (std::numeric_limits::epsilon()) ); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast( static_cast(zero + 9)), static_cast(9), (std::numeric_limits::epsilon()) ); BOOST_CHECK_THROW(lexical_cast( static_cast(zero + 10)), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast( static_cast(zero - 1)), bad_lexical_cast); @@ -467,8 +467,8 @@ void test_conversion_from_to_float() test_conversion_from_char_to_float(wzero); #endif - 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_CLOSE_FRACTION(lexical_cast("+1"), 1, std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE_FRACTION(lexical_cast("+9"), 9, std::numeric_limits::epsilon()); BOOST_CHECK_THROW(lexical_cast("++1"), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast("-+9"), bad_lexical_cast); From 27a7fac22ed34d464e274eb08141037101b5056e Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 8 Jul 2011 17:23:31 +0000 Subject: [PATCH 094/242] Updates #5660. Removed duplicate tests. Unified behaviour for float conversions on different compillers [SVN r72972] --- include/boost/lexical_cast.hpp | 51 ++++++++++++++++++++++++++++------ lexical_cast_test.cpp | 11 -------- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 044354f..4878b32 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1338,15 +1338,39 @@ namespace boost return lcast_ret_float(output,start,finish); } -#if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64) private: - // we need workaround - bool no_long_double_80bit_realization_workaround(double& output, int) { - return convert_using_base_class(output); + // Not optimised converter + template + bool float_types_converter_internal(T& output, int /*tag*/) { + bool return_value = convert_using_base_class(output); + + /* Some compilers and libraries successfully + * parse 'inf', 'INFINITY', '1.0E', '1.0E-'... + * We are trying to provide a unified behaviour, + * so we just forbid such conversions (as some + * of the most popular compilers/libraries do) + * */ + CharT const minus = lcast_char_constants::minus; + CharT const plus = lcast_char_constants::plus; + CharT const capital_e = lcast_char_constants::capital_e; + CharT const lowercase_e = lcast_char_constants::lowercase_e; + if ( return_value && + ( + output > (std::numeric_limits::max)() // +inf + || output < -(std::numeric_limits::max)() // -inf + || output != output // NaN + || *(finish-1) == lowercase_e // 1.0e + || *(finish-1) == capital_e // 1.0E + || *(finish-1) == minus // 1.0e- or 1.0E- + || *(finish-1) == plus // 1.0e+ or 1.0E+ + ) + ) return false; + + return return_value; } - // we do not need a workaround - bool no_long_double_80bit_realization_workaround(double& output,char) { + // Optimised converter + bool float_types_converter_internal(double& output,char /*tag*/) { return lcast_ret_float(output,start,finish); } public: @@ -1360,14 +1384,23 @@ namespace boost * double, because it will give a big precision loss. * */ boost::mpl::if_c< +#if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64) ::boost::type_traits::ice_eq< sizeof(double), sizeof(long double) >::value, +#else + 0 +#endif int, char - >::type dummy = 0; + >::type tag = 0; - return no_long_double_80bit_realization_workaround(output, dummy); + return float_types_converter_internal(output, tag); + } + + bool operator>>(long double& output) + { + int tag = 0; + return float_types_converter_internal(output, tag); } -#endif // Generic istream-based algorithm. // lcast_streambuf_for_target::value is true. diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 62449ea..afa16a6 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -921,17 +921,6 @@ void test_char_types_conversions() BOOST_CHECK(boost::lexical_cast(wc_arr) == std::wstring(wc_arr)); BOOST_CHECK(boost::lexical_cast(wc_arr[0]) == wc_arr[0]); - // Following tests depend on realization of std::locale. - // All we need to know, is that this functions must compile - BOOST_CHECK(boost::lexical_cast(c_arr[0]) == wc_arr[0]); - 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_THROW(boost::lexical_cast(uc_arr[0]), bad_lexical_cast); - BOOST_CHECK_THROW(boost::lexical_cast(sc_arr[0]), bad_lexical_cast); - #endif } From de3df54f809d6721a704eac29335feefbe7168a9 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 15 Jul 2011 11:20:11 +0000 Subject: [PATCH 095/242] Fixes #5689. Added code to work with Inf and NaN on any platform [SVN r73118] --- include/boost/lexical_cast.hpp | 144 ++++++++++++++++++++++++- lexical_cast.htm | 1 + lexical_cast_test.cpp | 4 + test/Jamfile.v2 | 1 + test/lexical_cast_float_types_test.cpp | 20 ---- test/lexical_cast_inf_nan_test.cpp | 109 +++++++++++++++++++ 6 files changed, 254 insertions(+), 25 deletions(-) create mode 100755 test/lexical_cast_inf_nan_test.cpp diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 4878b32..b4728f3 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -731,6 +732,136 @@ namespace boost } } + namespace detail + { + /* Returns true and sets the correct value if found NaN or Inf. */ + template + inline bool parse_inf_nan_impl(const CharT* begin, const CharT* end, T& value + , const CharT* lc_NAN, const CharT* lc_nan + , const CharT* lc_INFINITY, const CharT* lc_infinity + , const CharT opening_brace, const CharT closing_brace) + { + using namespace std; + const wchar_t minus = lcast_char_constants::minus; + const wchar_t plus = lcast_char_constants::plus; + const int inifinity_size = 8; + + bool has_minus = false; + /* Parsing +/- */ + if( *begin == minus) + { + ++ begin; + has_minus = true; + } + else if( *begin == plus ) ++begin; + + if( end-begin < 3 ) return false; + if( !memcmp(begin, lc_nan, 3*sizeof(CharT)) || !memcmp(begin, lc_NAN, 3*sizeof(CharT)) ) + { + begin += 3; + if (end != begin) /* It is 'nan(...)' or some bad input*/ + { + if(end-begin<2) return false; // bad input + -- end; + if( *begin != opening_brace || *end != closing_brace) return false; // bad input + } + + if( !has_minus ) value = std::numeric_limits::quiet_NaN(); + else value = -std::numeric_limits::quiet_NaN(); + return true; + } else + if (( /* 'INF' or 'inf' */ + end-begin==3 + && + (!memcmp(begin, lc_infinity, 3*sizeof(CharT)) || !memcmp(begin, lc_INFINITY, 3*sizeof(CharT))) + ) + || + ( /* 'INFINITY' or 'infinity' */ + end-begin==inifinity_size + && + (!memcmp(begin, lc_infinity, inifinity_size)|| !memcmp(begin, lc_INFINITY, inifinity_size)) + ) + ) + { + if( !has_minus ) value = std::numeric_limits::infinity(); + else value = -std::numeric_limits::infinity(); + return true; + } + + return false; + } + +#ifndef BOOST_LCAST_NO_WCHAR_T + template + bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value) + { + return parse_inf_nan_impl(begin, end, value + , L"NAN", L"nan" + , L"INFINITY", L"infinity" + , L'(', L')'); + } +#endif + + template + bool parse_inf_nan(const CharT* begin, const CharT* end, T& value) + { + return parse_inf_nan_impl(begin, end, value + , "NAN", "nan" + , "INFINITY", "infinity" + , '(', ')'); + } + + template + bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) + { + using namespace std; + if (value != value) + { + memcpy(begin,L"nan", sizeof(L"nan")); + end = begin + 3; + return true; + } else if ( value > numeric_limits::max() ) + { + memcpy(begin,L"inf", sizeof(L"inf")); + end = begin + 3; + return true; + } else if ( value < -numeric_limits::max() ) + { + memcpy(begin,L"-inf", sizeof(L"-inf")); + end = begin + 4; + return true; + } + + return false; + } + + template + bool put_inf_nan(CharT* begin, CharT*& end, const T& value) + { + using namespace std; + if (value != value) + { + memcpy(begin,"nan", sizeof("nan")); + end = begin + 3; + return true; + } else if ( value > numeric_limits::max() ) + { + memcpy(begin,"inf", sizeof("inf")); + end = begin + 3; + return true; + } else if ( value < -numeric_limits::max() ) + { + memcpy(begin,"-inf", sizeof("-inf")); + end = begin + 4; + return true; + } + + return false; + } + + } + + namespace detail // lcast_ret_float { template @@ -782,6 +913,8 @@ namespace boost value = 0.0; + if (parse_inf_nan(begin, end, value)) return true; + typedef typename Traits::int_type int_type; typedef BOOST_DEDUCED_TYPENAME mantissa_holder_type::type mantissa_type; int_type const zero = Traits::to_int_type(czero); @@ -1104,6 +1237,7 @@ namespace boost template bool lcast_put(const OutputStreamable& input) { + if(put_inf_nan(start, finish, input)) return true; this->setp(start, finish); std::basic_ostream stream(static_cast(this)); lcast_set_precision(stream, static_cast(0)); @@ -1342,10 +1476,13 @@ namespace boost // Not optimised converter template bool float_types_converter_internal(T& output, int /*tag*/) { + + if (parse_inf_nan(start, finish, output)) return true; + bool return_value = convert_using_base_class(output); /* Some compilers and libraries successfully - * parse 'inf', 'INFINITY', '1.0E', '1.0E-'... + * parse '1.0E', '1.0E-'... * We are trying to provide a unified behaviour, * so we just forbid such conversions (as some * of the most popular compilers/libraries do) @@ -1356,10 +1493,7 @@ namespace boost CharT const lowercase_e = lcast_char_constants::lowercase_e; if ( return_value && ( - output > (std::numeric_limits::max)() // +inf - || output < -(std::numeric_limits::max)() // -inf - || output != output // NaN - || *(finish-1) == lowercase_e // 1.0e + *(finish-1) == lowercase_e // 1.0e || *(finish-1) == capital_e // 1.0E || *(finish-1) == minus // 1.0e- or 1.0E- || *(finish-1) == plus // 1.0e+ or 1.0E+ diff --git a/lexical_cast.htm b/lexical_cast.htm index 2079a0f..35c6e58 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -269,6 +269,7 @@ Eliminate an overhead of std::locale if your program runs in the "C

      Changes

      July 2011:

        +
      • Added code to work with Inf and NaN on any platform.
      • Better performance and less memory usage for conversions to float type (and to double type, if sizeof(double)<sizeof(long double)).

      May 2011:

      diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index afa16a6..244addb 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -42,6 +42,10 @@ #define LCAST_TEST_LONGLONG #endif +#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) +#define BOOST_LCAST_NO_WCHAR_T +#endif + template struct my_traits : std::char_traits { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 9517c63..2dd3500 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -27,6 +27,7 @@ test-suite conversion [ run lexical_cast_vc8_bug_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_wchars_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_float_types_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run lexical_cast_inf_nan_test.cpp ../../test/build//boost_unit_test_framework/static ] ; diff --git a/test/lexical_cast_float_types_test.cpp b/test/lexical_cast_float_types_test.cpp index 10074d4..72279bb 100755 --- a/test/lexical_cast_float_types_test.cpp +++ b/test/lexical_cast_float_types_test.cpp @@ -242,22 +242,6 @@ void test_converion_to_float_types() CHECK_CLOSE_ABS_DIFF(.34, test_t); CHECK_CLOSE_ABS_DIFF(.34e10, test_t); -// BOOST_CHECK(lexical_cast("-inf") == -std::numeric_limits::infinity() ); -// BOOST_CHECK(lexical_cast("-INF") == -std::numeric_limits::infinity() ); -// BOOST_CHECK(lexical_cast("+inf") == std::numeric_limits::infinity() ); -// BOOST_CHECK(lexical_cast("infinity") == std::numeric_limits::infinity() ); -// -// BOOST_CHECK(lexical_cast("nan") == std::numeric_limits::quiet_NaN() ); -// BOOST_CHECK(lexical_cast("NaN") == std::numeric_limits::quiet_NaN() ); - - BOOST_CHECK_THROW(lexical_cast("-inf"), bad_lexical_cast ); - BOOST_CHECK_THROW(lexical_cast("-INF"), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast("+inf"), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast("infinity"), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast("nan"), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast("NaN"), bad_lexical_cast); - - BOOST_CHECK_THROW(lexical_cast("-1.e"), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast("-1.E"), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast("1.e"), bad_lexical_cast); @@ -381,10 +365,6 @@ void test_converion_from_to_float_types() TEST_TO_FROM_CAST_AROUND( 0.0 ); -// TEST_TO_FROM_CAST_AROUND( std::numeric_limits::infinity() ); -// TEST_TO_FROM_CAST_AROUND( -std::numeric_limits::infinity() ); -// TEST_TO_FROM_CAST_AROUND( std::numeric_limits::quiet_NaN() ); - long double val1; for(val1 = 1.0e-10L; val1 < 1e11; val1*=10 ) TEST_TO_FROM_CAST_AROUND( val1 ); diff --git a/test/lexical_cast_inf_nan_test.cpp b/test/lexical_cast_inf_nan_test.cpp new file mode 100755 index 0000000..64a4957 --- /dev/null +++ b/test/lexical_cast_inf_nan_test.cpp @@ -0,0 +1,109 @@ +// Unit test for boost::lexical_cast. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Antony Polukhin, 2011. +// +// 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 + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include + +#include +#include +#include + +#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) +#define BOOST_LCAST_NO_WCHAR_T +#endif + +using namespace boost; + +template +void test_inf_nan_templated() +{ + typedef T test_t; + + BOOST_CHECK(lexical_cast("inf") > (std::numeric_limits::max)() ); + BOOST_CHECK(lexical_cast("INF") > (std::numeric_limits::max)() ); + + BOOST_CHECK(lexical_cast("-inf") < -(std::numeric_limits::max)() ); + BOOST_CHECK(lexical_cast("-INF") < -(std::numeric_limits::max)() ); + + BOOST_CHECK(lexical_cast("+inf") > (std::numeric_limits::max)() ); + BOOST_CHECK(lexical_cast("+INF") > (std::numeric_limits::max)() ); + + BOOST_CHECK(lexical_cast("infinity") > (std::numeric_limits::max)() ); + BOOST_CHECK(lexical_cast("INFINITY") > (std::numeric_limits::max)() ); + + BOOST_CHECK(lexical_cast("-infinity") < -(std::numeric_limits::max)() ); + BOOST_CHECK(lexical_cast("-INFINITY") < -(std::numeric_limits::max)() ); + + BOOST_CHECK(lexical_cast("+infinity") > (std::numeric_limits::max)() ); + BOOST_CHECK(lexical_cast("+INFINITY") > (std::numeric_limits::max)() ); + + BOOST_CHECK( lexical_cast("nan") != lexical_cast("nan") ); + BOOST_CHECK( lexical_cast("NAN") != lexical_cast("NAN") ); + + BOOST_CHECK( lexical_cast("-nan") != lexical_cast("-nan") ); + BOOST_CHECK( lexical_cast("-NAN") != lexical_cast("-NAN") ); + + BOOST_CHECK( lexical_cast("+nan") != lexical_cast("+nan") ); + BOOST_CHECK( lexical_cast("+NAN") != lexical_cast("+NAN") ); + + BOOST_CHECK( lexical_cast("nan()") != lexical_cast("nan()") ); + BOOST_CHECK( lexical_cast("NAN(some string)") != lexical_cast("NAN(some string)") ); + BOOST_CHECK_THROW( lexical_cast("NAN(some string"), bad_lexical_cast ); + + BOOST_CHECK(lexical_cast( -std::numeric_limits::infinity()) == "-inf" ); + BOOST_CHECK(lexical_cast( std::numeric_limits::infinity()) == "inf" ); + BOOST_CHECK(lexical_cast( std::numeric_limits::quiet_NaN()) == "nan" ); + +#ifndef BOOST_LCAST_NO_WCHAR_T + BOOST_CHECK(lexical_cast(L"inf") > (std::numeric_limits::max)() ); + BOOST_CHECK(lexical_cast(L"INF") > (std::numeric_limits::max)() ); + + BOOST_CHECK( lexical_cast(L"nan") != lexical_cast(L"nan") ); + BOOST_CHECK( lexical_cast(L"NAN") != lexical_cast(L"NAN") ); + + BOOST_CHECK(lexical_cast( -std::numeric_limits::infinity()) == L"-inf" ); + BOOST_CHECK(lexical_cast( std::numeric_limits::infinity()) == L"inf" ); + BOOST_CHECK(lexical_cast( std::numeric_limits::quiet_NaN()) == L"nan" ); + +#endif +} + +void test_inf_nan_float() +{ + test_inf_nan_templated(); +} + +void test_inf_nan_double() +{ + test_inf_nan_templated(); +} + +void test_inf_nan_long_double() +{ + test_inf_nan_templated(); +} + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test_framework::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast inf anf nan parsing unit test"); + suite->add(BOOST_TEST_CASE(&test_inf_nan_float)); + suite->add(BOOST_TEST_CASE(&test_inf_nan_double)); + suite->add(BOOST_TEST_CASE(&test_inf_nan_long_double)); + + return suite; +} From c6c501c7693c838eac10763a619e77d9d3de0fb8 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sat, 16 Jul 2011 21:02:32 +0000 Subject: [PATCH 096/242] Fixes #5689. Added code to work -NaN on any platform. Removed some warnings [SVN r73155] --- include/boost/lexical_cast.hpp | 79 ++++++++++++-------- test/lexical_cast_inf_nan_test.cpp | 114 ++++++++++++++++++++++------- 2 files changed, 134 insertions(+), 59 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index b4728f3..99aeb24 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include #include @@ -767,7 +769,7 @@ namespace boost } if( !has_minus ) value = std::numeric_limits::quiet_NaN(); - else value = -std::numeric_limits::quiet_NaN(); + else value = (boost::math::changesign) (std::numeric_limits::quiet_NaN()); return true; } else if (( /* 'INF' or 'inf' */ @@ -784,7 +786,7 @@ namespace boost ) { if( !has_minus ) value = std::numeric_limits::infinity(); - else value = -std::numeric_limits::infinity(); + else value = (boost::math::changesign) (std::numeric_limits::infinity()); return true; } @@ -810,49 +812,67 @@ namespace boost , "INFINITY", "infinity" , '(', ')'); } - +#ifndef BOOST_LCAST_NO_WCHAR_T template bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) { using namespace std; - if (value != value) + if ( (boost::math::isnan)(value) ) { - memcpy(begin,L"nan", sizeof(L"nan")); - end = begin + 3; + if ( (boost::math::signbit)(value) ) + { + memcpy(begin,L"-nan", sizeof(L"-nan")); + end = begin + 4; + } else + { + memcpy(begin,L"nan", sizeof(L"nan")); + end = begin + 3; + } return true; - } else if ( value > numeric_limits::max() ) + } else if ( (boost::math::isinf)(value) ) { - memcpy(begin,L"inf", sizeof(L"inf")); - end = begin + 3; - return true; - } else if ( value < -numeric_limits::max() ) - { - memcpy(begin,L"-inf", sizeof(L"-inf")); - end = begin + 4; + if ( (boost::math::signbit)(value) ) + { + memcpy(begin,L"-inf", sizeof(L"-inf")); + end = begin + 4; + } else + { + memcpy(begin,L"inf", sizeof(L"inf")); + end = begin + 3; + } return true; } return false; } - +#endif template bool put_inf_nan(CharT* begin, CharT*& end, const T& value) { using namespace std; - if (value != value) + if ( (boost::math::isnan)(value) ) { - memcpy(begin,"nan", sizeof("nan")); - end = begin + 3; + if ( (boost::math::signbit)(value) ) + { + memcpy(begin,"-nan", sizeof("-nan")); + end = begin + 4; + } else + { + memcpy(begin,"nan", sizeof("nan")); + end = begin + 3; + } return true; - } else if ( value > numeric_limits::max() ) + } else if ( (boost::math::isinf)(value) ) { - memcpy(begin,"inf", sizeof("inf")); - end = begin + 3; - return true; - } else if ( value < -numeric_limits::max() ) - { - memcpy(begin,"-inf", sizeof("-inf")); - end = begin + 4; + if ( (boost::math::signbit)(value) ) + { + memcpy(begin,"-inf", sizeof("-inf")); + end = begin + 4; + } else + { + memcpy(begin,"inf", sizeof("inf")); + end = begin + 3; + } return true; } @@ -1095,12 +1115,9 @@ namespace boost * with long doubles (and with doubles if sizeof(double)==sizeof(long double)). */ long double result = std::pow(10.0L, pow_of_10) * mantissa; - value = ( has_minus ? -1 * result : result); + value = static_cast( has_minus ? -1 * result : result); - if ( value > (std::numeric_limits::max)() // is it +inf - || value < -(std::numeric_limits::max)() // is it -inf - || value != value) // is it NaN - return false; + if ( (boost::math::isinf)(value) || (boost::math::isnan)(value) ) return false; return true; } diff --git a/test/lexical_cast_inf_nan_test.cpp b/test/lexical_cast_inf_nan_test.cpp index 64a4957..ee50dee 100755 --- a/test/lexical_cast_inf_nan_test.cpp +++ b/test/lexical_cast_inf_nan_test.cpp @@ -18,7 +18,9 @@ #include -#include + +#include +#include #include #include @@ -28,57 +30,113 @@ using namespace boost; +template +bool is_pos_inf(T value) +{ + return (boost::math::isinf)(value) && !(boost::math::signbit)(value); +} + +template +bool is_neg_inf(T value) +{ + return (boost::math::isinf)(value) && (boost::math::signbit)(value); +} + +template +bool is_pos_nan(T value) +{ + return (boost::math::isnan)(value) && !(boost::math::signbit)(value); +} + +template +bool is_neg_nan(T value) +{ + return (boost::math::isnan)(value) && (boost::math::signbit)(value); +} + template void test_inf_nan_templated() { typedef T test_t; - BOOST_CHECK(lexical_cast("inf") > (std::numeric_limits::max)() ); - BOOST_CHECK(lexical_cast("INF") > (std::numeric_limits::max)() ); + BOOST_CHECK( is_pos_inf( lexical_cast("inf") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast("INF") ) ); - BOOST_CHECK(lexical_cast("-inf") < -(std::numeric_limits::max)() ); - BOOST_CHECK(lexical_cast("-INF") < -(std::numeric_limits::max)() ); + BOOST_CHECK( is_neg_inf( lexical_cast("-inf") ) ); + BOOST_CHECK( is_neg_inf( lexical_cast("-INF") ) ); - BOOST_CHECK(lexical_cast("+inf") > (std::numeric_limits::max)() ); - BOOST_CHECK(lexical_cast("+INF") > (std::numeric_limits::max)() ); + BOOST_CHECK( is_pos_inf( lexical_cast("+inf") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast("+INF") ) ); - BOOST_CHECK(lexical_cast("infinity") > (std::numeric_limits::max)() ); - BOOST_CHECK(lexical_cast("INFINITY") > (std::numeric_limits::max)() ); + BOOST_CHECK( is_pos_inf( lexical_cast("infinity") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast("INFINITY") ) ); - BOOST_CHECK(lexical_cast("-infinity") < -(std::numeric_limits::max)() ); - BOOST_CHECK(lexical_cast("-INFINITY") < -(std::numeric_limits::max)() ); + BOOST_CHECK( is_neg_inf( lexical_cast("-infinity") ) ); + BOOST_CHECK( is_neg_inf( lexical_cast("-INFINITY") ) ); - BOOST_CHECK(lexical_cast("+infinity") > (std::numeric_limits::max)() ); - BOOST_CHECK(lexical_cast("+INFINITY") > (std::numeric_limits::max)() ); + BOOST_CHECK( is_pos_inf( lexical_cast("+infinity") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast("+INFINITY") ) ); - BOOST_CHECK( lexical_cast("nan") != lexical_cast("nan") ); - BOOST_CHECK( lexical_cast("NAN") != lexical_cast("NAN") ); + BOOST_CHECK( is_pos_nan( lexical_cast("nan") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast("NAN") ) ); - BOOST_CHECK( lexical_cast("-nan") != lexical_cast("-nan") ); - BOOST_CHECK( lexical_cast("-NAN") != lexical_cast("-NAN") ); + BOOST_CHECK( is_neg_nan( lexical_cast("-nan") ) ); + BOOST_CHECK( is_neg_nan( lexical_cast("-NAN") ) ); - BOOST_CHECK( lexical_cast("+nan") != lexical_cast("+nan") ); - BOOST_CHECK( lexical_cast("+NAN") != lexical_cast("+NAN") ); + BOOST_CHECK( is_pos_nan( lexical_cast("+nan") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast("+NAN") ) ); - BOOST_CHECK( lexical_cast("nan()") != lexical_cast("nan()") ); - BOOST_CHECK( lexical_cast("NAN(some string)") != lexical_cast("NAN(some string)") ); + BOOST_CHECK( is_pos_nan( lexical_cast("nan()") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast("NAN(some string)") ) ); BOOST_CHECK_THROW( lexical_cast("NAN(some string"), bad_lexical_cast ); - BOOST_CHECK(lexical_cast( -std::numeric_limits::infinity()) == "-inf" ); + BOOST_CHECK(lexical_cast( (boost::math::changesign)(std::numeric_limits::infinity())) + == "-inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::infinity()) == "inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::quiet_NaN()) == "nan" ); + BOOST_CHECK(lexical_cast( + (boost::math::changesign)(std::numeric_limits::quiet_NaN())) + == "-nan" ); #ifndef BOOST_LCAST_NO_WCHAR_T - BOOST_CHECK(lexical_cast(L"inf") > (std::numeric_limits::max)() ); - BOOST_CHECK(lexical_cast(L"INF") > (std::numeric_limits::max)() ); + BOOST_CHECK( is_pos_inf( lexical_cast(L"inf") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast(L"INF") ) ); - BOOST_CHECK( lexical_cast(L"nan") != lexical_cast(L"nan") ); - BOOST_CHECK( lexical_cast(L"NAN") != lexical_cast(L"NAN") ); + BOOST_CHECK( is_neg_inf( lexical_cast(L"-inf") ) ); + BOOST_CHECK( is_neg_inf( lexical_cast(L"-INF") ) ); - BOOST_CHECK(lexical_cast( -std::numeric_limits::infinity()) == L"-inf" ); + BOOST_CHECK( is_pos_inf( lexical_cast(L"+inf") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast(L"+INF") ) ); + + BOOST_CHECK( is_pos_inf( lexical_cast(L"infinity") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast(L"INFINITY") ) ); + + BOOST_CHECK( is_neg_inf( lexical_cast(L"-infinity") ) ); + BOOST_CHECK( is_neg_inf( lexical_cast(L"-INFINITY") ) ); + + BOOST_CHECK( is_pos_inf( lexical_cast(L"+infinity") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast(L"+INFINITY") ) ); + + BOOST_CHECK( is_pos_nan( lexical_cast(L"nan") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast(L"NAN") ) ); + + BOOST_CHECK( is_neg_nan( lexical_cast(L"-nan") ) ); + BOOST_CHECK( is_neg_nan( lexical_cast(L"-NAN") ) ); + + BOOST_CHECK( is_pos_nan( lexical_cast(L"+nan") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast(L"+NAN") ) ); + + BOOST_CHECK( is_pos_nan( lexical_cast(L"nan()") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast(L"NAN(some string)") ) ); + BOOST_CHECK_THROW( lexical_cast(L"NAN(some string"), bad_lexical_cast ); + + BOOST_CHECK(lexical_cast( (boost::math::changesign)(std::numeric_limits::infinity())) + == L"-inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::infinity()) == L"inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::quiet_NaN()) == L"nan" ); - + BOOST_CHECK(lexical_cast( + (boost::math::changesign)(std::numeric_limits::quiet_NaN())) + == L"-nan" ); #endif } From 272e92ba7f7c34e82b8a1f8f6fe39ddf139112b2 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 20 Jul 2011 11:50:46 +0000 Subject: [PATCH 097/242] Fixes #5723. Updates lexical_cast maintainer info [SVN r73256] --- doc/Jamfile.v2 | 16 + doc/lexical_cast.qbk | 685 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 701 insertions(+) create mode 100644 doc/Jamfile.v2 create mode 100644 doc/lexical_cast.qbk diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 new file mode 100644 index 0000000..b629c6a --- /dev/null +++ b/doc/Jamfile.v2 @@ -0,0 +1,16 @@ +# Copyright Antony Polukhin 2011. Use, modification, and distribution are +# subject to 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) + +using quickbook ; +import boostbook : boostbook ; + +xml lexical_cast : lexical_cast.qbk ; +boostbook standalone + : + lexical_cast + : + boost.root=../../../.. + pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html + ; + diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk new file mode 100644 index 0000000..8ce54cb --- /dev/null +++ b/doc/lexical_cast.qbk @@ -0,0 +1,685 @@ +[library Boost.Lexical_Cast + [quickbook 1.5] + [version 1.0] + [copyright 2000-2005 Kevlin Henney] + [copyright 2006-2010 Alexander Nasonov] + [copyright 2011 Antony Polukhin] + [category String and text processing] + [category Miscellaneous] + [license + 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]) + ] +] + +[def __numericcast__ [@http://www.boost.org/libs/numeric/conversion/doc/html/boost_numericconversion/improved_numeric_cast__.html `boost::numeric_cast`]] +[def __proposallong__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1973.html Lexical Conversion Library Proposal for TR2, N1973 by Kevlin Henney and Beman Dawes]] +[def __proposalshort__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1973.html Lexical Conversion Library Proposal for TR2, N1973]] + +[section Motivation] +Sometimes a value must be converted to a literal text form, such as an [c++] `int` represented as a `std::string`, or vice-versa, when a `std::string` is interpreted as an `int`. Such examples are common when converting between data types internal to a program and representation external to a program, such as windows and configuration files. + +The standard C and C++ libraries offer a number of facilities for performing such conversions. However, they vary with their ease of use, extensibility, and safety. + +For instance, there are a number of limitations with the family of standard C functions typified by `atoi`: + +* Conversion is supported in one direction only: from text to internal data type. Converting the other way using the C library requires either the inconvenience and compromised safety of the `sprintf` function, or the loss of portability associated with non-standard functions such as `itoa`. +* The range of types supported is only a subset of the built-in numeric types, namely `int`, `long`, and `double`. +* The range of types cannot be extended in a uniform manner. For instance, conversion from string representation to complex or rational. + +The standard C functions typified by `strtol` have the same basic limitations, but offer finer control over the conversion process. However, for the common case such control is often either not required or not used. The `scanf` family of functions offer even greater control, but also lack safety and ease of use. + +The standard C++ library offers `stringstream` for the kind of in-core formatting being discussed. It offers a great deal of control over the formatting and conversion of I/O to and from arbitrary types through text. However, for simple conversions direct use of `stringstream` can be either clumsy (with the introduction of extra local variables and the loss of infix-expression convenience) or obscure (where `stringstream` objects are created as temporary objects in an expression). Facets provide a comprehensive concept and facility for controlling textual representation, but their perceived complexity and high entry level requires an extreme degree of involvement for simple conversions, and excludes all but a few programmers. + +The `lexical_cast` function template offers a convenient and consistent form for supporting common conversions to and from arbitrary types when they are represented as text. The simplification it offers is in expression-level convenience for such conversions. For more involved conversions, such as where precision or formatting need tighter control than is offered by the default behavior of `lexical_cast`, the conventional `std::stringstream` approach is recommended. Where the conversions are numeric to numeric, __numericcast__ may offer more reasonable behavior than `lexical_cast`. + +For a good discussion of the options and issues involved in string-based formatting, including comparison of `stringstream`, `lexical_cast`, and others, see Herb Sutter's article, [@http://www.gotw.ca/publications/mill19.htm The String Formatters of Manor Farm]. Also, take a look at the [link boost_lexical_cast.performance Performance] section. +[endsect] + +[section Examples] +The following example treats command line arguments as a sequence of numeric data: +`` + int main(int argc, char * argv[]) + { + using boost::lexical_cast; + using boost::bad_lexical_cast; + + std::vector args; + + while(*++argv) + { + try + { + args.push_back(lexical_cast(*argv)); + } + catch(bad_lexical_cast &) + { + args.push_back(0); + } + } + ... + } +`` +The following example uses numeric data in a string expression: +`` + void log_message(const std::string &); + + void log_errno(int yoko) + { + log_message("Error " + boost::lexical_cast(yoko) + ": " + strerror(yoko)); + } +`` +[endsect] + +[section Synopsis] +Library features defined in [@../../boost/lexical_cast.hpp boost/lexical_cast.hpp]: +`` + namespace boost + { + class bad_lexical_cast; + template + Target lexical_cast(const Source& arg); + } +`` + +[section lexical_cast] +`` + template + Target lexical_cast(const Source& arg); +`` +Returns the result of streaming arg into a standard library string-based stream and then out as a Target object. Where Target is either `std::string` or `std::wstring`, stream extraction takes the whole content of the string, including spaces, rather than relying on the default `operator>>` behavior. If the conversion is unsuccessful, a `bad_lexical_cast` exception is thrown. + +The requirements on the argument and result types are: + +* Source is OutputStreamable, meaning that an `operator<<` is defined that takes a `std::ostream` or `std::wostream` object on the left hand side and an instance of the argument type on the right. +* Target is InputStreamable, meaning that an `operator>>` is defined that takes a `std::istream` or `std::wistream` object on the left hand side and an instance of the result type on the right. +* Target is CopyConstructible [20.1.3]. +* Target is DefaultConstructible, meaning that it is possible to default-initialize an object of that type [8.5, 20.1.4]. + +The character type of the underlying stream is assumed to be char unless either the Source or the Target requires wide-character streaming, in which case the underlying stream uses `wchar_t`. Source types that require wide-character streaming are `wchar_t`, `wchar_t *`, and `std::wstring`. Target types that require wide-character streaming are `wchar_t` and `std::wstring`. + +Where a higher degree of control is required over conversions, `std::stringstream` and `std::wstringstream` offer a more appropriate path. Where non-stream-based conversions are required, `lexical_cast` is the wrong tool for the job and is not special-cased for such scenarios. +[endsect] + +[section bad_lexical_cast] +`` + class bad_lexical_cast : public std::bad_cast + { + public: + ... // same member function interface as std::exception + }; +`` +Exception used to indicate runtime lexical_cast failure. +[endsect] + +[endsect] + +[section Frequently Asked Questions] + +* [*Question:] Why does `lexical_cast("127")` throw `bad_lexical_cast`? + * [*Answer:] The type `int8_t` is a `typedef` to `char` or `signed char`. Lexical conversion to these types +is simply reading a byte from source but since the source has more than one byte, the exception is thrown. +Please use other integer types such as `int` or `short int`. If bounds checking is important, you can also +call __numericcast__: +`numeric_cast(lexical_cast("127"));` + + +* [*Question:] What does `lexical_cast` of an `int8_t` or `uint8_t` not do what I expect? + * [*Answer:] As above, note that int8_t and uint8_t are actually chars and are formatted as such. To avoid +this, cast to an integer type first: `lexical_cast(static_cast(n));` + + +* [*Question:] The implementation always resets the `ios_base::skipws` flag of an underlying stream object. +It breaks my `operator>>` that works only in presence of this flag. Can you remove code that resets the flag? + * [*Answer:] May be in a future version. There is no requirement in +__proposallong__ to reset the flag but +remember that __proposalshort__ is not yet accepted by the committee. By the way, it's a great opportunity to +make your `operator>>` conform to the standard. +Read a good C++ book, study `std::sentry` and [@../../libs/io/doc/ios_state.html `ios_state_saver`]. + + +* [*Question:] Why `std::cout << boost::lexical_cast("-1");` does not throw, but outputs 4294967295? + * [*Answer:] `boost::lexical_cast` has the behavior of `std::stringstream`, which uses `num_get` functions of +`std::locale` to convert numbers. If we look at the Programming languages — C++, we'll see, that `num_get` uses +the rules of `scanf` for conversions. And in the C99 standard for unsigned input value minus sign is optional, so +if a negative number is read, no errors will arise and the result will be the two's complement. + +[endsect] + +[section Changes] +* [*boost 1.48.0 :] + + * Added code to work with Inf and NaN on any platform. + * Better performance and less memory usage for conversions to float type (and to double type, if `sizeof(double) < sizeof(long double)`). + +* [*boost 1.47.0 :] + + * Optimizations for "C" and other locales without number grouping. + * 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). + +* [*boost 1.34.0 :] + + * Better performance for many combinations of Source and Target types. For more details refer to Alexander Nasonovs article [@http://accu.org/index.php/journals/1375 Fine Tuning for lexical_cast, Overload #74, August 2006] [@http://www.accu.org/var/uploads/journals/overload74.pdf (PDF)]. + +* [*boost 1.33.0 :] + + * Call-by-const reference for the parameters. This requires partial specialization of class templates, so it doesn't work for MSVC 6, and it uses the original pass by value there. + * The MSVC 6 support is deprecated, and will be removed in a future Boost version. + +* [*Earlier :] + + * The previous version of lexical_cast used the default stream precision for reading and writing floating-point numbers. For numerics that have a corresponding specialization of `std::numeric_limits`, the current version now chooses a precision to match. + * The previous version of lexical_cast did not support conversion to or from any wide-character-based types. For compilers with full language and library support for wide characters, `lexical_cast` now supports conversions from `wchar_t`, `wchar_t *`, and `std::wstring` and to `wchar_t` and `std::wstring`. + * The previous version of `lexical_cast` assumed that the conventional stream extractor operators were sufficient for reading values. However, string I/O is asymmetric, with the result that spaces play the role of I/O separators rather than string content. The current version fixes this error for `std::string` and, where supported, `std::wstring`: `lexical_cast("Hello, World")` succeeds instead of failing with a `bad_lexical_cast` exception. + * The previous version of `lexical_cast` allowed unsafe and meaningless conversions to pointers. The current version now throws a `bad_lexical_cast` for conversions to pointers: `lexical_cast("Goodbye, World")` now throws an exception instead of causing undefined behavior. + +[endsect] + +[section Performance] + +In most cases `boost::lexical_cast` is faster than `scanf`, `printf`, `std::stringstream`. For more detailed info you can look at the tables below. + +[section Tests description] +All the tests measure execution speed in milliseconds for 10000 iterations of the following code blocks: +[table:legend Tests source code +[[Test name] [Code]] +[[lexical_cast] + [`` + _out = boost::lexical_cast(_in); + ``] + ] +[[std::stringstream with construction] + [`` + std::stringstream ss; + ss << _in; + if (ss.fail()) throw std::logic_error(descr); + ss >> _out; + if (ss.fail()) throw std::logic_error(descr); + ``] + ] +[[std::stringstream without construction] + [`` + ss << _in; // ss is an instance of std::stringstream + if (ss.fail()) throw std::logic_error(descr); + ss >> _out; + if (ss.fail()) throw std::logic_error(descr); + /* reseting std::stringstream to use it again */ + ss.str(std::string()); + ss.clear(); + ``] + ] +[[scanf/printf] + [`` + typename OUTTYPE::value_type buffer[500]; + sprintf( (char*)buffer, conv, _in); + _out = buffer; + ``] + ] +] +Fastest results are highlitened with "!!! *x* !!!". +Do not use this results to compare compilers, because tests were taken on different hardware. + +[endsect] + +[/ BEGIN of section, generated by performance measuring program ] + +[section clang-linux-2.8][table:id Performance Table (clang-linux-2.8) +[[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]] +[[ string->char ][ !!! *<1* !!! ][ 106 ][ 11 ][ 11 ]] +[[ string->signed char ][ !!! *<1* !!! ][ 102 ][ 8 ][ 8 ]] +[[ string->unsigned char ][ !!! *<1* !!! ][ 83 ][ 7 ][ 15 ]] +[[ string->int ][ !!! *8* !!! ][ 114 ][ 21 ][ 17 ]] +[[ string->short ][ !!! *10* !!! ][ 111 ][ 20 ][ 17 ]] +[[ string->long int ][ !!! *9* !!! ][ 113 ][ 20 ][ 16 ]] +[[ string->long long ][ !!! *9* !!! ][ 112 ][ 21 ][ 16 ]] +[[ string->unsigned int ][ !!! *9* !!! ][ 115 ][ 23 ][ 17 ]] +[[ string->unsigned short ][ !!! *7* !!! ][ 111 ][ 21 ][ 16 ]] +[[ string->unsigned long int ][ !!! *9* !!! ][ 106 ][ 20 ][ 17 ]] +[[ string->unsigned long long ][ !!! *9* !!! ][ 104 ][ 21 ][ 17 ]] +[[ string->bool ][ !!! *<1* !!! ][ 101 ][ 17 ][ 10 ]] +[[ string->float ][ !!! *16* !!! ][ 175 ][ 67 ][ 33 ]] +[[ string->double ][ !!! *18* !!! ][ 196 ][ 91 ][ 56 ]] +[[ string->long double ][ 126 ][ 198 ][ 92 ][ !!! *61* !!! ]] +[[ char->string ][ !!! *12* !!! ][ 101 ][ 16 ][ 12 ]] +[[ unsigned char->string ][ !!! *10* !!! ][ 103 ][ 18 ][ 17 ]] +[[ signed char->string ][ !!! *12* !!! ][ 101 ][ 18 ][ 12 ]] +[[ int->string ][ !!! *19* !!! ][ 124 ][ 25 ][ 19 ]] +[[ short->string ][ 23 ][ 124 ][ 26 ][ !!! *17* !!! ]] +[[ long int->string ][ 20 ][ 123 ][ 23 ][ !!! *17* !!! ]] +[[ long long->string ][ 19 ][ 124 ][ 23 ][ !!! *18* !!! ]] +[[ unsigned int->string ][ 18 ][ 122 ][ 28 ][ !!! *17* !!! ]] +[[ unsigned short->string ][ 36 ][ 160 ][ 31 ][ !!! *17* !!! ]] +[[ unsigned long int->string ][ 22 ][ 123 ][ 28 ][ !!! *18* !!! ]] +[[ unsigned long long->string ][ !!! *23* !!! ][ 137 ][ 32 ][ 23 ]] +[[ bool->string ][ !!! *11* !!! ][ 124 ][ 26 ][ 17 ]] +[[ float->string ][ 178 ][ 273 ][ 124 ][ !!! *57* !!! ]] +[[ double->string ][ 227 ][ 450 ][ 241 ][ !!! *77* !!! ]] +[[ long double->string ][ 249 ][ 331 ][ 185 ][ !!! *85* !!! ]] +[[ char*->char ][ !!! *<1* !!! ][ 109 ][ 9 ][ 11 ]] +[[ char*->signed char ][ !!! *<1* !!! ][ 105 ][ 15 ][ 8 ]] +[[ char*->unsigned char ][ !!! *<1* !!! ][ 111 ][ 11 ][ 20 ]] +[[ char*->int ][ !!! *7* !!! ][ 143 ][ 25 ][ 19 ]] +[[ char*->short ][ !!! *10* !!! ][ 131 ][ 24 ][ 18 ]] +[[ char*->long int ][ !!! *12* !!! ][ 134 ][ 24 ][ 18 ]] +[[ char*->long long ][ !!! *12* !!! ][ 132 ][ 26 ][ 17 ]] +[[ char*->unsigned int ][ !!! *10* !!! ][ 133 ][ 26 ][ 19 ]] +[[ char*->unsigned short ][ !!! *11* !!! ][ 127 ][ 24 ][ 20 ]] +[[ char*->unsigned long int ][ !!! *10* !!! ][ 143 ][ 26 ][ 19 ]] +[[ char*->unsigned long long ][ !!! *12* !!! ][ 137 ][ 26 ][ 19 ]] +[[ char*->bool ][ !!! *2* !!! ][ 138 ][ 27 ][ 13 ]] +[[ char*->float ][ !!! *19* !!! ][ 186 ][ 65 ][ 31 ]] +[[ char*->double ][ !!! *19* !!! ][ 195 ][ 96 ][ 57 ]] +[[ char*->long double ][ 134 ][ 200 ][ 92 ][ !!! *61* !!! ]] +[[ unsigned char*->char ][ !!! *<1* !!! ][ 87 ][ 8 ][ 10 ]] +[[ unsigned char*->signed char ][ !!! *<1* !!! ][ 87 ][ 8 ][ 10 ]] +[[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 89 ][ 8 ][ 16 ]] +[[ unsigned char*->int ][ !!! *10* !!! ][ 117 ][ 22 ][ 17 ]] +[[ unsigned char*->short ][ !!! *11* !!! ][ 117 ][ 21 ][ 17 ]] +[[ unsigned char*->long int ][ !!! *10* !!! ][ 116 ][ 22 ][ 17 ]] +[[ unsigned char*->long long ][ !!! *9* !!! ][ 116 ][ 22 ][ 17 ]] +[[ unsigned char*->unsigned int ][ !!! *10* !!! ][ 117 ][ 24 ][ 17 ]] +[[ unsigned char*->unsigned short ][ !!! *11* !!! ][ 119 ][ 22 ][ 17 ]] +[[ unsigned char*->unsigned long int ][ !!! *10* !!! ][ 111 ][ 21 ][ 17 ]] +[[ unsigned char*->unsigned long long ][ !!! *10* !!! ][ 109 ][ 21 ][ 17 ]] +[[ unsigned char*->bool ][ !!! *<1* !!! ][ 105 ][ 18 ][ 10 ]] +[[ unsigned char*->float ][ !!! *17* !!! ][ 174 ][ 66 ][ 33 ]] +[[ unsigned char*->double ][ !!! *19* !!! ][ 198 ][ 91 ][ 56 ]] +[[ unsigned char*->long double ][ 129 ][ 200 ][ 92 ][ !!! *58* !!! ]] +[[ unsigned char*->string ][ !!! *12* !!! ][ 122 ][ 20 ][ --- ]] +[[ signed char*->char ][ !!! *<1* !!! ][ 87 ][ 8 ][ 9 ]] +[[ signed char*->signed char ][ !!! *<1* !!! ][ 86 ][ 8 ][ 10 ]] +[[ signed char*->unsigned char ][ !!! *<1* !!! ][ 93 ][ 8 ][ 16 ]] +[[ signed char*->int ][ !!! *10* !!! ][ 117 ][ 21 ][ 17 ]] +[[ signed char*->short ][ !!! *11* !!! ][ 117 ][ 22 ][ 17 ]] +[[ signed char*->long int ][ !!! *10* !!! ][ 115 ][ 21 ][ 17 ]] +[[ signed char*->long long ][ !!! *10* !!! ][ 115 ][ 24 ][ 17 ]] +[[ signed char*->unsigned int ][ !!! *10* !!! ][ 118 ][ 24 ][ 17 ]] +[[ signed char*->unsigned short ][ !!! *11* !!! ][ 139 ][ 27 ][ 20 ]] +[[ signed char*->unsigned long int ][ !!! *9* !!! ][ 144 ][ 27 ][ 19 ]] +[[ signed char*->unsigned long long ][ !!! *7* !!! ][ 127 ][ 25 ][ 22 ]] +[[ signed char*->bool ][ !!! *<1* !!! ][ 123 ][ 23 ][ 9 ]] +[[ signed char*->float ][ !!! *21* !!! ][ 207 ][ 80 ][ 41 ]] +[[ signed char*->double ][ !!! *23* !!! ][ 255 ][ 115 ][ 68 ]] +[[ signed char*->long double ][ 159 ][ 275 ][ 125 ][ !!! *72* !!! ]] +[[ signed char*->string ][ !!! *16* !!! ][ 155 ][ 27 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 150 ][ 32 ][ --- ]] +[[ float->double ][ !!! *<1* !!! ][ 304 ][ 162 ][ --- ]] +[[ double->double ][ !!! *<1* !!! ][ 298 ][ 168 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 311 ][ 154 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 308 ][ 154 ][ --- ]] +[[ char->unsigned char ][ !!! *<1* !!! ][ 97 ][ 9 ][ --- ]] +[[ char->signed char ][ !!! *<1* !!! ][ 94 ][ 11 ][ --- ]] +[[ unsigned char->char ][ !!! *<1* !!! ][ 106 ][ 8 ][ --- ]] +[[ signed char->char ][ !!! *<1* !!! ][ 111 ][ 8 ][ --- ]] +] +[endsect] +[section gcc-4.3][table:id Performance Table (gcc-4.3) +[[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]] +[[ string->char ][ !!! *<1* !!! ][ 92 ][ 7 ][ 8 ]] +[[ string->signed char ][ !!! *<1* !!! ][ 92 ][ 7 ][ 8 ]] +[[ string->unsigned char ][ !!! *<1* !!! ][ 92 ][ 7 ][ 13 ]] +[[ string->int ][ !!! *6* !!! ][ 115 ][ 21 ][ 14 ]] +[[ string->short ][ !!! *7* !!! ][ 141 ][ 26 ][ 24 ]] +[[ string->long int ][ !!! *7* !!! ][ 141 ][ 27 ][ 18 ]] +[[ string->long long ][ !!! *7* !!! ][ 153 ][ 28 ][ 17 ]] +[[ string->unsigned int ][ !!! *7* !!! ][ 156 ][ 26 ][ 18 ]] +[[ string->unsigned short ][ !!! *8* !!! ][ 146 ][ 25 ][ 18 ]] +[[ string->unsigned long int ][ !!! *9* !!! ][ 143 ][ 29 ][ 37 ]] +[[ string->unsigned long long ][ !!! *14* !!! ][ 135 ][ 20 ][ 15 ]] +[[ string->bool ][ !!! *<1* !!! ][ 117 ][ 20 ][ 8 ]] +[[ string->float ][ !!! *15* !!! ][ 177 ][ 63 ][ 31 ]] +[[ string->double ][ !!! *15* !!! ][ 198 ][ 89 ][ 54 ]] +[[ string->long double ][ 133 ][ 198 ][ 88 ][ !!! *55* !!! ]] +[[ char->string ][ !!! *10* !!! ][ 108 ][ 16 ][ 12 ]] +[[ unsigned char->string ][ !!! *10* !!! ][ 119 ][ 18 ][ 15 ]] +[[ signed char->string ][ !!! *10* !!! ][ 111 ][ 24 ][ 11 ]] +[[ int->string ][ !!! *14* !!! ][ 129 ][ 22 ][ 15 ]] +[[ short->string ][ !!! *14* !!! ][ 128 ][ 22 ][ 17 ]] +[[ long int->string ][ !!! *14* !!! ][ 127 ][ 21 ][ 17 ]] +[[ long long->string ][ !!! *14* !!! ][ 127 ][ 22 ][ 18 ]] +[[ unsigned int->string ][ !!! *15* !!! ][ 124 ][ 22 ][ 17 ]] +[[ unsigned short->string ][ 16 ][ 125 ][ 22 ][ !!! *15* !!! ]] +[[ unsigned long int->string ][ !!! *15* !!! ][ 125 ][ 22 ][ 17 ]] +[[ unsigned long long->string ][ !!! *18* !!! ][ 138 ][ 34 ][ 23 ]] +[[ bool->string ][ !!! *7* !!! ][ 120 ][ 22 ][ 12 ]] +[[ float->string ][ 136 ][ 229 ][ 110 ][ !!! *48* !!! ]] +[[ double->string ][ 184 ][ 270 ][ 136 ][ !!! *67* !!! ]] +[[ long double->string ][ 198 ][ 264 ][ 148 ][ !!! *69* !!! ]] +[[ char*->char ][ !!! *<1* !!! ][ 98 ][ 8 ][ 8 ]] +[[ char*->signed char ][ !!! *<1* !!! ][ 99 ][ 8 ][ 8 ]] +[[ char*->unsigned char ][ !!! *<1* !!! ][ 96 ][ 8 ][ 14 ]] +[[ char*->int ][ !!! *8* !!! ][ 120 ][ 21 ][ 15 ]] +[[ char*->short ][ !!! *8* !!! ][ 122 ][ 22 ][ 16 ]] +[[ char*->long int ][ !!! *8* !!! ][ 122 ][ 24 ][ 16 ]] +[[ char*->long long ][ !!! *8* !!! ][ 120 ][ 23 ][ 14 ]] +[[ char*->unsigned int ][ !!! *7* !!! ][ 123 ][ 23 ][ 15 ]] +[[ char*->unsigned short ][ !!! *8* !!! ][ 123 ][ 24 ][ 15 ]] +[[ char*->unsigned long int ][ !!! *8* !!! ][ 121 ][ 22 ][ 14 ]] +[[ char*->unsigned long long ][ !!! *7* !!! ][ 116 ][ 20 ][ 16 ]] +[[ char*->bool ][ !!! *<1* !!! ][ 107 ][ 18 ][ 10 ]] +[[ char*->float ][ !!! *14* !!! ][ 181 ][ 67 ][ 32 ]] +[[ char*->double ][ !!! *16* !!! ][ 197 ][ 88 ][ 53 ]] +[[ char*->long double ][ 127 ][ 208 ][ 93 ][ !!! *56* !!! ]] +[[ unsigned char*->char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 8 ]] +[[ unsigned char*->signed char ][ !!! *<1* !!! ][ 93 ][ 8 ][ 10 ]] +[[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 15 ]] +[[ unsigned char*->int ][ !!! *7* !!! ][ 117 ][ 21 ][ 16 ]] +[[ unsigned char*->short ][ !!! *8* !!! ][ 119 ][ 21 ][ 16 ]] +[[ unsigned char*->long int ][ !!! *7* !!! ][ 117 ][ 22 ][ 16 ]] +[[ unsigned char*->long long ][ !!! *8* !!! ][ 119 ][ 23 ][ 16 ]] +[[ unsigned char*->unsigned int ][ !!! *10* !!! ][ 123 ][ 20 ][ 15 ]] +[[ unsigned char*->unsigned short ][ !!! *8* !!! ][ 122 ][ 24 ][ 15 ]] +[[ unsigned char*->unsigned long int ][ !!! *8* !!! ][ 120 ][ 21 ][ 14 ]] +[[ unsigned char*->unsigned long long ][ !!! *8* !!! ][ 118 ][ 23 ][ 16 ]] +[[ unsigned char*->bool ][ !!! *1* !!! ][ 108 ][ 18 ][ 8 ]] +[[ unsigned char*->float ][ !!! *13* !!! ][ 182 ][ 63 ][ 30 ]] +[[ unsigned char*->double ][ !!! *16* !!! ][ 204 ][ 87 ][ 53 ]] +[[ unsigned char*->long double ][ 126 ][ 206 ][ 90 ][ !!! *60* !!! ]] +[[ unsigned char*->string ][ !!! *9* !!! ][ 123 ][ 21 ][ --- ]] +[[ signed char*->char ][ !!! *<1* !!! ][ 95 ][ 8 ][ 10 ]] +[[ signed char*->signed char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 10 ]] +[[ signed char*->unsigned char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 15 ]] +[[ signed char*->int ][ !!! *8* !!! ][ 117 ][ 22 ][ 16 ]] +[[ signed char*->short ][ !!! *7* !!! ][ 117 ][ 22 ][ 16 ]] +[[ signed char*->long int ][ !!! *8* !!! ][ 118 ][ 25 ][ 15 ]] +[[ signed char*->long long ][ !!! *7* !!! ][ 117 ][ 24 ][ 16 ]] +[[ signed char*->unsigned int ][ !!! *7* !!! ][ 120 ][ 20 ][ 16 ]] +[[ signed char*->unsigned short ][ !!! *8* !!! ][ 124 ][ 24 ][ 15 ]] +[[ signed char*->unsigned long int ][ !!! *8* !!! ][ 115 ][ 21 ][ 16 ]] +[[ signed char*->unsigned long long ][ !!! *9* !!! ][ 120 ][ 21 ][ 16 ]] +[[ signed char*->bool ][ !!! *1* !!! ][ 112 ][ 19 ][ 8 ]] +[[ signed char*->float ][ !!! *14* !!! ][ 183 ][ 64 ][ 31 ]] +[[ signed char*->double ][ !!! *18* !!! ][ 208 ][ 87 ][ 51 ]] +[[ signed char*->long double ][ 126 ][ 217 ][ 94 ][ !!! *55* !!! ]] +[[ signed char*->string ][ !!! *12* !!! ][ 126 ][ 22 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 146 ][ 23 ][ --- ]] +[[ float->double ][ !!! *<1* !!! ][ 275 ][ 139 ][ --- ]] +[[ double->double ][ !!! *<1* !!! ][ 270 ][ 142 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 281 ][ 145 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 301 ][ 145 ][ --- ]] +[[ char->unsigned char ][ !!! *<1* !!! ][ 96 ][ 7 ][ --- ]] +[[ char->signed char ][ !!! *<1* !!! ][ 95 ][ 7 ][ --- ]] +[[ unsigned char->char ][ !!! *<1* !!! ][ 96 ][ 7 ][ --- ]] +[[ signed char->char ][ !!! *<1* !!! ][ 91 ][ 7 ][ --- ]] +] +[endsect] +[section gcc-4.4][table:id Performance Table (gcc-4.4) +[[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]] +[[ string->char ][ !!! *<1* !!! ][ 81 ][ 8 ][ 8 ]] +[[ string->signed char ][ !!! *<1* !!! ][ 110 ][ 7 ][ 9 ]] +[[ string->unsigned char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 18 ]] +[[ string->int ][ !!! *9* !!! ][ 125 ][ 25 ][ 15 ]] +[[ string->short ][ !!! *7* !!! ][ 113 ][ 25 ][ 15 ]] +[[ string->long int ][ !!! *8* !!! ][ 112 ][ 24 ][ 15 ]] +[[ string->long long ][ !!! *8* !!! ][ 109 ][ 22 ][ 15 ]] +[[ string->unsigned int ][ !!! *8* !!! ][ 108 ][ 26 ][ 20 ]] +[[ string->unsigned short ][ !!! *9* !!! ][ 125 ][ 22 ][ 18 ]] +[[ string->unsigned long int ][ !!! *11* !!! ][ 125 ][ 32 ][ 17 ]] +[[ string->unsigned long long ][ !!! *10* !!! ][ 119 ][ 23 ][ 19 ]] +[[ string->bool ][ !!! *<1* !!! ][ 132 ][ 24 ][ 11 ]] +[[ string->float ][ !!! *18* !!! ][ 178 ][ 75 ][ 37 ]] +[[ string->double ][ !!! *24* !!! ][ 236 ][ 100 ][ 64 ]] +[[ string->long double ][ 146 ][ 233 ][ 118 ][ !!! *75* !!! ]] +[[ char->string ][ !!! *8* !!! ][ 136 ][ 22 ][ 13 ]] +[[ unsigned char->string ][ !!! *11* !!! ][ 127 ][ 22 ][ 20 ]] +[[ signed char->string ][ !!! *11* !!! ][ 128 ][ 21 ][ 15 ]] +[[ int->string ][ 25 ][ 159 ][ 30 ][ !!! *20* !!! ]] +[[ short->string ][ 25 ][ 151 ][ 30 ][ !!! *20* !!! ]] +[[ long int->string ][ !!! *20* !!! ][ 150 ][ 30 ][ 20 ]] +[[ long long->string ][ !!! *19* !!! ][ 164 ][ 26 ][ 21 ]] +[[ unsigned int->string ][ 35 ][ 147 ][ 27 ][ !!! *20* !!! ]] +[[ unsigned short->string ][ 26 ][ 149 ][ 26 ][ !!! *20* !!! ]] +[[ unsigned long int->string ][ 19 ][ 142 ][ 38 ][ !!! *17* !!! ]] +[[ unsigned long long->string ][ !!! *20* !!! ][ 139 ][ 36 ][ 26 ]] +[[ bool->string ][ !!! *10* !!! ][ 144 ][ 28 ][ 13 ]] +[[ float->string ][ 166 ][ 268 ][ 127 ][ !!! *52* !!! ]] +[[ double->string ][ 192 ][ 285 ][ 170 ][ !!! *90* !!! ]] +[[ long double->string ][ 250 ][ 344 ][ 160 ][ !!! *85* !!! ]] +[[ char*->char ][ !!! *<1* !!! ][ 90 ][ 9 ][ 8 ]] +[[ char*->signed char ][ !!! *<1* !!! ][ 82 ][ 9 ][ 8 ]] +[[ char*->unsigned char ][ !!! *<1* !!! ][ 88 ][ 8 ][ 13 ]] +[[ char*->int ][ !!! *6* !!! ][ 113 ][ 26 ][ 14 ]] +[[ char*->short ][ !!! *6* !!! ][ 114 ][ 25 ][ 14 ]] +[[ char*->long int ][ !!! *6* !!! ][ 123 ][ 38 ][ 17 ]] +[[ char*->long long ][ !!! *7* !!! ][ 126 ][ 37 ][ 17 ]] +[[ char*->unsigned int ][ !!! *6* !!! ][ 134 ][ 26 ][ 18 ]] +[[ char*->unsigned short ][ !!! *8* !!! ][ 126 ][ 24 ][ 17 ]] +[[ char*->unsigned long int ][ !!! *8* !!! ][ 121 ][ 24 ][ 17 ]] +[[ char*->unsigned long long ][ !!! *5* !!! ][ 117 ][ 24 ][ 18 ]] +[[ char*->bool ][ !!! *<1* !!! ][ 116 ][ 24 ][ 9 ]] +[[ char*->float ][ !!! *16* !!! ][ 171 ][ 67 ][ 30 ]] +[[ char*->double ][ !!! *15* !!! ][ 204 ][ 109 ][ 64 ]] +[[ char*->long double ][ 152 ][ 250 ][ 110 ][ !!! *71* !!! ]] +[[ unsigned char*->char ][ !!! *<1* !!! ][ 109 ][ 11 ][ 11 ]] +[[ unsigned char*->signed char ][ !!! *<1* !!! ][ 108 ][ 11 ][ 9 ]] +[[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 106 ][ 11 ][ 17 ]] +[[ unsigned char*->int ][ !!! *7* !!! ][ 143 ][ 31 ][ 17 ]] +[[ unsigned char*->short ][ !!! *9* !!! ][ 143 ][ 32 ][ 19 ]] +[[ unsigned char*->long int ][ !!! *8* !!! ][ 153 ][ 30 ][ 18 ]] +[[ unsigned char*->long long ][ !!! *10* !!! ][ 146 ][ 27 ][ 18 ]] +[[ unsigned char*->unsigned int ][ !!! *9* !!! ][ 144 ][ 25 ][ 18 ]] +[[ unsigned char*->unsigned short ][ !!! *9* !!! ][ 138 ][ 26 ][ 17 ]] +[[ unsigned char*->unsigned long int ][ !!! *9* !!! ][ 143 ][ 25 ][ 18 ]] +[[ unsigned char*->unsigned long long ][ !!! *10* !!! ][ 132 ][ 26 ][ 18 ]] +[[ unsigned char*->bool ][ !!! *<1* !!! ][ 102 ][ 18 ][ 9 ]] +[[ unsigned char*->float ][ !!! *13* !!! ][ 171 ][ 65 ][ 31 ]] +[[ unsigned char*->double ][ !!! *14* !!! ][ 197 ][ 89 ][ 53 ]] +[[ unsigned char*->long double ][ 122 ][ 208 ][ 89 ][ !!! *58* !!! ]] +[[ unsigned char*->string ][ !!! *8* !!! ][ 115 ][ 20 ][ --- ]] +[[ signed char*->char ][ !!! *<1* !!! ][ 93 ][ 10 ][ 9 ]] +[[ signed char*->signed char ][ !!! *<1* !!! ][ 91 ][ 8 ][ 8 ]] +[[ signed char*->unsigned char ][ !!! *<1* !!! ][ 90 ][ 10 ][ 15 ]] +[[ signed char*->int ][ !!! *7* !!! ][ 112 ][ 26 ][ 16 ]] +[[ signed char*->short ][ !!! *7* !!! ][ 112 ][ 26 ][ 16 ]] +[[ signed char*->long int ][ !!! *6* !!! ][ 118 ][ 25 ][ 14 ]] +[[ signed char*->long long ][ !!! *13* !!! ][ 114 ][ 25 ][ 14 ]] +[[ signed char*->unsigned int ][ !!! *7* !!! ][ 114 ][ 23 ][ 16 ]] +[[ signed char*->unsigned short ][ !!! *7* !!! ][ 107 ][ 25 ][ 16 ]] +[[ signed char*->unsigned long int ][ !!! *7* !!! ][ 106 ][ 23 ][ 14 ]] +[[ signed char*->unsigned long long ][ !!! *7* !!! ][ 103 ][ 22 ][ 16 ]] +[[ signed char*->bool ][ !!! *<1* !!! ][ 110 ][ 20 ][ 9 ]] +[[ signed char*->float ][ !!! *13* !!! ][ 175 ][ 66 ][ 32 ]] +[[ signed char*->double ][ !!! *14* !!! ][ 203 ][ 90 ][ 53 ]] +[[ signed char*->long double ][ 124 ][ 205 ][ 87 ][ !!! *55* !!! ]] +[[ signed char*->string ][ !!! *8* !!! ][ 120 ][ 20 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 116 ][ 28 ][ --- ]] +[[ float->double ][ !!! *<1* !!! ][ 264 ][ 135 ][ --- ]] +[[ double->double ][ !!! *<1* !!! ][ 260 ][ 140 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 275 ][ 135 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 274 ][ 135 ][ --- ]] +[[ char->unsigned char ][ !!! *<1* !!! ][ 77 ][ 7 ][ --- ]] +[[ char->signed char ][ !!! *<1* !!! ][ 79 ][ 7 ][ --- ]] +[[ unsigned char->char ][ !!! *<1* !!! ][ 78 ][ 8 ][ --- ]] +[[ signed char->char ][ !!! *<1* !!! ][ 83 ][ 7 ][ --- ]] +] +[endsect] +[section gcc-4.5][table:id Performance Table (gcc-4.5) +[[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]] +[[ string->char ][ !!! *<1* !!! ][ 86 ][ 8 ][ 9 ]] +[[ string->signed char ][ !!! *<1* !!! ][ 88 ][ 9 ][ 9 ]] +[[ string->unsigned char ][ !!! *<1* !!! ][ 87 ][ 8 ][ 15 ]] +[[ string->int ][ !!! *6* !!! ][ 107 ][ 23 ][ 16 ]] +[[ string->short ][ !!! *7* !!! ][ 108 ][ 25 ][ 15 ]] +[[ string->long int ][ !!! *6* !!! ][ 110 ][ 26 ][ 15 ]] +[[ string->long long ][ !!! *7* !!! ][ 110 ][ 26 ][ 15 ]] +[[ string->unsigned int ][ !!! *6* !!! ][ 108 ][ 26 ][ 16 ]] +[[ string->unsigned short ][ !!! *7* !!! ][ 105 ][ 24 ][ 15 ]] +[[ string->unsigned long int ][ !!! *6* !!! ][ 108 ][ 23 ][ 15 ]] +[[ string->unsigned long long ][ !!! *10* !!! ][ 104 ][ 24 ][ 15 ]] +[[ string->bool ][ !!! *<1* !!! ][ 102 ][ 21 ][ 9 ]] +[[ string->float ][ !!! *13* !!! ][ 173 ][ 64 ][ 34 ]] +[[ string->double ][ !!! *15* !!! ][ 196 ][ 89 ][ 53 ]] +[[ string->long double ][ 126 ][ 211 ][ 90 ][ !!! *56* !!! ]] +[[ char->string ][ !!! *8* !!! ][ 107 ][ 20 ][ 10 ]] +[[ unsigned char->string ][ !!! *8* !!! ][ 107 ][ 17 ][ 15 ]] +[[ signed char->string ][ !!! *8* !!! ][ 108 ][ 19 ][ 10 ]] +[[ int->string ][ 16 ][ 129 ][ 25 ][ !!! *15* !!! ]] +[[ short->string ][ !!! *14* !!! ][ 128 ][ 25 ][ 17 ]] +[[ long int->string ][ 20 ][ 128 ][ 24 ][ !!! *15* !!! ]] +[[ long long->string ][ !!! *16* !!! ][ 128 ][ 25 ][ 16 ]] +[[ unsigned int->string ][ !!! *15* !!! ][ 125 ][ 25 ][ 15 ]] +[[ unsigned short->string ][ !!! *14* !!! ][ 125 ][ 24 ][ 15 ]] +[[ unsigned long int->string ][ 16 ][ 125 ][ 25 ][ !!! *15* !!! ]] +[[ unsigned long long->string ][ !!! *18* !!! ][ 140 ][ 32 ][ 22 ]] +[[ bool->string ][ !!! *8* !!! ][ 121 ][ 24 ][ 10 ]] +[[ float->string ][ 137 ][ 226 ][ 108 ][ !!! *48* !!! ]] +[[ double->string ][ 174 ][ 255 ][ 141 ][ !!! *71* !!! ]] +[[ long double->string ][ 208 ][ 268 ][ 144 ][ !!! *72* !!! ]] +[[ char*->char ][ !!! *<1* !!! ][ 93 ][ 8 ][ 9 ]] +[[ char*->signed char ][ !!! *<1* !!! ][ 94 ][ 9 ][ 9 ]] +[[ char*->unsigned char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 15 ]] +[[ char*->int ][ !!! *7* !!! ][ 115 ][ 26 ][ 16 ]] +[[ char*->short ][ !!! *8* !!! ][ 114 ][ 26 ][ 15 ]] +[[ char*->long int ][ !!! *7* !!! ][ 115 ][ 27 ][ 16 ]] +[[ char*->long long ][ !!! *7* !!! ][ 114 ][ 26 ][ 16 ]] +[[ char*->unsigned int ][ !!! *8* !!! ][ 115 ][ 25 ][ 16 ]] +[[ char*->unsigned short ][ !!! *7* !!! ][ 113 ][ 24 ][ 16 ]] +[[ char*->unsigned long int ][ !!! *8* !!! ][ 117 ][ 23 ][ 16 ]] +[[ char*->unsigned long long ][ !!! *8* !!! ][ 107 ][ 25 ][ 16 ]] +[[ char*->bool ][ !!! *<1* !!! ][ 110 ][ 21 ][ 9 ]] +[[ char*->float ][ !!! *17* !!! ][ 170 ][ 67 ][ 34 ]] +[[ char*->double ][ !!! *14* !!! ][ 197 ][ 91 ][ 52 ]] +[[ char*->long double ][ 127 ][ 206 ][ 89 ][ !!! *56* !!! ]] +[[ unsigned char*->char ][ !!! *<1* !!! ][ 83 ][ 8 ][ 9 ]] +[[ unsigned char*->signed char ][ !!! *<1* !!! ][ 83 ][ 10 ][ 9 ]] +[[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 83 ][ 8 ][ 15 ]] +[[ unsigned char*->int ][ !!! *7* !!! ][ 113 ][ 26 ][ 16 ]] +[[ unsigned char*->short ][ !!! *7* !!! ][ 112 ][ 24 ][ 16 ]] +[[ unsigned char*->long int ][ !!! *8* !!! ][ 114 ][ 26 ][ 16 ]] +[[ unsigned char*->long long ][ !!! *8* !!! ][ 113 ][ 26 ][ 16 ]] +[[ unsigned char*->unsigned int ][ !!! *8* !!! ][ 114 ][ 25 ][ 16 ]] +[[ unsigned char*->unsigned short ][ !!! *8* !!! ][ 109 ][ 24 ][ 16 ]] +[[ unsigned char*->unsigned long int ][ !!! *8* !!! ][ 111 ][ 23 ][ 16 ]] +[[ unsigned char*->unsigned long long ][ !!! *7* !!! ][ 106 ][ 25 ][ 16 ]] +[[ unsigned char*->bool ][ !!! *<1* !!! ][ 106 ][ 20 ][ 9 ]] +[[ unsigned char*->float ][ !!! *14* !!! ][ 169 ][ 65 ][ 34 ]] +[[ unsigned char*->double ][ !!! *16* !!! ][ 198 ][ 91 ][ 52 ]] +[[ unsigned char*->long double ][ 127 ][ 205 ][ 88 ][ !!! *56* !!! ]] +[[ unsigned char*->string ][ !!! *10* !!! ][ 123 ][ 21 ][ --- ]] +[[ signed char*->char ][ !!! *<1* !!! ][ 90 ][ 9 ][ 9 ]] +[[ signed char*->signed char ][ !!! *<1* !!! ][ 91 ][ 8 ][ 9 ]] +[[ signed char*->unsigned char ][ !!! *<1* !!! ][ 92 ][ 8 ][ 15 ]] +[[ signed char*->int ][ !!! *7* !!! ][ 116 ][ 26 ][ 16 ]] +[[ signed char*->short ][ !!! *8* !!! ][ 113 ][ 26 ][ 15 ]] +[[ signed char*->long int ][ !!! *8* !!! ][ 113 ][ 24 ][ 16 ]] +[[ signed char*->long long ][ !!! *8* !!! ][ 113 ][ 27 ][ 16 ]] +[[ signed char*->unsigned int ][ !!! *8* !!! ][ 113 ][ 25 ][ 16 ]] +[[ signed char*->unsigned short ][ !!! *7* !!! ][ 107 ][ 24 ][ 16 ]] +[[ signed char*->unsigned long int ][ !!! *7* !!! ][ 111 ][ 23 ][ 17 ]] +[[ signed char*->unsigned long long ][ !!! *8* !!! ][ 105 ][ 25 ][ 16 ]] +[[ signed char*->bool ][ !!! *<1* !!! ][ 106 ][ 21 ][ 9 ]] +[[ signed char*->float ][ !!! *13* !!! ][ 169 ][ 63 ][ 34 ]] +[[ signed char*->double ][ !!! *16* !!! ][ 196 ][ 90 ][ 52 ]] +[[ signed char*->long double ][ 127 ][ 211 ][ 91 ][ !!! *60* !!! ]] +[[ signed char*->string ][ !!! *9* !!! ][ 123 ][ 21 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 120 ][ 29 ][ --- ]] +[[ float->double ][ !!! *<1* !!! ][ 258 ][ 147 ][ --- ]] +[[ double->double ][ !!! *<1* !!! ][ 261 ][ 140 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 266 ][ 138 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 266 ][ 137 ][ --- ]] +[[ char->unsigned char ][ !!! *<1* !!! ][ 89 ][ 8 ][ --- ]] +[[ char->signed char ][ !!! *<1* !!! ][ 91 ][ 8 ][ --- ]] +[[ unsigned char->char ][ !!! *<1* !!! ][ 90 ][ 9 ][ --- ]] +[[ signed char->char ][ !!! *<1* !!! ][ 89 ][ 8 ][ --- ]] +] +[endsect] +[section intel-12-linux][table:id Performance Table (intel-12-linux) +[[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]] +[[ string->char ][ !!! *1* !!! ][ 87 ][ 9 ][ 8 ]] +[[ string->signed char ][ !!! *<1* !!! ][ 90 ][ 9 ][ 8 ]] +[[ string->unsigned char ][ !!! *<1* !!! ][ 99 ][ 9 ][ 20 ]] +[[ string->int ][ !!! *8* !!! ][ 112 ][ 24 ][ 16 ]] +[[ string->short ][ !!! *8* !!! ][ 110 ][ 26 ][ 16 ]] +[[ string->long int ][ !!! *7* !!! ][ 110 ][ 23 ][ 16 ]] +[[ string->long long ][ !!! *10* !!! ][ 114 ][ 31 ][ 16 ]] +[[ string->unsigned int ][ !!! *7* !!! ][ 122 ][ 25 ][ 16 ]] +[[ string->unsigned short ][ !!! *7* !!! ][ 120 ][ 27 ][ 16 ]] +[[ string->unsigned long int ][ !!! *7* !!! ][ 114 ][ 25 ][ 16 ]] +[[ string->unsigned long long ][ !!! *7* !!! ][ 128 ][ 23 ][ 25 ]] +[[ string->bool ][ !!! *1* !!! ][ 103 ][ 20 ][ 9 ]] +[[ string->float ][ !!! *15* !!! ][ 166 ][ 73 ][ 31 ]] +[[ string->double ][ !!! *19* !!! ][ 206 ][ 103 ][ 56 ]] +[[ string->long double ][ 142 ][ 205 ][ 106 ][ !!! *61* !!! ]] +[[ char->string ][ !!! *10* !!! ][ 111 ][ 19 ][ 12 ]] +[[ unsigned char->string ][ !!! *12* !!! ][ 109 ][ 19 ][ 16 ]] +[[ signed char->string ][ !!! *9* !!! ][ 110 ][ 18 ][ 12 ]] +[[ int->string ][ 19 ][ 126 ][ 23 ][ !!! *17* !!! ]] +[[ short->string ][ 20 ][ 127 ][ 23 ][ !!! *18* !!! ]] +[[ long int->string ][ 20 ][ 128 ][ 24 ][ !!! *18* !!! ]] +[[ long long->string ][ !!! *16* !!! ][ 129 ][ 23 ][ 22 ]] +[[ unsigned int->string ][ 20 ][ 126 ][ 23 ][ !!! *17* !!! ]] +[[ unsigned short->string ][ 20 ][ 126 ][ 23 ][ !!! *17* !!! ]] +[[ unsigned long int->string ][ 20 ][ 126 ][ 23 ][ !!! *17* !!! ]] +[[ unsigned long long->string ][ !!! *24* !!! ][ 134 ][ 35 ][ 24 ]] +[[ bool->string ][ !!! *9* !!! ][ 124 ][ 29 ][ 12 ]] +[[ float->string ][ 147 ][ 218 ][ 104 ][ !!! *48* !!! ]] +[[ double->string ][ 202 ][ 245 ][ 128 ][ !!! *68* !!! ]] +[[ long double->string ][ 199 ][ 236 ][ 128 ][ !!! *69* !!! ]] +[[ char*->char ][ !!! *1* !!! ][ 91 ][ 10 ][ 9 ]] +[[ char*->signed char ][ !!! *1* !!! ][ 98 ][ 10 ][ 9 ]] +[[ char*->unsigned char ][ !!! *1* !!! ][ 97 ][ 14 ][ 15 ]] +[[ char*->int ][ !!! *8* !!! ][ 114 ][ 24 ][ 16 ]] +[[ char*->short ][ !!! *8* !!! ][ 112 ][ 27 ][ 15 ]] +[[ char*->long int ][ !!! *8* !!! ][ 117 ][ 28 ][ 16 ]] +[[ char*->long long ][ !!! *8* !!! ][ 123 ][ 30 ][ 16 ]] +[[ char*->unsigned int ][ !!! *8* !!! ][ 120 ][ 26 ][ 16 ]] +[[ char*->unsigned short ][ !!! *8* !!! ][ 122 ][ 30 ][ 16 ]] +[[ char*->unsigned long int ][ !!! *10* !!! ][ 119 ][ 25 ][ 16 ]] +[[ char*->unsigned long long ][ !!! *8* !!! ][ 140 ][ 54 ][ 34 ]] +[[ char*->bool ][ !!! *1* !!! ][ 108 ][ 21 ][ 8 ]] +[[ char*->float ][ !!! *16* !!! ][ 177 ][ 76 ][ 33 ]] +[[ char*->double ][ !!! *18* !!! ][ 271 ][ 104 ][ 56 ]] +[[ char*->long double ][ 142 ][ 207 ][ 106 ][ !!! *61* !!! ]] +[[ unsigned char*->char ][ !!! *1* !!! ][ 91 ][ 10 ][ 9 ]] +[[ unsigned char*->signed char ][ !!! *1* !!! ][ 92 ][ 10 ][ 8 ]] +[[ unsigned char*->unsigned char ][ !!! *1* !!! ][ 92 ][ 10 ][ 15 ]] +[[ unsigned char*->int ][ !!! *8* !!! ][ 111 ][ 24 ][ 16 ]] +[[ unsigned char*->short ][ !!! *9* !!! ][ 113 ][ 27 ][ 16 ]] +[[ unsigned char*->long int ][ !!! *7* !!! ][ 113 ][ 28 ][ 16 ]] +[[ unsigned char*->long long ][ !!! *7* !!! ][ 120 ][ 29 ][ 15 ]] +[[ unsigned char*->unsigned int ][ !!! *7* !!! ][ 119 ][ 24 ][ 15 ]] +[[ unsigned char*->unsigned short ][ !!! *8* !!! ][ 116 ][ 28 ][ 15 ]] +[[ unsigned char*->unsigned long int ][ !!! *7* !!! ][ 118 ][ 25 ][ 16 ]] +[[ unsigned char*->unsigned long long ][ !!! *7* !!! ][ 116 ][ 25 ][ 16 ]] +[[ unsigned char*->bool ][ !!! *1* !!! ][ 102 ][ 20 ][ 9 ]] +[[ unsigned char*->float ][ !!! *16* !!! ][ 167 ][ 74 ][ 31 ]] +[[ unsigned char*->double ][ !!! *19* !!! ][ 231 ][ 109 ][ 55 ]] +[[ unsigned char*->long double ][ 141 ][ 214 ][ 109 ][ !!! *61* !!! ]] +[[ unsigned char*->string ][ !!! *12* !!! ][ 122 ][ 23 ][ --- ]] +[[ signed char*->char ][ !!! *1* !!! ][ 91 ][ 10 ][ 8 ]] +[[ signed char*->signed char ][ !!! *1* !!! ][ 92 ][ 10 ][ 9 ]] +[[ signed char*->unsigned char ][ !!! *1* !!! ][ 92 ][ 10 ][ 15 ]] +[[ signed char*->int ][ !!! *7* !!! ][ 117 ][ 34 ][ 16 ]] +[[ signed char*->short ][ !!! *8* !!! ][ 117 ][ 25 ][ 15 ]] +[[ signed char*->long int ][ !!! *7* !!! ][ 115 ][ 28 ][ 16 ]] +[[ signed char*->long long ][ !!! *8* !!! ][ 116 ][ 31 ][ 15 ]] +[[ signed char*->unsigned int ][ !!! *8* !!! ][ 123 ][ 27 ][ 16 ]] +[[ signed char*->unsigned short ][ !!! *8* !!! ][ 120 ][ 27 ][ 16 ]] +[[ signed char*->unsigned long int ][ !!! *7* !!! ][ 119 ][ 26 ][ 16 ]] +[[ signed char*->unsigned long long ][ !!! *7* !!! ][ 118 ][ 26 ][ 17 ]] +[[ signed char*->bool ][ !!! *1* !!! ][ 108 ][ 26 ][ 9 ]] +[[ signed char*->float ][ !!! *16* !!! ][ 170 ][ 73 ][ 31 ]] +[[ signed char*->double ][ !!! *18* !!! ][ 210 ][ 112 ][ 55 ]] +[[ signed char*->long double ][ 137 ][ 210 ][ 107 ][ !!! *61* !!! ]] +[[ signed char*->string ][ !!! *14* !!! ][ 121 ][ 23 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 115 ][ 26 ][ --- ]] +[[ float->double ][ !!! *<1* !!! ][ 266 ][ 155 ][ --- ]] +[[ double->double ][ !!! *<1* !!! ][ 267 ][ 157 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 261 ][ 153 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 264 ][ 152 ][ --- ]] +[[ char->unsigned char ][ !!! *<1* !!! ][ 96 ][ 9 ][ --- ]] +[[ char->signed char ][ !!! *<1* !!! ][ 96 ][ 9 ][ --- ]] +[[ unsigned char->char ][ !!! *<1* !!! ][ 93 ][ 9 ][ --- ]] +[[ signed char->char ][ !!! *<1* !!! ][ 87 ][ 9 ][ --- ]] +] +[endsect] + + + +[/ END of section, generated by performance measuring program ] +[endsect] + From fa7f4ba7a729b6d42258ba7db9173d9b5d8e5e29 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Thu, 21 Jul 2011 07:35:29 +0000 Subject: [PATCH 098/242] Link up the new lexical cast documentation. [SVN r73267] --- index.html | 2 +- lexical_cast.htm | 362 ++--------------------------------------------- 2 files changed, 12 insertions(+), 352 deletions(-) diff --git a/index.html b/index.html index cf8527f..133680c 100644 --- a/index.html +++ b/index.html @@ -24,7 +24,7 @@ supplied by several headers:

      and polymorphic_downcast<> to perform safe casting between polymorphic types.
      -
    • The boost/lexical_cast header provides lexical_cast<> +
    • The boost/lexical_cast header provides lexical_cast<> general literal text conversions, such as an int represented as a string, or vice-versa.
    • diff --git a/lexical_cast.htm b/lexical_cast.htm index 35c6e58..73b6ba5 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -1,356 +1,16 @@ - - - - - lexical_cast - - - - -

      boost.png (6897 bytes)Header - boost/lexical_cast.hpp

      - -
      -

      Motivation

      - Sometimes a value must be converted to a literal text form, such as an int - represented as a string, or vice-versa, when a string - is interpreted as an int. Such examples are common when converting - between data types internal to a program and representation external to a - program, such as windows and configuration files. -

      - The standard C and C++ libraries offer a number of facilities for performing - such conversions. However, they vary with their ease of use, extensibility, and - safety. -

      - For instance, there are a number of limitations with the family of standard C - functions typified by atoi: -

        -
      • - Conversion is supported in one direction only: from text to internal data type. - Converting the other way using the C library requires either the inconvenience - and compromised safety of the sprintf function, or the loss of - portability associated with non-standard functions such as itoa. -
      • -
      • - The range of types supported is only a subset of the built-in numeric types, - namely int, long, and double. -
      • -
      • - The range of types cannot be extended in a uniform manner. For instance, - conversion from string representation to complex or rational. -
      • -
      - The standard C functions typified by strtol have the same basic - limitations, but offer finer control over the conversion process. However, for - the common case such control is often either not required or not used. The scanf - family of functions offer even greater control, but also lack safety and ease - of use. -

      - The standard C++ library offers stringstream for the kind of - in-core formatting being discussed. It offers a great deal of control over the - formatting and conversion of I/O to and from arbitrary types through text. - However, for simple conversions direct use of stringstream can be - either clumsy (with the introduction of extra local variables and the loss of - infix-expression convenience) or obscure (where stringstream - objects are created as temporary objects in an expression). Facets provide a - comprehensive concept and facility for controlling textual representation, but - their perceived complexity and high entry level requires an extreme degree of - involvement for simple conversions, and excludes all but a few programmers. -

      - The lexical_cast function template offers a convenient and - consistent form for supporting common conversions to and from arbitrary types - when they are represented as text. The simplification it offers is in - expression-level convenience for such conversions. For more involved - conversions, such as where precision or formatting need tighter control than is - offered by the default behavior of lexical_cast, the conventional - stringstream approach is recommended. Where the conversions are - numeric to numeric, numeric_cast - may offer more reasonable behavior than lexical_cast. -

      - For a good discussion of the options and issues involved in string-based - formatting, including comparison of stringstream, lexical_cast, - and others, see Herb Sutter's article, - The String Formatters of Manor Farm. Also, take a look at the Performance section. -

      -


      -

      Examples

      - The following example treats command line arguments as a sequence of numeric - data:
      -
      int main(int argc, char * argv[])
      -{
      -    using boost::lexical_cast;
      -    using boost::bad_lexical_cast;
       
      -    std::vector<short> args;
      -
      -    while(*++argv)
      -    {
      -        try
      -        {
      -            args.push_back(lexical_cast<short>(*argv));
      -        }
      -        catch(bad_lexical_cast &)
      -        {
      -            args.push_back(0);
      -        }
      -    }
      -    ...
      -}
      -
      -
      The following example uses numeric data in a string expression:
      -
      void log_message(const std::string &);
      -
      -void log_errno(int yoko)
      -{
      -    log_message("Error " + boost::lexical_cast<std::string>(yoko) + ": " + strerror(yoko));
      -}
      -
      -
      -
      -

      Synopsis

      - Library features defined in "boost/lexical_cast.hpp": -
      -
      namespace boost
      -{
      -    class bad_lexical_cast;
      -    template<typename Target, typename Source>
      -      Target lexical_cast(const Source& arg);
      -}
      -
      -
      Unit test defined in "lexical_cast_test.cpp". -

      -


      -

      lexical_cast

      -
      -
      template<typename Target, typename Source>
      -  Target lexical_cast(const Source& arg);
      -
      -
      Returns the result of streaming arg into a - standard library string-based stream and then out as a Target object. - Where Target is either std::string - or std::wstring, stream extraction takes the whole content - of the string, including spaces, rather than relying on the default - operator>> behavior. - If the conversion is unsuccessful, a - bad_lexical_cast exception is thrown. -

      - The requirements on the argument and result types are: -

        -
      • - Source is OutputStreamable, meaning that an operator<< - is defined that takes a std::ostream or std::wostream object on the - left hand side and an instance of the argument type on the right. -
      • -
      • - Target is InputStreamable, meaning that an operator>> - is defined that takes a std::istream or std::wistream object on the left hand side - and an instance of the result type on the right. -
      • -
      • - Target is CopyConstructible [20.1.3]. -
      • -
      • - Target is DefaultConstructible, meaning that it is possible - to default-initialize an object of that type [8.5, 20.1.4]. -
      • -
      - The character type of the underlying stream is assumed to be char unless - either the Source or the Target requires wide-character - streaming, in which case the underlying stream uses wchar_t. - Source types that require wide-character streaming are wchar_t, - wchar_t *, and std::wstring. Target types that - require wide-character streaming are wchar_t and std::wstring. -

      - Where a higher degree of control is required over conversions, std::stringstream - and std::wstringstream offer a more appropriate path. Where non-stream-based conversions are - required, lexical_cast - is the wrong tool for the job and is not special-cased for such scenarios. -

      -


      -

      bad_lexical_cast

      -
      -
      class bad_lexical_cast : public std::bad_cast
      -{
      -public:
      -    ... // same member function interface as std::exception
      -};
      -
      -
      Exception used to indicate runtime lexical_cast - failure. - -
      - - -

      Frequently Asked Questions

      -
      From->To target = lexical_cast<Target>(source); std::stringstream ss;
      ss << source;
      ss >> target;
      ss << source;
      ss >> target;
      ss.str(std::string());
      ss.clear();
      sscanf( (const char*)source, <...>, &target);
      OR
      sprintf( (char*)buffer, <...>, source);
      - target = buffer;
      From->To lexical_cast std::stringstream
      with construction
      std::stringstream
      without construction
      sscanf/sprintf
      string->char<191710
      string->int71152318
      string->unsigned int71172217
      string->int71152318
      string->unsigned int71172217
      string->bool<11041910
      string->float851726033
      string->float131726033
      char->string71051612
      int->string151312117
      unsigned int->string141252117
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Question:Why does lexical_cast<int8_t>("127") throw bad_lexical_cast?
      Answer:The type int8_t is a typedef to char or signed char. - Lexical conversion to these types is simply reading a byte from source but since the source has - more than one byte, the exception is thrown. - Please use other integer types such as int or short int. If bounds checking - is important, you can also call numeric_cast: -
      numeric_cast<int8_t>(lexical_cast<int>("127"));
      -
      Question:What does lexical_cast<std::string> of an int8_t or uint8_t not do what I expect?
      Answer:As above, note that int8_t and uint8_t are actually chars and are formatted as such. To avoid this, cast to an integer type first: -
      lexical_cast<std::string>(static_cast<int>(n));
      -
      Question:The implementation always resets the ios_base::skipws flag of an underlying stream object. It breaks my operator>> that works only in presence of this flag. Can you remove code that resets the flag?
      Answer:May be in a future version. There is no requirement in [N1973] to reset the flag but remember that [N1973] is not yet accepted by the committee. By the way, it's a great opportunity to make your operator>> conform to the standard. Read a good C++ book, study std::sentry and ios_state_saver. -
      Question:Why std::cout << boost::lexical_cast<unsigned int>("-1"); does not throw, but outputs 4294967295?
      Answer:boost::lexical_cast has the behavior of stringstream, which uses num_get functions of std::locale to convert numbers. If we look at the [22.2.2.1.2] of Programming languages — C++, we'll see, that num_get uses the rules of scanf for conversions. And in the C99 standard for unsigned input value minus sign is optional, so if a negative number is read, no errors will arise and the result will be the two's complement. -
      - -

      References

      -
        -
      • [N1973] Kevlin Henney, Beman Dawes, Lexical Conversion Library Proposal for TR2, - N1973. -
      • [Tuning] Alexander Nasonov, Fine Tuning for lexical_cast, - Overload #74 (PDF), - August 2006.
      • -
      -

      Changes

      -

      July 2011:

      -
        -
      • Added code to work with Inf and NaN on any platform.
      • -
      • Better performance and less memory usage for conversions to float type (and to double type, if sizeof(double)<sizeof(long double)).
      • -
      -

      May 2011:

      -
        -
      • Optimizations for "C" and other locales without number grouping.
      • -
      • 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).
      • -
      -

      August, October 2006:

      -
        -
      • Better performance for many combinations of Source and Target - types. Refer to [Tuning] for more details. -
      • -
      -

      June 2005:

      -
        -
      • Call-by-const reference for the parameters. This requires partial specialization - of class templates, so it doesn't work for MSVC 6, and it uses the original - pass by value there.
        -
      • -
      • The MSVC 6 support is deprecated, and will be removed in a future Boost - version.
      • -
      -

      Earlier:

      - -
        -
      • The previous version of lexical_cast used the default stream - precision for reading and writing floating-point numbers. For numerics that - have a corresponding specialization of std::numeric_limits, the - current version now chooses a precision to match.
        -
      • The previous version of lexical_cast did not support conversion - to or from any wide-character-based types. For compilers with full language - and library support for wide characters, lexical_cast now supports - conversions from wchar_t, wchar_t *, and std::wstring - and to wchar_t and std::wstring.
        -
      • The previous version of lexical_cast assumed that the conventional - stream extractor operators were sufficient for reading values. However, string - I/O is asymmetric, with the result that spaces play the role of I/O separators - rather than string content. The current version fixes this error for std::string - and, where supported, std::wstring: lexical_cast<std::string>("Hello, - World") succeeds instead of failing with a bad_lexical_cast - exception.
        -
      • The previous version of lexical_cast allowed unsafe and meaningless - conversions to pointers. The current version now throws a bad_lexical_cast - for conversions to pointers: lexical_cast<char *>("Goodbye, World") - now throws an exception instead of causing undefined behavior. -
      -

      -


      - -

      Performance

      -This table shows the execution time in milliseconds for 100000 calls of the following string formatters: - - - - - - - - - - - - - - - - - -
      From->To lexical_cast std::stringstream
      with construction
      std::stringstream
      without construction
      sscanf/sprintf
      string->char<191710
      string->int71152318
      string->unsigned int71172217
      string->bool<11041910
      string->float131726033
      char->string71051612
      int->string151312117
      unsigned int->string141252117
      bool->string71222412
      float->string12422311548
      char*->string912320---
      int->int<112026---
      float->float<1262142---
      - -Fastest results are highlitened with green. -
      -
      Copyright © Kevlin Henney, 2000-2005
      -
      Copyright © Alexander Nasonov, 2006-2010
      -
      Copyright © Antony Polukhin, 2011
      -
      - 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) -
      - + + + + + +Automatic redirection failed, please go to +../../doc/html/boost_lexical_cast.html + From c372f482a2e583d53a996669e6b3a415e9242d93 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 21 Jul 2011 08:20:35 +0000 Subject: [PATCH 099/242] Fixes #5723. Fixes broken link [SVN r73269] --- doc/lexical_cast.qbk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index 8ce54cb..f8a9b7c 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -73,7 +73,7 @@ The following example uses numeric data in a string expression: [endsect] [section Synopsis] -Library features defined in [@../../boost/lexical_cast.hpp boost/lexical_cast.hpp]: +Library features defined in [@http://www.boost.org/boost/lexical_cast.hpp boost/lexical_cast.hpp]: `` namespace boost { From c1c8485cb43559a069e02cfdad93bb786b52a7e2 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 21 Jul 2011 15:35:11 +0000 Subject: [PATCH 100/242] Fixes #5723. Links in documentation are now implemented via [@boost: ] [SVN r73277] --- doc/lexical_cast.qbk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index f8a9b7c..f5beec7 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -13,7 +13,7 @@ ] ] -[def __numericcast__ [@http://www.boost.org/libs/numeric/conversion/doc/html/boost_numericconversion/improved_numeric_cast__.html `boost::numeric_cast`]] +[def __numericcast__ [@boost:libs/numeric/conversion/doc/html/boost_numericconversion/improved_numeric_cast__.html `boost::numeric_cast`]] [def __proposallong__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1973.html Lexical Conversion Library Proposal for TR2, N1973 by Kevlin Henney and Beman Dawes]] [def __proposalshort__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1973.html Lexical Conversion Library Proposal for TR2, N1973]] @@ -73,7 +73,7 @@ The following example uses numeric data in a string expression: [endsect] [section Synopsis] -Library features defined in [@http://www.boost.org/boost/lexical_cast.hpp boost/lexical_cast.hpp]: +Library features defined in [@boost:boost/lexical_cast.hpp boost/lexical_cast.hpp]: `` namespace boost { @@ -136,7 +136,7 @@ It breaks my `operator>>` that works only in presence of this flag. Can you remo __proposallong__ to reset the flag but remember that __proposalshort__ is not yet accepted by the committee. By the way, it's a great opportunity to make your `operator>>` conform to the standard. -Read a good C++ book, study `std::sentry` and [@../../libs/io/doc/ios_state.html `ios_state_saver`]. +Read a good C++ book, study `std::sentry` and [@boost:libs/io/doc/ios_state.html `ios_state_saver`]. * [*Question:] Why `std::cout << boost::lexical_cast("-1");` does not throw, but outputs 4294967295? From 8a756eae7bba379765c17aebbe5ae7596b339e2e Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sat, 23 Jul 2011 15:55:54 +0000 Subject: [PATCH 101/242] Fixes #5732. * reduces templates count * leaves only one lexical converting class (at least for modern compilers) * fixes small TODOs and XXXs from source code * makes lexical_stream_limited_src more readable * updates status/explicit-failures-markup.xml * makes lexical_cast_inf_nan_test.cpp pass on Itanium pltform * makes lexical_cast able to convert signed and unsigned chars to wchar_t and updates lexical_cast_wchars_test [SVN r73313] --- include/boost/lexical_cast.hpp | 1162 ++++++++-------------------- test/lexical_cast_inf_nan_test.cpp | 13 + test/lexical_cast_wchars_test.cpp | 8 +- 3 files changed, 356 insertions(+), 827 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 99aeb24..58fdea8 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -47,7 +46,12 @@ #include #ifndef BOOST_NO_STD_LOCALE -#include +# include +#else +# ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE +# warning "Unable to use header. boost::lexical_cast will use the 'C' locale." +# define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE +# endif #endif #ifdef BOOST_NO_STRINGSTREAM @@ -223,156 +227,17 @@ namespace boost namespace detail // lcast_src_length { // Return max. length of string representation of Source; - // 0 if unlimited (with exceptions for some types, see below). - // Values with limited string representation are placed to - // the buffer locally defined in lexical_cast function. - // 1 is returned for few types such as CharT const* or - // std::basic_string that already have an internal - // buffer ready to be reused by lexical_stream_limited_src. - // Each specialization should have a correspondent operator<< - // defined in lexical_stream_limited_src. template< class CharT // A result of widest_char transformation. , class Source // Source type of lexical_cast. > struct lcast_src_length { - BOOST_STATIC_CONSTANT(std::size_t, value = 0); + BOOST_STATIC_CONSTANT(std::size_t, value = 1); // To check coverage, build the test with // bjam --v2 profile optimization=off 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() {} - }; - 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<> - 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_NO_INTRINSIC_WCHAR_T - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; -#endif -#endif - - 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<> - 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() {} - }; -#endif - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct lcast_src_length< CharT, std::basic_string > - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; -#else - template<> - struct lcast_src_length< char, std::basic_string > - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - -#ifndef BOOST_LCAST_NO_WCHAR_T - template<> - struct lcast_src_length< wchar_t, std::basic_string > - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; -#endif -#endif - // Helper for integral types. // Notes on length calculation: // Max length for 32bit int with grouping "\1" and thousands_sep ',': @@ -530,13 +395,6 @@ namespace boost #endif } - namespace detail // lexical_streambuf_fake - { - struct lexical_streambuf_fake - { - }; - } - namespace detail // lcast_to_unsigned { #if (defined _MSC_VER) @@ -575,7 +433,6 @@ namespace boost int_type const zero = Traits::to_int_type(czero); #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - // TODO: use BOOST_NO_STD_LOCALE std::locale loc; typedef std::numpunct numpunct; numpunct const& np = BOOST_USE_FACET(numpunct, loc); @@ -654,7 +511,6 @@ namespace boost T multiplier = 1; #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - // TODO: use BOOST_NO_STD_LOCALE std::locale loc; typedef std::numpunct numpunct; numpunct const& np = BOOST_USE_FACET(numpunct, loc); @@ -911,7 +767,6 @@ namespace boost { #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - // TODO: use BOOST_NO_STD_LOCALE std::locale loc; typedef std::numpunct numpunct; numpunct const& np = BOOST_USE_FACET(numpunct, loc); @@ -1115,7 +970,7 @@ namespace boost * with long doubles (and with doubles if sizeof(double)==sizeof(long double)). */ long double result = std::pow(10.0L, pow_of_10) * mantissa; - value = static_cast( has_minus ? -1 * result : result); + value = static_cast( has_minus ? (boost::math::changesign)(result) : result); if ( (boost::math::isinf)(value) || (boost::math::isnan)(value) ) return false; @@ -1123,92 +978,23 @@ namespace boost } } - namespace detail // stream wrapper for handling lexical conversions + namespace detail // stl_buf_unlocker { - template - class lexical_stream - { - private: - typedef typename widest_char< - typename stream_char::type, - typename stream_char::type>::type char_type; - - typedef Traits traits_type; - + template< class BufferType, class CharT > + class stl_buf_unlocker: public BufferType{ public: - lexical_stream(char_type* = 0, char_type* = 0) - { - stream.unsetf(std::ios::skipws); - lcast_set_precision(stream, static_cast(0), static_cast(0) ); - } - ~lexical_stream() - { - #if defined(BOOST_NO_STRINGSTREAM) - stream.freeze(false); - #endif - } - bool operator<<(const Source &input) - { - return !(stream << input).fail(); - } - template - bool operator>>(InputStreamable &output) - { - return !is_pointer::value && - stream >> output && - stream.get() == -#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) -// GCC 2.9x lacks std::char_traits<>::eof(). -// We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 -// configurations, which do provide std::char_traits<>::eof(). - - EOF; + typedef BufferType base_class; +#ifndef BOOST_NO_USING_TEMPLATE + using base_class::pptr; + using base_class::pbase; + using base_class::setg; + using base_class::setp; #else - traits_type::eof(); + CharT* pptr() const { return base_class::pptr(); } + CharT* pbase() const { return base_class::pbase(); } + void setg(CharT* gbeg, CharT* gnext, CharT* gend){ return base_class::setg(gbeg, gnext, gend); } + void setp(CharT* pbeg, CharT* pend) { return setp(pbeg, pend); } #endif - } - -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - bool operator>>(std::string &output) - { - #if defined(BOOST_NO_STRINGSTREAM) - stream << '\0'; - #endif - stream.str().swap(output); - return true; - } - #ifndef BOOST_LCAST_NO_WCHAR_T - bool operator>>(std::wstring &output) - { - stream.str().swap(output); - return true; - } - #endif - -#else - bool operator>>(std::basic_string& output) - { - stream.str().swap(output); - return true; - } - - template - bool operator>>(std::basic_string& out) - { - std::basic_string str(stream.str()); - out.assign(str.begin(), str.end()); - return true; - } -#endif - private: - #if defined(BOOST_NO_STRINGSTREAM) - std::strstream stream; - #elif defined(BOOST_NO_STD_LOCALE) - std::stringstream stream; - #else - std::basic_stringstream stream; - #endif }; } @@ -1216,66 +1002,133 @@ namespace boost { // String representation of Source has an upper limit. template< class CharT // a result of widest_char transformation - , class Base // lexical_streambuf_fake or basic_streambuf , class Traits // usually char_traits > - class lexical_stream_limited_src : public Base + class lexical_stream_limited_src { + typedef stl_buf_unlocker, CharT > local_streambuffer_t; + +#if defined(BOOST_NO_STRINGSTREAM) + typedef stl_buf_unlocker local_stringbuffer_t; +#elif defined(BOOST_NO_STD_LOCALE) + typedef stl_buf_unlocker local_stringbuffer_t; +#else + typedef stl_buf_unlocker, CharT > local_stringbuffer_t; +#endif // A string representation of Source is written to [start, finish). // Currently, it is assumed that [start, finish) is big enough // to hold a string representation of any Source value. CharT* start; CharT* finish; + local_stringbuffer_t *stringbuf; + + public: + lexical_stream_limited_src(CharT* sta, CharT* fin) + : start(sta) + , finish(fin) + , stringbuf(NULL) + {} + + ~lexical_stream_limited_src() + { + if (stringbuf) delete stringbuf; + } private: - - static void widen_and_assign(char*p, char ch) - { - Traits::assign(*p, ch); - } - -#ifndef BOOST_LCAST_NO_WCHAR_T - static void widen_and_assign(wchar_t* p, char ch) - { - // TODO: use BOOST_NO_STD_LOCALE - std::locale loc; - wchar_t w = BOOST_USE_FACET(std::ctype, loc).widen(ch); - Traits::assign(*p, w); - } - - static void widen_and_assign(wchar_t* p, wchar_t ch) - { - Traits::assign(*p, ch); - } - - static void widen_and_assign(char*, wchar_t ch); // undefined -#endif - - template - bool lcast_put(const OutputStreamable& input) - { - if(put_inf_nan(start, finish, input)) return true; - this->setp(start, finish); - std::basic_ostream stream(static_cast(this)); - lcast_set_precision(stream, static_cast(0)); - bool const result = !(stream << input).fail(); - finish = this->pptr(); - return result; - } - // Undefined: lexical_stream_limited_src(lexical_stream_limited_src const&); void operator=(lexical_stream_limited_src const&); +/************************************ HELPER FUNCTIONS FOR OPERATORS << ( ... ) ********************************/ + bool shl_char(CharT ch) + { + Traits::assign(*start, ch); + finish = start + 1; + return true; + } + +#ifndef BOOST_LCAST_NO_WCHAR_T + template + bool shl_char(T ch) + { + BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)) , + "boost::lexical_cast does not support conversions from whar_t to char types." + "Use boost::locale instead" ); +#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE + std::locale loc; + wchar_t w = BOOST_USE_FACET(std::ctype, loc).widen(ch); +#else + wchar_t w = ch; +#endif + Traits::assign(*start, w); + finish = start + 1; + return true; + } +#endif + + bool shl_char_array(CharT const* str) + { + start = const_cast(str); + finish = start + Traits::length(str); + return true; + } + +#ifndef BOOST_LCAST_NO_WCHAR_T + template + bool shl_char_array(T const* str) + { + BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)), + "boost::lexical_cast does not support conversions from whar_t to char types." + "Use boost::locale instead" ); + return shl_input_streamable(str); + } +#endif + + template + bool shl_input_streamable(InputStreamable& input) + { + /* No one will call this function twice, + * so we do not need `if (!stringbuf)' */ + stringbuf = new local_stringbuffer_t(); + + std::basic_ostream stream(stringbuf); + lcast_set_precision(stream, static_cast(0)); + bool const result = !(stream << input).fail(); + start = stringbuf->pbase(); + finish = stringbuf->pptr(); + return result; + } + + template + inline bool shl_signed(T n) + { + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + if(n < 0) + { + --start; + CharT const minus = lcast_char_constants::minus; + Traits::assign(*start, minus); + } + return true; + } + +#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION + template + bool shl_float_types(T val) + { + if (put_inf_nan(start, finish, val)) return true; + local_streambuffer_t bb; + bb.setp(start, finish); + std::basic_ostream stream(&bb); + lcast_set_precision(stream, &val); + bool const result = !(stream << val).fail(); + finish = bb.pptr(); + return result; + } +#endif + +/************************************ OPERATORS << ( ... ) ********************************/ public: - - lexical_stream_limited_src(CharT* sta, CharT* fin) - : start(sta) - , finish(fin) - {} - - public: // output - template bool operator<<(std::basic_string const& str) { @@ -1284,39 +1137,53 @@ namespace boost return true; } - 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); + bool operator<<(bool value) + { + CharT const czero = lcast_char_constants::zero; + Traits::assign(*start, Traits::to_char_type(czero + value)); + finish = start + 1; + return true; + } + + bool operator<<(char ch) { return shl_char(ch); } + bool operator<<(unsigned char ch) { return ((*this) << static_cast(ch)); } + bool operator<<(signed char ch) { return ((*this) << static_cast(ch)); } +#if !defined(BOOST_LCAST_NO_WCHAR_T) + bool operator<<(wchar_t const* str) { return shl_char_array(str); } +#ifndef BOOST_NO_INTRINSIC_WCHAR_T + bool operator<<(wchar_t ch) { return shl_char(ch); } #endif - bool operator<<(unsigned char const*); - bool operator<<(signed char const*); - bool operator<<(CharT const*); - bool operator<<(short); - bool operator<<(int); - bool operator<<(long); - bool operator<<(unsigned short); - bool operator<<(unsigned int); - bool operator<<(unsigned long); +#endif + bool operator<<(unsigned char const* ch) { return ((*this) << reinterpret_cast(ch)); } + bool operator<<(signed char const* ch) { return ((*this) << reinterpret_cast(ch)); } + bool operator<<(char const* str) { return shl_char_array(str); } + bool operator<<(short n) { return shl_signed(n); } + bool operator<<(int n) { return shl_signed(n); } + bool operator<<(long n) { return shl_signed(n); } + bool operator<<(unsigned short n) { start = lcast_put_unsigned(n, finish); return true; } + bool operator<<(unsigned int n) { start = lcast_put_unsigned(n, finish); return true; } + bool operator<<(unsigned long n) { start = lcast_put_unsigned(n, finish); return true; } + #if defined(BOOST_HAS_LONG_LONG) - bool operator<<(boost::ulong_long_type); - bool operator<<(boost::long_long_type ); + bool operator<<(boost::ulong_long_type n) { start = lcast_put_unsigned(n, finish); return true; } + bool operator<<(boost::long_long_type n) { return shl_signed(n); } #elif defined(BOOST_HAS_MS_INT64) - bool operator<<(unsigned __int64); - bool operator<<( __int64); + bool operator<<(unsigned __int64 n) { start = lcast_put_unsigned(n, finish); return true; } + bool operator<<( __int64 n) { return shl_signed(n); } #endif - // These three operators use ostream and streambuf. - // lcast_streambuf_for_source::value is true. - bool operator<<(float); - bool operator<<(double); - bool operator<<(long double); +#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION + bool operator<<(float val) { return shl_float_types(val); } + bool operator<<(double val) { return shl_float_types(val); } + bool operator<<(long double val) { return shl_float_types(val); } +#endif // BOOST_LCAST_NO_COMPILE_TIME_PRECISION + template + bool operator<<(const InStreamable& input) { return shl_input_streamable(input); } + +/************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/ private: - template - bool input_operator_helper_unsigned(Type& output) + bool shr_unsigned(Type& output) { CharT const minus = lcast_char_constants::minus; CharT const plus = lcast_char_constants::plus; @@ -1350,7 +1217,7 @@ namespace boost } template - bool input_operator_helper_signed(Type& output) + bool shr_signed(Type& output) { CharT const minus = lcast_char_constants::minus; CharT const plus = lcast_char_constants::plus; @@ -1393,63 +1260,81 @@ namespace boost return succeed; } - public: // input - - bool operator>>(unsigned short& output) + template + bool shr_using_base_class(InputStreamable& output) { - return input_operator_helper_unsigned(output); +#if (defined _MSC_VER) +# pragma warning( push ) + // conditional expression is constant +# pragma warning( disable : 4127 ) +#endif + if(is_pointer::value) + return false; + + local_streambuffer_t bb; + bb.setg(start, start, finish); + std::basic_istream stream(&bb); + stream.unsetf(std::ios::skipws); + lcast_set_precision(stream, static_cast(0)); +#if (defined _MSC_VER) +# pragma warning( pop ) +#endif + return stream >> output && + stream.get() == +#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) + // GCC 2.9x lacks std::char_traits<>::eof(). + // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 + // configurations, which do provide std::char_traits<>::eof(). + + EOF; +#else + Traits::eof(); +#endif } - bool operator>>(unsigned int& output) + template + inline bool shr_xchar(T& output) { - return input_operator_helper_unsigned(output); + BOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ), + "boost::lexical_cast does not support conversions from whar_t to char types." + "Use boost::locale instead" ); + bool const ok = (finish - start == 1); + if(ok) { + CharT out; + Traits::assign(out, *start); + output = static_cast(out); + } + return ok; } - bool operator>>(unsigned long int& output) - { - return input_operator_helper_unsigned(output); - } - - bool operator>>(short& output) - { - return input_operator_helper_signed(output); - } - - bool operator>>(int& output) - { - return input_operator_helper_signed(output); - } - - bool operator>>(long int& output) - { - return input_operator_helper_signed(output); - } - - +/************************************ OPERATORS >> ( ... ) ********************************/ + public: + bool operator>>(unsigned short& output) { return shr_unsigned(output); } + bool operator>>(unsigned int& output) { return shr_unsigned(output); } + bool operator>>(unsigned long int& output) { return shr_unsigned(output); } + bool operator>>(short& output) { return shr_signed(output); } + bool operator>>(int& output) { return shr_signed(output); } + bool operator>>(long int& output) { return shr_signed(output); } #if defined(BOOST_HAS_LONG_LONG) - bool operator>>( boost::ulong_long_type& output) - { - return input_operator_helper_unsigned(output); - } - - bool operator>>(boost::long_long_type& output) - { - return input_operator_helper_signed(output); - } - + bool operator>>(boost::ulong_long_type& output) { return shr_unsigned(output); } + bool operator>>(boost::long_long_type& output) { return shr_signed(output); } #elif defined(BOOST_HAS_MS_INT64) - bool operator>>(unsigned __int64& output) - { - return input_operator_helper_unsigned(output); - } - - bool operator>>(__int64& output) - { - return input_operator_helper_signed(output); - } + bool operator>>(unsigned __int64& output) { return shr_unsigned(output); } + bool operator>>(__int64& output) { return shr_signed(output); } #endif - + bool operator>>(CharT& output) { return shr_xchar(output); } + bool operator>>(unsigned char& output) { return shr_xchar(output); } + bool operator>>(signed char& output) { return shr_xchar(output); } +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + bool operator>>(std::string& str) { str.assign(start, finish); return true; } +# ifndef BOOST_LCAST_NO_WCHAR_T + bool operator>>(std::wstring& str) { str.assign(start, finish); return true; } +# endif +#else + template + bool operator>>(std::basic_string& str) { str.assign(start, finish); return true; } +#endif /* * case "-0" || "0" || "+0" : output = false; return true; * case "1" || "+1": output = true; return true; @@ -1484,22 +1369,17 @@ namespace boost } } - bool operator>>(float& output) - { - return lcast_ret_float(output,start,finish); - } + bool operator>>(float& output) { return lcast_ret_float(output,start,finish); } private: // Not optimised converter template bool float_types_converter_internal(T& output, int /*tag*/) { - if (parse_inf_nan(start, finish, output)) return true; - - bool return_value = convert_using_base_class(output); + bool return_value = shr_using_base_class(output); /* Some compilers and libraries successfully - * parse '1.0E', '1.0E-'... + * parse 'inf', 'INFINITY', '1.0E', '1.0E-'... * We are trying to provide a unified behaviour, * so we just forbid such conversions (as some * of the most popular compilers/libraries do) @@ -1556,424 +1436,11 @@ namespace boost // Generic istream-based algorithm. // lcast_streambuf_for_target::value is true. template - bool operator>>(InputStreamable& output) - { - return convert_using_base_class(output); - } - - private: - template - bool convert_using_base_class(InputStreamable& output) - { -#if (defined _MSC_VER) -# pragma warning( push ) - // conditional expression is constant -# pragma warning( disable : 4127 ) -#endif - if(is_pointer::value) - return false; - - this->setg(start, start, finish); - std::basic_istream stream(static_cast(this)); - stream.unsetf(std::ios::skipws); - lcast_set_precision(stream, static_cast(0)); -#if (defined _MSC_VER) -# pragma warning( pop ) -#endif - return stream >> output && - stream.get() == -#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) - // GCC 2.9x lacks std::char_traits<>::eof(). - // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 - // configurations, which do provide std::char_traits<>::eof(). - - EOF; -#else - Traits::eof(); -#endif - } - public: - - 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 - - bool operator>>(std::string&); - -#ifndef BOOST_LCAST_NO_WCHAR_T - bool operator>>(std::wstring&); -#endif - -#else - template - bool operator>>(std::basic_string& str) - { - str.assign(start, finish); - return true; - } -#endif - }; - - template - inline bool lexical_stream_limited_src::operator<<( - bool value) - { - typedef typename Traits::int_type int_type; - CharT const czero = lcast_char_constants::zero; - int_type const zero = Traits::to_int_type(czero); - Traits::assign(*start, Traits::to_char_type(zero + value)); - finish = start + 1; - return true; - } - - template - inline bool lexical_stream_limited_src::operator<<( - char ch) - { - widen_and_assign(start, ch); - finish = start + 1; - 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<<( - wchar_t ch) - { - widen_and_assign(start, ch); - finish = start + 1; - return true; - } -#endif - - template - inline bool lexical_stream_limited_src::operator<<( - short n) - { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); - if(n < 0) - { - --start; - CharT const minus = lcast_char_constants::minus; - Traits::assign(*start, minus); - } - return true; - } - - template - inline bool lexical_stream_limited_src::operator<<( - int n) - { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); - if(n < 0) - { - --start; - CharT const minus = lcast_char_constants::minus; - Traits::assign(*start, minus); - } - return true; - } - - template - inline bool lexical_stream_limited_src::operator<<( - long n) - { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); - if(n < 0) - { - --start; - CharT const minus = lcast_char_constants::minus; - Traits::assign(*start, minus); - } - return true; - } - -#if defined(BOOST_HAS_LONG_LONG) - template - inline bool lexical_stream_limited_src::operator<<( - boost::long_long_type n) - { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); - if(n < 0) - { - --start; - CharT const minus = lcast_char_constants::minus; - Traits::assign(*start, minus); - } - return true; - } -#elif defined(BOOST_HAS_MS_INT64) - template - inline bool lexical_stream_limited_src::operator<<( - __int64 n) - { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); - if(n < 0) - { - --start; - CharT const minus = lcast_char_constants::minus; - Traits::assign(*start, minus); - } - return true; - } -#endif - - template - inline bool lexical_stream_limited_src::operator<<( - unsigned short n) - { - start = lcast_put_unsigned(n, finish); - return true; - } - - template - inline bool lexical_stream_limited_src::operator<<( - unsigned int n) - { - start = lcast_put_unsigned(n, finish); - return true; - } - - template - inline bool lexical_stream_limited_src::operator<<( - unsigned long n) - { - start = lcast_put_unsigned(n, finish); - return true; - } - -#if defined(BOOST_HAS_LONG_LONG) - template - inline bool lexical_stream_limited_src::operator<<( - boost::ulong_long_type n) - { - start = lcast_put_unsigned(n, finish); - return true; - } -#elif defined(BOOST_HAS_MS_INT64) - template - inline bool lexical_stream_limited_src::operator<<( - unsigned __int64 n) - { - start = lcast_put_unsigned(n, finish); - return true; - } -#endif - - template - inline bool lexical_stream_limited_src::operator<<( - float val) - { - return this->lcast_put(val); - } - - template - inline bool lexical_stream_limited_src::operator<<( - double val) - { - return this->lcast_put(val); - } - - template - inline bool lexical_stream_limited_src::operator<<( - long double val) - { - return this->lcast_put(val); - } - - template - inline bool lexical_stream_limited_src::operator<<( - CharT const* str) - { - start = const_cast(str); - finish = start + Traits::length(str); - return true; - } - - template - inline bool lexical_stream_limited_src::operator>>( - CharT& output) - { - bool const ok = (finish - start == 1); - if(ok) - Traits::assign(output, *start); - 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>>( - std::string& str) - { - str.assign(start, finish); - return true; - } - -#ifndef BOOST_LCAST_NO_WCHAR_T - template - inline bool lexical_stream_limited_src::operator>>( - std::wstring& str) - { - str.assign(start, finish); - return true; - } -#endif -#endif - } - - namespace detail // lcast_streambuf_for_source - { - // Returns true if optimized stream wrapper needs ostream for writing. - template - struct lcast_streambuf_for_source - { - BOOST_STATIC_CONSTANT(bool, value = false); - }; - - template<> - struct lcast_streambuf_for_source - { - BOOST_STATIC_CONSTANT(bool, value = true); - }; - - template<> - struct lcast_streambuf_for_source - { - BOOST_STATIC_CONSTANT(bool, value = true); - }; - - template<> - struct lcast_streambuf_for_source - { - BOOST_STATIC_CONSTANT(bool, value = true); + bool operator>>(InputStreamable& output) { return shr_using_base_class(output); } }; } - namespace detail // lcast_streambuf_for_target - { - // Returns true if optimized stream wrapper needs istream for reading. - template - struct lcast_streambuf_for_target - { -#if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64) - BOOST_STATIC_CONSTANT(bool, value = - ( - ::boost::type_traits::ice_or< - ::boost::type_traits::ice_not< is_arithmetic::value >::value, - is_same::value, - ::boost::type_traits::ice_and< - is_same::value, - ::boost::type_traits::ice_eq::value - >::value - >::value - ) - ); -#else - BOOST_STATIC_CONSTANT(bool, value = - ( - ::boost::type_traits::ice_or< - ::boost::type_traits::ice_not< is_arithmetic::value >::value, - is_same::value, - is_same::value - >::value - ) - ); -#endif - }; - #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct lcast_streambuf_for_target< - std::basic_string > - { - BOOST_STATIC_CONSTANT(bool, value = false); - }; - -#ifndef BOOST_LCAST_NO_WCHAR_T - template - struct lcast_streambuf_for_target< - std::basic_string > - { - BOOST_STATIC_CONSTANT(bool, value = false); - }; -#endif -#else - template<> - struct lcast_streambuf_for_target - { - BOOST_STATIC_CONSTANT(bool, value = false); - }; - -#ifndef BOOST_LCAST_NO_WCHAR_T - template<> - struct lcast_streambuf_for_target - { - BOOST_STATIC_CONSTANT(bool, value = false); - }; -#endif -#endif - } - - #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // call-by-const reference version @@ -1991,47 +1458,6 @@ namespace boost typedef const T * type; }; -#if (defined _MSC_VER) -# pragma warning( push ) -# pragma warning( disable : 4701 ) // possible use of ... before initialization -# pragma warning( disable : 4702 ) // unreachable code -# pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int' -#endif - - template< typename Target - , typename Source - , bool Unlimited // string representation of Source is unlimited - , typename CharT - > - Target lexical_cast( - BOOST_DEDUCED_TYPENAME boost::call_traits::param_type arg, - CharT* buf, std::size_t src_len) - { - typedef BOOST_DEDUCED_TYPENAME - deduce_char_traits::type traits; - - typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< - lcast_streambuf_for_target::value || - lcast_streambuf_for_source::value - , std::basic_streambuf - , lexical_streambuf_fake - >::type base; - - BOOST_DEDUCED_TYPENAME boost::mpl::if_c< - Unlimited - , detail::lexical_stream - , detail::lexical_stream_limited_src - >::type interpreter(buf, buf + src_len); - - Target result; - if(!(interpreter << arg && interpreter >> result)) - BOOST_LCAST_THROW_BAD_CAST(Source, Target); - return result; - } -#if (defined _MSC_VER) -# pragma warning( pop ) -#endif - template struct is_stdstring { @@ -2134,25 +1560,43 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = true ); }; +#if (defined _MSC_VER) +# pragma warning( push ) +# pragma warning( disable : 4701 ) // possible use of ... before initialization +# pragma warning( disable : 4702 ) // unreachable code +# pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int' +#endif template struct lexical_cast_do_cast { - static inline Target lexical_cast_impl(const Source &arg) + static inline Target lexical_cast_impl(const Source& arg) { - typedef typename detail::array_to_pointer_decay::type src; + typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay::type src; - typedef typename detail::widest_char< - typename detail::stream_char::type - , typename detail::stream_char::type + typedef BOOST_DEDUCED_TYPENAME detail::widest_char< + BOOST_DEDUCED_TYPENAME detail::stream_char::type + , BOOST_DEDUCED_TYPENAME detail::stream_char::type >::type char_type; 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(); - return detail::lexical_cast(arg, buf, src_len); + + typedef BOOST_DEDUCED_TYPENAME + deduce_char_traits::type traits; + + detail::lexical_stream_limited_src interpreter(buf, buf + src_len); + + Target result; + if(!(interpreter << arg && interpreter >> result)) + BOOST_LCAST_THROW_BAD_CAST(Source, Target); + return result; } }; +#if (defined _MSC_VER) +# pragma warning( pop ) +#endif template struct lexical_cast_copy @@ -2315,6 +1759,78 @@ namespace boost #else + namespace detail // stream wrapper for handling lexical conversions + { + template + class lexical_stream + { + private: + typedef typename widest_char< + typename stream_char::type, + typename stream_char::type>::type char_type; + + typedef Traits traits_type; + + public: + lexical_stream(char_type* = 0, char_type* = 0) + { + stream.unsetf(std::ios::skipws); + lcast_set_precision(stream, static_cast(0), static_cast(0) ); + } + ~lexical_stream() + { + #if defined(BOOST_NO_STRINGSTREAM) + stream.freeze(false); + #endif + } + bool operator<<(const Source &input) + { + return !(stream << input).fail(); + } + template + bool operator>>(InputStreamable &output) + { + return !is_pointer::value && + stream >> output && + stream.get() == +#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) +// GCC 2.9x lacks std::char_traits<>::eof(). +// We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 +// configurations, which do provide std::char_traits<>::eof(). + + EOF; +#else + traits_type::eof(); +#endif + } + + bool operator>>(std::string &output) + { + #if defined(BOOST_NO_STRINGSTREAM) + stream << '\0'; + #endif + stream.str().swap(output); + return true; + } + #ifndef BOOST_LCAST_NO_WCHAR_T + bool operator>>(std::wstring &output) + { + stream.str().swap(output); + return true; + } + #endif + + private: + #if defined(BOOST_NO_STRINGSTREAM) + std::strstream stream; + #elif defined(BOOST_NO_STD_LOCALE) + std::stringstream stream; + #else + std::basic_stringstream stream; + #endif + }; + } + // call-by-value fallback version (deprecated) template diff --git a/test/lexical_cast_inf_nan_test.cpp b/test/lexical_cast_inf_nan_test.cpp index ee50dee..4617d5e 100755 --- a/test/lexical_cast_inf_nan_test.cpp +++ b/test/lexical_cast_inf_nan_test.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -51,7 +52,14 @@ bool is_pos_nan(T value) template bool is_neg_nan(T value) { + /* There is some strange behaviour on Itanium platform with -nan nuber for long double. + * It is a IA64 feature, or it is a boost::math feature, not a lexical_cast bug */ +#if defined(__ia64__) || defined(_M_IA64) + return (boost::math::isnan)(value) + && ( boost::is_same::value || (boost::math::signbit)(value) ); +#else return (boost::math::isnan)(value) && (boost::math::signbit)(value); +#endif } template @@ -94,9 +102,11 @@ void test_inf_nan_templated() == "-inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::infinity()) == "inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::quiet_NaN()) == "nan" ); +#if !defined(__ia64__) && !defined(_M_IA64) BOOST_CHECK(lexical_cast( (boost::math::changesign)(std::numeric_limits::quiet_NaN())) == "-nan" ); +#endif #ifndef BOOST_LCAST_NO_WCHAR_T BOOST_CHECK( is_pos_inf( lexical_cast(L"inf") ) ); @@ -134,10 +144,13 @@ void test_inf_nan_templated() == L"-inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::infinity()) == L"inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::quiet_NaN()) == L"nan" ); +#if !defined(__ia64__) && !defined(_M_IA64) BOOST_CHECK(lexical_cast( (boost::math::changesign)(std::numeric_limits::quiet_NaN())) == L"-nan" ); #endif + +#endif } void test_inf_nan_float() diff --git a/test/lexical_cast_wchars_test.cpp b/test/lexical_cast_wchars_test.cpp index 547f226..14ac461 100755 --- a/test/lexical_cast_wchars_test.cpp +++ b/test/lexical_cast_wchars_test.cpp @@ -37,11 +37,11 @@ void test_char_types_conversions() BOOST_CHECK(boost::lexical_cast(c_arr[0]) == wc_arr[0]); 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(sc_arr) == std::wstring(wc_arr) ); + BOOST_CHECK(boost::lexical_cast(uc_arr) == std::wstring(wc_arr) ); - BOOST_CHECK_THROW(boost::lexical_cast(uc_arr[0]), boost::bad_lexical_cast); - BOOST_CHECK_THROW(boost::lexical_cast(sc_arr[0]), boost::bad_lexical_cast); + BOOST_CHECK_EQUAL(boost::lexical_cast(uc_arr[0]), wc_arr[0]); + BOOST_CHECK_EQUAL(boost::lexical_cast(sc_arr[0]), wc_arr[0]); #endif BOOST_CHECK(1); } From fd264b05837d83fc602d8c27e7b44111e8c3a12b Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 24 Jul 2011 09:42:06 +0000 Subject: [PATCH 102/242] Fixes #5732. * fixes performance regression, that was added by previous commit * fixes float types preformance regression for old compilers [SVN r73323] --- include/boost/lexical_cast.hpp | 108 ++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 35 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 58fdea8..e3e0632 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -1003,6 +1005,7 @@ namespace boost // String representation of Source has an upper limit. template< class CharT // a result of widest_char transformation , class Traits // usually char_traits + , bool RequiresStringbuffer > class lexical_stream_limited_src { @@ -1015,25 +1018,23 @@ namespace boost #else typedef stl_buf_unlocker, CharT > local_stringbuffer_t; #endif + typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< + RequiresStringbuffer, + local_stringbuffer_t, + char + >::type deduced_stringbuffer_t; + // A string representation of Source is written to [start, finish). - // Currently, it is assumed that [start, finish) is big enough - // to hold a string representation of any Source value. CharT* start; CharT* finish; - local_stringbuffer_t *stringbuf; + deduced_stringbuffer_t stringbuffer; public: lexical_stream_limited_src(CharT* sta, CharT* fin) : start(sta) , finish(fin) - , stringbuf(NULL) {} - ~lexical_stream_limited_src() - { - if (stringbuf) delete stringbuf; - } - private: // Undefined: lexical_stream_limited_src(lexical_stream_limited_src const&); @@ -1078,7 +1079,7 @@ namespace boost bool shl_char_array(T const* str) { BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)), - "boost::lexical_cast does not support conversions from whar_t to char types." + "boost::lexical_cast does not support conversions from wchar_t to char types." "Use boost::locale instead" ); return shl_input_streamable(str); } @@ -1087,15 +1088,10 @@ namespace boost template bool shl_input_streamable(InputStreamable& input) { - /* No one will call this function twice, - * so we do not need `if (!stringbuf)' */ - stringbuf = new local_stringbuffer_t(); - - std::basic_ostream stream(stringbuf); - lcast_set_precision(stream, static_cast(0)); + std::basic_ostream stream(&stringbuffer); bool const result = !(stream << input).fail(); - start = stringbuf->pbase(); - finish = stringbuf->pptr(); + start = stringbuffer.pbase(); + finish = stringbuffer.pptr(); return result; } @@ -1112,18 +1108,44 @@ namespace boost return true; } -#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION template - bool shl_float_types(T val) - { - if (put_inf_nan(start, finish, val)) return true; - local_streambuffer_t bb; - bb.setp(start, finish); - std::basic_ostream stream(&bb); - lcast_set_precision(stream, &val); - bool const result = !(stream << val).fail(); - finish = bb.pptr(); - return result; + bool shl_float(float val,T* out) + { using namespace std; + finish = start + sprintf(out,"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); + return finish > start; + } + + template + bool shl_double(double val,T* out) + { using namespace std; + finish = start + sprintf(out,"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); + return finish > start; + } + + template + bool shl_long_double(long double val,T* out) + { using namespace std; + finish = start + sprintf(out,"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); + return finish > start; + } + +#ifndef BOOST_LCAST_NO_WCHAR_T + bool shl_float(float val,wchar_t* out) + { using namespace std; + finish = start + swprintf(out,finish-start,L"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); + return finish > start; + } + + bool shl_double(double val,wchar_t* out) + { using namespace std; + finish = start + swprintf(out,finish-start,L"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); + return finish > start; + } + + bool shl_long_double(long double val,wchar_t* out) + { using namespace std; + finish = start + swprintf(out,finish-start,L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); + return finish > start; } #endif @@ -1171,11 +1193,9 @@ namespace boost bool operator<<(unsigned __int64 n) { start = lcast_put_unsigned(n, finish); return true; } bool operator<<( __int64 n) { return shl_signed(n); } #endif -#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION - bool operator<<(float val) { return shl_float_types(val); } - bool operator<<(double val) { return shl_float_types(val); } - bool operator<<(long double val) { return shl_float_types(val); } -#endif // BOOST_LCAST_NO_COMPILE_TIME_PRECISION + bool operator<<(float val) { return shl_float(val,start); } + bool operator<<(double val) { return shl_double(val,start); } + bool operator<<(long double val) { return shl_long_double(val,start); } template bool operator<<(const InStreamable& input) { return shl_input_streamable(input); } @@ -1586,7 +1606,25 @@ namespace boost typedef BOOST_DEDUCED_TYPENAME deduce_char_traits::type traits; - detail::lexical_stream_limited_src interpreter(buf, buf + src_len); + typedef BOOST_DEDUCED_TYPENAME remove_pointer::type removed_ptr_t; + const bool requires_stringbuf = + !( + ::boost::type_traits::ice_or< + is_stdstring::value, + is_arithmetic::value, + ::boost::type_traits::ice_and< + is_pointer::value, + is_char_or_wchar::value, + ::boost::type_traits::ice_eq< + sizeof(char_type), + sizeof(removed_ptr_t) + >::value + >::value + >::value + ); + + detail::lexical_stream_limited_src + interpreter(buf, buf + src_len); Target result; if(!(interpreter << arg && interpreter >> result)) From 0ee6400d5ea89e6f4aa4e2508b6700a55a3e3006 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 24 Jul 2011 10:56:54 +0000 Subject: [PATCH 103/242] Fixes #5732. * fixes some warnings and bugs for VC [SVN r73328] --- include/boost/lexical_cast.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index e3e0632..5d85a5d 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1108,9 +1108,16 @@ namespace boost return true; } +#if (defined _MSC_VER) +# pragma warning( push ) +// C4996: This function or variable may be unsafe. Consider using sprintf_s instead +# pragma warning( disable : 4996 ) +#endif + template bool shl_float(float val,T* out) { using namespace std; + if (put_inf_nan(start,finish,val)) return true; finish = start + sprintf(out,"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); return finish > start; } @@ -1118,6 +1125,7 @@ namespace boost template bool shl_double(double val,T* out) { using namespace std; + if (put_inf_nan(start,finish,val)) return true; finish = start + sprintf(out,"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); return finish > start; } @@ -1125,25 +1133,34 @@ namespace boost template bool shl_long_double(long double val,T* out) { using namespace std; + if (put_inf_nan(start,finish,val)) return true; finish = start + sprintf(out,"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); return finish > start; } +#if (defined _MSC_VER) +# pragma warning( pop ) +#endif + + #ifndef BOOST_LCAST_NO_WCHAR_T bool shl_float(float val,wchar_t* out) { using namespace std; + if (put_inf_nan(start,finish,val)) return true; finish = start + swprintf(out,finish-start,L"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); return finish > start; } bool shl_double(double val,wchar_t* out) { using namespace std; + if (put_inf_nan(start,finish,val)) return true; finish = start + swprintf(out,finish-start,L"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); return finish > start; } bool shl_long_double(long double val,wchar_t* out) { using namespace std; + if (put_inf_nan(start,finish,val)) return true; finish = start + swprintf(out,finish-start,L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); return finish > start; } From 2b76f558c10fb965b2bad902f9d49a3fbb8b8c7c Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 25 Jul 2011 05:02:07 +0000 Subject: [PATCH 104/242] #5732. Adds workaround for MinGW bugs [SVN r73347] --- include/boost/lexical_cast.hpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 5d85a5d..7874743 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1147,21 +1147,42 @@ namespace boost bool shl_float(float val,wchar_t* out) { using namespace std; if (put_inf_nan(start,finish,val)) return true; - finish = start + swprintf(out,finish-start,L"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); + finish = start + swprintf(out, +#ifndef __MINGW32__ + finish-start, +#endif + L"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); + return finish > start; } + bool shl_double(double val,wchar_t* out) { using namespace std; if (put_inf_nan(start,finish,val)) return true; - finish = start + swprintf(out,finish-start,L"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); + /* __MINGW32__ is defined for both mingw.org and for mingw-w64. + * For mingw-w64, __MINGW64__ is defined, too, when targetting + * 64 bits. + * + * swprintf realization in MinGW does not conform to the ISO C + * Standard. + */ + finish = start + swprintf(out, +#ifndef __MINGW32__ + finish-start, +#endif + L"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); return finish > start; } bool shl_long_double(long double val,wchar_t* out) { using namespace std; if (put_inf_nan(start,finish,val)) return true; - finish = start + swprintf(out,finish-start,L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); + finish = start + swprintf(out, +#ifndef __MINGW32__ + finish-start, +#endif + L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); return finish > start; } #endif From 9ac4e2bef184f81a420da369f52ff4307b9ec7c6 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 25 Jul 2011 15:13:36 +0000 Subject: [PATCH 105/242] Fixes #5732. * fixes compilation errors for nonconst char arrays [SVN r73357] --- include/boost/lexical_cast.hpp | 11 ++++++++++- lexical_cast_test.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 7874743..9e0a7af 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1000,6 +1000,11 @@ namespace boost }; } + namespace detail + { + struct do_not_construct_stringbuffer_t{}; + } + namespace detail // optimized stream wrapper { // String representation of Source has an upper limit. @@ -1021,7 +1026,7 @@ namespace boost typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< RequiresStringbuffer, local_stringbuffer_t, - char + do_not_construct_stringbuffer_t >::type deduced_stringbuffer_t; // A string representation of Source is written to [start, finish). @@ -1210,13 +1215,17 @@ namespace boost bool operator<<(signed char ch) { return ((*this) << static_cast(ch)); } #if !defined(BOOST_LCAST_NO_WCHAR_T) bool operator<<(wchar_t const* str) { return shl_char_array(str); } + bool operator<<(wchar_t * str) { return shl_char_array(str); } #ifndef BOOST_NO_INTRINSIC_WCHAR_T bool operator<<(wchar_t ch) { return shl_char(ch); } #endif #endif bool operator<<(unsigned char const* ch) { return ((*this) << reinterpret_cast(ch)); } + bool operator<<(unsigned char * ch) { return ((*this) << reinterpret_cast(ch)); } bool operator<<(signed char const* ch) { return ((*this) << reinterpret_cast(ch)); } + bool operator<<(signed char * ch) { return ((*this) << reinterpret_cast(ch)); } bool operator<<(char const* str) { return shl_char_array(str); } + bool operator<<(char* str) { return shl_char_array(str); } bool operator<<(short n) { return shl_signed(n); } bool operator<<(int n) { return shl_signed(n); } bool operator<<(long n) { return shl_signed(n); } diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 244addb..37753ca 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #if (defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)) \ @@ -69,6 +70,7 @@ void test_conversion_to_char(); void test_conversion_to_int(); void test_conversion_to_double(); void test_conversion_to_bool(); +void test_conversion_with_nonconst_char(); void test_conversion_to_string(); void test_conversion_from_to_wchar_t_alias(); void test_conversion_to_pointer(); @@ -109,6 +111,7 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) suite->add(BOOST_TEST_CASE(test_conversion_from_to_wchar_t_alias)); suite->add(BOOST_TEST_CASE(test_conversion_to_pointer)); suite->add(BOOST_TEST_CASE(test_conversion_to_string)); + suite->add(BOOST_TEST_CASE(test_conversion_with_nonconst_char)); #ifndef BOOST_LCAST_NO_WCHAR_T suite->add(BOOST_TEST_CASE(test_conversion_from_wchar_t)); suite->add(BOOST_TEST_CASE(test_conversion_to_wchar_t)); @@ -199,6 +202,31 @@ void test_conversion_to_int() lexical_cast(std::string("Test")), bad_lexical_cast); } +void test_conversion_with_nonconst_char() +{ + std::vector buffer; + buffer.push_back('1'); + buffer.push_back('\0'); + BOOST_CHECK_EQUAL(boost::lexical_cast(&buffer[0]), 1); + + std::vector buffer2; + buffer2.push_back('1'); + buffer2.push_back('\0'); + BOOST_CHECK_EQUAL(boost::lexical_cast(&buffer2[0]), 1); + + std::vector buffer3; + buffer3.push_back('1'); + buffer3.push_back('\0'); + BOOST_CHECK_EQUAL(boost::lexical_cast(&buffer3[0]), 1); + +#ifndef BOOST_LCAST_NO_WCHAR_T + std::vector buffer4; + buffer4.push_back(L'1'); + buffer4.push_back(L'\0'); + BOOST_CHECK_EQUAL(boost::lexical_cast(&buffer4[0]), 1); +#endif +} + void test_conversion_to_double() { BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast('1'), (std::numeric_limits::epsilon())); From 19f316f768a20c45365e87e075b431c951def6d4 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 26 Jul 2011 18:51:39 +0000 Subject: [PATCH 106/242] Fixes #5732. * fixes compilation errors pgi compiler * fixes some bugs for MinGW compiler [SVN r73384] --- include/boost/lexical_cast.hpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 9e0a7af..5987908 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -47,6 +47,10 @@ #include #include +#ifdef __PGI +#include +#endif + #ifndef BOOST_NO_STD_LOCALE # include #else @@ -1134,7 +1138,7 @@ namespace boost finish = start + sprintf(out,"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); return finish > start; } - +#ifndef __MINGW32__ template bool shl_long_double(long double val,T* out) { using namespace std; @@ -1142,6 +1146,7 @@ namespace boost finish = start + sprintf(out,"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); return finish > start; } +#endif #if (defined _MSC_VER) # pragma warning( pop ) @@ -1180,16 +1185,16 @@ namespace boost return finish > start; } +#ifndef __MINGW32__ bool shl_long_double(long double val,wchar_t* out) { using namespace std; if (put_inf_nan(start,finish,val)) return true; - finish = start + swprintf(out, -#ifndef __MINGW32__ - finish-start, -#endif - L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); + finish = start + swprintf(out,finish-start, + L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); return finish > start; } + #endif + #endif /************************************ OPERATORS << ( ... ) ********************************/ @@ -1242,7 +1247,13 @@ namespace boost #endif bool operator<<(float val) { return shl_float(val,start); } bool operator<<(double val) { return shl_double(val,start); } - bool operator<<(long double val) { return shl_long_double(val,start); } + bool operator<<(long double val) { +#ifndef __MINGW32__ + return shl_long_double(val,start); +#else + return shl_double(val,start); +#endif + } template bool operator<<(const InStreamable& input) { return shl_input_streamable(input); } From 30e4efd062c698a24f3f943bf4f1340357de2dd7 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 27 Jul 2011 15:56:49 +0000 Subject: [PATCH 107/242] Fixes #5732. * one more try to fix compilation errors on pgi compiler [SVN r73401] --- include/boost/lexical_cast.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 5987908..4690a9e 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -46,10 +46,8 @@ #include #include #include - -#ifdef __PGI #include -#endif + #ifndef BOOST_NO_STD_LOCALE # include From aba423d425b6e8eed4aa70c82a674cac9cc9f038 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 29 Jul 2011 19:33:18 +0000 Subject: [PATCH 108/242] Fixes #5732. * one more try to fix compilation errors on pgi compiler [SVN r73435] --- include/boost/lexical_cast.hpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 4690a9e..48fdda7 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1156,7 +1156,7 @@ namespace boost { using namespace std; if (put_inf_nan(start,finish,val)) return true; finish = start + swprintf(out, -#ifndef __MINGW32__ +#if !defined(__MINGW32__) && !defined(__PGIC__) finish-start, #endif L"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); @@ -1176,7 +1176,7 @@ namespace boost * Standard. */ finish = start + swprintf(out, -#ifndef __MINGW32__ +#if !defined(__MINGW32__) && !defined(__PGIC__) finish-start, #endif L"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); @@ -1187,7 +1187,10 @@ namespace boost bool shl_long_double(long double val,wchar_t* out) { using namespace std; if (put_inf_nan(start,finish,val)) return true; - finish = start + swprintf(out,finish-start, + finish = start + swprintf(out, +#if !defined(__PGIC__) + finish-start, +#endif L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); return finish > start; } From a9778ad460659ea5d1d1960e710101b3e914e282 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sat, 30 Jul 2011 16:47:30 +0000 Subject: [PATCH 109/242] Fixes #5732. * at least compiles on pgi [SVN r73446] --- include/boost/lexical_cast.hpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 48fdda7..25884b6 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1156,7 +1156,7 @@ namespace boost { using namespace std; if (put_inf_nan(start,finish,val)) return true; finish = start + swprintf(out, -#if !defined(__MINGW32__) && !defined(__PGIC__) +#if !defined(__MINGW32__) finish-start, #endif L"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); @@ -1176,7 +1176,7 @@ namespace boost * Standard. */ finish = start + swprintf(out, -#if !defined(__MINGW32__) && !defined(__PGIC__) +#if !defined(__MINGW32__) finish-start, #endif L"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); @@ -1187,11 +1187,7 @@ namespace boost bool shl_long_double(long double val,wchar_t* out) { using namespace std; if (put_inf_nan(start,finish,val)) return true; - finish = start + swprintf(out, -#if !defined(__PGIC__) - finish-start, -#endif - L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); + finish = start + swprintf(out, finish-start, L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); return finish > start; } #endif From e8108e50668cac57209d4f0e2b2afc80f8463d7a Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 7 Aug 2011 17:38:33 +0000 Subject: [PATCH 110/242] Fixes #5732. * some fixes for WinCE * updated explicit failures markup [SVN r73601] --- include/boost/lexical_cast.hpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 25884b6..34a0aed 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1156,7 +1156,7 @@ namespace boost { using namespace std; if (put_inf_nan(start,finish,val)) return true; finish = start + swprintf(out, -#if !defined(__MINGW32__) +#if !defined(__MINGW32__) && !defined(UNDER_CE) finish-start, #endif L"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); @@ -1172,11 +1172,12 @@ namespace boost * For mingw-w64, __MINGW64__ is defined, too, when targetting * 64 bits. * - * swprintf realization in MinGW does not conform to the ISO C + * swprintf realization in MinGW and under WinCE does not conform + * to the ISO C * Standard. */ finish = start + swprintf(out, -#if !defined(__MINGW32__) +#if !defined(__MINGW32__) && !defined(UNDER_CE) finish-start, #endif L"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); @@ -1187,10 +1188,14 @@ namespace boost bool shl_long_double(long double val,wchar_t* out) { using namespace std; if (put_inf_nan(start,finish,val)) return true; - finish = start + swprintf(out, finish-start, L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); + finish = start + swprintf(out, +#if !defined(UNDER_CE) + finish-start, +#endif + L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); return finish > start; } - #endif +#endif #endif From 9955dcce51f746710b1fc67cda1026b2f41e60d4 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 10 Aug 2011 18:58:06 +0000 Subject: [PATCH 111/242] Fixes #5732. * suppress compilation warnings, if the compiler requires a return, even when it can never be reached [SVN r73640] --- include/boost/lexical_cast.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 34a0aed..686b9f5 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1750,6 +1750,7 @@ namespace boost } catch( ::boost::numeric::bad_numeric_cast const& ) { BOOST_LCAST_THROW_BAD_CAST(Source, Target); } + BOOST_UNREACHABLE_RETURN(static_cast(0)); } }; @@ -1776,6 +1777,7 @@ namespace boost } catch( ::boost::numeric::bad_numeric_cast const& ) { BOOST_LCAST_THROW_BAD_CAST(Source, Target); } + BOOST_UNREACHABLE_RETURN(static_cast(0)); } }; From 4a4150d0be5f09bae17efc9e194cf80bb0fbfff0 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 12 Aug 2011 17:04:31 +0000 Subject: [PATCH 112/242] Fixes #5746 Updates FAQ section of documentation [SVN r73705] --- doc/lexical_cast.qbk | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index f5beec7..360534a 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -118,17 +118,29 @@ Exception used to indicate runtime lexical_cast failure. [section Frequently Asked Questions] * [*Question:] Why does `lexical_cast("127")` throw `bad_lexical_cast`? - * [*Answer:] The type `int8_t` is a `typedef` to `char` or `signed char`. Lexical conversion to these types -is simply reading a byte from source but since the source has more than one byte, the exception is thrown. + * [*Answer:] The type `int8_t` is a `typedef` to `char` or `signed char`. Lexical conversion to these types is simply reading a byte from source but since the source has more than one byte, the exception is thrown. Please use other integer types such as `int` or `short int`. If bounds checking is important, you can also call __numericcast__: `numeric_cast(lexical_cast("127"));` +[pre +] + +* [*Question:] Why does `lexical_cast("127")` throw `bad_lexical_cast`? + * [*Answer:] Lexical conversion to any char type is simply reading a byte from source. But since the source has more than one byte, the exception is thrown. +Please use other integer types such as `int` or `short int`. If bounds checking is important, you can also +call __numericcast__: +`numeric_cast(lexical_cast("127"));` + +[pre +] * [*Question:] What does `lexical_cast` of an `int8_t` or `uint8_t` not do what I expect? * [*Answer:] As above, note that int8_t and uint8_t are actually chars and are formatted as such. To avoid this, cast to an integer type first: `lexical_cast(static_cast(n));` +[pre +] * [*Question:] The implementation always resets the `ios_base::skipws` flag of an underlying stream object. It breaks my `operator>>` that works only in presence of this flag. Can you remove code that resets the flag? @@ -138,6 +150,8 @@ remember that __proposalshort__ is not yet accepted by the committee. By the way make your `operator>>` conform to the standard. Read a good C++ book, study `std::sentry` and [@boost:libs/io/doc/ios_state.html `ios_state_saver`]. +[pre +] * [*Question:] Why `std::cout << boost::lexical_cast("-1");` does not throw, but outputs 4294967295? * [*Answer:] `boost::lexical_cast` has the behavior of `std::stringstream`, which uses `num_get` functions of From 5ebb13bbad64b7e2e2b44e7ca6593d0b81e13961 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 12 Aug 2011 17:08:17 +0000 Subject: [PATCH 113/242] Very small update for FAQ section of documentation [SVN r73706] --- doc/lexical_cast.qbk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index 360534a..9fb6cdf 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -130,7 +130,7 @@ call __numericcast__: * [*Answer:] Lexical conversion to any char type is simply reading a byte from source. But since the source has more than one byte, the exception is thrown. Please use other integer types such as `int` or `short int`. If bounds checking is important, you can also call __numericcast__: -`numeric_cast(lexical_cast("127"));` +`numeric_cast(lexical_cast("127"));` [pre ] From eb66b40e6729fca3971fd87d37a1dcbcfd74d984 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 12 Aug 2011 17:35:56 +0000 Subject: [PATCH 114/242] FIxes #5631 Workaround for nvcc bug [SVN r73707] --- include/boost/lexical_cast.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 686b9f5..3ac3cc9 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -261,7 +261,7 @@ namespace boost #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS BOOST_STATIC_CONSTANT(std::size_t, value = std::numeric_limits::is_signed + - std::numeric_limits::is_specialized + // == 1 + std::numeric_limits::is_specialized + /* == 1 */ std::numeric_limits::digits10 * 2 ); #else From 2f5d0c847bba655e5391d55bdc43d18c9cb3592f Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 16 Aug 2011 17:09:25 +0000 Subject: [PATCH 115/242] Fixes #5783 Fixes ambiguities with operators >> and <<. Adds tests for such cases. [SVN r73818] --- include/boost/lexical_cast.hpp | 3 ++- lexical_cast_test.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 3ac3cc9..6479e5d 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1687,7 +1687,8 @@ namespace boost interpreter(buf, buf + src_len); Target result; - if(!(interpreter << arg && interpreter >> 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/lexical_cast_test.cpp b/lexical_cast_test.cpp index 37753ca..f07926b 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -99,6 +99,7 @@ void test_allocator(); void test_wallocator(); #endif void test_char_types_conversions(); +void operators_overload_test(); unit_test::test_suite *init_unit_test_suite(int, char *[]) { @@ -140,6 +141,7 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) #endif suite->add(BOOST_TEST_CASE(&test_char_types_conversions)); + suite->add(BOOST_TEST_CASE(&operators_overload_test)); return suite; } @@ -958,7 +960,33 @@ void test_char_types_conversions() +struct foo_operators_test +{ + foo_operators_test() : f(2) {} + int f; +}; +template +OStream& operator<<(OStream& ostr, const foo_operators_test& foo) +{ + ostr << foo.f; + return ostr; +} +template +IStream& operator>>(IStream& istr, foo_operators_test& foo) +{ + istr >> foo.f; + return istr; +} +void operators_overload_test() +{ + foo_operators_test foo; + BOOST_CHECK_EQUAL(boost::lexical_cast(foo), "2"); + BOOST_CHECK_EQUAL((boost::lexical_cast("2")).f, 2); + + // Must compile + (void)boost::lexical_cast(foo); +} From 2acef7aa443b2cb448197b98289905b22e321746 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 5 Sep 2011 19:00:29 +0000 Subject: [PATCH 116/242] Basic support for char16_t and char32_t [SVN r74243] --- include/boost/lexical_cast.hpp | 223 ++++++++++++++++++++------------- lexical_cast_test.cpp | 34 ++++- 2 files changed, 166 insertions(+), 91 deletions(-) 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 + From d2ae7fdbd7578ac43427b2962d8f8a3d44f22718 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sat, 17 Sep 2011 09:09:27 +0000 Subject: [PATCH 117/242] char16_t and char32_t conversions now work on gcc for C locale Optimizations for C locale Performance section of documentation updated [SVN r74432] --- doc/lexical_cast.qbk | 780 +++++++++++++++------------------ include/boost/lexical_cast.hpp | 175 ++++---- lexical_cast_test.cpp | 10 + 3 files changed, 448 insertions(+), 517 deletions(-) diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index 9fb6cdf..b540267 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -243,457 +243,365 @@ Do not use this results to compare compilers, because tests were taken on differ [section clang-linux-2.8][table:id Performance Table (clang-linux-2.8) [[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]] -[[ string->char ][ !!! *<1* !!! ][ 106 ][ 11 ][ 11 ]] -[[ string->signed char ][ !!! *<1* !!! ][ 102 ][ 8 ][ 8 ]] -[[ string->unsigned char ][ !!! *<1* !!! ][ 83 ][ 7 ][ 15 ]] -[[ string->int ][ !!! *8* !!! ][ 114 ][ 21 ][ 17 ]] -[[ string->short ][ !!! *10* !!! ][ 111 ][ 20 ][ 17 ]] -[[ string->long int ][ !!! *9* !!! ][ 113 ][ 20 ][ 16 ]] -[[ string->long long ][ !!! *9* !!! ][ 112 ][ 21 ][ 16 ]] -[[ string->unsigned int ][ !!! *9* !!! ][ 115 ][ 23 ][ 17 ]] -[[ string->unsigned short ][ !!! *7* !!! ][ 111 ][ 21 ][ 16 ]] -[[ string->unsigned long int ][ !!! *9* !!! ][ 106 ][ 20 ][ 17 ]] -[[ string->unsigned long long ][ !!! *9* !!! ][ 104 ][ 21 ][ 17 ]] -[[ string->bool ][ !!! *<1* !!! ][ 101 ][ 17 ][ 10 ]] -[[ string->float ][ !!! *16* !!! ][ 175 ][ 67 ][ 33 ]] -[[ string->double ][ !!! *18* !!! ][ 196 ][ 91 ][ 56 ]] -[[ string->long double ][ 126 ][ 198 ][ 92 ][ !!! *61* !!! ]] -[[ char->string ][ !!! *12* !!! ][ 101 ][ 16 ][ 12 ]] -[[ unsigned char->string ][ !!! *10* !!! ][ 103 ][ 18 ][ 17 ]] -[[ signed char->string ][ !!! *12* !!! ][ 101 ][ 18 ][ 12 ]] -[[ int->string ][ !!! *19* !!! ][ 124 ][ 25 ][ 19 ]] -[[ short->string ][ 23 ][ 124 ][ 26 ][ !!! *17* !!! ]] -[[ long int->string ][ 20 ][ 123 ][ 23 ][ !!! *17* !!! ]] -[[ long long->string ][ 19 ][ 124 ][ 23 ][ !!! *18* !!! ]] -[[ unsigned int->string ][ 18 ][ 122 ][ 28 ][ !!! *17* !!! ]] -[[ unsigned short->string ][ 36 ][ 160 ][ 31 ][ !!! *17* !!! ]] -[[ unsigned long int->string ][ 22 ][ 123 ][ 28 ][ !!! *18* !!! ]] -[[ unsigned long long->string ][ !!! *23* !!! ][ 137 ][ 32 ][ 23 ]] -[[ bool->string ][ !!! *11* !!! ][ 124 ][ 26 ][ 17 ]] -[[ float->string ][ 178 ][ 273 ][ 124 ][ !!! *57* !!! ]] -[[ double->string ][ 227 ][ 450 ][ 241 ][ !!! *77* !!! ]] -[[ long double->string ][ 249 ][ 331 ][ 185 ][ !!! *85* !!! ]] -[[ char*->char ][ !!! *<1* !!! ][ 109 ][ 9 ][ 11 ]] -[[ char*->signed char ][ !!! *<1* !!! ][ 105 ][ 15 ][ 8 ]] -[[ char*->unsigned char ][ !!! *<1* !!! ][ 111 ][ 11 ][ 20 ]] -[[ char*->int ][ !!! *7* !!! ][ 143 ][ 25 ][ 19 ]] -[[ char*->short ][ !!! *10* !!! ][ 131 ][ 24 ][ 18 ]] -[[ char*->long int ][ !!! *12* !!! ][ 134 ][ 24 ][ 18 ]] -[[ char*->long long ][ !!! *12* !!! ][ 132 ][ 26 ][ 17 ]] -[[ char*->unsigned int ][ !!! *10* !!! ][ 133 ][ 26 ][ 19 ]] -[[ char*->unsigned short ][ !!! *11* !!! ][ 127 ][ 24 ][ 20 ]] -[[ char*->unsigned long int ][ !!! *10* !!! ][ 143 ][ 26 ][ 19 ]] -[[ char*->unsigned long long ][ !!! *12* !!! ][ 137 ][ 26 ][ 19 ]] -[[ char*->bool ][ !!! *2* !!! ][ 138 ][ 27 ][ 13 ]] -[[ char*->float ][ !!! *19* !!! ][ 186 ][ 65 ][ 31 ]] -[[ char*->double ][ !!! *19* !!! ][ 195 ][ 96 ][ 57 ]] -[[ char*->long double ][ 134 ][ 200 ][ 92 ][ !!! *61* !!! ]] -[[ unsigned char*->char ][ !!! *<1* !!! ][ 87 ][ 8 ][ 10 ]] -[[ unsigned char*->signed char ][ !!! *<1* !!! ][ 87 ][ 8 ][ 10 ]] -[[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 89 ][ 8 ][ 16 ]] -[[ unsigned char*->int ][ !!! *10* !!! ][ 117 ][ 22 ][ 17 ]] -[[ unsigned char*->short ][ !!! *11* !!! ][ 117 ][ 21 ][ 17 ]] -[[ unsigned char*->long int ][ !!! *10* !!! ][ 116 ][ 22 ][ 17 ]] -[[ unsigned char*->long long ][ !!! *9* !!! ][ 116 ][ 22 ][ 17 ]] -[[ unsigned char*->unsigned int ][ !!! *10* !!! ][ 117 ][ 24 ][ 17 ]] -[[ unsigned char*->unsigned short ][ !!! *11* !!! ][ 119 ][ 22 ][ 17 ]] -[[ unsigned char*->unsigned long int ][ !!! *10* !!! ][ 111 ][ 21 ][ 17 ]] -[[ unsigned char*->unsigned long long ][ !!! *10* !!! ][ 109 ][ 21 ][ 17 ]] -[[ unsigned char*->bool ][ !!! *<1* !!! ][ 105 ][ 18 ][ 10 ]] -[[ unsigned char*->float ][ !!! *17* !!! ][ 174 ][ 66 ][ 33 ]] -[[ unsigned char*->double ][ !!! *19* !!! ][ 198 ][ 91 ][ 56 ]] -[[ unsigned char*->long double ][ 129 ][ 200 ][ 92 ][ !!! *58* !!! ]] -[[ unsigned char*->string ][ !!! *12* !!! ][ 122 ][ 20 ][ --- ]] -[[ signed char*->char ][ !!! *<1* !!! ][ 87 ][ 8 ][ 9 ]] -[[ signed char*->signed char ][ !!! *<1* !!! ][ 86 ][ 8 ][ 10 ]] -[[ signed char*->unsigned char ][ !!! *<1* !!! ][ 93 ][ 8 ][ 16 ]] -[[ signed char*->int ][ !!! *10* !!! ][ 117 ][ 21 ][ 17 ]] -[[ signed char*->short ][ !!! *11* !!! ][ 117 ][ 22 ][ 17 ]] -[[ signed char*->long int ][ !!! *10* !!! ][ 115 ][ 21 ][ 17 ]] -[[ signed char*->long long ][ !!! *10* !!! ][ 115 ][ 24 ][ 17 ]] -[[ signed char*->unsigned int ][ !!! *10* !!! ][ 118 ][ 24 ][ 17 ]] -[[ signed char*->unsigned short ][ !!! *11* !!! ][ 139 ][ 27 ][ 20 ]] -[[ signed char*->unsigned long int ][ !!! *9* !!! ][ 144 ][ 27 ][ 19 ]] -[[ signed char*->unsigned long long ][ !!! *7* !!! ][ 127 ][ 25 ][ 22 ]] -[[ signed char*->bool ][ !!! *<1* !!! ][ 123 ][ 23 ][ 9 ]] -[[ signed char*->float ][ !!! *21* !!! ][ 207 ][ 80 ][ 41 ]] -[[ signed char*->double ][ !!! *23* !!! ][ 255 ][ 115 ][ 68 ]] -[[ signed char*->long double ][ 159 ][ 275 ][ 125 ][ !!! *72* !!! ]] -[[ signed char*->string ][ !!! *16* !!! ][ 155 ][ 27 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 150 ][ 32 ][ --- ]] -[[ float->double ][ !!! *<1* !!! ][ 304 ][ 162 ][ --- ]] -[[ double->double ][ !!! *<1* !!! ][ 298 ][ 168 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 311 ][ 154 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 308 ][ 154 ][ --- ]] -[[ char->unsigned char ][ !!! *<1* !!! ][ 97 ][ 9 ][ --- ]] -[[ char->signed char ][ !!! *<1* !!! ][ 94 ][ 11 ][ --- ]] -[[ unsigned char->char ][ !!! *<1* !!! ][ 106 ][ 8 ][ --- ]] -[[ signed char->char ][ !!! *<1* !!! ][ 111 ][ 8 ][ --- ]] -] -[endsect] -[section gcc-4.3][table:id Performance Table (gcc-4.3) -[[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]] -[[ string->char ][ !!! *<1* !!! ][ 92 ][ 7 ][ 8 ]] -[[ string->signed char ][ !!! *<1* !!! ][ 92 ][ 7 ][ 8 ]] -[[ string->unsigned char ][ !!! *<1* !!! ][ 92 ][ 7 ][ 13 ]] -[[ string->int ][ !!! *6* !!! ][ 115 ][ 21 ][ 14 ]] -[[ string->short ][ !!! *7* !!! ][ 141 ][ 26 ][ 24 ]] -[[ string->long int ][ !!! *7* !!! ][ 141 ][ 27 ][ 18 ]] -[[ string->long long ][ !!! *7* !!! ][ 153 ][ 28 ][ 17 ]] -[[ string->unsigned int ][ !!! *7* !!! ][ 156 ][ 26 ][ 18 ]] -[[ string->unsigned short ][ !!! *8* !!! ][ 146 ][ 25 ][ 18 ]] -[[ string->unsigned long int ][ !!! *9* !!! ][ 143 ][ 29 ][ 37 ]] -[[ string->unsigned long long ][ !!! *14* !!! ][ 135 ][ 20 ][ 15 ]] -[[ string->bool ][ !!! *<1* !!! ][ 117 ][ 20 ][ 8 ]] -[[ string->float ][ !!! *15* !!! ][ 177 ][ 63 ][ 31 ]] -[[ string->double ][ !!! *15* !!! ][ 198 ][ 89 ][ 54 ]] -[[ string->long double ][ 133 ][ 198 ][ 88 ][ !!! *55* !!! ]] -[[ char->string ][ !!! *10* !!! ][ 108 ][ 16 ][ 12 ]] -[[ unsigned char->string ][ !!! *10* !!! ][ 119 ][ 18 ][ 15 ]] -[[ signed char->string ][ !!! *10* !!! ][ 111 ][ 24 ][ 11 ]] -[[ int->string ][ !!! *14* !!! ][ 129 ][ 22 ][ 15 ]] -[[ short->string ][ !!! *14* !!! ][ 128 ][ 22 ][ 17 ]] -[[ long int->string ][ !!! *14* !!! ][ 127 ][ 21 ][ 17 ]] -[[ long long->string ][ !!! *14* !!! ][ 127 ][ 22 ][ 18 ]] -[[ unsigned int->string ][ !!! *15* !!! ][ 124 ][ 22 ][ 17 ]] -[[ unsigned short->string ][ 16 ][ 125 ][ 22 ][ !!! *15* !!! ]] -[[ unsigned long int->string ][ !!! *15* !!! ][ 125 ][ 22 ][ 17 ]] -[[ unsigned long long->string ][ !!! *18* !!! ][ 138 ][ 34 ][ 23 ]] -[[ bool->string ][ !!! *7* !!! ][ 120 ][ 22 ][ 12 ]] -[[ float->string ][ 136 ][ 229 ][ 110 ][ !!! *48* !!! ]] -[[ double->string ][ 184 ][ 270 ][ 136 ][ !!! *67* !!! ]] -[[ long double->string ][ 198 ][ 264 ][ 148 ][ !!! *69* !!! ]] -[[ char*->char ][ !!! *<1* !!! ][ 98 ][ 8 ][ 8 ]] -[[ char*->signed char ][ !!! *<1* !!! ][ 99 ][ 8 ][ 8 ]] -[[ char*->unsigned char ][ !!! *<1* !!! ][ 96 ][ 8 ][ 14 ]] -[[ char*->int ][ !!! *8* !!! ][ 120 ][ 21 ][ 15 ]] -[[ char*->short ][ !!! *8* !!! ][ 122 ][ 22 ][ 16 ]] -[[ char*->long int ][ !!! *8* !!! ][ 122 ][ 24 ][ 16 ]] -[[ char*->long long ][ !!! *8* !!! ][ 120 ][ 23 ][ 14 ]] -[[ char*->unsigned int ][ !!! *7* !!! ][ 123 ][ 23 ][ 15 ]] -[[ char*->unsigned short ][ !!! *8* !!! ][ 123 ][ 24 ][ 15 ]] -[[ char*->unsigned long int ][ !!! *8* !!! ][ 121 ][ 22 ][ 14 ]] -[[ char*->unsigned long long ][ !!! *7* !!! ][ 116 ][ 20 ][ 16 ]] -[[ char*->bool ][ !!! *<1* !!! ][ 107 ][ 18 ][ 10 ]] -[[ char*->float ][ !!! *14* !!! ][ 181 ][ 67 ][ 32 ]] -[[ char*->double ][ !!! *16* !!! ][ 197 ][ 88 ][ 53 ]] -[[ char*->long double ][ 127 ][ 208 ][ 93 ][ !!! *56* !!! ]] -[[ unsigned char*->char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 8 ]] -[[ unsigned char*->signed char ][ !!! *<1* !!! ][ 93 ][ 8 ][ 10 ]] -[[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 15 ]] -[[ unsigned char*->int ][ !!! *7* !!! ][ 117 ][ 21 ][ 16 ]] -[[ unsigned char*->short ][ !!! *8* !!! ][ 119 ][ 21 ][ 16 ]] -[[ unsigned char*->long int ][ !!! *7* !!! ][ 117 ][ 22 ][ 16 ]] -[[ unsigned char*->long long ][ !!! *8* !!! ][ 119 ][ 23 ][ 16 ]] -[[ unsigned char*->unsigned int ][ !!! *10* !!! ][ 123 ][ 20 ][ 15 ]] -[[ unsigned char*->unsigned short ][ !!! *8* !!! ][ 122 ][ 24 ][ 15 ]] -[[ unsigned char*->unsigned long int ][ !!! *8* !!! ][ 120 ][ 21 ][ 14 ]] -[[ unsigned char*->unsigned long long ][ !!! *8* !!! ][ 118 ][ 23 ][ 16 ]] -[[ unsigned char*->bool ][ !!! *1* !!! ][ 108 ][ 18 ][ 8 ]] -[[ unsigned char*->float ][ !!! *13* !!! ][ 182 ][ 63 ][ 30 ]] -[[ unsigned char*->double ][ !!! *16* !!! ][ 204 ][ 87 ][ 53 ]] -[[ unsigned char*->long double ][ 126 ][ 206 ][ 90 ][ !!! *60* !!! ]] -[[ unsigned char*->string ][ !!! *9* !!! ][ 123 ][ 21 ][ --- ]] -[[ signed char*->char ][ !!! *<1* !!! ][ 95 ][ 8 ][ 10 ]] -[[ signed char*->signed char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 10 ]] -[[ signed char*->unsigned char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 15 ]] -[[ signed char*->int ][ !!! *8* !!! ][ 117 ][ 22 ][ 16 ]] -[[ signed char*->short ][ !!! *7* !!! ][ 117 ][ 22 ][ 16 ]] -[[ signed char*->long int ][ !!! *8* !!! ][ 118 ][ 25 ][ 15 ]] -[[ signed char*->long long ][ !!! *7* !!! ][ 117 ][ 24 ][ 16 ]] -[[ signed char*->unsigned int ][ !!! *7* !!! ][ 120 ][ 20 ][ 16 ]] -[[ signed char*->unsigned short ][ !!! *8* !!! ][ 124 ][ 24 ][ 15 ]] -[[ signed char*->unsigned long int ][ !!! *8* !!! ][ 115 ][ 21 ][ 16 ]] -[[ signed char*->unsigned long long ][ !!! *9* !!! ][ 120 ][ 21 ][ 16 ]] -[[ signed char*->bool ][ !!! *1* !!! ][ 112 ][ 19 ][ 8 ]] -[[ signed char*->float ][ !!! *14* !!! ][ 183 ][ 64 ][ 31 ]] -[[ signed char*->double ][ !!! *18* !!! ][ 208 ][ 87 ][ 51 ]] -[[ signed char*->long double ][ 126 ][ 217 ][ 94 ][ !!! *55* !!! ]] -[[ signed char*->string ][ !!! *12* !!! ][ 126 ][ 22 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 146 ][ 23 ][ --- ]] -[[ float->double ][ !!! *<1* !!! ][ 275 ][ 139 ][ --- ]] -[[ double->double ][ !!! *<1* !!! ][ 270 ][ 142 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 281 ][ 145 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 301 ][ 145 ][ --- ]] -[[ char->unsigned char ][ !!! *<1* !!! ][ 96 ][ 7 ][ --- ]] -[[ char->signed char ][ !!! *<1* !!! ][ 95 ][ 7 ][ --- ]] -[[ unsigned char->char ][ !!! *<1* !!! ][ 96 ][ 7 ][ --- ]] -[[ signed char->char ][ !!! *<1* !!! ][ 91 ][ 7 ][ --- ]] +[[ string->char ][ !!! *<1* !!! ][ 148 ][ 14 ][ 12 ]] +[[ string->signed char ][ !!! *<1* !!! ][ 97 ][ 8 ][ 7 ]] +[[ string->unsigned char ][ !!! *<1* !!! ][ 90 ][ 8 ][ 13 ]] +[[ string->int ][ !!! *4* !!! ][ 102 ][ 19 ][ 15 ]] +[[ string->short ][ !!! *4* !!! ][ 105 ][ 20 ][ 15 ]] +[[ string->long int ][ !!! *4* !!! ][ 105 ][ 19 ][ 15 ]] +[[ string->long long ][ !!! *4* !!! ][ 115 ][ 19 ][ 14 ]] +[[ string->unsigned int ][ !!! *4* !!! ][ 102 ][ 18 ][ 14 ]] +[[ string->unsigned short ][ !!! *4* !!! ][ 101 ][ 19 ][ 15 ]] +[[ string->unsigned long int ][ !!! *3* !!! ][ 107 ][ 20 ][ 14 ]] +[[ string->unsigned long long ][ !!! *3* !!! ][ 103 ][ 20 ][ 14 ]] +[[ string->bool ][ !!! *<1* !!! ][ 97 ][ 16 ][ 8 ]] +[[ string->float ][ !!! *21* !!! ][ 170 ][ 61 ][ 32 ]] +[[ string->double ][ !!! *18* !!! ][ 206 ][ 93 ][ 58 ]] +[[ string->long double ][ 135 ][ 221 ][ 94 ][ !!! *57* !!! ]] +[[ char->string ][ !!! *7* !!! ][ 100 ][ 17 ][ 13 ]] +[[ unsigned char->string ][ !!! *7* !!! ][ 99 ][ 18 ][ 16 ]] +[[ signed char->string ][ !!! *7* !!! ][ 101 ][ 17 ][ 12 ]] +[[ int->string ][ !!! *13* !!! ][ 110 ][ 23 ][ 15 ]] +[[ short->string ][ !!! *13* !!! ][ 112 ][ 24 ][ 18 ]] +[[ long int->string ][ !!! *13* !!! ][ 119 ][ 23 ][ 17 ]] +[[ long long->string ][ !!! *13* !!! ][ 110 ][ 23 ][ 18 ]] +[[ unsigned int->string ][ !!! *14* !!! ][ 113 ][ 24 ][ 17 ]] +[[ unsigned short->string ][ !!! *13* !!! ][ 108 ][ 24 ][ 17 ]] +[[ unsigned long int->string ][ !!! *13* !!! ][ 109 ][ 24 ][ 16 ]] +[[ unsigned long long->string ][ !!! *13* !!! ][ 110 ][ 23 ][ 17 ]] +[[ bool->string ][ !!! *7* !!! ][ 105 ][ 24 ][ 12 ]] +[[ float->string ][ 70 ][ 192 ][ 94 ][ !!! *49* !!! ]] +[[ double->string ][ 106 ][ 217 ][ 122 ][ !!! *76* !!! ]] +[[ long double->string ][ 120 ][ 219 ][ 123 ][ !!! *80* !!! ]] +[[ char*->char ][ !!! *2* !!! ][ 90 ][ 9 ][ 8 ]] +[[ char*->signed char ][ !!! *2* !!! ][ 87 ][ 10 ][ 7 ]] +[[ char*->unsigned char ][ !!! *3* !!! ][ 90 ][ 10 ][ 13 ]] +[[ char*->int ][ !!! *6* !!! ][ 107 ][ 21 ][ 15 ]] +[[ char*->short ][ !!! *6* !!! ][ 110 ][ 19 ][ 14 ]] +[[ char*->long int ][ !!! *6* !!! ][ 103 ][ 19 ][ 14 ]] +[[ char*->long long ][ !!! *7* !!! ][ 104 ][ 20 ][ 15 ]] +[[ char*->unsigned int ][ !!! *6* !!! ][ 101 ][ 20 ][ 15 ]] +[[ char*->unsigned short ][ !!! *7* !!! ][ 100 ][ 20 ][ 14 ]] +[[ char*->unsigned long int ][ !!! *6* !!! ][ 105 ][ 22 ][ 15 ]] +[[ char*->unsigned long long ][ !!! *7* !!! ][ 106 ][ 21 ][ 14 ]] +[[ char*->bool ][ !!! *2* !!! ][ 99 ][ 18 ][ 7 ]] +[[ char*->float ][ !!! *22* !!! ][ 159 ][ 67 ][ 33 ]] +[[ char*->double ][ !!! *20* !!! ][ 205 ][ 94 ][ 58 ]] +[[ char*->long double ][ 140 ][ 214 ][ 95 ][ !!! *58* !!! ]] +[[ unsigned char*->char ][ !!! *2* !!! ][ 92 ][ 9 ][ 7 ]] +[[ unsigned char*->signed char ][ !!! *2* !!! ][ 89 ][ 10 ][ 7 ]] +[[ unsigned char*->unsigned char ][ !!! *2* !!! ][ 89 ][ 10 ][ 14 ]] +[[ unsigned char*->int ][ !!! *6* !!! ][ 104 ][ 20 ][ 14 ]] +[[ unsigned char*->short ][ !!! *6* !!! ][ 106 ][ 21 ][ 14 ]] +[[ unsigned char*->long int ][ !!! *6* !!! ][ 105 ][ 19 ][ 14 ]] +[[ unsigned char*->long long ][ !!! *6* !!! ][ 106 ][ 20 ][ 15 ]] +[[ unsigned char*->unsigned int ][ !!! *7* !!! ][ 105 ][ 19 ][ 14 ]] +[[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 103 ][ 19 ][ 14 ]] +[[ unsigned char*->unsigned long int ][ !!! *6* !!! ][ 106 ][ 19 ][ 14 ]] +[[ unsigned char*->unsigned long long ][ !!! *6* !!! ][ 104 ][ 21 ][ 15 ]] +[[ unsigned char*->bool ][ !!! *2* !!! ][ 102 ][ 18 ][ 7 ]] +[[ unsigned char*->float ][ !!! *23* !!! ][ 160 ][ 66 ][ 32 ]] +[[ unsigned char*->double ][ !!! *20* !!! ][ 201 ][ 95 ][ 58 ]] +[[ unsigned char*->long double ][ 144 ][ 221 ][ 95 ][ !!! *60* !!! ]] +[[ unsigned char*->string ][ !!! *12* !!! ][ 104 ][ 23 ][ --- ]] +[[ signed char*->char ][ !!! *2* !!! ][ 90 ][ 9 ][ 7 ]] +[[ signed char*->signed char ][ !!! *2* !!! ][ 89 ][ 9 ][ 7 ]] +[[ signed char*->unsigned char ][ !!! *2* !!! ][ 89 ][ 10 ][ 13 ]] +[[ signed char*->int ][ !!! *6* !!! ][ 106 ][ 19 ][ 15 ]] +[[ signed char*->short ][ !!! *6* !!! ][ 107 ][ 20 ][ 15 ]] +[[ signed char*->long int ][ !!! *6* !!! ][ 103 ][ 19 ][ 14 ]] +[[ signed char*->long long ][ !!! *6* !!! ][ 103 ][ 19 ][ 14 ]] +[[ signed char*->unsigned int ][ !!! *6* !!! ][ 101 ][ 19 ][ 15 ]] +[[ signed char*->unsigned short ][ !!! *6* !!! ][ 101 ][ 19 ][ 16 ]] +[[ signed char*->unsigned long int ][ !!! *6* !!! ][ 105 ][ 22 ][ 15 ]] +[[ signed char*->unsigned long long ][ !!! *6* !!! ][ 104 ][ 21 ][ 15 ]] +[[ signed char*->bool ][ !!! *2* !!! ][ 100 ][ 18 ][ 7 ]] +[[ signed char*->float ][ !!! *23* !!! ][ 161 ][ 62 ][ 32 ]] +[[ signed char*->double ][ !!! *20* !!! ][ 207 ][ 102 ][ 57 ]] +[[ signed char*->long double ][ 144 ][ 216 ][ 96 ][ !!! *63* !!! ]] +[[ signed char*->string ][ !!! *12* !!! ][ 104 ][ 23 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 110 ][ 22 ][ --- ]] +[[ float->double ][ !!! *<1* !!! ][ 223 ][ 113 ][ --- ]] +[[ double->double ][ !!! *<1* !!! ][ 227 ][ 111 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 231 ][ 122 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 229 ][ 121 ][ --- ]] +[[ char->unsigned char ][ !!! *<1* !!! ][ 90 ][ 8 ][ --- ]] +[[ char->signed char ][ !!! *<1* !!! ][ 88 ][ 8 ][ --- ]] +[[ unsigned char->char ][ !!! *<1* !!! ][ 89 ][ 8 ][ --- ]] +[[ signed char->char ][ !!! *<1* !!! ][ 91 ][ 9 ][ --- ]] ] [endsect] [section gcc-4.4][table:id Performance Table (gcc-4.4) [[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]] -[[ string->char ][ !!! *<1* !!! ][ 81 ][ 8 ][ 8 ]] -[[ string->signed char ][ !!! *<1* !!! ][ 110 ][ 7 ][ 9 ]] -[[ string->unsigned char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 18 ]] -[[ string->int ][ !!! *9* !!! ][ 125 ][ 25 ][ 15 ]] -[[ string->short ][ !!! *7* !!! ][ 113 ][ 25 ][ 15 ]] -[[ string->long int ][ !!! *8* !!! ][ 112 ][ 24 ][ 15 ]] -[[ string->long long ][ !!! *8* !!! ][ 109 ][ 22 ][ 15 ]] -[[ string->unsigned int ][ !!! *8* !!! ][ 108 ][ 26 ][ 20 ]] -[[ string->unsigned short ][ !!! *9* !!! ][ 125 ][ 22 ][ 18 ]] -[[ string->unsigned long int ][ !!! *11* !!! ][ 125 ][ 32 ][ 17 ]] -[[ string->unsigned long long ][ !!! *10* !!! ][ 119 ][ 23 ][ 19 ]] -[[ string->bool ][ !!! *<1* !!! ][ 132 ][ 24 ][ 11 ]] -[[ string->float ][ !!! *18* !!! ][ 178 ][ 75 ][ 37 ]] -[[ string->double ][ !!! *24* !!! ][ 236 ][ 100 ][ 64 ]] -[[ string->long double ][ 146 ][ 233 ][ 118 ][ !!! *75* !!! ]] -[[ char->string ][ !!! *8* !!! ][ 136 ][ 22 ][ 13 ]] -[[ unsigned char->string ][ !!! *11* !!! ][ 127 ][ 22 ][ 20 ]] -[[ signed char->string ][ !!! *11* !!! ][ 128 ][ 21 ][ 15 ]] -[[ int->string ][ 25 ][ 159 ][ 30 ][ !!! *20* !!! ]] -[[ short->string ][ 25 ][ 151 ][ 30 ][ !!! *20* !!! ]] -[[ long int->string ][ !!! *20* !!! ][ 150 ][ 30 ][ 20 ]] -[[ long long->string ][ !!! *19* !!! ][ 164 ][ 26 ][ 21 ]] -[[ unsigned int->string ][ 35 ][ 147 ][ 27 ][ !!! *20* !!! ]] -[[ unsigned short->string ][ 26 ][ 149 ][ 26 ][ !!! *20* !!! ]] -[[ unsigned long int->string ][ 19 ][ 142 ][ 38 ][ !!! *17* !!! ]] -[[ unsigned long long->string ][ !!! *20* !!! ][ 139 ][ 36 ][ 26 ]] -[[ bool->string ][ !!! *10* !!! ][ 144 ][ 28 ][ 13 ]] -[[ float->string ][ 166 ][ 268 ][ 127 ][ !!! *52* !!! ]] -[[ double->string ][ 192 ][ 285 ][ 170 ][ !!! *90* !!! ]] -[[ long double->string ][ 250 ][ 344 ][ 160 ][ !!! *85* !!! ]] -[[ char*->char ][ !!! *<1* !!! ][ 90 ][ 9 ][ 8 ]] -[[ char*->signed char ][ !!! *<1* !!! ][ 82 ][ 9 ][ 8 ]] -[[ char*->unsigned char ][ !!! *<1* !!! ][ 88 ][ 8 ][ 13 ]] -[[ char*->int ][ !!! *6* !!! ][ 113 ][ 26 ][ 14 ]] -[[ char*->short ][ !!! *6* !!! ][ 114 ][ 25 ][ 14 ]] -[[ char*->long int ][ !!! *6* !!! ][ 123 ][ 38 ][ 17 ]] -[[ char*->long long ][ !!! *7* !!! ][ 126 ][ 37 ][ 17 ]] -[[ char*->unsigned int ][ !!! *6* !!! ][ 134 ][ 26 ][ 18 ]] -[[ char*->unsigned short ][ !!! *8* !!! ][ 126 ][ 24 ][ 17 ]] -[[ char*->unsigned long int ][ !!! *8* !!! ][ 121 ][ 24 ][ 17 ]] -[[ char*->unsigned long long ][ !!! *5* !!! ][ 117 ][ 24 ][ 18 ]] -[[ char*->bool ][ !!! *<1* !!! ][ 116 ][ 24 ][ 9 ]] -[[ char*->float ][ !!! *16* !!! ][ 171 ][ 67 ][ 30 ]] -[[ char*->double ][ !!! *15* !!! ][ 204 ][ 109 ][ 64 ]] -[[ char*->long double ][ 152 ][ 250 ][ 110 ][ !!! *71* !!! ]] -[[ unsigned char*->char ][ !!! *<1* !!! ][ 109 ][ 11 ][ 11 ]] -[[ unsigned char*->signed char ][ !!! *<1* !!! ][ 108 ][ 11 ][ 9 ]] -[[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 106 ][ 11 ][ 17 ]] -[[ unsigned char*->int ][ !!! *7* !!! ][ 143 ][ 31 ][ 17 ]] -[[ unsigned char*->short ][ !!! *9* !!! ][ 143 ][ 32 ][ 19 ]] -[[ unsigned char*->long int ][ !!! *8* !!! ][ 153 ][ 30 ][ 18 ]] -[[ unsigned char*->long long ][ !!! *10* !!! ][ 146 ][ 27 ][ 18 ]] -[[ unsigned char*->unsigned int ][ !!! *9* !!! ][ 144 ][ 25 ][ 18 ]] -[[ unsigned char*->unsigned short ][ !!! *9* !!! ][ 138 ][ 26 ][ 17 ]] -[[ unsigned char*->unsigned long int ][ !!! *9* !!! ][ 143 ][ 25 ][ 18 ]] -[[ unsigned char*->unsigned long long ][ !!! *10* !!! ][ 132 ][ 26 ][ 18 ]] -[[ unsigned char*->bool ][ !!! *<1* !!! ][ 102 ][ 18 ][ 9 ]] -[[ unsigned char*->float ][ !!! *13* !!! ][ 171 ][ 65 ][ 31 ]] -[[ unsigned char*->double ][ !!! *14* !!! ][ 197 ][ 89 ][ 53 ]] -[[ unsigned char*->long double ][ 122 ][ 208 ][ 89 ][ !!! *58* !!! ]] -[[ unsigned char*->string ][ !!! *8* !!! ][ 115 ][ 20 ][ --- ]] -[[ signed char*->char ][ !!! *<1* !!! ][ 93 ][ 10 ][ 9 ]] -[[ signed char*->signed char ][ !!! *<1* !!! ][ 91 ][ 8 ][ 8 ]] -[[ signed char*->unsigned char ][ !!! *<1* !!! ][ 90 ][ 10 ][ 15 ]] -[[ signed char*->int ][ !!! *7* !!! ][ 112 ][ 26 ][ 16 ]] -[[ signed char*->short ][ !!! *7* !!! ][ 112 ][ 26 ][ 16 ]] -[[ signed char*->long int ][ !!! *6* !!! ][ 118 ][ 25 ][ 14 ]] -[[ signed char*->long long ][ !!! *13* !!! ][ 114 ][ 25 ][ 14 ]] -[[ signed char*->unsigned int ][ !!! *7* !!! ][ 114 ][ 23 ][ 16 ]] -[[ signed char*->unsigned short ][ !!! *7* !!! ][ 107 ][ 25 ][ 16 ]] -[[ signed char*->unsigned long int ][ !!! *7* !!! ][ 106 ][ 23 ][ 14 ]] -[[ signed char*->unsigned long long ][ !!! *7* !!! ][ 103 ][ 22 ][ 16 ]] -[[ signed char*->bool ][ !!! *<1* !!! ][ 110 ][ 20 ][ 9 ]] -[[ signed char*->float ][ !!! *13* !!! ][ 175 ][ 66 ][ 32 ]] -[[ signed char*->double ][ !!! *14* !!! ][ 203 ][ 90 ][ 53 ]] -[[ signed char*->long double ][ 124 ][ 205 ][ 87 ][ !!! *55* !!! ]] -[[ signed char*->string ][ !!! *8* !!! ][ 120 ][ 20 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 116 ][ 28 ][ --- ]] -[[ float->double ][ !!! *<1* !!! ][ 264 ][ 135 ][ --- ]] -[[ double->double ][ !!! *<1* !!! ][ 260 ][ 140 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 275 ][ 135 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 274 ][ 135 ][ --- ]] -[[ char->unsigned char ][ !!! *<1* !!! ][ 77 ][ 7 ][ --- ]] -[[ char->signed char ][ !!! *<1* !!! ][ 79 ][ 7 ][ --- ]] -[[ unsigned char->char ][ !!! *<1* !!! ][ 78 ][ 8 ][ --- ]] -[[ signed char->char ][ !!! *<1* !!! ][ 83 ][ 7 ][ --- ]] +[[ string->char ][ !!! *<1* !!! ][ 90 ][ 7 ][ 7 ]] +[[ string->signed char ][ !!! *<1* !!! ][ 88 ][ 7 ][ 8 ]] +[[ string->unsigned char ][ !!! *<1* !!! ][ 88 ][ 8 ][ 14 ]] +[[ string->int ][ !!! *3* !!! ][ 103 ][ 18 ][ 15 ]] +[[ string->short ][ !!! *3* !!! ][ 105 ][ 20 ][ 15 ]] +[[ string->long int ][ !!! *3* !!! ][ 101 ][ 18 ][ 16 ]] +[[ string->long long ][ !!! *3* !!! ][ 101 ][ 18 ][ 15 ]] +[[ string->unsigned int ][ !!! *3* !!! ][ 98 ][ 23 ][ 14 ]] +[[ string->unsigned short ][ !!! *3* !!! ][ 100 ][ 17 ][ 14 ]] +[[ string->unsigned long int ][ !!! *3* !!! ][ 100 ][ 21 ][ 15 ]] +[[ string->unsigned long long ][ !!! *3* !!! ][ 99 ][ 19 ][ 15 ]] +[[ string->bool ][ !!! *<1* !!! ][ 95 ][ 16 ][ 8 ]] +[[ string->float ][ !!! *13* !!! ][ 160 ][ 61 ][ 33 ]] +[[ string->double ][ !!! *14* !!! ][ 206 ][ 93 ][ 59 ]] +[[ string->long double ][ 128 ][ 217 ][ 96 ][ !!! *61* !!! ]] +[[ char->string ][ !!! *7* !!! ][ 100 ][ 17 ][ 12 ]] +[[ unsigned char->string ][ !!! *7* !!! ][ 109 ][ 17 ][ 16 ]] +[[ signed char->string ][ !!! *7* !!! ][ 99 ][ 17 ][ 12 ]] +[[ int->string ][ !!! *13* !!! ][ 110 ][ 21 ][ 15 ]] +[[ short->string ][ !!! *14* !!! ][ 110 ][ 22 ][ 17 ]] +[[ long int->string ][ !!! *14* !!! ][ 109 ][ 21 ][ 16 ]] +[[ long long->string ][ !!! *13* !!! ][ 114 ][ 20 ][ 17 ]] +[[ unsigned int->string ][ !!! *13* !!! ][ 109 ][ 23 ][ 15 ]] +[[ unsigned short->string ][ !!! *14* !!! ][ 109 ][ 23 ][ 17 ]] +[[ unsigned long int->string ][ !!! *13* !!! ][ 112 ][ 23 ][ 16 ]] +[[ unsigned long long->string ][ !!! *14* !!! ][ 109 ][ 21 ][ 17 ]] +[[ bool->string ][ !!! *7* !!! ][ 108 ][ 23 ][ 11 ]] +[[ float->string ][ 63 ][ 185 ][ 92 ][ !!! *50* !!! ]] +[[ double->string ][ 106 ][ 216 ][ 116 ][ !!! *75* !!! ]] +[[ long double->string ][ 118 ][ 219 ][ 119 ][ !!! *80* !!! ]] +[[ char*->char ][ !!! *1* !!! ][ 93 ][ 9 ][ 9 ]] +[[ char*->signed char ][ !!! *1* !!! ][ 92 ][ 9 ][ 9 ]] +[[ char*->unsigned char ][ !!! *1* !!! ][ 92 ][ 9 ][ 14 ]] +[[ char*->int ][ !!! *4* !!! ][ 107 ][ 19 ][ 15 ]] +[[ char*->short ][ !!! *5* !!! ][ 109 ][ 19 ][ 15 ]] +[[ char*->long int ][ !!! *4* !!! ][ 113 ][ 19 ][ 15 ]] +[[ char*->long long ][ !!! *4* !!! ][ 108 ][ 20 ][ 15 ]] +[[ char*->unsigned int ][ !!! *4* !!! ][ 106 ][ 19 ][ 15 ]] +[[ char*->unsigned short ][ !!! *4* !!! ][ 106 ][ 18 ][ 15 ]] +[[ char*->unsigned long int ][ !!! *4* !!! ][ 103 ][ 22 ][ 15 ]] +[[ char*->unsigned long long ][ !!! *4* !!! ][ 105 ][ 20 ][ 15 ]] +[[ char*->bool ][ !!! *1* !!! ][ 104 ][ 18 ][ 8 ]] +[[ char*->float ][ !!! *15* !!! ][ 164 ][ 62 ][ 33 ]] +[[ char*->double ][ !!! *16* !!! ][ 203 ][ 97 ][ 58 ]] +[[ char*->long double ][ 132 ][ 223 ][ 98 ][ !!! *60* !!! ]] +[[ unsigned char*->char ][ !!! *2* !!! ][ 90 ][ 9 ][ 8 ]] +[[ unsigned char*->signed char ][ !!! *2* !!! ][ 92 ][ 10 ][ 8 ]] +[[ unsigned char*->unsigned char ][ !!! *2* !!! ][ 91 ][ 9 ][ 14 ]] +[[ unsigned char*->int ][ !!! *6* !!! ][ 106 ][ 20 ][ 15 ]] +[[ unsigned char*->short ][ !!! *6* !!! ][ 106 ][ 21 ][ 15 ]] +[[ unsigned char*->long int ][ !!! *6* !!! ][ 111 ][ 19 ][ 15 ]] +[[ unsigned char*->long long ][ !!! *6* !!! ][ 107 ][ 20 ][ 15 ]] +[[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 105 ][ 19 ][ 15 ]] +[[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 103 ][ 18 ][ 15 ]] +[[ unsigned char*->unsigned long int ][ !!! *6* !!! ][ 106 ][ 22 ][ 14 ]] +[[ unsigned char*->unsigned long long ][ !!! *6* !!! ][ 105 ][ 20 ][ 14 ]] +[[ unsigned char*->bool ][ !!! *2* !!! ][ 106 ][ 18 ][ 8 ]] +[[ unsigned char*->float ][ !!! *15* !!! ][ 167 ][ 68 ][ 33 ]] +[[ unsigned char*->double ][ !!! *17* !!! ][ 203 ][ 99 ][ 58 ]] +[[ unsigned char*->long double ][ 129 ][ 216 ][ 97 ][ !!! *61* !!! ]] +[[ unsigned char*->string ][ !!! *13* !!! ][ 111 ][ 23 ][ --- ]] +[[ signed char*->char ][ !!! *2* !!! ][ 92 ][ 9 ][ 8 ]] +[[ signed char*->signed char ][ !!! *2* !!! ][ 91 ][ 9 ][ 8 ]] +[[ signed char*->unsigned char ][ !!! *2* !!! ][ 91 ][ 9 ][ 14 ]] +[[ signed char*->int ][ !!! *6* !!! ][ 107 ][ 19 ][ 15 ]] +[[ signed char*->short ][ !!! *6* !!! ][ 109 ][ 24 ][ 14 ]] +[[ signed char*->long int ][ !!! *6* !!! ][ 112 ][ 19 ][ 15 ]] +[[ signed char*->long long ][ !!! *5* !!! ][ 107 ][ 20 ][ 15 ]] +[[ signed char*->unsigned int ][ !!! *6* !!! ][ 108 ][ 20 ][ 15 ]] +[[ signed char*->unsigned short ][ !!! *6* !!! ][ 104 ][ 18 ][ 15 ]] +[[ signed char*->unsigned long int ][ !!! *6* !!! ][ 102 ][ 22 ][ 15 ]] +[[ signed char*->unsigned long long ][ !!! *6* !!! ][ 104 ][ 20 ][ 15 ]] +[[ signed char*->bool ][ !!! *2* !!! ][ 104 ][ 18 ][ 8 ]] +[[ signed char*->float ][ !!! *16* !!! ][ 165 ][ 63 ][ 33 ]] +[[ signed char*->double ][ !!! *16* !!! ][ 203 ][ 98 ][ 59 ]] +[[ signed char*->long double ][ 129 ][ 215 ][ 98 ][ !!! *61* !!! ]] +[[ signed char*->string ][ !!! *13* !!! ][ 109 ][ 21 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 109 ][ 21 ][ --- ]] +[[ float->double ][ !!! *<1* !!! ][ 221 ][ 102 ][ --- ]] +[[ double->double ][ !!! *<1* !!! ][ 223 ][ 103 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 231 ][ 115 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 231 ][ 115 ][ --- ]] +[[ char->unsigned char ][ !!! *<1* !!! ][ 92 ][ 8 ][ --- ]] +[[ char->signed char ][ !!! *<1* !!! ][ 88 ][ 8 ][ --- ]] +[[ unsigned char->char ][ !!! *<1* !!! ][ 88 ][ 7 ][ --- ]] +[[ signed char->char ][ !!! *<1* !!! ][ 89 ][ 8 ][ --- ]] ] [endsect] [section gcc-4.5][table:id Performance Table (gcc-4.5) [[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]] -[[ string->char ][ !!! *<1* !!! ][ 86 ][ 8 ][ 9 ]] -[[ string->signed char ][ !!! *<1* !!! ][ 88 ][ 9 ][ 9 ]] -[[ string->unsigned char ][ !!! *<1* !!! ][ 87 ][ 8 ][ 15 ]] -[[ string->int ][ !!! *6* !!! ][ 107 ][ 23 ][ 16 ]] -[[ string->short ][ !!! *7* !!! ][ 108 ][ 25 ][ 15 ]] -[[ string->long int ][ !!! *6* !!! ][ 110 ][ 26 ][ 15 ]] -[[ string->long long ][ !!! *7* !!! ][ 110 ][ 26 ][ 15 ]] -[[ string->unsigned int ][ !!! *6* !!! ][ 108 ][ 26 ][ 16 ]] -[[ string->unsigned short ][ !!! *7* !!! ][ 105 ][ 24 ][ 15 ]] -[[ string->unsigned long int ][ !!! *6* !!! ][ 108 ][ 23 ][ 15 ]] -[[ string->unsigned long long ][ !!! *10* !!! ][ 104 ][ 24 ][ 15 ]] -[[ string->bool ][ !!! *<1* !!! ][ 102 ][ 21 ][ 9 ]] -[[ string->float ][ !!! *13* !!! ][ 173 ][ 64 ][ 34 ]] -[[ string->double ][ !!! *15* !!! ][ 196 ][ 89 ][ 53 ]] -[[ string->long double ][ 126 ][ 211 ][ 90 ][ !!! *56* !!! ]] -[[ char->string ][ !!! *8* !!! ][ 107 ][ 20 ][ 10 ]] -[[ unsigned char->string ][ !!! *8* !!! ][ 107 ][ 17 ][ 15 ]] -[[ signed char->string ][ !!! *8* !!! ][ 108 ][ 19 ][ 10 ]] -[[ int->string ][ 16 ][ 129 ][ 25 ][ !!! *15* !!! ]] -[[ short->string ][ !!! *14* !!! ][ 128 ][ 25 ][ 17 ]] -[[ long int->string ][ 20 ][ 128 ][ 24 ][ !!! *15* !!! ]] -[[ long long->string ][ !!! *16* !!! ][ 128 ][ 25 ][ 16 ]] -[[ unsigned int->string ][ !!! *15* !!! ][ 125 ][ 25 ][ 15 ]] -[[ unsigned short->string ][ !!! *14* !!! ][ 125 ][ 24 ][ 15 ]] -[[ unsigned long int->string ][ 16 ][ 125 ][ 25 ][ !!! *15* !!! ]] -[[ unsigned long long->string ][ !!! *18* !!! ][ 140 ][ 32 ][ 22 ]] -[[ bool->string ][ !!! *8* !!! ][ 121 ][ 24 ][ 10 ]] -[[ float->string ][ 137 ][ 226 ][ 108 ][ !!! *48* !!! ]] -[[ double->string ][ 174 ][ 255 ][ 141 ][ !!! *71* !!! ]] -[[ long double->string ][ 208 ][ 268 ][ 144 ][ !!! *72* !!! ]] -[[ char*->char ][ !!! *<1* !!! ][ 93 ][ 8 ][ 9 ]] -[[ char*->signed char ][ !!! *<1* !!! ][ 94 ][ 9 ][ 9 ]] -[[ char*->unsigned char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 15 ]] -[[ char*->int ][ !!! *7* !!! ][ 115 ][ 26 ][ 16 ]] -[[ char*->short ][ !!! *8* !!! ][ 114 ][ 26 ][ 15 ]] -[[ char*->long int ][ !!! *7* !!! ][ 115 ][ 27 ][ 16 ]] -[[ char*->long long ][ !!! *7* !!! ][ 114 ][ 26 ][ 16 ]] -[[ char*->unsigned int ][ !!! *8* !!! ][ 115 ][ 25 ][ 16 ]] -[[ char*->unsigned short ][ !!! *7* !!! ][ 113 ][ 24 ][ 16 ]] -[[ char*->unsigned long int ][ !!! *8* !!! ][ 117 ][ 23 ][ 16 ]] -[[ char*->unsigned long long ][ !!! *8* !!! ][ 107 ][ 25 ][ 16 ]] -[[ char*->bool ][ !!! *<1* !!! ][ 110 ][ 21 ][ 9 ]] -[[ char*->float ][ !!! *17* !!! ][ 170 ][ 67 ][ 34 ]] -[[ char*->double ][ !!! *14* !!! ][ 197 ][ 91 ][ 52 ]] -[[ char*->long double ][ 127 ][ 206 ][ 89 ][ !!! *56* !!! ]] -[[ unsigned char*->char ][ !!! *<1* !!! ][ 83 ][ 8 ][ 9 ]] -[[ unsigned char*->signed char ][ !!! *<1* !!! ][ 83 ][ 10 ][ 9 ]] -[[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 83 ][ 8 ][ 15 ]] -[[ unsigned char*->int ][ !!! *7* !!! ][ 113 ][ 26 ][ 16 ]] -[[ unsigned char*->short ][ !!! *7* !!! ][ 112 ][ 24 ][ 16 ]] -[[ unsigned char*->long int ][ !!! *8* !!! ][ 114 ][ 26 ][ 16 ]] -[[ unsigned char*->long long ][ !!! *8* !!! ][ 113 ][ 26 ][ 16 ]] -[[ unsigned char*->unsigned int ][ !!! *8* !!! ][ 114 ][ 25 ][ 16 ]] -[[ unsigned char*->unsigned short ][ !!! *8* !!! ][ 109 ][ 24 ][ 16 ]] -[[ unsigned char*->unsigned long int ][ !!! *8* !!! ][ 111 ][ 23 ][ 16 ]] -[[ unsigned char*->unsigned long long ][ !!! *7* !!! ][ 106 ][ 25 ][ 16 ]] -[[ unsigned char*->bool ][ !!! *<1* !!! ][ 106 ][ 20 ][ 9 ]] -[[ unsigned char*->float ][ !!! *14* !!! ][ 169 ][ 65 ][ 34 ]] -[[ unsigned char*->double ][ !!! *16* !!! ][ 198 ][ 91 ][ 52 ]] -[[ unsigned char*->long double ][ 127 ][ 205 ][ 88 ][ !!! *56* !!! ]] -[[ unsigned char*->string ][ !!! *10* !!! ][ 123 ][ 21 ][ --- ]] -[[ signed char*->char ][ !!! *<1* !!! ][ 90 ][ 9 ][ 9 ]] -[[ signed char*->signed char ][ !!! *<1* !!! ][ 91 ][ 8 ][ 9 ]] -[[ signed char*->unsigned char ][ !!! *<1* !!! ][ 92 ][ 8 ][ 15 ]] -[[ signed char*->int ][ !!! *7* !!! ][ 116 ][ 26 ][ 16 ]] -[[ signed char*->short ][ !!! *8* !!! ][ 113 ][ 26 ][ 15 ]] -[[ signed char*->long int ][ !!! *8* !!! ][ 113 ][ 24 ][ 16 ]] -[[ signed char*->long long ][ !!! *8* !!! ][ 113 ][ 27 ][ 16 ]] -[[ signed char*->unsigned int ][ !!! *8* !!! ][ 113 ][ 25 ][ 16 ]] -[[ signed char*->unsigned short ][ !!! *7* !!! ][ 107 ][ 24 ][ 16 ]] -[[ signed char*->unsigned long int ][ !!! *7* !!! ][ 111 ][ 23 ][ 17 ]] -[[ signed char*->unsigned long long ][ !!! *8* !!! ][ 105 ][ 25 ][ 16 ]] -[[ signed char*->bool ][ !!! *<1* !!! ][ 106 ][ 21 ][ 9 ]] -[[ signed char*->float ][ !!! *13* !!! ][ 169 ][ 63 ][ 34 ]] -[[ signed char*->double ][ !!! *16* !!! ][ 196 ][ 90 ][ 52 ]] -[[ signed char*->long double ][ 127 ][ 211 ][ 91 ][ !!! *60* !!! ]] -[[ signed char*->string ][ !!! *9* !!! ][ 123 ][ 21 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 120 ][ 29 ][ --- ]] -[[ float->double ][ !!! *<1* !!! ][ 258 ][ 147 ][ --- ]] -[[ double->double ][ !!! *<1* !!! ][ 261 ][ 140 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 266 ][ 138 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 266 ][ 137 ][ --- ]] -[[ char->unsigned char ][ !!! *<1* !!! ][ 89 ][ 8 ][ --- ]] -[[ char->signed char ][ !!! *<1* !!! ][ 91 ][ 8 ][ --- ]] -[[ unsigned char->char ][ !!! *<1* !!! ][ 90 ][ 9 ][ --- ]] +[[ string->char ][ !!! *<1* !!! ][ 91 ][ 8 ][ 7 ]] +[[ string->signed char ][ !!! *<1* !!! ][ 91 ][ 8 ][ 7 ]] +[[ string->unsigned char ][ !!! *<1* !!! ][ 90 ][ 8 ][ 13 ]] +[[ string->int ][ !!! *3* !!! ][ 100 ][ 20 ][ 14 ]] +[[ string->short ][ !!! *3* !!! ][ 106 ][ 20 ][ 14 ]] +[[ string->long int ][ !!! *3* !!! ][ 100 ][ 18 ][ 14 ]] +[[ string->long long ][ !!! *9* !!! ][ 100 ][ 18 ][ 15 ]] +[[ string->unsigned int ][ !!! *3* !!! ][ 97 ][ 20 ][ 14 ]] +[[ string->unsigned short ][ !!! *3* !!! ][ 102 ][ 17 ][ 14 ]] +[[ string->unsigned long int ][ !!! *3* !!! ][ 97 ][ 21 ][ 14 ]] +[[ string->unsigned long long ][ !!! *3* !!! ][ 97 ][ 19 ][ 14 ]] +[[ string->bool ][ !!! *<1* !!! ][ 95 ][ 16 ][ 7 ]] +[[ string->float ][ !!! *15* !!! ][ 157 ][ 63 ][ 32 ]] +[[ string->double ][ !!! *17* !!! ][ 203 ][ 95 ][ 59 ]] +[[ string->long double ][ 129 ][ 216 ][ 93 ][ !!! *58* !!! ]] +[[ char->string ][ !!! *8* !!! ][ 100 ][ 17 ][ 10 ]] +[[ unsigned char->string ][ !!! *8* !!! ][ 96 ][ 18 ][ 16 ]] +[[ signed char->string ][ !!! *8* !!! ][ 96 ][ 18 ][ 10 ]] +[[ int->string ][ !!! *14* !!! ][ 105 ][ 22 ][ 15 ]] +[[ short->string ][ !!! *14* !!! ][ 107 ][ 23 ][ 17 ]] +[[ long int->string ][ !!! *14* !!! ][ 109 ][ 22 ][ 17 ]] +[[ long long->string ][ !!! *14* !!! ][ 105 ][ 22 ][ 18 ]] +[[ unsigned int->string ][ !!! *14* !!! ][ 105 ][ 25 ][ 15 ]] +[[ unsigned short->string ][ !!! *15* !!! ][ 105 ][ 23 ][ 17 ]] +[[ unsigned long int->string ][ !!! *14* !!! ][ 109 ][ 24 ][ 17 ]] +[[ unsigned long long->string ][ !!! *14* !!! ][ 102 ][ 23 ][ 17 ]] +[[ bool->string ][ !!! *8* !!! ][ 104 ][ 23 ][ 12 ]] +[[ float->string ][ 66 ][ 181 ][ 92 ][ !!! *49* !!! ]] +[[ double->string ][ 107 ][ 215 ][ 120 ][ !!! *75* !!! ]] +[[ long double->string ][ 117 ][ 221 ][ 125 ][ !!! *79* !!! ]] +[[ char*->char ][ !!! *1* !!! ][ 89 ][ 9 ][ 7 ]] +[[ char*->signed char ][ !!! *1* !!! ][ 90 ][ 9 ][ 7 ]] +[[ char*->unsigned char ][ !!! *2* !!! ][ 90 ][ 9 ][ 13 ]] +[[ char*->int ][ !!! *7* !!! ][ 103 ][ 20 ][ 15 ]] +[[ char*->short ][ !!! *6* !!! ][ 102 ][ 29 ][ 14 ]] +[[ char*->long int ][ !!! *7* !!! ][ 101 ][ 20 ][ 15 ]] +[[ char*->long long ][ !!! *6* !!! ][ 102 ][ 20 ][ 14 ]] +[[ char*->unsigned int ][ !!! *6* !!! ][ 99 ][ 19 ][ 14 ]] +[[ char*->unsigned short ][ !!! *6* !!! ][ 101 ][ 18 ][ 14 ]] +[[ char*->unsigned long int ][ !!! *6* !!! ][ 102 ][ 22 ][ 14 ]] +[[ char*->unsigned long long ][ !!! *6* !!! ][ 101 ][ 21 ][ 14 ]] +[[ char*->bool ][ !!! *3* !!! ][ 98 ][ 18 ][ 7 ]] +[[ char*->float ][ !!! *18* !!! ][ 162 ][ 63 ][ 31 ]] +[[ char*->double ][ !!! *17* !!! ][ 203 ][ 96 ][ 58 ]] +[[ char*->long double ][ 135 ][ 214 ][ 98 ][ !!! *58* !!! ]] +[[ unsigned char*->char ][ !!! *2* !!! ][ 87 ][ 9 ][ 7 ]] +[[ unsigned char*->signed char ][ !!! *2* !!! ][ 87 ][ 9 ][ 7 ]] +[[ unsigned char*->unsigned char ][ !!! *3* !!! ][ 87 ][ 9 ][ 13 ]] +[[ unsigned char*->int ][ !!! *6* !!! ][ 105 ][ 20 ][ 14 ]] +[[ unsigned char*->short ][ !!! *6* !!! ][ 102 ][ 21 ][ 14 ]] +[[ unsigned char*->long int ][ !!! *6* !!! ][ 101 ][ 20 ][ 14 ]] +[[ unsigned char*->long long ][ !!! *6* !!! ][ 102 ][ 20 ][ 14 ]] +[[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 99 ][ 19 ][ 14 ]] +[[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 100 ][ 18 ][ 14 ]] +[[ unsigned char*->unsigned long int ][ !!! *6* !!! ][ 101 ][ 24 ][ 14 ]] +[[ unsigned char*->unsigned long long ][ !!! *6* !!! ][ 100 ][ 20 ][ 14 ]] +[[ unsigned char*->bool ][ !!! *3* !!! ][ 99 ][ 18 ][ 8 ]] +[[ unsigned char*->float ][ !!! *17* !!! ][ 164 ][ 64 ][ 32 ]] +[[ unsigned char*->double ][ !!! *18* !!! ][ 201 ][ 94 ][ 58 ]] +[[ unsigned char*->long double ][ 133 ][ 217 ][ 95 ][ !!! *60* !!! ]] +[[ unsigned char*->string ][ !!! *14* !!! ][ 103 ][ 23 ][ --- ]] +[[ signed char*->char ][ !!! *3* !!! ][ 88 ][ 10 ][ 8 ]] +[[ signed char*->signed char ][ !!! *2* !!! ][ 87 ][ 10 ][ 7 ]] +[[ signed char*->unsigned char ][ !!! *3* !!! ][ 87 ][ 9 ][ 13 ]] +[[ signed char*->int ][ !!! *6* !!! ][ 104 ][ 20 ][ 14 ]] +[[ signed char*->short ][ !!! *6* !!! ][ 105 ][ 21 ][ 14 ]] +[[ signed char*->long int ][ !!! *6* !!! ][ 104 ][ 20 ][ 15 ]] +[[ signed char*->long long ][ !!! *6* !!! ][ 106 ][ 20 ][ 14 ]] +[[ signed char*->unsigned int ][ !!! *6* !!! ][ 99 ][ 20 ][ 14 ]] +[[ signed char*->unsigned short ][ !!! *6* !!! ][ 100 ][ 18 ][ 14 ]] +[[ signed char*->unsigned long int ][ !!! *6* !!! ][ 102 ][ 23 ][ 14 ]] +[[ signed char*->unsigned long long ][ !!! *6* !!! ][ 103 ][ 20 ][ 14 ]] +[[ signed char*->bool ][ !!! *3* !!! ][ 99 ][ 18 ][ 7 ]] +[[ signed char*->float ][ !!! *18* !!! ][ 159 ][ 60 ][ 32 ]] +[[ signed char*->double ][ !!! *18* !!! ][ 203 ][ 95 ][ 57 ]] +[[ signed char*->long double ][ 129 ][ 213 ][ 97 ][ !!! *56* !!! ]] +[[ signed char*->string ][ !!! *14* !!! ][ 105 ][ 22 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 109 ][ 22 ][ --- ]] +[[ float->double ][ !!! *<1* !!! ][ 226 ][ 104 ][ --- ]] +[[ double->double ][ !!! *<1* !!! ][ 229 ][ 103 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 225 ][ 115 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 227 ][ 115 ][ --- ]] +[[ char->unsigned char ][ !!! *<1* !!! ][ 90 ][ 8 ][ --- ]] +[[ char->signed char ][ !!! *<1* !!! ][ 84 ][ 8 ][ --- ]] +[[ unsigned char->char ][ !!! *<1* !!! ][ 88 ][ 8 ][ --- ]] [[ signed char->char ][ !!! *<1* !!! ][ 89 ][ 8 ][ --- ]] ] [endsect] -[section intel-12-linux][table:id Performance Table (intel-12-linux) +[section gcc-4.6][table:id Performance Table (gcc-4.6) [[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]] -[[ string->char ][ !!! *1* !!! ][ 87 ][ 9 ][ 8 ]] -[[ string->signed char ][ !!! *<1* !!! ][ 90 ][ 9 ][ 8 ]] -[[ string->unsigned char ][ !!! *<1* !!! ][ 99 ][ 9 ][ 20 ]] -[[ string->int ][ !!! *8* !!! ][ 112 ][ 24 ][ 16 ]] -[[ string->short ][ !!! *8* !!! ][ 110 ][ 26 ][ 16 ]] -[[ string->long int ][ !!! *7* !!! ][ 110 ][ 23 ][ 16 ]] -[[ string->long long ][ !!! *10* !!! ][ 114 ][ 31 ][ 16 ]] -[[ string->unsigned int ][ !!! *7* !!! ][ 122 ][ 25 ][ 16 ]] -[[ string->unsigned short ][ !!! *7* !!! ][ 120 ][ 27 ][ 16 ]] -[[ string->unsigned long int ][ !!! *7* !!! ][ 114 ][ 25 ][ 16 ]] -[[ string->unsigned long long ][ !!! *7* !!! ][ 128 ][ 23 ][ 25 ]] -[[ string->bool ][ !!! *1* !!! ][ 103 ][ 20 ][ 9 ]] -[[ string->float ][ !!! *15* !!! ][ 166 ][ 73 ][ 31 ]] -[[ string->double ][ !!! *19* !!! ][ 206 ][ 103 ][ 56 ]] -[[ string->long double ][ 142 ][ 205 ][ 106 ][ !!! *61* !!! ]] -[[ char->string ][ !!! *10* !!! ][ 111 ][ 19 ][ 12 ]] -[[ unsigned char->string ][ !!! *12* !!! ][ 109 ][ 19 ][ 16 ]] -[[ signed char->string ][ !!! *9* !!! ][ 110 ][ 18 ][ 12 ]] -[[ int->string ][ 19 ][ 126 ][ 23 ][ !!! *17* !!! ]] -[[ short->string ][ 20 ][ 127 ][ 23 ][ !!! *18* !!! ]] -[[ long int->string ][ 20 ][ 128 ][ 24 ][ !!! *18* !!! ]] -[[ long long->string ][ !!! *16* !!! ][ 129 ][ 23 ][ 22 ]] -[[ unsigned int->string ][ 20 ][ 126 ][ 23 ][ !!! *17* !!! ]] -[[ unsigned short->string ][ 20 ][ 126 ][ 23 ][ !!! *17* !!! ]] -[[ unsigned long int->string ][ 20 ][ 126 ][ 23 ][ !!! *17* !!! ]] -[[ unsigned long long->string ][ !!! *24* !!! ][ 134 ][ 35 ][ 24 ]] -[[ bool->string ][ !!! *9* !!! ][ 124 ][ 29 ][ 12 ]] -[[ float->string ][ 147 ][ 218 ][ 104 ][ !!! *48* !!! ]] -[[ double->string ][ 202 ][ 245 ][ 128 ][ !!! *68* !!! ]] -[[ long double->string ][ 199 ][ 236 ][ 128 ][ !!! *69* !!! ]] -[[ char*->char ][ !!! *1* !!! ][ 91 ][ 10 ][ 9 ]] -[[ char*->signed char ][ !!! *1* !!! ][ 98 ][ 10 ][ 9 ]] -[[ char*->unsigned char ][ !!! *1* !!! ][ 97 ][ 14 ][ 15 ]] -[[ char*->int ][ !!! *8* !!! ][ 114 ][ 24 ][ 16 ]] -[[ char*->short ][ !!! *8* !!! ][ 112 ][ 27 ][ 15 ]] -[[ char*->long int ][ !!! *8* !!! ][ 117 ][ 28 ][ 16 ]] -[[ char*->long long ][ !!! *8* !!! ][ 123 ][ 30 ][ 16 ]] -[[ char*->unsigned int ][ !!! *8* !!! ][ 120 ][ 26 ][ 16 ]] -[[ char*->unsigned short ][ !!! *8* !!! ][ 122 ][ 30 ][ 16 ]] -[[ char*->unsigned long int ][ !!! *10* !!! ][ 119 ][ 25 ][ 16 ]] -[[ char*->unsigned long long ][ !!! *8* !!! ][ 140 ][ 54 ][ 34 ]] -[[ char*->bool ][ !!! *1* !!! ][ 108 ][ 21 ][ 8 ]] -[[ char*->float ][ !!! *16* !!! ][ 177 ][ 76 ][ 33 ]] -[[ char*->double ][ !!! *18* !!! ][ 271 ][ 104 ][ 56 ]] -[[ char*->long double ][ 142 ][ 207 ][ 106 ][ !!! *61* !!! ]] -[[ unsigned char*->char ][ !!! *1* !!! ][ 91 ][ 10 ][ 9 ]] -[[ unsigned char*->signed char ][ !!! *1* !!! ][ 92 ][ 10 ][ 8 ]] -[[ unsigned char*->unsigned char ][ !!! *1* !!! ][ 92 ][ 10 ][ 15 ]] -[[ unsigned char*->int ][ !!! *8* !!! ][ 111 ][ 24 ][ 16 ]] -[[ unsigned char*->short ][ !!! *9* !!! ][ 113 ][ 27 ][ 16 ]] -[[ unsigned char*->long int ][ !!! *7* !!! ][ 113 ][ 28 ][ 16 ]] -[[ unsigned char*->long long ][ !!! *7* !!! ][ 120 ][ 29 ][ 15 ]] -[[ unsigned char*->unsigned int ][ !!! *7* !!! ][ 119 ][ 24 ][ 15 ]] -[[ unsigned char*->unsigned short ][ !!! *8* !!! ][ 116 ][ 28 ][ 15 ]] -[[ unsigned char*->unsigned long int ][ !!! *7* !!! ][ 118 ][ 25 ][ 16 ]] -[[ unsigned char*->unsigned long long ][ !!! *7* !!! ][ 116 ][ 25 ][ 16 ]] -[[ unsigned char*->bool ][ !!! *1* !!! ][ 102 ][ 20 ][ 9 ]] -[[ unsigned char*->float ][ !!! *16* !!! ][ 167 ][ 74 ][ 31 ]] -[[ unsigned char*->double ][ !!! *19* !!! ][ 231 ][ 109 ][ 55 ]] -[[ unsigned char*->long double ][ 141 ][ 214 ][ 109 ][ !!! *61* !!! ]] -[[ unsigned char*->string ][ !!! *12* !!! ][ 122 ][ 23 ][ --- ]] -[[ signed char*->char ][ !!! *1* !!! ][ 91 ][ 10 ][ 8 ]] -[[ signed char*->signed char ][ !!! *1* !!! ][ 92 ][ 10 ][ 9 ]] -[[ signed char*->unsigned char ][ !!! *1* !!! ][ 92 ][ 10 ][ 15 ]] -[[ signed char*->int ][ !!! *7* !!! ][ 117 ][ 34 ][ 16 ]] -[[ signed char*->short ][ !!! *8* !!! ][ 117 ][ 25 ][ 15 ]] -[[ signed char*->long int ][ !!! *7* !!! ][ 115 ][ 28 ][ 16 ]] -[[ signed char*->long long ][ !!! *8* !!! ][ 116 ][ 31 ][ 15 ]] -[[ signed char*->unsigned int ][ !!! *8* !!! ][ 123 ][ 27 ][ 16 ]] -[[ signed char*->unsigned short ][ !!! *8* !!! ][ 120 ][ 27 ][ 16 ]] -[[ signed char*->unsigned long int ][ !!! *7* !!! ][ 119 ][ 26 ][ 16 ]] -[[ signed char*->unsigned long long ][ !!! *7* !!! ][ 118 ][ 26 ][ 17 ]] -[[ signed char*->bool ][ !!! *1* !!! ][ 108 ][ 26 ][ 9 ]] -[[ signed char*->float ][ !!! *16* !!! ][ 170 ][ 73 ][ 31 ]] -[[ signed char*->double ][ !!! *18* !!! ][ 210 ][ 112 ][ 55 ]] -[[ signed char*->long double ][ 137 ][ 210 ][ 107 ][ !!! *61* !!! ]] -[[ signed char*->string ][ !!! *14* !!! ][ 121 ][ 23 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 115 ][ 26 ][ --- ]] -[[ float->double ][ !!! *<1* !!! ][ 266 ][ 155 ][ --- ]] -[[ double->double ][ !!! *<1* !!! ][ 267 ][ 157 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 261 ][ 153 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 264 ][ 152 ][ --- ]] -[[ char->unsigned char ][ !!! *<1* !!! ][ 96 ][ 9 ][ --- ]] -[[ char->signed char ][ !!! *<1* !!! ][ 96 ][ 9 ][ --- ]] -[[ unsigned char->char ][ !!! *<1* !!! ][ 93 ][ 9 ][ --- ]] -[[ signed char->char ][ !!! *<1* !!! ][ 87 ][ 9 ][ --- ]] +[[ string->char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 7 ]] +[[ string->signed char ][ !!! *<1* !!! ][ 96 ][ 9 ][ 7 ]] +[[ string->unsigned char ][ !!! *<1* !!! ][ 96 ][ 8 ][ 13 ]] +[[ string->int ][ !!! *3* !!! ][ 110 ][ 18 ][ 16 ]] +[[ string->short ][ !!! *3* !!! ][ 111 ][ 18 ][ 16 ]] +[[ string->long int ][ !!! *3* !!! ][ 109 ][ 18 ][ 15 ]] +[[ string->long long ][ !!! *3* !!! ][ 111 ][ 18 ][ 15 ]] +[[ string->unsigned int ][ !!! *3* !!! ][ 110 ][ 20 ][ 15 ]] +[[ string->unsigned short ][ !!! *3* !!! ][ 111 ][ 18 ][ 15 ]] +[[ string->unsigned long int ][ !!! *3* !!! ][ 109 ][ 18 ][ 15 ]] +[[ string->unsigned long long ][ !!! *3* !!! ][ 114 ][ 19 ][ 15 ]] +[[ string->bool ][ !!! *<1* !!! ][ 106 ][ 17 ][ 8 ]] +[[ string->float ][ !!! *13* !!! ][ 175 ][ 70 ][ 33 ]] +[[ string->double ][ !!! *14* !!! ][ 182 ][ 81 ][ 58 ]] +[[ string->long double ][ 118 ][ 190 ][ 87 ][ !!! *58* !!! ]] +[[ char->string ][ !!! *8* !!! ][ 118 ][ 21 ][ 12 ]] +[[ unsigned char->string ][ !!! *8* !!! ][ 109 ][ 18 ][ 16 ]] +[[ signed char->string ][ !!! *8* !!! ][ 108 ][ 18 ][ 12 ]] +[[ int->string ][ 20 ][ 121 ][ 21 ][ !!! *16* !!! ]] +[[ short->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 17 ]] +[[ long int->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 16 ]] +[[ long long->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 17 ]] +[[ unsigned int->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 16 ]] +[[ unsigned short->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 18 ]] +[[ unsigned long int->string ][ 16 ][ 118 ][ 22 ][ !!! *15* !!! ]] +[[ unsigned long long->string ][ !!! *15* !!! ][ 117 ][ 21 ][ 17 ]] +[[ bool->string ][ !!! *8* !!! ][ 117 ][ 23 ][ 10 ]] +[[ float->string ][ 77 ][ 218 ][ 105 ][ !!! *50* !!! ]] +[[ double->string ][ 108 ][ 247 ][ 129 ][ !!! *73* !!! ]] +[[ long double->string ][ 120 ][ 250 ][ 131 ][ !!! *79* !!! ]] +[[ char*->char ][ !!! *2* !!! ][ 99 ][ 9 ][ 7 ]] +[[ char*->signed char ][ !!! *2* !!! ][ 98 ][ 9 ][ 8 ]] +[[ char*->unsigned char ][ !!! *2* !!! ][ 98 ][ 9 ][ 13 ]] +[[ char*->int ][ !!! *6* !!! ][ 115 ][ 22 ][ 15 ]] +[[ char*->short ][ !!! *6* !!! ][ 114 ][ 22 ][ 15 ]] +[[ char*->long int ][ !!! *6* !!! ][ 114 ][ 22 ][ 16 ]] +[[ char*->long long ][ !!! *6* !!! ][ 119 ][ 22 ][ 15 ]] +[[ char*->unsigned int ][ !!! *6* !!! ][ 114 ][ 20 ][ 15 ]] +[[ char*->unsigned short ][ !!! *6* !!! ][ 116 ][ 20 ][ 15 ]] +[[ char*->unsigned long int ][ !!! *6* !!! ][ 117 ][ 22 ][ 15 ]] +[[ char*->unsigned long long ][ !!! *6* !!! ][ 118 ][ 22 ][ 15 ]] +[[ char*->bool ][ !!! *3* !!! ][ 113 ][ 18 ][ 8 ]] +[[ char*->float ][ !!! *15* !!! ][ 180 ][ 78 ][ 32 ]] +[[ char*->double ][ !!! *16* !!! ][ 185 ][ 89 ][ 58 ]] +[[ char*->long double ][ 119 ][ 193 ][ 91 ][ !!! *60* !!! ]] +[[ unsigned char*->char ][ !!! *2* !!! ][ 99 ][ 9 ][ 8 ]] +[[ unsigned char*->signed char ][ !!! *2* !!! ][ 99 ][ 10 ][ 8 ]] +[[ unsigned char*->unsigned char ][ !!! *2* !!! ][ 100 ][ 9 ][ 15 ]] +[[ unsigned char*->int ][ !!! *6* !!! ][ 118 ][ 22 ][ 15 ]] +[[ unsigned char*->short ][ !!! *6* !!! ][ 117 ][ 26 ][ 15 ]] +[[ unsigned char*->long int ][ !!! *6* !!! ][ 119 ][ 21 ][ 15 ]] +[[ unsigned char*->long long ][ !!! *6* !!! ][ 118 ][ 21 ][ 14 ]] +[[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 115 ][ 22 ][ 14 ]] +[[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 117 ][ 20 ][ 15 ]] +[[ unsigned char*->unsigned long int ][ !!! *6* !!! ][ 115 ][ 21 ][ 15 ]] +[[ unsigned char*->unsigned long long ][ !!! *6* !!! ][ 117 ][ 22 ][ 15 ]] +[[ unsigned char*->bool ][ !!! *3* !!! ][ 112 ][ 18 ][ 8 ]] +[[ unsigned char*->float ][ !!! *15* !!! ][ 181 ][ 78 ][ 33 ]] +[[ unsigned char*->double ][ !!! *16* !!! ][ 185 ][ 92 ][ 59 ]] +[[ unsigned char*->long double ][ 120 ][ 190 ][ 89 ][ !!! *58* !!! ]] +[[ unsigned char*->string ][ !!! *14* !!! ][ 121 ][ 22 ][ --- ]] +[[ signed char*->char ][ !!! *2* !!! ][ 99 ][ 9 ][ 9 ]] +[[ signed char*->signed char ][ !!! *2* !!! ][ 98 ][ 9 ][ 8 ]] +[[ signed char*->unsigned char ][ !!! *2* !!! ][ 98 ][ 9 ][ 14 ]] +[[ signed char*->int ][ !!! *6* !!! ][ 119 ][ 22 ][ 16 ]] +[[ signed char*->short ][ !!! *6* !!! ][ 115 ][ 22 ][ 15 ]] +[[ signed char*->long int ][ !!! *6* !!! ][ 119 ][ 22 ][ 15 ]] +[[ signed char*->long long ][ !!! *6* !!! ][ 117 ][ 22 ][ 15 ]] +[[ signed char*->unsigned int ][ !!! *6* !!! ][ 117 ][ 23 ][ 15 ]] +[[ signed char*->unsigned short ][ !!! *6* !!! ][ 117 ][ 21 ][ 14 ]] +[[ signed char*->unsigned long int ][ !!! *7* !!! ][ 119 ][ 24 ][ 15 ]] +[[ signed char*->unsigned long long ][ !!! *6* !!! ][ 116 ][ 22 ][ 15 ]] +[[ signed char*->bool ][ !!! *3* !!! ][ 111 ][ 18 ][ 8 ]] +[[ signed char*->float ][ !!! *16* !!! ][ 180 ][ 78 ][ 33 ]] +[[ signed char*->double ][ !!! *16* !!! ][ 185 ][ 89 ][ 59 ]] +[[ signed char*->long double ][ 120 ][ 191 ][ 91 ][ !!! *59* !!! ]] +[[ signed char*->string ][ !!! *14* !!! ][ 122 ][ 23 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 120 ][ 22 ][ --- ]] +[[ float->double ][ !!! *<1* !!! ][ 242 ][ 115 ][ --- ]] +[[ double->double ][ !!! *<1* !!! ][ 243 ][ 115 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 265 ][ 141 ][ --- ]] +[[ int->int ][ !!! *<1* !!! ][ 266 ][ 140 ][ --- ]] +[[ char->unsigned char ][ !!! *<1* !!! ][ 95 ][ 8 ][ --- ]] +[[ char->signed char ][ !!! *<1* !!! ][ 95 ][ 8 ][ --- ]] +[[ unsigned char->char ][ !!! *<1* !!! ][ 94 ][ 8 ][ --- ]] +[[ signed char->char ][ !!! *<1* !!! ][ 94 ][ 8 ][ --- ]] ] [endsect] - - [/ END of section, generated by performance measuring program ] [endsect] diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index e536ac5..94f8c70 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -461,7 +461,7 @@ namespace boost namespace detail // lcast_put_unsigned { template - CharT* lcast_put_unsigned(T n, CharT* finish) + CharT* lcast_put_unsigned(const T n_param, CharT* finish) { #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS BOOST_STATIC_ASSERT(!std::numeric_limits::is_signed); @@ -470,51 +470,58 @@ namespace boost typedef typename Traits::int_type int_type; CharT const czero = lcast_char_constants::zero; int_type const zero = Traits::to_int_type(czero); + BOOST_DEDUCED_TYPENAME boost::mpl::if_c< + (sizeof(int_type) > sizeof(T)) + , int_type + , T + >::type n = n_param; #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE std::locale loc; - typedef std::numpunct numpunct; - numpunct const& np = BOOST_USE_FACET(numpunct, loc); - std::string const& grouping = np.grouping(); - std::string::size_type const grouping_size = grouping.size(); + if (loc != std::locale::classic()) { + typedef std::numpunct numpunct; + numpunct const& np = BOOST_USE_FACET(numpunct, loc); + std::string const grouping = np.grouping(); + std::string::size_type const grouping_size = grouping.size(); - if ( grouping_size && grouping[0] > 0 ) - { + if ( grouping_size && grouping[0] > 0 ) + { #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - // Check that ulimited group is unreachable: - BOOST_STATIC_ASSERT(std::numeric_limits::digits10 < CHAR_MAX); + // Check that ulimited group is unreachable: + BOOST_STATIC_ASSERT(std::numeric_limits::digits10 < CHAR_MAX); #endif - CharT thousands_sep = np.thousands_sep(); - std::string::size_type group = 0; // current group number - char last_grp_size = grouping[0]; - char left = last_grp_size; + CharT thousands_sep = np.thousands_sep(); + std::string::size_type group = 0; // current group number + char last_grp_size = grouping[0]; + char left = last_grp_size; - do - { - if(left == 0) + do { - ++group; - if(group < grouping_size) + if(left == 0) { - char const grp_size = grouping[group]; - last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size; + ++group; + if(group < grouping_size) + { + char const grp_size = grouping[group]; + last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size; + } + + left = last_grp_size; + --finish; + Traits::assign(*finish, thousands_sep); } - left = last_grp_size; + --left; + --finish; - Traits::assign(*finish, thousands_sep); - } - - --left; - - --finish; - int_type const digit = static_cast(n % 10U); - Traits::assign(*finish, Traits::to_char_type(zero + digit)); - n /= 10; - } while(n); - - } else + int_type const digit = static_cast(n % 10U); + Traits::assign(*finish, Traits::to_char_type(zero + digit)); + n /= 10; + } while(n); + return finish; + } + } #endif { do @@ -551,61 +558,63 @@ namespace boost #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE std::locale loc; - typedef std::numpunct numpunct; - numpunct const& np = BOOST_USE_FACET(numpunct, loc); - std::string const& grouping = np.grouping(); - std::string::size_type const grouping_size = grouping.size(); + if (loc != std::locale::classic()) { + typedef std::numpunct numpunct; + numpunct const& np = BOOST_USE_FACET(numpunct, loc); + std::string const& grouping = np.grouping(); + std::string::size_type const grouping_size = grouping.size(); - /* According to Programming languages - C++ - * we MUST check for correct grouping - */ - if (grouping_size && grouping[0] > 0) - { - unsigned char current_grouping = 0; - CharT const thousands_sep = np.thousands_sep(); - char remained = grouping[current_grouping] - 1; - bool shall_we_return = true; - - for(;end>=begin; --end) + /* According to Programming languages - C++ + * we MUST check for correct grouping + */ + if (grouping_size && grouping[0] > 0) { - if (remained) { - T const new_sub_value = multiplier * 10 * (*end - czero); + unsigned char current_grouping = 0; + CharT const thousands_sep = np.thousands_sep(); + char remained = grouping[current_grouping] - 1; + bool shall_we_return = true; - if (*end < czero || *end >= czero + 10 - /* detecting overflow */ - || new_sub_value/10 != multiplier * (*end - czero) - || static_cast((std::numeric_limits::max)()-new_sub_value) < value - ) - return false; + for(;end>=begin; --end) + { + if (remained) { + T const new_sub_value = multiplier * 10 * (*end - czero); - value += new_sub_value; - multiplier *= 10; - --remained; - } else { - if ( !Traits::eq(*end, thousands_sep) ) //|| begin == end ) return false; - { - /* - * According to Programming languages - C++ - * Digit grouping is checked. That is, the positions of discarded - * separators is examined for consistency with - * use_facet >(loc ).grouping() - * - * BUT what if there is no separators at all and grouping() - * is not empty? Well, we have no extraced separators, so we - * won`t check them for consistency. This will allow us to - * work with "C" locale from other locales - */ - shall_we_return = false; - break; + if (*end < czero || *end >= czero + 10 + /* detecting overflow */ + || new_sub_value/10 != multiplier * (*end - czero) + || static_cast((std::numeric_limits::max)()-new_sub_value) < value + ) + return false; + + value += new_sub_value; + multiplier *= 10; + --remained; } else { - if ( begin == end ) return false; - if (current_grouping < grouping_size-1 ) ++current_grouping; - remained = grouping[current_grouping]; + if ( !Traits::eq(*end, thousands_sep) ) //|| begin == end ) return false; + { + /* + * According to Programming languages - C++ + * Digit grouping is checked. That is, the positions of discarded + * separators is examined for consistency with + * use_facet >(loc ).grouping() + * + * BUT what if there is no separators at all and grouping() + * is not empty? Well, we have no extraced separators, so we + * won`t check them for consistency. This will allow us to + * work with "C" locale from other locales + */ + shall_we_return = false; + break; + } else { + if ( begin == end ) return false; + if (current_grouping < grouping_size-1 ) ++current_grouping; + remained = grouping[current_grouping]; + } } } - } - if (shall_we_return) return true; + if (shall_we_return) return true; + } } #endif { @@ -809,7 +818,11 @@ namespace boost std::locale loc; typedef std::numpunct numpunct; numpunct const& np = BOOST_USE_FACET(numpunct, loc); - std::string const& grouping = np.grouping(); + std::string const grouping( + (loc == std::locale::classic()) + ? std::string() + : np.grouping() + ); std::string::size_type const grouping_size = grouping.size(); CharT const thousands_sep = grouping_size ? np.thousands_sep() : 0; CharT const decimal_point = np.decimal_point(); diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 47381cd..6820612 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -756,6 +756,16 @@ void test_conversion_from_to_integral() test_conversion_from_integral_to_char(wzero); test_conversion_from_char_to_integral(wzero); #endif +#ifndef BOOST_NO_CHAR16_T + char16_t const u16zero = u'0'; + test_conversion_from_integral_to_char(u16zero); + test_conversion_from_char_to_integral(u16zero); +#endif +#ifndef BOOST_NO_CHAR32_T + char32_t const u32zero = u'0'; + test_conversion_from_integral_to_char(u32zero); + test_conversion_from_char_to_integral(u32zero); +#endif BOOST_CHECK(lexical_cast("-1") == static_cast(-1)); BOOST_CHECK(lexical_cast("-9") == static_cast(-9)); From 3d60698843865475f2ae8b2cd7a025b0bdd624dd Mon Sep 17 00:00:00 2001 From: Gennadiy Rozental Date: Wed, 5 Oct 2011 09:15:12 +0000 Subject: [PATCH 118/242] eliminated unit_test_framework [SVN r74720] --- test/lexical_cast_abstract_test.cpp | 2 +- test/lexical_cast_float_types_test.cpp | 2 +- test/lexical_cast_inf_nan_test.cpp | 2 +- test/lexical_cast_loopback_test.cpp | 2 +- test/lexical_cast_noncopyable_test.cpp | 2 +- test/lexical_cast_vc8_bug_test.cpp | 2 +- test/lexical_cast_wchars_test.cpp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/lexical_cast_abstract_test.cpp b/test/lexical_cast_abstract_test.cpp index 4b92e49..70cdeca 100644 --- a/test/lexical_cast_abstract_test.cpp +++ b/test/lexical_cast_abstract_test.cpp @@ -28,7 +28,7 @@ void test_abstract(); unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast unit test"); suite->add(BOOST_TEST_CASE(&test_abstract)); diff --git a/test/lexical_cast_float_types_test.cpp b/test/lexical_cast_float_types_test.cpp index 72279bb..808f456 100755 --- a/test/lexical_cast_float_types_test.cpp +++ b/test/lexical_cast_float_types_test.cpp @@ -31,7 +31,7 @@ using namespace boost; unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast float types unit test"); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_float)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_double)); diff --git a/test/lexical_cast_inf_nan_test.cpp b/test/lexical_cast_inf_nan_test.cpp index 4617d5e..bb4331a 100755 --- a/test/lexical_cast_inf_nan_test.cpp +++ b/test/lexical_cast_inf_nan_test.cpp @@ -170,7 +170,7 @@ void test_inf_nan_long_double() unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast inf anf nan parsing unit test"); suite->add(BOOST_TEST_CASE(&test_inf_nan_float)); suite->add(BOOST_TEST_CASE(&test_inf_nan_double)); diff --git a/test/lexical_cast_loopback_test.cpp b/test/lexical_cast_loopback_test.cpp index 5787996..25b18ec 100644 --- a/test/lexical_cast_loopback_test.cpp +++ b/test/lexical_cast_loopback_test.cpp @@ -30,7 +30,7 @@ void test_round_conversion_long_double(); unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast unit test"); suite->add(BOOST_TEST_CASE(&test_round_conversion_float)); suite->add(BOOST_TEST_CASE(&test_round_conversion_double)); diff --git a/test/lexical_cast_noncopyable_test.cpp b/test/lexical_cast_noncopyable_test.cpp index 6284b14..1f120d9 100644 --- a/test/lexical_cast_noncopyable_test.cpp +++ b/test/lexical_cast_noncopyable_test.cpp @@ -28,7 +28,7 @@ void test_noncopyable(); unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast unit test"); suite->add(BOOST_TEST_CASE(&test_noncopyable)); diff --git a/test/lexical_cast_vc8_bug_test.cpp b/test/lexical_cast_vc8_bug_test.cpp index 151e4f8..9e5ef0b 100644 --- a/test/lexical_cast_vc8_bug_test.cpp +++ b/test/lexical_cast_vc8_bug_test.cpp @@ -60,7 +60,7 @@ void test_vc8_bug() unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast vc8 bug unit test"); suite->add(BOOST_TEST_CASE(test_vc8_bug)); return suite; diff --git a/test/lexical_cast_wchars_test.cpp b/test/lexical_cast_wchars_test.cpp index 14ac461..acd78b1 100755 --- a/test/lexical_cast_wchars_test.cpp +++ b/test/lexical_cast_wchars_test.cpp @@ -48,7 +48,7 @@ void test_char_types_conversions() unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast char<->wchar_t unit test"); suite->add(BOOST_TEST_CASE(&test_char_types_conversions)); From 8c7c7b9237aeab13f0ea50e7c12ae01ab5c6476f Mon Sep 17 00:00:00 2001 From: Gennadiy Rozental Date: Wed, 5 Oct 2011 09:42:21 +0000 Subject: [PATCH 119/242] eliminated unit_test_framework and BOOST_MESSAGE [SVN r74727] --- lexical_cast_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 6820612..faeaa93 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -110,7 +110,7 @@ void test_char32_conversions(); unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast unit test"); suite->add(BOOST_TEST_CASE(test_conversion_to_char)); suite->add(BOOST_TEST_CASE(test_conversion_to_int)); From c07cbcee5cf8ef5ea43706663ee07f89716023ee Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 13 Oct 2011 18:36:39 +0000 Subject: [PATCH 120/242] Performance optimizations and testsfor conversions to/from boost::container::basic_string [SVN r74940] --- include/boost/lexical_cast.hpp | 63 +++++++++++++++++++++++++++ test/Jamfile.v2 | 1 + test/lexical_cast_containers_test.cpp | 38 ++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 test/lexical_cast_containers_test.cpp diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 94f8c70..62f0f66 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -46,6 +46,7 @@ #include #include #include +#include #include @@ -145,6 +146,12 @@ namespace boost { typedef CharT type; }; + + template + struct stream_char< ::boost::container::basic_string > + { + typedef CharT type; + }; #endif #ifndef BOOST_LCAST_NO_WCHAR_T @@ -259,6 +266,24 @@ namespace boost typedef Traits type; }; + template + struct deduce_char_traits< CharT + , ::boost::container::basic_string + , Source + > + { + typedef Traits type; + }; + + template + struct deduce_char_traits< CharT + , Target + , ::boost::container::basic_string + > + { + typedef Traits type; + }; + template struct deduce_char_traits< CharT , std::basic_string @@ -267,6 +292,15 @@ namespace boost { typedef Traits type; }; + + template + struct deduce_char_traits< CharT + , ::boost::container::basic_string + , ::boost::container::basic_string + > + { + typedef Traits type; + }; #endif } @@ -1257,6 +1291,14 @@ namespace boost return true; } + template + bool operator<<(::boost::container::basic_string const& str) + { + start = const_cast(str.data()); + finish = start + str.length(); + return true; + } + bool operator<<(bool value) { CharT const czero = lcast_char_constants::zero; @@ -1462,6 +1504,9 @@ namespace boost #else template bool operator>>(std::basic_string& str) { str.assign(start, finish); return true; } + + template + bool operator>>(::boost::container::basic_string& str) { str.assign(start, finish); return true; } #endif /* * case "-0" || "0" || "+0" : output = false; return true; @@ -1598,6 +1643,12 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = true ); }; + template + struct is_stdstring< ::boost::container::basic_string > + { + BOOST_STATIC_CONSTANT(bool, value = true ); + }; + template struct is_char_or_wchar { @@ -1698,6 +1749,18 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = true ); }; + template + struct is_char_array_to_stdstring< ::boost::container::basic_string, CharT* > + { + BOOST_STATIC_CONSTANT(bool, value = true ); + }; + + template + struct is_char_array_to_stdstring< ::boost::container::basic_string, const CharT* > + { + BOOST_STATIC_CONSTANT(bool, value = true ); + }; + #if (defined _MSC_VER) # pragma warning( push ) # pragma warning( disable : 4701 ) // possible use of ... before initialization diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 2dd3500..7e5eacf 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -28,6 +28,7 @@ test-suite conversion [ run lexical_cast_wchars_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_float_types_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_inf_nan_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run lexical_cast_containers_test.cpp ../../test/build//boost_unit_test_framework/static ] ; diff --git a/test/lexical_cast_containers_test.cpp b/test/lexical_cast_containers_test.cpp new file mode 100644 index 0000000..5f98ac8 --- /dev/null +++ b/test/lexical_cast_containers_test.cpp @@ -0,0 +1,38 @@ +// Testing boost::lexical_cast with boost::container::string. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Antony Polukhin, 2011. +// +// 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_containers_basic_string(); + +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::container::string"); + suite->add(BOOST_TEST_CASE(testing_boost_containers_basic_string)); + + return suite; +} + +void testing_boost_containers_basic_string() +{ + BOOST_CHECK("100" == lexical_cast("100")); + BOOST_CHECK(L"100" == lexical_cast(L"100")); + + BOOST_CHECK("100" == lexical_cast(100)); + boost::container::string str("1000"); + BOOST_CHECK(1000 == lexical_cast(str)); +} + + From 4ddb0bfb9564c43e61f1ba764db137794ad4f157 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 3 Nov 2011 04:33:58 +0000 Subject: [PATCH 121/242] Fix for error noticed by Olaf van der Spek (ticket #6083) Added test case for that error [SVN r75283] --- include/boost/lexical_cast.hpp | 2 +- test/Jamfile.v2 | 1 + test/lexical_cast_empty_input_test.cpp | 58 ++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100755 test/lexical_cast_empty_input_test.cpp diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 62f0f66..3d65297 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1181,7 +1181,7 @@ namespace boost bool const result = !(stream << input).fail(); start = stringbuffer.pbase(); finish = stringbuffer.pptr(); - return result; + return result && (start != finish); } template diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7e5eacf..6eebe72 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -29,6 +29,7 @@ test-suite conversion [ run lexical_cast_float_types_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_inf_nan_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_containers_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run lexical_cast_empty_input_test.cpp ../../test/build//boost_unit_test_framework/static ] ; diff --git a/test/lexical_cast_empty_input_test.cpp b/test/lexical_cast_empty_input_test.cpp new file mode 100755 index 0000000..42e7cec --- /dev/null +++ b/test/lexical_cast_empty_input_test.cpp @@ -0,0 +1,58 @@ +// Unit test for boost::lexical_cast. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Antony Polukhin, 2011. +// +// 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 + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include +#include +#include + +using namespace boost; + +void test_empty_iterator_range() +{ + boost::iterator_range v; + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); +} + +void test_empty_string() +{ + BOOST_CHECK_THROW(lexical_cast(std::string()), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(std::string()), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(std::string()), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(std::string()), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(std::string()), bad_lexical_cast); + BOOST_CHECK_EQUAL(lexical_cast(std::string()), std::string()); + BOOST_CHECK_THROW(lexical_cast(std::string()), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(std::string()), bad_lexical_cast); +} + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast. Empty input unit test"); + suite->add(BOOST_TEST_CASE(&test_empty_iterator_range)); + suite->add(BOOST_TEST_CASE(&test_empty_string)); + + return suite; +} From 7dd63d08d64a3343830eef49e878c4f8fec6e594 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 5 Dec 2011 16:17:09 +0000 Subject: [PATCH 122/242] Fixes #6159 (compilation on platforms without cwchar) [SVN r75812] --- include/boost/lexical_cast.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 3d65297..4cfa298 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -17,7 +17,7 @@ // enhanced with contributions from Terje Slettebo, // with additional fixes and suggestions from Gennaro Prota, // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin and other Boosters +// Alexander Nasonov, Antony Polukhin, Justin Viiret and other Boosters // when: November 2000, March 2003, June 2005, June 2006, March 2011 #include @@ -47,8 +47,9 @@ #include #include #include -#include - +#ifndef BOOST_NO_CWCHAR +# include +#endif #ifndef BOOST_NO_STD_LOCALE # include From 2312691bdebad981cbe8461f3f93c3b23bc2406a Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 5 Dec 2011 16:29:45 +0000 Subject: [PATCH 123/242] Fixes #6127 (wchar_t usage outside of #ifndef BOOST_LCAST_NO_WCHAR_T ) [SVN r75813] --- include/boost/lexical_cast.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 4cfa298..e7ab248 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -17,7 +17,8 @@ // enhanced with contributions from Terje Slettebo, // with additional fixes and suggestions from Gennaro Prota, // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin, Justin Viiret and other Boosters +// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann +// and other Boosters // when: November 2000, March 2003, June 2005, June 2006, March 2011 #include @@ -683,8 +684,8 @@ namespace boost , const CharT opening_brace, const CharT closing_brace) { using namespace std; - const wchar_t minus = lcast_char_constants::minus; - const wchar_t plus = lcast_char_constants::plus; + const CharT minus = lcast_char_constants::minus; + const CharT plus = lcast_char_constants::plus; const int inifinity_size = 8; bool has_minus = false; From a9697b88fd3b946d6e8a4a7f678d5b0f7533843d Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 8 Dec 2011 15:29:44 +0000 Subject: [PATCH 124/242] Fixes #6186 (lexical_cast compliation error fixed, when wchar_t is a typedef for unsigned short. Test added) [SVN r75864] --- include/boost/lexical_cast.hpp | 15 ++++++- test/Jamfile.v2 | 7 ++- test/lexical_cast_typedefed_wchar_test.cpp | 50 ++++++++++++++++++++++ 3 files changed, 69 insertions(+), 3 deletions(-) create mode 100755 test/lexical_cast_typedefed_wchar_test.cpp diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index e7ab248..480d87a 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1093,6 +1093,8 @@ namespace boost namespace detail // optimized stream wrapper { + struct type_used_as_workaround_for_typedefed_wchar_ts{}; + // String representation of Source has an upper limit. template< class CharT // a result of widest_char transformation , class Traits // usually char_traits @@ -1354,6 +1356,8 @@ namespace boost /************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/ private: + bool shr_unsigned(type_used_as_workaround_for_typedefed_wchar_ts /*var*/) {return true;} + template bool shr_unsigned(Type& output) { @@ -1480,8 +1484,15 @@ namespace boost } /************************************ OPERATORS >> ( ... ) ********************************/ - public: - bool operator>>(unsigned short& output) { return shr_unsigned(output); } + + typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< + ::boost::is_same::value + , type_used_as_workaround_for_typedefed_wchar_ts + , unsigned short + >::type ushort_ambiguity_workaround; + + public: + bool operator>>(ushort_ambiguity_workaround& output){ return shr_unsigned(output); } bool operator>>(unsigned int& output) { return shr_unsigned(output); } bool operator>>(unsigned long int& output) { return shr_unsigned(output); } bool operator>>(short& output) { return shr_signed(output); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 6eebe72..e7408f3 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -14,7 +14,12 @@ # bring in rules for testing import testing ; +import feature ; +feature.feature nowchar : on : + composite optional propagated link-incompatible ; +feature.compose on : /Zc:wchar_t- ; + test-suite conversion : [ run implicit_cast.cpp ] [ compile-fail implicit_cast_fail.cpp ] @@ -30,6 +35,6 @@ test-suite conversion [ run lexical_cast_inf_nan_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_containers_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_empty_input_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run lexical_cast_typedefed_wchar_test.cpp ../../test/build//boost_unit_test_framework/static : : : msvc:on : : ] ; - diff --git a/test/lexical_cast_typedefed_wchar_test.cpp b/test/lexical_cast_typedefed_wchar_test.cpp new file mode 100755 index 0000000..ae84678 --- /dev/null +++ b/test/lexical_cast_typedefed_wchar_test.cpp @@ -0,0 +1,50 @@ +// Unit test for boost::lexical_cast. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Antony Polukhin, 2011. +// +// 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 + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include +#include + +void test_typedefed_wchar_t(); + +using namespace boost; + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast unit test for typedefed wchar_t (mainly for MSVC)"); + suite->add(BOOST_TEST_CASE(&test_typedefed_wchar_t)); + + return suite; +} + + +void test_typedefed_wchar_t() +{ +#ifdef BOOST_MSVC + BOOST_CHECK((boost::is_same::value)); +#endif + + BOOST_CHECK_EQUAL(lexical_cast(L"1000"), 1000); +} + + + + + + + From f32fb4b5e538be898323e8ba4f6dde683cf699e1 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 12 Dec 2011 18:09:53 +0000 Subject: [PATCH 125/242] Fixes #6186 test failures [SVN r75921] --- test/Jamfile.v2 | 2 +- test/lexical_cast_typedefed_wchar_test.cpp | 33 +++------------------- 2 files changed, 5 insertions(+), 30 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e7408f3..96ce8f6 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -35,6 +35,6 @@ test-suite conversion [ run lexical_cast_inf_nan_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_containers_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_empty_input_test.cpp ../../test/build//boost_unit_test_framework/static ] - [ run lexical_cast_typedefed_wchar_test.cpp ../../test/build//boost_unit_test_framework/static : : : msvc:on : : ] + [ compile lexical_cast_typedefed_wchar_test.cpp : msvc:on ] ; diff --git a/test/lexical_cast_typedefed_wchar_test.cpp b/test/lexical_cast_typedefed_wchar_test.cpp index ae84678..752c3e5 100755 --- a/test/lexical_cast_typedefed_wchar_test.cpp +++ b/test/lexical_cast_typedefed_wchar_test.cpp @@ -10,41 +10,16 @@ #include -#if defined(__INTEL_COMPILER) -#pragma warning(disable: 193 383 488 981 1418 1419) -#elif defined(BOOST_MSVC) -#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) -#endif - +#include #include -#include -void test_typedefed_wchar_t(); - -using namespace boost; - -unit_test::test_suite *init_unit_test_suite(int, char *[]) -{ - unit_test::test_suite *suite = - BOOST_TEST_SUITE("lexical_cast unit test for typedefed wchar_t (mainly for MSVC)"); - suite->add(BOOST_TEST_CASE(&test_typedefed_wchar_t)); - - return suite; -} - - -void test_typedefed_wchar_t() +int main() { #ifdef BOOST_MSVC - BOOST_CHECK((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); #endif - BOOST_CHECK_EQUAL(lexical_cast(L"1000"), 1000); + return ::boost::lexical_cast(L"1000") == 1000; } - - - - - From 8627f8bb8ac5dcc83b1a51d50fcd3078c098caed Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 14 Dec 2011 16:36:34 +0000 Subject: [PATCH 126/242] Fixes #6186 (treat conversions to/from single wchar_t character as conversions to/from unsigned short. Test added, documentation updated) [SVN r75937] --- doc/lexical_cast.qbk | 12 +++++ include/boost/lexical_cast.hpp | 28 +++++------ test/Jamfile.v2 | 1 + ...ical_cast_typedefed_wchar_test_runtime.cpp | 48 +++++++++++++++++++ 4 files changed, 74 insertions(+), 15 deletions(-) create mode 100755 test/lexical_cast_typedefed_wchar_test_runtime.cpp diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index b540267..0532b56 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -159,9 +159,21 @@ Read a good C++ book, study `std::sentry` and [@boost:libs/io/doc/ios_state.html the rules of `scanf` for conversions. And in the C99 standard for unsigned input value minus sign is optional, so if a negative number is read, no errors will arise and the result will be the two's complement. +[pre +] + +* [*Question:] Why `boost::lexical_cast(L'A');` outputs 65 and `boost::lexical_cast(L"65");` does not throw? + * [*Answer:] If you are using an old version of Visual Studio or compile code with /Zc:wchar_t- flag, +`boost::lexical_cast` sees single `wchar_t` character as `unsigned short`. It is not a `boost::lexical_cast` mistake, but a +limitation of compiler options that you use. + [endsect] [section Changes] +* [*boost 1.49.0 :] + + * Added code to work with typedefed wchar_t (compilation flag /Zc:wchar_t- for Visual Studio). + * [*boost 1.48.0 :] * Added code to work with Inf and NaN on any platform. diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 480d87a..5fa6a96 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -17,8 +17,8 @@ // enhanced with contributions from Terje Slettebo, // with additional fixes and suggestions from Gennaro Prota, // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann -// and other Boosters +// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, +// Cheng Yang and other Boosters // when: November 2000, March 2003, June 2005, June 2006, March 2011 #include @@ -1093,8 +1093,6 @@ namespace boost namespace detail // optimized stream wrapper { - struct type_used_as_workaround_for_typedefed_wchar_ts{}; - // String representation of Source has an upper limit. template< class CharT // a result of widest_char transformation , class Traits // usually char_traits @@ -1356,7 +1354,6 @@ namespace boost /************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/ private: - bool shr_unsigned(type_used_as_workaround_for_typedefed_wchar_ts /*var*/) {return true;} template bool shr_unsigned(Type& output) @@ -1484,15 +1481,8 @@ namespace boost } /************************************ OPERATORS >> ( ... ) ********************************/ - - typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< - ::boost::is_same::value - , type_used_as_workaround_for_typedefed_wchar_ts - , unsigned short - >::type ushort_ambiguity_workaround; - public: - bool operator>>(ushort_ambiguity_workaround& output){ return shr_unsigned(output); } + bool operator>>(unsigned short& output) { return shr_unsigned(output); } bool operator>>(unsigned int& output) { return shr_unsigned(output); } bool operator>>(unsigned long int& output) { return shr_unsigned(output); } bool operator>>(short& output) { return shr_signed(output); } @@ -1504,11 +1494,19 @@ namespace boost #elif defined(BOOST_HAS_MS_INT64) bool operator>>(unsigned __int64& output) { return shr_unsigned(output); } bool operator>>(__int64& output) { return shr_signed(output); } - #endif - bool operator>>(CharT& output) { return shr_xchar(output); } + bool operator>>(char& output) { return shr_xchar(output); } bool operator>>(unsigned char& output) { return shr_xchar(output); } bool operator>>(signed char& output) { return shr_xchar(output); } +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) + bool operator>>(wchar_t& output) { return shr_xchar(output); } +#endif +#ifndef BOOST_NO_CHAR16_T + bool operator>>(char16_t& output) { return shr_xchar(output); } +#endif +#ifndef BOOST_NO_CHAR32_T + bool operator>>(char32_t& output) { return shr_xchar(output); } +#endif #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION bool operator>>(std::string& str) { str.assign(start, finish); return true; } # ifndef BOOST_LCAST_NO_WCHAR_T diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 96ce8f6..8718301 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -36,5 +36,6 @@ test-suite conversion [ run lexical_cast_containers_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_empty_input_test.cpp ../../test/build//boost_unit_test_framework/static ] [ compile lexical_cast_typedefed_wchar_test.cpp : msvc:on ] + [ run lexical_cast_typedefed_wchar_test_runtime.cpp ../../test/build//boost_unit_test_framework/static : : : msvc:on ] ; diff --git a/test/lexical_cast_typedefed_wchar_test_runtime.cpp b/test/lexical_cast_typedefed_wchar_test_runtime.cpp new file mode 100755 index 0000000..d01700a --- /dev/null +++ b/test/lexical_cast_typedefed_wchar_test_runtime.cpp @@ -0,0 +1,48 @@ +// Unit test for boost::lexical_cast. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Antony Polukhin, 2011. +// +// 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 + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include + +#include +using namespace boost; + +void test_typedefed_wchar_t_runtime() +{ +#ifndef BOOST_LCAST_NO_WCHAR_T +#ifdef BOOST_MSVC + BOOST_STATIC_ASSERT((boost::is_same::value)); + + + BOOST_CHECK_EQUAL(boost::lexical_cast(L'A'), 65); + BOOST_CHECK_EQUAL(boost::lexical_cast(L'B'), 66); + + BOOST_CHECK_EQUAL(boost::lexical_cast(L"65"), 65); + BOOST_CHECK_EQUAL(boost::lexical_cast(L"66"), 66); +#endif +#endif + BOOST_CHECK(1); +} + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast typedefed wchar_t runtime test"); + suite->add(BOOST_TEST_CASE(&test_typedefed_wchar_t_runtime)); + + return suite; +} From 5d288580ee1c9a30ea2a56995438196ddd92a332 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 21 Dec 2011 17:03:52 +0000 Subject: [PATCH 127/242] Fixes #6298 Fixes #6264 [SVN r76096] --- include/boost/lexical_cast.hpp | 7 ++- test/lexical_cast_empty_input_test.cpp | 81 ++++++++++++++++++++++---- 2 files changed, 76 insertions(+), 12 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 5fa6a96..11ee183 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -586,7 +586,7 @@ namespace boost --end; value = 0; - if ( *end < czero || *end >= czero + 10 || begin > end) + if (begin > end || *end < czero || *end >= czero + 10) return false; value = *end - czero; --end; @@ -684,6 +684,7 @@ namespace boost , const CharT opening_brace, const CharT closing_brace) { using namespace std; + if (begin == end) return false; const CharT minus = lcast_char_constants::minus; const CharT plus = lcast_char_constants::plus; const int inifinity_size = 8; @@ -1183,7 +1184,7 @@ namespace boost bool const result = !(stream << input).fail(); start = stringbuffer.pbase(); finish = stringbuffer.pptr(); - return result && (start != finish); + return result; } template @@ -1358,6 +1359,7 @@ namespace boost template bool shr_unsigned(Type& output) { + if (start == finish) return false; CharT const minus = lcast_char_constants::minus; CharT const plus = lcast_char_constants::plus; bool has_minus = false; @@ -1392,6 +1394,7 @@ namespace boost template bool shr_signed(Type& output) { + if (start == finish) return false; CharT const minus = lcast_char_constants::minus; CharT const plus = lcast_char_constants::plus; typedef BOOST_DEDUCED_TYPENAME make_unsigned::type utype; diff --git a/test/lexical_cast_empty_input_test.cpp b/test/lexical_cast_empty_input_test.cpp index 42e7cec..0c67542 100755 --- a/test/lexical_cast_empty_input_test.cpp +++ b/test/lexical_cast_empty_input_test.cpp @@ -24,27 +24,86 @@ using namespace boost; void test_empty_iterator_range() { - boost::iterator_range v; + boost::iterator_range v; BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_EQUAL(lexical_cast(v), std::string()); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); } void test_empty_string() { - BOOST_CHECK_THROW(lexical_cast(std::string()), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(std::string()), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(std::string()), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(std::string()), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(std::string()), bad_lexical_cast); - BOOST_CHECK_EQUAL(lexical_cast(std::string()), std::string()); - BOOST_CHECK_THROW(lexical_cast(std::string()), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(std::string()), bad_lexical_cast); + std::string v; + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_EQUAL(lexical_cast(v), std::string()); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); +} + +struct Escape +{ + Escape(const std::string& s) + : str_(s) + {} + + std::string str_; +}; + +inline std::ostream& operator<< (std::ostream& o, const Escape& rhs) +{ + return o << rhs.str_; +} + +void test_empty_user_class() +{ + Escape v(""); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_EQUAL(lexical_cast(v), std::string()); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); +} + +namespace std { +inline std::ostream & operator<<(std::ostream & out, const std::vector & v) +{ + std::ostream_iterator it(out); + std::copy(v.begin(), v.end(), it); + assert(out); + return out; +} +} + +void test_empty_vector() +{ + std::vector v; + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_EQUAL(lexical_cast(v), std::string()); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); } unit_test::test_suite *init_unit_test_suite(int, char *[]) @@ -53,6 +112,8 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) BOOST_TEST_SUITE("lexical_cast. Empty input unit test"); suite->add(BOOST_TEST_CASE(&test_empty_iterator_range)); suite->add(BOOST_TEST_CASE(&test_empty_string)); + suite->add(BOOST_TEST_CASE(&test_empty_user_class)); + suite->add(BOOST_TEST_CASE(&test_empty_vector)); return suite; } From 085bd6f93c56d55ebd952086926449536162937f Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 25 Dec 2011 18:55:33 +0000 Subject: [PATCH 128/242] Fixes #6290 Tiny documentation update Updated char16_t and char32_t support (still some work required) lexical_cast_empty_input_test.cpp refactored [SVN r76154] --- doc/lexical_cast.qbk | 2 +- include/boost/lexical_cast.hpp | 24 +++++++- test/lexical_cast_empty_input_test.cpp | 80 ++++++++++++++++++-------- 3 files changed, 79 insertions(+), 27 deletions(-) diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index 0532b56..bf6b562 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -172,7 +172,7 @@ limitation of compiler options that you use. [section Changes] * [*boost 1.49.0 :] - * Added code to work with typedefed wchar_t (compilation flag /Zc:wchar_t- for Visual Studio). + * Restored work with typedefed wchar_t (compilation flag /Zc:wchar_t- for Visual Studio). * [*boost 1.48.0 :] diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 11ee183..b9bc984 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -18,7 +18,7 @@ // with additional fixes and suggestions from Gennaro Prota, // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, -// Cheng Yang and other Boosters +// Cheng Yang, Matthew Bradbury and other Boosters // when: November 2000, March 2003, June 2005, June 2006, March 2011 #include @@ -744,6 +744,26 @@ namespace boost , L'(', L')'); } #endif +#ifndef BOOST_NO_CHAR16_T + template + bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value) + { + return parse_inf_nan_impl(begin, end, value + , u"NAN", u"nan" + , u"INFINITY", u"infinity" + , u'(', u')'); + } +#endif +#ifndef BOOST_NO_CHAR32_T + template + bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value) + { + return parse_inf_nan_impl(begin, end, value + , U"NAN", U"nan" + , U"INFINITY", U"infinity" + , U'(', U')'); + } +#endif template bool parse_inf_nan(const CharT* begin, const CharT* end, T& value) @@ -864,7 +884,7 @@ namespace boost CharT const thousands_sep = grouping_size ? np.thousands_sep() : 0; CharT const decimal_point = np.decimal_point(); bool found_grouping = false; - unsigned int last_grouping_pos = grouping_size - 1; + std::string::size_type last_grouping_pos = grouping_size - 1; #else CharT const decimal_point = lcast_char_constants::c_decimal_separator; #endif diff --git a/test/lexical_cast_empty_input_test.cpp b/test/lexical_cast_empty_input_test.cpp index 0c67542..5a5881b 100755 --- a/test/lexical_cast_empty_input_test.cpp +++ b/test/lexical_cast_empty_input_test.cpp @@ -22,34 +22,78 @@ using namespace boost; -void test_empty_iterator_range() +#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) +#define BOOST_LCAST_NO_WCHAR_T +#endif + +template +void do_test_on_empty_input(T& v) { - boost::iterator_range v; BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_EQUAL(lexical_cast(v), std::string()); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); +#if defined(BOOST_HAS_LONG_LONG) + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); +#elif defined(BOOST_HAS_MS_INT64) + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast<__int64>(v), bad_lexical_cast); +#endif +} + +void test_empty_iterator_range() +{ + + boost::iterator_range v; + do_test_on_empty_input(v); + BOOST_CHECK_EQUAL(lexical_cast(v), std::string()); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + + boost::iterator_range cv; + do_test_on_empty_input(cv); + BOOST_CHECK_EQUAL(lexical_cast(cv), std::string()); + BOOST_CHECK_THROW(lexical_cast(cv), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(cv), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(cv), bad_lexical_cast); + + const boost::iterator_range ccv; + do_test_on_empty_input(ccv); + BOOST_CHECK_EQUAL(lexical_cast(ccv), std::string()); + BOOST_CHECK_THROW(lexical_cast(ccv), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(ccv), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(ccv), bad_lexical_cast); } void test_empty_string() { std::string v; - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_EQUAL(lexical_cast(v), std::string()); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + do_test_on_empty_input(v); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + +#ifndef BOOST_LCAST_NO_WCHAR_T + std::wstring vw; + do_test_on_empty_input(vw); + BOOST_CHECK_THROW(lexical_cast(vw), bad_lexical_cast); +#endif + +// Currently, no compiler and STL library fully support char16_t and char32_t +//#ifndef BOOST_NO_CHAR16_T +// std::basic_string v16w; +// do_test_on_empty_input(v16w); +// BOOST_CHECK_THROW(lexical_cast(v16w), bad_lexical_cast); +//#endif +//#ifndef BOOST_NO_CHAR32_T +// std::basic_string v32w; +// do_test_on_empty_input(v32w); +// BOOST_CHECK_THROW(lexical_cast(v32w), bad_lexical_cast); +//#endif } struct Escape @@ -69,13 +113,7 @@ inline std::ostream& operator<< (std::ostream& o, const Escape& rhs) void test_empty_user_class() { Escape v(""); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_EQUAL(lexical_cast(v), std::string()); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + do_test_on_empty_input(v); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); @@ -94,13 +132,7 @@ inline std::ostream & operator<<(std::ostream & out, const std::vector & v void test_empty_vector() { std::vector v; - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - BOOST_CHECK_EQUAL(lexical_cast(v), std::string()); - BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + do_test_on_empty_input(v); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); From d754143308c482d381aba9ee9834fd8ab6e2058b Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 4 Jan 2012 16:06:37 +0000 Subject: [PATCH 129/242] Fixes #6132 Fixes #6182 [SVN r76305] --- include/boost/lexical_cast.hpp | 27 ++++++-- test/Jamfile.v2 | 1 + test/lexical_cast_pointers_test.cpp | 96 +++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 6 deletions(-) create mode 100755 test/lexical_cast_pointers_test.cpp diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index b9bc984..cec2c50 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -19,7 +19,7 @@ // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, // Cheng Yang, Matthew Bradbury and other Boosters -// when: November 2000, March 2003, June 2005, June 2006, March 2011 +// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2012 #include #include @@ -1822,6 +1822,24 @@ namespace boost deduce_char_traits::type traits; typedef BOOST_DEDUCED_TYPENAME remove_pointer::type removed_ptr_t; + + // is_char_types_match variable value can be computed via + // sizeof(char_type) == sizeof(removed_ptr_t). But when + // removed_ptr_t is an incomplete type or void*, compilers + // produce warnings or errors. + const bool is_char_types_match = + (::boost::type_traits::ice_or< + ::boost::type_traits::ice_and< + ::boost::type_traits::ice_eq::value, + ::boost::type_traits::ice_or< + ::boost::is_same::value, + ::boost::is_same::value, + ::boost::is_same::value + >::value + >::value, + is_same::value + >::value); + const bool requires_stringbuf = !( ::boost::type_traits::ice_or< @@ -1830,10 +1848,7 @@ namespace boost ::boost::type_traits::ice_and< is_pointer::value, is_char_or_wchar::value, - ::boost::type_traits::ice_eq< - sizeof(char_type), - sizeof(removed_ptr_t) - >::value + is_char_types_match >::value >::value ); @@ -2111,7 +2126,7 @@ namespace boost // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011. +// Copyright Antony Polukhin, 2011-2012. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 8718301..c311420 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -35,6 +35,7 @@ test-suite conversion [ run lexical_cast_inf_nan_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_containers_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_empty_input_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run lexical_cast_pointers_test.cpp ../../test/build//boost_unit_test_framework/static ] [ compile lexical_cast_typedefed_wchar_test.cpp : msvc:on ] [ run lexical_cast_typedefed_wchar_test_runtime.cpp ../../test/build//boost_unit_test_framework/static : : : msvc:on ] ; diff --git a/test/lexical_cast_pointers_test.cpp b/test/lexical_cast_pointers_test.cpp new file mode 100755 index 0000000..d24a895 --- /dev/null +++ b/test/lexical_cast_pointers_test.cpp @@ -0,0 +1,96 @@ +// 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 + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include +#include + +using namespace boost; + +#if defined(BOOST_NO_STRINGSTREAM) + typedef std::strstream ss_t; +#else + typedef std::stringstream ss_t; +#endif + +void test_void_pointers_conversions() +{ + void *p_to_null = NULL; + const void *cp_to_data = "Some data"; + char nonconst_data[5]; + void *p_to_data = nonconst_data; + ss_t ss; + + ss << p_to_null; + BOOST_CHECK_EQUAL(boost::lexical_cast(p_to_null), ss.str()); + ss.str(std::string()); + + ss << cp_to_data; + BOOST_CHECK_EQUAL(boost::lexical_cast(cp_to_data), ss.str()); + ss.str(std::string()); + + ss << p_to_data; + BOOST_CHECK_EQUAL(boost::lexical_cast(p_to_data), ss.str()); + ss.str(std::string()); +} + +struct incomplete_type; + +void test_incomplete_type_pointers_conversions() +{ + incomplete_type *p_to_null = NULL; + const incomplete_type *cp_to_data = NULL; + char nonconst_data[5]; + incomplete_type *p_to_data = reinterpret_cast(nonconst_data); + ss_t ss; + + ss << p_to_null; + BOOST_CHECK_EQUAL(boost::lexical_cast(p_to_null), ss.str()); + ss.str(std::string()); + + ss << cp_to_data; + BOOST_CHECK_EQUAL(boost::lexical_cast(cp_to_data), ss.str()); + ss.str(std::string()); + + ss << p_to_data; + BOOST_CHECK_EQUAL(boost::lexical_cast(p_to_data), ss.str()); + ss.str(std::string()); +} + +struct ble; +typedef struct ble *meh; +std::ostream& operator <<(std::ostream &o, meh) { + o << "yay"; + return o; +} + +void test_inomplete_type_with_overloaded_ostream_op() { + meh heh = NULL; + ss_t ss; + ss << heh; + BOOST_CHECK_EQUAL(boost::lexical_cast(heh), ss.str()); +} + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast pinters test"); + suite->add(BOOST_TEST_CASE(&test_void_pointers_conversions)); + suite->add(BOOST_TEST_CASE(&test_incomplete_type_pointers_conversions)); + suite->add(BOOST_TEST_CASE(&test_inomplete_type_with_overloaded_ostream_op)); + return suite; +} From 9a6d983ee55ba495b3b5f9055fa86c7fd7018c6c Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 5 Jan 2012 12:09:15 +0000 Subject: [PATCH 130/242] Fixes #6193 [SVN r76318] --- include/boost/lexical_cast.hpp | 21 ++++++++++++++++----- lexical_cast_test.cpp | 11 +++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index cec2c50..0927e39 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -18,7 +18,7 @@ // with additional fixes and suggestions from Gennaro Prota, // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, -// Cheng Yang, Matthew Bradbury and other Boosters +// Cheng Yang, Matthew Bradbury, David W. Birdsall and other Boosters // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2012 #include @@ -591,6 +591,7 @@ namespace boost value = *end - czero; --end; T multiplier = 1; + bool multiplier_overflowed = false; #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE std::locale loc; @@ -613,12 +614,17 @@ namespace boost for(;end>=begin; --end) { if (remained) { - T const new_sub_value = multiplier * 10 * (*end - czero); + T const multiplier_10 = multiplier * 10; + if (multiplier_10 / 10 != multiplier) multiplier_overflowed = true; + + T const dig_value = *end - czero; + T const new_sub_value = multiplier_10 * dig_value; if (*end < czero || *end >= czero + 10 /* detecting overflow */ - || new_sub_value/10 != multiplier * (*end - czero) + || (dig_value && new_sub_value / dig_value != multiplier_10) || static_cast((std::numeric_limits::max)()-new_sub_value) < value + || (multiplier_overflowed && dig_value) ) return false; @@ -656,12 +662,17 @@ namespace boost { while ( begin <= end ) { - T const new_sub_value = multiplier * 10 * (*end - czero); + T const multiplier_10 = multiplier * 10; + if (multiplier_10 / 10 != multiplier) multiplier_overflowed = true; + + T const dig_value = *end - czero; + T const new_sub_value = multiplier_10 * dig_value; if (*end < czero || *end >= czero + 10 /* detecting overflow */ - || new_sub_value/10 != multiplier * (*end - czero) + || (dig_value && new_sub_value / dig_value != multiplier_10) || static_cast((std::numeric_limits::max)()-new_sub_value) < value + || (multiplier_overflowed && dig_value) ) return false; diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index faeaa93..4e9ec90 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -796,6 +796,17 @@ void test_conversion_from_to_integral() BOOST_CHECK_THROW(lexical_cast("+-9"), bad_lexical_cast); // test_conversion_from_to_integral_for_locale + // Overflow test case from David W. Birdsall + std::string must_owerflow_str = "160000000000000000000"; + std::string must_owerflow_negative_str = "-160000000000000000000"; + for (int i = 0; i < 15; ++i) { + BOOST_CHECK_THROW(lexical_cast(must_owerflow_str), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(must_owerflow_negative_str), bad_lexical_cast); + + must_owerflow_str += '0'; + must_owerflow_negative_str += '0'; + } + typedef std::numpunct numpunct; restore_oldloc guard; From 7bdc45327a2a1f5cefe513752d7548ba370145c6 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 8 Jan 2012 09:21:00 +0000 Subject: [PATCH 131/242] Tiny documentation update [SVN r76356] --- doc/lexical_cast.qbk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index bf6b562..4715803 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -172,7 +172,8 @@ limitation of compiler options that you use. [section Changes] * [*boost 1.49.0 :] - * Restored work with typedefed wchar_t (compilation flag /Zc:wchar_t- for Visual Studio). + * Restored work with typedefed wchar_t (compilation flag /Zc:wchar_t- for Visual Studio). + * Better performance and less memory usage for `boost::container::basic_string` conversions. * [*boost 1.48.0 :] From 5ed7bfd280aad6e060952b184826aa644a09f2b8 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 20 Jan 2012 19:33:04 +0000 Subject: [PATCH 132/242] Attempt to fix #6251 [SVN r76599] --- include/boost/lexical_cast.hpp | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 0927e39..cd7d512 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -21,6 +21,32 @@ // Cheng Yang, Matthew Bradbury, David W. Birdsall and other Boosters // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2012 +#include +#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) +#define BOOST_LCAST_NO_WCHAR_T +#endif + +#if (defined(__MINGW32__) || defined(__MINGW64__)) && (__GNUC__ == 4) \ + && ((__GNUC_MINOR__ == 4) || (__GNUC_MINOR__ == 5)) && defined(__STRICT_ANSI__) \ + && !defined(BOOST_LCAST_NO_WCHAR_T) + +// workaround for a mingw bug +// http://sourceforge.net/tracker/index.php?func=detail&aid=2373234&group_id=2435&atid=102435 +#include <_mingw.h> +#if (__GNUC_MINOR__ == 4) +extern "C" { +_CRTIMP int __cdecl swprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , ...); +_CRTIMP int __cdecl vswprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , ...); +} +#endif +#if (__GNUC_MINOR__ == 5) +extern "C" { +_CRTIMP int __cdecl swprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , ...); +_CRTIMP int __cdecl vswprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , va_list); +} +#endif +#endif + #include #include #include @@ -30,7 +56,6 @@ #include #include #include -#include #include #include #include @@ -67,10 +92,6 @@ #include #endif -#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) -#define BOOST_LCAST_NO_WCHAR_T -#endif - #ifdef BOOST_NO_TYPEID #define BOOST_LCAST_THROW_BAD_CAST(S, T) throw_exception(bad_lexical_cast()) #else From 84d9706182fd1ba05d3791f1a884ee58e76451e8 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 26 Jan 2012 17:47:56 +0000 Subject: [PATCH 133/242] Update tests with example from #6452 [SVN r76707] --- test/lexical_cast_empty_input_test.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/lexical_cast_empty_input_test.cpp b/test/lexical_cast_empty_input_test.cpp index 5a5881b..3b94f5f 100755 --- a/test/lexical_cast_empty_input_test.cpp +++ b/test/lexical_cast_empty_input_test.cpp @@ -138,6 +138,20 @@ void test_empty_vector() BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); } + +struct my_string { + friend std::ostream &operator<<(std::ostream& sout, my_string const&/* st*/) { + return sout << ""; + } +}; + +void test_empty_zero_terminated_string() +{ + my_string st; + std::string st2 = boost::lexical_cast(st); + (void)st2; +} + unit_test::test_suite *init_unit_test_suite(int, char *[]) { unit_test::test_suite *suite = @@ -146,6 +160,7 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) suite->add(BOOST_TEST_CASE(&test_empty_string)); suite->add(BOOST_TEST_CASE(&test_empty_user_class)); suite->add(BOOST_TEST_CASE(&test_empty_vector)); + suite->add(BOOST_TEST_CASE(&test_empty_zero_terminated_string)); return suite; } From efe20fcf765955a7a1ce8ff88ccbc15ce6186a64 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 26 Jan 2012 17:51:17 +0000 Subject: [PATCH 134/242] Tiny change to test case from #6452 [SVN r76708] --- test/lexical_cast_empty_input_test.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/lexical_cast_empty_input_test.cpp b/test/lexical_cast_empty_input_test.cpp index 3b94f5f..df05981 100755 --- a/test/lexical_cast_empty_input_test.cpp +++ b/test/lexical_cast_empty_input_test.cpp @@ -148,8 +148,7 @@ struct my_string { void test_empty_zero_terminated_string() { my_string st; - std::string st2 = boost::lexical_cast(st); - (void)st2; + BOOST_CHECK_EQUAL(boost::lexical_cast(st), std::string());; } unit_test::test_suite *init_unit_test_suite(int, char *[]) From a0cbfa8af636efc4ad2fc45cf5f751ac1e8f7d9a Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 31 Jan 2012 16:05:22 +0000 Subject: [PATCH 135/242] New test case from ticket #5793 [SVN r76809] --- test/lexical_cast_typedefed_wchar_test.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/lexical_cast_typedefed_wchar_test.cpp b/test/lexical_cast_typedefed_wchar_test.cpp index 752c3e5..82f7cc9 100755 --- a/test/lexical_cast_typedefed_wchar_test.cpp +++ b/test/lexical_cast_typedefed_wchar_test.cpp @@ -13,12 +13,26 @@ #include #include +#include +#include + +void parseDate() +{ + std::locale locale; + boost::date_time::format_date_parser parser(L"", locale); + boost::date_time::special_values_parser svp; + + boost::gregorian::date date = parser.parse_date(L"", L"", svp); +} + + int main() { #ifdef BOOST_MSVC BOOST_STATIC_ASSERT((boost::is_same::value)); #endif + parseDate(); return ::boost::lexical_cast(L"1000") == 1000; } From 132663404bdaa634838d205b52da2eee226639eb Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 1 Feb 2012 04:22:21 +0000 Subject: [PATCH 136/242] Added tests for ticket #6453 [SVN r76817] --- test/lexical_cast_containers_test.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/lexical_cast_containers_test.cpp b/test/lexical_cast_containers_test.cpp index 5f98ac8..0c6315b 100644 --- a/test/lexical_cast_containers_test.cpp +++ b/test/lexical_cast_containers_test.cpp @@ -13,6 +13,7 @@ #include void testing_boost_containers_basic_string(); +void testing_boost_containers_string_std_string(); using namespace boost; @@ -21,6 +22,7 @@ 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::container::string"); suite->add(BOOST_TEST_CASE(testing_boost_containers_basic_string)); + suite->add(BOOST_TEST_CASE(testing_boost_containers_string_std_string)); return suite; } @@ -35,4 +37,24 @@ void testing_boost_containers_basic_string() BOOST_CHECK(1000 == lexical_cast(str)); } +#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) +#define BOOST_LCAST_NO_WCHAR_T +#endif +void testing_boost_containers_string_std_string() +{ + std::string std_str("std_str"); + boost::container::string boost_str("boost_str"); + BOOST_CHECK(boost::lexical_cast(boost_str) == "boost_str"); + BOOST_CHECK(boost::lexical_cast(std_str) == "std_str"); + +#ifndef BOOST_LCAST_NO_WCHAR_T + std::wstring std_wstr(L"std_wstr"); + boost::container::wstring boost_wstr(L"boost_wstr"); + + BOOST_CHECK(boost::lexical_cast(boost_wstr) == L"boost_wstr"); + BOOST_CHECK(boost::lexical_cast(std_wstr) == L"std_wstr"); + +#endif + +} From c9863cd254c667dfb635f348674f7fb379f6737b Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 1 Feb 2012 04:25:21 +0000 Subject: [PATCH 137/242] FIxes #6453 (compile error due to deduce_char_traits ambiguity) [SVN r76818] --- include/boost/lexical_cast.hpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index cd7d512..b69d5a0 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -324,6 +324,24 @@ namespace boost { typedef Traits type; }; + + template + struct deduce_char_traits< CharT + , ::boost::container::basic_string + , std::basic_string + > + { + typedef Traits type; + }; + + template + struct deduce_char_traits< CharT + , std::basic_string + , ::boost::container::basic_string + > + { + typedef Traits type; + }; #endif } From 7a48fea517180d332f3f45c33cb6cfd772f53937 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 1 Feb 2012 17:08:10 +0000 Subject: [PATCH 138/242] Disabling some optimisations for sun cc Bug described in #6462 [SVN r76824] --- include/boost/lexical_cast.hpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index b69d5a0..5a3d4f0 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -72,7 +72,9 @@ _CRTIMP int __cdecl vswprintf(wchar_t * __restrict__ , const wchar_t * __restric #include #include #include +#if !defined(__SUNPRO_CC) #include +#endif // !defined(__SUNPRO_CC) #ifndef BOOST_NO_CWCHAR # include #endif @@ -170,11 +172,13 @@ namespace boost typedef CharT type; }; +#if !defined(__SUNPRO_CC) template struct stream_char< ::boost::container::basic_string > { typedef CharT type; }; +#endif // !defined(__SUNPRO_CC) #endif #ifndef BOOST_LCAST_NO_WCHAR_T @@ -289,6 +293,7 @@ namespace boost typedef Traits type; }; +#if !defined(__SUNPRO_CC) template struct deduce_char_traits< CharT , ::boost::container::basic_string @@ -342,6 +347,7 @@ namespace boost { typedef Traits type; }; +#endif // !defined(__SUNPRO_CC) #endif } @@ -1364,6 +1370,7 @@ namespace boost return true; } +#if !defined(__SUNPRO_CC) template bool operator<<(::boost::container::basic_string const& str) { @@ -1371,7 +1378,7 @@ namespace boost finish = start + str.length(); return true; } - +#endif // !defined(__SUNPRO_CC) bool operator<<(bool value) { CharT const czero = lcast_char_constants::zero; @@ -1588,9 +1595,10 @@ namespace boost #else template bool operator>>(std::basic_string& str) { str.assign(start, finish); return true; } - +#if !defined(__SUNPRO_CC) template bool operator>>(::boost::container::basic_string& str) { str.assign(start, finish); return true; } +#endif // !defined(__SUNPRO_CC) #endif /* * case "-0" || "0" || "+0" : output = false; return true; @@ -1726,13 +1734,13 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value = true ); }; - +#if !defined(__SUNPRO_CC) template struct is_stdstring< ::boost::container::basic_string > { BOOST_STATIC_CONSTANT(bool, value = true ); }; - +#endif // !defined(__SUNPRO_CC) template struct is_char_or_wchar { @@ -1832,7 +1840,7 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value = true ); }; - +#if !defined(__SUNPRO_CC) template struct is_char_array_to_stdstring< ::boost::container::basic_string, CharT* > { @@ -1844,6 +1852,7 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value = true ); }; +#endif // !defined(__SUNPRO_CC) #if (defined _MSC_VER) # pragma warning( push ) From 04f441e989ef073a69334ae313ee53c78724c348 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 7 Feb 2012 17:20:03 +0000 Subject: [PATCH 139/242] Commited sources of performance testing program and Jamfile.v2 to build and run it [SVN r76936] --- perf/Jamfile.v2 | 29 ++++ perf/performance_test.cpp | 309 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 338 insertions(+) create mode 100644 perf/Jamfile.v2 create mode 100644 perf/performance_test.cpp diff --git a/perf/Jamfile.v2 b/perf/Jamfile.v2 new file mode 100644 index 0000000..78176be --- /dev/null +++ b/perf/Jamfile.v2 @@ -0,0 +1,29 @@ +#============================================================================== +# Copyright (c) 2012 Antony Polukhin +# +# 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) +#============================================================================== + +# performance tests +import testing ; +import path ; + +path-constant TEST_DIR : . ; + +project performance/test + : source-location ./ + : requirements +# /boost/chrono//boost_chrono +# /boost/system//boost_system + static + freebsd:"-lrt" + linux:"-lrt" + gcc:-fvisibility=hidden + intel-linux:-fvisibility=hidden + sun:-xldscope=hidden + : default-build release + ; + +run performance_test.cpp : $(TEST_DIR) ; + diff --git a/perf/performance_test.cpp b/perf/performance_test.cpp new file mode 100644 index 0000000..ff1eb1d --- /dev/null +++ b/perf/performance_test.cpp @@ -0,0 +1,309 @@ +// (C) Copyright Antony Polukhin 2012. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org/libs/config for most recent version. + +// +// Testing lexical_cast<> performance +// + +#define BOOST_ERROR_CODE_HEADER_ONLY +#define BOOST_CHRONO_HEADER_ONLY + +#include +#include +#include +#include + +// File to output data +std::fstream fout; + +template +static inline void test_lexical(const InT& in_val) { + OutT out_val = boost::lexical_cast(in_val); + (void)out_val; +} + +template +static inline void test_ss_constr(const InT& in_val) { + OutT out_val; + std::stringstream ss; + ss << in_val; + if (ss.fail()) throw std::logic_error("descr"); + ss >> out_val; + if (ss.fail()) throw std::logic_error("descr"); +} + +template +static inline void test_ss_noconstr(StringStreamT& ss, const InT& in_val) { + OutT out_val; + ss << in_val; // ss is an instance of std::stringstream + if (ss.fail()) throw std::logic_error("descr"); + ss >> out_val; + if (ss.fail()) throw std::logic_error("descr"); + /* reseting std::stringstream to use it again */ + ss.str(std::string()); + ss.clear(); +} + +struct structure_sprintf { + template + static inline void test(BufferT* buffer, const InT& in_val, const char* const conv) { + sprintf(buffer, conv, in_val); + OutT out_val(buffer); + } + + template + static inline void test(BufferT* buffer, const std::string& in_val, const char* const conv) { + sprintf(buffer, conv, in_val.c_str()); + OutT out_val(buffer); + } +}; + +struct structure_sscanf { + template + static inline void test(BufferT* /*buffer*/, const InT& in_val, const char* const conv) { + OutT out_val; + sscanf(reinterpret_cast(in_val), conv, &out_val); + } + + template + static inline void test(BufferT* /*buffer*/, const std::string& in_val, const char* const conv) { + OutT out_val; + sscanf(in_val.c_str(), conv, &out_val); + } +}; + +struct structure_fake { + template + static inline void test(BufferT* /*buffer*/, const InT& /*in_val*/, const char* const /*conv*/) {} +}; + +static const int fake_test_value = 9999; + +template +static inline void min_fancy_output(T v1, T v2, T v3, T v4) { + const char beg_mark[] = "!!! *"; + const char end_mark[] = "* !!!"; + const char no_mark[] = ""; + + unsigned int res = 4; + if (v1 < v2 && v1 < v3 && v1 < v4) res = 1; + if (v2 < v1 && v2 < v3 && v2 < v4) res = 2; + if (v3 < v1 && v3 < v2 && v3 < v4) res = 3; + + fout << "[ " + << (res == 1 ? beg_mark : no_mark) + ; + + if (v1) fout << v1; + else fout << "<1"; + + fout << (res == 1 ? end_mark : no_mark) + << " ][ " + << (res == 2 ? beg_mark : no_mark) + ; + + if (v2) fout << v2; + else fout << "<1"; + + fout << (res == 2 ? end_mark : no_mark) + << " ][ " + << (res == 3 ? beg_mark : no_mark) + ; + + if (v3) fout << v3; + else fout << "<1"; + + fout << (res == 3 ? end_mark : no_mark) + << " ][ " + << (res == 4 ? beg_mark : no_mark) + ; + + if (!v4) fout << "<1"; + else if (v4 == fake_test_value) fout << "---"; + else fout << v4; + + fout + << (res == 4 ? end_mark : no_mark) + << " ]"; +} + +template +static inline void perf_test_impl(const FromT& in_val, const char* const conv) { + + typedef boost::chrono::steady_clock test_clock; + test_clock::time_point start; + typedef boost::chrono::milliseconds duration_t; + duration_t lexical_cast_time, ss_constr_time, ss_noconstr_time, printf_time; + + start = test_clock::now(); + for (unsigned int i = 0; i < IetartionsCountV; ++i) { + test_lexical(in_val); + test_lexical(in_val); + test_lexical(in_val); + test_lexical(in_val); + } + lexical_cast_time = boost::chrono::duration_cast(test_clock::now() - start); + + + start = test_clock::now(); + for (unsigned int i = 0; i < IetartionsCountV; ++i) { + test_ss_constr(in_val); + test_ss_constr(in_val); + test_ss_constr(in_val); + test_ss_constr(in_val); + } + ss_constr_time = boost::chrono::duration_cast(test_clock::now() - start); + + std::stringstream ss; + start = test_clock::now(); + for (unsigned int i = 0; i < IetartionsCountV; ++i) { + test_ss_noconstr(ss, in_val); + test_ss_noconstr(ss, in_val); + test_ss_noconstr(ss, in_val); + test_ss_noconstr(ss, in_val); + } + ss_noconstr_time = boost::chrono::duration_cast(test_clock::now() - start); + + + char buffer[128]; + start = test_clock::now(); + for (unsigned int i = 0; i < IetartionsCountV; ++i) { + SprintfT::template test(buffer, in_val, conv); + SprintfT::template test(buffer, in_val, conv); + SprintfT::template test(buffer, in_val, conv); + SprintfT::template test(buffer, in_val, conv); + } + printf_time = boost::chrono::duration_cast(test_clock::now() - start); + + min_fancy_output( + lexical_cast_time.count(), + ss_constr_time.count(), + ss_noconstr_time.count(), + boost::is_same::value ? fake_test_value : printf_time.count() + ); +} + +template +static inline void perf_test(const std::string& test_name, const FromT& in_val, const char* const conv) { + const unsigned int ITERATIONSCOUNT = 100000; + fout << " [[ " << test_name << " ]"; + + perf_test_impl(in_val, conv); + + fout << "]\n"; +} + + +template +void string_like_test_set(const std::string& from) { + typedef structure_sscanf ssc_t; + ConverterT conv; + + perf_test(from + "->char", conv("c"), "%c"); + perf_test(from + "->signed char", conv("c"), "%hhd"); + perf_test(from + "->unsigned char", conv("c"), "%hhu"); + + perf_test(from + "->int", conv("100"), "%d"); + perf_test(from + "->short", conv("100"), "%hd"); + perf_test(from + "->long int", conv("100"), "%ld"); + perf_test(from + "->long long", conv("100"), "%lld"); + + perf_test(from + "->unsigned int", conv("100"), "%u"); + perf_test(from + "->unsigned short", conv("100"), "%hu"); + perf_test(from + "->unsigned long int", conv("100"), "%lu"); + perf_test(from + "->unsigned long long", conv("100"), "%llu"); + + // perf_test(from + "->bool", conv("1"), "%"); + + perf_test(from + "->float", conv("1.123"), "%f"); + perf_test(from + "->double", conv("1.123"), "%lf"); + perf_test(from + "->long double", conv("1.123"), "%Lf"); + + + perf_test(from + "->string", conv("string"), "%Lf"); + perf_test(from + "->container::string" + , conv("string"), "%Lf"); + +} + +struct to_string_conv { + std::string operator()(const char* const c) const { + return c; + } +}; + +struct to_char_conv { + const char* operator()(const char* const c) const { + return c; + } +}; + +struct to_uchar_conv { + const unsigned char* operator()(const char* const c) const { + return reinterpret_cast(c); + } +}; + + +struct to_schar_conv { + const signed char* operator()(const char* const c) const { + return reinterpret_cast(c); + } +}; + +int main(int argc, char** argv) { + BOOST_ASSERT(argc >= 2); + std::string output_path(argv[1]); + output_path += "/results.txt"; + fout.open(output_path.c_str(), std::fstream::in | std::fstream::out | std::fstream::app); + BOOST_ASSERT(fout); + + fout << "[section " << BOOST_COMPILER << "]\n" + << "[table:id Performance Table ( "<< BOOST_COMPILER << ")\n" + << "[[From->To] [lexical_cast] [std::stringstream with construction] " + << "[std::stringstream without construction][scanf/printf]]\n"; + + + // From std::string to ... + string_like_test_set("string"); + + // From ... to std::string + perf_test("string->char", 'c', "%c"); + perf_test("string->signed char", static_cast('c'), "%hhd"); + perf_test("string->unsigned char", static_cast('c'), "%hhu"); + + perf_test("int->string", 100, "%d"); + perf_test("short->string", static_cast(100), "%hd"); + perf_test("long int->string", 100l, "%ld"); + perf_test("long long->string", 100ll, "%lld"); + + perf_test("unsigned int->string", static_cast(100u), "%u"); + perf_test("unsigned short->string", 100u, "%hu"); + perf_test("unsigned long int->string", 100ul, "%lu"); + perf_test("unsigned long long->string", static_cast(100), "%llu"); + + // perf_test("bool->string", std::string("1"), "%"); + + perf_test("float->string", 1.123f, "%f"); + perf_test("double->string", 1.123, "%lf"); + perf_test("long double->string", 1.123L, "%Lf"); + + + string_like_test_set("char*"); + string_like_test_set("unsigned char*"); + string_like_test_set("signed char*"); + + perf_test("int->int", 100, ""); + perf_test("float->double", 100.0f, ""); + perf_test("char->signed char", 'c', ""); + + fout << "]\n" + << "[endsect]\n\n"; + return 0; +} + + From 646b958a92a559cb49211c5a6c179930f89fcc1e Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 16 Feb 2012 17:56:27 +0000 Subject: [PATCH 140/242] FIx #5689 (issue from 5th comment) [SVN r77039] --- include/boost/lexical_cast.hpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 5a3d4f0..be27890 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -732,6 +732,15 @@ namespace boost namespace detail { + template + bool lc_iequal(const CharT* val, const CharT* lcase, const CharT* ucase, unsigned int len) { + for( unsigned int i=0; i < len; ++i ) { + if ( val[i] != lcase[i] && val[i] != ucase[i] ) return false; + } + + return true; + } + /* Returns true and sets the correct value if found NaN or Inf. */ template inline bool parse_inf_nan_impl(const CharT* begin, const CharT* end, T& value @@ -755,7 +764,7 @@ namespace boost else if( *begin == plus ) ++begin; if( end-begin < 3 ) return false; - if( !memcmp(begin, lc_nan, 3*sizeof(CharT)) || !memcmp(begin, lc_NAN, 3*sizeof(CharT)) ) + if( lc_iequal(begin, lc_nan, lc_NAN, 3) ) { begin += 3; if (end != begin) /* It is 'nan(...)' or some bad input*/ @@ -772,13 +781,13 @@ namespace boost if (( /* 'INF' or 'inf' */ end-begin==3 && - (!memcmp(begin, lc_infinity, 3*sizeof(CharT)) || !memcmp(begin, lc_INFINITY, 3*sizeof(CharT))) + lc_iequal(begin, lc_infinity, lc_INFINITY, 3) ) || ( /* 'INFINITY' or 'infinity' */ end-begin==inifinity_size && - (!memcmp(begin, lc_infinity, inifinity_size)|| !memcmp(begin, lc_INFINITY, inifinity_size)) + lc_iequal(begin, lc_infinity, lc_INFINITY, inifinity_size) ) ) { From 80e858b182fc2cef5425e97d8e792f0cbfaaf01a Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 16 Feb 2012 17:57:52 +0000 Subject: [PATCH 141/242] More tests for fixed #5689 (issue mentiond in 5th comment) [SVN r77040] --- test/lexical_cast_inf_nan_test.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/lexical_cast_inf_nan_test.cpp b/test/lexical_cast_inf_nan_test.cpp index bb4331a..af1caa0 100755 --- a/test/lexical_cast_inf_nan_test.cpp +++ b/test/lexical_cast_inf_nan_test.cpp @@ -85,6 +85,12 @@ void test_inf_nan_templated() BOOST_CHECK( is_pos_inf( lexical_cast("+infinity") ) ); BOOST_CHECK( is_pos_inf( lexical_cast("+INFINITY") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast("iNfiNity") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast("INfinity") ) ); + + BOOST_CHECK( is_neg_inf( lexical_cast("-inFINITY") ) ); + BOOST_CHECK( is_neg_inf( lexical_cast("-INFINITY") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast("nan") ) ); BOOST_CHECK( is_pos_nan( lexical_cast("NAN") ) ); @@ -94,6 +100,15 @@ void test_inf_nan_templated() BOOST_CHECK( is_pos_nan( lexical_cast("+nan") ) ); BOOST_CHECK( is_pos_nan( lexical_cast("+NAN") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast("nAn") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast("NaN") ) ); + + BOOST_CHECK( is_neg_nan( lexical_cast("-nAn") ) ); + BOOST_CHECK( is_neg_nan( lexical_cast("-NaN") ) ); + + BOOST_CHECK( is_pos_nan( lexical_cast("+Nan") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast("+nAN") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast("nan()") ) ); BOOST_CHECK( is_pos_nan( lexical_cast("NAN(some string)") ) ); BOOST_CHECK_THROW( lexical_cast("NAN(some string"), bad_lexical_cast ); @@ -127,6 +142,12 @@ void test_inf_nan_templated() BOOST_CHECK( is_pos_inf( lexical_cast(L"+infinity") ) ); BOOST_CHECK( is_pos_inf( lexical_cast(L"+INFINITY") ) ); + BOOST_CHECK( is_neg_inf( lexical_cast(L"-infINIty") ) ); + BOOST_CHECK( is_neg_inf( lexical_cast(L"-INFiniTY") ) ); + + BOOST_CHECK( is_pos_inf( lexical_cast(L"+inFINIty") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast(L"+INfinITY") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast(L"nan") ) ); BOOST_CHECK( is_pos_nan( lexical_cast(L"NAN") ) ); From d9baa71302b86b5d9eb2ec1c74e57a72abe1d75a Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 17 Feb 2012 18:51:05 +0000 Subject: [PATCH 142/242] Updated INF/NAN support for char16_t and char32_t [SVN r77058] --- include/boost/lexical_cast.hpp | 117 ++++++++++++++++----------------- 1 file changed, 55 insertions(+), 62 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index be27890..4658ab6 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -799,6 +799,41 @@ namespace boost return false; } + template + bool put_inf_nan_impl(CharT* begin, CharT*& end, const T& value + , const CharT* lc_nan + , const CharT* lc_infinity) + { + using namespace std; + const CharT minus = lcast_char_constants::minus; + if ( (boost::math::isnan)(value) ) + { + if ( (boost::math::signbit)(value) ) + { + *begin = minus; + ++ begin; + } + + memcpy(begin, lc_nan, 3 * sizeof(CharT)); + end = begin + 3; + return true; + } else if ( (boost::math::isinf)(value) ) + { + if ( (boost::math::signbit)(value) ) + { + *begin = minus; + ++ begin; + } + + memcpy(begin, lc_infinity, 3 * sizeof(CharT)); + end = begin + 3; + return true; + } + + return false; + } + + #ifndef BOOST_LCAST_NO_WCHAR_T template bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value) @@ -808,6 +843,13 @@ namespace boost , L"INFINITY", L"infinity" , L'(', L')'); } + + template + bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) + { + return put_inf_nan_impl(begin, end, value, L"nan", L"infinity"); + } + #endif #ifndef BOOST_NO_CHAR16_T template @@ -818,6 +860,12 @@ namespace boost , u"INFINITY", u"infinity" , u'(', u')'); } + + template + bool put_inf_nan(char16_t* begin, char16_t*& end, const T& value) + { + return put_inf_nan_impl(begin, end, value, u"nan", u"infinity"); + } #endif #ifndef BOOST_NO_CHAR32_T template @@ -828,6 +876,12 @@ namespace boost , U"INFINITY", U"infinity" , U'(', U')'); } + + template + bool put_inf_nan(char32_t* begin, char32_t*& end, const T& value) + { + return put_inf_nan_impl(begin, end, value, U"nan", U"infinity"); + } #endif template @@ -838,73 +892,12 @@ namespace boost , "INFINITY", "infinity" , '(', ')'); } -#ifndef BOOST_LCAST_NO_WCHAR_T - template - bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) - { - using namespace std; - if ( (boost::math::isnan)(value) ) - { - if ( (boost::math::signbit)(value) ) - { - memcpy(begin,L"-nan", sizeof(L"-nan")); - end = begin + 4; - } else - { - memcpy(begin,L"nan", sizeof(L"nan")); - end = begin + 3; - } - return true; - } else if ( (boost::math::isinf)(value) ) - { - if ( (boost::math::signbit)(value) ) - { - memcpy(begin,L"-inf", sizeof(L"-inf")); - end = begin + 4; - } else - { - memcpy(begin,L"inf", sizeof(L"inf")); - end = begin + 3; - } - return true; - } - return false; - } -#endif template bool put_inf_nan(CharT* begin, CharT*& end, const T& value) { - using namespace std; - if ( (boost::math::isnan)(value) ) - { - if ( (boost::math::signbit)(value) ) - { - memcpy(begin,"-nan", sizeof("-nan")); - end = begin + 4; - } else - { - memcpy(begin,"nan", sizeof("nan")); - end = begin + 3; - } - return true; - } else if ( (boost::math::isinf)(value) ) - { - if ( (boost::math::signbit)(value) ) - { - memcpy(begin,"-inf", sizeof("-inf")); - end = begin + 4; - } else - { - memcpy(begin,"inf", sizeof("inf")); - end = begin + 3; - } - return true; - } - - return false; + return put_inf_nan_impl(begin, end, value, "nan", "infinity"); } - } From b71fb9aada4fa8aee2decf40b17a7f957d9bf4ff Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 20 Feb 2012 16:20:09 +0000 Subject: [PATCH 143/242] Fixes #6441 (compilation error with BOOST_NO_STD_LOCALE defined) [SVN r77077] --- include/boost/lexical_cast.hpp | 53 +++++-- test/Jamfile.v2 | 1 + test/lexical_cast_no_locale_test.cpp | 166 +++++++++++++++++++++ test/lexical_cast_typedefed_wchar_test.cpp | 1 + 4 files changed, 205 insertions(+), 16 deletions(-) create mode 100755 test/lexical_cast_no_locale_test.cpp diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 4658ab6..398fa25 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1167,7 +1167,7 @@ namespace boost namespace detail { - struct do_not_construct_stringbuffer_t{}; + struct do_not_construct_out_stream_t{}; } namespace detail // optimized stream wrapper @@ -1179,25 +1179,27 @@ namespace boost > class lexical_stream_limited_src { - typedef stl_buf_unlocker, CharT > local_streambuffer_t; #if defined(BOOST_NO_STRINGSTREAM) - typedef stl_buf_unlocker local_stringbuffer_t; + typedef std::ostrstream out_stream_t; + typedef stl_buf_unlocker unlocked_but_t; #elif defined(BOOST_NO_STD_LOCALE) - typedef stl_buf_unlocker local_stringbuffer_t; + typedef std::ostringstream out_stream_t; + typedef stl_buf_unlocker unlocked_but_t; #else - typedef stl_buf_unlocker, CharT > local_stringbuffer_t; + typedef std::basic_ostringstream out_stream_t; + typedef stl_buf_unlocker, CharT> unlocked_but_t; #endif typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< RequiresStringbuffer, - local_stringbuffer_t, - do_not_construct_stringbuffer_t - >::type deduced_stringbuffer_t; + out_stream_t, + do_not_construct_out_stream_t + >::type deduced_out_stream_t; // A string representation of Source is written to [start, finish). CharT* start; CharT* finish; - deduced_stringbuffer_t stringbuffer; + deduced_out_stream_t out_stream; public: lexical_stream_limited_src(CharT* sta, CharT* fin) @@ -1258,10 +1260,16 @@ namespace boost template bool shl_input_streamable(InputStreamable& input) { - std::basic_ostream stream(&stringbuffer); - bool const result = !(stream << input).fail(); - start = stringbuffer.pbase(); - finish = stringbuffer.pptr(); +#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) + // If you have compilation error at this point, than your STL library + // unsupports such conversions. Try updating it. + BOOST_STATIC_ASSERT((boost::is_same::value)); +#endif + bool const result = !(out_stream << input).fail(); + const unlocked_but_t* const p + = static_cast(out_stream.rdbuf()) ; + start = p->pbase(); + finish = p->pptr(); return result; } @@ -1526,9 +1534,22 @@ namespace boost if(is_pointer::value) return false; - local_streambuffer_t bb; - bb.setg(start, start, finish); - std::basic_istream stream(&bb); +#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) + // If you have compilation error at this point, than your STL library + // unsupports such conversions. Try updating it. + BOOST_STATIC_ASSERT((boost::is_same::value)); +#endif + +#if defined(BOOST_NO_STRINGSTREAM) + std::istrstream stream(start, finish - start); +#elif defined(BOOST_NO_STD_LOCALE) + std::istringstream stream; +#else + std::basic_istringstream stream; +#endif + static_cast(stream.rdbuf()) + ->setg(start, start, finish); + stream.unsetf(std::ios::skipws); lcast_set_precision(stream, static_cast(0)); #if (defined _MSC_VER) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c311420..0618516 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -38,5 +38,6 @@ test-suite conversion [ run lexical_cast_pointers_test.cpp ../../test/build//boost_unit_test_framework/static ] [ compile lexical_cast_typedefed_wchar_test.cpp : msvc:on ] [ run lexical_cast_typedefed_wchar_test_runtime.cpp ../../test/build//boost_unit_test_framework/static : : : msvc:on ] + [ run lexical_cast_no_locale_test.cpp ../../test/build//boost_unit_test_framework/static : : : BOOST_NO_STD_LOCALE ] ; diff --git a/test/lexical_cast_no_locale_test.cpp b/test/lexical_cast_no_locale_test.cpp new file mode 100755 index 0000000..3404481 --- /dev/null +++ b/test/lexical_cast_no_locale_test.cpp @@ -0,0 +1,166 @@ +// 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 + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include +#include +#include + +using namespace boost; + +// Testing compilation and some basic usage with BOOST_NO_STD_LOCALE +// Tests are mainly copyied from lexical_cast_empty_input_test.cpp (something +// new added to test_empty_3) + +#ifndef BOOST_NO_STD_LOCALE +#error "This test must be compiled with -DBOOST_NO_STD_LOCALE" +#endif + + +template +void do_test_on_empty_input(T& v) +{ + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); +#if defined(BOOST_HAS_LONG_LONG) + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); +#elif defined(BOOST_HAS_MS_INT64) + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast<__int64>(v), bad_lexical_cast); +#endif +} + +void test_empty_1() +{ + boost::iterator_range v; + do_test_on_empty_input(v); + BOOST_CHECK_EQUAL(lexical_cast(v), std::string()); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + + boost::iterator_range cv; + do_test_on_empty_input(cv); + BOOST_CHECK_EQUAL(lexical_cast(cv), std::string()); + BOOST_CHECK_THROW(lexical_cast(cv), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(cv), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(cv), bad_lexical_cast); + + const boost::iterator_range ccv; + do_test_on_empty_input(ccv); + BOOST_CHECK_EQUAL(lexical_cast(ccv), std::string()); + BOOST_CHECK_THROW(lexical_cast(ccv), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(ccv), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(ccv), bad_lexical_cast); +} + +void test_empty_2() +{ + std::string v; + do_test_on_empty_input(v); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); +} + +struct Escape +{ + Escape(){} + Escape(const std::string& s) + : str_(s) + {} + + std::string str_; +}; + +inline std::ostream& operator<< (std::ostream& o, const Escape& rhs) +{ + return o << rhs.str_; +} + +inline std::istream& operator>> (std::istream& i, Escape& rhs) +{ + return i >> rhs.str_; +} + +void test_empty_3() +{ + Escape v(""); + do_test_on_empty_input(v); + + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + + v = lexical_cast(100); + BOOST_CHECK_EQUAL(lexical_cast(v), 100); + BOOST_CHECK_EQUAL(lexical_cast(v), 100); + + v = lexical_cast(0.0); + BOOST_CHECK_EQUAL(lexical_cast(v), 0.0); +} + +namespace std { +inline std::ostream & operator<<(std::ostream & out, const std::vector & v) +{ + std::ostream_iterator it(out); + std::copy(v.begin(), v.end(), it); + assert(out); + return out; +} +} + +void test_empty_4() +{ + std::vector v; + do_test_on_empty_input(v); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); +} + + +struct my_string { + friend std::ostream &operator<<(std::ostream& sout, my_string const&/* st*/) { + return sout << ""; + } +}; + +void test_empty_5() +{ + my_string st; + BOOST_CHECK_EQUAL(boost::lexical_cast(st), std::string());; +} + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast. Testing with BOOST_NO_STD_LOCALE"); + suite->add(BOOST_TEST_CASE(&test_empty_1)); + suite->add(BOOST_TEST_CASE(&test_empty_2)); + suite->add(BOOST_TEST_CASE(&test_empty_3)); + suite->add(BOOST_TEST_CASE(&test_empty_4)); + suite->add(BOOST_TEST_CASE(&test_empty_5)); + + return suite; +} + diff --git a/test/lexical_cast_typedefed_wchar_test.cpp b/test/lexical_cast_typedefed_wchar_test.cpp index 82f7cc9..2dc0098 100755 --- a/test/lexical_cast_typedefed_wchar_test.cpp +++ b/test/lexical_cast_typedefed_wchar_test.cpp @@ -23,6 +23,7 @@ void parseDate() boost::date_time::special_values_parser svp; boost::gregorian::date date = parser.parse_date(L"", L"", svp); + (void)date; } From 25d880f5ebc1e22ea0c85c86ac6f4a2358107f6d Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sat, 25 Feb 2012 16:58:46 +0000 Subject: [PATCH 144/242] Updates #5800 (partially fix lexical cast compilation with disabled exceptions) [SVN r77116] --- doc/lexical_cast.qbk | 7 +- include/boost/lexical_cast.hpp | 88 ++++++++++------------ test/Jamfile.v2 | 5 +- test/lexical_cast_no_exceptions_test.cpp | 95 ++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 50 deletions(-) create mode 100755 test/lexical_cast_no_exceptions_test.cpp diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index 4715803..5d45446 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -3,7 +3,7 @@ [version 1.0] [copyright 2000-2005 Kevlin Henney] [copyright 2006-2010 Alexander Nasonov] - [copyright 2011 Antony Polukhin] + [copyright 2011-2012 Antony Polukhin] [category String and text processing] [category Miscellaneous] [license @@ -170,6 +170,11 @@ limitation of compiler options that you use. [endsect] [section Changes] +* [*boost 1.50.0 :] + + * `boost::bad_lexical_cast` exception is now globaly visible and can be catched even if code is compiled with -fvisibility=hidden. + * Now it is possible to compile library with disabled exceptions. + * [*boost 1.49.0 :] * Restored work with typedefed wchar_t (compilation flag /Zc:wchar_t- for Visual Studio). diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 398fa25..a68152b 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -104,7 +104,7 @@ _CRTIMP int __cdecl vswprintf(wchar_t * __restrict__ , const wchar_t * __restric namespace boost { // exception used to indicate runtime lexical_cast failure - class bad_lexical_cast : + class BOOST_SYMBOL_VISIBLE bad_lexical_cast : // workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0 #if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS public std::exception @@ -1958,52 +1958,52 @@ namespace boost } }; - class precision_loss_error : public boost::numeric::bad_numeric_cast + template + struct detect_precision_loss { - public: - virtual const char * what() const throw() - { return "bad numeric conversion: precision loss error"; } - }; + typedef boost::numeric::Trunc Rounder; + typedef Source source_type ; - template - struct throw_on_precision_loss - { - typedef boost::numeric::Trunc Rounder; - typedef S source_type ; - - typedef typename mpl::if_< is_arithmetic,S,S const&>::type argument_type ; + typedef BOOST_DEDUCED_TYPENAME mpl::if_< + is_arithmetic, Source, Source const& + >::type argument_type ; static source_type nearbyint ( argument_type s ) { - source_type orig_div_round = s / Rounder::nearbyint(s); + const source_type orig_div_round = s / Rounder::nearbyint(s); + const source_type eps = std::numeric_limits::epsilon(); + + if ((orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > eps) + BOOST_LCAST_THROW_BAD_CAST(Source, Target); - if ( (orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > std::numeric_limits::epsilon() ) - BOOST_THROW_EXCEPTION( precision_loss_error() ); return s ; } typedef typename Rounder::round_style round_style; } ; + template + struct nothrow_overflow_handler + { + void operator() ( boost::numeric::range_check_result r ) + { + if (r != boost::numeric::cInRange) + BOOST_LCAST_THROW_BAD_CAST(Source, Target); + } + } ; + template struct lexical_cast_dynamic_num_not_ignoring_minus { static inline Target lexical_cast_impl(const Source &arg) { - try{ - typedef boost::numeric::converter< - Target, - Source, - boost::numeric::conversion_traits, - boost::numeric::def_overflow_handler, - throw_on_precision_loss - > Converter ; - - return Converter::convert(arg); - } catch( ::boost::numeric::bad_numeric_cast const& ) { - BOOST_LCAST_THROW_BAD_CAST(Source, Target); - } - BOOST_UNREACHABLE_RETURN(static_cast(0)); + return boost::numeric::converter< + Target, + Source, + boost::numeric::conversion_traits, + nothrow_overflow_handler, + detect_precision_loss + >::convert(arg); } }; @@ -2012,25 +2012,17 @@ namespace boost { static inline Target lexical_cast_impl(const Source &arg) { - try{ - typedef boost::numeric::converter< - Target, - Source, - boost::numeric::conversion_traits, - boost::numeric::def_overflow_handler, - throw_on_precision_loss - > Converter ; + typedef boost::numeric::converter< + Target, + Source, + boost::numeric::conversion_traits, + nothrow_overflow_handler, + detect_precision_loss + > converter_t; - bool has_minus = ( arg < 0); - if ( has_minus ) { - return static_cast(-Converter::convert(-arg)); - } else { - return Converter::convert(arg); - } - } catch( ::boost::numeric::bad_numeric_cast const& ) { - BOOST_LCAST_THROW_BAD_CAST(Source, Target); - } - BOOST_UNREACHABLE_RETURN(static_cast(0)); + return ( + arg < 0 ? -converter_t::convert(-arg) : converter_t::convert(arg) + ); } }; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0618516..5078436 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -39,5 +39,8 @@ test-suite conversion [ compile lexical_cast_typedefed_wchar_test.cpp : msvc:on ] [ run lexical_cast_typedefed_wchar_test_runtime.cpp ../../test/build//boost_unit_test_framework/static : : : msvc:on ] [ run lexical_cast_no_locale_test.cpp ../../test/build//boost_unit_test_framework/static : : : BOOST_NO_STD_LOCALE ] + [ run lexical_cast_no_exceptions_test.cpp ../../test/build//boost_unit_test_framework/static : : : BOOST_NO_EXCEPTIONS ] ; - +#Add missing flags, when numeric_cast compilation with exceptions disabled will be fixed: +# [ run lexical_cast_no_exceptions_test.cpp ../../test/build//boost_unit_test_framework/static : : : BOOST_NO_EXCEPTIONS gcc:-fno-exceptions ] + diff --git a/test/lexical_cast_no_exceptions_test.cpp b/test/lexical_cast_no_exceptions_test.cpp new file mode 100755 index 0000000..8431c3a --- /dev/null +++ b/test/lexical_cast_no_exceptions_test.cpp @@ -0,0 +1,95 @@ +// 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 + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include +#include +#include + +#ifndef BOOST_NO_EXCEPTIONS +#error "This test must be compiled with -DBOOST_NO_EXCEPTIONS" +#endif + +bool g_was_exception = false; + +namespace boost { + +void throw_exception(std::exception const & ) { + g_was_exception = true; +} + +} + +using namespace boost; + + +struct Escape +{ + Escape(){} + Escape(const std::string& s) + : str_(s) + {} + + std::string str_; +}; + +inline std::ostream& operator<< (std::ostream& o, const Escape& rhs) +{ + return o << rhs.str_; +} + +inline std::istream& operator>> (std::istream& i, Escape& rhs) +{ + return i >> rhs.str_; +} + +void test_exceptions_off() +{ + Escape v(""); + + g_was_exception = false; + lexical_cast(v); + BOOST_CHECK(g_was_exception); + + g_was_exception = false; + lexical_cast(v); + BOOST_CHECK(g_was_exception); + + v = lexical_cast(100); + BOOST_CHECK_EQUAL(lexical_cast(v), 100); + BOOST_CHECK_EQUAL(lexical_cast(v), 100u); + + v = lexical_cast(0.0); + BOOST_CHECK_EQUAL(lexical_cast(v), 0.0); + + BOOST_CHECK_EQUAL(lexical_cast(100), 100); + BOOST_CHECK_EQUAL(lexical_cast(0.0), 0.0); + + g_was_exception = false; + lexical_cast(700000); + BOOST_CHECK(g_was_exception); +} + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast. Testing with BOOST_NO_EXCEPTIONS"); + suite->add(BOOST_TEST_CASE(&test_exceptions_off)); + + return suite; +} + From 0dded6d3a7d5dd313cb04f7717b6e453f5675799 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sat, 25 Feb 2012 17:32:26 +0000 Subject: [PATCH 145/242] Update for fixed #6441 (unable to compile lexical_cast with BOOST_NO_STD_LOCALE defined) Now test must compile under VC, removed some warnings. [SVN r77117] --- test/Jamfile.v2 | 2 +- test/lexical_cast_no_locale_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5078436..54c1e42 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -38,7 +38,7 @@ test-suite conversion [ run lexical_cast_pointers_test.cpp ../../test/build//boost_unit_test_framework/static ] [ compile lexical_cast_typedefed_wchar_test.cpp : msvc:on ] [ run lexical_cast_typedefed_wchar_test_runtime.cpp ../../test/build//boost_unit_test_framework/static : : : msvc:on ] - [ run lexical_cast_no_locale_test.cpp ../../test/build//boost_unit_test_framework/static : : : BOOST_NO_STD_LOCALE ] + [ run lexical_cast_no_locale_test.cpp ../../test/build//boost_unit_test_framework/static : : : BOOST_NO_STD_LOCALE BOOST_LEXICAL_CAST_ASSUME_C_LOCALE ] [ run lexical_cast_no_exceptions_test.cpp ../../test/build//boost_unit_test_framework/static : : : BOOST_NO_EXCEPTIONS ] ; #Add missing flags, when numeric_cast compilation with exceptions disabled will be fixed: diff --git a/test/lexical_cast_no_locale_test.cpp b/test/lexical_cast_no_locale_test.cpp index 3404481..f3defb3 100755 --- a/test/lexical_cast_no_locale_test.cpp +++ b/test/lexical_cast_no_locale_test.cpp @@ -113,7 +113,7 @@ void test_empty_3() v = lexical_cast(100); BOOST_CHECK_EQUAL(lexical_cast(v), 100); - BOOST_CHECK_EQUAL(lexical_cast(v), 100); + BOOST_CHECK_EQUAL(lexical_cast(v), 100u); v = lexical_cast(0.0); BOOST_CHECK_EQUAL(lexical_cast(v), 0.0); From 83639bd9aee73ef88ea9c9aba075ba427287ce99 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 26 Feb 2012 09:19:55 +0000 Subject: [PATCH 146/242] Fixes #6571 (documentation update, added 'why lexical_cast does not understand "-1.#IND"' question and answer to it) [SVN r77118] --- doc/lexical_cast.qbk | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index 5d45446..4ad8336 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -167,6 +167,14 @@ if a negative number is read, no errors will arise and the result will be the tw `boost::lexical_cast` sees single `wchar_t` character as `unsigned short`. It is not a `boost::lexical_cast` mistake, but a limitation of compiler options that you use. +[pre +] + +* [*Question:] Why `boost::lexical_cast("-1.#IND");` throws `boost::bad_lexical_cast`? + * [*Answer:] `"-1.#IND"` is a compiler extension, that violates standard. You shall input `"-nan"`, `"nan"`, `"inf"` +, `"-inf"` (case insensitive) strings to get NaN and Inf values. `boost::lexical_cast` outputs `"-nan"`, `"nan"`, +`"inf"`, `"-inf"` strings, when has NaN or Inf input values. + [endsect] [section Changes] From 7e7f494dd12230982c1082c350eac29c3649037c Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 4 Mar 2012 17:59:03 +0000 Subject: [PATCH 147/242] Attempt to supress warning described in #6645 (implicit conversion shortens 64-bit value into a 32-bit value) [SVN r77221] --- include/boost/lexical_cast.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index a68152b..b73c741 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -953,7 +953,7 @@ namespace boost CharT const capital_e = lcast_char_constants::capital_e; CharT const lowercase_e = lcast_char_constants::lowercase_e; - value = 0.0; + value = static_cast(0); if (parse_inf_nan(begin, end, value)) return true; From 676bde6e1f3b9e658fd7890b13f203624c14fce5 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 5 Mar 2012 18:44:31 +0000 Subject: [PATCH 148/242] More strict tests for disabled exceptions (for fixed #5800) [SVN r77236] --- test/Jamfile.v2 | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 54c1e42..019c9e7 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -39,8 +39,11 @@ test-suite conversion [ compile lexical_cast_typedefed_wchar_test.cpp : msvc:on ] [ run lexical_cast_typedefed_wchar_test_runtime.cpp ../../test/build//boost_unit_test_framework/static : : : msvc:on ] [ run lexical_cast_no_locale_test.cpp ../../test/build//boost_unit_test_framework/static : : : BOOST_NO_STD_LOCALE BOOST_LEXICAL_CAST_ASSUME_C_LOCALE ] - [ run lexical_cast_no_exceptions_test.cpp ../../test/build//boost_unit_test_framework/static : : : BOOST_NO_EXCEPTIONS ] - ; -#Add missing flags, when numeric_cast compilation with exceptions disabled will be fixed: -# [ run lexical_cast_no_exceptions_test.cpp ../../test/build//boost_unit_test_framework/static : : : BOOST_NO_EXCEPTIONS gcc:-fno-exceptions ] + [ run lexical_cast_no_exceptions_test.cpp ../../test/build//boost_unit_test_framework/static : : : BOOST_NO_EXCEPTIONS + gcc-4.3:-fno-exceptions + gcc-4.4:-fno-exceptions + gcc-4.5:-fno-exceptions + gcc-4.6:-fno-exceptions + ] + ; From 76b9f29c12f668bf76050a0cf14120bab198ad3a Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sat, 24 Mar 2012 19:35:19 +0000 Subject: [PATCH 149/242] Fixes #6663 (much more optimizations for iterator_range, updated documentation and performance test results) [SVN r77517] --- doc/lexical_cast.qbk | 802 ++++++++++++---------- include/boost/lexical_cast.hpp | 108 ++- perf/performance_test.cpp | 15 + test/Jamfile.v2 | 1 + test/lexical_cast_iterator_range_test.cpp | 189 +++++ 5 files changed, 753 insertions(+), 362 deletions(-) create mode 100644 test/lexical_cast_iterator_range_test.cpp diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index 4ad8336..d58f90d 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -115,6 +115,55 @@ Exception used to indicate runtime lexical_cast failure. [endsect] +[section Tuning classes for fast lexical conversions] +Because of `boost::lexical_cast` optimizations for `boost::iterator_range`, it is possibile to make very fast lexical conversions for non zero terminated strings, substrings and user-defined classes. + +Consider the following example: +`` + class example_class { + char non_zero_terminated_data[10]; + std::size_t data_length; + + public: + example_class(); + void fill_data(); + + const char* data() const { + return non_zero_terminated_data; + } + + std::size_t length() const { + return data_length; + } + }; + + inline std::ostream& operator << (std::ostream& ostr, const example_class& rhs) { + return ostr << boost::make_iterator_range(rhs.data(), rhs.data() + rhs.length()); + } +`` + +This is a good generic solution for most use cases. +But we can make it even faster for some performance critical applications. During conversion, we loose speed at: + +* `std::basic_ostream` construction (it makes some heap allocations) +* `operator <<` (it copyies one by one all the symbols to an instance of `std::basic_ostream`) +* `std::basic_ostream` destruction (it makes some heap deallocations) + +We can avoid all of this, by specifieng an overload for `boost::lexical_cast`: +`` +namespace boost { + template + OutT lexical_cast(const example_class& rhs) { + return boost::lexical_cast( + boost::make_iterator_range(rhs.data(), rhs.data() + rhs.length()) + ); + } +} +`` +Now `boost::lexical_cast(example_class_instance)` conversions won't copy data and construct heavy STL stream objects. See [link boost_lexical_cast.performance Performance] section for info on `boost::iterator_range` conversion performance. +[endsect] + + [section Frequently Asked Questions] * [*Question:] Why does `lexical_cast("127")` throw `bad_lexical_cast`? @@ -175,6 +224,9 @@ limitation of compiler options that you use. , `"-inf"` (case insensitive) strings to get NaN and Inf values. `boost::lexical_cast` outputs `"-nan"`, `"nan"`, `"inf"`, `"-inf"` strings, when has NaN or Inf input values. +* [*Question:] What is the fastest way to convert a non zero terminated string or a substring using `boost::lexical_cast`? + * [*Answer:] Use `boost::iterator_range` for conversion. For example, if you whant to convert to `int` two characters from a string `str`, you shall write `lexacal_cast(make_iterator_range(str.c_str(), str.c_str() + 2));`. + [endsect] [section Changes] @@ -182,7 +234,8 @@ limitation of compiler options that you use. * `boost::bad_lexical_cast` exception is now globaly visible and can be catched even if code is compiled with -fvisibility=hidden. * Now it is possible to compile library with disabled exceptions. - + * Better performance, less memory usage and bugfixes for `boost::iterator_range` conversions. + * [*boost 1.49.0 :] * Restored work with typedefed wchar_t (compilation flag /Zc:wchar_t- for Visual Studio). @@ -267,364 +320,415 @@ Do not use this results to compare compilers, because tests were taken on differ [/ BEGIN of section, generated by performance measuring program ] -[section clang-linux-2.8][table:id Performance Table (clang-linux-2.8) +[section Clang version 2.9 (tags/RELEASE_29/final)] +[table:id Performance Table ( Clang version 2.9 (tags/RELEASE_29/final)) [[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]] -[[ string->char ][ !!! *<1* !!! ][ 148 ][ 14 ][ 12 ]] -[[ string->signed char ][ !!! *<1* !!! ][ 97 ][ 8 ][ 7 ]] -[[ string->unsigned char ][ !!! *<1* !!! ][ 90 ][ 8 ][ 13 ]] -[[ string->int ][ !!! *4* !!! ][ 102 ][ 19 ][ 15 ]] -[[ string->short ][ !!! *4* !!! ][ 105 ][ 20 ][ 15 ]] -[[ string->long int ][ !!! *4* !!! ][ 105 ][ 19 ][ 15 ]] -[[ string->long long ][ !!! *4* !!! ][ 115 ][ 19 ][ 14 ]] -[[ string->unsigned int ][ !!! *4* !!! ][ 102 ][ 18 ][ 14 ]] -[[ string->unsigned short ][ !!! *4* !!! ][ 101 ][ 19 ][ 15 ]] -[[ string->unsigned long int ][ !!! *3* !!! ][ 107 ][ 20 ][ 14 ]] -[[ string->unsigned long long ][ !!! *3* !!! ][ 103 ][ 20 ][ 14 ]] -[[ string->bool ][ !!! *<1* !!! ][ 97 ][ 16 ][ 8 ]] -[[ string->float ][ !!! *21* !!! ][ 170 ][ 61 ][ 32 ]] -[[ string->double ][ !!! *18* !!! ][ 206 ][ 93 ][ 58 ]] -[[ string->long double ][ 135 ][ 221 ][ 94 ][ !!! *57* !!! ]] -[[ char->string ][ !!! *7* !!! ][ 100 ][ 17 ][ 13 ]] -[[ unsigned char->string ][ !!! *7* !!! ][ 99 ][ 18 ][ 16 ]] -[[ signed char->string ][ !!! *7* !!! ][ 101 ][ 17 ][ 12 ]] -[[ int->string ][ !!! *13* !!! ][ 110 ][ 23 ][ 15 ]] -[[ short->string ][ !!! *13* !!! ][ 112 ][ 24 ][ 18 ]] -[[ long int->string ][ !!! *13* !!! ][ 119 ][ 23 ][ 17 ]] -[[ long long->string ][ !!! *13* !!! ][ 110 ][ 23 ][ 18 ]] -[[ unsigned int->string ][ !!! *14* !!! ][ 113 ][ 24 ][ 17 ]] -[[ unsigned short->string ][ !!! *13* !!! ][ 108 ][ 24 ][ 17 ]] -[[ unsigned long int->string ][ !!! *13* !!! ][ 109 ][ 24 ][ 16 ]] -[[ unsigned long long->string ][ !!! *13* !!! ][ 110 ][ 23 ][ 17 ]] -[[ bool->string ][ !!! *7* !!! ][ 105 ][ 24 ][ 12 ]] -[[ float->string ][ 70 ][ 192 ][ 94 ][ !!! *49* !!! ]] -[[ double->string ][ 106 ][ 217 ][ 122 ][ !!! *76* !!! ]] -[[ long double->string ][ 120 ][ 219 ][ 123 ][ !!! *80* !!! ]] -[[ char*->char ][ !!! *2* !!! ][ 90 ][ 9 ][ 8 ]] -[[ char*->signed char ][ !!! *2* !!! ][ 87 ][ 10 ][ 7 ]] -[[ char*->unsigned char ][ !!! *3* !!! ][ 90 ][ 10 ][ 13 ]] -[[ char*->int ][ !!! *6* !!! ][ 107 ][ 21 ][ 15 ]] -[[ char*->short ][ !!! *6* !!! ][ 110 ][ 19 ][ 14 ]] -[[ char*->long int ][ !!! *6* !!! ][ 103 ][ 19 ][ 14 ]] -[[ char*->long long ][ !!! *7* !!! ][ 104 ][ 20 ][ 15 ]] -[[ char*->unsigned int ][ !!! *6* !!! ][ 101 ][ 20 ][ 15 ]] -[[ char*->unsigned short ][ !!! *7* !!! ][ 100 ][ 20 ][ 14 ]] -[[ char*->unsigned long int ][ !!! *6* !!! ][ 105 ][ 22 ][ 15 ]] -[[ char*->unsigned long long ][ !!! *7* !!! ][ 106 ][ 21 ][ 14 ]] -[[ char*->bool ][ !!! *2* !!! ][ 99 ][ 18 ][ 7 ]] -[[ char*->float ][ !!! *22* !!! ][ 159 ][ 67 ][ 33 ]] -[[ char*->double ][ !!! *20* !!! ][ 205 ][ 94 ][ 58 ]] -[[ char*->long double ][ 140 ][ 214 ][ 95 ][ !!! *58* !!! ]] -[[ unsigned char*->char ][ !!! *2* !!! ][ 92 ][ 9 ][ 7 ]] -[[ unsigned char*->signed char ][ !!! *2* !!! ][ 89 ][ 10 ][ 7 ]] -[[ unsigned char*->unsigned char ][ !!! *2* !!! ][ 89 ][ 10 ][ 14 ]] -[[ unsigned char*->int ][ !!! *6* !!! ][ 104 ][ 20 ][ 14 ]] -[[ unsigned char*->short ][ !!! *6* !!! ][ 106 ][ 21 ][ 14 ]] -[[ unsigned char*->long int ][ !!! *6* !!! ][ 105 ][ 19 ][ 14 ]] -[[ unsigned char*->long long ][ !!! *6* !!! ][ 106 ][ 20 ][ 15 ]] -[[ unsigned char*->unsigned int ][ !!! *7* !!! ][ 105 ][ 19 ][ 14 ]] -[[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 103 ][ 19 ][ 14 ]] -[[ unsigned char*->unsigned long int ][ !!! *6* !!! ][ 106 ][ 19 ][ 14 ]] -[[ unsigned char*->unsigned long long ][ !!! *6* !!! ][ 104 ][ 21 ][ 15 ]] -[[ unsigned char*->bool ][ !!! *2* !!! ][ 102 ][ 18 ][ 7 ]] -[[ unsigned char*->float ][ !!! *23* !!! ][ 160 ][ 66 ][ 32 ]] -[[ unsigned char*->double ][ !!! *20* !!! ][ 201 ][ 95 ][ 58 ]] -[[ unsigned char*->long double ][ 144 ][ 221 ][ 95 ][ !!! *60* !!! ]] -[[ unsigned char*->string ][ !!! *12* !!! ][ 104 ][ 23 ][ --- ]] -[[ signed char*->char ][ !!! *2* !!! ][ 90 ][ 9 ][ 7 ]] -[[ signed char*->signed char ][ !!! *2* !!! ][ 89 ][ 9 ][ 7 ]] -[[ signed char*->unsigned char ][ !!! *2* !!! ][ 89 ][ 10 ][ 13 ]] -[[ signed char*->int ][ !!! *6* !!! ][ 106 ][ 19 ][ 15 ]] -[[ signed char*->short ][ !!! *6* !!! ][ 107 ][ 20 ][ 15 ]] -[[ signed char*->long int ][ !!! *6* !!! ][ 103 ][ 19 ][ 14 ]] -[[ signed char*->long long ][ !!! *6* !!! ][ 103 ][ 19 ][ 14 ]] -[[ signed char*->unsigned int ][ !!! *6* !!! ][ 101 ][ 19 ][ 15 ]] -[[ signed char*->unsigned short ][ !!! *6* !!! ][ 101 ][ 19 ][ 16 ]] -[[ signed char*->unsigned long int ][ !!! *6* !!! ][ 105 ][ 22 ][ 15 ]] -[[ signed char*->unsigned long long ][ !!! *6* !!! ][ 104 ][ 21 ][ 15 ]] -[[ signed char*->bool ][ !!! *2* !!! ][ 100 ][ 18 ][ 7 ]] -[[ signed char*->float ][ !!! *23* !!! ][ 161 ][ 62 ][ 32 ]] -[[ signed char*->double ][ !!! *20* !!! ][ 207 ][ 102 ][ 57 ]] -[[ signed char*->long double ][ 144 ][ 216 ][ 96 ][ !!! *63* !!! ]] -[[ signed char*->string ][ !!! *12* !!! ][ 104 ][ 23 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 110 ][ 22 ][ --- ]] -[[ float->double ][ !!! *<1* !!! ][ 223 ][ 113 ][ --- ]] -[[ double->double ][ !!! *<1* !!! ][ 227 ][ 111 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 231 ][ 122 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 229 ][ 121 ][ --- ]] -[[ char->unsigned char ][ !!! *<1* !!! ][ 90 ][ 8 ][ --- ]] -[[ char->signed char ][ !!! *<1* !!! ][ 88 ][ 8 ][ --- ]] -[[ unsigned char->char ][ !!! *<1* !!! ][ 89 ][ 8 ][ --- ]] -[[ signed char->char ][ !!! *<1* !!! ][ 91 ][ 9 ][ --- ]] + [[ string->char ][ !!! *<1* !!! ][ 319 ][ 17 ][ 16 ]] + [[ string->signed char ][ !!! *<1* !!! ][ 192 ][ 16 ][ 9 ]] + [[ string->unsigned char ][ !!! *<1* !!! ][ 142 ][ 9 ][ 9 ]] + [[ string->int ][ !!! *7* !!! ][ 109 ][ 21 ][ 16 ]] + [[ string->short ][ !!! *6* !!! ][ 113 ][ 21 ][ 15 ]] + [[ string->long int ][ !!! *7* !!! ][ 110 ][ 22 ][ 15 ]] + [[ string->long long ][ !!! *7* !!! ][ 112 ][ 23 ][ 17 ]] + [[ string->unsigned int ][ !!! *6* !!! ][ 107 ][ 19 ][ 14 ]] + [[ string->unsigned short ][ !!! *6* !!! ][ 106 ][ 18 ][ 16 ]] + [[ string->unsigned long int ][ !!! *7* !!! ][ 108 ][ 20 ][ 15 ]] + [[ string->unsigned long long ][ !!! *7* !!! ][ 109 ][ 22 ][ 15 ]] + [[ string->float ][ !!! *14* !!! ][ 204 ][ 81 ][ 43 ]] + [[ string->double ][ !!! *24* !!! ][ 244 ][ 74 ][ 45 ]] + [[ string->long double ][ 121 ][ 170 ][ 62 ][ !!! *38* !!! ]] + [[ string->string ][ !!! *1* !!! ][ 124 ][ 25 ][ --- ]] + [[ string->container::string ][ !!! *3* !!! ][ 121 ][ 28 ][ --- ]] + [[ string->char ][ 6 ][ 115 ][ 26 ][ !!! *6* !!! ]] + [[ string->signed char ][ !!! *6* !!! ][ 115 ][ 23 ][ 21 ]] + [[ string->unsigned char ][ !!! *6* !!! ][ 113 ][ 25 ][ 22 ]] + [[ int->string ][ !!! *12* !!! ][ 128 ][ 29 ][ 19 ]] + [[ short->string ][ !!! *12* !!! ][ 128 ][ 29 ][ 21 ]] + [[ long int->string ][ !!! *12* !!! ][ 132 ][ 29 ][ 21 ]] + [[ long long->string ][ !!! *12* !!! ][ 127 ][ 29 ][ 22 ]] + [[ unsigned int->string ][ !!! *12* !!! ][ 137 ][ 33 ][ 19 ]] + [[ unsigned short->string ][ !!! *12* !!! ][ 137 ][ 31 ][ 20 ]] + [[ unsigned long int->string ][ !!! *12* !!! ][ 136 ][ 30 ][ 21 ]] + [[ unsigned long long->string ][ !!! *12* !!! ][ 128 ][ 27 ][ 23 ]] + [[ float->string ][ 51 ][ 187 ][ 82 ][ !!! *44* !!! ]] + [[ double->string ][ 56 ][ 190 ][ 83 ][ !!! *42* !!! ]] + [[ long double->string ][ 69 ][ 208 ][ 90 ][ !!! *54* !!! ]] + [[ char*->char ][ !!! *<1* !!! ][ 138 ][ 18 ][ 8 ]] + [[ char*->signed char ][ !!! *8* !!! ][ 126 ][ 10 ][ 9 ]] + [[ char*->unsigned char ][ !!! *<1* !!! ][ 98 ][ 9 ][ 9 ]] + [[ char*->int ][ !!! *8* !!! ][ 113 ][ 22 ][ 15 ]] + [[ char*->short ][ !!! *7* !!! ][ 113 ][ 22 ][ 17 ]] + [[ char*->long int ][ !!! *8* !!! ][ 111 ][ 23 ][ 15 ]] + [[ char*->long long ][ !!! *9* !!! ][ 112 ][ 24 ][ 18 ]] + [[ char*->unsigned int ][ !!! *8* !!! ][ 113 ][ 20 ][ 15 ]] + [[ char*->unsigned short ][ !!! *8* !!! ][ 113 ][ 20 ][ 15 ]] + [[ char*->unsigned long int ][ !!! *8* !!! ][ 112 ][ 21 ][ 16 ]] + [[ char*->unsigned long long ][ !!! *9* !!! ][ 110 ][ 23 ][ 14 ]] + [[ char*->float ][ !!! *14* !!! ][ 149 ][ 54 ][ 32 ]] + [[ char*->double ][ !!! *15* !!! ][ 166 ][ 59 ][ 33 ]] + [[ char*->long double ][ 122 ][ 171 ][ 63 ][ !!! *38* !!! ]] + [[ char*->string ][ !!! *7* !!! ][ 126 ][ 26 ][ --- ]] + [[ char*->container::string ][ !!! *2* !!! ][ 124 ][ 27 ][ --- ]] + [[ unsigned char*->char ][ !!! *<1* !!! ][ 99 ][ 10 ][ 8 ]] + [[ unsigned char*->signed char ][ !!! *<1* !!! ][ 102 ][ 10 ][ 9 ]] + [[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 98 ][ 10 ][ 9 ]] + [[ unsigned char*->int ][ !!! *7* !!! ][ 115 ][ 24 ][ 15 ]] + [[ unsigned char*->short ][ !!! *7* !!! ][ 115 ][ 25 ][ 17 ]] + [[ unsigned char*->long int ][ !!! *8* !!! ][ 115 ][ 22 ][ 16 ]] + [[ unsigned char*->long long ][ !!! *8* !!! ][ 116 ][ 23 ][ 16 ]] + [[ unsigned char*->unsigned int ][ !!! *8* !!! ][ 113 ][ 20 ][ 14 ]] + [[ unsigned char*->unsigned short ][ !!! *7* !!! ][ 114 ][ 21 ][ 15 ]] + [[ unsigned char*->unsigned long int ][ !!! *8* !!! ][ 114 ][ 21 ][ 14 ]] + [[ unsigned char*->unsigned long long ][ !!! *9* !!! ][ 112 ][ 23 ][ 16 ]] + [[ unsigned char*->float ][ !!! *14* !!! ][ 149 ][ 52 ][ 32 ]] + [[ unsigned char*->double ][ !!! *15* !!! ][ 165 ][ 59 ][ 33 ]] + [[ unsigned char*->long double ][ 122 ][ 172 ][ 63 ][ !!! *37* !!! ]] + [[ unsigned char*->string ][ !!! *8* !!! ][ 125 ][ 26 ][ --- ]] + [[ unsigned char*->container::string ][ !!! *4* !!! ][ 119 ][ 26 ][ --- ]] + [[ signed char*->char ][ !!! *<1* !!! ][ 98 ][ 10 ][ 8 ]] + [[ signed char*->signed char ][ !!! *<1* !!! ][ 95 ][ 10 ][ 9 ]] + [[ signed char*->unsigned char ][ !!! *<1* !!! ][ 98 ][ 9 ][ 9 ]] + [[ signed char*->int ][ !!! *8* !!! ][ 111 ][ 21 ][ 15 ]] + [[ signed char*->short ][ !!! *7* !!! ][ 114 ][ 22 ][ 16 ]] + [[ signed char*->long int ][ !!! *8* !!! ][ 113 ][ 22 ][ 17 ]] + [[ signed char*->long long ][ !!! *8* !!! ][ 116 ][ 24 ][ 17 ]] + [[ signed char*->unsigned int ][ !!! *8* !!! ][ 109 ][ 20 ][ 15 ]] + [[ signed char*->unsigned short ][ !!! *8* !!! ][ 111 ][ 20 ][ 14 ]] + [[ signed char*->unsigned long int ][ !!! *8* !!! ][ 109 ][ 22 ][ 15 ]] + [[ signed char*->unsigned long long ][ !!! *8* !!! ][ 111 ][ 23 ][ 15 ]] + [[ signed char*->float ][ !!! *14* !!! ][ 150 ][ 53 ][ 32 ]] + [[ signed char*->double ][ !!! *15* !!! ][ 168 ][ 59 ][ 30 ]] + [[ signed char*->long double ][ 123 ][ 174 ][ 62 ][ !!! *37* !!! ]] + [[ signed char*->string ][ !!! *8* !!! ][ 127 ][ 28 ][ --- ]] + [[ signed char*->container::string ][ !!! *4* !!! ][ 124 ][ 27 ][ --- ]] + [[ iterator_range->char ][ !!! *<1* !!! ][ 103 ][ 13 ][ 8 ]] + [[ iterator_range->signed char ][ !!! *<1* !!! ][ 107 ][ 13 ][ 9 ]] + [[ iterator_range->unsigned char ][ !!! *<1* !!! ][ 121 ][ 26 ][ 13 ]] + [[ iterator_range->int ][ !!! *6* !!! ][ 165 ][ 33 ][ 23 ]] + [[ iterator_range->short ][ !!! *8* !!! ][ 175 ][ 34 ][ 29 ]] + [[ iterator_range->long int ][ !!! *14* !!! ][ 160 ][ 33 ][ 23 ]] + [[ iterator_range->long long ][ !!! *10* !!! ][ 199 ][ 35 ][ 28 ]] + [[ iterator_range->unsigned int ][ !!! *6* !!! ][ 131 ][ 24 ][ 16 ]] + [[ iterator_range->unsigned short ][ !!! *7* !!! ][ 110 ][ 22 ][ 16 ]] + [[ iterator_range->unsigned long int ][ !!! *7* !!! ][ 111 ][ 22 ][ 14 ]] + [[ iterator_range->unsigned long long ][ !!! *8* !!! ][ 115 ][ 24 ][ 15 ]] + [[ iterator_range->float ][ !!! *13* !!! ][ 134 ][ 40 ][ 33 ]] + [[ iterator_range->double ][ !!! *15* !!! ][ 140 ][ 59 ][ 41 ]] + [[ iterator_range->long double ][ 131 ][ 146 ][ 53 ][ !!! *38* !!! ]] + [[ iterator_range->string ][ !!! *9* !!! ][ 121 ][ 31 ][ --- ]] + [[ iterator_range->container::string ][ !!! *4* !!! ][ 115 ][ 25 ][ --- ]] + [[ int->int ][ !!! *<1* !!! ][ 113 ][ 25 ][ --- ]] + [[ float->double ][ !!! *<1* !!! ][ 234 ][ 117 ][ --- ]] + [[ char->signed char ][ !!! *<1* !!! ][ 97 ][ 9 ][ --- ]] ] [endsect] -[section gcc-4.4][table:id Performance Table (gcc-4.4) + +[section GNU C++ version 4.6.1] +[table:id Performance Table ( GNU C++ version 4.6.1) [[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]] -[[ string->char ][ !!! *<1* !!! ][ 90 ][ 7 ][ 7 ]] -[[ string->signed char ][ !!! *<1* !!! ][ 88 ][ 7 ][ 8 ]] -[[ string->unsigned char ][ !!! *<1* !!! ][ 88 ][ 8 ][ 14 ]] -[[ string->int ][ !!! *3* !!! ][ 103 ][ 18 ][ 15 ]] -[[ string->short ][ !!! *3* !!! ][ 105 ][ 20 ][ 15 ]] -[[ string->long int ][ !!! *3* !!! ][ 101 ][ 18 ][ 16 ]] -[[ string->long long ][ !!! *3* !!! ][ 101 ][ 18 ][ 15 ]] -[[ string->unsigned int ][ !!! *3* !!! ][ 98 ][ 23 ][ 14 ]] -[[ string->unsigned short ][ !!! *3* !!! ][ 100 ][ 17 ][ 14 ]] -[[ string->unsigned long int ][ !!! *3* !!! ][ 100 ][ 21 ][ 15 ]] -[[ string->unsigned long long ][ !!! *3* !!! ][ 99 ][ 19 ][ 15 ]] -[[ string->bool ][ !!! *<1* !!! ][ 95 ][ 16 ][ 8 ]] -[[ string->float ][ !!! *13* !!! ][ 160 ][ 61 ][ 33 ]] -[[ string->double ][ !!! *14* !!! ][ 206 ][ 93 ][ 59 ]] -[[ string->long double ][ 128 ][ 217 ][ 96 ][ !!! *61* !!! ]] -[[ char->string ][ !!! *7* !!! ][ 100 ][ 17 ][ 12 ]] -[[ unsigned char->string ][ !!! *7* !!! ][ 109 ][ 17 ][ 16 ]] -[[ signed char->string ][ !!! *7* !!! ][ 99 ][ 17 ][ 12 ]] -[[ int->string ][ !!! *13* !!! ][ 110 ][ 21 ][ 15 ]] -[[ short->string ][ !!! *14* !!! ][ 110 ][ 22 ][ 17 ]] -[[ long int->string ][ !!! *14* !!! ][ 109 ][ 21 ][ 16 ]] -[[ long long->string ][ !!! *13* !!! ][ 114 ][ 20 ][ 17 ]] -[[ unsigned int->string ][ !!! *13* !!! ][ 109 ][ 23 ][ 15 ]] -[[ unsigned short->string ][ !!! *14* !!! ][ 109 ][ 23 ][ 17 ]] -[[ unsigned long int->string ][ !!! *13* !!! ][ 112 ][ 23 ][ 16 ]] -[[ unsigned long long->string ][ !!! *14* !!! ][ 109 ][ 21 ][ 17 ]] -[[ bool->string ][ !!! *7* !!! ][ 108 ][ 23 ][ 11 ]] -[[ float->string ][ 63 ][ 185 ][ 92 ][ !!! *50* !!! ]] -[[ double->string ][ 106 ][ 216 ][ 116 ][ !!! *75* !!! ]] -[[ long double->string ][ 118 ][ 219 ][ 119 ][ !!! *80* !!! ]] -[[ char*->char ][ !!! *1* !!! ][ 93 ][ 9 ][ 9 ]] -[[ char*->signed char ][ !!! *1* !!! ][ 92 ][ 9 ][ 9 ]] -[[ char*->unsigned char ][ !!! *1* !!! ][ 92 ][ 9 ][ 14 ]] -[[ char*->int ][ !!! *4* !!! ][ 107 ][ 19 ][ 15 ]] -[[ char*->short ][ !!! *5* !!! ][ 109 ][ 19 ][ 15 ]] -[[ char*->long int ][ !!! *4* !!! ][ 113 ][ 19 ][ 15 ]] -[[ char*->long long ][ !!! *4* !!! ][ 108 ][ 20 ][ 15 ]] -[[ char*->unsigned int ][ !!! *4* !!! ][ 106 ][ 19 ][ 15 ]] -[[ char*->unsigned short ][ !!! *4* !!! ][ 106 ][ 18 ][ 15 ]] -[[ char*->unsigned long int ][ !!! *4* !!! ][ 103 ][ 22 ][ 15 ]] -[[ char*->unsigned long long ][ !!! *4* !!! ][ 105 ][ 20 ][ 15 ]] -[[ char*->bool ][ !!! *1* !!! ][ 104 ][ 18 ][ 8 ]] -[[ char*->float ][ !!! *15* !!! ][ 164 ][ 62 ][ 33 ]] -[[ char*->double ][ !!! *16* !!! ][ 203 ][ 97 ][ 58 ]] -[[ char*->long double ][ 132 ][ 223 ][ 98 ][ !!! *60* !!! ]] -[[ unsigned char*->char ][ !!! *2* !!! ][ 90 ][ 9 ][ 8 ]] -[[ unsigned char*->signed char ][ !!! *2* !!! ][ 92 ][ 10 ][ 8 ]] -[[ unsigned char*->unsigned char ][ !!! *2* !!! ][ 91 ][ 9 ][ 14 ]] -[[ unsigned char*->int ][ !!! *6* !!! ][ 106 ][ 20 ][ 15 ]] -[[ unsigned char*->short ][ !!! *6* !!! ][ 106 ][ 21 ][ 15 ]] -[[ unsigned char*->long int ][ !!! *6* !!! ][ 111 ][ 19 ][ 15 ]] -[[ unsigned char*->long long ][ !!! *6* !!! ][ 107 ][ 20 ][ 15 ]] -[[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 105 ][ 19 ][ 15 ]] -[[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 103 ][ 18 ][ 15 ]] -[[ unsigned char*->unsigned long int ][ !!! *6* !!! ][ 106 ][ 22 ][ 14 ]] -[[ unsigned char*->unsigned long long ][ !!! *6* !!! ][ 105 ][ 20 ][ 14 ]] -[[ unsigned char*->bool ][ !!! *2* !!! ][ 106 ][ 18 ][ 8 ]] -[[ unsigned char*->float ][ !!! *15* !!! ][ 167 ][ 68 ][ 33 ]] -[[ unsigned char*->double ][ !!! *17* !!! ][ 203 ][ 99 ][ 58 ]] -[[ unsigned char*->long double ][ 129 ][ 216 ][ 97 ][ !!! *61* !!! ]] -[[ unsigned char*->string ][ !!! *13* !!! ][ 111 ][ 23 ][ --- ]] -[[ signed char*->char ][ !!! *2* !!! ][ 92 ][ 9 ][ 8 ]] -[[ signed char*->signed char ][ !!! *2* !!! ][ 91 ][ 9 ][ 8 ]] -[[ signed char*->unsigned char ][ !!! *2* !!! ][ 91 ][ 9 ][ 14 ]] -[[ signed char*->int ][ !!! *6* !!! ][ 107 ][ 19 ][ 15 ]] -[[ signed char*->short ][ !!! *6* !!! ][ 109 ][ 24 ][ 14 ]] -[[ signed char*->long int ][ !!! *6* !!! ][ 112 ][ 19 ][ 15 ]] -[[ signed char*->long long ][ !!! *5* !!! ][ 107 ][ 20 ][ 15 ]] -[[ signed char*->unsigned int ][ !!! *6* !!! ][ 108 ][ 20 ][ 15 ]] -[[ signed char*->unsigned short ][ !!! *6* !!! ][ 104 ][ 18 ][ 15 ]] -[[ signed char*->unsigned long int ][ !!! *6* !!! ][ 102 ][ 22 ][ 15 ]] -[[ signed char*->unsigned long long ][ !!! *6* !!! ][ 104 ][ 20 ][ 15 ]] -[[ signed char*->bool ][ !!! *2* !!! ][ 104 ][ 18 ][ 8 ]] -[[ signed char*->float ][ !!! *16* !!! ][ 165 ][ 63 ][ 33 ]] -[[ signed char*->double ][ !!! *16* !!! ][ 203 ][ 98 ][ 59 ]] -[[ signed char*->long double ][ 129 ][ 215 ][ 98 ][ !!! *61* !!! ]] -[[ signed char*->string ][ !!! *13* !!! ][ 109 ][ 21 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 109 ][ 21 ][ --- ]] -[[ float->double ][ !!! *<1* !!! ][ 221 ][ 102 ][ --- ]] -[[ double->double ][ !!! *<1* !!! ][ 223 ][ 103 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 231 ][ 115 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 231 ][ 115 ][ --- ]] -[[ char->unsigned char ][ !!! *<1* !!! ][ 92 ][ 8 ][ --- ]] -[[ char->signed char ][ !!! *<1* !!! ][ 88 ][ 8 ][ --- ]] -[[ unsigned char->char ][ !!! *<1* !!! ][ 88 ][ 7 ][ --- ]] -[[ signed char->char ][ !!! *<1* !!! ][ 89 ][ 8 ][ --- ]] + [[ string->char ][ !!! *<1* !!! ][ 140 ][ 17 ][ 13 ]] + [[ string->signed char ][ !!! *<1* !!! ][ 129 ][ 8 ][ 10 ]] + [[ string->unsigned char ][ !!! *<1* !!! ][ 91 ][ 8 ][ 10 ]] + [[ string->int ][ !!! *6* !!! ][ 110 ][ 20 ][ 14 ]] + [[ string->short ][ !!! *5* !!! ][ 106 ][ 20 ][ 14 ]] + [[ string->long int ][ !!! *7* !!! ][ 107 ][ 22 ][ 14 ]] + [[ string->long long ][ !!! *7* !!! ][ 112 ][ 21 ][ 14 ]] + [[ string->unsigned int ][ !!! *6* !!! ][ 110 ][ 20 ][ 14 ]] + [[ string->unsigned short ][ !!! *5* !!! ][ 107 ][ 18 ][ 14 ]] + [[ string->unsigned long int ][ !!! *7* !!! ][ 108 ][ 23 ][ 14 ]] + [[ string->unsigned long long ][ !!! *7* !!! ][ 108 ][ 21 ][ 14 ]] + [[ string->float ][ !!! *12* !!! ][ 154 ][ 57 ][ 32 ]] + [[ string->double ][ !!! *11* !!! ][ 151 ][ 61 ][ 33 ]] + [[ string->long double ][ 109 ][ 187 ][ 79 ][ !!! *55* !!! ]] + [[ string->string ][ !!! *2* !!! ][ 122 ][ 27 ][ --- ]] + [[ string->container::string ][ !!! *3* !!! ][ 123 ][ 22 ][ --- ]] + [[ string->char ][ !!! *7* !!! ][ 109 ][ 27 ][ 17 ]] + [[ string->signed char ][ !!! *7* !!! ][ 110 ][ 25 ][ 22 ]] + [[ string->unsigned char ][ !!! *7* !!! ][ 112 ][ 27 ][ 24 ]] + [[ int->string ][ !!! *12* !!! ][ 187 ][ 48 ][ 37 ]] + [[ short->string ][ !!! *18* !!! ][ 133 ][ 33 ][ 20 ]] + [[ long int->string ][ !!! *12* !!! ][ 129 ][ 32 ][ 21 ]] + [[ long long->string ][ !!! *12* !!! ][ 127 ][ 35 ][ 23 ]] + [[ unsigned int->string ][ !!! *15* !!! ][ 133 ][ 31 ][ 21 ]] + [[ unsigned short->string ][ !!! *12* !!! ][ 133 ][ 31 ][ 21 ]] + [[ unsigned long int->string ][ !!! *12* !!! ][ 132 ][ 31 ][ 21 ]] + [[ unsigned long long->string ][ !!! *12* !!! ][ 127 ][ 29 ][ 24 ]] + [[ float->string ][ 53 ][ 215 ][ 103 ][ !!! *40* !!! ]] + [[ double->string ][ 58 ][ 215 ][ 103 ][ !!! *41* !!! ]] + [[ long double->string ][ 67 ][ 227 ][ 112 ][ !!! *45* !!! ]] + [[ char*->char ][ !!! *<1* !!! ][ 132 ][ 12 ][ 8 ]] + [[ char*->signed char ][ !!! *<1* !!! ][ 98 ][ 11 ][ 9 ]] + [[ char*->unsigned char ][ !!! *<1* !!! ][ 96 ][ 10 ][ 9 ]] + [[ char*->int ][ !!! *6* !!! ][ 109 ][ 22 ][ 14 ]] + [[ char*->short ][ !!! *5* !!! ][ 109 ][ 26 ][ 14 ]] + [[ char*->long int ][ !!! *7* !!! ][ 111 ][ 23 ][ 14 ]] + [[ char*->long long ][ !!! *8* !!! ][ 112 ][ 25 ][ 16 ]] + [[ char*->unsigned int ][ !!! *6* !!! ][ 113 ][ 19 ][ 14 ]] + [[ char*->unsigned short ][ !!! *6* !!! ][ 111 ][ 20 ][ 14 ]] + [[ char*->unsigned long int ][ !!! *7* !!! ][ 109 ][ 21 ][ 14 ]] + [[ char*->unsigned long long ][ !!! *7* !!! ][ 111 ][ 22 ][ 14 ]] + [[ char*->float ][ !!! *12* !!! ][ 156 ][ 62 ][ 32 ]] + [[ char*->double ][ !!! *13* !!! ][ 156 ][ 65 ][ 33 ]] + [[ char*->long double ][ 108 ][ 156 ][ 59 ][ !!! *36* !!! ]] + [[ char*->string ][ !!! *7* !!! ][ 123 ][ 29 ][ --- ]] + [[ char*->container::string ][ !!! *2* !!! ][ 116 ][ 24 ][ --- ]] + [[ unsigned char*->char ][ !!! *<1* !!! ][ 96 ][ 12 ][ 8 ]] + [[ unsigned char*->signed char ][ !!! *<1* !!! ][ 97 ][ 9 ][ 9 ]] + [[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 93 ][ 10 ][ 9 ]] + [[ unsigned char*->int ][ !!! *6* !!! ][ 110 ][ 22 ][ 14 ]] + [[ unsigned char*->short ][ !!! *6* !!! ][ 111 ][ 22 ][ 15 ]] + [[ unsigned char*->long int ][ !!! *8* !!! ][ 110 ][ 23 ][ 14 ]] + [[ unsigned char*->long long ][ !!! *7* !!! ][ 111 ][ 25 ][ 14 ]] + [[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 111 ][ 21 ][ 16 ]] + [[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 110 ][ 21 ][ 15 ]] + [[ unsigned char*->unsigned long int ][ !!! *8* !!! ][ 114 ][ 21 ][ 14 ]] + [[ unsigned char*->unsigned long long ][ !!! *8* !!! ][ 108 ][ 23 ][ 15 ]] + [[ unsigned char*->float ][ !!! *12* !!! ][ 154 ][ 62 ][ 33 ]] + [[ unsigned char*->double ][ !!! *14* !!! ][ 157 ][ 65 ][ 32 ]] + [[ unsigned char*->long double ][ 107 ][ 154 ][ 56 ][ !!! *36* !!! ]] + [[ unsigned char*->string ][ !!! *9* !!! ][ 122 ][ 28 ][ --- ]] + [[ unsigned char*->container::string ][ !!! *4* !!! ][ 118 ][ 26 ][ --- ]] + [[ signed char*->char ][ !!! *<1* !!! ][ 94 ][ 10 ][ 8 ]] + [[ signed char*->signed char ][ !!! *<1* !!! ][ 94 ][ 12 ][ 9 ]] + [[ signed char*->unsigned char ][ !!! *<1* !!! ][ 95 ][ 12 ][ 9 ]] + [[ signed char*->int ][ !!! *7* !!! ][ 109 ][ 22 ][ 14 ]] + [[ signed char*->short ][ !!! *5* !!! ][ 108 ][ 22 ][ 14 ]] + [[ signed char*->long int ][ !!! *7* !!! ][ 110 ][ 23 ][ 14 ]] + [[ signed char*->long long ][ !!! *7* !!! ][ 110 ][ 25 ][ 15 ]] + [[ signed char*->unsigned int ][ !!! *6* !!! ][ 109 ][ 20 ][ 15 ]] + [[ signed char*->unsigned short ][ !!! *6* !!! ][ 107 ][ 21 ][ 14 ]] + [[ signed char*->unsigned long int ][ !!! *8* !!! ][ 111 ][ 21 ][ 14 ]] + [[ signed char*->unsigned long long ][ !!! *7* !!! ][ 109 ][ 23 ][ 14 ]] + [[ signed char*->float ][ !!! *12* !!! ][ 156 ][ 61 ][ 31 ]] + [[ signed char*->double ][ !!! *13* !!! ][ 156 ][ 68 ][ 33 ]] + [[ signed char*->long double ][ 109 ][ 159 ][ 56 ][ !!! *36* !!! ]] + [[ signed char*->string ][ !!! *9* !!! ][ 123 ][ 28 ][ --- ]] + [[ signed char*->container::string ][ !!! *4* !!! ][ 125 ][ 25 ][ --- ]] + [[ iterator_range->char ][ !!! *<1* !!! ][ 100 ][ 13 ][ 8 ]] + [[ iterator_range->signed char ][ !!! *<1* !!! ][ 98 ][ 14 ][ 9 ]] + [[ iterator_range->unsigned char ][ !!! *<1* !!! ][ 99 ][ 12 ][ 10 ]] + [[ iterator_range->int ][ !!! *6* !!! ][ 108 ][ 21 ][ 16 ]] + [[ iterator_range->short ][ !!! *5* !!! ][ 110 ][ 22 ][ 17 ]] + [[ iterator_range->long int ][ !!! *7* !!! ][ 107 ][ 22 ][ 15 ]] + [[ iterator_range->long long ][ !!! *7* !!! ][ 110 ][ 27 ][ 15 ]] + [[ iterator_range->unsigned int ][ !!! *6* !!! ][ 107 ][ 24 ][ 15 ]] + [[ iterator_range->unsigned short ][ !!! *5* !!! ][ 106 ][ 21 ][ 15 ]] + [[ iterator_range->unsigned long int ][ !!! *7* !!! ][ 110 ][ 21 ][ 16 ]] + [[ iterator_range->unsigned long long ][ !!! *7* !!! ][ 109 ][ 23 ][ 16 ]] + [[ iterator_range->float ][ !!! *11* !!! ][ 137 ][ 46 ][ 33 ]] + [[ iterator_range->double ][ !!! *11* !!! ][ 131 ][ 50 ][ 33 ]] + [[ iterator_range->long double ][ 107 ][ 136 ][ 44 ][ !!! *39* !!! ]] + [[ iterator_range->string ][ !!! *8* !!! ][ 117 ][ 32 ][ --- ]] + [[ iterator_range->container::string ][ !!! *3* !!! ][ 111 ][ 23 ][ --- ]] + [[ int->int ][ !!! *<1* !!! ][ 110 ][ 33 ][ --- ]] + [[ float->double ][ !!! *<1* !!! ][ 241 ][ 152 ][ --- ]] + [[ char->signed char ][ !!! *<1* !!! ][ 90 ][ 8 ][ --- ]] ] [endsect] -[section gcc-4.5][table:id Performance Table (gcc-4.5) + +[section GNU C++ version 4.5.4] +[table:id Performance Table ( GNU C++ version 4.5.4) [[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]] -[[ string->char ][ !!! *<1* !!! ][ 91 ][ 8 ][ 7 ]] -[[ string->signed char ][ !!! *<1* !!! ][ 91 ][ 8 ][ 7 ]] -[[ string->unsigned char ][ !!! *<1* !!! ][ 90 ][ 8 ][ 13 ]] -[[ string->int ][ !!! *3* !!! ][ 100 ][ 20 ][ 14 ]] -[[ string->short ][ !!! *3* !!! ][ 106 ][ 20 ][ 14 ]] -[[ string->long int ][ !!! *3* !!! ][ 100 ][ 18 ][ 14 ]] -[[ string->long long ][ !!! *9* !!! ][ 100 ][ 18 ][ 15 ]] -[[ string->unsigned int ][ !!! *3* !!! ][ 97 ][ 20 ][ 14 ]] -[[ string->unsigned short ][ !!! *3* !!! ][ 102 ][ 17 ][ 14 ]] -[[ string->unsigned long int ][ !!! *3* !!! ][ 97 ][ 21 ][ 14 ]] -[[ string->unsigned long long ][ !!! *3* !!! ][ 97 ][ 19 ][ 14 ]] -[[ string->bool ][ !!! *<1* !!! ][ 95 ][ 16 ][ 7 ]] -[[ string->float ][ !!! *15* !!! ][ 157 ][ 63 ][ 32 ]] -[[ string->double ][ !!! *17* !!! ][ 203 ][ 95 ][ 59 ]] -[[ string->long double ][ 129 ][ 216 ][ 93 ][ !!! *58* !!! ]] -[[ char->string ][ !!! *8* !!! ][ 100 ][ 17 ][ 10 ]] -[[ unsigned char->string ][ !!! *8* !!! ][ 96 ][ 18 ][ 16 ]] -[[ signed char->string ][ !!! *8* !!! ][ 96 ][ 18 ][ 10 ]] -[[ int->string ][ !!! *14* !!! ][ 105 ][ 22 ][ 15 ]] -[[ short->string ][ !!! *14* !!! ][ 107 ][ 23 ][ 17 ]] -[[ long int->string ][ !!! *14* !!! ][ 109 ][ 22 ][ 17 ]] -[[ long long->string ][ !!! *14* !!! ][ 105 ][ 22 ][ 18 ]] -[[ unsigned int->string ][ !!! *14* !!! ][ 105 ][ 25 ][ 15 ]] -[[ unsigned short->string ][ !!! *15* !!! ][ 105 ][ 23 ][ 17 ]] -[[ unsigned long int->string ][ !!! *14* !!! ][ 109 ][ 24 ][ 17 ]] -[[ unsigned long long->string ][ !!! *14* !!! ][ 102 ][ 23 ][ 17 ]] -[[ bool->string ][ !!! *8* !!! ][ 104 ][ 23 ][ 12 ]] -[[ float->string ][ 66 ][ 181 ][ 92 ][ !!! *49* !!! ]] -[[ double->string ][ 107 ][ 215 ][ 120 ][ !!! *75* !!! ]] -[[ long double->string ][ 117 ][ 221 ][ 125 ][ !!! *79* !!! ]] -[[ char*->char ][ !!! *1* !!! ][ 89 ][ 9 ][ 7 ]] -[[ char*->signed char ][ !!! *1* !!! ][ 90 ][ 9 ][ 7 ]] -[[ char*->unsigned char ][ !!! *2* !!! ][ 90 ][ 9 ][ 13 ]] -[[ char*->int ][ !!! *7* !!! ][ 103 ][ 20 ][ 15 ]] -[[ char*->short ][ !!! *6* !!! ][ 102 ][ 29 ][ 14 ]] -[[ char*->long int ][ !!! *7* !!! ][ 101 ][ 20 ][ 15 ]] -[[ char*->long long ][ !!! *6* !!! ][ 102 ][ 20 ][ 14 ]] -[[ char*->unsigned int ][ !!! *6* !!! ][ 99 ][ 19 ][ 14 ]] -[[ char*->unsigned short ][ !!! *6* !!! ][ 101 ][ 18 ][ 14 ]] -[[ char*->unsigned long int ][ !!! *6* !!! ][ 102 ][ 22 ][ 14 ]] -[[ char*->unsigned long long ][ !!! *6* !!! ][ 101 ][ 21 ][ 14 ]] -[[ char*->bool ][ !!! *3* !!! ][ 98 ][ 18 ][ 7 ]] -[[ char*->float ][ !!! *18* !!! ][ 162 ][ 63 ][ 31 ]] -[[ char*->double ][ !!! *17* !!! ][ 203 ][ 96 ][ 58 ]] -[[ char*->long double ][ 135 ][ 214 ][ 98 ][ !!! *58* !!! ]] -[[ unsigned char*->char ][ !!! *2* !!! ][ 87 ][ 9 ][ 7 ]] -[[ unsigned char*->signed char ][ !!! *2* !!! ][ 87 ][ 9 ][ 7 ]] -[[ unsigned char*->unsigned char ][ !!! *3* !!! ][ 87 ][ 9 ][ 13 ]] -[[ unsigned char*->int ][ !!! *6* !!! ][ 105 ][ 20 ][ 14 ]] -[[ unsigned char*->short ][ !!! *6* !!! ][ 102 ][ 21 ][ 14 ]] -[[ unsigned char*->long int ][ !!! *6* !!! ][ 101 ][ 20 ][ 14 ]] -[[ unsigned char*->long long ][ !!! *6* !!! ][ 102 ][ 20 ][ 14 ]] -[[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 99 ][ 19 ][ 14 ]] -[[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 100 ][ 18 ][ 14 ]] -[[ unsigned char*->unsigned long int ][ !!! *6* !!! ][ 101 ][ 24 ][ 14 ]] -[[ unsigned char*->unsigned long long ][ !!! *6* !!! ][ 100 ][ 20 ][ 14 ]] -[[ unsigned char*->bool ][ !!! *3* !!! ][ 99 ][ 18 ][ 8 ]] -[[ unsigned char*->float ][ !!! *17* !!! ][ 164 ][ 64 ][ 32 ]] -[[ unsigned char*->double ][ !!! *18* !!! ][ 201 ][ 94 ][ 58 ]] -[[ unsigned char*->long double ][ 133 ][ 217 ][ 95 ][ !!! *60* !!! ]] -[[ unsigned char*->string ][ !!! *14* !!! ][ 103 ][ 23 ][ --- ]] -[[ signed char*->char ][ !!! *3* !!! ][ 88 ][ 10 ][ 8 ]] -[[ signed char*->signed char ][ !!! *2* !!! ][ 87 ][ 10 ][ 7 ]] -[[ signed char*->unsigned char ][ !!! *3* !!! ][ 87 ][ 9 ][ 13 ]] -[[ signed char*->int ][ !!! *6* !!! ][ 104 ][ 20 ][ 14 ]] -[[ signed char*->short ][ !!! *6* !!! ][ 105 ][ 21 ][ 14 ]] -[[ signed char*->long int ][ !!! *6* !!! ][ 104 ][ 20 ][ 15 ]] -[[ signed char*->long long ][ !!! *6* !!! ][ 106 ][ 20 ][ 14 ]] -[[ signed char*->unsigned int ][ !!! *6* !!! ][ 99 ][ 20 ][ 14 ]] -[[ signed char*->unsigned short ][ !!! *6* !!! ][ 100 ][ 18 ][ 14 ]] -[[ signed char*->unsigned long int ][ !!! *6* !!! ][ 102 ][ 23 ][ 14 ]] -[[ signed char*->unsigned long long ][ !!! *6* !!! ][ 103 ][ 20 ][ 14 ]] -[[ signed char*->bool ][ !!! *3* !!! ][ 99 ][ 18 ][ 7 ]] -[[ signed char*->float ][ !!! *18* !!! ][ 159 ][ 60 ][ 32 ]] -[[ signed char*->double ][ !!! *18* !!! ][ 203 ][ 95 ][ 57 ]] -[[ signed char*->long double ][ 129 ][ 213 ][ 97 ][ !!! *56* !!! ]] -[[ signed char*->string ][ !!! *14* !!! ][ 105 ][ 22 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 109 ][ 22 ][ --- ]] -[[ float->double ][ !!! *<1* !!! ][ 226 ][ 104 ][ --- ]] -[[ double->double ][ !!! *<1* !!! ][ 229 ][ 103 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 225 ][ 115 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 227 ][ 115 ][ --- ]] -[[ char->unsigned char ][ !!! *<1* !!! ][ 90 ][ 8 ][ --- ]] -[[ char->signed char ][ !!! *<1* !!! ][ 84 ][ 8 ][ --- ]] -[[ unsigned char->char ][ !!! *<1* !!! ][ 88 ][ 8 ][ --- ]] -[[ signed char->char ][ !!! *<1* !!! ][ 89 ][ 8 ][ --- ]] + [[ string->char ][ !!! *<1* !!! ][ 147 ][ 12 ][ 8 ]] + [[ string->signed char ][ !!! *<1* !!! ][ 138 ][ 13 ][ 10 ]] + [[ string->unsigned char ][ !!! *<1* !!! ][ 86 ][ 12 ][ 9 ]] + [[ string->int ][ !!! *7* !!! ][ 103 ][ 20 ][ 15 ]] + [[ string->short ][ !!! *5* !!! ][ 103 ][ 20 ][ 15 ]] + [[ string->long int ][ !!! *7* !!! ][ 103 ][ 22 ][ 15 ]] + [[ string->long long ][ !!! *7* !!! ][ 104 ][ 22 ][ 16 ]] + [[ string->unsigned int ][ !!! *6* !!! ][ 108 ][ 19 ][ 15 ]] + [[ string->unsigned short ][ !!! *5* !!! ][ 104 ][ 19 ][ 15 ]] + [[ string->unsigned long int ][ !!! *7* !!! ][ 103 ][ 20 ][ 16 ]] + [[ string->unsigned long long ][ !!! *7* !!! ][ 101 ][ 22 ][ 14 ]] + [[ string->float ][ !!! *13* !!! ][ 148 ][ 58 ][ 35 ]] + [[ string->double ][ !!! *13* !!! ][ 147 ][ 60 ][ 34 ]] + [[ string->long double ][ 103 ][ 149 ][ 56 ][ !!! *38* !!! ]] + [[ string->string ][ !!! *2* !!! ][ 127 ][ 27 ][ --- ]] + [[ string->container::string ][ !!! *3* !!! ][ 101 ][ 24 ][ --- ]] + [[ string->char ][ !!! *7* !!! ][ 108 ][ 35 ][ 17 ]] + [[ string->signed char ][ !!! *7* !!! ][ 112 ][ 26 ][ 23 ]] + [[ string->unsigned char ][ !!! *7* !!! ][ 113 ][ 25 ][ 25 ]] + [[ int->string ][ !!! *11* !!! ][ 183 ][ 47 ][ 40 ]] + [[ short->string ][ !!! *14* !!! ][ 153 ][ 35 ][ 23 ]] + [[ long int->string ][ !!! *12* !!! ][ 135 ][ 32 ][ 22 ]] + [[ long long->string ][ !!! *11* !!! ][ 131 ][ 30 ][ 24 ]] + [[ unsigned int->string ][ !!! *12* !!! ][ 137 ][ 31 ][ 22 ]] + [[ unsigned short->string ][ !!! *11* !!! ][ 137 ][ 33 ][ 22 ]] + [[ unsigned long int->string ][ !!! *11* !!! ][ 136 ][ 36 ][ 23 ]] + [[ unsigned long long->string ][ !!! *11* !!! ][ 127 ][ 29 ][ 23 ]] + [[ float->string ][ 56 ][ 218 ][ 107 ][ !!! *44* !!! ]] + [[ double->string ][ 63 ][ 223 ][ 106 ][ !!! *44* !!! ]] + [[ long double->string ][ 69 ][ 229 ][ 118 ][ !!! *49* !!! ]] + [[ char*->char ][ !!! *<1* !!! ][ 91 ][ 12 ][ 9 ]] + [[ char*->signed char ][ !!! *<1* !!! ][ 100 ][ 11 ][ 11 ]] + [[ char*->unsigned char ][ !!! *<1* !!! ][ 97 ][ 12 ][ 10 ]] + [[ char*->int ][ !!! *7* !!! ][ 112 ][ 23 ][ 16 ]] + [[ char*->short ][ !!! *6* !!! ][ 116 ][ 23 ][ 16 ]] + [[ char*->long int ][ !!! *8* !!! ][ 113 ][ 23 ][ 16 ]] + [[ char*->long long ][ !!! *8* !!! ][ 122 ][ 28 ][ 16 ]] + [[ char*->unsigned int ][ !!! *6* !!! ][ 117 ][ 21 ][ 15 ]] + [[ char*->unsigned short ][ !!! *6* !!! ][ 113 ][ 21 ][ 16 ]] + [[ char*->unsigned long int ][ !!! *7* !!! ][ 118 ][ 22 ][ 16 ]] + [[ char*->unsigned long long ][ !!! *8* !!! ][ 113 ][ 22 ][ 17 ]] + [[ char*->float ][ !!! *11* !!! ][ 164 ][ 67 ][ 34 ]] + [[ char*->double ][ !!! *13* !!! ][ 163 ][ 66 ][ 35 ]] + [[ char*->long double ][ 110 ][ 164 ][ 63 ][ !!! *39* !!! ]] + [[ char*->string ][ !!! *8* !!! ][ 130 ][ 30 ][ --- ]] + [[ char*->container::string ][ !!! *2* !!! ][ 113 ][ 24 ][ --- ]] + [[ unsigned char*->char ][ !!! *<1* !!! ][ 98 ][ 11 ][ 10 ]] + [[ unsigned char*->signed char ][ !!! *<1* !!! ][ 97 ][ 12 ][ 10 ]] + [[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 97 ][ 11 ][ 10 ]] + [[ unsigned char*->int ][ !!! *7* !!! ][ 112 ][ 23 ][ 16 ]] + [[ unsigned char*->short ][ !!! *6* !!! ][ 115 ][ 22 ][ 20 ]] + [[ unsigned char*->long int ][ !!! *8* !!! ][ 112 ][ 23 ][ 15 ]] + [[ unsigned char*->long long ][ !!! *8* !!! ][ 115 ][ 29 ][ 17 ]] + [[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 114 ][ 21 ][ 14 ]] + [[ unsigned char*->unsigned short ][ !!! *7* !!! ][ 112 ][ 22 ][ 15 ]] + [[ unsigned char*->unsigned long int ][ !!! *7* !!! ][ 115 ][ 23 ][ 14 ]] + [[ unsigned char*->unsigned long long ][ !!! *8* !!! ][ 112 ][ 24 ][ 15 ]] + [[ unsigned char*->float ][ !!! *12* !!! ][ 161 ][ 66 ][ 34 ]] + [[ unsigned char*->double ][ !!! *13* !!! ][ 162 ][ 66 ][ 36 ]] + [[ unsigned char*->long double ][ 112 ][ 161 ][ 63 ][ !!! *39* !!! ]] + [[ unsigned char*->string ][ !!! *9* !!! ][ 127 ][ 29 ][ --- ]] + [[ unsigned char*->container::string ][ !!! *4* !!! ][ 111 ][ 25 ][ --- ]] + [[ signed char*->char ][ !!! *<1* !!! ][ 104 ][ 11 ][ 8 ]] + [[ signed char*->signed char ][ !!! *<1* !!! ][ 98 ][ 11 ][ 11 ]] + [[ signed char*->unsigned char ][ !!! *<1* !!! ][ 98 ][ 11 ][ 11 ]] + [[ signed char*->int ][ !!! *7* !!! ][ 112 ][ 23 ][ 16 ]] + [[ signed char*->short ][ !!! *7* !!! ][ 113 ][ 23 ][ 15 ]] + [[ signed char*->long int ][ !!! *8* !!! ][ 112 ][ 22 ][ 14 ]] + [[ signed char*->long long ][ !!! *8* !!! ][ 115 ][ 25 ][ 16 ]] + [[ signed char*->unsigned int ][ !!! *8* !!! ][ 114 ][ 21 ][ 18 ]] + [[ signed char*->unsigned short ][ !!! *6* !!! ][ 112 ][ 22 ][ 15 ]] + [[ signed char*->unsigned long int ][ !!! *8* !!! ][ 116 ][ 22 ][ 15 ]] + [[ signed char*->unsigned long long ][ !!! *8* !!! ][ 113 ][ 23 ][ 16 ]] + [[ signed char*->float ][ !!! *13* !!! ][ 161 ][ 65 ][ 34 ]] + [[ signed char*->double ][ !!! *12* !!! ][ 172 ][ 67 ][ 34 ]] + [[ signed char*->long double ][ 110 ][ 164 ][ 63 ][ !!! *38* !!! ]] + [[ signed char*->string ][ !!! *9* !!! ][ 131 ][ 30 ][ --- ]] + [[ signed char*->container::string ][ !!! *4* !!! ][ 112 ][ 24 ][ --- ]] + [[ iterator_range->char ][ !!! *<1* !!! ][ 103 ][ 12 ][ 8 ]] + [[ iterator_range->signed char ][ !!! *<1* !!! ][ 101 ][ 13 ][ 9 ]] + [[ iterator_range->unsigned char ][ !!! *<1* !!! ][ 103 ][ 13 ][ 10 ]] + [[ iterator_range->int ][ !!! *7* !!! ][ 113 ][ 26 ][ 14 ]] + [[ iterator_range->short ][ !!! *5* !!! ][ 115 ][ 21 ][ 16 ]] + [[ iterator_range->long int ][ !!! *7* !!! ][ 115 ][ 22 ][ 15 ]] + [[ iterator_range->long long ][ !!! *7* !!! ][ 116 ][ 25 ][ 16 ]] + [[ iterator_range->unsigned int ][ !!! *6* !!! ][ 115 ][ 24 ][ 23 ]] + [[ iterator_range->unsigned short ][ !!! *5* !!! ][ 113 ][ 22 ][ 16 ]] + [[ iterator_range->unsigned long int ][ !!! *7* !!! ][ 117 ][ 20 ][ 16 ]] + [[ iterator_range->unsigned long long ][ !!! *7* !!! ][ 114 ][ 21 ][ 16 ]] + [[ iterator_range->float ][ !!! *11* !!! ][ 145 ][ 51 ][ 34 ]] + [[ iterator_range->double ][ !!! *11* !!! ][ 139 ][ 53 ][ 35 ]] + [[ iterator_range->long double ][ 109 ][ 147 ][ 44 ][ !!! *38* !!! ]] + [[ iterator_range->string ][ !!! *9* !!! ][ 123 ][ 36 ][ --- ]] + [[ iterator_range->container::string ][ !!! *3* !!! ][ 113 ][ 20 ][ --- ]] + [[ int->int ][ !!! *<1* !!! ][ 117 ][ 23 ][ --- ]] + [[ float->double ][ !!! *<1* !!! ][ 262 ][ 150 ][ --- ]] + [[ char->signed char ][ !!! *<1* !!! ][ 97 ][ 9 ][ --- ]] ] [endsect] -[section gcc-4.6][table:id Performance Table (gcc-4.6) + +[section GNU C++ version 4.4.6] +[table:id Performance Table ( GNU C++ version 4.4.6) [[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]] -[[ string->char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 7 ]] -[[ string->signed char ][ !!! *<1* !!! ][ 96 ][ 9 ][ 7 ]] -[[ string->unsigned char ][ !!! *<1* !!! ][ 96 ][ 8 ][ 13 ]] -[[ string->int ][ !!! *3* !!! ][ 110 ][ 18 ][ 16 ]] -[[ string->short ][ !!! *3* !!! ][ 111 ][ 18 ][ 16 ]] -[[ string->long int ][ !!! *3* !!! ][ 109 ][ 18 ][ 15 ]] -[[ string->long long ][ !!! *3* !!! ][ 111 ][ 18 ][ 15 ]] -[[ string->unsigned int ][ !!! *3* !!! ][ 110 ][ 20 ][ 15 ]] -[[ string->unsigned short ][ !!! *3* !!! ][ 111 ][ 18 ][ 15 ]] -[[ string->unsigned long int ][ !!! *3* !!! ][ 109 ][ 18 ][ 15 ]] -[[ string->unsigned long long ][ !!! *3* !!! ][ 114 ][ 19 ][ 15 ]] -[[ string->bool ][ !!! *<1* !!! ][ 106 ][ 17 ][ 8 ]] -[[ string->float ][ !!! *13* !!! ][ 175 ][ 70 ][ 33 ]] -[[ string->double ][ !!! *14* !!! ][ 182 ][ 81 ][ 58 ]] -[[ string->long double ][ 118 ][ 190 ][ 87 ][ !!! *58* !!! ]] -[[ char->string ][ !!! *8* !!! ][ 118 ][ 21 ][ 12 ]] -[[ unsigned char->string ][ !!! *8* !!! ][ 109 ][ 18 ][ 16 ]] -[[ signed char->string ][ !!! *8* !!! ][ 108 ][ 18 ][ 12 ]] -[[ int->string ][ 20 ][ 121 ][ 21 ][ !!! *16* !!! ]] -[[ short->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 17 ]] -[[ long int->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 16 ]] -[[ long long->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 17 ]] -[[ unsigned int->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 16 ]] -[[ unsigned short->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 18 ]] -[[ unsigned long int->string ][ 16 ][ 118 ][ 22 ][ !!! *15* !!! ]] -[[ unsigned long long->string ][ !!! *15* !!! ][ 117 ][ 21 ][ 17 ]] -[[ bool->string ][ !!! *8* !!! ][ 117 ][ 23 ][ 10 ]] -[[ float->string ][ 77 ][ 218 ][ 105 ][ !!! *50* !!! ]] -[[ double->string ][ 108 ][ 247 ][ 129 ][ !!! *73* !!! ]] -[[ long double->string ][ 120 ][ 250 ][ 131 ][ !!! *79* !!! ]] -[[ char*->char ][ !!! *2* !!! ][ 99 ][ 9 ][ 7 ]] -[[ char*->signed char ][ !!! *2* !!! ][ 98 ][ 9 ][ 8 ]] -[[ char*->unsigned char ][ !!! *2* !!! ][ 98 ][ 9 ][ 13 ]] -[[ char*->int ][ !!! *6* !!! ][ 115 ][ 22 ][ 15 ]] -[[ char*->short ][ !!! *6* !!! ][ 114 ][ 22 ][ 15 ]] -[[ char*->long int ][ !!! *6* !!! ][ 114 ][ 22 ][ 16 ]] -[[ char*->long long ][ !!! *6* !!! ][ 119 ][ 22 ][ 15 ]] -[[ char*->unsigned int ][ !!! *6* !!! ][ 114 ][ 20 ][ 15 ]] -[[ char*->unsigned short ][ !!! *6* !!! ][ 116 ][ 20 ][ 15 ]] -[[ char*->unsigned long int ][ !!! *6* !!! ][ 117 ][ 22 ][ 15 ]] -[[ char*->unsigned long long ][ !!! *6* !!! ][ 118 ][ 22 ][ 15 ]] -[[ char*->bool ][ !!! *3* !!! ][ 113 ][ 18 ][ 8 ]] -[[ char*->float ][ !!! *15* !!! ][ 180 ][ 78 ][ 32 ]] -[[ char*->double ][ !!! *16* !!! ][ 185 ][ 89 ][ 58 ]] -[[ char*->long double ][ 119 ][ 193 ][ 91 ][ !!! *60* !!! ]] -[[ unsigned char*->char ][ !!! *2* !!! ][ 99 ][ 9 ][ 8 ]] -[[ unsigned char*->signed char ][ !!! *2* !!! ][ 99 ][ 10 ][ 8 ]] -[[ unsigned char*->unsigned char ][ !!! *2* !!! ][ 100 ][ 9 ][ 15 ]] -[[ unsigned char*->int ][ !!! *6* !!! ][ 118 ][ 22 ][ 15 ]] -[[ unsigned char*->short ][ !!! *6* !!! ][ 117 ][ 26 ][ 15 ]] -[[ unsigned char*->long int ][ !!! *6* !!! ][ 119 ][ 21 ][ 15 ]] -[[ unsigned char*->long long ][ !!! *6* !!! ][ 118 ][ 21 ][ 14 ]] -[[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 115 ][ 22 ][ 14 ]] -[[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 117 ][ 20 ][ 15 ]] -[[ unsigned char*->unsigned long int ][ !!! *6* !!! ][ 115 ][ 21 ][ 15 ]] -[[ unsigned char*->unsigned long long ][ !!! *6* !!! ][ 117 ][ 22 ][ 15 ]] -[[ unsigned char*->bool ][ !!! *3* !!! ][ 112 ][ 18 ][ 8 ]] -[[ unsigned char*->float ][ !!! *15* !!! ][ 181 ][ 78 ][ 33 ]] -[[ unsigned char*->double ][ !!! *16* !!! ][ 185 ][ 92 ][ 59 ]] -[[ unsigned char*->long double ][ 120 ][ 190 ][ 89 ][ !!! *58* !!! ]] -[[ unsigned char*->string ][ !!! *14* !!! ][ 121 ][ 22 ][ --- ]] -[[ signed char*->char ][ !!! *2* !!! ][ 99 ][ 9 ][ 9 ]] -[[ signed char*->signed char ][ !!! *2* !!! ][ 98 ][ 9 ][ 8 ]] -[[ signed char*->unsigned char ][ !!! *2* !!! ][ 98 ][ 9 ][ 14 ]] -[[ signed char*->int ][ !!! *6* !!! ][ 119 ][ 22 ][ 16 ]] -[[ signed char*->short ][ !!! *6* !!! ][ 115 ][ 22 ][ 15 ]] -[[ signed char*->long int ][ !!! *6* !!! ][ 119 ][ 22 ][ 15 ]] -[[ signed char*->long long ][ !!! *6* !!! ][ 117 ][ 22 ][ 15 ]] -[[ signed char*->unsigned int ][ !!! *6* !!! ][ 117 ][ 23 ][ 15 ]] -[[ signed char*->unsigned short ][ !!! *6* !!! ][ 117 ][ 21 ][ 14 ]] -[[ signed char*->unsigned long int ][ !!! *7* !!! ][ 119 ][ 24 ][ 15 ]] -[[ signed char*->unsigned long long ][ !!! *6* !!! ][ 116 ][ 22 ][ 15 ]] -[[ signed char*->bool ][ !!! *3* !!! ][ 111 ][ 18 ][ 8 ]] -[[ signed char*->float ][ !!! *16* !!! ][ 180 ][ 78 ][ 33 ]] -[[ signed char*->double ][ !!! *16* !!! ][ 185 ][ 89 ][ 59 ]] -[[ signed char*->long double ][ 120 ][ 191 ][ 91 ][ !!! *59* !!! ]] -[[ signed char*->string ][ !!! *14* !!! ][ 122 ][ 23 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 120 ][ 22 ][ --- ]] -[[ float->double ][ !!! *<1* !!! ][ 242 ][ 115 ][ --- ]] -[[ double->double ][ !!! *<1* !!! ][ 243 ][ 115 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 265 ][ 141 ][ --- ]] -[[ int->int ][ !!! *<1* !!! ][ 266 ][ 140 ][ --- ]] -[[ char->unsigned char ][ !!! *<1* !!! ][ 95 ][ 8 ][ --- ]] -[[ char->signed char ][ !!! *<1* !!! ][ 95 ][ 8 ][ --- ]] -[[ unsigned char->char ][ !!! *<1* !!! ][ 94 ][ 8 ][ --- ]] -[[ signed char->char ][ !!! *<1* !!! ][ 94 ][ 8 ][ --- ]] + [[ string->char ][ !!! *<1* !!! ][ 162 ][ 17 ][ 8 ]] + [[ string->signed char ][ !!! *<1* !!! ][ 103 ][ 9 ][ 9 ]] + [[ string->unsigned char ][ !!! *<1* !!! ][ 91 ][ 9 ][ 9 ]] + [[ string->int ][ !!! *6* !!! ][ 104 ][ 21 ][ 14 ]] + [[ string->short ][ !!! *5* !!! ][ 107 ][ 22 ][ 14 ]] + [[ string->long int ][ !!! *7* !!! ][ 106 ][ 23 ][ 15 ]] + [[ string->long long ][ !!! *7* !!! ][ 104 ][ 21 ][ 16 ]] + [[ string->unsigned int ][ !!! *6* !!! ][ 100 ][ 20 ][ 16 ]] + [[ string->unsigned short ][ !!! *5* !!! ][ 102 ][ 20 ][ 16 ]] + [[ string->unsigned long int ][ !!! *7* !!! ][ 106 ][ 25 ][ 16 ]] + [[ string->unsigned long long ][ !!! *7* !!! ][ 109 ][ 25 ][ 14 ]] + [[ string->float ][ !!! *13* !!! ][ 142 ][ 48 ][ 32 ]] + [[ string->double ][ !!! *13* !!! ][ 162 ][ 62 ][ 33 ]] + [[ string->long double ][ 119 ][ 164 ][ 62 ][ !!! *37* !!! ]] + [[ string->string ][ !!! *2* !!! ][ 122 ][ 27 ][ --- ]] + [[ string->container::string ][ !!! *2* !!! ][ 107 ][ 23 ][ --- ]] + [[ string->char ][ !!! *6* !!! ][ 110 ][ 24 ][ 15 ]] + [[ string->signed char ][ !!! *6* !!! ][ 107 ][ 24 ][ 21 ]] + [[ string->unsigned char ][ !!! *6* !!! ][ 106 ][ 27 ][ 21 ]] + [[ int->string ][ !!! *12* !!! ][ 122 ][ 31 ][ 21 ]] + [[ short->string ][ !!! *12* !!! ][ 136 ][ 29 ][ 20 ]] + [[ long int->string ][ !!! *12* !!! ][ 127 ][ 32 ][ 19 ]] + [[ long long->string ][ !!! *12* !!! ][ 121 ][ 32 ][ 21 ]] + [[ unsigned int->string ][ !!! *12* !!! ][ 133 ][ 32 ][ 19 ]] + [[ unsigned short->string ][ !!! *12* !!! ][ 126 ][ 33 ][ 20 ]] + [[ unsigned long int->string ][ !!! *11* !!! ][ 126 ][ 34 ][ 19 ]] + [[ unsigned long long->string ][ !!! *12* !!! ][ 125 ][ 28 ][ 21 ]] + [[ float->string ][ 47 ][ 183 ][ 86 ][ !!! *43* !!! ]] + [[ double->string ][ 57 ][ 184 ][ 90 ][ !!! *42* !!! ]] + [[ long double->string ][ 64 ][ 199 ][ 87 ][ !!! *46* !!! ]] + [[ char*->char ][ !!! *<1* !!! ][ 95 ][ 10 ][ 8 ]] + [[ char*->signed char ][ !!! *<1* !!! ][ 90 ][ 12 ][ 9 ]] + [[ char*->unsigned char ][ !!! *<1* !!! ][ 93 ][ 12 ][ 9 ]] + [[ char*->int ][ !!! *6* !!! ][ 108 ][ 24 ][ 14 ]] + [[ char*->short ][ !!! *6* !!! ][ 106 ][ 23 ][ 14 ]] + [[ char*->long int ][ !!! *7* !!! ][ 107 ][ 24 ][ 17 ]] + [[ char*->long long ][ !!! *7* !!! ][ 109 ][ 25 ][ 17 ]] + [[ char*->unsigned int ][ !!! *6* !!! ][ 104 ][ 23 ][ 17 ]] + [[ char*->unsigned short ][ !!! *6* !!! ][ 102 ][ 22 ][ 17 ]] + [[ char*->unsigned long int ][ !!! *7* !!! ][ 107 ][ 23 ][ 17 ]] + [[ char*->unsigned long long ][ !!! *7* !!! ][ 115 ][ 26 ][ 14 ]] + [[ char*->float ][ !!! *12* !!! ][ 150 ][ 56 ][ 30 ]] + [[ char*->double ][ !!! *12* !!! ][ 165 ][ 66 ][ 32 ]] + [[ char*->long double ][ 116 ][ 173 ][ 66 ][ !!! *37* !!! ]] + [[ char*->string ][ !!! *7* !!! ][ 120 ][ 28 ][ --- ]] + [[ char*->container::string ][ !!! *2* !!! ][ 108 ][ 26 ][ --- ]] + [[ unsigned char*->char ][ !!! *<1* !!! ][ 90 ][ 12 ][ 8 ]] + [[ unsigned char*->signed char ][ !!! *<1* !!! ][ 91 ][ 11 ][ 9 ]] + [[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 91 ][ 12 ][ 9 ]] + [[ unsigned char*->int ][ !!! *6* !!! ][ 106 ][ 24 ][ 14 ]] + [[ unsigned char*->short ][ !!! *6* !!! ][ 108 ][ 24 ][ 14 ]] + [[ unsigned char*->long int ][ !!! *7* !!! ][ 116 ][ 23 ][ 14 ]] + [[ unsigned char*->long long ][ !!! *7* !!! ][ 108 ][ 28 ][ 14 ]] + [[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 107 ][ 22 ][ 14 ]] + [[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 105 ][ 21 ][ 16 ]] + [[ unsigned char*->unsigned long int ][ !!! *7* !!! ][ 106 ][ 25 ][ 16 ]] + [[ unsigned char*->unsigned long long ][ !!! *7* !!! ][ 105 ][ 24 ][ 17 ]] + [[ unsigned char*->float ][ !!! *14* !!! ][ 150 ][ 57 ][ 33 ]] + [[ unsigned char*->double ][ !!! *14* !!! ][ 171 ][ 72 ][ 34 ]] + [[ unsigned char*->long double ][ 118 ][ 171 ][ 73 ][ !!! *38* !!! ]] + [[ unsigned char*->string ][ !!! *8* !!! ][ 120 ][ 29 ][ --- ]] + [[ unsigned char*->container::string ][ !!! *3* !!! ][ 114 ][ 26 ][ --- ]] + [[ signed char*->char ][ !!! *<1* !!! ][ 92 ][ 12 ][ 8 ]] + [[ signed char*->signed char ][ !!! *<1* !!! ][ 92 ][ 12 ][ 9 ]] + [[ signed char*->unsigned char ][ !!! *<1* !!! ][ 91 ][ 14 ][ 9 ]] + [[ signed char*->int ][ !!! *6* !!! ][ 109 ][ 22 ][ 15 ]] + [[ signed char*->short ][ !!! *6* !!! ][ 106 ][ 24 ][ 17 ]] + [[ signed char*->long int ][ !!! *7* !!! ][ 107 ][ 24 ][ 16 ]] + [[ signed char*->long long ][ !!! *7* !!! ][ 106 ][ 24 ][ 14 ]] + [[ signed char*->unsigned int ][ !!! *6* !!! ][ 106 ][ 22 ][ 14 ]] + [[ signed char*->unsigned short ][ !!! *6* !!! ][ 104 ][ 20 ][ 14 ]] + [[ signed char*->unsigned long int ][ !!! *7* !!! ][ 105 ][ 22 ][ 16 ]] + [[ signed char*->unsigned long long ][ !!! *7* !!! ][ 108 ][ 24 ][ 15 ]] + [[ signed char*->float ][ !!! *14* !!! ][ 147 ][ 54 ][ 32 ]] + [[ signed char*->double ][ !!! *14* !!! ][ 170 ][ 68 ][ 37 ]] + [[ signed char*->long double ][ 133 ][ 167 ][ 66 ][ !!! *37* !!! ]] + [[ signed char*->string ][ !!! *8* !!! ][ 119 ][ 30 ][ --- ]] + [[ signed char*->container::string ][ !!! *3* !!! ][ 108 ][ 24 ][ --- ]] + [[ iterator_range->char ][ !!! *<1* !!! ][ 98 ][ 13 ][ 8 ]] + [[ iterator_range->signed char ][ !!! *<1* !!! ][ 98 ][ 15 ][ 9 ]] + [[ iterator_range->unsigned char ][ !!! *<1* !!! ][ 97 ][ 15 ][ 9 ]] + [[ iterator_range->int ][ !!! *6* !!! ][ 107 ][ 27 ][ 14 ]] + [[ iterator_range->short ][ !!! *5* !!! ][ 109 ][ 23 ][ 14 ]] + [[ iterator_range->long int ][ !!! *7* !!! ][ 109 ][ 22 ][ 14 ]] + [[ iterator_range->long long ][ !!! *7* !!! ][ 107 ][ 24 ][ 14 ]] + [[ iterator_range->unsigned int ][ !!! *6* !!! ][ 120 ][ 23 ][ 14 ]] + [[ iterator_range->unsigned short ][ !!! *5* !!! ][ 104 ][ 21 ][ 17 ]] + [[ iterator_range->unsigned long int ][ !!! *8* !!! ][ 108 ][ 25 ][ 16 ]] + [[ iterator_range->unsigned long long ][ !!! *7* !!! ][ 106 ][ 25 ][ 15 ]] + [[ iterator_range->float ][ !!! *13* !!! ][ 132 ][ 41 ][ 32 ]] + [[ iterator_range->double ][ !!! *12* !!! ][ 136 ][ 45 ][ 32 ]] + [[ iterator_range->long double ][ 113 ][ 138 ][ 50 ][ !!! *36* !!! ]] + [[ iterator_range->string ][ !!! *7* !!! ][ 114 ][ 33 ][ --- ]] + [[ iterator_range->container::string ][ !!! *2* !!! ][ 105 ][ 24 ][ --- ]] + [[ int->int ][ !!! *<1* !!! ][ 112 ][ 31 ][ --- ]] + [[ float->double ][ !!! *<1* !!! ][ 233 ][ 199 ][ --- ]] + [[ char->signed char ][ !!! *<1* !!! ][ 129 ][ 10 ][ --- ]] ] [endsect] diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index b73c741..fb1808f 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -72,6 +72,7 @@ _CRTIMP int __cdecl vswprintf(wchar_t * __restrict__ , const wchar_t * __restric #include #include #include +#include #if !defined(__SUNPRO_CC) #include #endif // !defined(__SUNPRO_CC) @@ -166,6 +167,18 @@ namespace boost }; #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct stream_char > + { + typedef BOOST_DEDUCED_TYPENAME stream_char::type type; + }; + + template + struct stream_char > + { + typedef BOOST_DEDUCED_TYPENAME stream_char::type type; + }; + template struct stream_char< std::basic_string > { @@ -1225,7 +1238,7 @@ namespace boost bool shl_char(T ch) { BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)) , - "boost::lexical_cast does not support conversions from whar_t to char types." + "boost::lexical_cast does not support conversions from wchar_t to char types." "Use boost::locale instead" ); #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE std::locale loc; @@ -1397,6 +1410,52 @@ namespace boost return true; } + bool operator<<(const iterator_range& rng) + { + start = rng.begin(); + finish = rng.end(); + return true; + } + + bool operator<<(const iterator_range& rng) + { + start = const_cast(rng.begin()); + finish = const_cast(rng.end()); + return true; + } + + bool operator<<(const iterator_range& rng) + { + return (*this) << iterator_range( + const_cast(reinterpret_cast(rng.begin())), + const_cast(reinterpret_cast(rng.end())) + ); + } + + bool operator<<(const iterator_range& rng) + { + return (*this) << iterator_range( + const_cast(reinterpret_cast(rng.begin())), + const_cast(reinterpret_cast(rng.end())) + ); + } + + bool operator<<(const iterator_range& rng) + { + return (*this) << iterator_range( + reinterpret_cast(rng.begin()), + reinterpret_cast(rng.end()) + ); + } + + bool operator<<(const iterator_range& rng) + { + return (*this) << iterator_range( + reinterpret_cast(rng.begin()), + reinterpret_cast(rng.end()) + ); + } + bool operator<<(char ch) { return shl_char(ch); } bool operator<<(unsigned char ch) { return ((*this) << static_cast(ch)); } bool operator<<(signed char ch) { return ((*this) << static_cast(ch)); } @@ -1572,7 +1631,7 @@ namespace boost inline bool shr_xchar(T& output) { BOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ), - "boost::lexical_cast does not support conversions from whar_t to char types." + "boost::lexical_cast does not support conversions from wchar_t to char types." "Use boost::locale instead" ); bool const ok = (finish - start == 1); if(ok) { @@ -1801,6 +1860,24 @@ namespace boost ); }; + template + struct is_char_iterator_range + { + BOOST_STATIC_CONSTANT(bool, value = false ); + }; + + template + struct is_char_iterator_range > + { + BOOST_STATIC_CONSTANT(bool, value = (is_char_or_wchar::value) ); + }; + + template + struct is_char_iterator_range > + { + BOOST_STATIC_CONSTANT(bool, value = (is_char_or_wchar::value) ); + }; + template struct is_arithmetic_and_not_xchars { @@ -1889,10 +1966,10 @@ namespace boost static inline Target lexical_cast_impl(const Source& arg) { typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay::type src; - + typedef BOOST_DEDUCED_TYPENAME detail::stream_char::type target_char_t; + typedef BOOST_DEDUCED_TYPENAME detail::stream_char::type src_char_type; typedef BOOST_DEDUCED_TYPENAME detail::widest_char< - BOOST_DEDUCED_TYPENAME detail::stream_char::type - , BOOST_DEDUCED_TYPENAME detail::stream_char::type + target_char_t, src_char_type >::type char_type; typedef detail::lcast_src_length lcast_src_length; @@ -1903,7 +1980,8 @@ namespace boost typedef BOOST_DEDUCED_TYPENAME deduce_char_traits::type traits; - typedef BOOST_DEDUCED_TYPENAME remove_pointer::type removed_ptr_t; + typedef BOOST_DEDUCED_TYPENAME remove_pointer::type removed_ptr_t_1; + typedef BOOST_DEDUCED_TYPENAME remove_cv::type removed_ptr_t; // is_char_types_match variable value can be computed via // sizeof(char_type) == sizeof(removed_ptr_t). But when @@ -1914,12 +1992,12 @@ namespace boost ::boost::type_traits::ice_and< ::boost::type_traits::ice_eq::value, ::boost::type_traits::ice_or< - ::boost::is_same::value, - ::boost::is_same::value, - ::boost::is_same::value + ::boost::is_same::value, + ::boost::is_same::value, + ::boost::is_same::value >::value >::value, - is_same::value + is_same::value >::value); const bool requires_stringbuf = @@ -1928,14 +2006,18 @@ namespace boost is_stdstring::value, is_arithmetic::value, ::boost::type_traits::ice_and< - is_pointer::value, - is_char_or_wchar::value, + is_char_iterator_range::value, + is_char_types_match + >::value, + ::boost::type_traits::ice_and< + is_pointer::value, + is_char_or_wchar::value, is_char_types_match >::value >::value ); - detail::lexical_stream_limited_src + detail::lexical_stream_limited_src interpreter(buf, buf + src_len); Target result; diff --git a/perf/performance_test.cpp b/perf/performance_test.cpp index ff1eb1d..8640bc4 100644 --- a/perf/performance_test.cpp +++ b/perf/performance_test.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include // File to output data @@ -74,6 +75,12 @@ struct structure_sscanf { OutT out_val; sscanf(in_val.c_str(), conv, &out_val); } + + template + static inline void test(BufferT* /*buffer*/, const boost::iterator_range& in_val, const char* const conv) { + OutT out_val; + sscanf(in_val.begin(), conv, &out_val); + } }; struct structure_fake { @@ -255,6 +262,12 @@ struct to_schar_conv { } }; +struct to_iterator_range { + boost::iterator_range operator()(const char* const c) const { + return boost::make_iterator_range(c, c + std::strlen(c)); + } +}; + int main(int argc, char** argv) { BOOST_ASSERT(argc >= 2); std::string output_path(argv[1]); @@ -296,11 +309,13 @@ int main(int argc, char** argv) { string_like_test_set("char*"); string_like_test_set("unsigned char*"); string_like_test_set("signed char*"); + string_like_test_set("iterator_range"); perf_test("int->int", 100, ""); perf_test("float->double", 100.0f, ""); perf_test("char->signed char", 'c', ""); + fout << "]\n" << "[endsect]\n\n"; return 0; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 019c9e7..131fa3e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -45,5 +45,6 @@ test-suite conversion gcc-4.5:-fno-exceptions gcc-4.6:-fno-exceptions ] + [ run lexical_cast_iterator_range_test.cpp ../../test/build//boost_unit_test_framework/static ] ; diff --git a/test/lexical_cast_iterator_range_test.cpp b/test/lexical_cast_iterator_range_test.cpp new file mode 100644 index 0000000..7afb1ae --- /dev/null +++ b/test/lexical_cast_iterator_range_test.cpp @@ -0,0 +1,189 @@ +// 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 + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include + +#include +#include + +using namespace boost; + +#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) +#define BOOST_LCAST_NO_WCHAR_T +#endif + +struct class_with_user_defined_sream_operators { + int i; + + operator int() const { + return i; + } +}; + +template +inline std::basic_istream& operator >> (std::basic_istream& istr, class_with_user_defined_sream_operators& rhs) +{ + return istr >> rhs.i; +} + + +template +void do_test_iterator_range(const RngT& rng) +{ + BOOST_CHECK_EQUAL(lexical_cast(rng), 1); + BOOST_CHECK_EQUAL(lexical_cast(rng), 1u); + BOOST_CHECK_EQUAL(lexical_cast(rng), 1); + BOOST_CHECK_EQUAL(lexical_cast(rng), 1u); + BOOST_CHECK_EQUAL(lexical_cast(rng), 1); + BOOST_CHECK_EQUAL(lexical_cast(rng), 1u); + BOOST_CHECK_EQUAL(lexical_cast(rng), 1.0f); + BOOST_CHECK_EQUAL(lexical_cast(rng), 1.0); + BOOST_CHECK_EQUAL(lexical_cast(rng), 1.0L); + BOOST_CHECK_EQUAL(lexical_cast(rng), 1); + +#if defined(BOOST_HAS_LONG_LONG) + BOOST_CHECK_EQUAL(lexical_cast(rng), 1u); + BOOST_CHECK_EQUAL(lexical_cast(rng), 1); +#elif defined(BOOST_HAS_MS_INT64) + BOOST_CHECK_EQUAL(lexical_cast(rng), 1u); + BOOST_CHECK_EQUAL(lexical_cast<__int64>(rng), 1); +#endif + +#ifndef BOOST_LCAST_NO_WCHAR_T + BOOST_CHECK(lexical_cast(rng) == L"1"); +#endif +} + +void test_char_iterator_ranges() +{ + typedef char test_char_type; + + // Zero terminated + test_char_type data1[] = "1"; + iterator_range rng1(data1, data1 + 1); + do_test_iterator_range(rng1); + BOOST_CHECK_EQUAL(lexical_cast(rng1), "1"); + + const test_char_type cdata1[] = "1"; + iterator_range crng1(cdata1, cdata1 + 1); + do_test_iterator_range(crng1); + BOOST_CHECK_EQUAL(lexical_cast(crng1), "1"); + + // Non zero terminated + test_char_type data2[] = "11"; + iterator_range rng2(data2, data2 + 1); + do_test_iterator_range(rng2); + BOOST_CHECK_EQUAL(lexical_cast(rng2), "1"); + + const test_char_type cdata2[] = "11"; + iterator_range crng2(cdata2, cdata2 + 1); + do_test_iterator_range(crng2); + BOOST_CHECK_EQUAL(lexical_cast(crng2), "1"); +} + +void test_unsigned_char_iterator_ranges() +{ + typedef unsigned char test_char_type; + + // Zero terminated + test_char_type data1[] = "1"; + iterator_range rng1(data1, data1 + 1); + do_test_iterator_range(rng1); + BOOST_CHECK_EQUAL(lexical_cast(rng1), "1"); + + const test_char_type cdata1[] = "1"; + iterator_range crng1(cdata1, cdata1 + 1); + do_test_iterator_range(crng1); + BOOST_CHECK_EQUAL(lexical_cast(crng1), "1"); + + // Non zero terminated + test_char_type data2[] = "11"; + iterator_range rng2(data2, data2 + 1); + do_test_iterator_range(rng2); + BOOST_CHECK_EQUAL(lexical_cast(rng2), "1"); + + const test_char_type cdata2[] = "11"; + iterator_range crng2(cdata2, cdata2 + 1); + do_test_iterator_range(crng2); + BOOST_CHECK_EQUAL(lexical_cast(crng2), "1"); +} + +void test_signed_char_iterator_ranges() +{ + typedef signed char test_char_type; + + // Zero terminated + test_char_type data1[] = "1"; + iterator_range rng1(data1, data1 + 1); + do_test_iterator_range(rng1); + BOOST_CHECK_EQUAL(lexical_cast(rng1), "1"); + + const test_char_type cdata1[] = "1"; + iterator_range crng1(cdata1, cdata1 + 1); + do_test_iterator_range(crng1); + BOOST_CHECK_EQUAL(lexical_cast(crng1), "1"); + + // Non zero terminated + test_char_type data2[] = "11"; + iterator_range rng2(data2, data2 + 1); + do_test_iterator_range(rng2); + BOOST_CHECK_EQUAL(lexical_cast(rng2), "1"); + + const test_char_type cdata2[] = "11"; + iterator_range crng2(cdata2, cdata2 + 1); + do_test_iterator_range(crng2); + BOOST_CHECK_EQUAL(lexical_cast(crng2), "1"); +} + +void test_wide_char_iterator_ranges() +{ +#ifndef BOOST_LCAST_NO_WCHAR_T + typedef wchar_t test_char_type; + + // Zero terminated + test_char_type data1[] = L"1"; + iterator_range rng1(data1, data1 + 1); + do_test_iterator_range(rng1); + + const test_char_type cdata1[] = L"1"; + iterator_range crng1(cdata1, cdata1 + 1); + do_test_iterator_range(crng1); + + // Non zero terminated + test_char_type data2[] = L"11"; + iterator_range rng2(data2, data2 + 1); + do_test_iterator_range(rng2); + + const test_char_type cdata2[] = L"11"; + iterator_range crng2(cdata2, cdata2 + 1); + do_test_iterator_range(crng2); +#endif + + BOOST_CHECK(true); +} + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast. Testing conversions using iterator_range<>"); + suite->add(BOOST_TEST_CASE(&test_char_iterator_ranges)); + suite->add(BOOST_TEST_CASE(&test_unsigned_char_iterator_ranges)); + suite->add(BOOST_TEST_CASE(&test_signed_char_iterator_ranges)); + suite->add(BOOST_TEST_CASE(&test_wide_char_iterator_ranges)); + + return suite; +} From 4265f454e13cf2b082477c8adbc8714ad3d0798d Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 25 Mar 2012 05:31:43 +0000 Subject: [PATCH 150/242] Small documentation updates for #6663 [SVN r77537] --- doc/lexical_cast.qbk | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index d58f90d..ffab311 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -132,22 +132,22 @@ Consider the following example: return non_zero_terminated_data; } - std::size_t length() const { + std::size_t size() const { return data_length; } }; inline std::ostream& operator << (std::ostream& ostr, const example_class& rhs) { - return ostr << boost::make_iterator_range(rhs.data(), rhs.data() + rhs.length()); + return ostr << boost::make_iterator_range(rhs.data(), rhs.data() + rhs.size()); } `` This is a good generic solution for most use cases. But we can make it even faster for some performance critical applications. During conversion, we loose speed at: -* `std::basic_ostream` construction (it makes some heap allocations) -* `operator <<` (it copyies one by one all the symbols to an instance of `std::basic_ostream`) -* `std::basic_ostream` destruction (it makes some heap deallocations) +* `std::ostream` construction (it makes some heap allocations) +* `operator <<` (it copyies one by one all the symbols to an instance of `std::ostream`) +* `std::ostream` destruction (it makes some heap deallocations) We can avoid all of this, by specifieng an overload for `boost::lexical_cast`: `` @@ -155,7 +155,7 @@ namespace boost { template OutT lexical_cast(const example_class& rhs) { return boost::lexical_cast( - boost::make_iterator_range(rhs.data(), rhs.data() + rhs.length()) + boost::make_iterator_range(rhs.data(), rhs.data() + rhs.size()) ); } } From dfb518997f7526bbf6ba21c1e6c9494df8f11fa2 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 30 Mar 2012 03:55:26 +0000 Subject: [PATCH 151/242] Fixes #6717 (now lexical_cast won`t try to support non confirming swprintf) [SVN r77639] --- include/boost/lexical_cast.hpp | 174 +++++++++++++++------------------ 1 file changed, 80 insertions(+), 94 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index fb1808f..d79e50a 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -26,27 +26,6 @@ #define BOOST_LCAST_NO_WCHAR_T #endif -#if (defined(__MINGW32__) || defined(__MINGW64__)) && (__GNUC__ == 4) \ - && ((__GNUC_MINOR__ == 4) || (__GNUC_MINOR__ == 5)) && defined(__STRICT_ANSI__) \ - && !defined(BOOST_LCAST_NO_WCHAR_T) - -// workaround for a mingw bug -// http://sourceforge.net/tracker/index.php?func=detail&aid=2373234&group_id=2435&atid=102435 -#include <_mingw.h> -#if (__GNUC_MINOR__ == 4) -extern "C" { -_CRTIMP int __cdecl swprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , ...); -_CRTIMP int __cdecl vswprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , ...); -} -#endif -#if (__GNUC_MINOR__ == 5) -extern "C" { -_CRTIMP int __cdecl swprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , ...); -_CRTIMP int __cdecl vswprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , va_list); -} -#endif -#endif - #include #include #include @@ -1299,34 +1278,40 @@ namespace boost return true; } + template + bool shl_real_type(const T& val, SomeCharT*, SomeCharT*) + { + return shl_input_streamable(val); + } + #if (defined _MSC_VER) # pragma warning( push ) // C4996: This function or variable may be unsafe. Consider using sprintf_s instead # pragma warning( disable : 4996 ) #endif - - template - bool shl_float(float val,T* out) + static bool shl_real_type(float val, char* begin, char*& end) { using namespace std; - if (put_inf_nan(start,finish,val)) return true; - finish = start + sprintf(out,"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); - return finish > start; + if (put_inf_nan(begin, end, val)) return true; + end = begin; + end += sprintf(begin,"%.*g", static_cast(boost::detail::lcast_get_precision()), val); + return end > begin; } - template - bool shl_double(double val,T* out) + static bool shl_real_type(double val, char* begin, char*& end) { using namespace std; - if (put_inf_nan(start,finish,val)) return true; - finish = start + sprintf(out,"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); - return finish > start; + if (put_inf_nan(begin, end, val)) return true; + end = begin; + end += sprintf(begin,"%.*lg", static_cast(boost::detail::lcast_get_precision()), val); + return end > begin; } + #ifndef __MINGW32__ - template - bool shl_long_double(long double val,T* out) + static bool shl_real_type(long double val, char* begin, char*& end) { using namespace std; - if (put_inf_nan(start,finish,val)) return true; - finish = start + sprintf(out,"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); - return finish > start; + if (put_inf_nan(begin, end, val)) return true; + end = begin; + end += sprintf(begin,"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); + return end > begin; } #endif @@ -1335,54 +1320,32 @@ namespace boost #endif -#ifndef BOOST_LCAST_NO_WCHAR_T - bool shl_float(float val,wchar_t* out) +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__) + static bool shl_real_type(float val, wchar_t* begin, wchar_t*& end) { using namespace std; - if (put_inf_nan(start,finish,val)) return true; - finish = start + swprintf(out, -#if !defined(__MINGW32__) && !defined(UNDER_CE) - finish-start, -#endif + if (put_inf_nan(begin, end, val)) return true; + end = begin + swprintf(begin, end-begin, L"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); - - return finish > start; + return end > begin; } - - bool shl_double(double val,wchar_t* out) + static bool shl_real_type(double val, wchar_t* begin, wchar_t*& end) { using namespace std; - if (put_inf_nan(start,finish,val)) return true; - /* __MINGW32__ is defined for both mingw.org and for mingw-w64. - * For mingw-w64, __MINGW64__ is defined, too, when targetting - * 64 bits. - * - * swprintf realization in MinGW and under WinCE does not conform - * to the ISO C - * Standard. - */ - finish = start + swprintf(out, -#if !defined(__MINGW32__) && !defined(UNDER_CE) - finish-start, -#endif + if (put_inf_nan(begin, end, val)) return true; + end = begin + swprintf(begin, end-begin, L"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); - return finish > start; + return end > begin; } -#ifndef __MINGW32__ - bool shl_long_double(long double val,wchar_t* out) + static bool shl_real_type(long double val, wchar_t* begin, wchar_t*& end) { using namespace std; - if (put_inf_nan(start,finish,val)) return true; - finish = start + swprintf(out, -#if !defined(UNDER_CE) - finish-start, -#endif + if (put_inf_nan(begin, end, val)) return true; + end = begin + swprintf(begin, end-begin, L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); - return finish > start; + return end > begin; } #endif -#endif - /************************************ OPERATORS << ( ... ) ********************************/ public: template @@ -1486,13 +1449,13 @@ namespace boost bool operator<<(unsigned __int64 n) { start = lcast_put_unsigned(n, finish); return true; } bool operator<<( __int64 n) { return shl_signed(n); } #endif - bool operator<<(float val) { return shl_float(val,start); } - bool operator<<(double val) { return shl_double(val,start); } + bool operator<<(float val) { return shl_real_type(val, start, finish); } + bool operator<<(double val) { return shl_real_type(val, start, finish); } bool operator<<(long double val) { #ifndef __MINGW32__ - return shl_long_double(val,start); + return shl_real_type(val, start, finish); #else - return shl_double(val,start); + return shl_real_type(static_cast(val), start, finish); #endif } @@ -1884,8 +1847,8 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = ( ::boost::type_traits::ice_and< - is_arithmetic::value, - is_arithmetic::value, + ::boost::is_arithmetic::value, + ::boost::is_arithmetic::value, ::boost::type_traits::ice_not< detail::is_char_or_wchar::value >::value, @@ -1923,6 +1886,28 @@ 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 { @@ -2003,15 +1988,16 @@ namespace boost const bool requires_stringbuf = !( ::boost::type_traits::ice_or< - is_stdstring::value, - is_arithmetic::value, + ::boost::detail::is_stdstring::value, + ::boost::is_integral::value, + ::boost::detail::is_this_float_conversion_optimized::value, ::boost::type_traits::ice_and< - is_char_iterator_range::value, + ::boost::detail::is_char_iterator_range::value, is_char_types_match >::value, ::boost::type_traits::ice_and< - is_pointer::value, - is_char_or_wchar::value, + ::boost::is_pointer::value, + ::boost::detail::is_char_or_wchar::value, is_char_types_match >::value >::value @@ -2047,7 +2033,7 @@ namespace boost typedef Source source_type ; typedef BOOST_DEDUCED_TYPENAME mpl::if_< - is_arithmetic, Source, Source const& + ::boost::is_arithmetic, Source, Source const& >::type argument_type ; static source_type nearbyint ( argument_type s ) @@ -2138,10 +2124,10 @@ namespace boost ::boost::is_float::value >::value, ::boost::type_traits::ice_not< - is_same::value + ::boost::is_same::value >::value, ::boost::type_traits::ice_not< - is_same::value + ::boost::is_same::value >::value, ::boost::is_unsigned::value >::value, @@ -2157,27 +2143,27 @@ namespace boost template inline Target lexical_cast(const Source &arg) { - typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay::type src; + typedef BOOST_DEDUCED_TYPENAME ::boost::detail::array_to_pointer_decay::type src; typedef BOOST_DEDUCED_TYPENAME ::boost::type_traits::ice_or< - detail::is_xchar_to_xchar::value, - detail::is_char_array_to_stdstring::value, + ::boost::detail::is_xchar_to_xchar::value, + ::boost::detail::is_char_array_to_stdstring::value, ::boost::type_traits::ice_and< - is_same::value, - detail::is_stdstring::value + ::boost::is_same::value, + ::boost::detail::is_stdstring::value >::value > do_copy_type; typedef BOOST_DEDUCED_TYPENAME - detail::is_arithmetic_and_not_xchars do_copy_with_dynamic_check_type; + ::boost::detail::is_arithmetic_and_not_xchars do_copy_with_dynamic_check_type; typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< do_copy_type::value, detail::lexical_cast_copy, BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< do_copy_with_dynamic_check_type::value, - detail::lexical_cast_dynamic_num, - detail::lexical_cast_do_cast + ::boost::detail::lexical_cast_dynamic_num, + ::boost::detail::lexical_cast_do_cast >::type >::type caster_type; From acb746274f0a6e1085ce26b1391a281f97f6dc44 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 1 Apr 2012 19:08:46 +0000 Subject: [PATCH 152/242] Fixes #6670 (now using BOOST_NO_UNICODE_LITERALS macro) [SVN r77691] --- include/boost/lexical_cast.hpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index d79e50a..438ee9c 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -480,7 +480,7 @@ namespace boost }; #endif -#ifndef BOOST_NO_CHAR16_T +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) template<> struct lcast_char_constants { @@ -493,7 +493,7 @@ namespace boost }; #endif -#ifndef BOOST_NO_CHAR32_T +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) template<> struct lcast_char_constants { @@ -1957,6 +1957,17 @@ namespace boost target_char_t, src_char_type >::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 detail::lcast_src_length lcast_src_length; std::size_t const src_len = lcast_src_length::value; char_type buf[src_len + 1]; @@ -1982,7 +1993,7 @@ namespace boost ::boost::is_same::value >::value >::value, - is_same::value + ::boost::is_same::value >::value); const bool requires_stringbuf = From 41a673db617e9afe03f8403cfb4be3f13618165e Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 2 Apr 2012 15:33:46 +0000 Subject: [PATCH 153/242] Fixes #6717 (now also setting precision for float types conversion when using iostreams) [SVN r77716] --- include/boost/lexical_cast.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 438ee9c..cb7ae12 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1254,7 +1254,7 @@ namespace boost { #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) // If you have compilation error at this point, than your STL library - // unsupports such conversions. Try updating it. + // does not support such conversions. Try updating it. BOOST_STATIC_ASSERT((boost::is_same::value)); #endif bool const result = !(out_stream << input).fail(); @@ -1279,8 +1279,10 @@ namespace boost } template - bool shl_real_type(const T& val, SomeCharT*, SomeCharT*) + bool shl_real_type(const T& val, SomeCharT* begin, SomeCharT*& end) { + if (put_inf_nan(begin, end, val)) return true; + lcast_set_precision(out_stream, &val); return shl_input_streamable(val); } From 969a913153bd53b816f4fbbbb038e595c55348d9 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 2 Apr 2012 16:58:32 +0000 Subject: [PATCH 154/242] More workarounds for fixed #6670 (disable basic char16_t and char32_t tests for some compilers, disable optimizations for them) [SVN r77721] --- include/boost/lexical_cast.hpp | 8 ++++---- lexical_cast_test.cpp | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index cb7ae12..61501d6 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -843,7 +843,7 @@ namespace boost } #endif -#ifndef BOOST_NO_CHAR16_T +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) template bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value) { @@ -859,7 +859,7 @@ namespace boost return put_inf_nan_impl(begin, end, value, u"nan", u"infinity"); } #endif -#ifndef BOOST_NO_CHAR32_T +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) template bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value) { @@ -1628,10 +1628,10 @@ namespace boost #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) bool operator>>(wchar_t& output) { return shr_xchar(output); } #endif -#ifndef BOOST_NO_CHAR16_T +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) bool operator>>(char16_t& output) { return shr_xchar(output); } #endif -#ifndef BOOST_NO_CHAR32_T +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) bool operator>>(char32_t& output) { return shr_xchar(output); } #endif #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 4e9ec90..14af705 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -100,10 +100,10 @@ void test_wallocator(); #endif void test_char_types_conversions(); void operators_overload_test(); -#ifndef BOOST_NO_CHAR16_T +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) void test_char16_conversions(); #endif -#ifndef BOOST_NO_CHAR32_T +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) void test_char32_conversions(); #endif @@ -149,10 +149,10 @@ 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 +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) suite->add(BOOST_TEST_CASE(&test_char16_conversions)); #endif -#ifndef BOOST_NO_CHAR32_T +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) suite->add(BOOST_TEST_CASE(&test_char32_conversions)); #endif @@ -1025,7 +1025,7 @@ void operators_overload_test() } -#ifndef BOOST_NO_CHAR16_T +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) void test_char16_conversions() { BOOST_CHECK(u"100" == lexical_cast(u"100")); @@ -1033,7 +1033,7 @@ void test_char16_conversions() } #endif -#ifndef BOOST_NO_CHAR32_T +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) void test_char32_conversions() { BOOST_CHECK(U"100" == lexical_cast(U"100")); From 4a617adce1d110d3f7e70f6c09e061f6d09f24d9 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 3 Apr 2012 18:00:30 +0000 Subject: [PATCH 155/242] More workarounds for fixed #6670 (disable more char16_t and char32_t tests for some compilers) [SVN r77745] --- lexical_cast_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 14af705..4e70bdd 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -756,12 +756,12 @@ void test_conversion_from_to_integral() test_conversion_from_integral_to_char(wzero); test_conversion_from_char_to_integral(wzero); #endif -#ifndef BOOST_NO_CHAR16_T +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) char16_t const u16zero = u'0'; test_conversion_from_integral_to_char(u16zero); test_conversion_from_char_to_integral(u16zero); #endif -#ifndef BOOST_NO_CHAR32_T +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) char32_t const u32zero = u'0'; test_conversion_from_integral_to_char(u32zero); test_conversion_from_char_to_integral(u32zero); From deef894ae2ab69a554df619398083e38cf64edc5 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 5 Apr 2012 03:53:58 +0000 Subject: [PATCH 156/242] Lexical_cast test's Jamfile has been rewritten (boost license is now explicitly defined, disabled build of typedefed_wchar_runtime for unsupported targets, nicer and more compact jamfile instructions) [SVN r77772] --- test/Jamfile.v2 | 60 ++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 131fa3e..2673009 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,50 +1,50 @@ -# Signals library - # Copyright (C) 2001-2003 Douglas Gregor +# Copyright (C) 2011-2012 Antony Polukhin +# +# 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) +# -# Permission to copy, use, sell and distribute this software is granted -# provided this copyright notice appears in all copies. Permission to modify -# the code and to distribute modified code is granted provided this copyright -# notice appears in all copies, and a notice that the code was modified is -# included with the copyright notice. This software is provided "as is" -# without express or implied warranty, and with no claim as to its suitability -# for any purpose. - -# For more information, see http://www.boost.org/ - -# bring in rules for testing import testing ; import feature ; +project + : requirements + /boost/test//boost_unit_test_framework + static + ; + +# Thanks to Steven Watanabe for helping with feature feature.feature nowchar : on : composite optional propagated link-incompatible ; -feature.compose on : /Zc:wchar_t- ; +feature.compose on : /Zc:wchar_t- ; test-suite conversion : [ run implicit_cast.cpp ] [ compile-fail implicit_cast_fail.cpp ] [ run ../cast_test.cpp ] [ run ../numeric_cast_test.cpp ] - [ run ../lexical_cast_test.cpp ../../test/build//boost_unit_test_framework/static ] - [ run lexical_cast_loopback_test.cpp ../../test/build//boost_unit_test_framework/static ] - [ run lexical_cast_abstract_test.cpp ../../test/build//boost_unit_test_framework/static ] - [ run lexical_cast_noncopyable_test.cpp ../../test/build//boost_unit_test_framework/static ] - [ run lexical_cast_vc8_bug_test.cpp ../../test/build//boost_unit_test_framework/static ] - [ run lexical_cast_wchars_test.cpp ../../test/build//boost_unit_test_framework/static ] - [ run lexical_cast_float_types_test.cpp ../../test/build//boost_unit_test_framework/static ] - [ run lexical_cast_inf_nan_test.cpp ../../test/build//boost_unit_test_framework/static ] - [ run lexical_cast_containers_test.cpp ../../test/build//boost_unit_test_framework/static ] - [ run lexical_cast_empty_input_test.cpp ../../test/build//boost_unit_test_framework/static ] - [ run lexical_cast_pointers_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run ../lexical_cast_test.cpp ] + [ run lexical_cast_loopback_test.cpp ] + [ run lexical_cast_abstract_test.cpp ] + [ run lexical_cast_noncopyable_test.cpp ] + [ run lexical_cast_vc8_bug_test.cpp ] + [ run lexical_cast_wchars_test.cpp ] + [ run lexical_cast_float_types_test.cpp ] + [ run lexical_cast_inf_nan_test.cpp ] + [ run lexical_cast_containers_test.cpp ] + [ run lexical_cast_empty_input_test.cpp ] + [ run lexical_cast_pointers_test.cpp ] [ compile lexical_cast_typedefed_wchar_test.cpp : msvc:on ] - [ run lexical_cast_typedefed_wchar_test_runtime.cpp ../../test/build//boost_unit_test_framework/static : : : msvc:on ] - [ run lexical_cast_no_locale_test.cpp ../../test/build//boost_unit_test_framework/static : : : BOOST_NO_STD_LOCALE BOOST_LEXICAL_CAST_ASSUME_C_LOCALE ] - [ run lexical_cast_no_exceptions_test.cpp ../../test/build//boost_unit_test_framework/static : : : BOOST_NO_EXCEPTIONS + [ run lexical_cast_typedefed_wchar_test_runtime.cpp : : : msvc:on msvc,stlport:no ] + [ run lexical_cast_no_locale_test.cpp : : : BOOST_NO_STD_LOCALE BOOST_LEXICAL_CAST_ASSUME_C_LOCALE ] + [ run lexical_cast_no_exceptions_test.cpp : : : BOOST_NO_EXCEPTIONS gcc-4.3:-fno-exceptions gcc-4.4:-fno-exceptions gcc-4.5:-fno-exceptions gcc-4.6:-fno-exceptions + gcc-4.7:-fno-exceptions ] - [ run lexical_cast_iterator_range_test.cpp ../../test/build//boost_unit_test_framework/static ] - ; + [ run lexical_cast_iterator_range_test.cpp ] + ; From 2af8c475588ae0e613679f3cc10b4d571b412e48 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 5 Apr 2012 03:59:02 +0000 Subject: [PATCH 157/242] Fix inspection warning (tab removed) [SVN r77773] --- test/lexical_cast_no_exceptions_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lexical_cast_no_exceptions_test.cpp b/test/lexical_cast_no_exceptions_test.cpp index 8431c3a..dbec8ea 100755 --- a/test/lexical_cast_no_exceptions_test.cpp +++ b/test/lexical_cast_no_exceptions_test.cpp @@ -29,7 +29,7 @@ bool g_was_exception = false; namespace boost { void throw_exception(std::exception const & ) { - g_was_exception = true; + g_was_exception = true; } } From 6ff6958204bc975fb6cb9e30516500b962d75979 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sat, 7 Apr 2012 08:05:16 +0000 Subject: [PATCH 158/242] Removed incorrect test [SVN r77807] --- lexical_cast_test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 4e70bdd..844ee71 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -427,7 +427,6 @@ void test_conversion_to_wstring() BOOST_CHECK(str == lexical_cast(str)); BOOST_CHECK(L"123" == lexical_cast(123)); BOOST_CHECK(L"1.23" == lexical_cast(1.23)); - BOOST_CHECK(L"1.111111111" == lexical_cast(1.111111111)); BOOST_CHECK(L"1" == lexical_cast(true)); BOOST_CHECK(L"0" == lexical_cast(false)); #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) From 8562b480f85c5ba64c24fe262752bc361b252017 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sat, 7 Apr 2012 19:44:07 +0000 Subject: [PATCH 159/242] * fixes #6504 (characters widening fixed) * much more tests * better support for unicode characters and template classes that are instantinated with unicode character types * meta code refactored (it is now shorter and clearer) [SVN r77824] --- include/boost/lexical_cast.hpp | 510 +++++++++++----------- test/Jamfile.v2 | 1 + test/lexical_cast_containers_test.cpp | 23 + test/lexical_cast_iterator_range_test.cpp | 177 ++++---- test/lexical_cast_wchars_test.cpp | 62 ++- 5 files changed, 418 insertions(+), 355 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 61501d6..a0454b3 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -28,36 +28,20 @@ #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(__SUNPRO_CC) -#include -#endif // !defined(__SUNPRO_CC) -#ifndef BOOST_NO_CWCHAR -# include -#endif + #ifndef BOOST_NO_STD_LOCALE # include @@ -137,118 +121,9 @@ namespace boost const std::type_info *target; }; - namespace detail // selectors for choosing stream character type + namespace detail // widest_char { - template - struct stream_char - { - typedef char type; - }; - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct stream_char > - { - typedef BOOST_DEDUCED_TYPENAME stream_char::type type; - }; - - template - struct stream_char > - { - typedef BOOST_DEDUCED_TYPENAME stream_char::type type; - }; - - template - struct stream_char< std::basic_string > - { - typedef CharT type; - }; - -#if !defined(__SUNPRO_CC) - template - struct stream_char< ::boost::container::basic_string > - { - typedef CharT type; - }; -#endif // !defined(__SUNPRO_CC) -#endif - -#ifndef BOOST_LCAST_NO_WCHAR_T -#ifndef BOOST_NO_INTRINSIC_WCHAR_T - 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; - }; - -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - 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 + template struct widest_char { typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< @@ -257,10 +132,162 @@ namespace boost , SourceChar >::type type; }; } +} // namespace boost + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(__SUNPRO_CC) +#include +#endif // !defined(__SUNPRO_CC) +#ifndef BOOST_NO_CWCHAR +# include +#endif + +namespace boost { + namespace detail // widest_char<...> (continuation) + { + struct not_a_character_type{}; + + template + struct widest_char + { + typedef CharT type; + }; + + template + struct widest_char< CharT, not_a_character_type > + { + typedef CharT type; + }; + + template <> + struct widest_char< not_a_character_type, not_a_character_type > + { + typedef char type; + }; + } + + namespace detail // is_char_or_wchar<...> and stream_char<...> templates + { + // returns true, if T is one of the character types + template + struct is_char_or_wchar + { + typedef ::boost::type_traits::ice_or< + ::boost::is_same< T, char >::value, + #ifndef BOOST_LCAST_NO_WCHAR_T + ::boost::is_same< T, wchar_t >::value, + #endif + #ifndef BOOST_NO_CHAR16_T + ::boost::is_same< T, char16_t >::value, + #endif + #ifndef BOOST_NO_CHAR32_T + ::boost::is_same< T, char32_t >::value, + #endif + ::boost::is_same< T, unsigned char >::value, + ::boost::is_same< T, signed char >::value + > result_type; + + BOOST_STATIC_CONSTANT(bool, value = (result_type::value) ); + }; + + // selectors for choosing stream character type + // returns one of char, wchar_t, char16_t, char32_t or not_a_character_type types + template + struct stream_char + { + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< + is_char_or_wchar::value, + Type, + boost::detail::not_a_character_type + >::type type; + }; + + template <> + struct stream_char + { + typedef char type; + }; + + template <> + struct stream_char + { + typedef char type; + }; + + template + struct stream_char + { + typedef BOOST_DEDUCED_TYPENAME stream_char::type type; + }; + + template + struct stream_char + { + typedef BOOST_DEDUCED_TYPENAME stream_char::type type; + }; + + template + struct stream_char > + { + typedef BOOST_DEDUCED_TYPENAME stream_char::type type; + }; + + template + struct stream_char > + { + typedef BOOST_DEDUCED_TYPENAME stream_char::type type; + }; + + template + struct stream_char< std::basic_string > + { + typedef CharT type; + }; + +#if !defined(__SUNPRO_CC) + template + struct stream_char< ::boost::container::basic_string > + { + typedef CharT type; + }; +#endif // !defined(__SUNPRO_CC) + +#if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T) + template<> + struct stream_char + { + typedef boost::detail::not_a_character_type type; + }; + + template<> + struct stream_char + { + typedef wchar_t type; + }; + + template<> + struct stream_char + { + typedef wchar_t type; + }; +#endif + } namespace detail // deduce_char_traits template { -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template struct deduce_char_traits { @@ -325,7 +352,7 @@ namespace boost template struct deduce_char_traits< CharT , ::boost::container::basic_string - , std::basic_string + , ::std::basic_string > { typedef Traits type; @@ -333,14 +360,13 @@ namespace boost template struct deduce_char_traits< CharT - , std::basic_string + , ::std::basic_string , ::boost::container::basic_string > { typedef Traits type; }; #endif // !defined(__SUNPRO_CC) -#endif } namespace detail // lcast_src_length @@ -383,7 +409,7 @@ namespace boost BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256); #endif }; -// 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 \ @@ -1243,7 +1269,7 @@ namespace boost bool shl_char_array(T const* str) { BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)), - "boost::lexical_cast does not support conversions from wchar_t to char types." + "boost::lexical_cast does not support conversions from wide character to char types." "Use boost::locale instead" ); return shl_input_streamable(str); } @@ -1634,19 +1660,13 @@ namespace boost #if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) bool operator>>(char32_t& output) { return shr_xchar(output); } #endif -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - bool operator>>(std::string& str) { str.assign(start, finish); return true; } -# ifndef BOOST_LCAST_NO_WCHAR_T - bool operator>>(std::wstring& str) { str.assign(start, finish); return true; } -# endif -#else template bool operator>>(std::basic_string& str) { str.assign(start, finish); return true; } #if !defined(__SUNPRO_CC) template bool operator>>(::boost::container::basic_string& str) { str.assign(start, finish); return true; } #endif // !defined(__SUNPRO_CC) -#endif + /* * case "-0" || "0" || "+0" : output = false; return true; * case "1" || "+1": output = true; return true; @@ -1752,10 +1772,6 @@ namespace boost }; } -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - // call-by-const reference version - namespace detail { template @@ -1788,60 +1804,6 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = true ); }; #endif // !defined(__SUNPRO_CC) - template - struct is_char_or_wchar - { - private: -#ifndef BOOST_LCAST_NO_WCHAR_T - 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 - ) - ); - }; - - template - struct is_char_iterator_range - { - BOOST_STATIC_CONSTANT(bool, value = false ); - }; - - template - struct is_char_iterator_range > - { - BOOST_STATIC_CONSTANT(bool, value = (is_char_or_wchar::value) ); - }; - - template - struct is_char_iterator_range > - { - BOOST_STATIC_CONSTANT(bool, value = (is_char_or_wchar::value) ); - }; template struct is_arithmetic_and_not_xchars @@ -1970,51 +1932,34 @@ namespace boost "Your compiler does not have full support for char32_t" ); #endif - 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(); - typedef BOOST_DEDUCED_TYPENAME - deduce_char_traits::type traits; + typedef BOOST_DEDUCED_TYPENAME ::boost::detail::deduce_char_traits< + char_type, Target, Source + >::type traits; - typedef BOOST_DEDUCED_TYPENAME remove_pointer::type removed_ptr_t_1; - typedef BOOST_DEDUCED_TYPENAME remove_cv::type removed_ptr_t; + typedef ::boost::type_traits::ice_and< + ::boost::detail::is_char_or_wchar::value, // source is lexical type + ::boost::detail::is_char_or_wchar::value, // target is a lexical type + ::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 + > is_string_widening_required_t; - // is_char_types_match variable value can be computed via - // sizeof(char_type) == sizeof(removed_ptr_t). But when - // removed_ptr_t is an incomplete type or void*, compilers - // produce warnings or errors. - const bool is_char_types_match = - (::boost::type_traits::ice_or< - ::boost::type_traits::ice_and< - ::boost::type_traits::ice_eq::value, - ::boost::type_traits::ice_or< - ::boost::is_same::value, - ::boost::is_same::value, - ::boost::is_same::value - >::value - >::value, - ::boost::is_same::value - >::value); + typedef ::boost::type_traits::ice_or< + ::boost::is_integral::value, + ::boost::detail::is_this_float_conversion_optimized::value, + ::boost::detail::is_char_or_wchar::value + > is_source_input_optimized_t; - const bool requires_stringbuf = - !( - ::boost::type_traits::ice_or< - ::boost::detail::is_stdstring::value, - ::boost::is_integral::value, - ::boost::detail::is_this_float_conversion_optimized::value, - ::boost::type_traits::ice_and< - ::boost::detail::is_char_iterator_range::value, - is_char_types_match - >::value, - ::boost::type_traits::ice_and< - ::boost::is_pointer::value, - ::boost::detail::is_char_or_wchar::value, - is_char_types_match - >::value - >::value - ); + // 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; detail::lexical_stream_limited_src interpreter(buf, buf + src_len); @@ -2030,7 +1975,7 @@ namespace boost # pragma warning( pop ) #endif - template + template struct lexical_cast_copy { static inline Source lexical_cast_impl(const Source &arg) @@ -2039,7 +1984,7 @@ namespace boost } }; - template + template struct detect_precision_loss { typedef boost::numeric::Trunc Rounder; @@ -2063,7 +2008,7 @@ namespace boost typedef typename Rounder::round_style round_style; } ; - template + template struct nothrow_overflow_handler { void operator() ( boost::numeric::range_check_result r ) @@ -2073,7 +2018,7 @@ namespace boost } } ; - template + template struct lexical_cast_dynamic_num_not_ignoring_minus { static inline Target lexical_cast_impl(const Source &arg) @@ -2088,7 +2033,7 @@ namespace boost } }; - template + template struct lexical_cast_dynamic_num_ignoring_minus { static inline Target lexical_cast_impl(const Source &arg) @@ -2125,7 +2070,7 @@ namespace boost * optional, so if a negative number is read, no errors will arise * and the result will be the two's complement. */ - template + template struct lexical_cast_dynamic_num { static inline Target lexical_cast_impl(const Source &arg) @@ -2153,40 +2098,80 @@ namespace boost }; } - template + template inline Target lexical_cast(const Source &arg) { typedef BOOST_DEDUCED_TYPENAME ::boost::detail::array_to_pointer_decay::type src; typedef BOOST_DEDUCED_TYPENAME ::boost::type_traits::ice_or< - ::boost::detail::is_xchar_to_xchar::value, - ::boost::detail::is_char_array_to_stdstring::value, + ::boost::detail::is_xchar_to_xchar::value, + ::boost::detail::is_char_array_to_stdstring::value, ::boost::type_traits::ice_and< - ::boost::is_same::value, - ::boost::detail::is_stdstring::value + ::boost::is_same::value, + ::boost::detail::is_stdstring::value >::value - > do_copy_type; + > shall_we_copy_t; typedef BOOST_DEDUCED_TYPENAME - ::boost::detail::is_arithmetic_and_not_xchars do_copy_with_dynamic_check_type; + ::boost::detail::is_arithmetic_and_not_xchars shall_we_copy_with_dynamic_check_t; typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< - do_copy_type::value, - detail::lexical_cast_copy, + shall_we_copy_t::value, + ::boost::detail::lexical_cast_copy, BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< - do_copy_with_dynamic_check_type::value, - ::boost::detail::lexical_cast_dynamic_num, - ::boost::detail::lexical_cast_do_cast + shall_we_copy_with_dynamic_check_t::value, + ::boost::detail::lexical_cast_dynamic_num, + ::boost::detail::lexical_cast_do_cast >::type >::type caster_type; return caster_type::lexical_cast_impl(arg); } - #else +} // namespace boost - namespace detail // stream wrapper for handling lexical conversions +#else // #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +namespace boost { + namespace detail { + + // selectors for choosing stream character type + template + struct stream_char + { + typedef char type; + }; + +#ifndef BOOST_LCAST_NO_WCHAR_T +#ifndef BOOST_NO_INTRINSIC_WCHAR_T + 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; + }; +#endif + + // stream wrapper for handling lexical conversions template class lexical_stream { @@ -2276,8 +2261,9 @@ namespace boost return result; } - #endif -} +} // namespace boost + +#endif // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2010. @@ -2287,5 +2273,7 @@ namespace boost // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#undef BOOST_LCAST_THROW_BAD_CAST #undef BOOST_LCAST_NO_WCHAR_T -#endif + +#endif // BOOST_LEXICAL_CAST_INCLUDED diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 2673009..6edd59b 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -12,6 +12,7 @@ project : requirements /boost/test//boost_unit_test_framework static + gcc-4.8:BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES ; # Thanks to Steven Watanabe for helping with feature diff --git a/test/lexical_cast_containers_test.cpp b/test/lexical_cast_containers_test.cpp index 0c6315b..e6c544a 100644 --- a/test/lexical_cast_containers_test.cpp +++ b/test/lexical_cast_containers_test.cpp @@ -14,6 +14,8 @@ void testing_boost_containers_basic_string(); void testing_boost_containers_string_std_string(); +void testing_boost_containers_string_widening(); + using namespace boost; @@ -23,6 +25,7 @@ boost::unit_test::test_suite *init_unit_test_suite(int, char *[]) BOOST_TEST_SUITE("Testing boost::lexical_cast with boost::container::string"); suite->add(BOOST_TEST_CASE(testing_boost_containers_basic_string)); suite->add(BOOST_TEST_CASE(testing_boost_containers_string_std_string)); + suite->add(BOOST_TEST_CASE(testing_boost_containers_string_widening)); return suite; } @@ -58,3 +61,23 @@ void testing_boost_containers_string_std_string() #endif } + +void testing_boost_containers_string_widening() +{ + const char char_array[] = "Test string"; + +#ifndef BOOST_LCAST_NO_WCHAR_T + const wchar_t wchar_array[] = L"Test string"; + BOOST_CHECK(boost::lexical_cast(char_array) == wchar_array); +#endif + +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES) + const char16_t char16_array[] = u"Test string"; + BOOST_CHECK(boost::lexical_cast >(char_array) == char16_array); +#endif + +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES) + const char32_t char32_array[] = U"Test string"; + BOOST_CHECK(boost::lexical_cast >(char_array) == char32_array); +#endif +} diff --git a/test/lexical_cast_iterator_range_test.cpp b/test/lexical_cast_iterator_range_test.cpp index 7afb1ae..ca8b3ef 100644 --- a/test/lexical_cast_iterator_range_test.cpp +++ b/test/lexical_cast_iterator_range_test.cpp @@ -43,7 +43,7 @@ inline std::basic_istream& operator >> (std::basic_istream& istr, template -void do_test_iterator_range(const RngT& rng) +void do_test_iterator_range_impl(const RngT& rng) { BOOST_CHECK_EQUAL(lexical_cast(rng), 1); BOOST_CHECK_EQUAL(lexical_cast(rng), 1u); @@ -69,109 +69,128 @@ void do_test_iterator_range(const RngT& rng) #endif } +template +void test_it_range_using_any_chars(CharT* one, CharT* eleven) +{ + typedef CharT test_char_type; + + // Zero terminated + iterator_range rng1(one, one + 1); + do_test_iterator_range_impl(rng1); + + iterator_range crng1(one, one + 1); + do_test_iterator_range_impl(crng1); + + // Non zero terminated + iterator_range rng2(eleven, eleven + 1); + do_test_iterator_range_impl(rng2); + + iterator_range crng2(eleven, eleven + 1); + do_test_iterator_range_impl(crng2); +} + +template +void test_it_range_using_char(CharT* one, CharT* eleven) +{ + typedef CharT test_char_type; + + iterator_range rng1(one, one + 1); + BOOST_CHECK_EQUAL(lexical_cast(rng1), "1"); + + iterator_range crng1(one, one + 1); + BOOST_CHECK_EQUAL(lexical_cast(crng1), "1"); + + iterator_range rng2(eleven, eleven + 1); + BOOST_CHECK_EQUAL(lexical_cast(rng2), "1"); + + iterator_range crng2(eleven, eleven + 1); + BOOST_CHECK_EQUAL(lexical_cast(crng2), "1"); + + +#ifndef BOOST_LCAST_NO_WCHAR_T + BOOST_CHECK(lexical_cast(rng1) == L"1"); + BOOST_CHECK(lexical_cast(crng1) == L"1"); + BOOST_CHECK(lexical_cast(rng2) == L"1"); + BOOST_CHECK(lexical_cast(crng2) == L"1"); +#endif + +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES) + typedef std::basic_string my_char16_string; + BOOST_CHECK(lexical_cast(rng1) == u"1"); + BOOST_CHECK(lexical_cast(crng1) == u"1"); + BOOST_CHECK(lexical_cast(rng2) == u"1"); + BOOST_CHECK(lexical_cast(crng2) == u"1"); +#endif + +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES) + typedef std::basic_string my_char32_string; + BOOST_CHECK(lexical_cast(rng1) == U"1"); + BOOST_CHECK(lexical_cast(crng1) == U"1"); + BOOST_CHECK(lexical_cast(rng2) == U"1"); + BOOST_CHECK(lexical_cast(crng2) == U"1"); +#endif +} + void test_char_iterator_ranges() { typedef char test_char_type; - - // Zero terminated test_char_type data1[] = "1"; - iterator_range rng1(data1, data1 + 1); - do_test_iterator_range(rng1); - BOOST_CHECK_EQUAL(lexical_cast(rng1), "1"); - - const test_char_type cdata1[] = "1"; - iterator_range crng1(cdata1, cdata1 + 1); - do_test_iterator_range(crng1); - BOOST_CHECK_EQUAL(lexical_cast(crng1), "1"); - - // Non zero terminated test_char_type data2[] = "11"; - iterator_range rng2(data2, data2 + 1); - do_test_iterator_range(rng2); - BOOST_CHECK_EQUAL(lexical_cast(rng2), "1"); - - const test_char_type cdata2[] = "11"; - iterator_range crng2(cdata2, cdata2 + 1); - do_test_iterator_range(crng2); - BOOST_CHECK_EQUAL(lexical_cast(crng2), "1"); + test_it_range_using_any_chars(data1, data2); + test_it_range_using_char(data1, data2); } + + void test_unsigned_char_iterator_ranges() { typedef unsigned char test_char_type; - - // Zero terminated test_char_type data1[] = "1"; - iterator_range rng1(data1, data1 + 1); - do_test_iterator_range(rng1); - BOOST_CHECK_EQUAL(lexical_cast(rng1), "1"); - - const test_char_type cdata1[] = "1"; - iterator_range crng1(cdata1, cdata1 + 1); - do_test_iterator_range(crng1); - BOOST_CHECK_EQUAL(lexical_cast(crng1), "1"); - - // Non zero terminated test_char_type data2[] = "11"; - iterator_range rng2(data2, data2 + 1); - do_test_iterator_range(rng2); - BOOST_CHECK_EQUAL(lexical_cast(rng2), "1"); - - const test_char_type cdata2[] = "11"; - iterator_range crng2(cdata2, cdata2 + 1); - do_test_iterator_range(crng2); - BOOST_CHECK_EQUAL(lexical_cast(crng2), "1"); + test_it_range_using_any_chars(data1, data2); + test_it_range_using_char(data1, data2); } void test_signed_char_iterator_ranges() { typedef signed char test_char_type; - - // Zero terminated test_char_type data1[] = "1"; - iterator_range rng1(data1, data1 + 1); - do_test_iterator_range(rng1); - BOOST_CHECK_EQUAL(lexical_cast(rng1), "1"); - - const test_char_type cdata1[] = "1"; - iterator_range crng1(cdata1, cdata1 + 1); - do_test_iterator_range(crng1); - BOOST_CHECK_EQUAL(lexical_cast(crng1), "1"); - - // Non zero terminated test_char_type data2[] = "11"; - iterator_range rng2(data2, data2 + 1); - do_test_iterator_range(rng2); - BOOST_CHECK_EQUAL(lexical_cast(rng2), "1"); - - const test_char_type cdata2[] = "11"; - iterator_range crng2(cdata2, cdata2 + 1); - do_test_iterator_range(crng2); - BOOST_CHECK_EQUAL(lexical_cast(crng2), "1"); + test_it_range_using_any_chars(data1, data2); + test_it_range_using_char(data1, data2); } -void test_wide_char_iterator_ranges() +void test_wchar_iterator_ranges() { #ifndef BOOST_LCAST_NO_WCHAR_T typedef wchar_t test_char_type; - - // Zero terminated test_char_type data1[] = L"1"; - iterator_range rng1(data1, data1 + 1); - do_test_iterator_range(rng1); - - const test_char_type cdata1[] = L"1"; - iterator_range crng1(cdata1, cdata1 + 1); - do_test_iterator_range(crng1); - - // Non zero terminated test_char_type data2[] = L"11"; - iterator_range rng2(data2, data2 + 1); - do_test_iterator_range(rng2); + test_it_range_using_any_chars(data1, data2); +#endif - const test_char_type cdata2[] = L"11"; - iterator_range crng2(cdata2, cdata2 + 1); - do_test_iterator_range(crng2); + BOOST_CHECK(true); +} + +void test_char16_iterator_ranges() +{ +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) + typedef char16_t test_char_type; + test_char_type data1[] = u"1"; + test_char_type data2[] = u"11"; + test_it_range_using_any_chars(data1, data2); +#endif + + BOOST_CHECK(true); +} + +void test_char32_iterator_ranges() +{ +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) + typedef char32_t test_char_type; + test_char_type data1[] = U"1"; + test_char_type data2[] = U"11"; + test_it_range_using_any_chars(data1, data2); #endif BOOST_CHECK(true); @@ -183,7 +202,9 @@ unit_test::test_suite *init_unit_test_suite(int, char *[]) suite->add(BOOST_TEST_CASE(&test_char_iterator_ranges)); suite->add(BOOST_TEST_CASE(&test_unsigned_char_iterator_ranges)); suite->add(BOOST_TEST_CASE(&test_signed_char_iterator_ranges)); - suite->add(BOOST_TEST_CASE(&test_wide_char_iterator_ranges)); + suite->add(BOOST_TEST_CASE(&test_wchar_iterator_ranges)); + suite->add(BOOST_TEST_CASE(&test_char16_iterator_ranges)); + suite->add(BOOST_TEST_CASE(&test_char32_iterator_ranges)); return suite; } diff --git a/test/lexical_cast_wchars_test.cpp b/test/lexical_cast_wchars_test.cpp index acd78b1..f78de1d 100755 --- a/test/lexical_cast_wchars_test.cpp +++ b/test/lexical_cast_wchars_test.cpp @@ -2,7 +2,7 @@ // // See http://www.boost.org for most recent version, including documentation. // -// Copyright Antony Polukhin, 2011. +// Copyright Antony Polukhin, 2011-2012. // // Distributed under the Boost // Software License, Version 1.0. (See accompanying file @@ -17,40 +17,70 @@ #endif #include - -#include #include -#include using namespace boost; -void test_char_types_conversions() +#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) +#define BOOST_LCAST_NO_WCHAR_T +#endif + +template +void test_impl(const CharT* wc_arr) { -#ifndef BOOST_LCAST_NO_WCHAR_T + typedef CharT wide_char; + typedef std::basic_string wide_string; 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"; - const wchar_t wc_arr[] =L"Test array of chars"; // Following tests depend on realization of std::locale // and pass for popular compilers and STL realizations - BOOST_CHECK(boost::lexical_cast(c_arr[0]) == wc_arr[0]); - BOOST_CHECK(boost::lexical_cast(c_arr) == std::wstring(wc_arr)); + BOOST_CHECK(boost::lexical_cast(c_arr[0]) == wc_arr[0]); + BOOST_CHECK(boost::lexical_cast(c_arr) == wide_string(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(sc_arr) == wide_string(wc_arr) ); + BOOST_CHECK(boost::lexical_cast(uc_arr) == wide_string(wc_arr) ); - BOOST_CHECK_EQUAL(boost::lexical_cast(uc_arr[0]), wc_arr[0]); - BOOST_CHECK_EQUAL(boost::lexical_cast(sc_arr[0]), wc_arr[0]); + BOOST_CHECK_EQUAL(boost::lexical_cast(uc_arr[0]), wc_arr[0]); + BOOST_CHECK_EQUAL(boost::lexical_cast(sc_arr[0]), wc_arr[0]); +} + + +void test_char_types_conversions_wchar_t() +{ +#ifndef BOOST_LCAST_NO_WCHAR_T + test_impl(L"Test array of chars"); #endif - BOOST_CHECK(1); + + BOOST_CHECK(true); +} + +void test_char_types_conversions_char16_t() +{ +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES) + test_impl(u"Test array of chars"); +#endif + + BOOST_CHECK(true); +} + +void test_char_types_conversions_char32_t() +{ +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES) + test_impl(U"Test array of chars"); +#endif + + BOOST_CHECK(true); } unit_test::test_suite *init_unit_test_suite(int, char *[]) { unit_test::test_suite *suite = - BOOST_TEST_SUITE("lexical_cast char<->wchar_t unit test"); - suite->add(BOOST_TEST_CASE(&test_char_types_conversions)); + BOOST_TEST_SUITE("lexical_cast char => wide characters unit test (widening test)"); + suite->add(BOOST_TEST_CASE(&test_char_types_conversions_wchar_t)); + suite->add(BOOST_TEST_CASE(&test_char_types_conversions_char16_t)); + suite->add(BOOST_TEST_CASE(&test_char_types_conversions_char32_t)); return suite; } From 7881eb5666c6f8c961a8a540e691d7c4215d9353 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 9 Apr 2012 18:07:51 +0000 Subject: [PATCH 160/242] Remove incorrect test [SVN r77854] --- test/lexical_cast_iterator_range_test.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/lexical_cast_iterator_range_test.cpp b/test/lexical_cast_iterator_range_test.cpp index ca8b3ef..80008d9 100644 --- a/test/lexical_cast_iterator_range_test.cpp +++ b/test/lexical_cast_iterator_range_test.cpp @@ -63,10 +63,6 @@ void do_test_iterator_range_impl(const RngT& rng) BOOST_CHECK_EQUAL(lexical_cast(rng), 1u); BOOST_CHECK_EQUAL(lexical_cast<__int64>(rng), 1); #endif - -#ifndef BOOST_LCAST_NO_WCHAR_T - BOOST_CHECK(lexical_cast(rng) == L"1"); -#endif } template From 35d592fc21bcb91ba21ddc1948d7c5af4c6a4290 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 11 Apr 2012 18:34:10 +0000 Subject: [PATCH 161/242] Fix iterator_range test for compilers with new unicode characters but without new unicode locales support [SVN r77921] --- test/lexical_cast_iterator_range_test.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/lexical_cast_iterator_range_test.cpp b/test/lexical_cast_iterator_range_test.cpp index 80008d9..d54de7a 100644 --- a/test/lexical_cast_iterator_range_test.cpp +++ b/test/lexical_cast_iterator_range_test.cpp @@ -51,11 +51,13 @@ void do_test_iterator_range_impl(const RngT& rng) BOOST_CHECK_EQUAL(lexical_cast(rng), 1u); BOOST_CHECK_EQUAL(lexical_cast(rng), 1); BOOST_CHECK_EQUAL(lexical_cast(rng), 1u); + +#ifdef BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES BOOST_CHECK_EQUAL(lexical_cast(rng), 1.0f); BOOST_CHECK_EQUAL(lexical_cast(rng), 1.0); BOOST_CHECK_EQUAL(lexical_cast(rng), 1.0L); BOOST_CHECK_EQUAL(lexical_cast(rng), 1); - +#endif #if defined(BOOST_HAS_LONG_LONG) BOOST_CHECK_EQUAL(lexical_cast(rng), 1u); BOOST_CHECK_EQUAL(lexical_cast(rng), 1); @@ -102,6 +104,15 @@ void test_it_range_using_char(CharT* one, CharT* eleven) iterator_range crng2(eleven, eleven + 1); BOOST_CHECK_EQUAL(lexical_cast(crng2), "1"); + BOOST_CHECK_EQUAL(lexical_cast(rng1), 1.0f); + BOOST_CHECK_EQUAL(lexical_cast(rng1), 1.0); + BOOST_CHECK_EQUAL(lexical_cast(rng1), 1.0L); + BOOST_CHECK_EQUAL(lexical_cast(rng1), 1); + + BOOST_CHECK_EQUAL(lexical_cast(crng2), 1.0f); + BOOST_CHECK_EQUAL(lexical_cast(crng2), 1.0); + BOOST_CHECK_EQUAL(lexical_cast(crng2), 1.0L); + BOOST_CHECK_EQUAL(lexical_cast(crng2), 1); #ifndef BOOST_LCAST_NO_WCHAR_T BOOST_CHECK(lexical_cast(rng1) == L"1"); From 674e71fb7d8a23a3b0146c94fa23c731c83c2652 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 12 Apr 2012 17:15:22 +0000 Subject: [PATCH 162/242] Fix compile time error in lexical_cast, when new unicode characters are being converted (Refs #6504 ) [SVN r77936] --- include/boost/lexical_cast.hpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index a0454b3..9897f16 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1243,7 +1243,7 @@ namespace boost { bool shl_char(T ch) { BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)) , - "boost::lexical_cast does not support conversions from wchar_t to char types." + "boost::lexical_cast does not support conversions from wide character to char types." "Use boost::locale instead" ); #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE std::locale loc; @@ -1269,7 +1269,7 @@ namespace boost { bool shl_char_array(T const* str) { BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)), - "boost::lexical_cast does not support conversions from wide character to char types." + "boost::lexical_cast does not support conversions from wide characters to char types." "Use boost::locale instead" ); return shl_input_streamable(str); } @@ -1456,6 +1456,16 @@ namespace boost { #ifndef BOOST_NO_INTRINSIC_WCHAR_T bool operator<<(wchar_t ch) { return shl_char(ch); } #endif +#endif +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) + bool operator<<(char16_t ch) { return shl_char(ch); } + bool operator<<(char16_t * str) { return shl_char_array(str); } + bool operator<<(char16_t const * str) { return shl_char_array(str); } +#endif +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) + bool operator<<(char32_t ch) { return shl_char(ch); } + bool operator<<(char32_t * str) { return shl_char_array(str); } + bool operator<<(char32_t const * str) { return shl_char_array(str); } #endif bool operator<<(unsigned char const* ch) { return ((*this) << reinterpret_cast(ch)); } bool operator<<(unsigned char * ch) { return ((*this) << reinterpret_cast(ch)); } From 746d466e382dff03b05d7c284634138e546046fb Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 16 Apr 2012 17:13:11 +0000 Subject: [PATCH 163/242] Comment out bad advise in documentation ( refs #6786, refs #6663) [SVN r78015] --- doc/lexical_cast.qbk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index ffab311..3c8c332 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -115,6 +115,7 @@ Exception used to indicate runtime lexical_cast failure. [endsect] +[/ Commenting out bad advise (this will break the ability to get correct function pointers via &lexical_cast) [section Tuning classes for fast lexical conversions] Because of `boost::lexical_cast` optimizations for `boost::iterator_range`, it is possibile to make very fast lexical conversions for non zero terminated strings, substrings and user-defined classes. @@ -162,7 +163,7 @@ namespace boost { `` Now `boost::lexical_cast(example_class_instance)` conversions won't copy data and construct heavy STL stream objects. See [link boost_lexical_cast.performance Performance] section for info on `boost::iterator_range` conversion performance. [endsect] - +] [section Frequently Asked Questions] From 9ff79f4df9e0b9d359b9d1d505fa8223a52a43ca Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 17 Apr 2012 16:27:50 +0000 Subject: [PATCH 164/242] Update documentation ( more info about stream character type detection + warn about new unicode types support; refs #6786, refs #6663) [SVN r78044] --- doc/lexical_cast.qbk | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index 3c8c332..5613cd0 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -97,7 +97,21 @@ The requirements on the argument and result types are: * Target is CopyConstructible [20.1.3]. * Target is DefaultConstructible, meaning that it is possible to default-initialize an object of that type [8.5, 20.1.4]. -The character type of the underlying stream is assumed to be char unless either the Source or the Target requires wide-character streaming, in which case the underlying stream uses `wchar_t`. Source types that require wide-character streaming are `wchar_t`, `wchar_t *`, and `std::wstring`. Target types that require wide-character streaming are `wchar_t` and `std::wstring`. +The character type of the underlying stream is assumed to be `char` unless either the `Source` or the `Target` requires wide-character streaming, in which case the underlying stream uses `wchar_t`, `char16_t` or `char32_t`. Wide-character streaming is currently detected for: + +* Single character: `wchar_t`, `char16_t`, `char32_t` +* Arrays of characters: `wchar_t *`, `char16_t *`, `char32_t *`, `const wchar_t *`, `const char16_t *`, `const char32_t *` +* Strings: `std::basic_string`, `boost::containers::basic_string` +* Character ranges: `boost::iterator_range`, `boost::iterator_range` + +[important Many compilers and runtime libraries fail to make conversions using new Unicode characters. Make shure that the following code compiles and outputs nonzero values, before using new types: +`` + std::cout + << booat::lexical_cast(1.0).size() + << " " + << booat::lexical_cast(1.0).size(); +`` +] Where a higher degree of control is required over conversions, `std::stringstream` and `std::wstringstream` offer a more appropriate path. Where non-stream-based conversions are required, `lexical_cast` is the wrong tool for the job and is not special-cased for such scenarios. [endsect] @@ -146,9 +160,9 @@ Consider the following example: This is a good generic solution for most use cases. But we can make it even faster for some performance critical applications. During conversion, we loose speed at: -* `std::ostream` construction (it makes some heap allocations) -* `operator <<` (it copyies one by one all the symbols to an instance of `std::ostream`) -* `std::ostream` destruction (it makes some heap deallocations) + * `std::ostream` construction (it makes some heap allocations) + * `operator <<` (it copyies one by one all the symbols to an instance of `std::ostream`) + * `std::ostream` destruction (it makes some heap deallocations) We can avoid all of this, by specifieng an overload for `boost::lexical_cast`: `` From d963842d7042905e560160069b1352d2cf14906d Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 17 Apr 2012 18:00:30 +0000 Subject: [PATCH 165/242] Typo fix in documentation. New line added to the end of lexical_cast.hpp file [SVN r78051] --- doc/lexical_cast.qbk | 2 +- include/boost/lexical_cast.hpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index 5613cd0..c786fbc 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -102,7 +102,7 @@ The character type of the underlying stream is assumed to be `char` unless eithe * Single character: `wchar_t`, `char16_t`, `char32_t` * Arrays of characters: `wchar_t *`, `char16_t *`, `char32_t *`, `const wchar_t *`, `const char16_t *`, `const char32_t *` * Strings: `std::basic_string`, `boost::containers::basic_string` -* Character ranges: `boost::iterator_range`, `boost::iterator_range` +* `boost::iterator_range`, where `WideCharPtr` is a pointer to wide-character or pointer to const wide-character [important Many compilers and runtime libraries fail to make conversions using new Unicode characters. Make shure that the following code compiles and outputs nonzero values, before using new types: `` diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 9897f16..2e5c140 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -2287,3 +2287,4 @@ namespace boost { #undef BOOST_LCAST_NO_WCHAR_T #endif // BOOST_LEXICAL_CAST_INCLUDED + From 15ab0d6385092055356eddd9d35600c5c4940b07 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sat, 21 Apr 2012 11:08:03 +0000 Subject: [PATCH 166/242] Fixes #6812 (now converting "." to float type throws bad_lexical_cast) [SVN r78111] --- include/boost/lexical_cast.hpp | 3 ++- test/lexical_cast_float_types_test.cpp | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 2e5c140..fb76d29 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1062,9 +1062,10 @@ namespace boost { ) return false; #endif - if(*begin == decimal_point){ + if(*begin == decimal_point) { ++ begin; found_decimal = true; + if (!found_number_before_exp && begin==end) return false; continue; }else { if (!found_number_before_exp) return false; diff --git a/test/lexical_cast_float_types_test.cpp b/test/lexical_cast_float_types_test.cpp index 808f456..60db0e1 100755 --- a/test/lexical_cast_float_types_test.cpp +++ b/test/lexical_cast_float_types_test.cpp @@ -261,6 +261,7 @@ void test_converion_to_float_types() BOOST_CHECK_THROW(lexical_cast(".e"), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(".11111111111111111111111111111111111111111111111111111111111111111111ee"), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(".11111111111111111111111111111111111111111111111111111111111111111111e-"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("."), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast("-B"), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast("0xB"), bad_lexical_cast); @@ -276,6 +277,7 @@ void test_converion_to_float_types() BOOST_CHECK_THROW(lexical_cast("-"), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast('\0'), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast('-'), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast('.'), bad_lexical_cast); } template From d30dd9e3c8e78c3d01c90ded5734381b1dfc17e8 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 2 May 2012 19:00:37 +0000 Subject: [PATCH 167/242] =?UTF-8?q?Fixes=20#6852=20(ISO=20C++=20does=20not?= =?UTF-8?q?=20support=20the=20=E2=80=98%lg=E2=80=99=20gnu=5Fprintf=20forma?= =?UTF-8?q?t=20fixed)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [SVN r78308] --- include/boost/lexical_cast.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index fb76d29..328700b 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1322,7 +1322,8 @@ namespace boost { { using namespace std; if (put_inf_nan(begin, end, val)) return true; end = begin; - end += sprintf(begin,"%.*g", static_cast(boost::detail::lcast_get_precision()), val); + const double val_as_double = val; + end += sprintf(begin,"%.*g", static_cast(boost::detail::lcast_get_precision()), val_as_double); return end > begin; } @@ -1330,7 +1331,7 @@ namespace boost { { using namespace std; if (put_inf_nan(begin, end, val)) return true; end = begin; - end += sprintf(begin,"%.*lg", static_cast(boost::detail::lcast_get_precision()), val); + end += sprintf(begin,"%.*g", static_cast(boost::detail::lcast_get_precision()), val); return end > begin; } From bb46dbc46c70f0d7dbdd05dfa5f92404e4b6921f Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 10 May 2012 17:39:46 +0000 Subject: [PATCH 168/242] =?UTF-8?q?Fixes=20#6852=20for=20wide=20characters?= =?UTF-8?q?=20(ISO=20C++=20does=20not=20support=20the=20=E2=80=98%lg?= =?UTF-8?q?=E2=80=99=20gnu=5Fprintf=20format=20fixed)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [SVN r78408] --- include/boost/lexical_cast.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 328700b..c2580ec 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1354,8 +1354,11 @@ namespace boost { static bool shl_real_type(float val, wchar_t* begin, wchar_t*& end) { using namespace std; if (put_inf_nan(begin, end, val)) return true; + const double val_as_double = val; end = begin + swprintf(begin, end-begin, - L"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); + L"%.*g", + static_cast(boost::detail::lcast_get_precision()), + val_as_double ); return end > begin; } @@ -1363,7 +1366,7 @@ namespace boost { { using namespace std; if (put_inf_nan(begin, end, val)) return true; end = begin + swprintf(begin, end-begin, - L"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); + L"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); return end > begin; } From e691b15b775fe7f428569cc34b439272e35dbb2d Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 15 May 2012 18:51:35 +0000 Subject: [PATCH 169/242] Force PGI and SunCC compillers to use fallback version of lexical_cast [SVN r78485] --- include/boost/lexical_cast.hpp | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index c2580ec..a9550d5 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -134,7 +134,7 @@ namespace boost } } // namespace boost -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) && !defined(__PGIC__) #include #include @@ -147,9 +147,7 @@ namespace boost #include #include #include -#if !defined(__SUNPRO_CC) #include -#endif // !defined(__SUNPRO_CC) #ifndef BOOST_NO_CWCHAR # include #endif @@ -256,13 +254,11 @@ namespace boost { typedef CharT type; }; -#if !defined(__SUNPRO_CC) template struct stream_char< ::boost::container::basic_string > { typedef CharT type; }; -#endif // !defined(__SUNPRO_CC) #if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T) template<> @@ -312,7 +308,6 @@ namespace boost { typedef Traits type; }; -#if !defined(__SUNPRO_CC) template struct deduce_char_traits< CharT , ::boost::container::basic_string @@ -366,7 +361,6 @@ namespace boost { { typedef Traits type; }; -#endif // !defined(__SUNPRO_CC) } namespace detail // lcast_src_length @@ -1389,7 +1383,6 @@ namespace boost { return true; } -#if !defined(__SUNPRO_CC) template bool operator<<(::boost::container::basic_string const& str) { @@ -1397,7 +1390,7 @@ namespace boost { finish = start + str.length(); return true; } -#endif // !defined(__SUNPRO_CC) + bool operator<<(bool value) { CharT const czero = lcast_char_constants::zero; @@ -1677,10 +1670,9 @@ namespace boost { #endif template bool operator>>(std::basic_string& str) { str.assign(start, finish); return true; } -#if !defined(__SUNPRO_CC) + template bool operator>>(::boost::container::basic_string& str) { str.assign(start, finish); return true; } -#endif // !defined(__SUNPRO_CC) /* * case "-0" || "0" || "+0" : output = false; return true; @@ -1812,13 +1804,12 @@ namespace boost { { BOOST_STATIC_CONSTANT(bool, value = true ); }; -#if !defined(__SUNPRO_CC) + template struct is_stdstring< ::boost::container::basic_string > { BOOST_STATIC_CONSTANT(bool, value = true ); }; -#endif // !defined(__SUNPRO_CC) template struct is_arithmetic_and_not_xchars @@ -1904,7 +1895,7 @@ namespace boost { { BOOST_STATIC_CONSTANT(bool, value = true ); }; -#if !defined(__SUNPRO_CC) + template struct is_char_array_to_stdstring< ::boost::container::basic_string, CharT* > { @@ -1916,7 +1907,6 @@ namespace boost { { BOOST_STATIC_CONSTANT(bool, value = true ); }; -#endif // !defined(__SUNPRO_CC) #if (defined _MSC_VER) # pragma warning( push ) From c6318e381992313b08ec032d9ac996f2c3cb823a Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 20 May 2012 16:25:21 +0000 Subject: [PATCH 170/242] Do not force PGI compiler to use fallback version of lexical_cast (PGI fails tests even in fallback version) Trialing whitespaces removed [SVN r78521] --- doc/Jamfile.v2 | 6 +- doc/lexical_cast.qbk | 62 +++++++++---------- perf/Jamfile.v2 | 10 +-- test/Jamfile.v2 | 10 +-- test/implicit_cast.cpp | 2 +- test/lexical_cast_containers_test.cpp | 2 +- test/lexical_cast_float_types_test.cpp | 2 +- test/lexical_cast_iterator_range_test.cpp | 12 ++-- test/lexical_cast_no_exceptions_test.cpp | 14 ++--- test/lexical_cast_no_locale_test.cpp | 10 +-- ...ical_cast_typedefed_wchar_test_runtime.cpp | 2 +- 11 files changed, 66 insertions(+), 66 deletions(-) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index b629c6a..0b47ee3 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -6,9 +6,9 @@ using quickbook ; import boostbook : boostbook ; xml lexical_cast : lexical_cast.qbk ; -boostbook standalone - : - lexical_cast +boostbook standalone + : + lexical_cast : boost.root=../../../.. pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index c786fbc..b856594 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -34,7 +34,7 @@ The standard C++ library offers `stringstream` for the kind of in-core formattin The `lexical_cast` function template offers a convenient and consistent form for supporting common conversions to and from arbitrary types when they are represented as text. The simplification it offers is in expression-level convenience for such conversions. For more involved conversions, such as where precision or formatting need tighter control than is offered by the default behavior of `lexical_cast`, the conventional `std::stringstream` approach is recommended. Where the conversions are numeric to numeric, __numericcast__ may offer more reasonable behavior than `lexical_cast`. -For a good discussion of the options and issues involved in string-based formatting, including comparison of `stringstream`, `lexical_cast`, and others, see Herb Sutter's article, [@http://www.gotw.ca/publications/mill19.htm The String Formatters of Manor Farm]. Also, take a look at the [link boost_lexical_cast.performance Performance] section. +For a good discussion of the options and issues involved in string-based formatting, including comparison of `stringstream`, `lexical_cast`, and others, see Herb Sutter's article, [@http://www.gotw.ca/publications/mill19.htm The String Formatters of Manor Farm]. Also, take a look at the [link boost_lexical_cast.performance Performance] section. [endsect] [section Examples] @@ -105,8 +105,8 @@ The character type of the underlying stream is assumed to be `char` unless eithe * `boost::iterator_range`, where `WideCharPtr` is a pointer to wide-character or pointer to const wide-character [important Many compilers and runtime libraries fail to make conversions using new Unicode characters. Make shure that the following code compiles and outputs nonzero values, before using new types: -`` - std::cout +`` + std::cout << booat::lexical_cast(1.0).size() << " " << booat::lexical_cast(1.0).size(); @@ -151,13 +151,13 @@ Consider the following example: return data_length; } }; - + inline std::ostream& operator << (std::ostream& ostr, const example_class& rhs) { return ostr << boost::make_iterator_range(rhs.data(), rhs.data() + rhs.size()); } `` -This is a good generic solution for most use cases. +This is a good generic solution for most use cases. But we can make it even faster for some performance critical applications. During conversion, we loose speed at: * `std::ostream` construction (it makes some heap allocations) @@ -182,35 +182,35 @@ Now `boost::lexical_cast(example_class_instance)` conversions won't c [section Frequently Asked Questions] * [*Question:] Why does `lexical_cast("127")` throw `bad_lexical_cast`? - * [*Answer:] The type `int8_t` is a `typedef` to `char` or `signed char`. Lexical conversion to these types is simply reading a byte from source but since the source has more than one byte, the exception is thrown. -Please use other integer types such as `int` or `short int`. If bounds checking is important, you can also -call __numericcast__: + * [*Answer:] The type `int8_t` is a `typedef` to `char` or `signed char`. Lexical conversion to these types is simply reading a byte from source but since the source has more than one byte, the exception is thrown. +Please use other integer types such as `int` or `short int`. If bounds checking is important, you can also +call __numericcast__: `numeric_cast(lexical_cast("127"));` [pre ] * [*Question:] Why does `lexical_cast("127")` throw `bad_lexical_cast`? - * [*Answer:] Lexical conversion to any char type is simply reading a byte from source. But since the source has more than one byte, the exception is thrown. -Please use other integer types such as `int` or `short int`. If bounds checking is important, you can also -call __numericcast__: + * [*Answer:] Lexical conversion to any char type is simply reading a byte from source. But since the source has more than one byte, the exception is thrown. +Please use other integer types such as `int` or `short int`. If bounds checking is important, you can also +call __numericcast__: `numeric_cast(lexical_cast("127"));` [pre ] * [*Question:] What does `lexical_cast` of an `int8_t` or `uint8_t` not do what I expect? - * [*Answer:] As above, note that int8_t and uint8_t are actually chars and are formatted as such. To avoid + * [*Answer:] As above, note that int8_t and uint8_t are actually chars and are formatted as such. To avoid this, cast to an integer type first: `lexical_cast(static_cast(n));` [pre ] -* [*Question:] The implementation always resets the `ios_base::skipws` flag of an underlying stream object. +* [*Question:] The implementation always resets the `ios_base::skipws` flag of an underlying stream object. It breaks my `operator>>` that works only in presence of this flag. Can you remove code that resets the flag? - * [*Answer:] May be in a future version. There is no requirement in -__proposallong__ to reset the flag but -remember that __proposalshort__ is not yet accepted by the committee. By the way, it's a great opportunity to + * [*Answer:] May be in a future version. There is no requirement in +__proposallong__ to reset the flag but +remember that __proposalshort__ is not yet accepted by the committee. By the way, it's a great opportunity to make your `operator>>` conform to the standard. Read a good C++ book, study `std::sentry` and [@boost:libs/io/doc/ios_state.html `ios_state_saver`]. @@ -218,17 +218,17 @@ Read a good C++ book, study `std::sentry` and [@boost:libs/io/doc/ios_state.html ] * [*Question:] Why `std::cout << boost::lexical_cast("-1");` does not throw, but outputs 4294967295? - * [*Answer:] `boost::lexical_cast` has the behavior of `std::stringstream`, which uses `num_get` functions of -`std::locale` to convert numbers. If we look at the Programming languages — C++, we'll see, that `num_get` uses -the rules of `scanf` for conversions. And in the C99 standard for unsigned input value minus sign is optional, so + * [*Answer:] `boost::lexical_cast` has the behavior of `std::stringstream`, which uses `num_get` functions of +`std::locale` to convert numbers. If we look at the Programming languages — C++, we'll see, that `num_get` uses +the rules of `scanf` for conversions. And in the C99 standard for unsigned input value minus sign is optional, so if a negative number is read, no errors will arise and the result will be the two's complement. [pre ] * [*Question:] Why `boost::lexical_cast(L'A');` outputs 65 and `boost::lexical_cast(L"65");` does not throw? - * [*Answer:] If you are using an old version of Visual Studio or compile code with /Zc:wchar_t- flag, -`boost::lexical_cast` sees single `wchar_t` character as `unsigned short`. It is not a `boost::lexical_cast` mistake, but a + * [*Answer:] If you are using an old version of Visual Studio or compile code with /Zc:wchar_t- flag, +`boost::lexical_cast` sees single `wchar_t` character as `unsigned short`. It is not a `boost::lexical_cast` mistake, but a limitation of compiler options that you use. [pre @@ -236,7 +236,7 @@ limitation of compiler options that you use. * [*Question:] Why `boost::lexical_cast("-1.#IND");` throws `boost::bad_lexical_cast`? * [*Answer:] `"-1.#IND"` is a compiler extension, that violates standard. You shall input `"-nan"`, `"nan"`, `"inf"` -, `"-inf"` (case insensitive) strings to get NaN and Inf values. `boost::lexical_cast` outputs `"-nan"`, `"nan"`, +, `"-inf"` (case insensitive) strings to get NaN and Inf values. `boost::lexical_cast` outputs `"-nan"`, `"nan"`, `"inf"`, `"-inf"` strings, when has NaN or Inf input values. * [*Question:] What is the fastest way to convert a non zero terminated string or a substring using `boost::lexical_cast`? @@ -246,21 +246,21 @@ limitation of compiler options that you use. [section Changes] * [*boost 1.50.0 :] - + * `boost::bad_lexical_cast` exception is now globaly visible and can be catched even if code is compiled with -fvisibility=hidden. * Now it is possible to compile library with disabled exceptions. * Better performance, less memory usage and bugfixes for `boost::iterator_range` conversions. * [*boost 1.49.0 :] - - * Restored work with typedefed wchar_t (compilation flag /Zc:wchar_t- for Visual Studio). + + * Restored work with typedefed wchar_t (compilation flag /Zc:wchar_t- for Visual Studio). * Better performance and less memory usage for `boost::container::basic_string` conversions. - + * [*boost 1.48.0 :] - - * Added code to work with Inf and NaN on any platform. + + * Added code to work with Inf and NaN on any platform. * Better performance and less memory usage for conversions to float type (and to double type, if `sizeof(double) < sizeof(long double)`). - + * [*boost 1.47.0 :] * Optimizations for "C" and other locales without number grouping. @@ -283,7 +283,7 @@ limitation of compiler options that you use. * The previous version of lexical_cast used the default stream precision for reading and writing floating-point numbers. For numerics that have a corresponding specialization of `std::numeric_limits`, the current version now chooses a precision to match. * The previous version of lexical_cast did not support conversion to or from any wide-character-based types. For compilers with full language and library support for wide characters, `lexical_cast` now supports conversions from `wchar_t`, `wchar_t *`, and `std::wstring` and to `wchar_t` and `std::wstring`. * The previous version of `lexical_cast` assumed that the conventional stream extractor operators were sufficient for reading values. However, string I/O is asymmetric, with the result that spaces play the role of I/O separators rather than string content. The current version fixes this error for `std::string` and, where supported, `std::wstring`: `lexical_cast("Hello, World")` succeeds instead of failing with a `bad_lexical_cast` exception. - * The previous version of `lexical_cast` allowed unsafe and meaningless conversions to pointers. The current version now throws a `bad_lexical_cast` for conversions to pointers: `lexical_cast("Goodbye, World")` now throws an exception instead of causing undefined behavior. + * The previous version of `lexical_cast` allowed unsafe and meaningless conversions to pointers. The current version now throws a `bad_lexical_cast` for conversions to pointers: `lexical_cast("Goodbye, World")` now throws an exception instead of causing undefined behavior. [endsect] @@ -328,7 +328,7 @@ All the tests measure execution speed in milliseconds for 10000 iterations of th ``] ] ] -Fastest results are highlitened with "!!! *x* !!!". +Fastest results are highlitened with "!!! *x* !!!". Do not use this results to compare compilers, because tests were taken on different hardware. [endsect] diff --git a/perf/Jamfile.v2 b/perf/Jamfile.v2 index 78176be..6f03fe1 100644 --- a/perf/Jamfile.v2 +++ b/perf/Jamfile.v2 @@ -13,17 +13,17 @@ path-constant TEST_DIR : . ; project performance/test : source-location ./ - : requirements -# /boost/chrono//boost_chrono + : requirements +# /boost/chrono//boost_chrono # /boost/system//boost_system static - freebsd:"-lrt" + freebsd:"-lrt" linux:"-lrt" gcc:-fvisibility=hidden intel-linux:-fvisibility=hidden sun:-xldscope=hidden : default-build release ; - + run performance_test.cpp : $(TEST_DIR) ; - + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 6edd59b..f8ee0d3 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -11,20 +11,20 @@ import feature ; project : requirements /boost/test//boost_unit_test_framework - static + static gcc-4.8:BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES ; -# Thanks to Steven Watanabe for helping with feature +# Thanks to Steven Watanabe for helping with feature feature.feature nowchar : on : composite optional propagated link-incompatible ; feature.compose on : /Zc:wchar_t- ; - + test-suite conversion : [ run implicit_cast.cpp ] [ compile-fail implicit_cast_fail.cpp ] [ run ../cast_test.cpp ] - [ run ../numeric_cast_test.cpp ] + [ run ../numeric_cast_test.cpp ] [ run ../lexical_cast_test.cpp ] [ run lexical_cast_loopback_test.cpp ] [ run lexical_cast_abstract_test.cpp ] @@ -39,7 +39,7 @@ test-suite conversion [ compile lexical_cast_typedefed_wchar_test.cpp : msvc:on ] [ run lexical_cast_typedefed_wchar_test_runtime.cpp : : : msvc:on msvc,stlport:no ] [ run lexical_cast_no_locale_test.cpp : : : BOOST_NO_STD_LOCALE BOOST_LEXICAL_CAST_ASSUME_C_LOCALE ] - [ run lexical_cast_no_exceptions_test.cpp : : : BOOST_NO_EXCEPTIONS + [ run lexical_cast_no_exceptions_test.cpp : : : BOOST_NO_EXCEPTIONS gcc-4.3:-fno-exceptions gcc-4.4:-fno-exceptions gcc-4.5:-fno-exceptions diff --git a/test/implicit_cast.cpp b/test/implicit_cast.cpp index 8c3bc52..0cad067 100644 --- a/test/implicit_cast.cpp +++ b/test/implicit_cast.cpp @@ -28,7 +28,7 @@ int main() type f = check_return(boost::implicit_cast("hello")); type z = check_return(boost::implicit_cast(foo("hello"))); - + // warning supression: (void)x; (void)f; diff --git a/test/lexical_cast_containers_test.cpp b/test/lexical_cast_containers_test.cpp index e6c544a..bb13f31 100644 --- a/test/lexical_cast_containers_test.cpp +++ b/test/lexical_cast_containers_test.cpp @@ -31,7 +31,7 @@ boost::unit_test::test_suite *init_unit_test_suite(int, char *[]) } void testing_boost_containers_basic_string() -{ +{ BOOST_CHECK("100" == lexical_cast("100")); BOOST_CHECK(L"100" == lexical_cast(L"100")); diff --git a/test/lexical_cast_float_types_test.cpp b/test/lexical_cast_float_types_test.cpp index 60db0e1..827b6ec 100755 --- a/test/lexical_cast_float_types_test.cpp +++ b/test/lexical_cast_float_types_test.cpp @@ -237,7 +237,7 @@ void test_converion_to_float_types() CHECK_CLOSE_ABS_DIFF(-10101.0E-011, test_t); CHECK_CLOSE_ABS_DIFF(-10101093, test_t); CHECK_CLOSE_ABS_DIFF(10101093, test_t); - + CHECK_CLOSE_ABS_DIFF(-.34, test_t); CHECK_CLOSE_ABS_DIFF(.34, test_t); CHECK_CLOSE_ABS_DIFF(.34e10, test_t); diff --git a/test/lexical_cast_iterator_range_test.cpp b/test/lexical_cast_iterator_range_test.cpp index d54de7a..50b86ff 100644 --- a/test/lexical_cast_iterator_range_test.cpp +++ b/test/lexical_cast_iterator_range_test.cpp @@ -138,7 +138,7 @@ void test_it_range_using_char(CharT* one, CharT* eleven) #endif } -void test_char_iterator_ranges() +void test_char_iterator_ranges() { typedef char test_char_type; test_char_type data1[] = "1"; @@ -149,7 +149,7 @@ void test_char_iterator_ranges() -void test_unsigned_char_iterator_ranges() +void test_unsigned_char_iterator_ranges() { typedef unsigned char test_char_type; test_char_type data1[] = "1"; @@ -158,7 +158,7 @@ void test_unsigned_char_iterator_ranges() test_it_range_using_char(data1, data2); } -void test_signed_char_iterator_ranges() +void test_signed_char_iterator_ranges() { typedef signed char test_char_type; test_char_type data1[] = "1"; @@ -167,7 +167,7 @@ void test_signed_char_iterator_ranges() test_it_range_using_char(data1, data2); } -void test_wchar_iterator_ranges() +void test_wchar_iterator_ranges() { #ifndef BOOST_LCAST_NO_WCHAR_T typedef wchar_t test_char_type; @@ -179,7 +179,7 @@ void test_wchar_iterator_ranges() BOOST_CHECK(true); } -void test_char16_iterator_ranges() +void test_char16_iterator_ranges() { #if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) typedef char16_t test_char_type; @@ -191,7 +191,7 @@ void test_char16_iterator_ranges() BOOST_CHECK(true); } -void test_char32_iterator_ranges() +void test_char32_iterator_ranges() { #if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) typedef char32_t test_char_type; diff --git a/test/lexical_cast_no_exceptions_test.cpp b/test/lexical_cast_no_exceptions_test.cpp index dbec8ea..c470eda 100755 --- a/test/lexical_cast_no_exceptions_test.cpp +++ b/test/lexical_cast_no_exceptions_test.cpp @@ -22,7 +22,7 @@ #ifndef BOOST_NO_EXCEPTIONS #error "This test must be compiled with -DBOOST_NO_EXCEPTIONS" -#endif +#endif bool g_was_exception = false; @@ -60,25 +60,25 @@ inline std::istream& operator>> (std::istream& i, Escape& rhs) void test_exceptions_off() { Escape v(""); - - g_was_exception = false; + + g_was_exception = false; lexical_cast(v); BOOST_CHECK(g_was_exception); - + g_was_exception = false; lexical_cast(v); BOOST_CHECK(g_was_exception); - + v = lexical_cast(100); BOOST_CHECK_EQUAL(lexical_cast(v), 100); BOOST_CHECK_EQUAL(lexical_cast(v), 100u); - + v = lexical_cast(0.0); BOOST_CHECK_EQUAL(lexical_cast(v), 0.0); BOOST_CHECK_EQUAL(lexical_cast(100), 100); BOOST_CHECK_EQUAL(lexical_cast(0.0), 0.0); - + g_was_exception = false; lexical_cast(700000); BOOST_CHECK(g_was_exception); diff --git a/test/lexical_cast_no_locale_test.cpp b/test/lexical_cast_no_locale_test.cpp index f3defb3..2a5120b 100755 --- a/test/lexical_cast_no_locale_test.cpp +++ b/test/lexical_cast_no_locale_test.cpp @@ -23,12 +23,12 @@ using namespace boost; // Testing compilation and some basic usage with BOOST_NO_STD_LOCALE -// Tests are mainly copyied from lexical_cast_empty_input_test.cpp (something +// Tests are mainly copyied from lexical_cast_empty_input_test.cpp (something // new added to test_empty_3) #ifndef BOOST_NO_STD_LOCALE #error "This test must be compiled with -DBOOST_NO_STD_LOCALE" -#endif +#endif template @@ -106,15 +106,15 @@ void test_empty_3() { Escape v(""); do_test_on_empty_input(v); - + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); - + v = lexical_cast(100); BOOST_CHECK_EQUAL(lexical_cast(v), 100); BOOST_CHECK_EQUAL(lexical_cast(v), 100u); - + v = lexical_cast(0.0); BOOST_CHECK_EQUAL(lexical_cast(v), 0.0); } diff --git a/test/lexical_cast_typedefed_wchar_test_runtime.cpp b/test/lexical_cast_typedefed_wchar_test_runtime.cpp index d01700a..adb024e 100755 --- a/test/lexical_cast_typedefed_wchar_test_runtime.cpp +++ b/test/lexical_cast_typedefed_wchar_test_runtime.cpp @@ -30,7 +30,7 @@ void test_typedefed_wchar_t_runtime() BOOST_CHECK_EQUAL(boost::lexical_cast(L'A'), 65); BOOST_CHECK_EQUAL(boost::lexical_cast(L'B'), 66); - + BOOST_CHECK_EQUAL(boost::lexical_cast(L"65"), 65); BOOST_CHECK_EQUAL(boost::lexical_cast(L"66"), 66); #endif From e3cd0ca7faf1e42400676890a39cb75722bc4b1d Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 2 Jul 2012 18:30:21 +0000 Subject: [PATCH 171/242] 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