diff options
Diffstat (limited to 'boost/lexical_cast.hpp')
-rw-r--r-- | boost/lexical_cast.hpp | 1172 |
1 files changed, 712 insertions, 460 deletions
diff --git a/boost/lexical_cast.hpp b/boost/lexical_cast.hpp index 5a3d4f072a..acfc3e85f0 100644 --- a/boost/lexical_cast.hpp +++ b/boost/lexical_cast.hpp @@ -26,58 +26,22 @@ #define BOOST_LCAST_NO_WCHAR_T #endif -#if (defined(__MINGW32__) || defined(__MINGW64__)) && (__GNUC__ == 4) \ - && ((__GNUC_MINOR__ == 4) || (__GNUC_MINOR__ == 5)) && defined(__STRICT_ANSI__) \ - && !defined(BOOST_LCAST_NO_WCHAR_T) - -// workaround for a mingw bug -// http://sourceforge.net/tracker/index.php?func=detail&aid=2373234&group_id=2435&atid=102435 -#include <_mingw.h> -#if (__GNUC_MINOR__ == 4) -extern "C" { -_CRTIMP int __cdecl swprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , ...); -_CRTIMP int __cdecl vswprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , ...); -} -#endif -#if (__GNUC_MINOR__ == 5) -extern "C" { -_CRTIMP int __cdecl swprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , ...); -_CRTIMP int __cdecl vswprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , va_list); -} -#endif -#endif - #include <climits> #include <cstddef> -#include <istream> #include <string> #include <cstring> #include <cstdio> #include <typeinfo> #include <exception> -#include <cmath> #include <boost/limits.hpp> #include <boost/mpl/if.hpp> #include <boost/throw_exception.hpp> -#include <boost/type_traits/is_pointer.hpp> -#include <boost/type_traits/is_integral.hpp> -#include <boost/type_traits/is_arithmetic.hpp> -#include <boost/type_traits/remove_pointer.hpp> -#include <boost/numeric/conversion/cast.hpp> #include <boost/type_traits/ice.hpp> -#include <boost/type_traits/make_unsigned.hpp> -#include <boost/type_traits/is_signed.hpp> -#include <boost/math/special_functions/sign.hpp> -#include <boost/math/special_functions/fpclassify.hpp> +#include <boost/type_traits/is_pointer.hpp> #include <boost/static_assert.hpp> #include <boost/detail/lcast_precision.hpp> #include <boost/detail/workaround.hpp> -#if !defined(__SUNPRO_CC) -#include <boost/container/container_fwd.hpp> -#endif // !defined(__SUNPRO_CC) -#ifndef BOOST_NO_CWCHAR -# include <cwchar> -#endif + #ifndef BOOST_NO_STD_LOCALE # include <locale> @@ -104,7 +68,7 @@ _CRTIMP int __cdecl vswprintf(wchar_t * __restrict__ , const wchar_t * __restric namespace boost { // exception used to indicate runtime lexical_cast failure - class bad_lexical_cast : + class BOOST_SYMBOL_VISIBLE bad_lexical_cast : // workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0 #if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS public std::exception @@ -157,118 +121,201 @@ namespace boost const std::type_info *target; }; - namespace detail // selectors for choosing stream character type - { - template<typename Type> - struct stream_char + namespace detail // widest_char { - typedef char type; - }; + template <typename TargetChar, typename SourceChar> + struct widest_char + { + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< + (sizeof(TargetChar) > sizeof(SourceChar)) + , TargetChar + , SourceChar >::type type; + }; + } +} // namespace boost -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template<class CharT, class Traits, class Alloc> - struct stream_char< std::basic_string<CharT,Traits,Alloc> > - { - typedef CharT type; - }; +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) && !defined(__PGIC__) -#if !defined(__SUNPRO_CC) - template<class CharT, class Traits, class Alloc> - struct stream_char< ::boost::container::basic_string<CharT,Traits,Alloc> > - { - typedef CharT type; - }; -#endif // !defined(__SUNPRO_CC) +#include <cmath> +#include <istream> + +#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) +#include <array> #endif -#ifndef BOOST_LCAST_NO_WCHAR_T -#ifndef BOOST_NO_INTRINSIC_WCHAR_T - template<> - struct stream_char<wchar_t> - { - typedef wchar_t type; - }; +#include <boost/array.hpp> +#include <boost/numeric/conversion/cast.hpp> +#include <boost/type_traits/make_unsigned.hpp> +#include <boost/type_traits/is_signed.hpp> +#include <boost/type_traits/is_integral.hpp> +#include <boost/type_traits/is_arithmetic.hpp> +#include <boost/type_traits/remove_pointer.hpp> +#include <boost/math/special_functions/sign.hpp> +#include <boost/math/special_functions/fpclassify.hpp> +#include <boost/range/iterator_range_core.hpp> +#include <boost/container/container_fwd.hpp> +#ifndef BOOST_NO_CWCHAR +# include <cwchar> #endif - template<> - struct stream_char<wchar_t *> +namespace boost { + namespace detail // widest_char<...> (continuation) { - typedef wchar_t type; - }; + struct not_a_character_type{}; - template<> - struct stream_char<const wchar_t *> - { - typedef wchar_t type; - }; + template <typename CharT> + struct widest_char<not_a_character_type, CharT > + { + typedef CharT type; + }; -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template<> - struct stream_char<std::wstring> + template <typename CharT> + struct widest_char< CharT, not_a_character_type > + { + typedef CharT type; + }; + + template <> + struct widest_char< not_a_character_type, not_a_character_type > + { + typedef char type; + }; + } + + namespace detail // is_char_or_wchar<...> and stream_char<...> templates { - typedef wchar_t type; - }; -#endif -#endif + // returns true, if T is one of the character types + template <typename T> + struct is_char_or_wchar + { + typedef ::boost::type_traits::ice_or< + ::boost::is_same< T, char >::value, + #ifndef BOOST_LCAST_NO_WCHAR_T + ::boost::is_same< T, wchar_t >::value, + #endif + #ifndef BOOST_NO_CHAR16_T + ::boost::is_same< T, char16_t >::value, + #endif + #ifndef BOOST_NO_CHAR32_T + ::boost::is_same< T, char32_t >::value, + #endif + ::boost::is_same< T, unsigned char >::value, + ::boost::is_same< T, signed char >::value + > result_type; + + BOOST_STATIC_CONSTANT(bool, value = (result_type::value) ); + }; + // selectors for choosing stream character type + // returns one of char, wchar_t, char16_t, char32_t or not_a_character_type types + template <typename Type> + struct stream_char + { + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< + is_char_or_wchar<Type >::value, + Type, + boost::detail::not_a_character_type + >::type type; + }; -#ifndef BOOST_NO_CHAR16_T + template <> + struct stream_char<unsigned char> + { + typedef char type; + }; - template<> - struct stream_char<char16_t> - { - typedef char16_t type; - }; + template <> + struct stream_char<signed char> + { + typedef char type; + }; - template<> - struct stream_char<char16_t *> - { - typedef char16_t type; - }; + template <typename CharT> + struct stream_char<CharT*> + { + typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type; + }; - template<> - struct stream_char<const char16_t *> - { - typedef char16_t type; - }; + template <typename CharT> + struct stream_char<const CharT*> + { + typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type; + }; -#endif + template <typename CharT> + struct stream_char<iterator_range<CharT*> > + { + typedef BOOST_DEDUCED_TYPENAME stream_char<CharT*>::type type; + }; + + template <typename CharT> + struct stream_char<iterator_range<const CharT*> > + { + typedef BOOST_DEDUCED_TYPENAME stream_char<const CharT*>::type type; + }; -#ifndef BOOST_NO_CHAR32_T + template <class CharT, class Traits, class Alloc> + struct stream_char< std::basic_string<CharT, Traits, Alloc> > + { + typedef CharT type; + }; - template<> - struct stream_char<char32_t> - { - typedef char32_t type; - }; + template <class CharT, class Traits, class Alloc> + struct stream_char< ::boost::container::basic_string<CharT, Traits, Alloc> > + { + typedef CharT type; + }; - template<> - struct stream_char<char32_t *> - { - typedef char32_t type; - }; + template<typename CharT, std::size_t N> + struct stream_char<boost::array<CharT, N> > + { + typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type; + }; - template<> - struct stream_char<const char32_t *> - { - typedef char32_t type; - }; + template<typename CharT, std::size_t N> + struct stream_char<boost::array<const CharT, N> > + { + typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type; + }; -#endif +#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) + template <typename CharT, std::size_t N> + struct stream_char<std::array<CharT, N> > + { + typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type; + }; - template<typename TargetChar, typename SourceChar> - struct widest_char + template <typename CharT, std::size_t N> + struct stream_char<std::array<const CharT, N> > { - typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< - (sizeof(TargetChar) > sizeof(SourceChar)) - , TargetChar - , SourceChar >::type type; + typedef BOOST_DEDUCED_TYPENAME stream_char<CharT>::type type; }; +#endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) + +#if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T) + template<> + struct stream_char<wchar_t> + { + typedef boost::detail::not_a_character_type type; + }; + + template<> + struct stream_char<wchar_t*> + { + typedef wchar_t type; + }; + + template<> + struct stream_char<const wchar_t*> + { + typedef wchar_t type; + }; +#endif } namespace detail // deduce_char_traits template { -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template<class CharT, class Target, class Source> struct deduce_char_traits { @@ -293,7 +340,6 @@ namespace boost typedef Traits type; }; -#if !defined(__SUNPRO_CC) template<class CharT, class Traits, class Alloc, class Source> struct deduce_char_traits< CharT , ::boost::container::basic_string<CharT,Traits,Alloc> @@ -333,7 +379,7 @@ namespace boost template<class CharT, class Traits, class Alloc1, class Alloc2> struct deduce_char_traits< CharT , ::boost::container::basic_string<CharT,Traits,Alloc1> - , std::basic_string<CharT,Traits,Alloc2> + , ::std::basic_string<CharT,Traits,Alloc2> > { typedef Traits type; @@ -341,14 +387,12 @@ namespace boost template<class CharT, class Traits, class Alloc1, class Alloc2> struct deduce_char_traits< CharT - , std::basic_string<CharT,Traits,Alloc1> + , ::std::basic_string<CharT,Traits,Alloc1> , ::boost::container::basic_string<CharT,Traits,Alloc2> > { typedef Traits type; }; -#endif // !defined(__SUNPRO_CC) -#endif } namespace detail // lcast_src_length @@ -391,7 +435,7 @@ namespace boost BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256); #endif }; -// TODO: FIX for char16_t, char32_t, we can ignore CharT + #define BOOST_LCAST_DEF(T) \ template<> struct lcast_src_length<T> \ : lcast_src_length_integral<T> \ @@ -488,7 +532,7 @@ namespace boost }; #endif -#ifndef BOOST_NO_CHAR16_T +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) template<> struct lcast_char_constants<char16_t> { @@ -501,7 +545,7 @@ namespace boost }; #endif -#ifndef BOOST_NO_CHAR32_T +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) template<> struct lcast_char_constants<char32_t> { @@ -732,6 +776,15 @@ namespace boost namespace detail { + template <class CharT> + bool lc_iequal(const CharT* val, const CharT* lcase, const CharT* ucase, unsigned int len) { + for( unsigned int i=0; i < len; ++i ) { + if ( val[i] != lcase[i] && val[i] != ucase[i] ) return false; + } + + return true; + } + /* Returns true and sets the correct value if found NaN or Inf. */ template <class CharT, class T> inline bool parse_inf_nan_impl(const CharT* begin, const CharT* end, T& value @@ -755,7 +808,7 @@ namespace boost else if( *begin == plus ) ++begin; if( end-begin < 3 ) return false; - if( !memcmp(begin, lc_nan, 3*sizeof(CharT)) || !memcmp(begin, lc_NAN, 3*sizeof(CharT)) ) + if( lc_iequal(begin, lc_nan, lc_NAN, 3) ) { begin += 3; if (end != begin) /* It is 'nan(...)' or some bad input*/ @@ -772,13 +825,13 @@ namespace boost if (( /* 'INF' or 'inf' */ end-begin==3 && - (!memcmp(begin, lc_infinity, 3*sizeof(CharT)) || !memcmp(begin, lc_INFINITY, 3*sizeof(CharT))) + lc_iequal(begin, lc_infinity, lc_INFINITY, 3) ) || ( /* 'INFINITY' or 'infinity' */ end-begin==inifinity_size && - (!memcmp(begin, lc_infinity, inifinity_size)|| !memcmp(begin, lc_INFINITY, inifinity_size)) + lc_iequal(begin, lc_infinity, lc_INFINITY, inifinity_size) ) ) { @@ -790,6 +843,41 @@ namespace boost return false; } + template <class CharT, class T> + bool put_inf_nan_impl(CharT* begin, CharT*& end, const T& value + , const CharT* lc_nan + , const CharT* lc_infinity) + { + using namespace std; + const CharT minus = lcast_char_constants<CharT>::minus; + if ( (boost::math::isnan)(value) ) + { + if ( (boost::math::signbit)(value) ) + { + *begin = minus; + ++ begin; + } + + memcpy(begin, lc_nan, 3 * sizeof(CharT)); + end = begin + 3; + return true; + } else if ( (boost::math::isinf)(value) ) + { + if ( (boost::math::signbit)(value) ) + { + *begin = minus; + ++ begin; + } + + memcpy(begin, lc_infinity, 3 * sizeof(CharT)); + end = begin + 3; + return true; + } + + return false; + } + + #ifndef BOOST_LCAST_NO_WCHAR_T template <class T> bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value) @@ -799,8 +887,15 @@ namespace boost , L"INFINITY", L"infinity" , L'(', L')'); } + + template <class T> + bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) + { + return put_inf_nan_impl(begin, end, value, L"nan", L"infinity"); + } + #endif -#ifndef BOOST_NO_CHAR16_T +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) template <class T> bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value) { @@ -809,8 +904,14 @@ namespace boost , u"INFINITY", u"infinity" , u'(', u')'); } + + template <class T> + bool put_inf_nan(char16_t* begin, char16_t*& end, const T& value) + { + return put_inf_nan_impl(begin, end, value, u"nan", u"infinity"); + } #endif -#ifndef BOOST_NO_CHAR32_T +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) template <class T> bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value) { @@ -819,6 +920,12 @@ namespace boost , U"INFINITY", U"infinity" , U'(', U')'); } + + template <class T> + bool put_inf_nan(char32_t* begin, char32_t*& end, const T& value) + { + return put_inf_nan_impl(begin, end, value, U"nan", U"infinity"); + } #endif template <class CharT, class T> @@ -829,73 +936,12 @@ namespace boost , "INFINITY", "infinity" , '(', ')'); } -#ifndef BOOST_LCAST_NO_WCHAR_T - template <class T> - bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) - { - using namespace std; - if ( (boost::math::isnan)(value) ) - { - if ( (boost::math::signbit)(value) ) - { - memcpy(begin,L"-nan", sizeof(L"-nan")); - end = begin + 4; - } else - { - memcpy(begin,L"nan", sizeof(L"nan")); - end = begin + 3; - } - return true; - } else if ( (boost::math::isinf)(value) ) - { - if ( (boost::math::signbit)(value) ) - { - memcpy(begin,L"-inf", sizeof(L"-inf")); - end = begin + 4; - } else - { - memcpy(begin,L"inf", sizeof(L"inf")); - end = begin + 3; - } - return true; - } - return false; - } -#endif template <class CharT, class T> bool put_inf_nan(CharT* begin, CharT*& end, const T& value) { - using namespace std; - if ( (boost::math::isnan)(value) ) - { - if ( (boost::math::signbit)(value) ) - { - memcpy(begin,"-nan", sizeof("-nan")); - end = begin + 4; - } else - { - memcpy(begin,"nan", sizeof("nan")); - end = begin + 3; - } - return true; - } else if ( (boost::math::isinf)(value) ) - { - if ( (boost::math::signbit)(value) ) - { - memcpy(begin,"-inf", sizeof("-inf")); - end = begin + 4; - } else - { - memcpy(begin,"inf", sizeof("inf")); - end = begin + 3; - } - return true; - } - - return false; + return put_inf_nan_impl(begin, end, value, "nan", "infinity"); } - } @@ -951,7 +997,7 @@ namespace boost CharT const capital_e = lcast_char_constants<CharT>::capital_e; CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e; - value = 0.0; + value = static_cast<T>(0); if (parse_inf_nan(begin, end, value)) return true; @@ -1042,9 +1088,10 @@ namespace boost ) return false; #endif - if(*begin == decimal_point){ + if(*begin == decimal_point) { ++ begin; found_decimal = true; + if (!found_number_before_exp && begin==end) return false; continue; }else { if (!found_number_before_exp) return false; @@ -1165,7 +1212,7 @@ namespace boost namespace detail { - struct do_not_construct_stringbuffer_t{}; + struct do_not_construct_out_stream_t{}; } namespace detail // optimized stream wrapper @@ -1177,25 +1224,27 @@ namespace boost > class lexical_stream_limited_src { - typedef stl_buf_unlocker<std::basic_streambuf<CharT, Traits>, CharT > local_streambuffer_t; #if defined(BOOST_NO_STRINGSTREAM) - typedef stl_buf_unlocker<std::strstream, CharT > local_stringbuffer_t; + typedef std::ostrstream out_stream_t; + typedef stl_buf_unlocker<std::strstreambuf, char> unlocked_but_t; #elif defined(BOOST_NO_STD_LOCALE) - typedef stl_buf_unlocker<std::stringstream, CharT > local_stringbuffer_t; + typedef std::ostringstream out_stream_t; + typedef stl_buf_unlocker<std::stringbuf, char> unlocked_but_t; #else - typedef stl_buf_unlocker<std::basic_stringbuf<CharT, Traits>, CharT > local_stringbuffer_t; + typedef std::basic_ostringstream<CharT, Traits> out_stream_t; + typedef stl_buf_unlocker<std::basic_stringbuf<CharT, Traits>, CharT> unlocked_but_t; #endif typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< RequiresStringbuffer, - local_stringbuffer_t, - do_not_construct_stringbuffer_t - >::type deduced_stringbuffer_t; + out_stream_t, + do_not_construct_out_stream_t + >::type deduced_out_stream_t; // A string representation of Source is written to [start, finish). CharT* start; CharT* finish; - deduced_stringbuffer_t stringbuffer; + deduced_out_stream_t out_stream; public: lexical_stream_limited_src(CharT* sta, CharT* fin) @@ -1221,7 +1270,7 @@ namespace boost bool shl_char(T ch) { BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)) , - "boost::lexical_cast does not support conversions from whar_t to char types." + "boost::lexical_cast does not support conversions from wide character to char types." "Use boost::locale instead" ); #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE std::locale loc; @@ -1242,24 +1291,35 @@ namespace boost return true; } -#ifndef BOOST_LCAST_NO_WCHAR_T template <class T> bool shl_char_array(T const* str) { BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)), - "boost::lexical_cast does not support conversions from wchar_t to char types." + "boost::lexical_cast does not support conversions from wide characters to char types." "Use boost::locale instead" ); return shl_input_streamable(str); } -#endif + + bool shl_char_array_limited(CharT const* str, std::size_t max_size) + { + start = const_cast<CharT*>(str); + finish = std::find(start, start + max_size, static_cast<CharT>(0)); + return true; + } template<typename InputStreamable> bool shl_input_streamable(InputStreamable& input) { - std::basic_ostream<CharT> stream(&stringbuffer); - bool const result = !(stream << input).fail(); - start = stringbuffer.pbase(); - finish = stringbuffer.pptr(); +#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) + // If you have compilation error at this point, than your STL library + // does not support such conversions. Try updating it. + BOOST_STATIC_ASSERT((boost::is_same<char, CharT>::value)); +#endif + bool const result = !(out_stream << input).fail(); + const unlocked_but_t* const p + = static_cast<unlocked_but_t*>(out_stream.rdbuf()) ; + start = p->pbase(); + finish = p->pptr(); return result; } @@ -1276,90 +1336,86 @@ namespace boost return true; } -#if (defined _MSC_VER) -# pragma warning( push ) -// C4996: This function or variable may be unsafe. Consider using sprintf_s instead -# pragma warning( disable : 4996 ) -#endif + template <class T, class SomeCharT> + bool shl_real_type(const T& val, SomeCharT* begin, SomeCharT*& end) + { + if (put_inf_nan(begin, end, val)) return true; + lcast_set_precision(out_stream, &val); + return shl_input_streamable(val); + } - template <class T> - bool shl_float(float val,T* out) + static bool shl_real_type(float val, char* begin, char*& end) { using namespace std; - if (put_inf_nan(start,finish,val)) return true; - finish = start + sprintf(out,"%.*g", static_cast<int>(boost::detail::lcast_get_precision<float >()), val ); - return finish > start; + if (put_inf_nan(begin, end, val)) return true; + const double val_as_double = val; + end = begin + +#if (defined _MSC_VER) + sprintf_s(begin, end-begin, +#else + sprintf(begin, +#endif + "%.*g", static_cast<int>(boost::detail::lcast_get_precision<float>()), val_as_double); + return end > begin; } - template <class T> - bool shl_double(double val,T* out) + static bool shl_real_type(double val, char* begin, char*& end) { using namespace std; - if (put_inf_nan(start,finish,val)) return true; - finish = start + sprintf(out,"%.*lg", static_cast<int>(boost::detail::lcast_get_precision<double >()), val ); - return finish > start; + if (put_inf_nan(begin, end, val)) return true; + end = begin + +#if (defined _MSC_VER) + sprintf_s(begin, end-begin, +#else + sprintf(begin, +#endif + "%.*g", static_cast<int>(boost::detail::lcast_get_precision<double>()), val); + return end > begin; } + #ifndef __MINGW32__ - template <class T> - bool shl_long_double(long double val,T* out) + static bool shl_real_type(long double val, char* begin, char*& end) { using namespace std; - if (put_inf_nan(start,finish,val)) return true; - finish = start + sprintf(out,"%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double >()), val ); - return finish > start; - } -#endif - + if (put_inf_nan(begin, end, val)) return true; + end = begin + #if (defined _MSC_VER) -# pragma warning( pop ) + sprintf_s(begin, end-begin, +#else + sprintf(begin, +#endif + "%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double>()), val ); + return end > begin; + } #endif -#ifndef BOOST_LCAST_NO_WCHAR_T - bool shl_float(float val,wchar_t* out) +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__) + static bool shl_real_type(float val, wchar_t* begin, wchar_t*& end) { using namespace std; - if (put_inf_nan(start,finish,val)) return true; - finish = start + swprintf(out, -#if !defined(__MINGW32__) && !defined(UNDER_CE) - finish-start, -#endif - L"%.*g", static_cast<int>(boost::detail::lcast_get_precision<float >()), val ); - - return finish > start; + if (put_inf_nan(begin, end, val)) return true; + const double val_as_double = val; + end = begin + swprintf(begin, end-begin, + L"%.*g", + static_cast<int>(boost::detail::lcast_get_precision<float >()), + val_as_double ); + return end > begin; } - - bool shl_double(double val,wchar_t* out) + static bool shl_real_type(double val, wchar_t* begin, wchar_t*& end) { using namespace std; - if (put_inf_nan(start,finish,val)) return true; - /* __MINGW32__ is defined for both mingw.org and for mingw-w64. - * For mingw-w64, __MINGW64__ is defined, too, when targetting - * 64 bits. - * - * swprintf realization in MinGW and under WinCE does not conform - * to the ISO C - * Standard. - */ - finish = start + swprintf(out, -#if !defined(__MINGW32__) && !defined(UNDER_CE) - finish-start, -#endif - L"%.*lg", static_cast<int>(boost::detail::lcast_get_precision<double >()), val ); - return finish > start; + if (put_inf_nan(begin, end, val)) return true; + end = begin + swprintf(begin, end-begin, + L"%.*g", static_cast<int>(boost::detail::lcast_get_precision<double >()), val ); + return end > begin; } -#ifndef __MINGW32__ - bool shl_long_double(long double val,wchar_t* out) + static bool shl_real_type(long double val, wchar_t* begin, wchar_t*& end) { using namespace std; - if (put_inf_nan(start,finish,val)) return true; - finish = start + swprintf(out, -#if !defined(UNDER_CE) - finish-start, -#endif + if (put_inf_nan(begin, end, val)) return true; + end = begin + swprintf(begin, end-begin, L"%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double >()), val ); - return finish > start; + return end > begin; } #endif -#endif - /************************************ OPERATORS << ( ... ) ********************************/ public: template<class Alloc> @@ -1370,7 +1426,6 @@ namespace boost return true; } -#if !defined(__SUNPRO_CC) template<class Alloc> bool operator<<(::boost::container::basic_string<CharT,Traits,Alloc> const& str) { @@ -1378,7 +1433,7 @@ namespace boost finish = start + str.length(); return true; } -#endif // !defined(__SUNPRO_CC) + bool operator<<(bool value) { CharT const czero = lcast_char_constants<CharT>::zero; @@ -1387,6 +1442,52 @@ namespace boost return true; } + bool operator<<(const iterator_range<CharT*>& rng) + { + start = rng.begin(); + finish = rng.end(); + return true; + } + + bool operator<<(const iterator_range<const CharT*>& rng) + { + start = const_cast<CharT*>(rng.begin()); + finish = const_cast<CharT*>(rng.end()); + return true; + } + + bool operator<<(const iterator_range<const signed char*>& rng) + { + return (*this) << iterator_range<char*>( + const_cast<char*>(reinterpret_cast<const char*>(rng.begin())), + const_cast<char*>(reinterpret_cast<const char*>(rng.end())) + ); + } + + bool operator<<(const iterator_range<const unsigned char*>& rng) + { + return (*this) << iterator_range<char*>( + const_cast<char*>(reinterpret_cast<const char*>(rng.begin())), + const_cast<char*>(reinterpret_cast<const char*>(rng.end())) + ); + } + + bool operator<<(const iterator_range<signed char*>& rng) + { + return (*this) << iterator_range<char*>( + reinterpret_cast<char*>(rng.begin()), + reinterpret_cast<char*>(rng.end()) + ); + } + + bool operator<<(const iterator_range<unsigned char*>& rng) + { + return (*this) << iterator_range<char*>( + reinterpret_cast<char*>(rng.begin()), + reinterpret_cast<char*>(rng.end()) + ); + } + bool operator<<(char ch) { return shl_char(ch); } bool operator<<(unsigned char ch) { return ((*this) << static_cast<char>(ch)); } bool operator<<(signed char ch) { return ((*this) << static_cast<char>(ch)); } @@ -1397,6 +1498,16 @@ namespace boost bool operator<<(wchar_t ch) { return shl_char(ch); } #endif #endif +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) + bool operator<<(char16_t ch) { return shl_char(ch); } + bool operator<<(char16_t * str) { return shl_char_array(str); } + bool operator<<(char16_t const * str) { return shl_char_array(str); } +#endif +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) + bool operator<<(char32_t ch) { return shl_char(ch); } + bool operator<<(char32_t * str) { return shl_char_array(str); } + bool operator<<(char32_t const * str) { return shl_char_array(str); } +#endif bool operator<<(unsigned char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); } bool operator<<(unsigned char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); } bool operator<<(signed char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); } @@ -1417,17 +1528,67 @@ namespace boost bool operator<<(unsigned __int64 n) { start = lcast_put_unsigned<Traits>(n, finish); return true; } bool operator<<( __int64 n) { return shl_signed(n); } #endif - bool operator<<(float val) { return shl_float(val,start); } - bool operator<<(double val) { return shl_double(val,start); } + bool operator<<(float val) { return shl_real_type(val, start, finish); } + bool operator<<(double val) { return shl_real_type(val, start, finish); } bool operator<<(long double val) { #ifndef __MINGW32__ - return shl_long_double(val,start); + return shl_real_type(val, start, finish); #else - return shl_double(val,start); + return shl_real_type(static_cast<double>(val), start, finish); #endif } - - template<class InStreamable> + + template <std::size_t N> + bool operator<<(boost::array<CharT, N> const& input) + { return shl_char_array_limited(input.begin(), N); } + + template <std::size_t N> + bool operator<<(boost::array<unsigned char, N> const& input) + { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); } + + template <std::size_t N> + bool operator<<(boost::array<signed char, N> const& input) + { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); } + + template <std::size_t N> + bool operator<<(boost::array<const CharT, N> const& input) + { return shl_char_array_limited(input.begin(), N); } + + template <std::size_t N> + bool operator<<(boost::array<const unsigned char, N> const& input) + { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); } + + template <std::size_t N> + bool operator<<(boost::array<const signed char, N> const& input) + { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); } + +#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) + template <std::size_t N> + bool operator<<(std::array<CharT, N> const& input) + { return shl_char_array_limited(input.begin(), N); } + + template <std::size_t N> + bool operator<<(std::array<unsigned char, N> const& input) + { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); } + + template <std::size_t N> + bool operator<<(std::array<signed char, N> const& input) + { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); } + + template <std::size_t N> + bool operator<<(std::array<const CharT, N> const& input) + { return shl_char_array_limited(input.begin(), N); } + + template <std::size_t N> + bool operator<<(std::array<const unsigned char, N> const& input) + { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); } + + template <std::size_t N> + bool operator<<(std::array<const signed char, N> const& input) + { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); } +#endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) + + template <class InStreamable> bool operator<<(const InStreamable& input) { return shl_input_streamable(input); } /************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/ @@ -1524,9 +1685,22 @@ namespace boost if(is_pointer<InputStreamable>::value) return false; - local_streambuffer_t bb; - bb.setg(start, start, finish); - std::basic_istream<CharT> stream(&bb); +#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) + // If you have compilation error at this point, than your STL library + // unsupports such conversions. Try updating it. + BOOST_STATIC_ASSERT((boost::is_same<char, CharT>::value)); +#endif + +#if defined(BOOST_NO_STRINGSTREAM) + std::istrstream stream(start, finish - start); +#elif defined(BOOST_NO_STD_LOCALE) + std::istringstream stream; +#else + std::basic_istringstream<CharT, Traits> stream; +#endif + static_cast<unlocked_but_t*>(stream.rdbuf()) + ->setg(start, start, finish); + stream.unsetf(std::ios::skipws); lcast_set_precision(stream, static_cast<InputStreamable*>(0)); #if (defined _MSC_VER) @@ -1549,7 +1723,7 @@ namespace boost inline bool shr_xchar(T& output) { BOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ), - "boost::lexical_cast does not support conversions from whar_t to char types." + "boost::lexical_cast does not support conversions from wchar_t to char types." "Use boost::locale instead" ); bool const ok = (finish - start == 1); if(ok) { @@ -1581,25 +1755,82 @@ namespace boost #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) bool operator>>(wchar_t& output) { return shr_xchar(output); } #endif -#ifndef BOOST_NO_CHAR16_T +#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) bool operator>>(char16_t& output) { return shr_xchar(output); } #endif -#ifndef BOOST_NO_CHAR32_T +#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) bool operator>>(char32_t& output) { return shr_xchar(output); } #endif -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - bool operator>>(std::string& str) { str.assign(start, finish); return true; } -# ifndef BOOST_LCAST_NO_WCHAR_T - bool operator>>(std::wstring& str) { str.assign(start, finish); return true; } -# endif -#else template<class Alloc> bool operator>>(std::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; } -#if !defined(__SUNPRO_CC) + template<class Alloc> bool operator>>(::boost::container::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; } -#endif // !defined(__SUNPRO_CC) -#endif + + + private: + template <std::size_t N, class ArrayT> + bool shr_std_array(ArrayT& output, boost::mpl::bool_<true> /*is_T_char_tag*/) + { + using namespace std; + const std::size_t size = finish - start; + if (size > N - 1) { // `-1` because we need to store \0 at the end + return false; + } + + memcpy(output.begin(), start, size * sizeof(CharT)); + *(output.begin() + size) = static_cast<CharT>(0); + return true; + } + + template <std::size_t N, class ArrayT> + bool shr_std_array(ArrayT& output, boost::mpl::bool_<false> /*is_T_char_tag*/) + { + return shr_using_base_class(output); // Array consist of non character types or unmatching character type + } + public: + + template <std::size_t N> + bool operator>>(boost::array<CharT, N>& output) + { + typedef boost::mpl::bool_<true> tag_type; + return shr_std_array<N>(output, tag_type()); + } + + template <std::size_t N> + bool operator>>(boost::array<unsigned char, N>& output) + { + return ((*this) >> reinterpret_cast<boost::array<char, N>& >(output)); + } + + template <std::size_t N> + bool operator>>(boost::array<signed char, N>& output) + { + return ((*this) >> reinterpret_cast<boost::array<char, N>& >(output)); + } + +#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) + template <std::size_t N> + bool operator>>(std::array<CharT, N>& output) + { + typedef boost::mpl::bool_<true> tag_type; + return shr_std_array<N>(output, tag_type()); + } + + template <std::size_t N> + bool operator>>(std::array<unsigned char, N>& output) + { + return ((*this) >> reinterpret_cast<std::array<char, N>& >(output)); + } + + template <std::size_t N> + bool operator>>(std::array<signed char, N>& in) + { + return ((*this) >> reinterpret_cast<std::array<char, N>& >(output)); + } +#endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) + + /* * case "-0" || "0" || "+0" : output = false; return true; * case "1" || "+1": output = true; return true; @@ -1705,10 +1936,6 @@ namespace boost }; } -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - // call-by-const reference version - namespace detail { template<class T> @@ -1734,49 +1961,12 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value = true ); }; -#if !defined(__SUNPRO_CC) + template<typename CharT, typename Traits, typename Alloc> struct is_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc> > { BOOST_STATIC_CONSTANT(bool, value = true ); }; -#endif // !defined(__SUNPRO_CC) - template<typename T> - struct is_char_or_wchar - { - private: -#ifndef BOOST_LCAST_NO_WCHAR_T - typedef wchar_t wchar_t_if_supported; -#else - typedef char wchar_t_if_supported; -#endif - -#ifndef BOOST_NO_CHAR16_T - typedef char16_t char16_t_if_supported; -#else - typedef char char16_t_if_supported; -#endif - -#ifndef BOOST_NO_CHAR32_T - typedef char32_t char32_t_if_supported; -#else - typedef char char32_t_if_supported; -#endif - public: - - BOOST_STATIC_CONSTANT(bool, value = - ( - ::boost::type_traits::ice_or< - is_same< T, char >::value, - is_same< T, wchar_t_if_supported >::value, - is_same< T, char16_t_if_supported >::value, - is_same< T, char32_t_if_supported >::value, - is_same< T, unsigned char >::value, - is_same< T, signed char >::value - >::value - ) - ); - }; template<typename Target, typename Source> struct is_arithmetic_and_not_xchars @@ -1784,8 +1974,8 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = ( ::boost::type_traits::ice_and< - is_arithmetic<Source>::value, - is_arithmetic<Target>::value, + ::boost::is_arithmetic<Source>::value, + ::boost::is_arithmetic<Target>::value, ::boost::type_traits::ice_not< detail::is_char_or_wchar<Target>::value >::value, @@ -1823,6 +2013,28 @@ namespace boost ); }; + + // this metafunction evaluates to true, if we have optimized comnversion + // from Float type to Char array. + // Must be in sync with lexical_stream_limited_src<Char, ...>::shl_real_type(...) + template <typename Float, typename Char> + struct is_this_float_conversion_optimized + { + typedef ::boost::type_traits::ice_and< + ::boost::is_float<Float>::value, +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__) + ::boost::type_traits::ice_or< + ::boost::type_traits::ice_eq<sizeof(Char), sizeof(char) >::value, + ::boost::is_same<Char, wchar_t>::value + >::value +#else + ::boost::type_traits::ice_eq<sizeof(Char), sizeof(char) >::value +#endif + > result_type; + + BOOST_STATIC_CONSTANT(bool, value = (result_type::value) ); + }; + template<typename Target, typename Source> struct is_char_array_to_stdstring { @@ -1840,7 +2052,7 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value = true ); }; -#if !defined(__SUNPRO_CC) + template<typename CharT, typename Traits, typename Alloc> struct is_char_array_to_stdstring< ::boost::container::basic_string<CharT, Traits, Alloc>, CharT* > { @@ -1852,7 +2064,6 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value = true ); }; -#endif // !defined(__SUNPRO_CC) #if (defined _MSC_VER) # pragma warning( push ) @@ -1866,59 +2077,64 @@ namespace boost static inline Target lexical_cast_impl(const Source& arg) { typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay<Source>::type src; - + typedef BOOST_DEDUCED_TYPENAME ::boost::remove_cv<src>::type no_cv_src; + typedef BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type target_char_t; + typedef BOOST_DEDUCED_TYPENAME detail::stream_char<no_cv_src>::type src_char_type; typedef BOOST_DEDUCED_TYPENAME detail::widest_char< - BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type - , BOOST_DEDUCED_TYPENAME detail::stream_char<src>::type + target_char_t, src_char_type >::type char_type; - typedef detail::lcast_src_length<src> lcast_src_length; - std::size_t const src_len = lcast_src_length::value; - char_type buf[src_len + 1]; - lcast_src_length::check_coverage(); +#if !defined(BOOST_NO_CHAR16_T) && defined(BOOST_NO_UNICODE_LITERALS) + BOOST_STATIC_ASSERT_MSG(( !::boost::is_same<char16_t, src_char_type>::value + && !::boost::is_same<char16_t, target_char_t>::value), + "Your compiler does not have full support for char16_t" ); +#endif +#if !defined(BOOST_NO_CHAR32_T) && defined(BOOST_NO_UNICODE_LITERALS) + BOOST_STATIC_ASSERT_MSG(( !::boost::is_same<char32_t, src_char_type>::value + && !::boost::is_same<char32_t, target_char_t>::value), + "Your compiler does not have full support for char32_t" ); +#endif - typedef BOOST_DEDUCED_TYPENAME - deduce_char_traits<char_type,Target,Source>::type traits; + typedef BOOST_DEDUCED_TYPENAME ::boost::detail::deduce_char_traits< + char_type, Target, no_cv_src + >::type traits; - typedef BOOST_DEDUCED_TYPENAME remove_pointer<src >::type removed_ptr_t; + typedef ::boost::type_traits::ice_and< + ::boost::detail::is_char_or_wchar<src_char_type>::value, // source is lexical type + ::boost::detail::is_char_or_wchar<target_char_t>::value, // target is a lexical type + ::boost::is_same<char, src_char_type>::value, // source is not a wide character based type + ::boost::type_traits::ice_ne<sizeof(char), sizeof(target_char_t) >::value // target type is based on wide character + > is_string_widening_required_t; - // is_char_types_match variable value can be computed via - // sizeof(char_type) == sizeof(removed_ptr_t). But when - // removed_ptr_t is an incomplete type or void*, compilers - // produce warnings or errors. - const bool is_char_types_match = - (::boost::type_traits::ice_or< - ::boost::type_traits::ice_and< - ::boost::type_traits::ice_eq<sizeof(char_type), sizeof(char) >::value, - ::boost::type_traits::ice_or< - ::boost::is_same<char, removed_ptr_t>::value, - ::boost::is_same<unsigned char, removed_ptr_t>::value, - ::boost::is_same<signed char, removed_ptr_t>::value - >::value - >::value, - is_same<char_type, removed_ptr_t>::value - >::value); - - const bool requires_stringbuf = - !( - ::boost::type_traits::ice_or< - is_stdstring<src >::value, - is_arithmetic<src >::value, - ::boost::type_traits::ice_and< - is_pointer<src >::value, - is_char_or_wchar<removed_ptr_t >::value, - is_char_types_match - >::value - >::value - ); - - detail::lexical_stream_limited_src<char_type,traits, requires_stringbuf > - interpreter(buf, buf + src_len); + typedef ::boost::type_traits::ice_or< + ::boost::is_integral<no_cv_src>::value, + ::boost::detail::is_this_float_conversion_optimized<no_cv_src, char_type >::value, + ::boost::detail::is_char_or_wchar<src_char_type >::value + > is_source_input_optimized_t; + // Target type must be default constructible Target result; + + // If we have an optimized conversion for + // Source, we do not need to construct stringbuf. + const bool requires_stringbuf = ::boost::type_traits::ice_or< + is_string_widening_required_t::value, + ::boost::type_traits::ice_not< is_source_input_optimized_t::value >::value + >::value; + + typedef detail::lexical_stream_limited_src<char_type, traits, requires_stringbuf > interpreter_type; + + typedef detail::lcast_src_length<no_cv_src> lcast_src_length; + std::size_t const src_len = lcast_src_length::value; + char_type buf[src_len + 1]; + lcast_src_length::check_coverage(); + + interpreter_type interpreter(buf, buf + src_len); + // Disabling ADL, by directly specifying operators. if(!(interpreter.operator <<(arg) && interpreter.operator >>(result))) BOOST_LCAST_THROW_BAD_CAST(Source, Target); + return result; } }; @@ -1926,7 +2142,7 @@ namespace boost # pragma warning( pop ) #endif - template<typename Source> + template <typename Source> struct lexical_cast_copy { static inline Source lexical_cast_impl(const Source &arg) @@ -1935,79 +2151,71 @@ namespace boost } }; - class precision_loss_error : public boost::numeric::bad_numeric_cast + template <class Source, class Target > + struct detect_precision_loss { - public: - virtual const char * what() const throw() - { return "bad numeric conversion: precision loss error"; } - }; + typedef boost::numeric::Trunc<Source> Rounder; + typedef Source source_type ; - template<class S > - struct throw_on_precision_loss - { - typedef boost::numeric::Trunc<S> Rounder; - typedef S source_type ; - - typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ; + typedef BOOST_DEDUCED_TYPENAME mpl::if_< + ::boost::is_arithmetic<Source>, Source, Source const& + >::type argument_type ; static source_type nearbyint ( argument_type s ) { - source_type orig_div_round = s / Rounder::nearbyint(s); + const source_type orig_div_round = s / Rounder::nearbyint(s); + const source_type eps = std::numeric_limits<source_type>::epsilon(); + + if ((orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > eps) + BOOST_LCAST_THROW_BAD_CAST(Source, Target); - if ( (orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > std::numeric_limits<source_type>::epsilon() ) - BOOST_THROW_EXCEPTION( precision_loss_error() ); return s ; } typedef typename Rounder::round_style round_style; } ; - template<typename Target, typename Source> + template <class Source, class Target > + struct nothrow_overflow_handler + { + void operator() ( boost::numeric::range_check_result r ) + { + if (r != boost::numeric::cInRange) + BOOST_LCAST_THROW_BAD_CAST(Source, Target); + } + } ; + + template <typename Target, typename Source> struct lexical_cast_dynamic_num_not_ignoring_minus { static inline Target lexical_cast_impl(const Source &arg) { - try{ - typedef boost::numeric::converter< - Target, - Source, - boost::numeric::conversion_traits<Target,Source>, - boost::numeric::def_overflow_handler, - throw_on_precision_loss<Source> - > Converter ; - - return Converter::convert(arg); - } catch( ::boost::numeric::bad_numeric_cast const& ) { - BOOST_LCAST_THROW_BAD_CAST(Source, Target); - } - BOOST_UNREACHABLE_RETURN(static_cast<Target>(0)); + return boost::numeric::converter< + Target, + Source, + boost::numeric::conversion_traits<Target,Source>, + nothrow_overflow_handler<Source, Target>, + detect_precision_loss<Source, Target> + >::convert(arg); } }; - template<typename Target, typename Source> + template <typename Target, typename Source> struct lexical_cast_dynamic_num_ignoring_minus { static inline Target lexical_cast_impl(const Source &arg) { - try{ - typedef boost::numeric::converter< - Target, - Source, - boost::numeric::conversion_traits<Target,Source>, - boost::numeric::def_overflow_handler, - throw_on_precision_loss<Source> - > Converter ; - - bool has_minus = ( arg < 0); - if ( has_minus ) { - return static_cast<Target>(-Converter::convert(-arg)); - } else { - return Converter::convert(arg); - } - } catch( ::boost::numeric::bad_numeric_cast const& ) { - BOOST_LCAST_THROW_BAD_CAST(Source, Target); - } - BOOST_UNREACHABLE_RETURN(static_cast<Target>(0)); + typedef boost::numeric::converter< + Target, + Source, + boost::numeric::conversion_traits<Target,Source>, + nothrow_overflow_handler<Source, Target>, + detect_precision_loss<Source, Target> + > converter_t; + + return ( + arg < 0 ? -converter_t::convert(-arg) : converter_t::convert(arg) + ); } }; @@ -2029,7 +2237,7 @@ namespace boost * optional, so if a negative number is read, no errors will arise * and the result will be the two's complement. */ - template<typename Target, typename Source> + template <typename Target, typename Source> struct lexical_cast_dynamic_num { static inline Target lexical_cast_impl(const Source &arg) @@ -2041,10 +2249,10 @@ namespace boost ::boost::is_float<Source>::value >::value, ::boost::type_traits::ice_not< - is_same<Source, bool>::value + ::boost::is_same<Source, bool>::value >::value, ::boost::type_traits::ice_not< - is_same<Target, bool>::value + ::boost::is_same<Target, bool>::value >::value, ::boost::is_unsigned<Target>::value >::value, @@ -2057,40 +2265,80 @@ namespace boost }; } - template<typename Target, typename Source> + template <typename Target, typename Source> inline Target lexical_cast(const Source &arg) { - typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay<Source>::type src; + typedef BOOST_DEDUCED_TYPENAME ::boost::detail::array_to_pointer_decay<Source>::type src; typedef BOOST_DEDUCED_TYPENAME ::boost::type_traits::ice_or< - detail::is_xchar_to_xchar<Target, src>::value, - detail::is_char_array_to_stdstring<Target,src>::value, + ::boost::detail::is_xchar_to_xchar<Target, src >::value, + ::boost::detail::is_char_array_to_stdstring<Target, src >::value, ::boost::type_traits::ice_and< - is_same<Target, src>::value, - detail::is_stdstring<Target>::value + ::boost::is_same<Target, src >::value, + ::boost::detail::is_stdstring<Target >::value >::value - > do_copy_type; + > shall_we_copy_t; typedef BOOST_DEDUCED_TYPENAME - detail::is_arithmetic_and_not_xchars<Target, src> do_copy_with_dynamic_check_type; + ::boost::detail::is_arithmetic_and_not_xchars<Target, src > shall_we_copy_with_dynamic_check_t; typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< - do_copy_type::value, - detail::lexical_cast_copy<src>, + shall_we_copy_t::value, + ::boost::detail::lexical_cast_copy<src >, BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< - do_copy_with_dynamic_check_type::value, - detail::lexical_cast_dynamic_num<Target, src>, - detail::lexical_cast_do_cast<Target, src> + shall_we_copy_with_dynamic_check_t::value, + ::boost::detail::lexical_cast_dynamic_num<Target, src >, + ::boost::detail::lexical_cast_do_cast<Target, src > >::type >::type caster_type; return caster_type::lexical_cast_impl(arg); } - #else +} // namespace boost + +#else // #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - namespace detail // stream wrapper for handling lexical conversions +namespace boost { + namespace detail { + + // selectors for choosing stream character type + template<typename Type> + struct stream_char + { + typedef char type; + }; + +#ifndef BOOST_LCAST_NO_WCHAR_T +#ifndef BOOST_NO_INTRINSIC_WCHAR_T + template<> + struct stream_char<wchar_t> + { + typedef wchar_t type; + }; +#endif + + template<> + struct stream_char<wchar_t *> + { + typedef wchar_t type; + }; + + template<> + struct stream_char<const wchar_t *> + { + typedef wchar_t type; + }; + + template<> + struct stream_char<std::wstring> + { + typedef wchar_t type; + }; +#endif + + // stream wrapper for handling lexical conversions template<typename Target, typename Source, typename Traits> class lexical_stream { @@ -2180,8 +2428,9 @@ namespace boost return result; } - #endif -} +} // namespace boost + +#endif // Copyright Kevlin Henney, 2000-2005. // Copyright Alexander Nasonov, 2006-2010. @@ -2191,5 +2440,8 @@ namespace boost // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#undef BOOST_LCAST_THROW_BAD_CAST #undef BOOST_LCAST_NO_WCHAR_T -#endif + +#endif // BOOST_LEXICAL_CAST_INCLUDED + |