Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:36:34

0001 // Copyright Kevlin Henney, 2000-2005.
0002 // Copyright Alexander Nasonov, 2006-2010.
0003 // Copyright Antony Polukhin, 2011-2024.
0004 //
0005 // Distributed under the Boost Software License, Version 1.0. (See
0006 // accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 // what:  lexical_cast custom keyword cast
0010 // who:   contributed by Kevlin Henney,
0011 //        enhanced with contributions from Terje Slettebo,
0012 //        with additional fixes and suggestions from Gennaro Prota,
0013 //        Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
0014 //        Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
0015 //        Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
0016 // when:  November 2000, March 2003, June 2005, June 2006, March 2011 - 2014, Nowember 2016
0017 
0018 #ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_STREAMS_HPP
0019 #define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_STREAMS_HPP
0020 
0021 #include <boost/config.hpp>
0022 #ifdef BOOST_HAS_PRAGMA_ONCE
0023 #   pragma once
0024 #endif
0025 
0026 
0027 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
0028 #define BOOST_LCAST_NO_WCHAR_T
0029 #endif
0030 
0031 #include <cstddef>
0032 #include <string>
0033 #include <cstring>
0034 #include <cstdio>
0035 #include <boost/limits.hpp>
0036 #include <boost/type_traits/conditional.hpp>
0037 #include <boost/type_traits/is_enum.hpp>
0038 #include <boost/type_traits/is_signed.hpp>
0039 #include <boost/type_traits/is_unsigned.hpp>
0040 #include <boost/type_traits/is_pointer.hpp>
0041 #include <boost/detail/lcast_precision.hpp>
0042 #include <boost/detail/workaround.hpp>
0043 #include <boost/core/snprintf.hpp>
0044 
0045 #ifndef BOOST_NO_STD_LOCALE
0046 #   include <locale>
0047 #else
0048 #   ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
0049         // Getting error at this point means, that your STL library is old/lame/misconfigured.
0050         // If nothing can be done with STL library, define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE,
0051         // but beware: lexical_cast will understand only 'C' locale delimeters and thousands
0052         // separators.
0053 #       error "Unable to use <locale> header. Define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE to force "
0054 #       error "boost::lexical_cast to use only 'C' locale during conversions."
0055 #   endif
0056 #endif
0057 
0058 #ifdef BOOST_NO_STRINGSTREAM
0059 #include <strstream>
0060 #else
0061 #include <sstream>
0062 #endif
0063 
0064 #include <boost/lexical_cast/detail/buffer_view.hpp>
0065 #include <boost/lexical_cast/detail/lcast_char_constants.hpp>
0066 #include <boost/lexical_cast/detail/lcast_unsigned_converters.hpp>
0067 #include <boost/lexical_cast/detail/lcast_basic_unlockedbuf.hpp>
0068 #include <boost/lexical_cast/detail/inf_nan.hpp>
0069 
0070 #include <istream>
0071 
0072 #include <array>
0073 
0074 #include <boost/type_traits/make_unsigned.hpp>
0075 #include <boost/type_traits/is_integral.hpp>
0076 #include <boost/type_traits/is_float.hpp>
0077 #include <boost/type_traits/is_const.hpp>
0078 #include <boost/type_traits/is_reference.hpp>
0079 #include <boost/container/container_fwd.hpp>
0080 #include <boost/core/enable_if.hpp>
0081 #ifndef BOOST_NO_CWCHAR
0082 #   include <cwchar>
0083 #endif
0084 
0085 // Forward declarations
0086 namespace boost {
0087     template<class T, std::size_t N>
0088     class array;
0089     template<class IteratorT>
0090     class iterator_range;
0091 
0092     // forward declaration of boost::basic_string_view from Utility
0093     template<class Ch, class Tr> class basic_string_view;
0094 }
0095 
0096 namespace boost { namespace detail { namespace lcast {
0097 
0098     template <typename T>
0099     struct exact {
0100         static_assert(!boost::is_const<T>::value, "");
0101         static_assert(!boost::is_reference<T>::value, "");
0102 
0103         const T& payload;
0104     };
0105 
0106     template< class CharT // a result of widest_char transformation
0107             , class Traits
0108             , std::size_t CharacterBufferSize
0109             >
0110     class optimized_src_stream {
0111         CharT buffer[CharacterBufferSize];
0112 
0113         // After the `stream_in(`  finishes, `[start, finish)` is
0114         // the range to output by `operator >>`
0115         const CharT*  start;
0116         const CharT*  finish;
0117     public:
0118         optimized_src_stream(optimized_src_stream&&) = delete;
0119         optimized_src_stream(const optimized_src_stream&) = delete;
0120         optimized_src_stream& operator=(optimized_src_stream&&) = delete;
0121         optimized_src_stream& operator=(const optimized_src_stream&) = delete;
0122 
0123         optimized_src_stream() noexcept
0124           : start(buffer)
0125           , finish(buffer + CharacterBufferSize)
0126         {}
0127 
0128         const CharT* cbegin() const noexcept {
0129             return start;
0130         }
0131 
0132         const CharT* cend() const noexcept {
0133             return finish;
0134         }
0135 
0136     private:
0137         bool shl_char(CharT ch) noexcept {
0138             Traits::assign(buffer[0], ch);
0139             finish = start + 1;
0140             return true;
0141         }
0142 
0143 #ifndef BOOST_LCAST_NO_WCHAR_T
0144         template <class T>
0145         bool shl_char(T ch) {
0146             static_assert(sizeof(T) <= sizeof(CharT),
0147                 "boost::lexical_cast does not support narrowing of char types."
0148                 "Use boost::locale instead" );
0149 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
0150             std::locale loc;
0151             CharT const w = BOOST_USE_FACET(std::ctype<CharT>, loc).widen(ch);
0152 #else
0153             CharT const w = static_cast<CharT>(ch);
0154 #endif
0155             Traits::assign(buffer[0], w);
0156             finish = start + 1;
0157             return true;
0158         }
0159 #endif
0160 
0161         bool shl_char_array(CharT const* str_value) noexcept {
0162             start = str_value;
0163             finish = start + Traits::length(str_value);
0164             return true;
0165         }
0166 
0167         bool shl_char_array_limited(CharT const* str, std::size_t max_size) noexcept {
0168             start = str;
0169             finish = start;
0170             const auto zero = Traits::to_char_type(0);
0171             while (finish < start + max_size && zero != *finish) {
0172                  ++ finish;
0173             }
0174             return true;
0175         }
0176 
0177         template <class T>
0178         inline bool shl_unsigned(const T n) {
0179             CharT* tmp_finish = buffer + CharacterBufferSize;
0180             start = lcast_put_unsigned<Traits, T, CharT>(n, tmp_finish).convert();
0181             finish = tmp_finish;
0182             return true;
0183         }
0184 
0185         template <class T>
0186         inline bool shl_signed(const T n) {
0187             CharT* tmp_finish = buffer + CharacterBufferSize;
0188             typedef typename boost::make_unsigned<T>::type utype;
0189             CharT* tmp_start = lcast_put_unsigned<Traits, utype, CharT>(lcast_to_unsigned(n), tmp_finish).convert();
0190             if (n < 0) {
0191                 --tmp_start;
0192                 CharT const minus = lcast_char_constants<CharT>::minus;
0193                 Traits::assign(*tmp_start, minus);
0194             }
0195             start = tmp_start;
0196             finish = tmp_finish;
0197             return true;
0198         }
0199 
0200         bool shl_real_type(float val, char* begin) {
0201             const double val_as_double = val;
0202             finish = start +
0203                 boost::core::snprintf(begin, CharacterBufferSize,
0204                 "%.*g", static_cast<int>(boost::detail::lcast_get_precision<float>()), val_as_double);
0205             return finish > start;
0206         }
0207 
0208         bool shl_real_type(double val, char* begin) {
0209             finish = start +
0210                 boost::core::snprintf(begin, CharacterBufferSize,
0211                 "%.*g", static_cast<int>(boost::detail::lcast_get_precision<double>()), val);
0212             return finish > start;
0213         }
0214 
0215 #ifndef __MINGW32__
0216         bool shl_real_type(long double val, char* begin) {
0217             finish = start +
0218                 boost::core::snprintf(begin, CharacterBufferSize,
0219                 "%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double>()), val );
0220             return finish > start;
0221         }
0222 #else
0223         bool shl_real_type(long double val, char* begin) {
0224             return shl_real_type(static_cast<double>(val), begin);
0225         }
0226 #endif
0227 
0228 #if !defined(BOOST_LCAST_NO_WCHAR_T)
0229         bool shl_real_type(float val, wchar_t* begin) {
0230             const double val_as_double = val;
0231             finish = start + boost::core::swprintf(
0232                 begin, CharacterBufferSize, L"%.*g",
0233                 static_cast<int>(boost::detail::lcast_get_precision<float >()),
0234                 val_as_double
0235             );
0236             return finish > start;
0237         }
0238 
0239         bool shl_real_type(double val, wchar_t* begin) {
0240             finish = start + boost::core::swprintf(
0241               begin, CharacterBufferSize, L"%.*g",
0242               static_cast<int>(boost::detail::lcast_get_precision<double>()),
0243               val
0244             );
0245             return finish > start;
0246         }
0247 
0248         bool shl_real_type(long double val, wchar_t* begin) {
0249             finish = start + boost::core::swprintf(
0250                 begin, CharacterBufferSize, L"%.*Lg",
0251                 static_cast<int>(boost::detail::lcast_get_precision<long double>()),
0252                 val
0253             );
0254             return finish > start;
0255         }
0256 #endif
0257     public:
0258         template <class C>
0259         using enable_if_compatible_char_t = typename boost::enable_if_c<
0260             boost::is_same<const C, const CharT>::value || (
0261                 boost::is_same<const char, const CharT>::value && (
0262                     boost::is_same<const C, const unsigned char>::value ||
0263                     boost::is_same<const C, const signed char>::value
0264                 )
0265             ), bool
0266         >::type;
0267 
0268         template<class CharTraits, class Alloc>
0269         bool stream_in(lcast::exact<std::basic_string<CharT,CharTraits,Alloc>> x) noexcept {
0270             start = x.payload.data();
0271             finish = start + x.payload.length();
0272             return true;
0273         }
0274 
0275         template<class CharTraits, class Alloc>
0276         bool stream_in(lcast::exact<boost::container::basic_string<CharT,CharTraits,Alloc>> x) noexcept {
0277             start = x.payload.data();
0278             finish = start + x.payload.length();
0279             return true;
0280         }
0281 
0282         bool stream_in(lcast::exact<bool> x) noexcept {
0283             CharT const czero = lcast_char_constants<CharT>::zero;
0284             Traits::assign(buffer[0], Traits::to_char_type(czero + x.payload));
0285             finish = start + 1;
0286             return true;
0287         }
0288 
0289         bool stream_in(lcast::exact<boost::conversion::detail::buffer_view<CharT>> x) noexcept {
0290             start = x.payload.begin;
0291             finish = x.payload.end;
0292             return true;
0293         }
0294 
0295         template <class C>
0296         enable_if_compatible_char_t<C>
0297         stream_in(lcast::exact<boost::iterator_range<C*>> x) noexcept {
0298             auto buf = boost::conversion::detail::make_buffer_view(x.payload.begin(), x.payload.end());
0299             return stream_in(lcast::exact<decltype(buf)>{buf});
0300         }
0301 
0302         bool stream_in(lcast::exact<char> x)                    { return shl_char(x.payload); }
0303         bool stream_in(lcast::exact<unsigned char> x)           { return shl_char(static_cast<char>(x.payload)); }
0304         bool stream_in(lcast::exact<signed char> x)             { return shl_char(static_cast<char>(x.payload)); }
0305         
0306         template <class C>
0307         typename boost::enable_if_c<boost::detail::is_character<C>::value, bool>::type
0308                 stream_in(lcast::exact<C> x)                    { return shl_char(x.payload); }
0309 
0310         template <class Type>
0311         enable_if_compatible_char_t<Type>
0312                 stream_in(lcast::exact<Type*> x)                { return shl_char_array(reinterpret_cast<CharT const*>(x.payload)); }
0313 
0314         template <class Type>
0315         typename boost::enable_if_c<boost::is_signed<Type>::value && !boost::is_enum<Type>::value, bool>::type
0316                 stream_in(lcast::exact<Type> x)                  { return shl_signed(x.payload); }
0317 
0318         template <class Type>
0319         typename boost::enable_if_c<boost::is_unsigned<Type>::value && !boost::is_enum<Type>::value, bool>::type
0320                 stream_in(lcast::exact<Type> x)                  { return shl_unsigned(x.payload); }
0321 
0322         template <class Type>
0323         auto stream_in(lcast::exact<Type> x) -> decltype(shl_real_type(x.payload, buffer)) {
0324             const CharT* inf_nan  = detail::get_inf_nan(x.payload, CharT());
0325             if (inf_nan) {
0326                 start = inf_nan;
0327                 finish = start + Traits::length(inf_nan);
0328                 return true;
0329             }
0330             return shl_real_type(x.payload, buffer);
0331         }
0332 
0333         template <class C, std::size_t N>
0334         enable_if_compatible_char_t<C>
0335         stream_in(lcast::exact<boost::array<C, N>> x) noexcept {
0336             return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), N);
0337         }
0338 
0339         template <class C, std::size_t N>
0340         enable_if_compatible_char_t<C>
0341         stream_in(lcast::exact<std::array<C, N>> x) noexcept {
0342             return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), N);
0343         }
0344 
0345 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
0346         template <class C, class CharTraits>
0347         enable_if_compatible_char_t<C>
0348         stream_in(lcast::exact<std::basic_string_view<C, CharTraits>> x) noexcept {
0349             start = reinterpret_cast<const CharT*>(x.payload.data());
0350             finish = start + x.payload.size();
0351             return true;
0352         }
0353 #endif
0354         template <class C, class CharTraits>
0355         enable_if_compatible_char_t<C>
0356         stream_in(lcast::exact<boost::basic_string_view<C, CharTraits>> x) noexcept {
0357             start = reinterpret_cast<const CharT*>(x.payload.data());
0358             finish = start + x.payload.size();
0359             return true;
0360         }
0361     };
0362 
0363 
0364     template <class CharT, class Traits>
0365     class ios_src_stream {
0366         typedef detail::lcast::out_stream_t<CharT, Traits> deduced_out_stream_t;
0367         typedef detail::lcast::stringbuffer_t<CharT, Traits> deduced_out_buffer_t;
0368 
0369         deduced_out_buffer_t out_buffer;
0370         deduced_out_stream_t out_stream;
0371 
0372         const CharT*  start = nullptr;
0373         const CharT*  finish = nullptr;
0374     public:
0375         ios_src_stream(ios_src_stream&&) = delete;
0376         ios_src_stream(const ios_src_stream&) = delete;
0377         ios_src_stream& operator=(ios_src_stream&&) = delete;
0378         ios_src_stream& operator=(const ios_src_stream&) = delete;
0379 
0380         ios_src_stream(): out_buffer(), out_stream(&out_buffer) {}
0381 
0382         const CharT* cbegin() const noexcept {
0383             return start;
0384         }
0385 
0386         const CharT* cend() const noexcept {
0387             return finish;
0388         }
0389     private:
0390         const deduced_out_buffer_t* get_rdbuf() const {
0391             return static_cast<deduced_out_buffer_t*>(
0392                 out_stream.rdbuf()
0393             );
0394         }
0395 
0396         template<typename InputStreamable>
0397         bool shl_input_streamable(InputStreamable& input) {
0398 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE)
0399             // If you have compilation error at this point, than your STL library
0400             // does not support such conversions. Try updating it.
0401             static_assert(boost::is_same<char, CharT>::value, "");
0402 #endif
0403 
0404 #ifndef BOOST_NO_EXCEPTIONS
0405             out_stream.exceptions(std::ios::badbit);
0406             try {
0407 #endif
0408             bool const result = !(out_stream << input).fail();
0409             const auto* const p = get_rdbuf();
0410             start = p->pbase();
0411             finish = p->pptr();
0412             return result;
0413 #ifndef BOOST_NO_EXCEPTIONS
0414             } catch (const ::std::ios_base::failure& /*f*/) {
0415                 return false;
0416             }
0417 #endif
0418         }
0419 
0420         template <class T>
0421         bool shl_char_array(T const* str_value) {
0422             static_assert(sizeof(T) <= sizeof(CharT),
0423                 "boost::lexical_cast does not support narrowing of char types."
0424                 "Use boost::locale instead" );
0425             return shl_input_streamable(str_value);
0426         }
0427 
0428         template <class T>
0429         bool shl_real(T val) {
0430             const CharT* inf_nan  = detail::get_inf_nan(val, CharT());
0431             if (inf_nan) {
0432                 start = inf_nan;
0433                 finish = start + Traits::length(inf_nan);
0434                 return true;
0435             }
0436 
0437             lcast_set_precision(out_stream, &val);
0438             return shl_input_streamable(val);
0439         }
0440 
0441     public:
0442         template <class Type>
0443         typename boost::enable_if_c<boost::detail::is_character<Type>::value && sizeof(char) == sizeof(Type), bool>::type
0444                 stream_in(lcast::exact<const Type*> x)         { return shl_char_array(reinterpret_cast<char const*>(x.payload)); }
0445 
0446         template <class Type>
0447         typename boost::enable_if_c<boost::detail::is_character<Type>::value && sizeof(char) != sizeof(Type), bool>::type
0448                 stream_in(lcast::exact<const Type*> x)         { return shl_char_array(x.payload); }
0449 
0450         bool stream_in(lcast::exact<float> x)                  { return shl_real(x.payload); }
0451         bool stream_in(lcast::exact<double> x)                 { return shl_real(x.payload); }
0452         bool stream_in(lcast::exact<long double> x)            {
0453 #ifndef __MINGW32__
0454             return shl_real(x.payload);
0455 #else
0456             return shl_real(static_cast<double>(x.payload));
0457 #endif
0458         }
0459 
0460         template <class C>
0461         typename boost::enable_if_c<boost::detail::is_character<C>::value, bool>::type
0462         stream_in(lcast::exact<iterator_range<C*>> x) noexcept {
0463             auto buf = boost::conversion::detail::make_buffer_view(x.payload.begin(), x.payload.end());
0464             return stream_in(lcast::exact<decltype(buf)>{buf});
0465         }
0466 
0467         template <class C>
0468         typename boost::enable_if_c<boost::detail::is_character<C>::value, bool>::type
0469         stream_in(lcast::exact<iterator_range<const C*>> x) noexcept {
0470             auto buf = boost::conversion::detail::make_buffer_view(x.payload.begin(), x.payload.end());
0471             return stream_in(lcast::exact<decltype(buf)>{buf});
0472         }
0473 
0474         template <class InStreamable>
0475         bool stream_in(lcast::exact<InStreamable> x)  { return shl_input_streamable(x.payload); }
0476     };
0477 
0478 
0479     template <class CharT, class Traits>
0480     class to_target_stream {
0481         //`[start, finish)` is the range to output by `operator >>`
0482         const CharT*        start;
0483         const CharT* const  finish;
0484 
0485     public:
0486         to_target_stream(to_target_stream&&) = delete;
0487         to_target_stream(const to_target_stream&) = delete;
0488         to_target_stream& operator=(to_target_stream&&) = delete;
0489         to_target_stream& operator=(const to_target_stream&) = delete;
0490 
0491         to_target_stream(const CharT* begin, const CharT* end) noexcept
0492           : start(begin)
0493           , finish(end)
0494         {}
0495 
0496     private:
0497         template <typename Type>
0498 #if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6)
0499         __attribute__((no_sanitize("unsigned-integer-overflow")))
0500 #endif
0501         bool shr_unsigned(Type& output) {
0502             if (start == finish) return false;
0503             CharT const minus = lcast_char_constants<CharT>::minus;
0504             CharT const plus = lcast_char_constants<CharT>::plus;
0505             bool const has_minus = Traits::eq(minus, *start);
0506 
0507             /* We won`t use `start' any more, so no need in decrementing it after */
0508             if (has_minus || Traits::eq(plus, *start)) {
0509                 ++start;
0510             }
0511 
0512             bool const succeed = lcast_ret_unsigned<Traits, Type, CharT>(output, start, finish).convert();
0513 
0514             if (has_minus) {
0515                 output = static_cast<Type>(0u - output);
0516             }
0517 
0518             return succeed;
0519         }
0520 
0521         template <typename Type>
0522 #if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6)
0523         __attribute__((no_sanitize("unsigned-integer-overflow")))
0524 #endif
0525         bool shr_signed(Type& output) {
0526             if (start == finish) return false;
0527             CharT const minus = lcast_char_constants<CharT>::minus;
0528             CharT const plus = lcast_char_constants<CharT>::plus;
0529             typedef typename make_unsigned<Type>::type utype;
0530             utype out_tmp = 0;
0531             bool const has_minus = Traits::eq(minus, *start);
0532 
0533             /* We won`t use `start' any more, so no need in decrementing it after */
0534             if (has_minus || Traits::eq(plus, *start)) {
0535                 ++start;
0536             }
0537 
0538             bool succeed = lcast_ret_unsigned<Traits, utype, CharT>(out_tmp, start, finish).convert();
0539             if (has_minus) {
0540                 utype const comp_val = (static_cast<utype>(1) << std::numeric_limits<Type>::digits);
0541                 succeed = succeed && out_tmp<=comp_val;
0542                 output = static_cast<Type>(0u - out_tmp);
0543             } else {
0544                 utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)());
0545                 succeed = succeed && out_tmp<=comp_val;
0546                 output = static_cast<Type>(out_tmp);
0547             }
0548             return succeed;
0549         }
0550 
0551         template<typename InputStreamable>
0552         bool shr_using_base_class(InputStreamable& output)
0553         {
0554             static_assert(
0555                 !boost::is_pointer<InputStreamable>::value,
0556                 "boost::lexical_cast can not convert to pointers"
0557             );
0558 
0559 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE)
0560             static_assert(boost::is_same<char, CharT>::value,
0561                 "boost::lexical_cast can not convert, because your STL library does not "
0562                 "support such conversions. Try updating it."
0563             );
0564 #endif
0565 
0566 #if defined(BOOST_NO_STRINGSTREAM)
0567             std::istrstream stream(start, static_cast<std::istrstream::streamsize>(finish - start));
0568 #else
0569             typedef detail::lcast::buffer_t<CharT, Traits> buffer_t;
0570             buffer_t buf;
0571             // Usually `istream` and `basic_istream` do not modify
0572             // content of buffer; `buffer_t` assures that this is true
0573             buf.setbuf(const_cast<CharT*>(start), static_cast<typename buffer_t::streamsize>(finish - start));
0574 #if defined(BOOST_NO_STD_LOCALE)
0575             std::istream stream(&buf);
0576 #else
0577             std::basic_istream<CharT, Traits> stream(&buf);
0578 #endif // BOOST_NO_STD_LOCALE
0579 #endif // BOOST_NO_STRINGSTREAM
0580 
0581 #ifndef BOOST_NO_EXCEPTIONS
0582             stream.exceptions(std::ios::badbit);
0583             try {
0584 #endif
0585             stream.unsetf(std::ios::skipws);
0586             lcast_set_precision(stream, static_cast<InputStreamable*>(0));
0587 
0588             return (stream >> output)
0589                 && (stream.get() == Traits::eof());
0590 
0591 #ifndef BOOST_NO_EXCEPTIONS
0592             } catch (const ::std::ios_base::failure& /*f*/) {
0593                 return false;
0594             }
0595 #endif
0596         }
0597 
0598         template<class T>
0599         inline bool shr_xchar(T& output) noexcept {
0600             static_assert(sizeof(CharT) == sizeof(T),
0601                 "boost::lexical_cast does not support narrowing of character types."
0602                 "Use boost::locale instead" );
0603             bool const ok = (finish - start == 1);
0604             if (ok) {
0605                 CharT out;
0606                 Traits::assign(out, *start);
0607                 output = static_cast<T>(out);
0608             }
0609             return ok;
0610         }
0611 
0612         template <std::size_t N, class ArrayT>
0613         bool shr_std_array(ArrayT& output) noexcept {
0614             const std::size_t size = static_cast<std::size_t>(finish - start);
0615             if (size > N - 1) { // `-1` because we need to store \0 at the end
0616                 return false;
0617             }
0618 
0619             std::memcpy(&output[0], start, size * sizeof(CharT));
0620             output[size] = Traits::to_char_type(0);
0621             return true;
0622         }
0623 
0624     public:
0625         bool stream_out(unsigned short& output)             { return shr_unsigned(output); }
0626         bool stream_out(unsigned int& output)               { return shr_unsigned(output); }
0627         bool stream_out(unsigned long int& output)          { return shr_unsigned(output); }
0628         bool stream_out(short& output)                      { return shr_signed(output); }
0629         bool stream_out(int& output)                        { return shr_signed(output); }
0630         bool stream_out(long int& output)                   { return shr_signed(output); }
0631 #if defined(BOOST_HAS_LONG_LONG)
0632         bool stream_out(boost::ulong_long_type& output)     { return shr_unsigned(output); }
0633         bool stream_out(boost::long_long_type& output)      { return shr_signed(output); }
0634 #elif defined(BOOST_HAS_MS_INT64)
0635         bool stream_out(unsigned __int64& output)           { return shr_unsigned(output); }
0636         bool stream_out(__int64& output)                    { return shr_signed(output); }
0637 #endif
0638 
0639 #ifdef BOOST_HAS_INT128
0640         bool stream_out(boost::uint128_type& output)        { return shr_unsigned(output); }
0641         bool stream_out(boost::int128_type& output)         { return shr_signed(output); }
0642 #endif
0643 
0644         bool stream_out(char& output)                       { return shr_xchar(output); }
0645         bool stream_out(unsigned char& output)              { return shr_xchar(output); }
0646         bool stream_out(signed char& output)                { return shr_xchar(output); }
0647 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
0648         bool stream_out(wchar_t& output)                    { return shr_xchar(output); }
0649 #endif
0650 #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
0651         bool stream_out(char16_t& output)                   { return shr_xchar(output); }
0652 #endif
0653 #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
0654         bool stream_out(char32_t& output)                   { return shr_xchar(output); }
0655 #endif
0656         template<class CharTraits, class Alloc>
0657         bool stream_out(std::basic_string<CharT,CharTraits,Alloc>& str) {
0658             str.assign(start, finish); return true;
0659         }
0660 
0661         template<class CharTraits, class Alloc>
0662         bool stream_out(boost::container::basic_string<CharT,CharTraits,Alloc>& str) {
0663             str.assign(start, finish); return true;
0664         }
0665 
0666         template <class C, std::size_t N>
0667         bool stream_out(std::array<C, N>& output) noexcept {
0668             static_assert(sizeof(C) == sizeof(CharT), "");
0669             return shr_std_array<N>(output);
0670         }
0671 
0672         template <class C, std::size_t N>
0673         bool stream_out(boost::array<C, N>& output) noexcept {
0674             static_assert(sizeof(C) == sizeof(CharT), "");
0675             return shr_std_array<N>(output);
0676         }
0677 
0678         bool stream_out(bool& output) noexcept {
0679             output = false; // Suppress warning about uninitalized variable
0680 
0681             if (start == finish) return false;
0682             CharT const zero = lcast_char_constants<CharT>::zero;
0683             CharT const plus = lcast_char_constants<CharT>::plus;
0684             CharT const minus = lcast_char_constants<CharT>::minus;
0685 
0686             const CharT* const dec_finish = finish - 1;
0687             output = Traits::eq(*dec_finish, zero + 1);
0688             if (!output && !Traits::eq(*dec_finish, zero)) {
0689                 return false; // Does not ends on '0' or '1'
0690             }
0691 
0692             if (start == dec_finish) return true;
0693 
0694             // We may have sign at the beginning
0695             if (Traits::eq(plus, *start) || (Traits::eq(minus, *start) && !output)) {
0696                 ++ start;
0697             }
0698 
0699             // Skipping zeros
0700             while (start != dec_finish) {
0701                 if (!Traits::eq(zero, *start)) {
0702                     return false; // Not a zero => error
0703                 }
0704 
0705                 ++ start;
0706             }
0707 
0708             return true;
0709         }
0710 
0711     private:
0712         // Not optimised converter
0713         template <class T>
0714         bool float_types_converter_internal(T& output) {
0715             if (parse_inf_nan(start, finish, output)) return true;
0716             bool const return_value = shr_using_base_class(output);
0717 
0718             /* Some compilers and libraries successfully
0719              * parse 'inf', 'INFINITY', '1.0E', '1.0E-'...
0720              * We are trying to provide a unified behaviour,
0721              * so we just forbid such conversions (as some
0722              * of the most popular compilers/libraries do)
0723              * */
0724             CharT const minus = lcast_char_constants<CharT>::minus;
0725             CharT const plus = lcast_char_constants<CharT>::plus;
0726             CharT const capital_e = lcast_char_constants<CharT>::capital_e;
0727             CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
0728             if ( return_value &&
0729                  (
0730                     Traits::eq(*(finish-1), lowercase_e)                   // 1.0e
0731                     || Traits::eq(*(finish-1), capital_e)                  // 1.0E
0732                     || Traits::eq(*(finish-1), minus)                      // 1.0e- or 1.0E-
0733                     || Traits::eq(*(finish-1), plus)                       // 1.0e+ or 1.0E+
0734                  )
0735             ) return false;
0736 
0737             return return_value;
0738         }
0739 
0740     public:
0741         bool stream_out(float& output) { return float_types_converter_internal(output); }
0742         bool stream_out(double& output) { return float_types_converter_internal(output); }
0743         bool stream_out(long double& output) { return float_types_converter_internal(output); }
0744 
0745         // Generic istream-based algorithm.
0746         // lcast_streambuf_for_target<InputStreamable>::value is true.
0747         template <typename InputStreamable>
0748         bool stream_out(InputStreamable& output) {
0749             return shr_using_base_class(output);
0750         }
0751     };
0752     
0753 }}} // namespace boost::detail::lcast
0754 
0755 #undef BOOST_LCAST_NO_WCHAR_T
0756 
0757 #endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP
0758