1 #ifndef BOOST_LEXICAL_CAST_INCLUDED
2 #define BOOST_LEXICAL_CAST_INCLUDED
4 // MS compatible compilers support #pragma once
6 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
10 // Boost lexical_cast.hpp header -------------------------------------------//
12 // See http://www.boost.org/libs/conversion for documentation.
13 // See end of this header for rights and permissions.
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 and other Boosters
22 // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2012
24 #include <boost/config.hpp>
25 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
26 #define BOOST_LCAST_NO_WCHAR_T
29 #if (defined(__MINGW32__) || defined(__MINGW64__)) && (__GNUC__ == 4) \
30 && ((__GNUC_MINOR__ == 4) || (__GNUC_MINOR__ == 5)) && defined(__STRICT_ANSI__) \
31 && !defined(BOOST_LCAST_NO_WCHAR_T)
33 // workaround for a mingw bug
34 // http://sourceforge.net/tracker/index.php?func=detail&aid=2373234&group_id=2435&atid=102435
36 #if (__GNUC_MINOR__ == 4)
38 _CRTIMP int __cdecl swprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , ...);
39 _CRTIMP int __cdecl vswprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , ...);
42 #if (__GNUC_MINOR__ == 5)
44 _CRTIMP int __cdecl swprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , ...);
45 _CRTIMP int __cdecl vswprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , va_list);
59 #include <boost/limits.hpp>
60 #include <boost/mpl/if.hpp>
61 #include <boost/throw_exception.hpp>
62 #include <boost/type_traits/is_pointer.hpp>
63 #include <boost/type_traits/is_integral.hpp>
64 #include <boost/type_traits/is_arithmetic.hpp>
65 #include <boost/type_traits/remove_pointer.hpp>
66 #include <boost/numeric/conversion/cast.hpp>
67 #include <boost/type_traits/ice.hpp>
68 #include <boost/type_traits/make_unsigned.hpp>
69 #include <boost/type_traits/is_signed.hpp>
70 #include <boost/math/special_functions/sign.hpp>
71 #include <boost/math/special_functions/fpclassify.hpp>
72 #include <boost/static_assert.hpp>
73 #include <boost/detail/lcast_precision.hpp>
74 #include <boost/detail/workaround.hpp>
75 #if !defined(__SUNPRO_CC)
76 #include <boost/container/container_fwd.hpp>
77 #endif // !defined(__SUNPRO_CC)
78 #ifndef BOOST_NO_CWCHAR
82 #ifndef BOOST_NO_STD_LOCALE
85 # ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
86 # warning "Unable to use <locale> header. boost::lexical_cast will use the 'C' locale."
87 # define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
91 #ifdef BOOST_NO_STRINGSTREAM
97 #ifdef BOOST_NO_TYPEID
98 #define BOOST_LCAST_THROW_BAD_CAST(S, T) throw_exception(bad_lexical_cast())
100 #define BOOST_LCAST_THROW_BAD_CAST(Source, Target) \
101 throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)))
106 // exception used to indicate runtime lexical_cast failure
107 class bad_lexical_cast :
108 // workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0
109 #if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
110 public std::exception
115 #if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 )
116 // under bcc32 5.5.1 bad_cast doesn't derive from exception
117 , public std::exception
123 #ifndef BOOST_NO_TYPEID
124 source(&typeid(void)), target(&typeid(void))
126 source(0), target(0) // this breaks getters
132 const std::type_info &source_type_arg,
133 const std::type_info &target_type_arg) :
134 source(&source_type_arg), target(&target_type_arg)
138 const std::type_info &source_type() const
142 const std::type_info &target_type() const
147 virtual const char *what() const throw()
149 return "bad lexical cast: "
150 "source type value could not be interpreted as target";
152 virtual ~bad_lexical_cast() throw()
156 const std::type_info *source;
157 const std::type_info *target;
160 namespace detail // selectors for choosing stream character type
162 template<typename Type>
168 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
169 template<class CharT, class Traits, class Alloc>
170 struct stream_char< std::basic_string<CharT,Traits,Alloc> >
175 #if !defined(__SUNPRO_CC)
176 template<class CharT, class Traits, class Alloc>
177 struct stream_char< ::boost::container::basic_string<CharT,Traits,Alloc> >
181 #endif // !defined(__SUNPRO_CC)
184 #ifndef BOOST_LCAST_NO_WCHAR_T
185 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
187 struct stream_char<wchar_t>
189 typedef wchar_t type;
194 struct stream_char<wchar_t *>
196 typedef wchar_t type;
200 struct stream_char<const wchar_t *>
202 typedef wchar_t type;
205 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
207 struct stream_char<std::wstring>
209 typedef wchar_t type;
215 #ifndef BOOST_NO_CHAR16_T
218 struct stream_char<char16_t>
220 typedef char16_t type;
224 struct stream_char<char16_t *>
226 typedef char16_t type;
230 struct stream_char<const char16_t *>
232 typedef char16_t type;
237 #ifndef BOOST_NO_CHAR32_T
240 struct stream_char<char32_t>
242 typedef char32_t type;
246 struct stream_char<char32_t *>
248 typedef char32_t type;
252 struct stream_char<const char32_t *>
254 typedef char32_t type;
259 template<typename TargetChar, typename SourceChar>
262 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
263 (sizeof(TargetChar) > sizeof(SourceChar))
265 , SourceChar >::type type;
269 namespace detail // deduce_char_traits template
271 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
272 template<class CharT, class Target, class Source>
273 struct deduce_char_traits
275 typedef std::char_traits<CharT> type;
278 template<class CharT, class Traits, class Alloc, class Source>
279 struct deduce_char_traits< CharT
280 , std::basic_string<CharT,Traits,Alloc>
287 template<class CharT, class Target, class Traits, class Alloc>
288 struct deduce_char_traits< CharT
290 , std::basic_string<CharT,Traits,Alloc>
296 #if !defined(__SUNPRO_CC)
297 template<class CharT, class Traits, class Alloc, class Source>
298 struct deduce_char_traits< CharT
299 , ::boost::container::basic_string<CharT,Traits,Alloc>
306 template<class CharT, class Target, class Traits, class Alloc>
307 struct deduce_char_traits< CharT
309 , ::boost::container::basic_string<CharT,Traits,Alloc>
315 template<class CharT, class Traits, class Alloc1, class Alloc2>
316 struct deduce_char_traits< CharT
317 , std::basic_string<CharT,Traits,Alloc1>
318 , std::basic_string<CharT,Traits,Alloc2>
324 template<class CharT, class Traits, class Alloc1, class Alloc2>
325 struct deduce_char_traits< CharT
326 , ::boost::container::basic_string<CharT,Traits,Alloc1>
327 , ::boost::container::basic_string<CharT,Traits,Alloc2>
333 template<class CharT, class Traits, class Alloc1, class Alloc2>
334 struct deduce_char_traits< CharT
335 , ::boost::container::basic_string<CharT,Traits,Alloc1>
336 , std::basic_string<CharT,Traits,Alloc2>
342 template<class CharT, class Traits, class Alloc1, class Alloc2>
343 struct deduce_char_traits< CharT
344 , std::basic_string<CharT,Traits,Alloc1>
345 , ::boost::container::basic_string<CharT,Traits,Alloc2>
350 #endif // !defined(__SUNPRO_CC)
354 namespace detail // lcast_src_length
356 // Return max. length of string representation of Source;
357 template< class Source // Source type of lexical_cast.
359 struct lcast_src_length
361 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
362 // To check coverage, build the test with
363 // bjam --v2 profile optimization=off
364 static void check_coverage() {}
367 // Helper for integral types.
368 // Notes on length calculation:
369 // Max length for 32bit int with grouping "\1" and thousands_sep ',':
370 // "-2,1,4,7,4,8,3,6,4,7"
372 // ^ - 1 digit not counted by digits10
373 // ^^^^^^^^^^^^^^^^^^ - digits10 * 2
375 // Constant is_specialized is used instead of constant 1
376 // to prevent buffer overflow in a rare case when
377 // <boost/limits.hpp> doesn't add missing specialization for
378 // numeric_limits<T> for some integral type T.
379 // When is_specialized is false, the whole expression is 0.
380 template<class Source>
381 struct lcast_src_length_integral
383 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
384 BOOST_STATIC_CONSTANT(std::size_t, value =
385 std::numeric_limits<Source>::is_signed +
386 std::numeric_limits<Source>::is_specialized + /* == 1 */
387 std::numeric_limits<Source>::digits10 * 2
390 BOOST_STATIC_CONSTANT(std::size_t, value = 156);
391 BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256);
394 // TODO: FIX for char16_t, char32_t, we can ignore CharT
395 #define BOOST_LCAST_DEF(T) \
396 template<> struct lcast_src_length<T> \
397 : lcast_src_length_integral<T> \
398 { static void check_coverage() {} };
400 BOOST_LCAST_DEF(short)
401 BOOST_LCAST_DEF(unsigned short)
403 BOOST_LCAST_DEF(unsigned int)
404 BOOST_LCAST_DEF(long)
405 BOOST_LCAST_DEF(unsigned long)
406 #if defined(BOOST_HAS_LONG_LONG)
407 BOOST_LCAST_DEF(boost::ulong_long_type)
408 BOOST_LCAST_DEF(boost::long_long_type )
409 #elif defined(BOOST_HAS_MS_INT64)
410 BOOST_LCAST_DEF(unsigned __int64)
411 BOOST_LCAST_DEF( __int64)
414 #undef BOOST_LCAST_DEF
416 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
417 // Helper for floating point types.
418 // -1.23456789e-123456
422 // ^^^^^^^^ lcast_precision<Source>::value
425 // ^^^^^^ exponent (assumed 6 or less digits)
426 // sign + leading digit + decimal point + "e" + exponent sign == 5
427 template<class Source>
428 struct lcast_src_length_floating
431 std::numeric_limits<Source>::max_exponent10 <= 999999L &&
432 std::numeric_limits<Source>::min_exponent10 >= -999999L
434 BOOST_STATIC_CONSTANT(std::size_t, value =
435 5 + lcast_precision<Source>::value + 6
440 struct lcast_src_length<float>
441 : lcast_src_length_floating<float>
443 static void check_coverage() {}
447 struct lcast_src_length<double>
448 : lcast_src_length_floating<double>
450 static void check_coverage() {}
454 struct lcast_src_length<long double>
455 : lcast_src_length_floating<long double>
457 static void check_coverage() {}
460 #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
463 namespace detail // '0', '+' and '-' constants
465 template<typename CharT> struct lcast_char_constants;
468 struct lcast_char_constants<char>
470 BOOST_STATIC_CONSTANT(char, zero = '0');
471 BOOST_STATIC_CONSTANT(char, minus = '-');
472 BOOST_STATIC_CONSTANT(char, plus = '+');
473 BOOST_STATIC_CONSTANT(char, lowercase_e = 'e');
474 BOOST_STATIC_CONSTANT(char, capital_e = 'E');
475 BOOST_STATIC_CONSTANT(char, c_decimal_separator = '.');
478 #ifndef BOOST_LCAST_NO_WCHAR_T
480 struct lcast_char_constants<wchar_t>
482 BOOST_STATIC_CONSTANT(wchar_t, zero = L'0');
483 BOOST_STATIC_CONSTANT(wchar_t, minus = L'-');
484 BOOST_STATIC_CONSTANT(wchar_t, plus = L'+');
485 BOOST_STATIC_CONSTANT(wchar_t, lowercase_e = L'e');
486 BOOST_STATIC_CONSTANT(wchar_t, capital_e = L'E');
487 BOOST_STATIC_CONSTANT(wchar_t, c_decimal_separator = L'.');
491 #ifndef BOOST_NO_CHAR16_T
493 struct lcast_char_constants<char16_t>
495 BOOST_STATIC_CONSTANT(char16_t, zero = u'0');
496 BOOST_STATIC_CONSTANT(char16_t, minus = u'-');
497 BOOST_STATIC_CONSTANT(char16_t, plus = u'+');
498 BOOST_STATIC_CONSTANT(char16_t, lowercase_e = u'e');
499 BOOST_STATIC_CONSTANT(char16_t, capital_e = u'E');
500 BOOST_STATIC_CONSTANT(char16_t, c_decimal_separator = u'.');
504 #ifndef BOOST_NO_CHAR32_T
506 struct lcast_char_constants<char32_t>
508 BOOST_STATIC_CONSTANT(char32_t, zero = U'0');
509 BOOST_STATIC_CONSTANT(char32_t, minus = U'-');
510 BOOST_STATIC_CONSTANT(char32_t, plus = U'+');
511 BOOST_STATIC_CONSTANT(char32_t, lowercase_e = U'e');
512 BOOST_STATIC_CONSTANT(char32_t, capital_e = U'E');
513 BOOST_STATIC_CONSTANT(char32_t, c_decimal_separator = U'.');
518 namespace detail // lcast_to_unsigned
520 #if (defined _MSC_VER)
521 # pragma warning( push )
522 // C4146: unary minus operator applied to unsigned type, result still unsigned
523 # pragma warning( disable : 4146 )
524 #elif defined( __BORLANDC__ )
525 # pragma option push -w-8041
529 BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value)
531 typedef BOOST_DEDUCED_TYPENAME make_unsigned<T>::type result_type;
532 result_type uvalue = static_cast<result_type>(value);
533 return value < 0 ? -uvalue : uvalue;
535 #if (defined _MSC_VER)
536 # pragma warning( pop )
537 #elif defined( __BORLANDC__ )
542 namespace detail // lcast_put_unsigned
544 template<class Traits, class T, class CharT>
545 CharT* lcast_put_unsigned(const T n_param, CharT* finish)
547 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
548 BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
551 typedef typename Traits::int_type int_type;
552 CharT const czero = lcast_char_constants<CharT>::zero;
553 int_type const zero = Traits::to_int_type(czero);
554 BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
555 (sizeof(int_type) > sizeof(T))
560 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
562 if (loc != std::locale::classic()) {
563 typedef std::numpunct<CharT> numpunct;
564 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
565 std::string const grouping = np.grouping();
566 std::string::size_type const grouping_size = grouping.size();
568 if ( grouping_size && grouping[0] > 0 )
571 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
572 // Check that ulimited group is unreachable:
573 BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
575 CharT thousands_sep = np.thousands_sep();
576 std::string::size_type group = 0; // current group number
577 char last_grp_size = grouping[0];
578 char left = last_grp_size;
585 if(group < grouping_size)
587 char const grp_size = grouping[group];
588 last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size;
591 left = last_grp_size;
593 Traits::assign(*finish, thousands_sep);
599 int_type const digit = static_cast<int_type>(n % 10U);
600 Traits::assign(*finish, Traits::to_char_type(zero + digit));
611 int_type const digit = static_cast<int_type>(n % 10U);
612 Traits::assign(*finish, Traits::to_char_type(zero + digit));
621 namespace detail // lcast_ret_unsigned
623 template<class Traits, class T, class CharT>
624 inline bool lcast_ret_unsigned(T& value, const CharT* const begin, const CharT* end)
626 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
627 BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
629 typedef typename Traits::int_type int_type;
630 CharT const czero = lcast_char_constants<CharT>::zero;
634 if (begin > end || *end < czero || *end >= czero + 10)
636 value = *end - czero;
639 bool multiplier_overflowed = false;
641 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
643 if (loc != std::locale::classic()) {
644 typedef std::numpunct<CharT> numpunct;
645 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
646 std::string const& grouping = np.grouping();
647 std::string::size_type const grouping_size = grouping.size();
649 /* According to Programming languages - C++
650 * we MUST check for correct grouping
652 if (grouping_size && grouping[0] > 0)
654 unsigned char current_grouping = 0;
655 CharT const thousands_sep = np.thousands_sep();
656 char remained = grouping[current_grouping] - 1;
657 bool shall_we_return = true;
659 for(;end>=begin; --end)
662 T const multiplier_10 = multiplier * 10;
663 if (multiplier_10 / 10 != multiplier) multiplier_overflowed = true;
665 T const dig_value = *end - czero;
666 T const new_sub_value = multiplier_10 * dig_value;
668 if (*end < czero || *end >= czero + 10
669 /* detecting overflow */
670 || (dig_value && new_sub_value / dig_value != multiplier_10)
671 || static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
672 || (multiplier_overflowed && dig_value)
676 value += new_sub_value;
680 if ( !Traits::eq(*end, thousands_sep) ) //|| begin == end ) return false;
683 * According to Programming languages - C++
684 * Digit grouping is checked. That is, the positions of discarded
685 * separators is examined for consistency with
686 * use_facet<numpunct<charT> >(loc ).grouping()
688 * BUT what if there is no separators at all and grouping()
689 * is not empty? Well, we have no extraced separators, so we
690 * won`t check them for consistency. This will allow us to
691 * work with "C" locale from other locales
693 shall_we_return = false;
696 if ( begin == end ) return false;
697 if (current_grouping < grouping_size-1 ) ++current_grouping;
698 remained = grouping[current_grouping];
703 if (shall_we_return) return true;
708 while ( begin <= end )
710 T const multiplier_10 = multiplier * 10;
711 if (multiplier_10 / 10 != multiplier) multiplier_overflowed = true;
713 T const dig_value = *end - czero;
714 T const new_sub_value = multiplier_10 * dig_value;
716 if (*end < czero || *end >= czero + 10
717 /* detecting overflow */
718 || (dig_value && new_sub_value / dig_value != multiplier_10)
719 || static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
720 || (multiplier_overflowed && dig_value)
724 value += new_sub_value;
735 /* Returns true and sets the correct value if found NaN or Inf. */
736 template <class CharT, class T>
737 inline bool parse_inf_nan_impl(const CharT* begin, const CharT* end, T& value
738 , const CharT* lc_NAN, const CharT* lc_nan
739 , const CharT* lc_INFINITY, const CharT* lc_infinity
740 , const CharT opening_brace, const CharT closing_brace)
743 if (begin == end) return false;
744 const CharT minus = lcast_char_constants<CharT>::minus;
745 const CharT plus = lcast_char_constants<CharT>::plus;
746 const int inifinity_size = 8;
748 bool has_minus = false;
755 else if( *begin == plus ) ++begin;
757 if( end-begin < 3 ) return false;
758 if( !memcmp(begin, lc_nan, 3*sizeof(CharT)) || !memcmp(begin, lc_NAN, 3*sizeof(CharT)) )
761 if (end != begin) /* It is 'nan(...)' or some bad input*/
763 if(end-begin<2) return false; // bad input
765 if( *begin != opening_brace || *end != closing_brace) return false; // bad input
768 if( !has_minus ) value = std::numeric_limits<T>::quiet_NaN();
769 else value = (boost::math::changesign) (std::numeric_limits<T>::quiet_NaN());
772 if (( /* 'INF' or 'inf' */
775 (!memcmp(begin, lc_infinity, 3*sizeof(CharT)) || !memcmp(begin, lc_INFINITY, 3*sizeof(CharT)))
778 ( /* 'INFINITY' or 'infinity' */
779 end-begin==inifinity_size
781 (!memcmp(begin, lc_infinity, inifinity_size)|| !memcmp(begin, lc_INFINITY, inifinity_size))
785 if( !has_minus ) value = std::numeric_limits<T>::infinity();
786 else value = (boost::math::changesign) (std::numeric_limits<T>::infinity());
793 #ifndef BOOST_LCAST_NO_WCHAR_T
795 bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value)
797 return parse_inf_nan_impl(begin, end, value
799 , L"INFINITY", L"infinity"
803 #ifndef BOOST_NO_CHAR16_T
805 bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value)
807 return parse_inf_nan_impl(begin, end, value
809 , u"INFINITY", u"infinity"
813 #ifndef BOOST_NO_CHAR32_T
815 bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value)
817 return parse_inf_nan_impl(begin, end, value
819 , U"INFINITY", U"infinity"
824 template <class CharT, class T>
825 bool parse_inf_nan(const CharT* begin, const CharT* end, T& value)
827 return parse_inf_nan_impl(begin, end, value
829 , "INFINITY", "infinity"
832 #ifndef BOOST_LCAST_NO_WCHAR_T
834 bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value)
837 if ( (boost::math::isnan)(value) )
839 if ( (boost::math::signbit)(value) )
841 memcpy(begin,L"-nan", sizeof(L"-nan"));
845 memcpy(begin,L"nan", sizeof(L"nan"));
849 } else if ( (boost::math::isinf)(value) )
851 if ( (boost::math::signbit)(value) )
853 memcpy(begin,L"-inf", sizeof(L"-inf"));
857 memcpy(begin,L"inf", sizeof(L"inf"));
866 template <class CharT, class T>
867 bool put_inf_nan(CharT* begin, CharT*& end, const T& value)
870 if ( (boost::math::isnan)(value) )
872 if ( (boost::math::signbit)(value) )
874 memcpy(begin,"-nan", sizeof("-nan"));
878 memcpy(begin,"nan", sizeof("nan"));
882 } else if ( (boost::math::isinf)(value) )
884 if ( (boost::math::signbit)(value) )
886 memcpy(begin,"-inf", sizeof("-inf"));
890 memcpy(begin,"inf", sizeof("inf"));
902 namespace detail // lcast_ret_float
905 struct mantissa_holder_type
907 /* Can not be used with this type */
911 struct mantissa_holder_type<float>
913 typedef unsigned int type;
917 struct mantissa_holder_type<double>
919 #if defined(BOOST_HAS_LONG_LONG)
920 typedef boost::ulong_long_type type;
921 #elif defined(BOOST_HAS_MS_INT64)
922 typedef unsigned __int64 type;
926 template<class Traits, class T, class CharT>
927 inline bool lcast_ret_float(T& value, const CharT* begin, const CharT* end)
930 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
932 typedef std::numpunct<CharT> numpunct;
933 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
934 std::string const grouping(
935 (loc == std::locale::classic())
939 std::string::size_type const grouping_size = grouping.size();
940 CharT const thousands_sep = grouping_size ? np.thousands_sep() : 0;
941 CharT const decimal_point = np.decimal_point();
942 bool found_grouping = false;
943 std::string::size_type last_grouping_pos = grouping_size - 1;
945 CharT const decimal_point = lcast_char_constants<CharT>::c_decimal_separator;
948 CharT const czero = lcast_char_constants<CharT>::zero;
949 CharT const minus = lcast_char_constants<CharT>::minus;
950 CharT const plus = lcast_char_constants<CharT>::plus;
951 CharT const capital_e = lcast_char_constants<CharT>::capital_e;
952 CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
956 if (parse_inf_nan(begin, end, value)) return true;
958 typedef typename Traits::int_type int_type;
959 typedef BOOST_DEDUCED_TYPENAME mantissa_holder_type<T>::type mantissa_type;
960 int_type const zero = Traits::to_int_type(czero);
961 if (begin == end) return false;
963 /* Getting the plus/minus sign */
964 bool has_minus = false;
965 if ( *begin == minus ) {
968 if (begin == end) return false;
969 } else if ( *begin == plus ) {
971 if (begin == end) return false;
974 bool found_decimal = false;
975 bool found_number_before_exp = false;
977 mantissa_type mantissa=0;
978 bool is_mantissa_full = false;
980 char length_since_last_delim = 0;
982 while ( begin != end )
985 /* We allow no thousand_separators after decimal point */
987 mantissa_type tmp_mantissa = mantissa * 10u;
988 if ( *begin == lowercase_e || *begin == capital_e ) break;
989 if ( *begin < czero || *begin >= czero + 10 ) return false;
990 if ( is_mantissa_full
991 || tmp_mantissa / 10u != mantissa
992 || (std::numeric_limits<mantissa_type>::max)()-(*begin - zero) < tmp_mantissa
994 is_mantissa_full = true;
1000 mantissa = tmp_mantissa;
1001 mantissa += *begin - zero;
1003 found_number_before_exp = true;
1006 if (*begin >= czero && *begin < czero + 10) {
1008 /* Checking for mantissa overflow. If overflow will
1009 * occur, them we only increase multiplyer
1011 mantissa_type tmp_mantissa = mantissa * 10u;
1012 if( !is_mantissa_full
1013 && tmp_mantissa / 10u == mantissa
1014 && (std::numeric_limits<mantissa_type>::max)()-(*begin - zero) >= tmp_mantissa
1017 mantissa = tmp_mantissa;
1018 mantissa += *begin - zero;
1021 is_mantissa_full = true;
1025 found_number_before_exp = true;
1026 ++ length_since_last_delim;
1027 } else if ( *begin == decimal_point || *begin == lowercase_e || *begin == capital_e) {
1028 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
1029 /* If ( we need to check grouping
1030 * and ( grouping missmatches
1031 * or grouping position is incorrect
1032 * or we are using the grouping position 0 twice
1034 * ) then return error
1036 if( grouping_size && found_grouping
1038 length_since_last_delim != grouping[0]
1039 || last_grouping_pos>1
1040 || (last_grouping_pos==0 && grouping_size>1)
1045 if(*begin == decimal_point){
1047 found_decimal = true;
1050 if (!found_number_before_exp) return false;
1054 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
1055 else if (grouping_size && *begin == thousands_sep){
1058 /* It is not he first time, when we find thousands separator,
1059 * so we need to chek, is the distance between two groupings
1060 * equal to grouping[last_grouping_pos] */
1062 if (length_since_last_delim != grouping[last_grouping_pos] )
1064 if (!last_grouping_pos) return false;
1067 -- last_grouping_pos;
1068 if (length_since_last_delim != grouping[last_grouping_pos]) return false;
1071 /* We are calling the grouping[0] twice, when grouping size is more than 1 */
1072 if (grouping_size>1u && last_grouping_pos+1<grouping_size) return false;
1075 /* Delimiter at the begining ',000' */
1076 if (!length_since_last_delim) return false;
1078 found_grouping = true;
1079 if (length_since_last_delim > grouping[last_grouping_pos] ) return false;
1082 length_since_last_delim = 0;
1085 /* Delimiter at the end '100,' */
1086 if (begin == end) return false;
1097 if ( begin != end && ( *begin == lowercase_e || *begin == capital_e ) ) {
1099 if ( begin == end ) return false;
1101 bool exp_has_minus = false;
1102 if( *begin == minus ) {
1103 exp_has_minus = true;
1105 if ( begin == end ) return false;
1106 } else if (*begin == plus ) {
1108 if ( begin == end ) return false;
1111 int exp_pow_of_10 = 0;
1112 while ( begin != end )
1115 || *begin >= czero + 10
1116 || exp_pow_of_10 * 10 < exp_pow_of_10) /* Overflows are checked lower more precisely*/
1119 exp_pow_of_10 *= 10;
1120 exp_pow_of_10 += *begin - zero;
1124 if ( exp_pow_of_10 ) {
1125 /* Overflows are checked lower */
1126 if ( exp_has_minus ) {
1127 pow_of_10 -= exp_pow_of_10;
1129 pow_of_10 += exp_pow_of_10;
1134 /* We need a more accurate algorithm... We can not use current algorithm
1135 * with long doubles (and with doubles if sizeof(double)==sizeof(long double)).
1137 long double result = std::pow(10.0L, pow_of_10) * mantissa;
1138 value = static_cast<T>( has_minus ? (boost::math::changesign)(result) : result);
1140 if ( (boost::math::isinf)(value) || (boost::math::isnan)(value) ) return false;
1146 namespace detail // stl_buf_unlocker
1148 template< class BufferType, class CharT >
1149 class stl_buf_unlocker: public BufferType{
1151 typedef BufferType base_class;
1152 #ifndef BOOST_NO_USING_TEMPLATE
1153 using base_class::pptr;
1154 using base_class::pbase;
1155 using base_class::setg;
1156 using base_class::setp;
1158 CharT* pptr() const { return base_class::pptr(); }
1159 CharT* pbase() const { return base_class::pbase(); }
1160 void setg(CharT* gbeg, CharT* gnext, CharT* gend){ return base_class::setg(gbeg, gnext, gend); }
1161 void setp(CharT* pbeg, CharT* pend) { return setp(pbeg, pend); }
1168 struct do_not_construct_stringbuffer_t{};
1171 namespace detail // optimized stream wrapper
1173 // String representation of Source has an upper limit.
1174 template< class CharT // a result of widest_char transformation
1175 , class Traits // usually char_traits<CharT>
1176 , bool RequiresStringbuffer
1178 class lexical_stream_limited_src
1180 typedef stl_buf_unlocker<std::basic_streambuf<CharT, Traits>, CharT > local_streambuffer_t;
1182 #if defined(BOOST_NO_STRINGSTREAM)
1183 typedef stl_buf_unlocker<std::strstream, CharT > local_stringbuffer_t;
1184 #elif defined(BOOST_NO_STD_LOCALE)
1185 typedef stl_buf_unlocker<std::stringstream, CharT > local_stringbuffer_t;
1187 typedef stl_buf_unlocker<std::basic_stringbuf<CharT, Traits>, CharT > local_stringbuffer_t;
1189 typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
1190 RequiresStringbuffer,
1191 local_stringbuffer_t,
1192 do_not_construct_stringbuffer_t
1193 >::type deduced_stringbuffer_t;
1195 // A string representation of Source is written to [start, finish).
1198 deduced_stringbuffer_t stringbuffer;
1201 lexical_stream_limited_src(CharT* sta, CharT* fin)
1208 lexical_stream_limited_src(lexical_stream_limited_src const&);
1209 void operator=(lexical_stream_limited_src const&);
1211 /************************************ HELPER FUNCTIONS FOR OPERATORS << ( ... ) ********************************/
1212 bool shl_char(CharT ch)
1214 Traits::assign(*start, ch);
1219 #ifndef BOOST_LCAST_NO_WCHAR_T
1223 BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)) ,
1224 "boost::lexical_cast does not support conversions from whar_t to char types."
1225 "Use boost::locale instead" );
1226 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
1228 wchar_t w = BOOST_USE_FACET(std::ctype<wchar_t>, loc).widen(ch);
1232 Traits::assign(*start, w);
1238 bool shl_char_array(CharT const* str)
1240 start = const_cast<CharT*>(str);
1241 finish = start + Traits::length(str);
1245 #ifndef BOOST_LCAST_NO_WCHAR_T
1247 bool shl_char_array(T const* str)
1249 BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)),
1250 "boost::lexical_cast does not support conversions from wchar_t to char types."
1251 "Use boost::locale instead" );
1252 return shl_input_streamable(str);
1256 template<typename InputStreamable>
1257 bool shl_input_streamable(InputStreamable& input)
1259 std::basic_ostream<CharT> stream(&stringbuffer);
1260 bool const result = !(stream << input).fail();
1261 start = stringbuffer.pbase();
1262 finish = stringbuffer.pptr();
1267 inline bool shl_signed(T n)
1269 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
1273 CharT const minus = lcast_char_constants<CharT>::minus;
1274 Traits::assign(*start, minus);
1279 #if (defined _MSC_VER)
1280 # pragma warning( push )
1281 // C4996: This function or variable may be unsafe. Consider using sprintf_s instead
1282 # pragma warning( disable : 4996 )
1286 bool shl_float(float val,T* out)
1287 { using namespace std;
1288 if (put_inf_nan(start,finish,val)) return true;
1289 const double val_as_double = val;
1290 finish = start + sprintf(out,"%.*g", static_cast<int>(boost::detail::lcast_get_precision<float >()), val_as_double );
1291 return finish > start;
1295 bool shl_double(double val,T* out)
1296 { using namespace std;
1297 if (put_inf_nan(start,finish,val)) return true;
1298 finish = start + sprintf(out,"%.*g", static_cast<int>(boost::detail::lcast_get_precision<double >()), val );
1299 return finish > start;
1303 bool shl_long_double(long double val,T* out)
1304 { using namespace std;
1305 if (put_inf_nan(start,finish,val)) return true;
1306 finish = start + sprintf(out,"%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double >()), val );
1307 return finish > start;
1311 #if (defined _MSC_VER)
1312 # pragma warning( pop )
1316 #ifndef BOOST_LCAST_NO_WCHAR_T
1317 bool shl_float(float val,wchar_t* out)
1318 { using namespace std;
1319 if (put_inf_nan(start,finish,val)) return true;
1320 finish = start + swprintf(out,
1321 #if !defined(__MINGW32__) && !defined(UNDER_CE)
1324 L"%.*g", static_cast<int>(boost::detail::lcast_get_precision<float >()), val );
1326 return finish > start;
1330 bool shl_double(double val,wchar_t* out)
1331 { using namespace std;
1332 if (put_inf_nan(start,finish,val)) return true;
1333 /* __MINGW32__ is defined for both mingw.org and for mingw-w64.
1334 * For mingw-w64, __MINGW64__ is defined, too, when targetting
1337 * swprintf realization in MinGW and under WinCE does not conform
1341 finish = start + swprintf(out,
1342 #if !defined(__MINGW32__) && !defined(UNDER_CE)
1345 L"%.*lg", static_cast<int>(boost::detail::lcast_get_precision<double >()), val );
1346 return finish > start;
1350 bool shl_long_double(long double val,wchar_t* out)
1351 { using namespace std;
1352 if (put_inf_nan(start,finish,val)) return true;
1353 finish = start + swprintf(out,
1354 #if !defined(UNDER_CE)
1357 L"%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double >()), val );
1358 return finish > start;
1364 /************************************ OPERATORS << ( ... ) ********************************/
1366 template<class Alloc>
1367 bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str)
1369 start = const_cast<CharT*>(str.data());
1370 finish = start + str.length();
1374 #if !defined(__SUNPRO_CC)
1375 template<class Alloc>
1376 bool operator<<(::boost::container::basic_string<CharT,Traits,Alloc> const& str)
1378 start = const_cast<CharT*>(str.data());
1379 finish = start + str.length();
1382 #endif // !defined(__SUNPRO_CC)
1383 bool operator<<(bool value)
1385 CharT const czero = lcast_char_constants<CharT>::zero;
1386 Traits::assign(*start, Traits::to_char_type(czero + value));
1391 bool operator<<(char ch) { return shl_char(ch); }
1392 bool operator<<(unsigned char ch) { return ((*this) << static_cast<char>(ch)); }
1393 bool operator<<(signed char ch) { return ((*this) << static_cast<char>(ch)); }
1394 #if !defined(BOOST_LCAST_NO_WCHAR_T)
1395 bool operator<<(wchar_t const* str) { return shl_char_array(str); }
1396 bool operator<<(wchar_t * str) { return shl_char_array(str); }
1397 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
1398 bool operator<<(wchar_t ch) { return shl_char(ch); }
1401 bool operator<<(unsigned char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); }
1402 bool operator<<(unsigned char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); }
1403 bool operator<<(signed char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); }
1404 bool operator<<(signed char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); }
1405 bool operator<<(char const* str) { return shl_char_array(str); }
1406 bool operator<<(char* str) { return shl_char_array(str); }
1407 bool operator<<(short n) { return shl_signed(n); }
1408 bool operator<<(int n) { return shl_signed(n); }
1409 bool operator<<(long n) { return shl_signed(n); }
1410 bool operator<<(unsigned short n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1411 bool operator<<(unsigned int n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1412 bool operator<<(unsigned long n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1414 #if defined(BOOST_HAS_LONG_LONG)
1415 bool operator<<(boost::ulong_long_type n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1416 bool operator<<(boost::long_long_type n) { return shl_signed(n); }
1417 #elif defined(BOOST_HAS_MS_INT64)
1418 bool operator<<(unsigned __int64 n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1419 bool operator<<( __int64 n) { return shl_signed(n); }
1421 bool operator<<(float val) { return shl_float(val,start); }
1422 bool operator<<(double val) { return shl_double(val,start); }
1423 bool operator<<(long double val) {
1425 return shl_long_double(val,start);
1427 return shl_double(val,start);
1431 template<class InStreamable>
1432 bool operator<<(const InStreamable& input) { return shl_input_streamable(input); }
1434 /************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/
1437 template <typename Type>
1438 bool shr_unsigned(Type& output)
1440 if (start == finish) return false;
1441 CharT const minus = lcast_char_constants<CharT>::minus;
1442 CharT const plus = lcast_char_constants<CharT>::plus;
1443 bool has_minus = false;
1445 /* We won`t use `start' any more, so no need in decrementing it after */
1446 if ( Traits::eq(minus,*start) )
1450 } else if ( Traits::eq( plus, *start ) )
1455 bool const succeed = lcast_ret_unsigned<Traits>(output, start, finish);
1456 #if (defined _MSC_VER)
1457 # pragma warning( push )
1458 // C4146: unary minus operator applied to unsigned type, result still unsigned
1459 # pragma warning( disable : 4146 )
1460 #elif defined( __BORLANDC__ )
1461 # pragma option push -w-8041
1463 if (has_minus) output = static_cast<Type>(-output);
1464 #if (defined _MSC_VER)
1465 # pragma warning( pop )
1466 #elif defined( __BORLANDC__ )
1472 template <typename Type>
1473 bool shr_signed(Type& output)
1475 if (start == finish) return false;
1476 CharT const minus = lcast_char_constants<CharT>::minus;
1477 CharT const plus = lcast_char_constants<CharT>::plus;
1478 typedef BOOST_DEDUCED_TYPENAME make_unsigned<Type>::type utype;
1480 bool has_minus = false;
1482 /* We won`t use `start' any more, so no need in decrementing it after */
1483 if ( Traits::eq(minus,*start) )
1487 } else if ( Traits::eq(plus, *start) )
1492 bool succeed = lcast_ret_unsigned<Traits>(out_tmp, start, finish);
1494 #if (defined _MSC_VER)
1495 # pragma warning( push )
1496 // C4146: unary minus operator applied to unsigned type, result still unsigned
1497 # pragma warning( disable : 4146 )
1498 #elif defined( __BORLANDC__ )
1499 # pragma option push -w-8041
1501 utype const comp_val = static_cast<utype>(-(std::numeric_limits<Type>::min)());
1502 succeed = succeed && out_tmp<=comp_val;
1504 #if (defined _MSC_VER)
1505 # pragma warning( pop )
1506 #elif defined( __BORLANDC__ )
1510 utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)());
1511 succeed = succeed && out_tmp<=comp_val;
1517 template<typename InputStreamable>
1518 bool shr_using_base_class(InputStreamable& output)
1520 #if (defined _MSC_VER)
1521 # pragma warning( push )
1522 // conditional expression is constant
1523 # pragma warning( disable : 4127 )
1525 if(is_pointer<InputStreamable>::value)
1528 local_streambuffer_t bb;
1529 bb.setg(start, start, finish);
1530 std::basic_istream<CharT> stream(&bb);
1531 stream.unsetf(std::ios::skipws);
1532 lcast_set_precision(stream, static_cast<InputStreamable*>(0));
1533 #if (defined _MSC_VER)
1534 # pragma warning( pop )
1536 return stream >> output &&
1538 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
1539 // GCC 2.9x lacks std::char_traits<>::eof().
1540 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
1541 // configurations, which do provide std::char_traits<>::eof().
1550 inline bool shr_xchar(T& output)
1552 BOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ),
1553 "boost::lexical_cast does not support conversions from whar_t to char types."
1554 "Use boost::locale instead" );
1555 bool const ok = (finish - start == 1);
1558 Traits::assign(out, *start);
1559 output = static_cast<T>(out);
1564 /************************************ OPERATORS >> ( ... ) ********************************/
1566 bool operator>>(unsigned short& output) { return shr_unsigned(output); }
1567 bool operator>>(unsigned int& output) { return shr_unsigned(output); }
1568 bool operator>>(unsigned long int& output) { return shr_unsigned(output); }
1569 bool operator>>(short& output) { return shr_signed(output); }
1570 bool operator>>(int& output) { return shr_signed(output); }
1571 bool operator>>(long int& output) { return shr_signed(output); }
1572 #if defined(BOOST_HAS_LONG_LONG)
1573 bool operator>>(boost::ulong_long_type& output) { return shr_unsigned(output); }
1574 bool operator>>(boost::long_long_type& output) { return shr_signed(output); }
1575 #elif defined(BOOST_HAS_MS_INT64)
1576 bool operator>>(unsigned __int64& output) { return shr_unsigned(output); }
1577 bool operator>>(__int64& output) { return shr_signed(output); }
1579 bool operator>>(char& output) { return shr_xchar(output); }
1580 bool operator>>(unsigned char& output) { return shr_xchar(output); }
1581 bool operator>>(signed char& output) { return shr_xchar(output); }
1582 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
1583 bool operator>>(wchar_t& output) { return shr_xchar(output); }
1585 #ifndef BOOST_NO_CHAR16_T
1586 bool operator>>(char16_t& output) { return shr_xchar(output); }
1588 #ifndef BOOST_NO_CHAR32_T
1589 bool operator>>(char32_t& output) { return shr_xchar(output); }
1591 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1592 bool operator>>(std::string& str) { str.assign(start, finish); return true; }
1593 # ifndef BOOST_LCAST_NO_WCHAR_T
1594 bool operator>>(std::wstring& str) { str.assign(start, finish); return true; }
1597 template<class Alloc>
1598 bool operator>>(std::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
1599 #if !defined(__SUNPRO_CC)
1600 template<class Alloc>
1601 bool operator>>(::boost::container::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
1602 #endif // !defined(__SUNPRO_CC)
1605 * case "-0" || "0" || "+0" : output = false; return true;
1606 * case "1" || "+1": output = true; return true;
1607 * default: return false;
1609 bool operator>>(bool& output)
1611 CharT const zero = lcast_char_constants<CharT>::zero;
1612 CharT const plus = lcast_char_constants<CharT>::plus;
1613 CharT const minus = lcast_char_constants<CharT>::minus;
1615 switch(finish-start)
1618 output = Traits::eq(start[0], zero+1);
1619 return output || Traits::eq(start[0], zero );
1621 if ( Traits::eq( plus, *start) )
1624 output = Traits::eq(start[0], zero +1);
1625 return output || Traits::eq(start[0], zero );
1629 return Traits::eq( minus, *start)
1630 && Traits::eq( zero, start[1]);
1633 output = false; // Suppress warning about uninitalized variable
1638 bool operator>>(float& output) { return lcast_ret_float<Traits>(output,start,finish); }
1641 // Not optimised converter
1643 bool float_types_converter_internal(T& output, int /*tag*/) {
1644 if (parse_inf_nan(start, finish, output)) return true;
1645 bool return_value = shr_using_base_class(output);
1647 /* Some compilers and libraries successfully
1648 * parse 'inf', 'INFINITY', '1.0E', '1.0E-'...
1649 * We are trying to provide a unified behaviour,
1650 * so we just forbid such conversions (as some
1651 * of the most popular compilers/libraries do)
1653 CharT const minus = lcast_char_constants<CharT>::minus;
1654 CharT const plus = lcast_char_constants<CharT>::plus;
1655 CharT const capital_e = lcast_char_constants<CharT>::capital_e;
1656 CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
1657 if ( return_value &&
1659 *(finish-1) == lowercase_e // 1.0e
1660 || *(finish-1) == capital_e // 1.0E
1661 || *(finish-1) == minus // 1.0e- or 1.0E-
1662 || *(finish-1) == plus // 1.0e+ or 1.0E+
1666 return return_value;
1669 // Optimised converter
1670 bool float_types_converter_internal(double& output,char /*tag*/) {
1671 return lcast_ret_float<Traits>(output,start,finish);
1675 bool operator>>(double& output)
1678 * Some compilers implement long double as double. In that case these types have
1679 * same size, same precision, same max and min values... And it means,
1680 * that current implementation of lcast_ret_float cannot be used for type
1681 * double, because it will give a big precision loss.
1684 #if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)
1685 ::boost::type_traits::ice_eq< sizeof(double), sizeof(long double) >::value,
1693 return float_types_converter_internal(output, tag);
1696 bool operator>>(long double& output)
1699 return float_types_converter_internal(output, tag);
1702 // Generic istream-based algorithm.
1703 // lcast_streambuf_for_target<InputStreamable>::value is true.
1704 template<typename InputStreamable>
1705 bool operator>>(InputStreamable& output) { return shr_using_base_class(output); }
1709 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1711 // call-by-const reference version
1716 struct array_to_pointer_decay
1721 template<class T, std::size_t N>
1722 struct array_to_pointer_decay<T[N]>
1724 typedef const T * type;
1727 template<typename T>
1730 BOOST_STATIC_CONSTANT(bool, value = false );
1733 template<typename CharT, typename Traits, typename Alloc>
1734 struct is_stdstring< std::basic_string<CharT, Traits, Alloc> >
1736 BOOST_STATIC_CONSTANT(bool, value = true );
1738 #if !defined(__SUNPRO_CC)
1739 template<typename CharT, typename Traits, typename Alloc>
1740 struct is_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc> >
1742 BOOST_STATIC_CONSTANT(bool, value = true );
1744 #endif // !defined(__SUNPRO_CC)
1745 template<typename T>
1746 struct is_char_or_wchar
1749 #ifndef BOOST_LCAST_NO_WCHAR_T
1750 typedef wchar_t wchar_t_if_supported;
1752 typedef char wchar_t_if_supported;
1755 #ifndef BOOST_NO_CHAR16_T
1756 typedef char16_t char16_t_if_supported;
1758 typedef char char16_t_if_supported;
1761 #ifndef BOOST_NO_CHAR32_T
1762 typedef char32_t char32_t_if_supported;
1764 typedef char char32_t_if_supported;
1768 BOOST_STATIC_CONSTANT(bool, value =
1770 ::boost::type_traits::ice_or<
1771 is_same< T, char >::value,
1772 is_same< T, wchar_t_if_supported >::value,
1773 is_same< T, char16_t_if_supported >::value,
1774 is_same< T, char32_t_if_supported >::value,
1775 is_same< T, unsigned char >::value,
1776 is_same< T, signed char >::value
1782 template<typename Target, typename Source>
1783 struct is_arithmetic_and_not_xchars
1785 BOOST_STATIC_CONSTANT(bool, value =
1787 ::boost::type_traits::ice_and<
1788 is_arithmetic<Source>::value,
1789 is_arithmetic<Target>::value,
1790 ::boost::type_traits::ice_not<
1791 detail::is_char_or_wchar<Target>::value
1793 ::boost::type_traits::ice_not<
1794 detail::is_char_or_wchar<Source>::value
1802 * is_xchar_to_xchar<Target, Source>::value is true, when
1803 * Target and Souce are the same char types, or when
1804 * Target and Souce are char types of the same size.
1806 template<typename Target, typename Source>
1807 struct is_xchar_to_xchar
1809 BOOST_STATIC_CONSTANT(bool, value =
1811 ::boost::type_traits::ice_or<
1812 ::boost::type_traits::ice_and<
1813 is_same<Source,Target>::value,
1814 is_char_or_wchar<Target>::value
1816 ::boost::type_traits::ice_and<
1817 ::boost::type_traits::ice_eq< sizeof(char),sizeof(Target)>::value,
1818 ::boost::type_traits::ice_eq< sizeof(char),sizeof(Source)>::value,
1819 is_char_or_wchar<Target>::value,
1820 is_char_or_wchar<Source>::value
1827 template<typename Target, typename Source>
1828 struct is_char_array_to_stdstring
1830 BOOST_STATIC_CONSTANT(bool, value = false );
1833 template<typename CharT, typename Traits, typename Alloc>
1834 struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, CharT* >
1836 BOOST_STATIC_CONSTANT(bool, value = true );
1839 template<typename CharT, typename Traits, typename Alloc>
1840 struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, const CharT* >
1842 BOOST_STATIC_CONSTANT(bool, value = true );
1844 #if !defined(__SUNPRO_CC)
1845 template<typename CharT, typename Traits, typename Alloc>
1846 struct is_char_array_to_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc>, CharT* >
1848 BOOST_STATIC_CONSTANT(bool, value = true );
1851 template<typename CharT, typename Traits, typename Alloc>
1852 struct is_char_array_to_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc>, const CharT* >
1854 BOOST_STATIC_CONSTANT(bool, value = true );
1856 #endif // !defined(__SUNPRO_CC)
1858 #if (defined _MSC_VER)
1859 # pragma warning( push )
1860 # pragma warning( disable : 4701 ) // possible use of ... before initialization
1861 # pragma warning( disable : 4702 ) // unreachable code
1862 # pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int'
1864 template<typename Target, typename Source>
1865 struct lexical_cast_do_cast
1867 static inline Target lexical_cast_impl(const Source& arg)
1869 typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay<Source>::type src;
1871 typedef BOOST_DEDUCED_TYPENAME detail::widest_char<
1872 BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type
1873 , BOOST_DEDUCED_TYPENAME detail::stream_char<src>::type
1876 typedef detail::lcast_src_length<src> lcast_src_length;
1877 std::size_t const src_len = lcast_src_length::value;
1878 char_type buf[src_len + 1];
1879 lcast_src_length::check_coverage();
1881 typedef BOOST_DEDUCED_TYPENAME
1882 deduce_char_traits<char_type,Target,Source>::type traits;
1884 typedef BOOST_DEDUCED_TYPENAME remove_pointer<src >::type removed_ptr_t;
1886 // is_char_types_match variable value can be computed via
1887 // sizeof(char_type) == sizeof(removed_ptr_t). But when
1888 // removed_ptr_t is an incomplete type or void*, compilers
1889 // produce warnings or errors.
1890 const bool is_char_types_match =
1891 (::boost::type_traits::ice_or<
1892 ::boost::type_traits::ice_and<
1893 ::boost::type_traits::ice_eq<sizeof(char_type), sizeof(char) >::value,
1894 ::boost::type_traits::ice_or<
1895 ::boost::is_same<char, removed_ptr_t>::value,
1896 ::boost::is_same<unsigned char, removed_ptr_t>::value,
1897 ::boost::is_same<signed char, removed_ptr_t>::value
1900 is_same<char_type, removed_ptr_t>::value
1903 const bool requires_stringbuf =
1905 ::boost::type_traits::ice_or<
1906 is_stdstring<src >::value,
1907 is_arithmetic<src >::value,
1908 ::boost::type_traits::ice_and<
1909 is_pointer<src >::value,
1910 is_char_or_wchar<removed_ptr_t >::value,
1916 detail::lexical_stream_limited_src<char_type,traits, requires_stringbuf >
1917 interpreter(buf, buf + src_len);
1920 // Disabling ADL, by directly specifying operators.
1921 if(!(interpreter.operator <<(arg) && interpreter.operator >>(result)))
1922 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1926 #if (defined _MSC_VER)
1927 # pragma warning( pop )
1930 template<typename Source>
1931 struct lexical_cast_copy
1933 static inline Source lexical_cast_impl(const Source &arg)
1939 class precision_loss_error : public boost::numeric::bad_numeric_cast
1942 virtual const char * what() const throw()
1943 { return "bad numeric conversion: precision loss error"; }
1947 struct throw_on_precision_loss
1949 typedef boost::numeric::Trunc<S> Rounder;
1950 typedef S source_type ;
1952 typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
1954 static source_type nearbyint ( argument_type s )
1956 source_type orig_div_round = s / Rounder::nearbyint(s);
1958 if ( (orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > std::numeric_limits<source_type>::epsilon() )
1959 BOOST_THROW_EXCEPTION( precision_loss_error() );
1963 typedef typename Rounder::round_style round_style;
1966 template<typename Target, typename Source>
1967 struct lexical_cast_dynamic_num_not_ignoring_minus
1969 static inline Target lexical_cast_impl(const Source &arg)
1972 typedef boost::numeric::converter<
1975 boost::numeric::conversion_traits<Target,Source>,
1976 boost::numeric::def_overflow_handler,
1977 throw_on_precision_loss<Source>
1980 return Converter::convert(arg);
1981 } catch( ::boost::numeric::bad_numeric_cast const& ) {
1982 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1984 BOOST_UNREACHABLE_RETURN(static_cast<Target>(0));
1988 template<typename Target, typename Source>
1989 struct lexical_cast_dynamic_num_ignoring_minus
1991 static inline Target lexical_cast_impl(const Source &arg)
1994 typedef boost::numeric::converter<
1997 boost::numeric::conversion_traits<Target,Source>,
1998 boost::numeric::def_overflow_handler,
1999 throw_on_precision_loss<Source>
2002 bool has_minus = ( arg < 0);
2004 return static_cast<Target>(-Converter::convert(-arg));
2006 return Converter::convert(arg);
2008 } catch( ::boost::numeric::bad_numeric_cast const& ) {
2009 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
2011 BOOST_UNREACHABLE_RETURN(static_cast<Target>(0));
2016 * lexical_cast_dynamic_num follows the rules:
2017 * 1) If Source can be converted to Target without precision loss and
2018 * without overflows, then assign Source to Target and return
2020 * 2) If Source is less than 0 and Target is an unsigned integer,
2021 * then negate Source, check the requirements of rule 1) and if
2022 * successful, assign static_casted Source to Target and return
2024 * 3) Otherwise throw a bad_lexical_cast exception
2027 * Rule 2) required because boost::lexical_cast has the behavior of
2028 * stringstream, which uses the rules of scanf for conversions. And
2029 * in the C99 standard for unsigned input value minus sign is
2030 * optional, so if a negative number is read, no errors will arise
2031 * and the result will be the two's complement.
2033 template<typename Target, typename Source>
2034 struct lexical_cast_dynamic_num
2036 static inline Target lexical_cast_impl(const Source &arg)
2038 typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
2039 ::boost::type_traits::ice_and<
2040 ::boost::type_traits::ice_or<
2041 ::boost::is_signed<Source>::value,
2042 ::boost::is_float<Source>::value
2044 ::boost::type_traits::ice_not<
2045 is_same<Source, bool>::value
2047 ::boost::type_traits::ice_not<
2048 is_same<Target, bool>::value
2050 ::boost::is_unsigned<Target>::value
2052 lexical_cast_dynamic_num_ignoring_minus<Target, Source>,
2053 lexical_cast_dynamic_num_not_ignoring_minus<Target, Source>
2054 >::type caster_type;
2056 return caster_type::lexical_cast_impl(arg);
2061 template<typename Target, typename Source>
2062 inline Target lexical_cast(const Source &arg)
2064 typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay<Source>::type src;
2066 typedef BOOST_DEDUCED_TYPENAME ::boost::type_traits::ice_or<
2067 detail::is_xchar_to_xchar<Target, src>::value,
2068 detail::is_char_array_to_stdstring<Target,src>::value,
2069 ::boost::type_traits::ice_and<
2070 is_same<Target, src>::value,
2071 detail::is_stdstring<Target>::value
2075 typedef BOOST_DEDUCED_TYPENAME
2076 detail::is_arithmetic_and_not_xchars<Target, src> do_copy_with_dynamic_check_type;
2078 typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
2079 do_copy_type::value,
2080 detail::lexical_cast_copy<src>,
2081 BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
2082 do_copy_with_dynamic_check_type::value,
2083 detail::lexical_cast_dynamic_num<Target, src>,
2084 detail::lexical_cast_do_cast<Target, src>
2086 >::type caster_type;
2088 return caster_type::lexical_cast_impl(arg);
2093 namespace detail // stream wrapper for handling lexical conversions
2095 template<typename Target, typename Source, typename Traits>
2096 class lexical_stream
2099 typedef typename widest_char<
2100 typename stream_char<Target>::type,
2101 typename stream_char<Source>::type>::type char_type;
2103 typedef Traits traits_type;
2106 lexical_stream(char_type* = 0, char_type* = 0)
2108 stream.unsetf(std::ios::skipws);
2109 lcast_set_precision(stream, static_cast<Source*>(0), static_cast<Target*>(0) );
2113 #if defined(BOOST_NO_STRINGSTREAM)
2114 stream.freeze(false);
2117 bool operator<<(const Source &input)
2119 return !(stream << input).fail();
2121 template<typename InputStreamable>
2122 bool operator>>(InputStreamable &output)
2124 return !is_pointer<InputStreamable>::value &&
2127 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
2128 // GCC 2.9x lacks std::char_traits<>::eof().
2129 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
2130 // configurations, which do provide std::char_traits<>::eof().
2138 bool operator>>(std::string &output)
2140 #if defined(BOOST_NO_STRINGSTREAM)
2143 stream.str().swap(output);
2146 #ifndef BOOST_LCAST_NO_WCHAR_T
2147 bool operator>>(std::wstring &output)
2149 stream.str().swap(output);
2155 #if defined(BOOST_NO_STRINGSTREAM)
2156 std::strstream stream;
2157 #elif defined(BOOST_NO_STD_LOCALE)
2158 std::stringstream stream;
2160 std::basic_stringstream<char_type,traits_type> stream;
2165 // call-by-value fallback version (deprecated)
2167 template<typename Target, typename Source>
2168 Target lexical_cast(Source arg)
2170 typedef typename detail::widest_char<
2171 BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type
2172 , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type
2175 typedef std::char_traits<char_type> traits;
2176 detail::lexical_stream<Target, Source, traits> interpreter;
2179 if(!(interpreter << arg && interpreter >> result))
2180 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
2187 // Copyright Kevlin Henney, 2000-2005.
2188 // Copyright Alexander Nasonov, 2006-2010.
2189 // Copyright Antony Polukhin, 2011-2012.
2191 // Distributed under the Boost Software License, Version 1.0. (See
2192 // accompanying file LICENSE_1_0.txt or copy at
2193 // http://www.boost.org/LICENSE_1_0.txt)
2195 #undef BOOST_LCAST_NO_WCHAR_T