1#ifndef BOOST_LEXICAL_CAST_INCLUDED 2#define BOOST_LEXICAL_CAST_INCLUDED 3 4// MS compatible compilers support #pragma once 5 6#if defined(_MSC_VER) && (_MSC_VER >= 1020) 7# pragma once 8#endif 9 10// Boost lexical_cast.hpp header -------------------------------------------// 11// 12// See http://www.boost.org/libs/conversion for documentation. 13// See end of this header for rights and permissions. 14// 15// what: lexical_cast custom keyword cast 16// who: contributed by Kevlin Henney, 17// enhanced with contributions from Terje Slettebo, 18// with additional fixes and suggestions from Gennaro Prota, 19// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, 20// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, 21// Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters 22// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2012 23 24#include <boost/config.hpp> 25#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) 26#define BOOST_LCAST_NO_WCHAR_T 27#endif 28 29#include <climits> 30#include <cstddef> 31#include <string> 32#include <cstring> 33#include <cstdio> 34#include <typeinfo> 35#include <exception> 36#include <boost/limits.hpp> 37#include <boost/mpl/if.hpp> 38#include <boost/throw_exception.hpp> 39#include <boost/type_traits/ice.hpp> 40#include <boost/type_traits/is_pointer.hpp> 41#include <boost/static_assert.hpp> 42#include <boost/detail/lcast_precision.hpp> 43#include <boost/detail/workaround.hpp> 44 45 46#ifndef BOOST_NO_STD_LOCALE 47# include <locale> 48#else 49# ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE 50 // Getting error at this point means, that your STL library is old/lame/misconfigured. 51 // If nothing can be done with STL library, define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE, 52 // but beware: lexical_cast will understand only 'C' locale delimeters and thousands 53 // separators. 54# error "Unable to use <locale> header. Define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE to force " 55# error "boost::lexical_cast to use only 'C' locale during conversions." 56# endif 57#endif 58 59#ifdef BOOST_NO_STRINGSTREAM 60#include <strstream> 61#else 62#include <sstream> 63#endif 64 65#ifdef BOOST_NO_TYPEID 66#define BOOST_LCAST_THROW_BAD_CAST(S, T) throw_exception(bad_lexical_cast()) 67#else 68#define BOOST_LCAST_THROW_BAD_CAST(Source, Target) \ 69 throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))) 70#endif 71 72namespace boost 73{ 74 // exception used to indicate runtime lexical_cast failure 75 class BOOST_SYMBOL_VISIBLE bad_lexical_cast : 76 // workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0 77#if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS 78 public std::exception 79#else 80 public std::bad_cast 81#endif 82 83#if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 ) 84 // under bcc32 5.5.1 bad_cast doesn't derive from exception 85 , public std::exception 86#endif 87 88 { 89 public: 90 bad_lexical_cast() BOOST_NOEXCEPT : 91#ifndef BOOST_NO_TYPEID 92 source(&typeid(void)), target(&typeid(void)) 93#else 94 source(0), target(0) // this breaks getters 95#endif 96 { 97 } 98 99 bad_lexical_cast( 100 const std::type_info &source_type_arg, 101 const std::type_info &target_type_arg) BOOST_NOEXCEPT : 102 source(&source_type_arg), target(&target_type_arg) 103 { 104 } 105 106 const std::type_info &source_type() const 107 { 108 return *source; 109 } 110 const std::type_info &target_type() const 111 { 112 return *target; 113 } 114 115#ifndef BOOST_NO_NOEXCEPT 116 virtual const char *what() const noexcept 117#else 118 virtual const char *what() const throw() 119#endif 120 { 121 return "bad lexical cast: " 122 "source type value could not be interpreted as target"; 123 } 124 125#ifndef BOOST_NO_NOEXCEPT 126 virtual ~bad_lexical_cast() BOOST_NOEXCEPT 127#else 128 virtual ~bad_lexical_cast() throw() 129#endif 130 {} 131 private: 132 const std::type_info *source; 133 const std::type_info *target; 134 }; 135 136 namespace detail // widest_char 137 { 138 template <typename TargetChar, typename SourceChar> 139 struct widest_char 140 { 141 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< 142 (sizeof(TargetChar) > sizeof(SourceChar)) 143 , TargetChar 144 , SourceChar >::type type; 145 }; 146 } 147} // namespace boost 148 149#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) && !defined(__PGIC__) 150 151#include <cmath> 152#include <istream> 153 154#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) 155#include <array> 156#endif 157 158#include <boost/array.hpp> 159#include <boost/numeric/conversion/cast.hpp> 160#include <boost/type_traits/make_unsigned.hpp> 161#include <boost/type_traits/is_signed.hpp> 162#include <boost/type_traits/is_integral.hpp> 163#include <boost/type_traits/is_arithmetic.hpp> 164#include <boost/type_traits/remove_pointer.hpp> 165#include <boost/math/special_functions/sign.hpp> 166#include <boost/math/special_functions/fpclassify.hpp> 167#include <boost/range/iterator_range_core.hpp> 168#include <boost/container/container_fwd.hpp> 169#ifndef BOOST_NO_CWCHAR 170# include <cwchar> 171#endif 172 173namespace boost { 174 namespace detail // widest_char<...> (continuation) 175 { 176 struct not_a_character_type{}; 177 178 template <typename CharT> 179 struct widest_char<not_a_character_type, CharT > 180 { 181 typedef CharT type; 182 }; 183 184 template <typename CharT> 185 struct widest_char< CharT, not_a_character_type > 186 { 187 typedef CharT type; 188 }; 189 190 template <> 191 struct widest_char< not_a_character_type, not_a_character_type > 192 { 193 typedef char type; 194 }; 195 } 196 197 namespace detail // is_char_or_wchar<...> and stream_char<...> templates 198 { 199 // returns true, if T is one of the character types 200 template <typename T> 201 struct is_char_or_wchar 202 { 203 typedef ::boost::type_traits::ice_or< 204 ::boost::is_same< T, char >::value, 205 #ifndef BOOST_LCAST_NO_WCHAR_T 206 ::boost::is_same< T, wchar_t >::value, 207 #endif 208 #ifndef BOOST_NO_CHAR16_T 209 ::boost::is_same< T, char16_t >::value, 210 #endif 211 #ifndef BOOST_NO_CHAR32_T 212 ::boost::is_same< T, char32_t >::value, 213 #endif 214 ::boost::is_same< T, unsigned char >::value, 215 ::boost::is_same< T, signed char >::value 216 > result_type; 217 218 BOOST_STATIC_CONSTANT(bool, value = (result_type::value) ); 219 }; 220 221 // selectors for choosing stream character type 222 // returns one of char, wchar_t, char16_t, char32_t or not_a_character_type types 223 template <typename Type> 224 struct stream_char 225 { 226 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< 227 is_char_or_wchar<Type >::value, 228 Type, 229 boost::detail::not_a_character_type 230 >::type type; 231 }; 232 233 template <> 234 struct stream_char<unsigned char> 235 { 236 typedef char type; 237 }; 238 239 template <> 240 struct stream_char<signed char> 241 { 242 typedef char type; 243 }; 244 245 template <typename CharT> 246 struct stream_char<CharT*> 247 { 248 typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type; 249 }; 250 251 template <typename CharT> 252 struct stream_char<const CharT*> 253 { 254 typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type; 255 }; 256 257 template <typename CharT> 258 struct stream_char<iterator_range<CharT*> > 259 { 260 typedef BOOST_DEDUCED_TYPENAME stream_char<CharT*>::type type; 261 }; 262 263 template <typename CharT> 264 struct stream_char<iterator_range<const CharT*> > 265 { 266 typedef BOOST_DEDUCED_TYPENAME stream_char<const CharT*>::type type; 267 }; 268 269 template <class CharT, class Traits, class Alloc> 270 struct stream_char< std::basic_string<CharT, Traits, Alloc> > 271 { 272 typedef CharT type; 273 }; 274 275 template <class CharT, class Traits, class Alloc> 276 struct stream_char< ::boost::container::basic_string<CharT, Traits, Alloc> > 277 { 278 typedef CharT type; 279 }; 280 281 template<typename CharT, std::size_t N> 282 struct stream_char<boost::array<CharT, N> > 283 { 284 typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type; 285 }; 286 287 template<typename CharT, std::size_t N> 288 struct stream_char<boost::array<const CharT, N> > 289 { 290 typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type; 291 }; 292 293#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) 294 template <typename CharT, std::size_t N> 295 struct stream_char<std::array<CharT, N> > 296 { 297 typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type; 298 }; 299 300 template <typename CharT, std::size_t N> 301 struct stream_char<std::array<const CharT, N> > 302 { 303 typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type; 304 }; 305#endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) 306 307#if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T) 308 template<> 309 struct stream_char<wchar_t> 310 { 311 typedef boost::detail::not_a_character_type type; 312 }; 313 314 template<> 315 struct stream_char<wchar_t*> 316 { 317 typedef wchar_t type; 318 }; 319 320 template<> 321 struct stream_char<const wchar_t*> 322 { 323 typedef wchar_t type; 324 }; 325#endif 326 } 327 328 namespace detail // deduce_char_traits template 329 { 330 331 template<class CharT, class Target, class Source> 332 struct deduce_char_traits 333 { 334 typedef std::char_traits<CharT> type; 335 }; 336 337 template<class CharT, class Traits, class Alloc, class Source> 338 struct deduce_char_traits< CharT 339 , std::basic_string<CharT,Traits,Alloc> 340 , Source 341 > 342 { 343 typedef Traits type; 344 }; 345 346 template<class CharT, class Target, class Traits, class Alloc> 347 struct deduce_char_traits< CharT 348 , Target 349 , std::basic_string<CharT,Traits,Alloc> 350 > 351 { 352 typedef Traits type; 353 }; 354 355 template<class CharT, class Traits, class Alloc, class Source> 356 struct deduce_char_traits< CharT 357 , ::boost::container::basic_string<CharT,Traits,Alloc> 358 , Source 359 > 360 { 361 typedef Traits type; 362 }; 363 364 template<class CharT, class Target, class Traits, class Alloc> 365 struct deduce_char_traits< CharT 366 , Target 367 , ::boost::container::basic_string<CharT,Traits,Alloc> 368 > 369 { 370 typedef Traits type; 371 }; 372 373 template<class CharT, class Traits, class Alloc1, class Alloc2> 374 struct deduce_char_traits< CharT 375 , std::basic_string<CharT,Traits,Alloc1> 376 , std::basic_string<CharT,Traits,Alloc2> 377 > 378 { 379 typedef Traits type; 380 }; 381 382 template<class CharT, class Traits, class Alloc1, class Alloc2> 383 struct deduce_char_traits< CharT 384 , ::boost::container::basic_string<CharT,Traits,Alloc1> 385 , ::boost::container::basic_string<CharT,Traits,Alloc2> 386 > 387 { 388 typedef Traits type; 389 }; 390 391 template<class CharT, class Traits, class Alloc1, class Alloc2> 392 struct deduce_char_traits< CharT 393 , ::boost::container::basic_string<CharT,Traits,Alloc1> 394 , ::std::basic_string<CharT,Traits,Alloc2> 395 > 396 { 397 typedef Traits type; 398 }; 399 400 template<class CharT, class Traits, class Alloc1, class Alloc2> 401 struct deduce_char_traits< CharT 402 , ::std::basic_string<CharT,Traits,Alloc1> 403 , ::boost::container::basic_string<CharT,Traits,Alloc2> 404 > 405 { 406 typedef Traits type; 407 }; 408 } 409 410 namespace detail // lcast_src_length 411 { 412 // Return max. length of string representation of Source; 413 template< class Source // Source type of lexical_cast. 414 > 415 struct lcast_src_length 416 { 417 BOOST_STATIC_CONSTANT(std::size_t, value = 1); 418 // To check coverage, build the test with 419 // bjam --v2 profile optimization=off 420 static void check_coverage() {} 421 }; 422 423 // Helper for integral types. 424 // Notes on length calculation: 425 // Max length for 32bit int with grouping "\1" and thousands_sep ',': 426 // "-2,1,4,7,4,8,3,6,4,7" 427 // ^ - is_signed 428 // ^ - 1 digit not counted by digits10 429 // ^^^^^^^^^^^^^^^^^^ - digits10 * 2 430 // 431 // Constant is_specialized is used instead of constant 1 432 // to prevent buffer overflow in a rare case when 433 // <boost/limits.hpp> doesn't add missing specialization for 434 // numeric_limits<T> for some integral type T. 435 // When is_specialized is false, the whole expression is 0. 436 template<class Source> 437 struct lcast_src_length_integral 438 { 439#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS 440 BOOST_STATIC_CONSTANT(std::size_t, value = 441 std::numeric_limits<Source>::is_signed + 442 std::numeric_limits<Source>::is_specialized + /* == 1 */ 443 std::numeric_limits<Source>::digits10 * 2 444 ); 445#else 446 BOOST_STATIC_CONSTANT(std::size_t, value = 156); 447 BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256); 448#endif 449 }; 450 451#define BOOST_LCAST_DEF(T) \ 452 template<> struct lcast_src_length<T> \ 453 : lcast_src_length_integral<T> \ 454 { static void check_coverage() {} }; 455 456 BOOST_LCAST_DEF(short) 457 BOOST_LCAST_DEF(unsigned short) 458 BOOST_LCAST_DEF(int) 459 BOOST_LCAST_DEF(unsigned int) 460 BOOST_LCAST_DEF(long) 461 BOOST_LCAST_DEF(unsigned long) 462#if defined(BOOST_HAS_LONG_LONG) 463 BOOST_LCAST_DEF(boost::ulong_long_type) 464 BOOST_LCAST_DEF(boost::long_long_type ) 465#elif defined(BOOST_HAS_MS_INT64) 466 BOOST_LCAST_DEF(unsigned __int64) 467 BOOST_LCAST_DEF( __int64) 468#endif 469 470#undef BOOST_LCAST_DEF 471 472#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION 473 // Helper for floating point types. 474 // -1.23456789e-123456 475 // ^ sign 476 // ^ leading digit 477 // ^ decimal point 478 // ^^^^^^^^ lcast_precision<Source>::value 479 // ^ "e" 480 // ^ exponent sign 481 // ^^^^^^ exponent (assumed 6 or less digits) 482 // sign + leading digit + decimal point + "e" + exponent sign == 5 483 template<class Source> 484 struct lcast_src_length_floating 485 { 486 BOOST_STATIC_ASSERT( 487 std::numeric_limits<Source>::max_exponent10 <= 999999L && 488 std::numeric_limits<Source>::min_exponent10 >= -999999L 489 ); 490 BOOST_STATIC_CONSTANT(std::size_t, value = 491 5 + lcast_precision<Source>::value + 6 492 ); 493 }; 494 495 template<> 496 struct lcast_src_length<float> 497 : lcast_src_length_floating<float> 498 { 499 static void check_coverage() {} 500 }; 501 502 template<> 503 struct lcast_src_length<double> 504 : lcast_src_length_floating<double> 505 { 506 static void check_coverage() {} 507 }; 508 509 template<> 510 struct lcast_src_length<long double> 511 : lcast_src_length_floating<long double> 512 { 513 static void check_coverage() {} 514 }; 515 516#endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION 517 } 518 519 namespace detail // '0', '+' and '-' constants 520 { 521 template<typename CharT> struct lcast_char_constants; 522 523 template<> 524 struct lcast_char_constants<char> 525 { 526 BOOST_STATIC_CONSTANT(char, zero = '0'); 527 BOOST_STATIC_CONSTANT(char, minus = '-'); 528 BOOST_STATIC_CONSTANT(char, plus = '+'); 529 BOOST_STATIC_CONSTANT(char, lowercase_e = 'e'); 530 BOOST_STATIC_CONSTANT(char, capital_e = 'E'); 531 BOOST_STATIC_CONSTANT(char, c_decimal_separator = '.'); 532 }; 533 534#ifndef BOOST_LCAST_NO_WCHAR_T 535 template<> 536 struct lcast_char_constants<wchar_t> 537 { 538 BOOST_STATIC_CONSTANT(wchar_t, zero = L'0'); 539 BOOST_STATIC_CONSTANT(wchar_t, minus = L'-'); 540 BOOST_STATIC_CONSTANT(wchar_t, plus = L'+'); 541 BOOST_STATIC_CONSTANT(wchar_t, lowercase_e = L'e'); 542 BOOST_STATIC_CONSTANT(wchar_t, capital_e = L'E'); 543 BOOST_STATIC_CONSTANT(wchar_t, c_decimal_separator = L'.'); 544 }; 545#endif 546 547#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) 548 template<> 549 struct lcast_char_constants<char16_t> 550 { 551 BOOST_STATIC_CONSTANT(char16_t, zero = u'0'); 552 BOOST_STATIC_CONSTANT(char16_t, minus = u'-'); 553 BOOST_STATIC_CONSTANT(char16_t, plus = u'+'); 554 BOOST_STATIC_CONSTANT(char16_t, lowercase_e = u'e'); 555 BOOST_STATIC_CONSTANT(char16_t, capital_e = u'E'); 556 BOOST_STATIC_CONSTANT(char16_t, c_decimal_separator = u'.'); 557 }; 558#endif 559 560#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) 561 template<> 562 struct lcast_char_constants<char32_t> 563 { 564 BOOST_STATIC_CONSTANT(char32_t, zero = U'0'); 565 BOOST_STATIC_CONSTANT(char32_t, minus = U'-'); 566 BOOST_STATIC_CONSTANT(char32_t, plus = U'+'); 567 BOOST_STATIC_CONSTANT(char32_t, lowercase_e = U'e'); 568 BOOST_STATIC_CONSTANT(char32_t, capital_e = U'E'); 569 BOOST_STATIC_CONSTANT(char32_t, c_decimal_separator = U'.'); 570 }; 571#endif 572 } 573 574 namespace detail // lcast_to_unsigned 575 { 576#if (defined _MSC_VER) 577# pragma warning( push ) 578// C4146: unary minus operator applied to unsigned type, result still unsigned 579# pragma warning( disable : 4146 ) 580#elif defined( __BORLANDC__ ) 581# pragma option push -w-8041 582#endif 583 template<class T> 584 inline 585 BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value) BOOST_NOEXCEPT 586 { 587 typedef BOOST_DEDUCED_TYPENAME make_unsigned<T>::type result_type; 588 const result_type uvalue = static_cast<result_type>(value); 589 return value < 0 ? -uvalue : uvalue; 590 } 591#if (defined _MSC_VER) 592# pragma warning( pop ) 593#elif defined( __BORLANDC__ ) 594# pragma option pop 595#endif 596 } 597 598 namespace detail // lcast_put_unsigned 599 { 600 template<class Traits, class T, class CharT> 601 CharT* lcast_put_unsigned(const T n_param, CharT* finish) 602 { 603#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS 604 BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed); 605#endif 606 607 typedef typename Traits::int_type int_type; 608 CharT const czero = lcast_char_constants<CharT>::zero; 609 int_type const zero = Traits::to_int_type(czero); 610 BOOST_DEDUCED_TYPENAME boost::mpl::if_c< 611 (sizeof(int_type) > sizeof(T)) 612 , int_type 613 , T 614 >::type n = n_param; 615 616#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE 617 std::locale loc; 618 if (loc != std::locale::classic()) { 619 typedef std::numpunct<CharT> numpunct; 620 numpunct const& np = BOOST_USE_FACET(numpunct, loc); 621 std::string const grouping = np.grouping(); 622 std::string::size_type const grouping_size = grouping.size(); 623 624 if ( grouping_size && grouping[0] > 0 ) 625 { 626 627#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS 628 // Check that ulimited group is unreachable: 629 BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX); 630#endif 631 CharT thousands_sep = np.thousands_sep(); 632 std::string::size_type group = 0; // current group number 633 char last_grp_size = grouping[0]; 634 char left = last_grp_size; 635 636 do 637 { 638 if(left == 0) 639 { 640 ++group; 641 if(group < grouping_size) 642 { 643 char const grp_size = grouping[group]; 644 last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size; 645 } 646 647 left = last_grp_size; 648 --finish; 649 Traits::assign(*finish, thousands_sep); 650 } 651 652 --left; 653 654 --finish; 655 int_type const digit = static_cast<int_type>(n % 10U); 656 Traits::assign(*finish, Traits::to_char_type(zero + digit)); 657 n /= 10; 658 } while(n); 659 return finish; 660 } 661 } 662#endif 663 { 664 do 665 { 666 --finish; 667 int_type const digit = static_cast<int_type>(n % 10U); 668 Traits::assign(*finish, Traits::to_char_type(zero + digit)); 669 n /= 10; 670 } while(n); 671 } 672 673 return finish; 674 } 675 } 676 677 namespace detail // lcast_ret_unsigned 678 { 679 template<class Traits, class T, class CharT> 680 inline bool lcast_ret_unsigned(T& value, const CharT* const begin, const CharT* end) 681 { 682#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS 683 BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed); 684#endif 685 typedef typename Traits::int_type int_type; 686 CharT const czero = lcast_char_constants<CharT>::zero; 687 --end; 688 value = 0; 689 690 if (begin > end || *end < czero || *end >= czero + 10) 691 return false; 692 value = *end - czero; 693 --end; 694 T multiplier = 1; 695 bool multiplier_overflowed = false; 696 697#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE 698 std::locale loc; 699 if (loc != std::locale::classic()) { 700 typedef std::numpunct<CharT> numpunct; 701 numpunct const& np = BOOST_USE_FACET(numpunct, loc); 702 std::string const& grouping = np.grouping(); 703 std::string::size_type const grouping_size = grouping.size(); 704 705 /* According to Programming languages - C++ 706 * we MUST check for correct grouping 707 */ 708 if (grouping_size && grouping[0] > 0) 709 { 710 unsigned char current_grouping = 0; 711 CharT const thousands_sep = np.thousands_sep(); 712 char remained = grouping[current_grouping] - 1; 713 bool shall_we_return = true; 714 715 for(;end>=begin; --end) 716 { 717 if (remained) { 718 T const multiplier_10 = multiplier * 10; 719 if (multiplier_10 / 10 != multiplier) multiplier_overflowed = true; 720 721 T const dig_value = *end - czero; 722 T const new_sub_value = multiplier_10 * dig_value; 723 724 if (*end < czero || *end >= czero + 10 725 /* detecting overflow */ 726 || (dig_value && new_sub_value / dig_value != multiplier_10) 727 || static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value 728 || (multiplier_overflowed && dig_value) 729 ) 730 return false; 731 732 value += new_sub_value; 733 multiplier *= 10; 734 --remained; 735 } else { 736 if ( !Traits::eq(*end, thousands_sep) ) //|| begin == end ) return false; 737 { 738 /* 739 * According to Programming languages - C++ 740 * Digit grouping is checked. That is, the positions of discarded 741 * separators is examined for consistency with 742 * use_facet<numpunct<charT> >(loc ).grouping() 743 * 744 * BUT what if there is no separators at all and grouping() 745 * is not empty? Well, we have no extraced separators, so we 746 * won`t check them for consistency. This will allow us to 747 * work with "C" locale from other locales 748 */ 749 shall_we_return = false; 750 break; 751 } else { 752 if ( begin == end ) return false; 753 if (current_grouping < grouping_size-1 ) ++current_grouping; 754 remained = grouping[current_grouping]; 755 } 756 } 757 } 758 759 if (shall_we_return) return true; 760 } 761 } 762#endif 763 { 764 while ( begin <= end ) 765 { 766 T const multiplier_10 = multiplier * 10; 767 if (multiplier_10 / 10 != multiplier) multiplier_overflowed = true; 768 769 T const dig_value = *end - czero; 770 T const new_sub_value = multiplier_10 * dig_value; 771 772 if (*end < czero || *end >= czero + 10 773 /* detecting overflow */ 774 || (dig_value && new_sub_value / dig_value != multiplier_10) 775 || static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value 776 || (multiplier_overflowed && dig_value) 777 ) 778 return false; 779 780 value += new_sub_value; 781 multiplier *= 10; 782 --end; 783 } 784 } 785 return true; 786 } 787 } 788 789 namespace detail 790 { 791 template <class CharT> 792 bool lc_iequal(const CharT* val, const CharT* lcase, const CharT* ucase, unsigned int len) BOOST_NOEXCEPT { 793 for( unsigned int i=0; i < len; ++i ) { 794 if ( val[i] != lcase[i] && val[i] != ucase[i] ) return false; 795 } 796 797 return true; 798 } 799 800 /* Returns true and sets the correct value if found NaN or Inf. */ 801 template <class CharT, class T> 802 inline bool parse_inf_nan_impl(const CharT* begin, const CharT* end, T& value 803 , const CharT* lc_NAN, const CharT* lc_nan 804 , const CharT* lc_INFINITY, const CharT* lc_infinity 805 , const CharT opening_brace, const CharT closing_brace) BOOST_NOEXCEPT 806 { 807 using namespace std; 808 if (begin == end) return false; 809 const CharT minus = lcast_char_constants<CharT>::minus; 810 const CharT plus = lcast_char_constants<CharT>::plus; 811 const int inifinity_size = 8; 812 813 bool has_minus = false; 814 /* Parsing +/- */ 815 if( *begin == minus) 816 { 817 ++ begin; 818 has_minus = true; 819 } 820 else if( *begin == plus ) ++begin; 821 822 if( end-begin < 3 ) return false; 823 if( lc_iequal(begin, lc_nan, lc_NAN, 3) ) 824 { 825 begin += 3; 826 if (end != begin) /* It is 'nan(...)' or some bad input*/ 827 { 828 if(end-begin<2) return false; // bad input 829 -- end; 830 if( *begin != opening_brace || *end != closing_brace) return false; // bad input 831 } 832 833 if( !has_minus ) value = std::numeric_limits<T>::quiet_NaN(); 834 else value = (boost::math::changesign) (std::numeric_limits<T>::quiet_NaN()); 835 return true; 836 } else 837 if (( /* 'INF' or 'inf' */ 838 end-begin==3 839 && 840 lc_iequal(begin, lc_infinity, lc_INFINITY, 3) 841 ) 842 || 843 ( /* 'INFINITY' or 'infinity' */ 844 end-begin==inifinity_size 845 && 846 lc_iequal(begin, lc_infinity, lc_INFINITY, inifinity_size) 847 ) 848 ) 849 { 850 if( !has_minus ) value = std::numeric_limits<T>::infinity(); 851 else value = (boost::math::changesign) (std::numeric_limits<T>::infinity()); 852 return true; 853 } 854 855 return false; 856 } 857 858 template <class CharT, class T> 859 bool put_inf_nan_impl(CharT* begin, CharT*& end, const T& value 860 , const CharT* lc_nan 861 , const CharT* lc_infinity) BOOST_NOEXCEPT 862 { 863 using namespace std; 864 const CharT minus = lcast_char_constants<CharT>::minus; 865 if ( (boost::math::isnan)(value) ) 866 { 867 if ( (boost::math::signbit)(value) ) 868 { 869 *begin = minus; 870 ++ begin; 871 } 872 873 memcpy(begin, lc_nan, 3 * sizeof(CharT)); 874 end = begin + 3; 875 return true; 876 } else if ( (boost::math::isinf)(value) ) 877 { 878 if ( (boost::math::signbit)(value) ) 879 { 880 *begin = minus; 881 ++ begin; 882 } 883 884 memcpy(begin, lc_infinity, 3 * sizeof(CharT)); 885 end = begin + 3; 886 return true; 887 } 888 889 return false; 890 } 891 892 893#ifndef BOOST_LCAST_NO_WCHAR_T 894 template <class T> 895 bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value) BOOST_NOEXCEPT 896 { 897 return parse_inf_nan_impl(begin, end, value 898 , L"NAN", L"nan" 899 , L"INFINITY", L"infinity" 900 , L'(', L')'); 901 } 902 903 template <class T> 904 bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) BOOST_NOEXCEPT 905 { 906 return put_inf_nan_impl(begin, end, value, L"nan", L"infinity"); 907 } 908 909#endif 910#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) 911 template <class T> 912 bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value) BOOST_NOEXCEPT 913 { 914 return parse_inf_nan_impl(begin, end, value 915 , u"NAN", u"nan" 916 , u"INFINITY", u"infinity" 917 , u'(', u')'); 918 } 919 920 template <class T> 921 bool put_inf_nan(char16_t* begin, char16_t*& end, const T& value) BOOST_NOEXCEPT 922 { 923 return put_inf_nan_impl(begin, end, value, u"nan", u"infinity"); 924 } 925#endif 926#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) 927 template <class T> 928 bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value) BOOST_NOEXCEPT 929 { 930 return parse_inf_nan_impl(begin, end, value 931 , U"NAN", U"nan" 932 , U"INFINITY", U"infinity" 933 , U'(', U')'); 934 } 935 936 template <class T> 937 bool put_inf_nan(char32_t* begin, char32_t*& end, const T& value) BOOST_NOEXCEPT 938 { 939 return put_inf_nan_impl(begin, end, value, U"nan", U"infinity"); 940 } 941#endif 942 943 template <class CharT, class T> 944 bool parse_inf_nan(const CharT* begin, const CharT* end, T& value) BOOST_NOEXCEPT 945 { 946 return parse_inf_nan_impl(begin, end, value 947 , "NAN", "nan" 948 , "INFINITY", "infinity" 949 , '(', ')'); 950 } 951 952 template <class CharT, class T> 953 bool put_inf_nan(CharT* begin, CharT*& end, const T& value) BOOST_NOEXCEPT 954 { 955 return put_inf_nan_impl(begin, end, value, "nan", "infinity"); 956 } 957 } 958 959 960 namespace detail // lcast_ret_float 961 { 962 template <class T> 963 struct mantissa_holder_type 964 { 965 /* Can not be used with this type */ 966 }; 967 968 template <> 969 struct mantissa_holder_type<float> 970 { 971 typedef unsigned int type; 972 }; 973 974 template <> 975 struct mantissa_holder_type<double> 976 { 977#if defined(BOOST_HAS_LONG_LONG) 978 typedef boost::ulong_long_type type; 979#elif defined(BOOST_HAS_MS_INT64) 980 typedef unsigned __int64 type; 981#endif 982 }; 983 984 template<class Traits, class T, class CharT> 985 inline bool lcast_ret_float(T& value, const CharT* begin, const CharT* end) 986 { 987 988#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE 989 std::locale loc; 990 typedef std::numpunct<CharT> numpunct; 991 numpunct const& np = BOOST_USE_FACET(numpunct, loc); 992 std::string const grouping( 993 (loc == std::locale::classic()) 994 ? std::string() 995 : np.grouping() 996 ); 997 std::string::size_type const grouping_size = grouping.size(); 998 CharT const thousands_sep = grouping_size ? np.thousands_sep() : 0; 999 CharT const decimal_point = np.decimal_point(); 1000 bool found_grouping = false; 1001 std::string::size_type last_grouping_pos = grouping_size - 1; 1002#else 1003 CharT const decimal_point = lcast_char_constants<CharT>::c_decimal_separator; 1004#endif 1005 1006 CharT const czero = lcast_char_constants<CharT>::zero; 1007 CharT const minus = lcast_char_constants<CharT>::minus; 1008 CharT const plus = lcast_char_constants<CharT>::plus; 1009 CharT const capital_e = lcast_char_constants<CharT>::capital_e; 1010 CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e; 1011 1012 value = static_cast<T>(0); 1013 1014 if (parse_inf_nan(begin, end, value)) return true; 1015 1016 typedef typename Traits::int_type int_type; 1017 typedef BOOST_DEDUCED_TYPENAME mantissa_holder_type<T>::type mantissa_type; 1018 int_type const zero = Traits::to_int_type(czero); 1019 if (begin == end) return false; 1020 1021 /* Getting the plus/minus sign */ 1022 bool has_minus = false; 1023 if (Traits::eq(*begin, minus) ) { 1024 ++ begin; 1025 has_minus = true; 1026 if (begin == end) return false; 1027 } else if (Traits::eq(*begin, plus) ) { 1028 ++begin; 1029 if (begin == end) return false; 1030 } 1031 1032 bool found_decimal = false; 1033 bool found_number_before_exp = false; 1034 int pow_of_10 = 0; 1035 mantissa_type mantissa=0; 1036 bool is_mantissa_full = false; 1037 1038 char length_since_last_delim = 0; 1039 1040 while ( begin != end ) 1041 { 1042 if (found_decimal) { 1043 /* We allow no thousand_separators after decimal point */ 1044 1045 mantissa_type tmp_mantissa = mantissa * 10u; 1046 if (Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) break; 1047 if ( *begin < czero || *begin >= czero + 10 ) return false; 1048 if ( is_mantissa_full 1049 || tmp_mantissa / 10u != mantissa 1050 || (std::numeric_limits<mantissa_type>::max)()-(*begin - zero) < tmp_mantissa 1051 ) { 1052 is_mantissa_full = true; 1053 ++ begin; 1054 continue; 1055 } 1056 1057 -- pow_of_10; 1058 mantissa = tmp_mantissa; 1059 mantissa += *begin - zero; 1060 1061 found_number_before_exp = true; 1062 } else { 1063 1064 if (*begin >= czero && *begin < czero + 10) { 1065 1066 /* Checking for mantissa overflow. If overflow will 1067 * occur, them we only increase multiplyer 1068 */ 1069 mantissa_type tmp_mantissa = mantissa * 10u; 1070 if( !is_mantissa_full 1071 && tmp_mantissa / 10u == mantissa 1072 && (std::numeric_limits<mantissa_type>::max)()-(*begin - zero) >= tmp_mantissa 1073 ) 1074 { 1075 mantissa = tmp_mantissa; 1076 mantissa += *begin - zero; 1077 } else 1078 { 1079 is_mantissa_full = true; 1080 ++ pow_of_10; 1081 } 1082 1083 found_number_before_exp = true; 1084 ++ length_since_last_delim; 1085 } else if (Traits::eq(*begin, decimal_point) || Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) { 1086#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE 1087 /* If ( we need to check grouping 1088 * and ( grouping missmatches 1089 * or grouping position is incorrect 1090 * or we are using the grouping position 0 twice 1091 * ) 1092 * ) then return error 1093 */ 1094 if( grouping_size && found_grouping 1095 && ( 1096 length_since_last_delim != grouping[0] 1097 || last_grouping_pos>1 1098 || (last_grouping_pos==0 && grouping_size>1) 1099 ) 1100 ) return false; 1101#endif 1102 1103 if(Traits::eq(*begin, decimal_point)) { 1104 ++ begin; 1105 found_decimal = true; 1106 if (!found_number_before_exp && begin==end) return false; 1107 continue; 1108 }else { 1109 if (!found_number_before_exp) return false; 1110 break; 1111 } 1112 } 1113#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE 1114 else if (grouping_size && Traits::eq(*begin, thousands_sep)){ 1115 if(found_grouping) 1116 { 1117 /* It is not he first time, when we find thousands separator, 1118 * so we need to chek, is the distance between two groupings 1119 * equal to grouping[last_grouping_pos] */ 1120 1121 if (length_since_last_delim != grouping[last_grouping_pos] ) 1122 { 1123 if (!last_grouping_pos) return false; 1124 else 1125 { 1126 -- last_grouping_pos; 1127 if (length_since_last_delim != grouping[last_grouping_pos]) return false; 1128 } 1129 } else 1130 /* We are calling the grouping[0] twice, when grouping size is more than 1 */ 1131 if (grouping_size>1u && last_grouping_pos+1<grouping_size) return false; 1132 1133 } else { 1134 /* Delimiter at the begining ',000' */ 1135 if (!length_since_last_delim) return false; 1136 1137 found_grouping = true; 1138 if (length_since_last_delim > grouping[last_grouping_pos] ) return false; 1139 } 1140 1141 length_since_last_delim = 0; 1142 ++ begin; 1143 1144 /* Delimiter at the end '100,' */ 1145 if (begin == end) return false; 1146 continue; 1147 } 1148#endif 1149 else return false; 1150 } 1151 1152 ++begin; 1153 } 1154 1155 // Exponent found 1156 if ( begin != end && (Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) ) { 1157 ++ begin; 1158 if ( begin == end ) return false; 1159 1160 bool exp_has_minus = false; 1161 if(Traits::eq(*begin, minus)) { 1162 exp_has_minus = true; 1163 ++ begin; 1164 if ( begin == end ) return false; 1165 } else if (Traits::eq(*begin, plus)) { 1166 ++ begin; 1167 if ( begin == end ) return false; 1168 } 1169 1170 int exp_pow_of_10 = 0; 1171 while ( begin != end ) 1172 { 1173 if ( *begin < czero 1174 || *begin >= czero + 10 1175 || exp_pow_of_10 * 10 < exp_pow_of_10) /* Overflows are checked lower more precisely*/ 1176 return false; 1177 1178 exp_pow_of_10 *= 10; 1179 exp_pow_of_10 += *begin - zero; 1180 ++ begin; 1181 }; 1182 1183 if ( exp_pow_of_10 ) { 1184 /* Overflows are checked lower */ 1185 if ( exp_has_minus ) { 1186 pow_of_10 -= exp_pow_of_10; 1187 } else { 1188 pow_of_10 += exp_pow_of_10; 1189 } 1190 } 1191 } 1192 1193 /* We need a more accurate algorithm... We can not use current algorithm 1194 * with long doubles (and with doubles if sizeof(double)==sizeof(long double)). 1195 */ 1196 long double result = std::pow(10.0L, pow_of_10) * mantissa; 1197 value = static_cast<T>( has_minus ? (boost::math::changesign)(result) : result); 1198 1199 if ( (boost::math::isinf)(value) || (boost::math::isnan)(value) ) return false; 1200 1201 return true; 1202 } 1203 } 1204 1205 namespace detail // stl_buf_unlocker 1206 { 1207 template< class BufferType, class CharT > 1208 class stl_buf_unlocker: public BufferType{ 1209 public: 1210 typedef BufferType base_class; 1211#ifndef BOOST_NO_USING_TEMPLATE 1212 using base_class::pptr; 1213 using base_class::pbase; 1214 using base_class::setg; 1215 using base_class::setp; 1216#else 1217 CharT* pptr() const { return base_class::pptr(); } 1218 CharT* pbase() const { return base_class::pbase(); } 1219 void setg(CharT* gbeg, CharT* gnext, CharT* gend){ return base_class::setg(gbeg, gnext, gend); } 1220 void setp(CharT* pbeg, CharT* pend) { return setp(pbeg, pend); } 1221#endif 1222 }; 1223 } 1224 1225 namespace detail 1226 { 1227 struct do_not_construct_out_stream_t{}; 1228 } 1229 1230 namespace detail // optimized stream wrapper 1231 { 1232 // String representation of Source has an upper limit. 1233 template< class CharT // a result of widest_char transformation 1234 , class Traits // usually char_traits<CharT> 1235 , bool RequiresStringbuffer 1236 > 1237 class lexical_stream_limited_src 1238 { 1239 1240#if defined(BOOST_NO_STRINGSTREAM) 1241 typedef std::ostrstream out_stream_t; 1242 typedef stl_buf_unlocker<std::strstreambuf, char> unlocked_but_t; 1243#elif defined(BOOST_NO_STD_LOCALE) 1244 typedef std::ostringstream out_stream_t; 1245 typedef stl_buf_unlocker<std::stringbuf, char> unlocked_but_t; 1246#else 1247 typedef std::basic_ostringstream<CharT, Traits> out_stream_t; 1248 typedef stl_buf_unlocker<std::basic_stringbuf<CharT, Traits>, CharT> unlocked_but_t; 1249#endif 1250 typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< 1251 RequiresStringbuffer, 1252 out_stream_t, 1253 do_not_construct_out_stream_t 1254 >::type deduced_out_stream_t; 1255 1256 // A string representation of Source is written to [start, finish). 1257 CharT* start; 1258 CharT* finish; 1259 deduced_out_stream_t out_stream; 1260 1261 public: 1262 lexical_stream_limited_src(CharT* sta, CharT* fin) 1263 : start(sta) 1264 , finish(fin) 1265 {} 1266 1267 private: 1268 // Undefined: 1269 lexical_stream_limited_src(lexical_stream_limited_src const&); 1270 void operator=(lexical_stream_limited_src const&); 1271 1272/************************************ HELPER FUNCTIONS FOR OPERATORS << ( ... ) ********************************/ 1273 bool shl_char(CharT ch) BOOST_NOEXCEPT 1274 { 1275 Traits::assign(*start, ch); 1276 finish = start + 1; 1277 return true; 1278 } 1279 1280#ifndef BOOST_LCAST_NO_WCHAR_T 1281 template <class T> 1282 bool shl_char(T ch) 1283 { 1284 BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)) , 1285 "boost::lexical_cast does not support narrowing of char types." 1286 "Use boost::locale instead" ); 1287#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE 1288 std::locale loc; 1289 CharT const w = BOOST_USE_FACET(std::ctype<CharT>, loc).widen(ch); 1290#else 1291 CharT const w = ch; 1292#endif 1293 Traits::assign(*start, w); 1294 finish = start + 1; 1295 return true; 1296 } 1297#endif 1298 1299 bool shl_char_array(CharT const* str) BOOST_NOEXCEPT 1300 { 1301 start = const_cast<CharT*>(str); 1302 finish = start + Traits::length(str); 1303 return true; 1304 } 1305 1306 template <class T> 1307 bool shl_char_array(T const* str) 1308 { 1309 BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)), 1310 "boost::lexical_cast does not support narrowing of char types." 1311 "Use boost::locale instead" ); 1312 return shl_input_streamable(str); 1313 } 1314 1315 bool shl_char_array_limited(CharT const* str, std::size_t max_size) BOOST_NOEXCEPT 1316 { 1317 start = const_cast<CharT*>(str); 1318 finish = std::find(start, start + max_size, Traits::to_char_type(0)); 1319 return true; 1320 } 1321 1322 template<typename InputStreamable> 1323 bool shl_input_streamable(InputStreamable& input) 1324 { 1325#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) 1326 // If you have compilation error at this point, than your STL library 1327 // does not support such conversions. Try updating it. 1328 BOOST_STATIC_ASSERT((boost::is_same<char, CharT>::value)); 1329#endif 1330 bool const result = !(out_stream << input).fail(); 1331 const unlocked_but_t* const p 1332 = static_cast<unlocked_but_t*>(out_stream.rdbuf()) ; 1333 start = p->pbase(); 1334 finish = p->pptr(); 1335 return result; 1336 } 1337 1338 template <class T> 1339 inline bool shl_signed(T n) 1340 { 1341 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish); 1342 if(n < 0) 1343 { 1344 --start; 1345 CharT const minus = lcast_char_constants<CharT>::minus; 1346 Traits::assign(*start, minus); 1347 } 1348 return true; 1349 } 1350 1351 template <class T, class SomeCharT> 1352 bool shl_real_type(const T& val, SomeCharT* begin, SomeCharT*& end) 1353 { 1354 if (put_inf_nan(begin, end, val)) return true; 1355 lcast_set_precision(out_stream, &val); 1356 return shl_input_streamable(val); 1357 } 1358 1359 static bool shl_real_type(float val, char* begin, char*& end) 1360 { using namespace std; 1361 if (put_inf_nan(begin, end, val)) return true; 1362 const double val_as_double = val; 1363 end = begin + 1364#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) 1365 sprintf_s(begin, end-begin, 1366#else 1367 sprintf(begin, 1368#endif 1369 "%.*g", static_cast<int>(boost::detail::lcast_get_precision<float>()), val_as_double); 1370 return end > begin; 1371 } 1372 1373 static bool shl_real_type(double val, char* begin, char*& end) 1374 { using namespace std; 1375 if (put_inf_nan(begin, end, val)) return true; 1376 end = begin + 1377#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) 1378 sprintf_s(begin, end-begin, 1379#else 1380 sprintf(begin, 1381#endif 1382 "%.*g", static_cast<int>(boost::detail::lcast_get_precision<double>()), val); 1383 return end > begin; 1384 } 1385 1386#ifndef __MINGW32__ 1387 static bool shl_real_type(long double val, char* begin, char*& end) 1388 { using namespace std; 1389 if (put_inf_nan(begin, end, val)) return true; 1390 end = begin + 1391#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) 1392 sprintf_s(begin, end-begin, 1393#else 1394 sprintf(begin, 1395#endif 1396 "%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double>()), val ); 1397 return end > begin; 1398 } 1399#endif 1400 1401 1402#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__) 1403 static bool shl_real_type(float val, wchar_t* begin, wchar_t*& end) 1404 { using namespace std; 1405 if (put_inf_nan(begin, end, val)) return true; 1406 const double val_as_double = val; 1407 end = begin + swprintf(begin, end-begin, 1408 L"%.*g", 1409 static_cast<int>(boost::detail::lcast_get_precision<float >()), 1410 val_as_double ); 1411 return end > begin; 1412 } 1413 1414 static bool shl_real_type(double val, wchar_t* begin, wchar_t*& end) 1415 { using namespace std; 1416 if (put_inf_nan(begin, end, val)) return true; 1417 end = begin + swprintf(begin, end-begin, 1418 L"%.*g", static_cast<int>(boost::detail::lcast_get_precision<double >()), val ); 1419 return end > begin; 1420 } 1421 1422 static bool shl_real_type(long double val, wchar_t* begin, wchar_t*& end) 1423 { using namespace std; 1424 if (put_inf_nan(begin, end, val)) return true; 1425 end = begin + swprintf(begin, end-begin, 1426 L"%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double >()), val ); 1427 return end > begin; 1428 } 1429#endif 1430 1431/************************************ OPERATORS << ( ... ) ********************************/ 1432 public: 1433 template<class Alloc> 1434 bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str) BOOST_NOEXCEPT 1435 { 1436 start = const_cast<CharT*>(str.data()); 1437 finish = start + str.length(); 1438 return true; 1439 } 1440 1441 template<class Alloc> 1442 bool operator<<(::boost::container::basic_string<CharT,Traits,Alloc> const& str) BOOST_NOEXCEPT 1443 { 1444 start = const_cast<CharT*>(str.data()); 1445 finish = start + str.length(); 1446 return true; 1447 } 1448 1449 bool operator<<(bool value) BOOST_NOEXCEPT 1450 { 1451 CharT const czero = lcast_char_constants<CharT>::zero; 1452 Traits::assign(*start, Traits::to_char_type(czero + value)); 1453 finish = start + 1; 1454 return true; 1455 } 1456 1457 bool operator<<(const iterator_range<CharT*>& rng) BOOST_NOEXCEPT 1458 { 1459 start = rng.begin(); 1460 finish = rng.end(); 1461 return true; 1462 } 1463 1464 bool operator<<(const iterator_range<const CharT*>& rng) BOOST_NOEXCEPT 1465 { 1466 start = const_cast<CharT*>(rng.begin()); 1467 finish = const_cast<CharT*>(rng.end()); 1468 return true; 1469 } 1470 1471 bool operator<<(const iterator_range<const signed char*>& rng) BOOST_NOEXCEPT 1472 { 1473 return (*this) << iterator_range<char*>( 1474 const_cast<char*>(reinterpret_cast<const char*>(rng.begin())), 1475 const_cast<char*>(reinterpret_cast<const char*>(rng.end())) 1476 ); 1477 } 1478 1479 bool operator<<(const iterator_range<const unsigned char*>& rng) BOOST_NOEXCEPT 1480 { 1481 return (*this) << iterator_range<char*>( 1482 const_cast<char*>(reinterpret_cast<const char*>(rng.begin())), 1483 const_cast<char*>(reinterpret_cast<const char*>(rng.end())) 1484 ); 1485 } 1486 1487 bool operator<<(const iterator_range<signed char*>& rng) BOOST_NOEXCEPT 1488 { 1489 return (*this) << iterator_range<char*>( 1490 reinterpret_cast<char*>(rng.begin()), 1491 reinterpret_cast<char*>(rng.end()) 1492 ); 1493 } 1494 1495 bool operator<<(const iterator_range<unsigned char*>& rng) BOOST_NOEXCEPT 1496 { 1497 return (*this) << iterator_range<char*>( 1498 reinterpret_cast<char*>(rng.begin()), 1499 reinterpret_cast<char*>(rng.end()) 1500 ); 1501 } 1502 1503 bool operator<<(char ch) { return shl_char(ch); } 1504 bool operator<<(unsigned char ch) { return ((*this) << static_cast<char>(ch)); } 1505 bool operator<<(signed char ch) { return ((*this) << static_cast<char>(ch)); } 1506#if !defined(BOOST_LCAST_NO_WCHAR_T) 1507 bool operator<<(wchar_t const* str) { return shl_char_array(str); } 1508 bool operator<<(wchar_t * str) { return shl_char_array(str); } 1509#ifndef BOOST_NO_INTRINSIC_WCHAR_T 1510 bool operator<<(wchar_t ch) { return shl_char(ch); } 1511#endif 1512#endif 1513#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) 1514 bool operator<<(char16_t ch) { return shl_char(ch); } 1515 bool operator<<(char16_t * str) { return shl_char_array(str); } 1516 bool operator<<(char16_t const * str) { return shl_char_array(str); } 1517#endif 1518#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) 1519 bool operator<<(char32_t ch) { return shl_char(ch); } 1520 bool operator<<(char32_t * str) { return shl_char_array(str); } 1521 bool operator<<(char32_t const * str) { return shl_char_array(str); } 1522#endif 1523 bool operator<<(unsigned char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); } 1524 bool operator<<(unsigned char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); } 1525 bool operator<<(signed char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); } 1526 bool operator<<(signed char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); } 1527 bool operator<<(char const* str) { return shl_char_array(str); } 1528 bool operator<<(char* str) { return shl_char_array(str); } 1529 bool operator<<(short n) { return shl_signed(n); } 1530 bool operator<<(int n) { return shl_signed(n); } 1531 bool operator<<(long n) { return shl_signed(n); } 1532 bool operator<<(unsigned short n) { start = lcast_put_unsigned<Traits>(n, finish); return true; } 1533 bool operator<<(unsigned int n) { start = lcast_put_unsigned<Traits>(n, finish); return true; } 1534 bool operator<<(unsigned long n) { start = lcast_put_unsigned<Traits>(n, finish); return true; } 1535 1536#if defined(BOOST_HAS_LONG_LONG) 1537 bool operator<<(boost::ulong_long_type n) { start = lcast_put_unsigned<Traits>(n, finish); return true; } 1538 bool operator<<(boost::long_long_type n) { return shl_signed(n); } 1539#elif defined(BOOST_HAS_MS_INT64) 1540 bool operator<<(unsigned __int64 n) { start = lcast_put_unsigned<Traits>(n, finish); return true; } 1541 bool operator<<( __int64 n) { return shl_signed(n); } 1542#endif 1543 bool operator<<(float val) { return shl_real_type(val, start, finish); } 1544 bool operator<<(double val) { return shl_real_type(val, start, finish); } 1545 bool operator<<(long double val) { 1546#ifndef __MINGW32__ 1547 return shl_real_type(val, start, finish); 1548#else 1549 return shl_real_type(static_cast<double>(val), start, finish); 1550#endif 1551 } 1552 1553 template <std::size_t N> 1554 bool operator<<(boost::array<CharT, N> const& input) BOOST_NOEXCEPT 1555 { return shl_char_array_limited(input.begin(), N); } 1556 1557 template <std::size_t N> 1558 bool operator<<(boost::array<unsigned char, N> const& input) BOOST_NOEXCEPT 1559 { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); } 1560 1561 template <std::size_t N> 1562 bool operator<<(boost::array<signed char, N> const& input) BOOST_NOEXCEPT 1563 { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); } 1564 1565 template <std::size_t N> 1566 bool operator<<(boost::array<const CharT, N> const& input) BOOST_NOEXCEPT 1567 { return shl_char_array_limited(input.begin(), N); } 1568 1569 template <std::size_t N> 1570 bool operator<<(boost::array<const unsigned char, N> const& input) BOOST_NOEXCEPT 1571 { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); } 1572 1573 template <std::size_t N> 1574 bool operator<<(boost::array<const signed char, N> const& input) BOOST_NOEXCEPT 1575 { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); } 1576 1577#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) 1578 template <std::size_t N> 1579 bool operator<<(std::array<CharT, N> const& input) BOOST_NOEXCEPT 1580 { return shl_char_array_limited(input.begin(), N); } 1581 1582 template <std::size_t N> 1583 bool operator<<(std::array<unsigned char, N> const& input) BOOST_NOEXCEPT 1584 { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); } 1585 1586 template <std::size_t N> 1587 bool operator<<(std::array<signed char, N> const& input) BOOST_NOEXCEPT 1588 { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); } 1589 1590 template <std::size_t N> 1591 bool operator<<(std::array<const CharT, N> const& input) BOOST_NOEXCEPT 1592 { return shl_char_array_limited(input.begin(), N); } 1593 1594 template <std::size_t N> 1595 bool operator<<(std::array<const unsigned char, N> const& input) BOOST_NOEXCEPT 1596 { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); } 1597 1598 template <std::size_t N> 1599 bool operator<<(std::array<const signed char, N> const& input) BOOST_NOEXCEPT 1600 { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); } 1601#endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) 1602 1603 template <class InStreamable> 1604 bool operator<<(const InStreamable& input) { return shl_input_streamable(input); } 1605 1606/************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/ 1607 private: 1608 1609 template <typename Type> 1610 bool shr_unsigned(Type& output) 1611 { 1612 if (start == finish) return false; 1613 CharT const minus = lcast_char_constants<CharT>::minus; 1614 CharT const plus = lcast_char_constants<CharT>::plus; 1615 bool has_minus = false; 1616 1617 /* We won`t use `start' any more, so no need in decrementing it after */ 1618 if ( Traits::eq(minus,*start) ) 1619 { 1620 ++start; 1621 has_minus = true; 1622 } else if ( Traits::eq( plus, *start ) ) 1623 { 1624 ++start; 1625 } 1626 1627 bool const succeed = lcast_ret_unsigned<Traits>(output, start, finish); 1628#if (defined _MSC_VER) 1629# pragma warning( push ) 1630// C4146: unary minus operator applied to unsigned type, result still unsigned 1631# pragma warning( disable : 4146 ) 1632#elif defined( __BORLANDC__ ) 1633# pragma option push -w-8041 1634#endif 1635 if (has_minus) output = static_cast<Type>(-output); 1636#if (defined _MSC_VER) 1637# pragma warning( pop ) 1638#elif defined( __BORLANDC__ ) 1639# pragma option pop 1640#endif 1641 return succeed; 1642 } 1643 1644 template <typename Type> 1645 bool shr_signed(Type& output) 1646 { 1647 if (start == finish) return false; 1648 CharT const minus = lcast_char_constants<CharT>::minus; 1649 CharT const plus = lcast_char_constants<CharT>::plus; 1650 typedef BOOST_DEDUCED_TYPENAME make_unsigned<Type>::type utype; 1651 utype out_tmp =0; 1652 bool has_minus = false; 1653 1654 /* We won`t use `start' any more, so no need in decrementing it after */ 1655 if ( Traits::eq(minus,*start) ) 1656 { 1657 ++start; 1658 has_minus = true; 1659 } else if ( Traits::eq(plus, *start) ) 1660 { 1661 ++start; 1662 } 1663 1664 bool succeed = lcast_ret_unsigned<Traits>(out_tmp, start, finish); 1665 if (has_minus) { 1666#if (defined _MSC_VER) 1667# pragma warning( push ) 1668// C4146: unary minus operator applied to unsigned type, result still unsigned 1669# pragma warning( disable : 4146 ) 1670#elif defined( __BORLANDC__ ) 1671# pragma option push -w-8041 1672#endif 1673 utype const comp_val = static_cast<utype>(-(std::numeric_limits<Type>::min)()); 1674 succeed = succeed && out_tmp<=comp_val; 1675 output = -out_tmp; 1676#if (defined _MSC_VER) 1677# pragma warning( pop ) 1678#elif defined( __BORLANDC__ ) 1679# pragma option pop 1680#endif 1681 } else { 1682 utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)()); 1683 succeed = succeed && out_tmp<=comp_val; 1684 output = out_tmp; 1685 } 1686 return succeed; 1687 } 1688 1689 template<typename InputStreamable> 1690 bool shr_using_base_class(InputStreamable& output) 1691 { 1692#if (defined _MSC_VER) 1693# pragma warning( push ) 1694 // conditional expression is constant 1695# pragma warning( disable : 4127 ) 1696#endif 1697 if(is_pointer<InputStreamable>::value) 1698 return false; 1699 1700#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) 1701 // If you have compilation error at this point, than your STL library 1702 // unsupports such conversions. Try updating it. 1703 BOOST_STATIC_ASSERT((boost::is_same<char, CharT>::value)); 1704#endif 1705 1706#if defined(BOOST_NO_STRINGSTREAM) 1707 std::istrstream stream(start, finish - start); 1708#elif defined(BOOST_NO_STD_LOCALE) 1709 std::istringstream stream; 1710#else 1711 std::basic_istringstream<CharT, Traits> stream; 1712#endif 1713 static_cast<unlocked_but_t*>(stream.rdbuf()) 1714 ->setg(start, start, finish); 1715 1716 stream.unsetf(std::ios::skipws); 1717 lcast_set_precision(stream, static_cast<InputStreamable*>(0)); 1718#if (defined _MSC_VER) 1719# pragma warning( pop ) 1720#endif 1721 return stream >> output && 1722 stream.get() == 1723#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) 1724 // GCC 2.9x lacks std::char_traits<>::eof(). 1725 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 1726 // configurations, which do provide std::char_traits<>::eof(). 1727 1728 EOF; 1729#else 1730 Traits::eof(); 1731#endif 1732 } 1733 1734 template<class T> 1735 inline bool shr_xchar(T& output) 1736 { 1737 BOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ), 1738 "boost::lexical_cast does not support narrowing of character types." 1739 "Use boost::locale instead" ); 1740 bool const ok = (finish - start == 1); 1741 if (ok) { 1742 CharT out; 1743 Traits::assign(out, *start); 1744 output = static_cast<T>(out); 1745 } 1746 return ok; 1747 } 1748 1749/************************************ OPERATORS >> ( ... ) ********************************/ 1750 public: 1751 bool operator>>(unsigned short& output) { return shr_unsigned(output); } 1752 bool operator>>(unsigned int& output) { return shr_unsigned(output); } 1753 bool operator>>(unsigned long int& output) { return shr_unsigned(output); } 1754 bool operator>>(short& output) { return shr_signed(output); } 1755 bool operator>>(int& output) { return shr_signed(output); } 1756 bool operator>>(long int& output) { return shr_signed(output); } 1757#if defined(BOOST_HAS_LONG_LONG) 1758 bool operator>>(boost::ulong_long_type& output) { return shr_unsigned(output); } 1759 bool operator>>(boost::long_long_type& output) { return shr_signed(output); } 1760#elif defined(BOOST_HAS_MS_INT64) 1761 bool operator>>(unsigned __int64& output) { return shr_unsigned(output); } 1762 bool operator>>(__int64& output) { return shr_signed(output); } 1763#endif 1764 bool operator>>(char& output) { return shr_xchar(output); } 1765 bool operator>>(unsigned char& output) { return shr_xchar(output); } 1766 bool operator>>(signed char& output) { return shr_xchar(output); } 1767#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) 1768 bool operator>>(wchar_t& output) { return shr_xchar(output); } 1769#endif 1770#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) 1771 bool operator>>(char16_t& output) { return shr_xchar(output); } 1772#endif 1773#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) 1774 bool operator>>(char32_t& output) { return shr_xchar(output); } 1775#endif 1776 template<class Alloc> 1777 bool operator>>(std::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; } 1778 1779 template<class Alloc> 1780 bool operator>>(::boost::container::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; } 1781 1782 1783 private: 1784 template <std::size_t N, class ArrayT> 1785 bool shr_std_array(ArrayT& output) BOOST_NOEXCEPT 1786 { 1787 using namespace std; 1788 const std::size_t size = finish - start; 1789 if (size > N - 1) { // `-1` because we need to store \0 at the end 1790 return false; 1791 } 1792 1793 memcpy(output.begin(), start, size * sizeof(CharT)); 1794 *(output.begin() + size) = Traits::to_char_type(0); 1795 return true; 1796 } 1797 1798 public: 1799 1800 template <std::size_t N> 1801 bool operator>>(boost::array<CharT, N>& output) BOOST_NOEXCEPT 1802 { 1803 return shr_std_array<N>(output); 1804 } 1805 1806 template <std::size_t N> 1807 bool operator>>(boost::array<unsigned char, N>& output) 1808 { 1809 return ((*this) >> reinterpret_cast<boost::array<char, N>& >(output)); 1810 } 1811 1812 template <std::size_t N> 1813 bool operator>>(boost::array<signed char, N>& output) 1814 { 1815 return ((*this) >> reinterpret_cast<boost::array<char, N>& >(output)); 1816 } 1817 1818#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) 1819 template <std::size_t N> 1820 bool operator>>(std::array<CharT, N>& output) BOOST_NOEXCEPT 1821 { 1822 return shr_std_array<N>(output); 1823 } 1824 1825 template <std::size_t N> 1826 bool operator>>(std::array<unsigned char, N>& output) 1827 { 1828 return ((*this) >> reinterpret_cast<std::array<char, N>& >(output)); 1829 } 1830 1831 template <std::size_t N> 1832 bool operator>>(std::array<signed char, N>& in) 1833 { 1834 return ((*this) >> reinterpret_cast<std::array<char, N>& >(output)); 1835 } 1836#endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) 1837 1838 1839 /* 1840 * case "-0" || "0" || "+0" : output = false; return true; 1841 * case "1" || "+1": output = true; return true; 1842 * default: return false; 1843 */ 1844 bool operator>>(bool& output) BOOST_NOEXCEPT 1845 { 1846 CharT const zero = lcast_char_constants<CharT>::zero; 1847 CharT const plus = lcast_char_constants<CharT>::plus; 1848 CharT const minus = lcast_char_constants<CharT>::minus; 1849 1850 switch(finish-start) 1851 { 1852 case 1: 1853 output = Traits::eq(start[0], zero+1); 1854 return output || Traits::eq(start[0], zero ); 1855 case 2: 1856 if ( Traits::eq( plus, *start) ) 1857 { 1858 ++start; 1859 output = Traits::eq(start[0], zero +1); 1860 return output || Traits::eq(start[0], zero ); 1861 } else 1862 { 1863 output = false; 1864 return Traits::eq( minus, *start) 1865 && Traits::eq( zero, start[1]); 1866 } 1867 default: 1868 output = false; // Suppress warning about uninitalized variable 1869 return false; 1870 } 1871 } 1872 1873 bool operator>>(float& output) { return lcast_ret_float<Traits>(output,start,finish); } 1874 1875 private: 1876 // Not optimised converter 1877 template <class T> 1878 bool float_types_converter_internal(T& output, int /*tag*/) { 1879 if (parse_inf_nan(start, finish, output)) return true; 1880 bool return_value = shr_using_base_class(output); 1881 1882 /* Some compilers and libraries successfully 1883 * parse 'inf', 'INFINITY', '1.0E', '1.0E-'... 1884 * We are trying to provide a unified behaviour, 1885 * so we just forbid such conversions (as some 1886 * of the most popular compilers/libraries do) 1887 * */ 1888 CharT const minus = lcast_char_constants<CharT>::minus; 1889 CharT const plus = lcast_char_constants<CharT>::plus; 1890 CharT const capital_e = lcast_char_constants<CharT>::capital_e; 1891 CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e; 1892 if ( return_value && 1893 ( 1894 Traits::eq(*(finish-1), lowercase_e) // 1.0e 1895 || Traits::eq(*(finish-1), capital_e) // 1.0E 1896 || Traits::eq(*(finish-1), minus) // 1.0e- or 1.0E- 1897 || Traits::eq(*(finish-1), plus) // 1.0e+ or 1.0E+ 1898 ) 1899 ) return false; 1900 1901 return return_value; 1902 } 1903 1904 // Optimised converter 1905 bool float_types_converter_internal(double& output,char /*tag*/) { 1906 return lcast_ret_float<Traits>(output,start,finish); 1907 } 1908 public: 1909 1910 bool operator>>(double& output) 1911 { 1912 /* 1913 * Some compilers implement long double as double. In that case these types have 1914 * same size, same precision, same max and min values... And it means, 1915 * that current implementation of lcast_ret_float cannot be used for type 1916 * double, because it will give a big precision loss. 1917 * */ 1918 boost::mpl::if_c< 1919#if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64) 1920 ::boost::type_traits::ice_eq< sizeof(double), sizeof(long double) >::value, 1921#else 1922 0 1923#endif 1924 int, 1925 char 1926 >::type tag = 0; 1927 1928 return float_types_converter_internal(output, tag); 1929 } 1930 1931 bool operator>>(long double& output) 1932 { 1933 int tag = 0; 1934 return float_types_converter_internal(output, tag); 1935 } 1936 1937 // Generic istream-based algorithm. 1938 // lcast_streambuf_for_target<InputStreamable>::value is true. 1939 template<typename InputStreamable> 1940 bool operator>>(InputStreamable& output) { return shr_using_base_class(output); } 1941 }; 1942 } 1943 1944 namespace detail 1945 { 1946 template<class T> 1947 struct array_to_pointer_decay 1948 { 1949 typedef T type; 1950 }; 1951 1952 template<class T, std::size_t N> 1953 struct array_to_pointer_decay<T[N]> 1954 { 1955 typedef const T * type; 1956 }; 1957 1958 template<typename T> 1959 struct is_stdstring 1960 { 1961 BOOST_STATIC_CONSTANT(bool, value = false ); 1962 }; 1963 1964 template<typename CharT, typename Traits, typename Alloc> 1965 struct is_stdstring< std::basic_string<CharT, Traits, Alloc> > 1966 { 1967 BOOST_STATIC_CONSTANT(bool, value = true ); 1968 }; 1969 1970 template<typename CharT, typename Traits, typename Alloc> 1971 struct is_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc> > 1972 { 1973 BOOST_STATIC_CONSTANT(bool, value = true ); 1974 }; 1975 1976 template<typename Target, typename Source> 1977 struct is_arithmetic_and_not_xchars 1978 { 1979 BOOST_STATIC_CONSTANT(bool, value = 1980 ( 1981 ::boost::type_traits::ice_and< 1982 ::boost::is_arithmetic<Source>::value, 1983 ::boost::is_arithmetic<Target>::value, 1984 ::boost::type_traits::ice_not< 1985 detail::is_char_or_wchar<Target>::value 1986 >::value, 1987 ::boost::type_traits::ice_not< 1988 detail::is_char_or_wchar<Source>::value 1989 >::value 1990 >::value 1991 ) 1992 ); 1993 }; 1994 1995 /* 1996 * is_xchar_to_xchar<Target, Source>::value is true, when 1997 * Target and Souce are the same char types, or when 1998 * Target and Souce are char types of the same size. 1999 */ 2000 template<typename Target, typename Source> 2001 struct is_xchar_to_xchar 2002 { 2003 BOOST_STATIC_CONSTANT(bool, value = 2004 ( 2005 ::boost::type_traits::ice_or< 2006 ::boost::type_traits::ice_and< 2007 is_same<Source,Target>::value, 2008 is_char_or_wchar<Target>::value 2009 >::value, 2010 ::boost::type_traits::ice_and< 2011 ::boost::type_traits::ice_eq< sizeof(char),sizeof(Target)>::value, 2012 ::boost::type_traits::ice_eq< sizeof(char),sizeof(Source)>::value, 2013 is_char_or_wchar<Target>::value, 2014 is_char_or_wchar<Source>::value 2015 >::value 2016 >::value 2017 ) 2018 ); 2019 }; 2020 2021 2022 // this metafunction evaluates to true, if we have optimized comnversion 2023 // from Float type to Char array. 2024 // Must be in sync with lexical_stream_limited_src<Char, ...>::shl_real_type(...) 2025 template <typename Float, typename Char> 2026 struct is_this_float_conversion_optimized 2027 { 2028 typedef ::boost::type_traits::ice_and< 2029 ::boost::is_float<Float>::value, 2030#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__) 2031 ::boost::type_traits::ice_or< 2032 ::boost::type_traits::ice_eq<sizeof(Char), sizeof(char) >::value, 2033 ::boost::is_same<Char, wchar_t>::value 2034 >::value 2035#else 2036 ::boost::type_traits::ice_eq<sizeof(Char), sizeof(char) >::value 2037#endif 2038 > result_type; 2039 2040 BOOST_STATIC_CONSTANT(bool, value = (result_type::value) ); 2041 }; 2042 2043 template<typename Target, typename Source> 2044 struct is_char_array_to_stdstring 2045 { 2046 BOOST_STATIC_CONSTANT(bool, value = false ); 2047 }; 2048 2049 template<typename CharT, typename Traits, typename Alloc> 2050 struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, CharT* > 2051 { 2052 BOOST_STATIC_CONSTANT(bool, value = true ); 2053 }; 2054 2055 template<typename CharT, typename Traits, typename Alloc> 2056 struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, const CharT* > 2057 { 2058 BOOST_STATIC_CONSTANT(bool, value = true ); 2059 }; 2060 2061 template<typename CharT, typename Traits, typename Alloc> 2062 struct is_char_array_to_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc>, CharT* > 2063 { 2064 BOOST_STATIC_CONSTANT(bool, value = true ); 2065 }; 2066 2067 template<typename CharT, typename Traits, typename Alloc> 2068 struct is_char_array_to_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc>, const CharT* > 2069 { 2070 BOOST_STATIC_CONSTANT(bool, value = true ); 2071 }; 2072 2073#if (defined _MSC_VER) 2074# pragma warning( push ) 2075# pragma warning( disable : 4701 ) // possible use of ... before initialization 2076# pragma warning( disable : 4702 ) // unreachable code 2077# pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int' 2078#endif 2079 template<typename Target, typename Source> 2080 struct lexical_cast_do_cast 2081 { 2082 static inline Target lexical_cast_impl(const Source& arg) 2083 { 2084 typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay<Source>::type src; 2085 typedef BOOST_DEDUCED_TYPENAME ::boost::remove_cv<src>::type no_cv_src; 2086 typedef BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type target_char_t; 2087 typedef BOOST_DEDUCED_TYPENAME detail::stream_char<no_cv_src>::type src_char_type; 2088 typedef BOOST_DEDUCED_TYPENAME detail::widest_char< 2089 target_char_t, src_char_type 2090 >::type char_type; 2091 2092#if !defined(BOOST_NO_CHAR16_T) && defined(BOOST_NO_UNICODE_LITERALS) 2093 BOOST_STATIC_ASSERT_MSG(( !::boost::is_same<char16_t, src_char_type>::value 2094 && !::boost::is_same<char16_t, target_char_t>::value), 2095 "Your compiler does not have full support for char16_t" ); 2096#endif 2097#if !defined(BOOST_NO_CHAR32_T) && defined(BOOST_NO_UNICODE_LITERALS) 2098 BOOST_STATIC_ASSERT_MSG(( !::boost::is_same<char32_t, src_char_type>::value 2099 && !::boost::is_same<char32_t, target_char_t>::value), 2100 "Your compiler does not have full support for char32_t" ); 2101#endif 2102 2103 typedef BOOST_DEDUCED_TYPENAME ::boost::detail::deduce_char_traits< 2104 char_type, Target, no_cv_src 2105 >::type traits; 2106 2107 typedef ::boost::type_traits::ice_and< 2108 ::boost::detail::is_char_or_wchar<src_char_type>::value, // source is lexical type 2109 ::boost::detail::is_char_or_wchar<target_char_t>::value, // target is a lexical type 2110 ::boost::is_same<char, src_char_type>::value, // source is not a wide character based type 2111 ::boost::type_traits::ice_ne<sizeof(char), sizeof(target_char_t) >::value // target type is based on wide character 2112 > is_string_widening_required_t; 2113 2114 typedef ::boost::type_traits::ice_or< 2115 ::boost::is_integral<no_cv_src>::value, 2116 ::boost::detail::is_this_float_conversion_optimized<no_cv_src, char_type >::value, 2117 ::boost::detail::is_char_or_wchar<src_char_type >::value 2118 > is_source_input_optimized_t; 2119 2120 // Target type must be default constructible 2121 Target result; 2122 2123 // If we have an optimized conversion for 2124 // Source, we do not need to construct stringbuf. 2125 const bool requires_stringbuf = ::boost::type_traits::ice_or< 2126 is_string_widening_required_t::value, 2127 ::boost::type_traits::ice_not< is_source_input_optimized_t::value >::value 2128 >::value; 2129 2130 typedef detail::lexical_stream_limited_src<char_type, traits, requires_stringbuf > interpreter_type; 2131 2132 typedef detail::lcast_src_length<no_cv_src> lcast_src_length; 2133 std::size_t const src_len = lcast_src_length::value; 2134 char_type buf[src_len + 1]; 2135 lcast_src_length::check_coverage(); 2136 2137 interpreter_type interpreter(buf, buf + src_len); 2138 2139 // Disabling ADL, by directly specifying operators. 2140 if(!(interpreter.operator <<(arg) && interpreter.operator >>(result))) 2141 BOOST_LCAST_THROW_BAD_CAST(Source, Target); 2142 2143 return result; 2144 } 2145 }; 2146#if (defined _MSC_VER) 2147# pragma warning( pop ) 2148#endif 2149 2150 template <typename Source> 2151 struct lexical_cast_copy 2152 { 2153 static inline const Source& lexical_cast_impl(const Source &arg) BOOST_NOEXCEPT 2154 { 2155 return arg; 2156 } 2157 }; 2158 2159 template <class Source, class Target > 2160 struct detect_precision_loss 2161 { 2162 typedef boost::numeric::Trunc<Source> Rounder; 2163 typedef Source source_type ; 2164 2165 typedef BOOST_DEDUCED_TYPENAME mpl::if_< 2166 ::boost::is_arithmetic<Source>, Source, Source const& 2167 >::type argument_type ; 2168 2169 static source_type nearbyint ( argument_type s ) 2170 { 2171 const source_type orig_div_round = s / Rounder::nearbyint(s); 2172 const source_type eps = std::numeric_limits<source_type>::epsilon(); 2173 2174 if ((orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > eps) 2175 BOOST_LCAST_THROW_BAD_CAST(Source, Target); 2176 2177 return s ; 2178 } 2179 2180 typedef typename Rounder::round_style round_style; 2181 } ; 2182 2183 template <class Source, class Target > 2184 struct nothrow_overflow_handler 2185 { 2186 void operator() ( boost::numeric::range_check_result r ) 2187 { 2188 if (r != boost::numeric::cInRange) 2189 BOOST_LCAST_THROW_BAD_CAST(Source, Target); 2190 } 2191 } ; 2192 2193 template <typename Target, typename Source> 2194 struct lexical_cast_dynamic_num_not_ignoring_minus 2195 { 2196 static inline Target lexical_cast_impl(const Source &arg) 2197 { 2198 return boost::numeric::converter< 2199 Target, 2200 Source, 2201 boost::numeric::conversion_traits<Target,Source>, 2202 nothrow_overflow_handler<Source, Target>, 2203 detect_precision_loss<Source, Target> 2204 >::convert(arg); 2205 } 2206 }; 2207 2208 template <typename Target, typename Source> 2209 struct lexical_cast_dynamic_num_ignoring_minus 2210 { 2211 static inline Target lexical_cast_impl(const Source &arg) 2212 { 2213 typedef boost::numeric::converter< 2214 Target, 2215 Source, 2216 boost::numeric::conversion_traits<Target,Source>, 2217 nothrow_overflow_handler<Source, Target>, 2218 detect_precision_loss<Source, Target> 2219 > converter_t; 2220 2221 return ( 2222 arg < 0 ? -converter_t::convert(-arg) : converter_t::convert(arg) 2223 ); 2224 } 2225 }; 2226 2227 /* 2228 * lexical_cast_dynamic_num follows the rules: 2229 * 1) If Source can be converted to Target without precision loss and 2230 * without overflows, then assign Source to Target and return 2231 * 2232 * 2) If Source is less than 0 and Target is an unsigned integer, 2233 * then negate Source, check the requirements of rule 1) and if 2234 * successful, assign static_casted Source to Target and return 2235 * 2236 * 3) Otherwise throw a bad_lexical_cast exception 2237 * 2238 * 2239 * Rule 2) required because boost::lexical_cast has the behavior of 2240 * stringstream, which uses the rules of scanf for conversions. And 2241 * in the C99 standard for unsigned input value minus sign is 2242 * optional, so if a negative number is read, no errors will arise 2243 * and the result will be the two's complement. 2244 */ 2245 template <typename Target, typename Source> 2246 struct lexical_cast_dynamic_num 2247 { 2248 static inline Target lexical_cast_impl(const Source &arg) 2249 { 2250 typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< 2251 ::boost::type_traits::ice_and< 2252 ::boost::type_traits::ice_or< 2253 ::boost::is_signed<Source>::value, 2254 ::boost::is_float<Source>::value 2255 >::value, 2256 ::boost::type_traits::ice_not< 2257 ::boost::is_same<Source, bool>::value 2258 >::value, 2259 ::boost::type_traits::ice_not< 2260 ::boost::is_same<Target, bool>::value 2261 >::value, 2262 ::boost::is_unsigned<Target>::value 2263 >::value, 2264 lexical_cast_dynamic_num_ignoring_minus<Target, Source>, 2265 lexical_cast_dynamic_num_not_ignoring_minus<Target, Source> 2266 >::type caster_type; 2267 2268 return caster_type::lexical_cast_impl(arg); 2269 } 2270 }; 2271 } 2272 2273 template <typename Target, typename Source> 2274 inline Target lexical_cast(const Source &arg) 2275 { 2276 typedef BOOST_DEDUCED_TYPENAME ::boost::detail::array_to_pointer_decay<Source>::type src; 2277 2278 typedef BOOST_DEDUCED_TYPENAME ::boost::type_traits::ice_or< 2279 ::boost::detail::is_xchar_to_xchar<Target, src >::value, 2280 ::boost::detail::is_char_array_to_stdstring<Target, src >::value, 2281 ::boost::type_traits::ice_and< 2282 ::boost::is_same<Target, src >::value, 2283 ::boost::detail::is_stdstring<Target >::value 2284 >::value 2285 > shall_we_copy_t; 2286 2287 typedef BOOST_DEDUCED_TYPENAME 2288 ::boost::detail::is_arithmetic_and_not_xchars<Target, src > shall_we_copy_with_dynamic_check_t; 2289 2290 typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< 2291 shall_we_copy_t::value, 2292 ::boost::detail::lexical_cast_copy<src >, 2293 BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< 2294 shall_we_copy_with_dynamic_check_t::value, 2295 ::boost::detail::lexical_cast_dynamic_num<Target, src >, 2296 ::boost::detail::lexical_cast_do_cast<Target, src > 2297 >::type 2298 >::type caster_type; 2299 2300 return caster_type::lexical_cast_impl(arg); 2301 } 2302 2303 template <typename Target> 2304 inline Target lexical_cast(const char* chars, std::size_t count) 2305 { 2306 return ::boost::lexical_cast<Target>( 2307 ::boost::iterator_range<const char*>(chars, chars + count) 2308 ); 2309 } 2310 2311 2312 template <typename Target> 2313 inline Target lexical_cast(const unsigned char* chars, std::size_t count) 2314 { 2315 return ::boost::lexical_cast<Target>( 2316 ::boost::iterator_range<const unsigned char*>(chars, chars + count) 2317 ); 2318 } 2319 2320 template <typename Target> 2321 inline Target lexical_cast(const signed char* chars, std::size_t count) 2322 { 2323 return ::boost::lexical_cast<Target>( 2324 ::boost::iterator_range<const signed char*>(chars, chars + count) 2325 ); 2326 } 2327 2328#ifndef BOOST_LCAST_NO_WCHAR_T 2329 template <typename Target> 2330 inline Target lexical_cast(const wchar_t* chars, std::size_t count) 2331 { 2332 return ::boost::lexical_cast<Target>( 2333 ::boost::iterator_range<const wchar_t*>(chars, chars + count) 2334 ); 2335 } 2336#endif 2337#ifndef BOOST_NO_CHAR16_T 2338 template <typename Target> 2339 inline Target lexical_cast(const char16_t* chars, std::size_t count) 2340 { 2341 return ::boost::lexical_cast<Target>( 2342 ::boost::iterator_range<const char16_t*>(chars, chars + count) 2343 ); 2344 } 2345#endif 2346#ifndef BOOST_NO_CHAR32_T 2347 template <typename Target> 2348 inline Target lexical_cast(const char32_t* chars, std::size_t count) 2349 { 2350 return ::boost::lexical_cast<Target>( 2351 ::boost::iterator_range<const char32_t*>(chars, chars + count) 2352 ); 2353 } 2354#endif 2355 2356} // namespace boost 2357 2358#else // #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION 2359 2360namespace boost { 2361 namespace detail 2362 { 2363 2364 // selectors for choosing stream character type 2365 template<typename Type> 2366 struct stream_char 2367 { 2368 typedef char type; 2369 }; 2370 2371#ifndef BOOST_LCAST_NO_WCHAR_T 2372#ifndef BOOST_NO_INTRINSIC_WCHAR_T 2373 template<> 2374 struct stream_char<wchar_t> 2375 { 2376 typedef wchar_t type; 2377 }; 2378#endif 2379 2380 template<> 2381 struct stream_char<wchar_t *> 2382 { 2383 typedef wchar_t type; 2384 }; 2385 2386 template<> 2387 struct stream_char<const wchar_t *> 2388 { 2389 typedef wchar_t type; 2390 }; 2391 2392 template<> 2393 struct stream_char<std::wstring> 2394 { 2395 typedef wchar_t type; 2396 }; 2397#endif 2398 2399 // stream wrapper for handling lexical conversions 2400 template<typename Target, typename Source, typename Traits> 2401 class lexical_stream 2402 { 2403 private: 2404 typedef typename widest_char< 2405 typename stream_char<Target>::type, 2406 typename stream_char<Source>::type>::type char_type; 2407 2408 typedef Traits traits_type; 2409 2410 public: 2411 lexical_stream(char_type* = 0, char_type* = 0) 2412 { 2413 stream.unsetf(std::ios::skipws); 2414 lcast_set_precision(stream, static_cast<Source*>(0), static_cast<Target*>(0) ); 2415 } 2416 ~lexical_stream() 2417 { 2418 #if defined(BOOST_NO_STRINGSTREAM) 2419 stream.freeze(false); 2420 #endif 2421 } 2422 bool operator<<(const Source &input) 2423 { 2424 return !(stream << input).fail(); 2425 } 2426 template<typename InputStreamable> 2427 bool operator>>(InputStreamable &output) 2428 { 2429 return !is_pointer<InputStreamable>::value && 2430 stream >> output && 2431 stream.get() == 2432#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) 2433// GCC 2.9x lacks std::char_traits<>::eof(). 2434// We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 2435// configurations, which do provide std::char_traits<>::eof(). 2436 2437 EOF; 2438#else 2439 traits_type::eof(); 2440#endif 2441 } 2442 2443 bool operator>>(std::string &output) 2444 { 2445 #if defined(BOOST_NO_STRINGSTREAM) 2446 stream << '\0'; 2447 #endif 2448 stream.str().swap(output); 2449 return true; 2450 } 2451 #ifndef BOOST_LCAST_NO_WCHAR_T 2452 bool operator>>(std::wstring &output) 2453 { 2454 stream.str().swap(output); 2455 return true; 2456 } 2457 #endif 2458 2459 private: 2460 #if defined(BOOST_NO_STRINGSTREAM) 2461 std::strstream stream; 2462 #elif defined(BOOST_NO_STD_LOCALE) 2463 std::stringstream stream; 2464 #else 2465 std::basic_stringstream<char_type,traits_type> stream; 2466 #endif 2467 }; 2468 } 2469 2470 // call-by-value fallback version (deprecated) 2471 2472 template<typename Target, typename Source> 2473 Target lexical_cast(Source arg) 2474 { 2475 typedef typename detail::widest_char< 2476 BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type 2477 , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type 2478 >::type char_type; 2479 2480 typedef std::char_traits<char_type> traits; 2481 detail::lexical_stream<Target, Source, traits> interpreter; 2482 Target result; 2483 2484 if(!(interpreter << arg && interpreter >> result)) 2485 BOOST_LCAST_THROW_BAD_CAST(Source, Target); 2486 return result; 2487 } 2488 2489} // namespace boost 2490 2491#endif 2492 2493// Copyright Kevlin Henney, 2000-2005. 2494// Copyright Alexander Nasonov, 2006-2010. 2495// Copyright Antony Polukhin, 2011-2012. 2496// 2497// Distributed under the Boost Software License, Version 1.0. (See 2498// accompanying file LICENSE_1_0.txt or copy at 2499// http://www.boost.org/LICENSE_1_0.txt) 2500 2501#undef BOOST_LCAST_THROW_BAD_CAST 2502#undef BOOST_LCAST_NO_WCHAR_T 2503 2504#endif // BOOST_LEXICAL_CAST_INCLUDED 2505 2506