Chris@102: // Copyright Kevlin Henney, 2000-2005. Chris@102: // Copyright Alexander Nasonov, 2006-2010. Chris@102: // Copyright Antony Polukhin, 2011-2014. Chris@102: // Chris@102: // Distributed under the Boost Software License, Version 1.0. (See Chris@102: // accompanying file LICENSE_1_0.txt or copy at Chris@102: // http://www.boost.org/LICENSE_1_0.txt) Chris@102: // Chris@102: // what: lexical_cast custom keyword cast Chris@102: // who: contributed by Kevlin Henney, Chris@102: // enhanced with contributions from Terje Slettebo, Chris@102: // with additional fixes and suggestions from Gennaro Prota, Chris@102: // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, Chris@102: // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, Chris@102: // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters Chris@102: // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 Chris@102: Chris@102: #ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_STREAMS_HPP Chris@102: #define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_STREAMS_HPP Chris@102: Chris@102: #include Chris@102: #ifdef BOOST_HAS_PRAGMA_ONCE Chris@102: # pragma once Chris@102: #endif Chris@102: Chris@102: Chris@102: #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) Chris@102: #define BOOST_LCAST_NO_WCHAR_T Chris@102: #endif Chris@102: Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: Chris@102: Chris@102: #ifndef BOOST_NO_STD_LOCALE Chris@102: # include Chris@102: #else Chris@102: # ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE Chris@102: // Getting error at this point means, that your STL library is old/lame/misconfigured. Chris@102: // If nothing can be done with STL library, define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE, Chris@102: // but beware: lexical_cast will understand only 'C' locale delimeters and thousands Chris@102: // separators. Chris@102: # error "Unable to use header. Define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE to force " Chris@102: # error "boost::lexical_cast to use only 'C' locale during conversions." Chris@102: # endif Chris@102: #endif Chris@102: Chris@102: #ifdef BOOST_NO_STRINGSTREAM Chris@102: #include Chris@102: #else Chris@102: #include Chris@102: #endif Chris@102: Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: Chris@102: #include Chris@102: Chris@102: #ifndef BOOST_NO_CXX11_HDR_ARRAY Chris@102: #include Chris@102: #endif Chris@102: Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #ifndef BOOST_NO_CWCHAR Chris@102: # include Chris@102: #endif Chris@102: Chris@102: namespace boost { Chris@102: Chris@102: namespace detail // basic_unlockedbuf Chris@102: { Chris@102: // acts as a stream buffer which wraps around a pair of pointers Chris@102: // and gives acces to internals Chris@102: template Chris@102: class basic_unlockedbuf : public basic_pointerbuf { Chris@102: public: Chris@102: typedef basic_pointerbuf base_type; Chris@102: typedef BOOST_DEDUCED_TYPENAME base_type::streamsize streamsize; Chris@102: Chris@102: #ifndef BOOST_NO_USING_TEMPLATE Chris@102: using base_type::pptr; Chris@102: using base_type::pbase; Chris@102: using base_type::setbuf; Chris@102: #else Chris@102: charT* pptr() const { return base_type::pptr(); } Chris@102: charT* pbase() const { return base_type::pbase(); } Chris@102: BufferType* setbuf(char_type* s, streamsize n) { return base_type::setbuf(s, n); } Chris@102: #endif Chris@102: }; Chris@102: } Chris@102: Chris@102: namespace detail Chris@102: { Chris@102: struct do_not_construct_out_stream_t{}; Chris@102: Chris@102: template Chris@102: struct out_stream_helper_trait { Chris@102: #if defined(BOOST_NO_STRINGSTREAM) Chris@102: typedef std::ostrstream out_stream_t; Chris@102: typedef void buffer_t; Chris@102: #elif defined(BOOST_NO_STD_LOCALE) Chris@102: typedef std::ostringstream out_stream_t; Chris@102: typedef basic_unlockedbuf buffer_t; Chris@102: #else Chris@102: typedef std::basic_ostringstream Chris@102: out_stream_t; Chris@102: typedef basic_unlockedbuf, CharT> Chris@102: buffer_t; Chris@102: #endif Chris@102: }; Chris@102: } Chris@102: Chris@102: namespace detail // optimized stream wrappers Chris@102: { Chris@102: template< class CharT // a result of widest_char transformation Chris@102: , class Traits Chris@102: , bool RequiresStringbuffer Chris@102: , std::size_t CharacterBufferSize Chris@102: > Chris@102: class lexical_istream_limited_src: boost::noncopyable { Chris@102: typedef BOOST_DEDUCED_TYPENAME out_stream_helper_trait::buffer_t Chris@102: buffer_t; Chris@102: Chris@102: typedef BOOST_DEDUCED_TYPENAME out_stream_helper_trait::out_stream_t Chris@102: out_stream_t; Chris@102: Chris@102: typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< Chris@102: RequiresStringbuffer, Chris@102: out_stream_t, Chris@102: do_not_construct_out_stream_t Chris@102: >::type deduced_out_stream_t; Chris@102: Chris@102: // A string representation of Source is written to `buffer`. Chris@102: deduced_out_stream_t out_stream; Chris@102: CharT buffer[CharacterBufferSize]; Chris@102: Chris@102: // After the `operator <<` finishes, `[start, finish)` is Chris@102: // the range to output by `operator >>` Chris@102: const CharT* start; Chris@102: const CharT* finish; Chris@102: Chris@102: public: Chris@102: lexical_istream_limited_src() BOOST_NOEXCEPT Chris@102: : start(buffer) Chris@102: , finish(buffer + CharacterBufferSize) Chris@102: {} Chris@102: Chris@102: const CharT* cbegin() const BOOST_NOEXCEPT { Chris@102: return start; Chris@102: } Chris@102: Chris@102: const CharT* cend() const BOOST_NOEXCEPT { Chris@102: return finish; Chris@102: } Chris@102: Chris@102: private: Chris@102: // Undefined: Chris@102: lexical_istream_limited_src(lexical_istream_limited_src const&); Chris@102: void operator=(lexical_istream_limited_src const&); Chris@102: Chris@102: /************************************ HELPER FUNCTIONS FOR OPERATORS << ( ... ) ********************************/ Chris@102: bool shl_char(CharT ch) BOOST_NOEXCEPT { Chris@102: Traits::assign(buffer[0], ch); Chris@102: finish = start + 1; Chris@102: return true; Chris@102: } Chris@102: Chris@102: #ifndef BOOST_LCAST_NO_WCHAR_T Chris@102: template Chris@102: bool shl_char(T ch) { Chris@102: BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)) , Chris@102: "boost::lexical_cast does not support narrowing of char types." Chris@102: "Use boost::locale instead" ); Chris@102: #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE Chris@102: std::locale loc; Chris@102: CharT const w = BOOST_USE_FACET(std::ctype, loc).widen(ch); Chris@102: #else Chris@102: CharT const w = static_cast(ch); Chris@102: #endif Chris@102: Traits::assign(buffer[0], w); Chris@102: finish = start + 1; Chris@102: return true; Chris@102: } Chris@102: #endif Chris@102: Chris@102: bool shl_char_array(CharT const* str) BOOST_NOEXCEPT { Chris@102: start = str; Chris@102: finish = start + Traits::length(str); Chris@102: return true; Chris@102: } Chris@102: Chris@102: template Chris@102: bool shl_char_array(T const* str) { Chris@102: BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)), Chris@102: "boost::lexical_cast does not support narrowing of char types." Chris@102: "Use boost::locale instead" ); Chris@102: return shl_input_streamable(str); Chris@102: } Chris@102: Chris@102: bool shl_char_array_limited(CharT const* str, std::size_t max_size) BOOST_NOEXCEPT { Chris@102: start = str; Chris@102: finish = std::find(start, start + max_size, Traits::to_char_type(0)); Chris@102: return true; Chris@102: } Chris@102: Chris@102: template Chris@102: bool shl_input_streamable(InputStreamable& input) { Chris@102: #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) Chris@102: // If you have compilation error at this point, than your STL library Chris@102: // does not support such conversions. Try updating it. Chris@102: BOOST_STATIC_ASSERT((boost::is_same::value)); Chris@102: #endif Chris@102: Chris@102: #ifndef BOOST_NO_EXCEPTIONS Chris@102: out_stream.exceptions(std::ios::badbit); Chris@102: try { Chris@102: #endif Chris@102: bool const result = !(out_stream << input).fail(); Chris@102: const buffer_t* const p = static_cast( Chris@102: static_cast*>(out_stream.rdbuf()) Chris@102: ); Chris@102: start = p->pbase(); Chris@102: finish = p->pptr(); Chris@102: return result; Chris@102: #ifndef BOOST_NO_EXCEPTIONS Chris@102: } catch (const ::std::ios_base::failure& /*f*/) { Chris@102: return false; Chris@102: } Chris@102: #endif Chris@102: } Chris@102: Chris@102: template Chris@102: inline bool shl_unsigned(const T n) { Chris@102: CharT* tmp_finish = buffer + CharacterBufferSize; Chris@102: start = lcast_put_unsigned(n, tmp_finish).convert(); Chris@102: finish = tmp_finish; Chris@102: return true; Chris@102: } Chris@102: Chris@102: template Chris@102: inline bool shl_signed(const T n) { Chris@102: CharT* tmp_finish = buffer + CharacterBufferSize; Chris@102: typedef BOOST_DEDUCED_TYPENAME boost::make_unsigned::type utype; Chris@102: CharT* tmp_start = lcast_put_unsigned(lcast_to_unsigned(n), tmp_finish).convert(); Chris@102: if (n < 0) { Chris@102: --tmp_start; Chris@102: CharT const minus = lcast_char_constants::minus; Chris@102: Traits::assign(*tmp_start, minus); Chris@102: } Chris@102: start = tmp_start; Chris@102: finish = tmp_finish; Chris@102: return true; Chris@102: } Chris@102: Chris@102: template Chris@102: bool shl_real_type(const T& val, SomeCharT* /*begin*/) { Chris@102: lcast_set_precision(out_stream, &val); Chris@102: return shl_input_streamable(val); Chris@102: } Chris@102: Chris@102: bool shl_real_type(float val, char* begin) { Chris@102: using namespace std; Chris@102: const double val_as_double = val; Chris@102: finish = start + Chris@102: #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) Chris@102: sprintf_s(begin, CharacterBufferSize, Chris@102: #else Chris@102: sprintf(begin, Chris@102: #endif Chris@102: "%.*g", static_cast(boost::detail::lcast_get_precision()), val_as_double); Chris@102: return finish > start; Chris@102: } Chris@102: Chris@102: bool shl_real_type(double val, char* begin) { Chris@102: using namespace std; Chris@102: finish = start + Chris@102: #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) Chris@102: sprintf_s(begin, CharacterBufferSize, Chris@102: #else Chris@102: sprintf(begin, Chris@102: #endif Chris@102: "%.*g", static_cast(boost::detail::lcast_get_precision()), val); Chris@102: return finish > start; Chris@102: } Chris@102: Chris@102: #ifndef __MINGW32__ Chris@102: bool shl_real_type(long double val, char* begin) { Chris@102: using namespace std; Chris@102: finish = start + Chris@102: #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) Chris@102: sprintf_s(begin, CharacterBufferSize, Chris@102: #else Chris@102: sprintf(begin, Chris@102: #endif Chris@102: "%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); Chris@102: return finish > start; Chris@102: } Chris@102: #endif Chris@102: Chris@102: Chris@102: #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__) Chris@102: bool shl_real_type(float val, wchar_t* begin) { Chris@102: using namespace std; Chris@102: const double val_as_double = val; Chris@102: finish = start + swprintf(begin, CharacterBufferSize, Chris@102: L"%.*g", Chris@102: static_cast(boost::detail::lcast_get_precision()), Chris@102: val_as_double ); Chris@102: return finish > start; Chris@102: } Chris@102: Chris@102: bool shl_real_type(double val, wchar_t* begin) { Chris@102: using namespace std; Chris@102: finish = start + swprintf(begin, CharacterBufferSize, Chris@102: L"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); Chris@102: return finish > start; Chris@102: } Chris@102: Chris@102: bool shl_real_type(long double val, wchar_t* begin) { Chris@102: using namespace std; Chris@102: finish = start + swprintf(begin, CharacterBufferSize, Chris@102: L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); Chris@102: return finish > start; Chris@102: } Chris@102: #endif Chris@102: template Chris@102: bool shl_real(T val) { Chris@102: CharT* tmp_finish = buffer + CharacterBufferSize; Chris@102: if (put_inf_nan(buffer, tmp_finish, val)) { Chris@102: finish = tmp_finish; Chris@102: return true; Chris@102: } Chris@102: Chris@102: return shl_real_type(val, static_cast(buffer)); Chris@102: } Chris@102: Chris@102: /************************************ OPERATORS << ( ... ) ********************************/ Chris@102: public: Chris@102: template Chris@102: bool operator<<(std::basic_string const& str) BOOST_NOEXCEPT { Chris@102: start = str.data(); Chris@102: finish = start + str.length(); Chris@102: return true; Chris@102: } Chris@102: Chris@102: template Chris@102: bool operator<<(boost::container::basic_string const& str) BOOST_NOEXCEPT { Chris@102: start = str.data(); Chris@102: finish = start + str.length(); Chris@102: return true; Chris@102: } Chris@102: Chris@102: bool operator<<(bool value) BOOST_NOEXCEPT { Chris@102: CharT const czero = lcast_char_constants::zero; Chris@102: Traits::assign(buffer[0], Traits::to_char_type(czero + value)); Chris@102: finish = start + 1; Chris@102: return true; Chris@102: } Chris@102: Chris@102: template Chris@102: BOOST_DEDUCED_TYPENAME boost::disable_if, bool>::type Chris@102: operator<<(const iterator_range& rng) BOOST_NOEXCEPT { Chris@102: return (*this) << iterator_range(rng.begin(), rng.end()); Chris@102: } Chris@102: Chris@102: bool operator<<(const iterator_range& rng) BOOST_NOEXCEPT { Chris@102: start = rng.begin(); Chris@102: finish = rng.end(); Chris@102: return true; Chris@102: } Chris@102: Chris@102: bool operator<<(const iterator_range& rng) BOOST_NOEXCEPT { Chris@102: return (*this) << iterator_range( Chris@102: reinterpret_cast(rng.begin()), Chris@102: reinterpret_cast(rng.end()) Chris@102: ); Chris@102: } Chris@102: Chris@102: bool operator<<(const iterator_range& rng) BOOST_NOEXCEPT { Chris@102: return (*this) << iterator_range( Chris@102: reinterpret_cast(rng.begin()), Chris@102: reinterpret_cast(rng.end()) Chris@102: ); Chris@102: } Chris@102: Chris@102: bool operator<<(char ch) { return shl_char(ch); } Chris@102: bool operator<<(unsigned char ch) { return ((*this) << static_cast(ch)); } Chris@102: bool operator<<(signed char ch) { return ((*this) << static_cast(ch)); } Chris@102: #if !defined(BOOST_LCAST_NO_WCHAR_T) Chris@102: bool operator<<(wchar_t const* str) { return shl_char_array(str); } Chris@102: bool operator<<(wchar_t * str) { return shl_char_array(str); } Chris@102: #ifndef BOOST_NO_INTRINSIC_WCHAR_T Chris@102: bool operator<<(wchar_t ch) { return shl_char(ch); } Chris@102: #endif Chris@102: #endif Chris@102: #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) Chris@102: bool operator<<(char16_t ch) { return shl_char(ch); } Chris@102: bool operator<<(char16_t * str) { return shl_char_array(str); } Chris@102: bool operator<<(char16_t const * str) { return shl_char_array(str); } Chris@102: #endif Chris@102: #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) Chris@102: bool operator<<(char32_t ch) { return shl_char(ch); } Chris@102: bool operator<<(char32_t * str) { return shl_char_array(str); } Chris@102: bool operator<<(char32_t const * str) { return shl_char_array(str); } Chris@102: #endif Chris@102: bool operator<<(unsigned char const* ch) { return ((*this) << reinterpret_cast(ch)); } Chris@102: bool operator<<(unsigned char * ch) { return ((*this) << reinterpret_cast(ch)); } Chris@102: bool operator<<(signed char const* ch) { return ((*this) << reinterpret_cast(ch)); } Chris@102: bool operator<<(signed char * ch) { return ((*this) << reinterpret_cast(ch)); } Chris@102: bool operator<<(char const* str) { return shl_char_array(str); } Chris@102: bool operator<<(char* str) { return shl_char_array(str); } Chris@102: bool operator<<(short n) { return shl_signed(n); } Chris@102: bool operator<<(int n) { return shl_signed(n); } Chris@102: bool operator<<(long n) { return shl_signed(n); } Chris@102: bool operator<<(unsigned short n) { return shl_unsigned(n); } Chris@102: bool operator<<(unsigned int n) { return shl_unsigned(n); } Chris@102: bool operator<<(unsigned long n) { return shl_unsigned(n); } Chris@102: Chris@102: #if defined(BOOST_HAS_LONG_LONG) Chris@102: bool operator<<(boost::ulong_long_type n) { return shl_unsigned(n); } Chris@102: bool operator<<(boost::long_long_type n) { return shl_signed(n); } Chris@102: #elif defined(BOOST_HAS_MS_INT64) Chris@102: bool operator<<(unsigned __int64 n) { return shl_unsigned(n); } Chris@102: bool operator<<( __int64 n) { return shl_signed(n); } Chris@102: #endif Chris@102: Chris@102: #ifdef BOOST_HAS_INT128 Chris@102: bool operator<<(const boost::uint128_type& n) { return shl_unsigned(n); } Chris@102: bool operator<<(const boost::int128_type& n) { return shl_signed(n); } Chris@102: #endif Chris@102: bool operator<<(float val) { return shl_real(val); } Chris@102: bool operator<<(double val) { return shl_real(val); } Chris@102: bool operator<<(long double val) { Chris@102: #ifndef __MINGW32__ Chris@102: return shl_real(val); Chris@102: #else Chris@102: return shl_real(static_cast(val)); Chris@102: #endif Chris@102: } Chris@102: Chris@102: // Adding constness to characters. Constness does not change layout Chris@102: template Chris@102: BOOST_DEDUCED_TYPENAME boost::disable_if, bool>::type Chris@102: operator<<(boost::array const& input) BOOST_NOEXCEPT { Chris@102: BOOST_STATIC_ASSERT_MSG( Chris@102: (sizeof(boost::array) == sizeof(boost::array)), Chris@102: "boost::array and boost::array must have exactly the same layout." Chris@102: ); Chris@102: return ((*this) << reinterpret_cast const& >(input)); Chris@102: } Chris@102: Chris@102: template Chris@102: bool operator<<(boost::array const& input) BOOST_NOEXCEPT { Chris@102: return shl_char_array_limited(input.begin(), N); Chris@102: } Chris@102: Chris@102: template Chris@102: bool operator<<(boost::array const& input) BOOST_NOEXCEPT { Chris@102: return ((*this) << reinterpret_cast const& >(input)); Chris@102: } Chris@102: Chris@102: template Chris@102: bool operator<<(boost::array const& input) BOOST_NOEXCEPT { Chris@102: return ((*this) << reinterpret_cast const& >(input)); Chris@102: } Chris@102: Chris@102: #ifndef BOOST_NO_CXX11_HDR_ARRAY Chris@102: // Making a Boost.Array from std::array Chris@102: template Chris@102: bool operator<<(std::array const& input) BOOST_NOEXCEPT { Chris@102: BOOST_STATIC_ASSERT_MSG( Chris@102: (sizeof(std::array) == sizeof(boost::array)), Chris@102: "std::array and boost::array must have exactly the same layout. " Chris@102: "Bug in implementation of std::array or boost::array." Chris@102: ); Chris@102: return ((*this) << reinterpret_cast const& >(input)); Chris@102: } Chris@102: #endif Chris@102: template Chris@102: bool operator<<(const InStreamable& input) { return shl_input_streamable(input); } Chris@102: }; Chris@102: Chris@102: Chris@102: template Chris@102: class lexical_ostream_limited_src: boost::noncopyable { Chris@102: //`[start, finish)` is the range to output by `operator >>` Chris@102: const CharT* start; Chris@102: const CharT* const finish; Chris@102: Chris@102: public: Chris@102: lexical_ostream_limited_src(const CharT* begin, const CharT* end) BOOST_NOEXCEPT Chris@102: : start(begin) Chris@102: , finish(end) Chris@102: {} Chris@102: Chris@102: /************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/ Chris@102: private: Chris@102: template Chris@102: bool shr_unsigned(Type& output) { Chris@102: if (start == finish) return false; Chris@102: CharT const minus = lcast_char_constants::minus; Chris@102: CharT const plus = lcast_char_constants::plus; Chris@102: bool const has_minus = Traits::eq(minus, *start); Chris@102: Chris@102: /* We won`t use `start' any more, so no need in decrementing it after */ Chris@102: if (has_minus || Traits::eq(plus, *start)) { Chris@102: ++start; Chris@102: } Chris@102: Chris@102: bool const succeed = lcast_ret_unsigned(output, start, finish).convert(); Chris@102: Chris@102: if (has_minus) { Chris@102: output = static_cast(0u - output); Chris@102: } Chris@102: Chris@102: return succeed; Chris@102: } Chris@102: Chris@102: template Chris@102: bool shr_signed(Type& output) { Chris@102: if (start == finish) return false; Chris@102: CharT const minus = lcast_char_constants::minus; Chris@102: CharT const plus = lcast_char_constants::plus; Chris@102: typedef BOOST_DEDUCED_TYPENAME make_unsigned::type utype; Chris@102: utype out_tmp = 0; Chris@102: bool const has_minus = Traits::eq(minus, *start); Chris@102: Chris@102: /* We won`t use `start' any more, so no need in decrementing it after */ Chris@102: if (has_minus || Traits::eq(plus, *start)) { Chris@102: ++start; Chris@102: } Chris@102: Chris@102: bool succeed = lcast_ret_unsigned(out_tmp, start, finish).convert(); Chris@102: if (has_minus) { Chris@102: utype const comp_val = (static_cast(1) << std::numeric_limits::digits); Chris@102: succeed = succeed && out_tmp<=comp_val; Chris@102: output = static_cast(0u - out_tmp); Chris@102: } else { Chris@102: utype const comp_val = static_cast((std::numeric_limits::max)()); Chris@102: succeed = succeed && out_tmp<=comp_val; Chris@102: output = static_cast(out_tmp); Chris@102: } Chris@102: return succeed; Chris@102: } Chris@102: Chris@102: template Chris@102: bool shr_using_base_class(InputStreamable& output) Chris@102: { Chris@102: BOOST_STATIC_ASSERT_MSG( Chris@102: (!boost::is_pointer::value), Chris@102: "boost::lexical_cast can not convert to pointers" Chris@102: ); Chris@102: Chris@102: #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) Chris@102: BOOST_STATIC_ASSERT_MSG((boost::is_same::value), Chris@102: "boost::lexical_cast can not convert, because your STL library does not " Chris@102: "support such conversions. Try updating it." Chris@102: ); Chris@102: #endif Chris@102: typedef BOOST_DEDUCED_TYPENAME out_stream_helper_trait::buffer_t Chris@102: buffer_t; Chris@102: Chris@102: #if defined(BOOST_NO_STRINGSTREAM) Chris@102: std::istrstream stream(start, finish - start); Chris@102: #else Chris@102: Chris@102: buffer_t buf; Chris@102: // Usually `istream` and `basic_istream` do not modify Chris@102: // content of buffer; `buffer_t` assures that this is true Chris@102: buf.setbuf(const_cast(start), finish - start); Chris@102: #if defined(BOOST_NO_STD_LOCALE) Chris@102: std::istream stream(&buf); Chris@102: #else Chris@102: std::basic_istream stream(&buf); Chris@102: #endif // BOOST_NO_STD_LOCALE Chris@102: #endif // BOOST_NO_STRINGSTREAM Chris@102: Chris@102: #ifndef BOOST_NO_EXCEPTIONS Chris@102: stream.exceptions(std::ios::badbit); Chris@102: try { Chris@102: #endif Chris@102: stream.unsetf(std::ios::skipws); Chris@102: lcast_set_precision(stream, static_cast(0)); Chris@102: Chris@102: return (stream >> output) Chris@102: && (stream.get() == Traits::eof()); Chris@102: Chris@102: #ifndef BOOST_NO_EXCEPTIONS Chris@102: } catch (const ::std::ios_base::failure& /*f*/) { Chris@102: return false; Chris@102: } Chris@102: #endif Chris@102: } Chris@102: Chris@102: template Chris@102: inline bool shr_xchar(T& output) BOOST_NOEXCEPT { Chris@102: BOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ), Chris@102: "boost::lexical_cast does not support narrowing of character types." Chris@102: "Use boost::locale instead" ); Chris@102: bool const ok = (finish - start == 1); Chris@102: if (ok) { Chris@102: CharT out; Chris@102: Traits::assign(out, *start); Chris@102: output = static_cast(out); Chris@102: } Chris@102: return ok; Chris@102: } Chris@102: Chris@102: template Chris@102: bool shr_std_array(ArrayT& output) BOOST_NOEXCEPT { Chris@102: using namespace std; Chris@102: const std::size_t size = static_cast(finish - start); Chris@102: if (size > N - 1) { // `-1` because we need to store \0 at the end Chris@102: return false; Chris@102: } Chris@102: Chris@102: memcpy(&output[0], start, size * sizeof(CharT)); Chris@102: output[size] = Traits::to_char_type(0); Chris@102: return true; Chris@102: } Chris@102: Chris@102: /************************************ OPERATORS >> ( ... ) ********************************/ Chris@102: public: Chris@102: bool operator>>(unsigned short& output) { return shr_unsigned(output); } Chris@102: bool operator>>(unsigned int& output) { return shr_unsigned(output); } Chris@102: bool operator>>(unsigned long int& output) { return shr_unsigned(output); } Chris@102: bool operator>>(short& output) { return shr_signed(output); } Chris@102: bool operator>>(int& output) { return shr_signed(output); } Chris@102: bool operator>>(long int& output) { return shr_signed(output); } Chris@102: #if defined(BOOST_HAS_LONG_LONG) Chris@102: bool operator>>(boost::ulong_long_type& output) { return shr_unsigned(output); } Chris@102: bool operator>>(boost::long_long_type& output) { return shr_signed(output); } Chris@102: #elif defined(BOOST_HAS_MS_INT64) Chris@102: bool operator>>(unsigned __int64& output) { return shr_unsigned(output); } Chris@102: bool operator>>(__int64& output) { return shr_signed(output); } Chris@102: #endif Chris@102: Chris@102: #ifdef BOOST_HAS_INT128 Chris@102: bool operator>>(boost::uint128_type& output) { return shr_unsigned(output); } Chris@102: bool operator>>(boost::int128_type& output) { return shr_signed(output); } Chris@102: #endif Chris@102: Chris@102: bool operator>>(char& output) { return shr_xchar(output); } Chris@102: bool operator>>(unsigned char& output) { return shr_xchar(output); } Chris@102: bool operator>>(signed char& output) { return shr_xchar(output); } Chris@102: #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) Chris@102: bool operator>>(wchar_t& output) { return shr_xchar(output); } Chris@102: #endif Chris@102: #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) Chris@102: bool operator>>(char16_t& output) { return shr_xchar(output); } Chris@102: #endif Chris@102: #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) Chris@102: bool operator>>(char32_t& output) { return shr_xchar(output); } Chris@102: #endif Chris@102: template Chris@102: bool operator>>(std::basic_string& str) { Chris@102: str.assign(start, finish); return true; Chris@102: } Chris@102: Chris@102: template Chris@102: bool operator>>(boost::container::basic_string& str) { Chris@102: str.assign(start, finish); return true; Chris@102: } Chris@102: Chris@102: template Chris@102: bool operator>>(boost::array& output) BOOST_NOEXCEPT { Chris@102: return shr_std_array(output); Chris@102: } Chris@102: Chris@102: template Chris@102: bool operator>>(boost::array& output) BOOST_NOEXCEPT { Chris@102: return ((*this) >> reinterpret_cast& >(output)); Chris@102: } Chris@102: Chris@102: template Chris@102: bool operator>>(boost::array& output) BOOST_NOEXCEPT { Chris@102: return ((*this) >> reinterpret_cast& >(output)); Chris@102: } Chris@102: Chris@102: #ifndef BOOST_NO_CXX11_HDR_ARRAY Chris@102: template Chris@102: bool operator>>(std::array& output) BOOST_NOEXCEPT { Chris@102: BOOST_STATIC_ASSERT_MSG( Chris@102: (sizeof(boost::array) == sizeof(boost::array)), Chris@102: "std::array and boost::array must have exactly the same layout." Chris@102: ); Chris@102: return ((*this) >> reinterpret_cast& >(output)); Chris@102: } Chris@102: #endif Chris@102: Chris@102: bool operator>>(bool& output) BOOST_NOEXCEPT { Chris@102: output = false; // Suppress warning about uninitalized variable Chris@102: Chris@102: if (start == finish) return false; Chris@102: CharT const zero = lcast_char_constants::zero; Chris@102: CharT const plus = lcast_char_constants::plus; Chris@102: CharT const minus = lcast_char_constants::minus; Chris@102: Chris@102: const CharT* const dec_finish = finish - 1; Chris@102: output = Traits::eq(*dec_finish, zero + 1); Chris@102: if (!output && !Traits::eq(*dec_finish, zero)) { Chris@102: return false; // Does not ends on '0' or '1' Chris@102: } Chris@102: Chris@102: if (start == dec_finish) return true; Chris@102: Chris@102: // We may have sign at the beginning Chris@102: if (Traits::eq(plus, *start) || (Traits::eq(minus, *start) && !output)) { Chris@102: ++ start; Chris@102: } Chris@102: Chris@102: // Skipping zeros Chris@102: while (start != dec_finish) { Chris@102: if (!Traits::eq(zero, *start)) { Chris@102: return false; // Not a zero => error Chris@102: } Chris@102: Chris@102: ++ start; Chris@102: } Chris@102: Chris@102: return true; Chris@102: } Chris@102: Chris@102: private: Chris@102: // Not optimised converter Chris@102: template Chris@102: bool float_types_converter_internal(T& output) { Chris@102: if (parse_inf_nan(start, finish, output)) return true; Chris@102: bool const return_value = shr_using_base_class(output); Chris@102: Chris@102: /* Some compilers and libraries successfully Chris@102: * parse 'inf', 'INFINITY', '1.0E', '1.0E-'... Chris@102: * We are trying to provide a unified behaviour, Chris@102: * so we just forbid such conversions (as some Chris@102: * of the most popular compilers/libraries do) Chris@102: * */ Chris@102: CharT const minus = lcast_char_constants::minus; Chris@102: CharT const plus = lcast_char_constants::plus; Chris@102: CharT const capital_e = lcast_char_constants::capital_e; Chris@102: CharT const lowercase_e = lcast_char_constants::lowercase_e; Chris@102: if ( return_value && Chris@102: ( Chris@102: Traits::eq(*(finish-1), lowercase_e) // 1.0e Chris@102: || Traits::eq(*(finish-1), capital_e) // 1.0E Chris@102: || Traits::eq(*(finish-1), minus) // 1.0e- or 1.0E- Chris@102: || Traits::eq(*(finish-1), plus) // 1.0e+ or 1.0E+ Chris@102: ) Chris@102: ) return false; Chris@102: Chris@102: return return_value; Chris@102: } Chris@102: Chris@102: public: Chris@102: bool operator>>(float& output) { return float_types_converter_internal(output); } Chris@102: bool operator>>(double& output) { return float_types_converter_internal(output); } Chris@102: bool operator>>(long double& output) { return float_types_converter_internal(output); } Chris@102: Chris@102: // Generic istream-based algorithm. Chris@102: // lcast_streambuf_for_target::value is true. Chris@102: template Chris@102: bool operator>>(InputStreamable& output) { Chris@102: return shr_using_base_class(output); Chris@102: } Chris@102: }; Chris@102: } Chris@102: } // namespace boost Chris@102: Chris@102: #undef BOOST_LCAST_NO_WCHAR_T Chris@102: Chris@102: #endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP Chris@102: