Changeset 73118
 Timestamp:
 Jul 15, 2011, 11:20:11 AM (7 years ago)
 Location:
 trunk
 Files:

 1 added
 5 edited
Legend:
 Unmodified
 Added
 Removed

trunk/boost/lexical_cast.hpp
r72972 r73118 25 25 #include <istream> 26 26 #include <string> 27 #include <cstring> 27 28 #include <typeinfo> 28 29 #include <exception> … … 732 733 } 733 734 735 namespace detail 736 { 737 /* Returns true and sets the correct value if found NaN or Inf. */ 738 template <class CharT, class T> 739 inline bool parse_inf_nan_impl(const CharT* begin, const CharT* end, T& value 740 , const CharT* lc_NAN, const CharT* lc_nan 741 , const CharT* lc_INFINITY, const CharT* lc_infinity 742 , const CharT opening_brace, const CharT closing_brace) 743 { 744 using namespace std; 745 const wchar_t minus = lcast_char_constants<wchar_t>::minus; 746 const wchar_t plus = lcast_char_constants<wchar_t>::plus; 747 const int inifinity_size = 8; 748 749 bool has_minus = false; 750 /* Parsing +/ */ 751 if( *begin == minus) 752 { 753 ++ begin; 754 has_minus = true; 755 } 756 else if( *begin == plus ) ++begin; 757 758 if( endbegin < 3 ) return false; 759 if( !memcmp(begin, lc_nan, 3*sizeof(CharT))  !memcmp(begin, lc_NAN, 3*sizeof(CharT)) ) 760 { 761 begin += 3; 762 if (end != begin) /* It is 'nan(...)' or some bad input*/ 763 { 764 if(endbegin<2) return false; // bad input 765  end; 766 if( *begin != opening_brace  *end != closing_brace) return false; // bad input 767 } 768 769 if( !has_minus ) value = std::numeric_limits<T>::quiet_NaN(); 770 else value = std::numeric_limits<T>::quiet_NaN(); 771 return true; 772 } else 773 if (( /* 'INF' or 'inf' */ 774 endbegin==3 775 && 776 (!memcmp(begin, lc_infinity, 3*sizeof(CharT))  !memcmp(begin, lc_INFINITY, 3*sizeof(CharT))) 777 ) 778  779 ( /* 'INFINITY' or 'infinity' */ 780 endbegin==inifinity_size 781 && 782 (!memcmp(begin, lc_infinity, inifinity_size) !memcmp(begin, lc_INFINITY, inifinity_size)) 783 ) 784 ) 785 { 786 if( !has_minus ) value = std::numeric_limits<T>::infinity(); 787 else value = std::numeric_limits<T>::infinity(); 788 return true; 789 } 790 791 return false; 792 } 793 794 #ifndef BOOST_LCAST_NO_WCHAR_T 795 template <class T> 796 bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value) 797 { 798 return parse_inf_nan_impl(begin, end, value 799 , L"NAN", L"nan" 800 , L"INFINITY", L"infinity" 801 , L'(', L')'); 802 } 803 #endif 804 805 template <class CharT, class T> 806 bool parse_inf_nan(const CharT* begin, const CharT* end, T& value) 807 { 808 return parse_inf_nan_impl(begin, end, value 809 , "NAN", "nan" 810 , "INFINITY", "infinity" 811 , '(', ')'); 812 } 813 814 template <class T> 815 bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) 816 { 817 using namespace std; 818 if (value != value) 819 { 820 memcpy(begin,L"nan", sizeof(L"nan")); 821 end = begin + 3; 822 return true; 823 } else if ( value > numeric_limits<T>::max() ) 824 { 825 memcpy(begin,L"inf", sizeof(L"inf")); 826 end = begin + 3; 827 return true; 828 } else if ( value < numeric_limits<T>::max() ) 829 { 830 memcpy(begin,L"inf", sizeof(L"inf")); 831 end = begin + 4; 832 return true; 833 } 834 835 return false; 836 } 837 838 template <class CharT, class T> 839 bool put_inf_nan(CharT* begin, CharT*& end, const T& value) 840 { 841 using namespace std; 842 if (value != value) 843 { 844 memcpy(begin,"nan", sizeof("nan")); 845 end = begin + 3; 846 return true; 847 } else if ( value > numeric_limits<T>::max() ) 848 { 849 memcpy(begin,"inf", sizeof("inf")); 850 end = begin + 3; 851 return true; 852 } else if ( value < numeric_limits<T>::max() ) 853 { 854 memcpy(begin,"inf", sizeof("inf")); 855 end = begin + 4; 856 return true; 857 } 858 859 return false; 860 } 861 862 } 863 864 734 865 namespace detail // lcast_ret_float 735 866 { … … 782 913 783 914 value = 0.0; 915 916 if (parse_inf_nan(begin, end, value)) return true; 784 917 785 918 typedef typename Traits::int_type int_type; … … 1105 1238 bool lcast_put(const OutputStreamable& input) 1106 1239 { 1240 if(put_inf_nan(start, finish, input)) return true; 1107 1241 this>setp(start, finish); 1108 1242 std::basic_ostream<CharT> stream(static_cast<Base*>(this)); … … 1343 1477 template <class T> 1344 1478 bool float_types_converter_internal(T& output, int /*tag*/) { 1479 1480 if (parse_inf_nan(start, finish, output)) return true; 1481 1345 1482 bool return_value = convert_using_base_class(output); 1346 1483 1347 1484 /* Some compilers and libraries successfully 1348 * parse ' inf', 'INFINITY', '1.0E', '1.0E'...1485 * parse '1.0E', '1.0E'... 1349 1486 * We are trying to provide a unified behaviour, 1350 1487 * so we just forbid such conversions (as some … … 1357 1494 if ( return_value && 1358 1495 ( 1359 output > (std::numeric_limits<T>::max)() // +inf 1360  output < (std::numeric_limits<T>::max)() // inf 1361  output != output // NaN 1362  *(finish1) == lowercase_e // 1.0e 1496 *(finish1) == lowercase_e // 1.0e 1363 1497  *(finish1) == capital_e // 1.0E 1364 1498  *(finish1) == minus // 1.0e or 1.0E 
trunk/libs/conversion/lexical_cast.htm
r72954 r73118 270 270 <h3>July 2011:</h3> 271 271 <ul type="square"> 272 <li>Added code to work with Inf and NaN on any platform.</li> 272 273 <li>Better performance and less memory usage for conversions to float type (and to double type, if sizeof(double)<sizeof(long double)).</li> 273 274 </ul> 
trunk/libs/conversion/lexical_cast_test.cpp
r72972 r73118 41 41 && !(defined(BOOST_MSVC) && BOOST_MSVC < 1300) 42 42 #define LCAST_TEST_LONGLONG 43 #endif 44 45 #if defined(BOOST_NO_STRINGSTREAM)  defined(BOOST_NO_STD_WSTRING) 46 #define BOOST_LCAST_NO_WCHAR_T 43 47 #endif 44 48 
trunk/libs/conversion/test/Jamfile.v2
r72925 r73118 28 28 [ run lexical_cast_wchars_test.cpp ../../test/build//boost_unit_test_framework/<link>static ] 29 29 [ run lexical_cast_float_types_test.cpp ../../test/build//boost_unit_test_framework/<link>static ] 30 [ run lexical_cast_inf_nan_test.cpp ../../test/build//boost_unit_test_framework/<link>static ] 30 31 ; 31 32 
trunk/libs/conversion/test/lexical_cast_float_types_test.cpp
r72955 r73118 242 242 CHECK_CLOSE_ABS_DIFF(.34, test_t); 243 243 CHECK_CLOSE_ABS_DIFF(.34e10, test_t); 244 245 // BOOST_CHECK(lexical_cast<test_t>("inf") == std::numeric_limits<test_t>::infinity() );246 // BOOST_CHECK(lexical_cast<test_t>("INF") == std::numeric_limits<test_t>::infinity() );247 // BOOST_CHECK(lexical_cast<test_t>("+inf") == std::numeric_limits<test_t>::infinity() );248 // BOOST_CHECK(lexical_cast<test_t>("infinity") == std::numeric_limits<test_t>::infinity() );249 //250 // BOOST_CHECK(lexical_cast<test_t>("nan") == std::numeric_limits<test_t>::quiet_NaN() );251 // BOOST_CHECK(lexical_cast<test_t>("NaN") == std::numeric_limits<test_t>::quiet_NaN() );252 253 BOOST_CHECK_THROW(lexical_cast<test_t>("inf"), bad_lexical_cast );254 BOOST_CHECK_THROW(lexical_cast<test_t>("INF"), bad_lexical_cast);255 BOOST_CHECK_THROW(lexical_cast<test_t>("+inf"), bad_lexical_cast);256 BOOST_CHECK_THROW(lexical_cast<test_t>("infinity"), bad_lexical_cast);257 BOOST_CHECK_THROW(lexical_cast<test_t>("nan"), bad_lexical_cast);258 BOOST_CHECK_THROW(lexical_cast<test_t>("NaN"), bad_lexical_cast);259 260 244 261 245 BOOST_CHECK_THROW(lexical_cast<test_t>("1.e"), bad_lexical_cast); … … 381 365 382 366 TEST_TO_FROM_CAST_AROUND( 0.0 ); 383 384 // TEST_TO_FROM_CAST_AROUND( std::numeric_limits<test_t>::infinity() );385 // TEST_TO_FROM_CAST_AROUND( std::numeric_limits<test_t>::infinity() );386 // TEST_TO_FROM_CAST_AROUND( std::numeric_limits<test_t>::quiet_NaN() );387 367 388 368 long double val1;
Note: See TracChangeset
for help on using the changeset viewer.