diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 58fdea8..e3e0632 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -1003,6 +1005,7 @@ namespace boost // String representation of Source has an upper limit. template< class CharT // a result of widest_char transformation , class Traits // usually char_traits + , bool RequiresStringbuffer > class lexical_stream_limited_src { @@ -1015,25 +1018,23 @@ namespace boost #else typedef stl_buf_unlocker, CharT > local_stringbuffer_t; #endif + typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< + RequiresStringbuffer, + local_stringbuffer_t, + char + >::type deduced_stringbuffer_t; + // A string representation of Source is written to [start, finish). - // Currently, it is assumed that [start, finish) is big enough - // to hold a string representation of any Source value. CharT* start; CharT* finish; - local_stringbuffer_t *stringbuf; + deduced_stringbuffer_t stringbuffer; public: lexical_stream_limited_src(CharT* sta, CharT* fin) : start(sta) , finish(fin) - , stringbuf(NULL) {} - ~lexical_stream_limited_src() - { - if (stringbuf) delete stringbuf; - } - private: // Undefined: lexical_stream_limited_src(lexical_stream_limited_src const&); @@ -1078,7 +1079,7 @@ namespace boost bool shl_char_array(T const* str) { 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 wchar_t to char types." "Use boost::locale instead" ); return shl_input_streamable(str); } @@ -1087,15 +1088,10 @@ namespace boost template bool shl_input_streamable(InputStreamable& input) { - /* No one will call this function twice, - * so we do not need `if (!stringbuf)' */ - stringbuf = new local_stringbuffer_t(); - - std::basic_ostream stream(stringbuf); - lcast_set_precision(stream, static_cast(0)); + std::basic_ostream stream(&stringbuffer); bool const result = !(stream << input).fail(); - start = stringbuf->pbase(); - finish = stringbuf->pptr(); + start = stringbuffer.pbase(); + finish = stringbuffer.pptr(); return result; } @@ -1112,18 +1108,44 @@ namespace boost return true; } -#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION template - bool shl_float_types(T val) - { - if (put_inf_nan(start, finish, val)) return true; - local_streambuffer_t bb; - bb.setp(start, finish); - std::basic_ostream stream(&bb); - lcast_set_precision(stream, &val); - bool const result = !(stream << val).fail(); - finish = bb.pptr(); - return result; + bool shl_float(float val,T* out) + { using namespace std; + finish = start + sprintf(out,"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); + return finish > start; + } + + template + bool shl_double(double val,T* out) + { using namespace std; + finish = start + sprintf(out,"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); + return finish > start; + } + + template + bool shl_long_double(long double val,T* out) + { using namespace std; + finish = start + sprintf(out,"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); + return finish > start; + } + +#ifndef BOOST_LCAST_NO_WCHAR_T + bool shl_float(float val,wchar_t* out) + { using namespace std; + finish = start + swprintf(out,finish-start,L"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); + return finish > start; + } + + bool shl_double(double val,wchar_t* out) + { using namespace std; + finish = start + swprintf(out,finish-start,L"%.*lg", static_cast(boost::detail::lcast_get_precision()), val ); + return finish > start; + } + + bool shl_long_double(long double val,wchar_t* out) + { using namespace std; + finish = start + swprintf(out,finish-start,L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); + return finish > start; } #endif @@ -1171,11 +1193,9 @@ namespace boost bool operator<<(unsigned __int64 n) { start = lcast_put_unsigned(n, finish); return true; } bool operator<<( __int64 n) { return shl_signed(n); } #endif -#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION - bool operator<<(float val) { return shl_float_types(val); } - bool operator<<(double val) { return shl_float_types(val); } - bool operator<<(long double val) { return shl_float_types(val); } -#endif // BOOST_LCAST_NO_COMPILE_TIME_PRECISION + bool operator<<(float val) { return shl_float(val,start); } + bool operator<<(double val) { return shl_double(val,start); } + bool operator<<(long double val) { return shl_long_double(val,start); } template bool operator<<(const InStreamable& input) { return shl_input_streamable(input); } @@ -1586,7 +1606,25 @@ namespace boost typedef BOOST_DEDUCED_TYPENAME deduce_char_traits::type traits; - detail::lexical_stream_limited_src interpreter(buf, buf + src_len); + typedef BOOST_DEDUCED_TYPENAME remove_pointer::type removed_ptr_t; + const bool requires_stringbuf = + !( + ::boost::type_traits::ice_or< + is_stdstring::value, + is_arithmetic::value, + ::boost::type_traits::ice_and< + is_pointer::value, + is_char_or_wchar::value, + ::boost::type_traits::ice_eq< + sizeof(char_type), + sizeof(removed_ptr_t) + >::value + >::value + >::value + ); + + detail::lexical_stream_limited_src + interpreter(buf, buf + src_len); Target result; if(!(interpreter << arg && interpreter >> result))