diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 99aeb24..58fdea8 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -47,7 +46,12 @@ #include #ifndef BOOST_NO_STD_LOCALE -#include +# include +#else +# ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE +# warning "Unable to use header. boost::lexical_cast will use the 'C' locale." +# define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE +# endif #endif #ifdef BOOST_NO_STRINGSTREAM @@ -223,156 +227,17 @@ namespace boost namespace detail // lcast_src_length { // Return max. length of string representation of Source; - // 0 if unlimited (with exceptions for some types, see below). - // Values with limited string representation are placed to - // the buffer locally defined in lexical_cast function. - // 1 is returned for few types such as CharT const* or - // std::basic_string that already have an internal - // buffer ready to be reused by lexical_stream_limited_src. - // Each specialization should have a correspondent operator<< - // defined in lexical_stream_limited_src. template< class CharT // A result of widest_char transformation. , class Source // Source type of lexical_cast. > struct lcast_src_length { - BOOST_STATIC_CONSTANT(std::size_t, value = 0); + BOOST_STATIC_CONSTANT(std::size_t, value = 1); // To check coverage, build the test with // bjam --v2 profile optimization=off static void check_coverage() {} }; - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - -#ifndef BOOST_LCAST_NO_WCHAR_T - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - -#ifndef BOOST_NO_INTRINSIC_WCHAR_T - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; -#endif -#endif - - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - -#ifndef BOOST_LCAST_NO_WCHAR_T - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - - template<> - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; -#endif - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct lcast_src_length< CharT, std::basic_string > - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; -#else - template<> - struct lcast_src_length< char, std::basic_string > - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; - -#ifndef BOOST_LCAST_NO_WCHAR_T - template<> - struct lcast_src_length< wchar_t, std::basic_string > - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - static void check_coverage() {} - }; -#endif -#endif - // Helper for integral types. // Notes on length calculation: // Max length for 32bit int with grouping "\1" and thousands_sep ',': @@ -530,13 +395,6 @@ namespace boost #endif } - namespace detail // lexical_streambuf_fake - { - struct lexical_streambuf_fake - { - }; - } - namespace detail // lcast_to_unsigned { #if (defined _MSC_VER) @@ -575,7 +433,6 @@ namespace boost int_type const zero = Traits::to_int_type(czero); #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - // TODO: use BOOST_NO_STD_LOCALE std::locale loc; typedef std::numpunct numpunct; numpunct const& np = BOOST_USE_FACET(numpunct, loc); @@ -654,7 +511,6 @@ namespace boost T multiplier = 1; #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - // TODO: use BOOST_NO_STD_LOCALE std::locale loc; typedef std::numpunct numpunct; numpunct const& np = BOOST_USE_FACET(numpunct, loc); @@ -911,7 +767,6 @@ namespace boost { #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - // TODO: use BOOST_NO_STD_LOCALE std::locale loc; typedef std::numpunct numpunct; numpunct const& np = BOOST_USE_FACET(numpunct, loc); @@ -1115,7 +970,7 @@ namespace boost * with long doubles (and with doubles if sizeof(double)==sizeof(long double)). */ long double result = std::pow(10.0L, pow_of_10) * mantissa; - value = static_cast( has_minus ? -1 * result : result); + value = static_cast( has_minus ? (boost::math::changesign)(result) : result); if ( (boost::math::isinf)(value) || (boost::math::isnan)(value) ) return false; @@ -1123,92 +978,23 @@ namespace boost } } - namespace detail // stream wrapper for handling lexical conversions + namespace detail // stl_buf_unlocker { - template - class lexical_stream - { - private: - typedef typename widest_char< - typename stream_char::type, - typename stream_char::type>::type char_type; - - typedef Traits traits_type; - + template< class BufferType, class CharT > + class stl_buf_unlocker: public BufferType{ public: - lexical_stream(char_type* = 0, char_type* = 0) - { - stream.unsetf(std::ios::skipws); - lcast_set_precision(stream, static_cast(0), static_cast(0) ); - } - ~lexical_stream() - { - #if defined(BOOST_NO_STRINGSTREAM) - stream.freeze(false); - #endif - } - bool operator<<(const Source &input) - { - return !(stream << input).fail(); - } - template - bool operator>>(InputStreamable &output) - { - return !is_pointer::value && - stream >> output && - stream.get() == -#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) -// GCC 2.9x lacks std::char_traits<>::eof(). -// We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 -// configurations, which do provide std::char_traits<>::eof(). - - EOF; + typedef BufferType base_class; +#ifndef BOOST_NO_USING_TEMPLATE + using base_class::pptr; + using base_class::pbase; + using base_class::setg; + using base_class::setp; #else - traits_type::eof(); + CharT* pptr() const { return base_class::pptr(); } + CharT* pbase() const { return base_class::pbase(); } + void setg(CharT* gbeg, CharT* gnext, CharT* gend){ return base_class::setg(gbeg, gnext, gend); } + void setp(CharT* pbeg, CharT* pend) { return setp(pbeg, pend); } #endif - } - -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - bool operator>>(std::string &output) - { - #if defined(BOOST_NO_STRINGSTREAM) - stream << '\0'; - #endif - stream.str().swap(output); - return true; - } - #ifndef BOOST_LCAST_NO_WCHAR_T - bool operator>>(std::wstring &output) - { - stream.str().swap(output); - return true; - } - #endif - -#else - bool operator>>(std::basic_string& output) - { - stream.str().swap(output); - return true; - } - - template - bool operator>>(std::basic_string& out) - { - std::basic_string str(stream.str()); - out.assign(str.begin(), str.end()); - return true; - } -#endif - private: - #if defined(BOOST_NO_STRINGSTREAM) - std::strstream stream; - #elif defined(BOOST_NO_STD_LOCALE) - std::stringstream stream; - #else - std::basic_stringstream stream; - #endif }; } @@ -1216,66 +1002,133 @@ namespace boost { // String representation of Source has an upper limit. template< class CharT // a result of widest_char transformation - , class Base // lexical_streambuf_fake or basic_streambuf , class Traits // usually char_traits > - class lexical_stream_limited_src : public Base + class lexical_stream_limited_src { + typedef stl_buf_unlocker, CharT > local_streambuffer_t; + +#if defined(BOOST_NO_STRINGSTREAM) + typedef stl_buf_unlocker local_stringbuffer_t; +#elif defined(BOOST_NO_STD_LOCALE) + typedef stl_buf_unlocker local_stringbuffer_t; +#else + typedef stl_buf_unlocker, CharT > local_stringbuffer_t; +#endif // 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; + + public: + lexical_stream_limited_src(CharT* sta, CharT* fin) + : start(sta) + , finish(fin) + , stringbuf(NULL) + {} + + ~lexical_stream_limited_src() + { + if (stringbuf) delete stringbuf; + } private: - - static void widen_and_assign(char*p, char ch) - { - Traits::assign(*p, ch); - } - -#ifndef BOOST_LCAST_NO_WCHAR_T - static void widen_and_assign(wchar_t* p, char ch) - { - // TODO: use BOOST_NO_STD_LOCALE - std::locale loc; - wchar_t w = BOOST_USE_FACET(std::ctype, loc).widen(ch); - Traits::assign(*p, w); - } - - static void widen_and_assign(wchar_t* p, wchar_t ch) - { - Traits::assign(*p, ch); - } - - static void widen_and_assign(char*, wchar_t ch); // undefined -#endif - - template - bool lcast_put(const OutputStreamable& input) - { - if(put_inf_nan(start, finish, input)) return true; - this->setp(start, finish); - std::basic_ostream stream(static_cast(this)); - lcast_set_precision(stream, static_cast(0)); - bool const result = !(stream << input).fail(); - finish = this->pptr(); - return result; - } - // Undefined: lexical_stream_limited_src(lexical_stream_limited_src const&); void operator=(lexical_stream_limited_src const&); +/************************************ HELPER FUNCTIONS FOR OPERATORS << ( ... ) ********************************/ + bool shl_char(CharT ch) + { + Traits::assign(*start, ch); + finish = start + 1; + return true; + } + +#ifndef BOOST_LCAST_NO_WCHAR_T + template + 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." + "Use boost::locale instead" ); +#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE + std::locale loc; + wchar_t w = BOOST_USE_FACET(std::ctype, loc).widen(ch); +#else + wchar_t w = ch; +#endif + Traits::assign(*start, w); + finish = start + 1; + return true; + } +#endif + + bool shl_char_array(CharT const* str) + { + start = const_cast(str); + finish = start + Traits::length(str); + return true; + } + +#ifndef BOOST_LCAST_NO_WCHAR_T + template + 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." + "Use boost::locale instead" ); + return shl_input_streamable(str); + } +#endif + + 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)); + bool const result = !(stream << input).fail(); + start = stringbuf->pbase(); + finish = stringbuf->pptr(); + return result; + } + + template + inline bool shl_signed(T n) + { + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + if(n < 0) + { + --start; + CharT const minus = lcast_char_constants::minus; + Traits::assign(*start, minus); + } + 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; + } +#endif + +/************************************ OPERATORS << ( ... ) ********************************/ public: - - lexical_stream_limited_src(CharT* sta, CharT* fin) - : start(sta) - , finish(fin) - {} - - public: // output - template bool operator<<(std::basic_string const& str) { @@ -1284,39 +1137,53 @@ namespace boost return true; } - bool operator<<(bool); - bool operator<<(char); - bool operator<<(unsigned char); - bool operator<<(signed char); -#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) - bool operator<<(wchar_t); + bool operator<<(bool value) + { + CharT const czero = lcast_char_constants::zero; + Traits::assign(*start, Traits::to_char_type(czero + value)); + finish = start + 1; + return true; + } + + bool operator<<(char ch) { return shl_char(ch); } + bool operator<<(unsigned char ch) { return ((*this) << static_cast(ch)); } + bool operator<<(signed char ch) { return ((*this) << static_cast(ch)); } +#if !defined(BOOST_LCAST_NO_WCHAR_T) + bool operator<<(wchar_t const* str) { return shl_char_array(str); } +#ifndef BOOST_NO_INTRINSIC_WCHAR_T + bool operator<<(wchar_t ch) { return shl_char(ch); } #endif - bool operator<<(unsigned char const*); - bool operator<<(signed char const*); - bool operator<<(CharT const*); - bool operator<<(short); - bool operator<<(int); - bool operator<<(long); - bool operator<<(unsigned short); - bool operator<<(unsigned int); - bool operator<<(unsigned long); +#endif + bool operator<<(unsigned char const* ch) { return ((*this) << reinterpret_cast(ch)); } + bool operator<<(signed char const* ch) { return ((*this) << reinterpret_cast(ch)); } + bool operator<<(char const* str) { return shl_char_array(str); } + bool operator<<(short n) { return shl_signed(n); } + bool operator<<(int n) { return shl_signed(n); } + bool operator<<(long n) { return shl_signed(n); } + bool operator<<(unsigned short n) { start = lcast_put_unsigned(n, finish); return true; } + bool operator<<(unsigned int n) { start = lcast_put_unsigned(n, finish); return true; } + bool operator<<(unsigned long n) { start = lcast_put_unsigned(n, finish); return true; } + #if defined(BOOST_HAS_LONG_LONG) - bool operator<<(boost::ulong_long_type); - bool operator<<(boost::long_long_type ); + bool operator<<(boost::ulong_long_type n) { start = lcast_put_unsigned(n, finish); return true; } + bool operator<<(boost::long_long_type n) { return shl_signed(n); } #elif defined(BOOST_HAS_MS_INT64) - bool operator<<(unsigned __int64); - bool operator<<( __int64); + bool operator<<(unsigned __int64 n) { start = lcast_put_unsigned(n, finish); return true; } + bool operator<<( __int64 n) { return shl_signed(n); } #endif - // These three operators use ostream and streambuf. - // lcast_streambuf_for_source::value is true. - bool operator<<(float); - bool operator<<(double); - bool operator<<(long double); +#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 + template + bool operator<<(const InStreamable& input) { return shl_input_streamable(input); } + +/************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/ private: - template - bool input_operator_helper_unsigned(Type& output) + bool shr_unsigned(Type& output) { CharT const minus = lcast_char_constants::minus; CharT const plus = lcast_char_constants::plus; @@ -1350,7 +1217,7 @@ namespace boost } template - bool input_operator_helper_signed(Type& output) + bool shr_signed(Type& output) { CharT const minus = lcast_char_constants::minus; CharT const plus = lcast_char_constants::plus; @@ -1393,63 +1260,81 @@ namespace boost return succeed; } - public: // input - - bool operator>>(unsigned short& output) + template + bool shr_using_base_class(InputStreamable& output) { - return input_operator_helper_unsigned(output); +#if (defined _MSC_VER) +# pragma warning( push ) + // conditional expression is constant +# pragma warning( disable : 4127 ) +#endif + if(is_pointer::value) + return false; + + local_streambuffer_t bb; + bb.setg(start, start, finish); + std::basic_istream stream(&bb); + stream.unsetf(std::ios::skipws); + lcast_set_precision(stream, static_cast(0)); +#if (defined _MSC_VER) +# pragma warning( pop ) +#endif + return stream >> output && + stream.get() == +#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) + // GCC 2.9x lacks std::char_traits<>::eof(). + // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 + // configurations, which do provide std::char_traits<>::eof(). + + EOF; +#else + Traits::eof(); +#endif } - bool operator>>(unsigned int& output) + template + inline bool shr_xchar(T& output) { - return input_operator_helper_unsigned(output); + BOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ), + "boost::lexical_cast does not support conversions from whar_t to char types." + "Use boost::locale instead" ); + bool const ok = (finish - start == 1); + if(ok) { + CharT out; + Traits::assign(out, *start); + output = static_cast(out); + } + return ok; } - bool operator>>(unsigned long int& output) - { - return input_operator_helper_unsigned(output); - } - - bool operator>>(short& output) - { - return input_operator_helper_signed(output); - } - - bool operator>>(int& output) - { - return input_operator_helper_signed(output); - } - - bool operator>>(long int& output) - { - return input_operator_helper_signed(output); - } - - +/************************************ OPERATORS >> ( ... ) ********************************/ + public: + bool operator>>(unsigned short& output) { return shr_unsigned(output); } + bool operator>>(unsigned int& output) { return shr_unsigned(output); } + bool operator>>(unsigned long int& output) { return shr_unsigned(output); } + bool operator>>(short& output) { return shr_signed(output); } + bool operator>>(int& output) { return shr_signed(output); } + bool operator>>(long int& output) { return shr_signed(output); } #if defined(BOOST_HAS_LONG_LONG) - bool operator>>( boost::ulong_long_type& output) - { - return input_operator_helper_unsigned(output); - } - - bool operator>>(boost::long_long_type& output) - { - return input_operator_helper_signed(output); - } - + bool operator>>(boost::ulong_long_type& output) { return shr_unsigned(output); } + bool operator>>(boost::long_long_type& output) { return shr_signed(output); } #elif defined(BOOST_HAS_MS_INT64) - bool operator>>(unsigned __int64& output) - { - return input_operator_helper_unsigned(output); - } - - bool operator>>(__int64& output) - { - return input_operator_helper_signed(output); - } + bool operator>>(unsigned __int64& output) { return shr_unsigned(output); } + bool operator>>(__int64& output) { return shr_signed(output); } #endif - + bool operator>>(CharT& output) { return shr_xchar(output); } + bool operator>>(unsigned char& output) { return shr_xchar(output); } + bool operator>>(signed char& output) { return shr_xchar(output); } +#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 + bool operator>>(std::basic_string& str) { str.assign(start, finish); return true; } +#endif /* * case "-0" || "0" || "+0" : output = false; return true; * case "1" || "+1": output = true; return true; @@ -1484,22 +1369,17 @@ namespace boost } } - bool operator>>(float& output) - { - return lcast_ret_float(output,start,finish); - } + bool operator>>(float& output) { return lcast_ret_float(output,start,finish); } private: // Not optimised converter template bool float_types_converter_internal(T& output, int /*tag*/) { - if (parse_inf_nan(start, finish, output)) return true; - - bool return_value = convert_using_base_class(output); + bool return_value = shr_using_base_class(output); /* Some compilers and libraries successfully - * parse '1.0E', '1.0E-'... + * parse 'inf', 'INFINITY', '1.0E', '1.0E-'... * We are trying to provide a unified behaviour, * so we just forbid such conversions (as some * of the most popular compilers/libraries do) @@ -1556,424 +1436,11 @@ namespace boost // Generic istream-based algorithm. // lcast_streambuf_for_target::value is true. template - bool operator>>(InputStreamable& output) - { - return convert_using_base_class(output); - } - - private: - template - bool convert_using_base_class(InputStreamable& output) - { -#if (defined _MSC_VER) -# pragma warning( push ) - // conditional expression is constant -# pragma warning( disable : 4127 ) -#endif - if(is_pointer::value) - return false; - - this->setg(start, start, finish); - std::basic_istream stream(static_cast(this)); - stream.unsetf(std::ios::skipws); - lcast_set_precision(stream, static_cast(0)); -#if (defined _MSC_VER) -# pragma warning( pop ) -#endif - return stream >> output && - stream.get() == -#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) - // GCC 2.9x lacks std::char_traits<>::eof(). - // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 - // configurations, which do provide std::char_traits<>::eof(). - - EOF; -#else - Traits::eof(); -#endif - } - public: - - bool operator>>(CharT&); - bool operator>>(unsigned char&); - bool operator>>(signed char&); - -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -// This #if is in sync with lcast_streambuf_for_target - - bool operator>>(std::string&); - -#ifndef BOOST_LCAST_NO_WCHAR_T - bool operator>>(std::wstring&); -#endif - -#else - template - bool operator>>(std::basic_string& str) - { - str.assign(start, finish); - return true; - } -#endif - }; - - template - inline bool lexical_stream_limited_src::operator<<( - bool value) - { - typedef typename Traits::int_type int_type; - CharT const czero = lcast_char_constants::zero; - int_type const zero = Traits::to_int_type(czero); - Traits::assign(*start, Traits::to_char_type(zero + value)); - finish = start + 1; - return true; - } - - template - inline bool lexical_stream_limited_src::operator<<( - char ch) - { - widen_and_assign(start, ch); - finish = start + 1; - return true; - } - - template - inline bool lexical_stream_limited_src::operator<<( - unsigned char ch) - { - return ((*this) << static_cast(ch)); - } - - template - inline bool lexical_stream_limited_src::operator<<( - signed char ch) - { - return ((*this) << static_cast(ch)); - } - - template - inline bool lexical_stream_limited_src::operator<<( - unsigned char const* ch) - { - return ((*this) << reinterpret_cast(ch)); - } - - template - inline bool lexical_stream_limited_src::operator<<( - signed char const* ch) - { - return ((*this) << reinterpret_cast(ch)); - } - -#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) - template - inline bool lexical_stream_limited_src::operator<<( - wchar_t ch) - { - widen_and_assign(start, ch); - finish = start + 1; - return true; - } -#endif - - template - inline bool lexical_stream_limited_src::operator<<( - short n) - { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); - if(n < 0) - { - --start; - CharT const minus = lcast_char_constants::minus; - Traits::assign(*start, minus); - } - return true; - } - - template - inline bool lexical_stream_limited_src::operator<<( - int n) - { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); - if(n < 0) - { - --start; - CharT const minus = lcast_char_constants::minus; - Traits::assign(*start, minus); - } - return true; - } - - template - inline bool lexical_stream_limited_src::operator<<( - long n) - { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); - if(n < 0) - { - --start; - CharT const minus = lcast_char_constants::minus; - Traits::assign(*start, minus); - } - return true; - } - -#if defined(BOOST_HAS_LONG_LONG) - template - inline bool lexical_stream_limited_src::operator<<( - boost::long_long_type n) - { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); - if(n < 0) - { - --start; - CharT const minus = lcast_char_constants::minus; - Traits::assign(*start, minus); - } - return true; - } -#elif defined(BOOST_HAS_MS_INT64) - template - inline bool lexical_stream_limited_src::operator<<( - __int64 n) - { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); - if(n < 0) - { - --start; - CharT const minus = lcast_char_constants::minus; - Traits::assign(*start, minus); - } - return true; - } -#endif - - template - inline bool lexical_stream_limited_src::operator<<( - unsigned short n) - { - start = lcast_put_unsigned(n, finish); - return true; - } - - template - inline bool lexical_stream_limited_src::operator<<( - unsigned int n) - { - start = lcast_put_unsigned(n, finish); - return true; - } - - template - inline bool lexical_stream_limited_src::operator<<( - unsigned long n) - { - start = lcast_put_unsigned(n, finish); - return true; - } - -#if defined(BOOST_HAS_LONG_LONG) - template - inline bool lexical_stream_limited_src::operator<<( - boost::ulong_long_type n) - { - start = lcast_put_unsigned(n, finish); - return true; - } -#elif defined(BOOST_HAS_MS_INT64) - template - inline bool lexical_stream_limited_src::operator<<( - unsigned __int64 n) - { - start = lcast_put_unsigned(n, finish); - return true; - } -#endif - - template - inline bool lexical_stream_limited_src::operator<<( - float val) - { - return this->lcast_put(val); - } - - template - inline bool lexical_stream_limited_src::operator<<( - double val) - { - return this->lcast_put(val); - } - - template - inline bool lexical_stream_limited_src::operator<<( - long double val) - { - return this->lcast_put(val); - } - - template - inline bool lexical_stream_limited_src::operator<<( - CharT const* str) - { - start = const_cast(str); - finish = start + Traits::length(str); - return true; - } - - template - inline bool lexical_stream_limited_src::operator>>( - CharT& output) - { - bool const ok = (finish - start == 1); - if(ok) - Traits::assign(output, *start); - return ok; - } - - template - inline bool lexical_stream_limited_src::operator>>( - unsigned char& output) - { - BOOST_STATIC_ASSERT( sizeof(CharT) == sizeof(unsigned char) ); - bool const ok = (finish - start == 1); - if(ok) { - CharT out; - Traits::assign(out, *start); - output = static_cast(out); - } - return ok; - } - - template - inline bool lexical_stream_limited_src::operator>>( - signed char& output) - { - BOOST_STATIC_ASSERT( sizeof(CharT) == sizeof(signed char) ); - bool const ok = (finish - start == 1); - if(ok) { - CharT out; - Traits::assign(out, *start); - output = static_cast(out); - } - return ok; - } - -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - inline bool lexical_stream_limited_src::operator>>( - std::string& str) - { - str.assign(start, finish); - return true; - } - -#ifndef BOOST_LCAST_NO_WCHAR_T - template - inline bool lexical_stream_limited_src::operator>>( - std::wstring& str) - { - str.assign(start, finish); - return true; - } -#endif -#endif - } - - namespace detail // lcast_streambuf_for_source - { - // Returns true if optimized stream wrapper needs ostream for writing. - template - struct lcast_streambuf_for_source - { - BOOST_STATIC_CONSTANT(bool, value = false); - }; - - template<> - struct lcast_streambuf_for_source - { - BOOST_STATIC_CONSTANT(bool, value = true); - }; - - template<> - struct lcast_streambuf_for_source - { - BOOST_STATIC_CONSTANT(bool, value = true); - }; - - template<> - struct lcast_streambuf_for_source - { - BOOST_STATIC_CONSTANT(bool, value = true); + bool operator>>(InputStreamable& output) { return shr_using_base_class(output); } }; } - namespace detail // lcast_streambuf_for_target - { - // Returns true if optimized stream wrapper needs istream for reading. - template - struct lcast_streambuf_for_target - { -#if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64) - BOOST_STATIC_CONSTANT(bool, value = - ( - ::boost::type_traits::ice_or< - ::boost::type_traits::ice_not< is_arithmetic::value >::value, - is_same::value, - ::boost::type_traits::ice_and< - is_same::value, - ::boost::type_traits::ice_eq::value - >::value - >::value - ) - ); -#else - BOOST_STATIC_CONSTANT(bool, value = - ( - ::boost::type_traits::ice_or< - ::boost::type_traits::ice_not< is_arithmetic::value >::value, - is_same::value, - is_same::value - >::value - ) - ); -#endif - }; - #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct lcast_streambuf_for_target< - std::basic_string > - { - BOOST_STATIC_CONSTANT(bool, value = false); - }; - -#ifndef BOOST_LCAST_NO_WCHAR_T - template - struct lcast_streambuf_for_target< - std::basic_string > - { - BOOST_STATIC_CONSTANT(bool, value = false); - }; -#endif -#else - template<> - struct lcast_streambuf_for_target - { - BOOST_STATIC_CONSTANT(bool, value = false); - }; - -#ifndef BOOST_LCAST_NO_WCHAR_T - template<> - struct lcast_streambuf_for_target - { - BOOST_STATIC_CONSTANT(bool, value = false); - }; -#endif -#endif - } - - #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // call-by-const reference version @@ -1991,47 +1458,6 @@ namespace boost typedef const T * type; }; -#if (defined _MSC_VER) -# pragma warning( push ) -# pragma warning( disable : 4701 ) // possible use of ... before initialization -# pragma warning( disable : 4702 ) // unreachable code -# pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int' -#endif - - template< typename Target - , typename Source - , bool Unlimited // string representation of Source is unlimited - , typename CharT - > - Target lexical_cast( - BOOST_DEDUCED_TYPENAME boost::call_traits::param_type arg, - CharT* buf, std::size_t src_len) - { - typedef BOOST_DEDUCED_TYPENAME - deduce_char_traits::type traits; - - typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< - lcast_streambuf_for_target::value || - lcast_streambuf_for_source::value - , std::basic_streambuf - , lexical_streambuf_fake - >::type base; - - BOOST_DEDUCED_TYPENAME boost::mpl::if_c< - Unlimited - , detail::lexical_stream - , detail::lexical_stream_limited_src - >::type interpreter(buf, buf + src_len); - - Target result; - if(!(interpreter << arg && interpreter >> result)) - BOOST_LCAST_THROW_BAD_CAST(Source, Target); - return result; - } -#if (defined _MSC_VER) -# pragma warning( pop ) -#endif - template struct is_stdstring { @@ -2134,25 +1560,43 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = true ); }; +#if (defined _MSC_VER) +# pragma warning( push ) +# pragma warning( disable : 4701 ) // possible use of ... before initialization +# pragma warning( disable : 4702 ) // unreachable code +# pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int' +#endif template struct lexical_cast_do_cast { - static inline Target lexical_cast_impl(const Source &arg) + static inline Target lexical_cast_impl(const Source& arg) { - typedef typename detail::array_to_pointer_decay::type src; + typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay::type src; - typedef typename detail::widest_char< - typename detail::stream_char::type - , typename detail::stream_char::type + typedef BOOST_DEDUCED_TYPENAME detail::widest_char< + BOOST_DEDUCED_TYPENAME detail::stream_char::type + , BOOST_DEDUCED_TYPENAME detail::stream_char::type >::type char_type; typedef detail::lcast_src_length lcast_src_length; std::size_t const src_len = lcast_src_length::value; char_type buf[src_len + 1]; lcast_src_length::check_coverage(); - return detail::lexical_cast(arg, buf, src_len); + + typedef BOOST_DEDUCED_TYPENAME + deduce_char_traits::type traits; + + detail::lexical_stream_limited_src interpreter(buf, buf + src_len); + + Target result; + if(!(interpreter << arg && interpreter >> result)) + BOOST_LCAST_THROW_BAD_CAST(Source, Target); + return result; } }; +#if (defined _MSC_VER) +# pragma warning( pop ) +#endif template struct lexical_cast_copy @@ -2315,6 +1759,78 @@ namespace boost #else + namespace detail // stream wrapper for handling lexical conversions + { + template + class lexical_stream + { + private: + typedef typename widest_char< + typename stream_char::type, + typename stream_char::type>::type char_type; + + typedef Traits traits_type; + + public: + lexical_stream(char_type* = 0, char_type* = 0) + { + stream.unsetf(std::ios::skipws); + lcast_set_precision(stream, static_cast(0), static_cast(0) ); + } + ~lexical_stream() + { + #if defined(BOOST_NO_STRINGSTREAM) + stream.freeze(false); + #endif + } + bool operator<<(const Source &input) + { + return !(stream << input).fail(); + } + template + bool operator>>(InputStreamable &output) + { + return !is_pointer::value && + stream >> output && + stream.get() == +#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) +// GCC 2.9x lacks std::char_traits<>::eof(). +// We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 +// configurations, which do provide std::char_traits<>::eof(). + + EOF; +#else + traits_type::eof(); +#endif + } + + bool operator>>(std::string &output) + { + #if defined(BOOST_NO_STRINGSTREAM) + stream << '\0'; + #endif + stream.str().swap(output); + return true; + } + #ifndef BOOST_LCAST_NO_WCHAR_T + bool operator>>(std::wstring &output) + { + stream.str().swap(output); + return true; + } + #endif + + private: + #if defined(BOOST_NO_STRINGSTREAM) + std::strstream stream; + #elif defined(BOOST_NO_STD_LOCALE) + std::stringstream stream; + #else + std::basic_stringstream stream; + #endif + }; + } + // call-by-value fallback version (deprecated) template diff --git a/test/lexical_cast_inf_nan_test.cpp b/test/lexical_cast_inf_nan_test.cpp index ee50dee..4617d5e 100755 --- a/test/lexical_cast_inf_nan_test.cpp +++ b/test/lexical_cast_inf_nan_test.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -51,7 +52,14 @@ bool is_pos_nan(T value) template bool is_neg_nan(T value) { + /* There is some strange behaviour on Itanium platform with -nan nuber for long double. + * It is a IA64 feature, or it is a boost::math feature, not a lexical_cast bug */ +#if defined(__ia64__) || defined(_M_IA64) + return (boost::math::isnan)(value) + && ( boost::is_same::value || (boost::math::signbit)(value) ); +#else return (boost::math::isnan)(value) && (boost::math::signbit)(value); +#endif } template @@ -94,9 +102,11 @@ void test_inf_nan_templated() == "-inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::infinity()) == "inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::quiet_NaN()) == "nan" ); +#if !defined(__ia64__) && !defined(_M_IA64) BOOST_CHECK(lexical_cast( (boost::math::changesign)(std::numeric_limits::quiet_NaN())) == "-nan" ); +#endif #ifndef BOOST_LCAST_NO_WCHAR_T BOOST_CHECK( is_pos_inf( lexical_cast(L"inf") ) ); @@ -134,10 +144,13 @@ void test_inf_nan_templated() == L"-inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::infinity()) == L"inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::quiet_NaN()) == L"nan" ); +#if !defined(__ia64__) && !defined(_M_IA64) BOOST_CHECK(lexical_cast( (boost::math::changesign)(std::numeric_limits::quiet_NaN())) == L"-nan" ); #endif + +#endif } void test_inf_nan_float() diff --git a/test/lexical_cast_wchars_test.cpp b/test/lexical_cast_wchars_test.cpp index 547f226..14ac461 100755 --- a/test/lexical_cast_wchars_test.cpp +++ b/test/lexical_cast_wchars_test.cpp @@ -37,11 +37,11 @@ void test_char_types_conversions() BOOST_CHECK(boost::lexical_cast(c_arr[0]) == wc_arr[0]); BOOST_CHECK(boost::lexical_cast(c_arr) == std::wstring(wc_arr)); - BOOST_CHECK(boost::lexical_cast(sc_arr) != std::wstring(wc_arr) ); - BOOST_CHECK(boost::lexical_cast(uc_arr) != std::wstring(wc_arr) ); + BOOST_CHECK(boost::lexical_cast(sc_arr) == std::wstring(wc_arr) ); + BOOST_CHECK(boost::lexical_cast(uc_arr) == std::wstring(wc_arr) ); - BOOST_CHECK_THROW(boost::lexical_cast(uc_arr[0]), boost::bad_lexical_cast); - BOOST_CHECK_THROW(boost::lexical_cast(sc_arr[0]), boost::bad_lexical_cast); + BOOST_CHECK_EQUAL(boost::lexical_cast(uc_arr[0]), wc_arr[0]); + BOOST_CHECK_EQUAL(boost::lexical_cast(sc_arr[0]), wc_arr[0]); #endif BOOST_CHECK(1); }