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 finish = start + sprintf(out,"%.*g", static_cast<int>(boost::detail::lcast_get_precision<float >()), val );
1290 return finish > start;
1294 bool shl_double(double val,T* out)
1295 { using namespace std;
1296 if (put_inf_nan(start,finish,val)) return true;
1297 finish = start + sprintf(out,"%.*lg", static_cast<int>(boost::detail::lcast_get_precision<double >()), val );
1298 return finish > start;
1302 bool shl_long_double(long double val,T* out)
1303 { using namespace std;
1304 if (put_inf_nan(start,finish,val)) return true;
1305 finish = start + sprintf(out,"%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double >()), val );
1306 return finish > start;
1310 #if (defined _MSC_VER)
1311 # pragma warning( pop )
1315 #ifndef BOOST_LCAST_NO_WCHAR_T
1316 bool shl_float(float val,wchar_t* out)
1317 { using namespace std;
1318 if (put_inf_nan(start,finish,val)) return true;
1319 finish = start + swprintf(out,
1320 #if !defined(__MINGW32__) && !defined(UNDER_CE)
1323 L"%.*g", static_cast<int>(boost::detail::lcast_get_precision<float >()), val );
1325 return finish > start;
1329 bool shl_double(double val,wchar_t* out)
1330 { using namespace std;
1331 if (put_inf_nan(start,finish,val)) return true;
1332 /* __MINGW32__ is defined for both mingw.org and for mingw-w64.
1333 * For mingw-w64, __MINGW64__ is defined, too, when targetting
1336 * swprintf realization in MinGW and under WinCE does not conform
1340 finish = start + swprintf(out,
1341 #if !defined(__MINGW32__) && !defined(UNDER_CE)
1344 L"%.*lg", static_cast<int>(boost::detail::lcast_get_precision<double >()), val );
1345 return finish > start;
1349 bool shl_long_double(long double val,wchar_t* out)
1350 { using namespace std;
1351 if (put_inf_nan(start,finish,val)) return true;
1352 finish = start + swprintf(out,
1353 #if !defined(UNDER_CE)
1356 L"%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double >()), val );
1357 return finish > start;
1363 /************************************ OPERATORS << ( ... ) ********************************/
1365 template<class Alloc>
1366 bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str)
1368 start = const_cast<CharT*>(str.data());
1369 finish = start + str.length();
1373 #if !defined(__SUNPRO_CC)
1374 template<class Alloc>
1375 bool operator<<(::boost::container::basic_string<CharT,Traits,Alloc> const& str)
1377 start = const_cast<CharT*>(str.data());
1378 finish = start + str.length();
1381 #endif // !defined(__SUNPRO_CC)
1382 bool operator<<(bool value)
1384 CharT const czero = lcast_char_constants<CharT>::zero;
1385 Traits::assign(*start, Traits::to_char_type(czero + value));
1390 bool operator<<(char ch) { return shl_char(ch); }
1391 bool operator<<(unsigned char ch) { return ((*this) << static_cast<char>(ch)); }
1392 bool operator<<(signed char ch) { return ((*this) << static_cast<char>(ch)); }
1393 #if !defined(BOOST_LCAST_NO_WCHAR_T)
1394 bool operator<<(wchar_t const* str) { return shl_char_array(str); }
1395 bool operator<<(wchar_t * str) { return shl_char_array(str); }
1396 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
1397 bool operator<<(wchar_t ch) { return shl_char(ch); }
1400 bool operator<<(unsigned char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); }
1401 bool operator<<(unsigned char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); }
1402 bool operator<<(signed char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); }
1403 bool operator<<(signed char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); }
1404 bool operator<<(char const* str) { return shl_char_array(str); }
1405 bool operator<<(char* str) { return shl_char_array(str); }
1406 bool operator<<(short n) { return shl_signed(n); }
1407 bool operator<<(int n) { return shl_signed(n); }
1408 bool operator<<(long n) { return shl_signed(n); }
1409 bool operator<<(unsigned short n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1410 bool operator<<(unsigned int n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1411 bool operator<<(unsigned long n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1413 #if defined(BOOST_HAS_LONG_LONG)
1414 bool operator<<(boost::ulong_long_type n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1415 bool operator<<(boost::long_long_type n) { return shl_signed(n); }
1416 #elif defined(BOOST_HAS_MS_INT64)
1417 bool operator<<(unsigned __int64 n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1418 bool operator<<( __int64 n) { return shl_signed(n); }
1420 bool operator<<(float val) { return shl_float(val,start); }
1421 bool operator<<(double val) { return shl_double(val,start); }
1422 bool operator<<(long double val) {
1424 return shl_long_double(val,start);
1426 return shl_double(val,start);
1430 template<class InStreamable>
1431 bool operator<<(const InStreamable& input) { return shl_input_streamable(input); }
1433 /************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/
1436 template <typename Type>
1437 bool shr_unsigned(Type& output)
1439 if (start == finish) return false;
1440 CharT const minus = lcast_char_constants<CharT>::minus;
1441 CharT const plus = lcast_char_constants<CharT>::plus;
1442 bool has_minus = false;
1444 /* We won`t use `start' any more, so no need in decrementing it after */
1445 if ( Traits::eq(minus,*start) )
1449 } else if ( Traits::eq( plus, *start ) )
1454 bool const succeed = lcast_ret_unsigned<Traits>(output, start, finish);
1455 #if (defined _MSC_VER)
1456 # pragma warning( push )
1457 // C4146: unary minus operator applied to unsigned type, result still unsigned
1458 # pragma warning( disable : 4146 )
1459 #elif defined( __BORLANDC__ )
1460 # pragma option push -w-8041
1462 if (has_minus) output = static_cast<Type>(-output);
1463 #if (defined _MSC_VER)
1464 # pragma warning( pop )
1465 #elif defined( __BORLANDC__ )
1471 template <typename Type>
1472 bool shr_signed(Type& output)
1474 if (start == finish) return false;
1475 CharT const minus = lcast_char_constants<CharT>::minus;
1476 CharT const plus = lcast_char_constants<CharT>::plus;
1477 typedef BOOST_DEDUCED_TYPENAME make_unsigned<Type>::type utype;
1479 bool has_minus = false;
1481 /* We won`t use `start' any more, so no need in decrementing it after */
1482 if ( Traits::eq(minus,*start) )
1486 } else if ( Traits::eq(plus, *start) )
1491 bool succeed = lcast_ret_unsigned<Traits>(out_tmp, start, finish);
1493 #if (defined _MSC_VER)
1494 # pragma warning( push )
1495 // C4146: unary minus operator applied to unsigned type, result still unsigned
1496 # pragma warning( disable : 4146 )
1497 #elif defined( __BORLANDC__ )
1498 # pragma option push -w-8041
1500 utype const comp_val = static_cast<utype>(-(std::numeric_limits<Type>::min)());
1501 succeed = succeed && out_tmp<=comp_val;
1503 #if (defined _MSC_VER)
1504 # pragma warning( pop )
1505 #elif defined( __BORLANDC__ )
1509 utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)());
1510 succeed = succeed && out_tmp<=comp_val;
1516 template<typename InputStreamable>
1517 bool shr_using_base_class(InputStreamable& output)
1519 #if (defined _MSC_VER)
1520 # pragma warning( push )
1521 // conditional expression is constant
1522 # pragma warning( disable : 4127 )
1524 if(is_pointer<InputStreamable>::value)
1527 local_streambuffer_t bb;
1528 bb.setg(start, start, finish);
1529 std::basic_istream<CharT> stream(&bb);
1530 stream.unsetf(std::ios::skipws);
1531 lcast_set_precision(stream, static_cast<InputStreamable*>(0));
1532 #if (defined _MSC_VER)
1533 # pragma warning( pop )
1535 return stream >> output &&
1537 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
1538 // GCC 2.9x lacks std::char_traits<>::eof().
1539 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
1540 // configurations, which do provide std::char_traits<>::eof().
1549 inline bool shr_xchar(T& output)
1551 BOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ),
1552 "boost::lexical_cast does not support conversions from whar_t to char types."
1553 "Use boost::locale instead" );
1554 bool const ok = (finish - start == 1);
1557 Traits::assign(out, *start);
1558 output = static_cast<T>(out);
1563 /************************************ OPERATORS >> ( ... ) ********************************/
1565 bool operator>>(unsigned short& output) { return shr_unsigned(output); }
1566 bool operator>>(unsigned int& output) { return shr_unsigned(output); }
1567 bool operator>>(unsigned long int& output) { return shr_unsigned(output); }
1568 bool operator>>(short& output) { return shr_signed(output); }
1569 bool operator>>(int& output) { return shr_signed(output); }
1570 bool operator>>(long int& output) { return shr_signed(output); }
1571 #if defined(BOOST_HAS_LONG_LONG)
1572 bool operator>>(boost::ulong_long_type& output) { return shr_unsigned(output); }
1573 bool operator>>(boost::long_long_type& output) { return shr_signed(output); }
1574 #elif defined(BOOST_HAS_MS_INT64)
1575 bool operator>>(unsigned __int64& output) { return shr_unsigned(output); }
1576 bool operator>>(__int64& output) { return shr_signed(output); }
1578 bool operator>>(char& output) { return shr_xchar(output); }
1579 bool operator>>(unsigned char& output) { return shr_xchar(output); }
1580 bool operator>>(signed char& output) { return shr_xchar(output); }
1581 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
1582 bool operator>>(wchar_t& output) { return shr_xchar(output); }
1584 #ifndef BOOST_NO_CHAR16_T
1585 bool operator>>(char16_t& output) { return shr_xchar(output); }
1587 #ifndef BOOST_NO_CHAR32_T
1588 bool operator>>(char32_t& output) { return shr_xchar(output); }
1590 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1591 bool operator>>(std::string& str) { str.assign(start, finish); return true; }
1592 # ifndef BOOST_LCAST_NO_WCHAR_T
1593 bool operator>>(std::wstring& str) { str.assign(start, finish); return true; }
1596 template<class Alloc>
1597 bool operator>>(std::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
1598 #if !defined(__SUNPRO_CC)
1599 template<class Alloc>
1600 bool operator>>(::boost::container::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
1601 #endif // !defined(__SUNPRO_CC)
1604 * case "-0" || "0" || "+0" : output = false; return true;
1605 * case "1" || "+1": output = true; return true;
1606 * default: return false;
1608 bool operator>>(bool& output)
1610 CharT const zero = lcast_char_constants<CharT>::zero;
1611 CharT const plus = lcast_char_constants<CharT>::plus;
1612 CharT const minus = lcast_char_constants<CharT>::minus;
1614 switch(finish-start)
1617 output = Traits::eq(start[0], zero+1);
1618 return output || Traits::eq(start[0], zero );
1620 if ( Traits::eq( plus, *start) )
1623 output = Traits::eq(start[0], zero +1);
1624 return output || Traits::eq(start[0], zero );
1628 return Traits::eq( minus, *start)
1629 && Traits::eq( zero, start[1]);
1632 output = false; // Suppress warning about uninitalized variable
1637 bool operator>>(float& output) { return lcast_ret_float<Traits>(output,start,finish); }
1640 // Not optimised converter
1642 bool float_types_converter_internal(T& output, int /*tag*/) {
1643 if (parse_inf_nan(start, finish, output)) return true;
1644 bool return_value = shr_using_base_class(output);
1646 /* Some compilers and libraries successfully
1647 * parse 'inf', 'INFINITY', '1.0E', '1.0E-'...
1648 * We are trying to provide a unified behaviour,
1649 * so we just forbid such conversions (as some
1650 * of the most popular compilers/libraries do)
1652 CharT const minus = lcast_char_constants<CharT>::minus;
1653 CharT const plus = lcast_char_constants<CharT>::plus;
1654 CharT const capital_e = lcast_char_constants<CharT>::capital_e;
1655 CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
1656 if ( return_value &&
1658 *(finish-1) == lowercase_e // 1.0e
1659 || *(finish-1) == capital_e // 1.0E
1660 || *(finish-1) == minus // 1.0e- or 1.0E-
1661 || *(finish-1) == plus // 1.0e+ or 1.0E+
1665 return return_value;
1668 // Optimised converter
1669 bool float_types_converter_internal(double& output,char /*tag*/) {
1670 return lcast_ret_float<Traits>(output,start,finish);
1674 bool operator>>(double& output)
1677 * Some compilers implement long double as double. In that case these types have
1678 * same size, same precision, same max and min values... And it means,
1679 * that current implementation of lcast_ret_float cannot be used for type
1680 * double, because it will give a big precision loss.
1683 #if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)
1684 ::boost::type_traits::ice_eq< sizeof(double), sizeof(long double) >::value,
1692 return float_types_converter_internal(output, tag);
1695 bool operator>>(long double& output)
1698 return float_types_converter_internal(output, tag);
1701 // Generic istream-based algorithm.
1702 // lcast_streambuf_for_target<InputStreamable>::value is true.
1703 template<typename InputStreamable>
1704 bool operator>>(InputStreamable& output) { return shr_using_base_class(output); }
1708 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
1710 // call-by-const reference version
1715 struct array_to_pointer_decay
1720 template<class T, std::size_t N>
1721 struct array_to_pointer_decay<T[N]>
1723 typedef const T * type;
1726 template<typename T>
1729 BOOST_STATIC_CONSTANT(bool, value = false );
1732 template<typename CharT, typename Traits, typename Alloc>
1733 struct is_stdstring< std::basic_string<CharT, Traits, Alloc> >
1735 BOOST_STATIC_CONSTANT(bool, value = true );
1737 #if !defined(__SUNPRO_CC)
1738 template<typename CharT, typename Traits, typename Alloc>
1739 struct is_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc> >
1741 BOOST_STATIC_CONSTANT(bool, value = true );
1743 #endif // !defined(__SUNPRO_CC)
1744 template<typename T>
1745 struct is_char_or_wchar
1748 #ifndef BOOST_LCAST_NO_WCHAR_T
1749 typedef wchar_t wchar_t_if_supported;
1751 typedef char wchar_t_if_supported;
1754 #ifndef BOOST_NO_CHAR16_T
1755 typedef char16_t char16_t_if_supported;
1757 typedef char char16_t_if_supported;
1760 #ifndef BOOST_NO_CHAR32_T
1761 typedef char32_t char32_t_if_supported;
1763 typedef char char32_t_if_supported;
1767 BOOST_STATIC_CONSTANT(bool, value =
1769 ::boost::type_traits::ice_or<
1770 is_same< T, char >::value,
1771 is_same< T, wchar_t_if_supported >::value,
1772 is_same< T, char16_t_if_supported >::value,
1773 is_same< T, char32_t_if_supported >::value,
1774 is_same< T, unsigned char >::value,
1775 is_same< T, signed char >::value
1781 template<typename Target, typename Source>
1782 struct is_arithmetic_and_not_xchars
1784 BOOST_STATIC_CONSTANT(bool, value =
1786 ::boost::type_traits::ice_and<
1787 is_arithmetic<Source>::value,
1788 is_arithmetic<Target>::value,
1789 ::boost::type_traits::ice_not<
1790 detail::is_char_or_wchar<Target>::value
1792 ::boost::type_traits::ice_not<
1793 detail::is_char_or_wchar<Source>::value
1801 * is_xchar_to_xchar<Target, Source>::value is true, when
1802 * Target and Souce are the same char types, or when
1803 * Target and Souce are char types of the same size.
1805 template<typename Target, typename Source>
1806 struct is_xchar_to_xchar
1808 BOOST_STATIC_CONSTANT(bool, value =
1810 ::boost::type_traits::ice_or<
1811 ::boost::type_traits::ice_and<
1812 is_same<Source,Target>::value,
1813 is_char_or_wchar<Target>::value
1815 ::boost::type_traits::ice_and<
1816 ::boost::type_traits::ice_eq< sizeof(char),sizeof(Target)>::value,
1817 ::boost::type_traits::ice_eq< sizeof(char),sizeof(Source)>::value,
1818 is_char_or_wchar<Target>::value,
1819 is_char_or_wchar<Source>::value
1826 template<typename Target, typename Source>
1827 struct is_char_array_to_stdstring
1829 BOOST_STATIC_CONSTANT(bool, value = false );
1832 template<typename CharT, typename Traits, typename Alloc>
1833 struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, CharT* >
1835 BOOST_STATIC_CONSTANT(bool, value = true );
1838 template<typename CharT, typename Traits, typename Alloc>
1839 struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, const CharT* >
1841 BOOST_STATIC_CONSTANT(bool, value = true );
1843 #if !defined(__SUNPRO_CC)
1844 template<typename CharT, typename Traits, typename Alloc>
1845 struct is_char_array_to_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc>, CharT* >
1847 BOOST_STATIC_CONSTANT(bool, value = true );
1850 template<typename CharT, typename Traits, typename Alloc>
1851 struct is_char_array_to_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc>, const CharT* >
1853 BOOST_STATIC_CONSTANT(bool, value = true );
1855 #endif // !defined(__SUNPRO_CC)
1857 #if (defined _MSC_VER)
1858 # pragma warning( push )
1859 # pragma warning( disable : 4701 ) // possible use of ... before initialization
1860 # pragma warning( disable : 4702 ) // unreachable code
1861 # pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int'
1863 template<typename Target, typename Source>
1864 struct lexical_cast_do_cast
1866 static inline Target lexical_cast_impl(const Source& arg)
1868 typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay<Source>::type src;
1870 typedef BOOST_DEDUCED_TYPENAME detail::widest_char<
1871 BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type
1872 , BOOST_DEDUCED_TYPENAME detail::stream_char<src>::type
1875 typedef detail::lcast_src_length<src> lcast_src_length;
1876 std::size_t const src_len = lcast_src_length::value;
1877 char_type buf[src_len + 1];
1878 lcast_src_length::check_coverage();
1880 typedef BOOST_DEDUCED_TYPENAME
1881 deduce_char_traits<char_type,Target,Source>::type traits;
1883 typedef BOOST_DEDUCED_TYPENAME remove_pointer<src >::type removed_ptr_t;
1885 // is_char_types_match variable value can be computed via
1886 // sizeof(char_type) == sizeof(removed_ptr_t). But when
1887 // removed_ptr_t is an incomplete type or void*, compilers
1888 // produce warnings or errors.
1889 const bool is_char_types_match =
1890 (::boost::type_traits::ice_or<
1891 ::boost::type_traits::ice_and<
1892 ::boost::type_traits::ice_eq<sizeof(char_type), sizeof(char) >::value,
1893 ::boost::type_traits::ice_or<
1894 ::boost::is_same<char, removed_ptr_t>::value,
1895 ::boost::is_same<unsigned char, removed_ptr_t>::value,
1896 ::boost::is_same<signed char, removed_ptr_t>::value
1899 is_same<char_type, removed_ptr_t>::value
1902 const bool requires_stringbuf =
1904 ::boost::type_traits::ice_or<
1905 is_stdstring<src >::value,
1906 is_arithmetic<src >::value,
1907 ::boost::type_traits::ice_and<
1908 is_pointer<src >::value,
1909 is_char_or_wchar<removed_ptr_t >::value,
1915 detail::lexical_stream_limited_src<char_type,traits, requires_stringbuf >
1916 interpreter(buf, buf + src_len);
1919 // Disabling ADL, by directly specifying operators.
1920 if(!(interpreter.operator <<(arg) && interpreter.operator >>(result)))
1921 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1925 #if (defined _MSC_VER)
1926 # pragma warning( pop )
1929 template<typename Source>
1930 struct lexical_cast_copy
1932 static inline Source lexical_cast_impl(const Source &arg)
1938 class precision_loss_error : public boost::numeric::bad_numeric_cast
1941 virtual const char * what() const throw()
1942 { return "bad numeric conversion: precision loss error"; }
1946 struct throw_on_precision_loss
1948 typedef boost::numeric::Trunc<S> Rounder;
1949 typedef S source_type ;
1951 typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
1953 static source_type nearbyint ( argument_type s )
1955 source_type orig_div_round = s / Rounder::nearbyint(s);
1957 if ( (orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > std::numeric_limits<source_type>::epsilon() )
1958 BOOST_THROW_EXCEPTION( precision_loss_error() );
1962 typedef typename Rounder::round_style round_style;
1965 template<typename Target, typename Source>
1966 struct lexical_cast_dynamic_num_not_ignoring_minus
1968 static inline Target lexical_cast_impl(const Source &arg)
1971 typedef boost::numeric::converter<
1974 boost::numeric::conversion_traits<Target,Source>,
1975 boost::numeric::def_overflow_handler,
1976 throw_on_precision_loss<Source>
1979 return Converter::convert(arg);
1980 } catch( ::boost::numeric::bad_numeric_cast const& ) {
1981 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
1983 BOOST_UNREACHABLE_RETURN(static_cast<Target>(0));
1987 template<typename Target, typename Source>
1988 struct lexical_cast_dynamic_num_ignoring_minus
1990 static inline Target lexical_cast_impl(const Source &arg)
1993 typedef boost::numeric::converter<
1996 boost::numeric::conversion_traits<Target,Source>,
1997 boost::numeric::def_overflow_handler,
1998 throw_on_precision_loss<Source>
2001 bool has_minus = ( arg < 0);
2003 return static_cast<Target>(-Converter::convert(-arg));
2005 return Converter::convert(arg);
2007 } catch( ::boost::numeric::bad_numeric_cast const& ) {
2008 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
2010 BOOST_UNREACHABLE_RETURN(static_cast<Target>(0));
2015 * lexical_cast_dynamic_num follows the rules:
2016 * 1) If Source can be converted to Target without precision loss and
2017 * without overflows, then assign Source to Target and return
2019 * 2) If Source is less than 0 and Target is an unsigned integer,
2020 * then negate Source, check the requirements of rule 1) and if
2021 * successful, assign static_casted Source to Target and return
2023 * 3) Otherwise throw a bad_lexical_cast exception
2026 * Rule 2) required because boost::lexical_cast has the behavior of
2027 * stringstream, which uses the rules of scanf for conversions. And
2028 * in the C99 standard for unsigned input value minus sign is
2029 * optional, so if a negative number is read, no errors will arise
2030 * and the result will be the two's complement.
2032 template<typename Target, typename Source>
2033 struct lexical_cast_dynamic_num
2035 static inline Target lexical_cast_impl(const Source &arg)
2037 typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
2038 ::boost::type_traits::ice_and<
2039 ::boost::type_traits::ice_or<
2040 ::boost::is_signed<Source>::value,
2041 ::boost::is_float<Source>::value
2043 ::boost::type_traits::ice_not<
2044 is_same<Source, bool>::value
2046 ::boost::type_traits::ice_not<
2047 is_same<Target, bool>::value
2049 ::boost::is_unsigned<Target>::value
2051 lexical_cast_dynamic_num_ignoring_minus<Target, Source>,
2052 lexical_cast_dynamic_num_not_ignoring_minus<Target, Source>
2053 >::type caster_type;
2055 return caster_type::lexical_cast_impl(arg);
2060 template<typename Target, typename Source>
2061 inline Target lexical_cast(const Source &arg)
2063 typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay<Source>::type src;
2065 typedef BOOST_DEDUCED_TYPENAME ::boost::type_traits::ice_or<
2066 detail::is_xchar_to_xchar<Target, src>::value,
2067 detail::is_char_array_to_stdstring<Target,src>::value,
2068 ::boost::type_traits::ice_and<
2069 is_same<Target, src>::value,
2070 detail::is_stdstring<Target>::value
2074 typedef BOOST_DEDUCED_TYPENAME
2075 detail::is_arithmetic_and_not_xchars<Target, src> do_copy_with_dynamic_check_type;
2077 typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
2078 do_copy_type::value,
2079 detail::lexical_cast_copy<src>,
2080 BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c<
2081 do_copy_with_dynamic_check_type::value,
2082 detail::lexical_cast_dynamic_num<Target, src>,
2083 detail::lexical_cast_do_cast<Target, src>
2085 >::type caster_type;
2087 return caster_type::lexical_cast_impl(arg);
2092 namespace detail // stream wrapper for handling lexical conversions
2094 template<typename Target, typename Source, typename Traits>
2095 class lexical_stream
2098 typedef typename widest_char<
2099 typename stream_char<Target>::type,
2100 typename stream_char<Source>::type>::type char_type;
2102 typedef Traits traits_type;
2105 lexical_stream(char_type* = 0, char_type* = 0)
2107 stream.unsetf(std::ios::skipws);
2108 lcast_set_precision(stream, static_cast<Source*>(0), static_cast<Target*>(0) );
2112 #if defined(BOOST_NO_STRINGSTREAM)
2113 stream.freeze(false);
2116 bool operator<<(const Source &input)
2118 return !(stream << input).fail();
2120 template<typename InputStreamable>
2121 bool operator>>(InputStreamable &output)
2123 return !is_pointer<InputStreamable>::value &&
2126 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
2127 // GCC 2.9x lacks std::char_traits<>::eof().
2128 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
2129 // configurations, which do provide std::char_traits<>::eof().
2137 bool operator>>(std::string &output)
2139 #if defined(BOOST_NO_STRINGSTREAM)
2142 stream.str().swap(output);
2145 #ifndef BOOST_LCAST_NO_WCHAR_T
2146 bool operator>>(std::wstring &output)
2148 stream.str().swap(output);
2154 #if defined(BOOST_NO_STRINGSTREAM)
2155 std::strstream stream;
2156 #elif defined(BOOST_NO_STD_LOCALE)
2157 std::stringstream stream;
2159 std::basic_stringstream<char_type,traits_type> stream;
2164 // call-by-value fallback version (deprecated)
2166 template<typename Target, typename Source>
2167 Target lexical_cast(Source arg)
2169 typedef typename detail::widest_char<
2170 BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type
2171 , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type
2174 typedef std::char_traits<char_type> traits;
2175 detail::lexical_stream<Target, Source, traits> interpreter;
2178 if(!(interpreter << arg && interpreter >> result))
2179 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
2186 // Copyright Kevlin Henney, 2000-2005.
2187 // Copyright Alexander Nasonov, 2006-2010.
2188 // Copyright Antony Polukhin, 2011-2012.
2190 // Distributed under the Boost Software License, Version 1.0. (See
2191 // accompanying file LICENSE_1_0.txt or copy at
2192 // http://www.boost.org/LICENSE_1_0.txt)
2194 #undef BOOST_LCAST_NO_WCHAR_T