LCOV - code coverage report
Current view: top level - opt/homebrew/include/boost/lexical_cast/detail - converter_lexical_streams.hpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 32 53 60.4 %
Date: 2026-06-25 07:23:43 Functions: 11 13 84.6 %

          Line data    Source code
       1             : // Copyright Kevlin Henney, 2000-2005.
       2             : // Copyright Alexander Nasonov, 2006-2010.
       3             : // Copyright Antony Polukhin, 2011-2025.
       4             : //
       5             : // Distributed under the Boost Software License, Version 1.0. (See
       6             : // accompanying file LICENSE_1_0.txt or copy at
       7             : // http://www.boost.org/LICENSE_1_0.txt)
       8             : //
       9             : // what:  lexical_cast custom keyword cast
      10             : // who:   contributed by Kevlin Henney,
      11             : //        enhanced with contributions from Terje Slettebo,
      12             : //        with additional fixes and suggestions from Gennaro Prota,
      13             : //        Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
      14             : //        Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
      15             : //        Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
      16             : // when:  November 2000, March 2003, June 2005, June 2006, March 2011 - 2014, Nowember 2016
      17             : 
      18             : #ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_STREAMS_HPP
      19             : #define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_STREAMS_HPP
      20             : 
      21             : #include <boost/config.hpp>
      22             : #ifdef BOOST_HAS_PRAGMA_ONCE
      23             : #   pragma once
      24             : #endif
      25             : 
      26             : 
      27             : #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
      28             : #define BOOST_LCAST_NO_WCHAR_T
      29             : #endif
      30             : 
      31             : #include <cstddef>
      32             : #include <string>
      33             : #include <cstring>
      34             : #include <cstdio>
      35             : #include <type_traits>
      36             : #include <boost/limits.hpp>
      37             : #include <boost/detail/lcast_precision.hpp>
      38             : #include <boost/lexical_cast/detail/type_traits.hpp>
      39             : #include <boost/config/workaround.hpp>
      40             : #include <boost/core/snprintf.hpp>
      41             : 
      42             : #ifndef BOOST_NO_STD_LOCALE
      43             : #   include <locale>
      44             : #else
      45             : #   ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
      46             :         // Getting error at this point means, that your STL library is old/lame/misconfigured.
      47             :         // If nothing can be done with STL library, define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE,
      48             :         // but beware: lexical_cast will understand only 'C' locale delimeters and thousands
      49             :         // separators.
      50             : #       error "Unable to use <locale> header. Define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE to force "
      51             : #       error "boost::lexical_cast to use only 'C' locale during conversions."
      52             : #   endif
      53             : #endif
      54             : 
      55             : #ifdef BOOST_NO_STRINGSTREAM
      56             : #include <strstream>
      57             : #else
      58             : #include <sstream>
      59             : #endif
      60             : 
      61             : #include <boost/lexical_cast/detail/buffer_view.hpp>
      62             : #include <boost/lexical_cast/detail/lcast_char_constants.hpp>
      63             : #include <boost/lexical_cast/detail/lcast_unsigned_converters.hpp>
      64             : #include <boost/lexical_cast/detail/lcast_basic_unlockedbuf.hpp>
      65             : #include <boost/lexical_cast/detail/inf_nan.hpp>
      66             : 
      67             : #include <istream>
      68             : 
      69             : #include <array>
      70             : 
      71             : #include <boost/container/container_fwd.hpp>
      72             : #ifndef BOOST_NO_CWCHAR
      73             : #   include <cwchar>
      74             : #endif
      75             : 
      76             : // Forward declarations
      77             : namespace boost {
      78             :     template<class T, std::size_t N>
      79             :     class array;
      80             :     template<class IteratorT>
      81             :     class iterator_range;
      82             : 
      83             :     // forward declaration of boost::basic_string_view from Utility
      84             :     template<class Ch, class Tr> class basic_string_view;
      85             : }
      86             : 
      87             : namespace boost { namespace detail { namespace lcast {
      88             : 
      89             :     template <typename T>
      90             :     struct exact {
      91             :         static_assert(!std::is_const<T>::value, "");
      92             :         static_assert(!std::is_reference<T>::value, "");
      93             : 
      94             :         const T& payload;
      95             :     };
      96             : 
      97             :     template< class CharT // a result of widest_char transformation
      98             :             , class Traits
      99             :             , std::size_t CharacterBufferSize
     100             :             >
     101             :     class optimized_src_stream {
     102             :         CharT buffer[CharacterBufferSize];
     103             : 
     104             :         // After the `stream_in(`  finishes, `[start, finish)` is
     105             :         // the range to output by `operator >>`
     106             :         const CharT*  start;
     107             :         const CharT*  finish;
     108             :     public:
     109             :         optimized_src_stream(optimized_src_stream&&) = delete;
     110             :         optimized_src_stream(const optimized_src_stream&) = delete;
     111             :         optimized_src_stream& operator=(optimized_src_stream&&) = delete;
     112             :         optimized_src_stream& operator=(const optimized_src_stream&) = delete;
     113             : 
     114       30000 :         optimized_src_stream() noexcept
     115       15000 :           : start(buffer)
     116       15000 :           , finish(buffer + CharacterBufferSize)
     117       30000 :         {}
     118             : 
     119       15000 :         const CharT* cbegin() const noexcept {
     120       15000 :             return start;
     121             :         }
     122             : 
     123       15000 :         const CharT* cend() const noexcept {
     124       15000 :             return finish;
     125             :         }
     126             : 
     127             :     private:
     128             :         bool shl_char(CharT ch) noexcept {
     129             :             Traits::assign(buffer[0], ch);
     130             :             finish = start + 1;
     131             :             return true;
     132             :         }
     133             : 
     134             : #ifndef BOOST_LCAST_NO_WCHAR_T
     135             :         template <class T>
     136             :         bool shl_char(T ch) {
     137             :             static_assert(sizeof(T) <= sizeof(CharT),
     138             :                 "boost::lexical_cast does not support narrowing of char types."
     139             :                 "Use boost::locale instead" );
     140             : #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
     141             :             std::locale loc;
     142             :             CharT const w = BOOST_USE_FACET(std::ctype<CharT>, loc).widen(ch);
     143             : #else
     144             :             CharT const w = static_cast<CharT>(ch);
     145             : #endif
     146             :             Traits::assign(buffer[0], w);
     147             :             finish = start + 1;
     148             :             return true;
     149             :         }
     150             : #endif
     151             : 
     152             :         bool shl_char_array(CharT const* str_value) noexcept {
     153             :             start = str_value;
     154             :             finish = start + Traits::length(str_value);
     155             :             return true;
     156             :         }
     157             : 
     158             :         bool shl_char_array_limited(CharT const* str, std::size_t max_size) noexcept {
     159             :             start = str;
     160             :             finish = start;
     161             :             const auto zero = Traits::to_char_type(0);
     162             :             while (finish < start + max_size && zero != *finish) {
     163             :                  ++ finish;
     164             :             }
     165             :             return true;
     166             :         }
     167             : 
     168             :         template <class T>
     169             :         inline bool shl_unsigned(const T n) {
     170             :             CharT* tmp_finish = buffer + CharacterBufferSize;
     171             :             start = lcast_put_unsigned<Traits, T, CharT>(n, tmp_finish).convert();
     172             :             finish = tmp_finish;
     173             :             return true;
     174             :         }
     175             : 
     176             :         template <class T>
     177             :         inline bool shl_signed(const T n) {
     178             :             CharT* tmp_finish = buffer + CharacterBufferSize;
     179             :             typedef typename boost::detail::lcast::make_unsigned<T>::type utype;
     180             :             CharT* tmp_start = lcast_put_unsigned<Traits, utype, CharT>(lcast_to_unsigned(n), tmp_finish).convert();
     181             :             if (n < 0) {
     182             :                 --tmp_start;
     183             :                 CharT const minus = lcast_char_constants<CharT>::minus;
     184             :                 Traits::assign(*tmp_start, minus);
     185             :             }
     186             :             start = tmp_start;
     187             :             finish = tmp_finish;
     188             :             return true;
     189             :         }
     190             : 
     191             :         bool shl_real_type(lcast::exact<float> val, char* begin) {
     192             :             const double val_as_double = static_cast<double>(val.payload);
     193             :             finish = start +
     194             :                 boost::core::snprintf(begin, CharacterBufferSize,
     195             :                 "%.*g", static_cast<int>(boost::detail::lcast_precision<float>::value), val_as_double);
     196             :             return finish > start;
     197             :         }
     198             : 
     199             :         bool shl_real_type(lcast::exact<double> val, char* begin) {
     200             :             finish = start +
     201             :                 boost::core::snprintf(begin, CharacterBufferSize,
     202             :                 "%.*g", static_cast<int>(boost::detail::lcast_precision<double>::value), val.payload);
     203             :             return finish > start;
     204             :         }
     205             : 
     206             : #ifndef __MINGW32__
     207             :         bool shl_real_type(lcast::exact<long double> val, char* begin) {
     208             :             finish = start +
     209             :                 boost::core::snprintf(begin, CharacterBufferSize,
     210             :                 "%.*Lg", static_cast<int>(boost::detail::lcast_precision<long double>::value), val.payload );
     211             :             return finish > start;
     212             :         }
     213             : #else
     214             :         bool shl_real_type(lcast::exact<long double> val, char* begin) {
     215             :             return shl_real_type(lcast::exact<double>{static_cast<double>(val.payload)}, begin);
     216             :         }
     217             : #endif
     218             : 
     219             : #if !defined(BOOST_LCAST_NO_WCHAR_T)
     220             :         bool shl_real_type(lcast::exact<float> val, wchar_t* begin) {
     221             :             const double val_as_double = static_cast<double>(val.payload);
     222             :             finish = start + boost::core::swprintf(
     223             :                 begin, CharacterBufferSize, L"%.*g",
     224             :                 static_cast<int>(boost::detail::lcast_precision<float>::value),
     225             :                 val_as_double
     226             :             );
     227             :             return finish > start;
     228             :         }
     229             : 
     230             :         bool shl_real_type(lcast::exact<double> val, wchar_t* begin) {
     231             :             finish = start + boost::core::swprintf(
     232             :               begin, CharacterBufferSize, L"%.*g",
     233             :               static_cast<int>(boost::detail::lcast_precision<double>::value),
     234             :               val.payload
     235             :             );
     236             :             return finish > start;
     237             :         }
     238             : 
     239             :         bool shl_real_type(lcast::exact<long double> val, wchar_t* begin) {
     240             :             finish = start + boost::core::swprintf(
     241             :                 begin, CharacterBufferSize, L"%.*Lg",
     242             :                 static_cast<int>(boost::detail::lcast_precision<long double>::value),
     243             :                 val.payload
     244             :             );
     245             :             return finish > start;
     246             :         }
     247             : #endif
     248             :     public:
     249             :         template <class C>
     250             :         using enable_if_compatible_char_t = typename std::enable_if<
     251             :             std::is_same<const C, const CharT>::value || (
     252             :                 std::is_same<const char, const CharT>::value && (
     253             :                     std::is_same<const C, const unsigned char>::value ||
     254             :                     std::is_same<const C, const signed char>::value
     255             :                 )
     256             :             ), bool
     257             :         >::type;
     258             : 
     259             :         template<class CharTraits, class Alloc>
     260       15000 :         bool stream_in(lcast::exact<std::basic_string<CharT,CharTraits,Alloc>> x) noexcept {
     261       15000 :             start = x.payload.data();
     262       15000 :             finish = start + x.payload.length();
     263       15000 :             return true;
     264             :         }
     265             : 
     266             :         template<class CharTraits, class Alloc>
     267             :         bool stream_in(lcast::exact<boost::container::basic_string<CharT,CharTraits,Alloc>> x) noexcept {
     268             :             start = x.payload.data();
     269             :             finish = start + x.payload.length();
     270             :             return true;
     271             :         }
     272             : 
     273             :         bool stream_in(lcast::exact<bool> x) noexcept {
     274             :             CharT const czero = lcast_char_constants<CharT>::zero;
     275             :             Traits::assign(buffer[0], Traits::to_char_type(czero + x.payload));
     276             :             finish = start + 1;
     277             :             return true;
     278             :         }
     279             : 
     280             :         bool stream_in(lcast::exact<boost::conversion::detail::buffer_view<CharT>> x) noexcept {
     281             :             start = x.payload.begin;
     282             :             finish = x.payload.end;
     283             :             return true;
     284             :         }
     285             : 
     286             :         template <class C>
     287             :         enable_if_compatible_char_t<C>
     288             :         stream_in(lcast::exact<boost::iterator_range<C*>> x) noexcept {
     289             :             auto buf = boost::conversion::detail::make_buffer_view(x.payload.begin(), x.payload.end());
     290             :             return stream_in(lcast::exact<decltype(buf)>{buf});
     291             :         }
     292             : 
     293             :         bool stream_in(lcast::exact<char> x)                    { return shl_char(x.payload); }
     294             :         bool stream_in(lcast::exact<unsigned char> x)           { return shl_char(static_cast<char>(x.payload)); }
     295             :         bool stream_in(lcast::exact<signed char> x)             { return shl_char(static_cast<char>(x.payload)); }
     296             : 
     297             : #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
     298             :         template <class C>
     299             :         typename std::enable_if<boost::detail::is_character<C>::value, bool>::type
     300             :                 stream_in(lcast::exact<C> x)                    { return shl_char(x.payload); }
     301             : #endif
     302             : 
     303             :         template <class Type>
     304             :         enable_if_compatible_char_t<Type>
     305             :                 stream_in(lcast::exact<Type*> x)                { return shl_char_array(reinterpret_cast<CharT const*>(x.payload)); }
     306             : 
     307             :         template <class Type>
     308             :         typename std::enable_if<!std::is_floating_point<Type>::value && boost::detail::lcast::is_signed<Type>::value && !std::is_enum<Type>::value, bool>::type
     309             :                 stream_in(lcast::exact<Type> x)                  { return shl_signed(x.payload); }
     310             : 
     311             :         template <class Type>
     312             :         typename std::enable_if<boost::detail::lcast::is_unsigned<Type>::value && !std::is_enum<Type>::value, bool>::type
     313             :                 stream_in(lcast::exact<Type> x)                  { return shl_unsigned(x.payload); }
     314             : 
     315             :         template <class Type>
     316             :         auto stream_in(lcast::exact<Type> x) -> decltype(shl_real_type(x, buffer)) {
     317             :             const CharT* inf_nan  = detail::get_inf_nan(x.payload, CharT());
     318             :             if (inf_nan) {
     319             :                 start = inf_nan;
     320             :                 finish = start + Traits::length(inf_nan);
     321             :                 return true;
     322             :             }
     323             :             return shl_real_type(x, buffer);
     324             :         }
     325             : 
     326             :         template <class C, std::size_t N>
     327             :         enable_if_compatible_char_t<C>
     328             :         stream_in(lcast::exact<boost::array<C, N>> x) noexcept {
     329             :             return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), N);
     330             :         }
     331             : 
     332             :         template <class C, std::size_t N>
     333             :         enable_if_compatible_char_t<C>
     334             :         stream_in(lcast::exact<std::array<C, N>> x) noexcept {
     335             :             return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), N);
     336             :         }
     337             : 
     338             : #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
     339             :         template <class C, class CharTraits>
     340             :         enable_if_compatible_char_t<C>
     341             :         stream_in(lcast::exact<std::basic_string_view<C, CharTraits>> x) noexcept {
     342             :             start = reinterpret_cast<const CharT*>(x.payload.data());
     343             :             finish = start + x.payload.size();
     344             :             return true;
     345             :         }
     346             : #endif
     347             :         template <class C, class CharTraits>
     348             :         enable_if_compatible_char_t<C>
     349             :         stream_in(lcast::exact<boost::basic_string_view<C, CharTraits>> x) noexcept {
     350             :             start = reinterpret_cast<const CharT*>(x.payload.data());
     351             :             finish = start + x.payload.size();
     352             :             return true;
     353             :         }
     354             :     };
     355             : 
     356             : 
     357             :     template <class CharT, class Traits>
     358             :     class ios_src_stream {
     359             :         typedef detail::lcast::out_stream_t<CharT, Traits> deduced_out_stream_t;
     360             :         typedef detail::lcast::stringbuffer_t<CharT, Traits> deduced_out_buffer_t;
     361             : 
     362             :         deduced_out_buffer_t out_buffer;
     363             :         deduced_out_stream_t out_stream;
     364             : 
     365             :         const CharT*  start = nullptr;
     366             :         const CharT*  finish = nullptr;
     367             :     public:
     368             :         ios_src_stream(ios_src_stream&&) = delete;
     369             :         ios_src_stream(const ios_src_stream&) = delete;
     370             :         ios_src_stream& operator=(ios_src_stream&&) = delete;
     371             :         ios_src_stream& operator=(const ios_src_stream&) = delete;
     372             : 
     373             :         ios_src_stream(): out_buffer(), out_stream(&out_buffer) {}
     374             : 
     375             :         const CharT* cbegin() const noexcept {
     376             :             return start;
     377             :         }
     378             : 
     379             :         const CharT* cend() const noexcept {
     380             :             return finish;
     381             :         }
     382             :     private:
     383             :         const deduced_out_buffer_t* get_rdbuf() const {
     384             :             return static_cast<deduced_out_buffer_t*>(
     385             :                 out_stream.rdbuf()
     386             :             );
     387             :         }
     388             : 
     389             :         template<typename InputStreamable>
     390             :         bool shl_input_streamable(InputStreamable& input) {
     391             : #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE)
     392             :             // If you have compilation error at this point, than your STL library
     393             :             // does not support such conversions. Try updating it.
     394             :             static_assert(std::is_same<char, CharT>::value, "");
     395             : #endif
     396             : 
     397             : #ifndef BOOST_NO_EXCEPTIONS
     398             :             out_stream.exceptions(std::ios::badbit);
     399             :             try {
     400             : #endif
     401             :             bool const result = !(out_stream << input).fail();
     402             :             const auto* const p = get_rdbuf();
     403             :             start = p->pbase();
     404             :             finish = p->pptr();
     405             :             return result;
     406             : #ifndef BOOST_NO_EXCEPTIONS
     407             :             } catch (const ::std::ios_base::failure& /*f*/) {
     408             :                 return false;
     409             :             }
     410             : #endif
     411             :         }
     412             : 
     413             :         template <class T>
     414             :         bool shl_char_array(T const* str_value) {
     415             :             static_assert(sizeof(T) <= sizeof(CharT),
     416             :                 "boost::lexical_cast does not support narrowing of char types."
     417             :                 "Use boost::locale instead" );
     418             :             return shl_input_streamable(str_value);
     419             :         }
     420             : 
     421             :         template <class T>
     422             :         bool shl_real(T val) {
     423             :             const CharT* inf_nan  = detail::get_inf_nan(val, CharT());
     424             :             if (inf_nan) {
     425             :                 start = inf_nan;
     426             :                 finish = start + Traits::length(inf_nan);
     427             :                 return true;
     428             :             }
     429             : 
     430             :             boost::detail::lcast_set_precision(out_stream, &val);
     431             :             return shl_input_streamable(val);
     432             :         }
     433             : 
     434             :     public:
     435             :         template <class Type>
     436             :         typename std::enable_if<boost::detail::is_character<Type>::value && sizeof(char) == sizeof(Type), bool>::type
     437             :                 stream_in(lcast::exact<const Type*> x)         { return shl_char_array(reinterpret_cast<char const*>(x.payload)); }
     438             : 
     439             :         template <class Type>
     440             :         typename std::enable_if<boost::detail::is_character<Type>::value && sizeof(char) != sizeof(Type), bool>::type
     441             :                 stream_in(lcast::exact<const Type*> x)         { return shl_char_array(x.payload); }
     442             : 
     443             :         bool stream_in(lcast::exact<float> x)                  { return shl_real(x.payload); }
     444             :         bool stream_in(lcast::exact<double> x)                 { return shl_real(x.payload); }
     445             :         bool stream_in(lcast::exact<long double> x)            {
     446             : #ifndef __MINGW32__
     447             :             return shl_real(x.payload);
     448             : #else
     449             :             return shl_real(static_cast<double>(x.payload));
     450             : #endif
     451             :         }
     452             : 
     453             :         template <class C>
     454             :         typename std::enable_if<boost::detail::is_character<C>::value, bool>::type
     455             :         stream_in(lcast::exact<iterator_range<C*>> x) noexcept {
     456             :             auto buf = boost::conversion::detail::make_buffer_view(x.payload.begin(), x.payload.end());
     457             :             return stream_in(lcast::exact<decltype(buf)>{buf});
     458             :         }
     459             : 
     460             :         template <class C>
     461             :         typename std::enable_if<boost::detail::is_character<C>::value, bool>::type
     462             :         stream_in(lcast::exact<iterator_range<const C*>> x) noexcept {
     463             :             auto buf = boost::conversion::detail::make_buffer_view(x.payload.begin(), x.payload.end());
     464             :             return stream_in(lcast::exact<decltype(buf)>{buf});
     465             :         }
     466             : 
     467             :         template <class InStreamable>
     468             :         bool stream_in(lcast::exact<InStreamable> x)  { return shl_input_streamable(x.payload); }
     469             :     };
     470             : 
     471             : 
     472             :     template <class CharT, class Traits>
     473             :     class to_target_stream {
     474             :         //`[start, finish)` is the range to output by `operator >>`
     475             :         const CharT*        start;
     476             :         const CharT* const  finish;
     477             : 
     478             :     public:
     479             :         to_target_stream(to_target_stream&&) = delete;
     480             :         to_target_stream(const to_target_stream&) = delete;
     481             :         to_target_stream& operator=(to_target_stream&&) = delete;
     482             :         to_target_stream& operator=(const to_target_stream&) = delete;
     483             : 
     484       30000 :         to_target_stream(const CharT* begin, const CharT* end) noexcept
     485       15000 :           : start(begin)
     486       15000 :           , finish(end)
     487       30000 :         {}
     488             : 
     489             :     private:
     490             :         template <typename Type>
     491             : #if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6)
     492             :         __attribute__((no_sanitize("unsigned-integer-overflow")))
     493             : #endif
     494           0 :         bool shr_unsigned(Type& output) {
     495           0 :             if (start == finish) return false;
     496           0 :             CharT const minus = lcast_char_constants<CharT>::minus;
     497           0 :             CharT const plus = lcast_char_constants<CharT>::plus;
     498           0 :             bool const has_minus = Traits::eq(minus, *start);
     499             : 
     500             :             /* We won`t use `start' any more, so no need in decrementing it after */
     501           0 :             if (has_minus || Traits::eq(plus, *start)) {
     502           0 :                 ++start;
     503           0 :             }
     504             : 
     505           0 :             bool const succeed = lcast_ret_unsigned<Traits, Type, CharT>(output, start, finish).convert();
     506             : 
     507           0 :             if (has_minus) {
     508           0 :                 output = static_cast<Type>(0u - output);
     509           0 :             }
     510             : 
     511           0 :             return succeed;
     512           0 :         }
     513             : 
     514             :         template <typename Type>
     515             : #if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6)
     516             :         __attribute__((no_sanitize("unsigned-integer-overflow")))
     517             : #endif
     518       15000 :         bool shr_signed(Type& output) {
     519       15000 :             if (start == finish) return false;
     520       15000 :             CharT const minus = lcast_char_constants<CharT>::minus;
     521       15000 :             CharT const plus = lcast_char_constants<CharT>::plus;
     522             :             typedef typename boost::detail::lcast::make_unsigned<Type>::type utype;
     523       15000 :             utype out_tmp = 0;
     524       15000 :             bool const has_minus = Traits::eq(minus, *start);
     525             : 
     526             :             /* We won`t use `start' any more, so no need in decrementing it after */
     527       15000 :             if (has_minus || Traits::eq(plus, *start)) {
     528           0 :                 ++start;
     529           0 :             }
     530             : 
     531       15000 :             bool succeed = lcast_ret_unsigned<Traits, utype, CharT>(out_tmp, start, finish).convert();
     532       15000 :             if (has_minus) {
     533           0 :                 utype const comp_val = (static_cast<utype>(1) << std::numeric_limits<Type>::digits);
     534           0 :                 succeed = succeed && out_tmp<=comp_val;
     535           0 :                 output = static_cast<Type>(0u - out_tmp);
     536           0 :             } else {
     537       15000 :                 utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)());
     538       15000 :                 succeed = succeed && out_tmp<=comp_val;
     539       15000 :                 output = static_cast<Type>(out_tmp);
     540             :             }
     541       15000 :             return succeed;
     542       15000 :         }
     543             : 
     544             :         template<typename InputStreamable>
     545             :         bool shr_using_base_class(InputStreamable& output)
     546             :         {
     547             :             static_assert(
     548             :                 !std::is_pointer<InputStreamable>::value,
     549             :                 "boost::lexical_cast can not convert to pointers"
     550             :             );
     551             : 
     552             : #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE)
     553             :             static_assert(std::is_same<char, CharT>::value,
     554             :                 "boost::lexical_cast can not convert, because your STL library does not "
     555             :                 "support such conversions. Try updating it."
     556             :             );
     557             : #endif
     558             : 
     559             : #if defined(BOOST_NO_STRINGSTREAM)
     560             :             std::istrstream stream(start, static_cast<std::istrstream::streamsize>(finish - start));
     561             : #else
     562             :             typedef detail::lcast::buffer_t<CharT, Traits> buffer_t;
     563             :             buffer_t buf;
     564             :             // Usually `istream` and `basic_istream` do not modify
     565             :             // content of buffer; `buffer_t` assures that this is true
     566             :             buf.setbuf(const_cast<CharT*>(start), static_cast<typename buffer_t::streamsize>(finish - start));
     567             : #if defined(BOOST_NO_STD_LOCALE)
     568             :             std::istream stream(&buf);
     569             : #else
     570             :             std::basic_istream<CharT, Traits> stream(&buf);
     571             : #endif // BOOST_NO_STD_LOCALE
     572             : #endif // BOOST_NO_STRINGSTREAM
     573             : 
     574             : #ifndef BOOST_NO_EXCEPTIONS
     575             :             stream.exceptions(std::ios::badbit);
     576             :             try {
     577             : #endif
     578             :             stream.unsetf(std::ios::skipws);
     579             :             boost::detail::lcast_set_precision(stream, static_cast<InputStreamable*>(0));
     580             : 
     581             :             return (stream >> output)
     582             :                 && (stream.get() == Traits::eof());
     583             : 
     584             : #ifndef BOOST_NO_EXCEPTIONS
     585             :             } catch (const ::std::ios_base::failure& /*f*/) {
     586             :                 return false;
     587             :             }
     588             : #endif
     589             :         }
     590             : 
     591             :         template<class T>
     592             :         inline bool shr_xchar(T& output) noexcept {
     593             :             static_assert(sizeof(CharT) == sizeof(T),
     594             :                 "boost::lexical_cast does not support narrowing of character types."
     595             :                 "Use boost::locale instead" );
     596             :             bool const ok = (finish - start == 1);
     597             :             if (ok) {
     598             :                 CharT out;
     599             :                 Traits::assign(out, *start);
     600             :                 output = static_cast<T>(out);
     601             :             }
     602             :             return ok;
     603             :         }
     604             : 
     605             :         template <std::size_t N, class ArrayT>
     606             :         bool shr_std_array(ArrayT& output) noexcept {
     607             :             const std::size_t size = static_cast<std::size_t>(finish - start);
     608             :             if (size > N - 1) { // `-1` because we need to store \0 at the end
     609             :                 return false;
     610             :             }
     611             : 
     612             :             std::memcpy(&output[0], start, size * sizeof(CharT));
     613             :             output[size] = Traits::to_char_type(0);
     614             :             return true;
     615             :         }
     616             : 
     617             :     public:
     618           0 :         bool stream_out(unsigned short& output)             { return shr_unsigned(output); }
     619             :         bool stream_out(unsigned int& output)               { return shr_unsigned(output); }
     620             :         bool stream_out(unsigned long int& output)          { return shr_unsigned(output); }
     621        7500 :         bool stream_out(short& output)                      { return shr_signed(output); }
     622             :         bool stream_out(int& output)                        { return shr_signed(output); }
     623             :         bool stream_out(long int& output)                   { return shr_signed(output); }
     624             : #if defined(BOOST_HAS_LONG_LONG)
     625             :         bool stream_out(boost::ulong_long_type& output)     { return shr_unsigned(output); }
     626        7500 :         bool stream_out(boost::long_long_type& output)      { return shr_signed(output); }
     627             : #elif defined(BOOST_HAS_MS_INT64)
     628             :         bool stream_out(unsigned __int64& output)           { return shr_unsigned(output); }
     629             :         bool stream_out(__int64& output)                    { return shr_signed(output); }
     630             : #endif
     631             : 
     632             : #ifdef BOOST_HAS_INT128
     633             :         bool stream_out(boost::uint128_type& output)        { return shr_unsigned(output); }
     634             :         bool stream_out(boost::int128_type& output)         { return shr_signed(output); }
     635             : #endif
     636             : 
     637             :         bool stream_out(char& output)                       { return shr_xchar(output); }
     638             :         bool stream_out(unsigned char& output)              { return shr_xchar(output); }
     639             :         bool stream_out(signed char& output)                { return shr_xchar(output); }
     640             : #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
     641             :         bool stream_out(wchar_t& output)                    { return shr_xchar(output); }
     642             : #endif
     643             : #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
     644             :         bool stream_out(char16_t& output)                   { return shr_xchar(output); }
     645             : #endif
     646             : #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
     647             :         bool stream_out(char32_t& output)                   { return shr_xchar(output); }
     648             : #endif
     649             :         template<class CharTraits, class Alloc>
     650             :         bool stream_out(std::basic_string<CharT,CharTraits,Alloc>& str) {
     651             :             str.assign(start, finish); return true;
     652             :         }
     653             : 
     654             :         template<class CharTraits, class Alloc>
     655             :         bool stream_out(boost::container::basic_string<CharT,CharTraits,Alloc>& str) {
     656             :             str.assign(start, finish); return true;
     657             :         }
     658             : 
     659             :         template <class C, std::size_t N>
     660             :         bool stream_out(std::array<C, N>& output) noexcept {
     661             :             static_assert(sizeof(C) == sizeof(CharT), "");
     662             :             return shr_std_array<N>(output);
     663             :         }
     664             : 
     665             :         template <class C, std::size_t N>
     666             :         bool stream_out(boost::array<C, N>& output) noexcept {
     667             :             static_assert(sizeof(C) == sizeof(CharT), "");
     668             :             return shr_std_array<N>(output);
     669             :         }
     670             : 
     671             :         bool stream_out(bool& output) noexcept {
     672             :             output = false; // Suppress warning about uninitalized variable
     673             : 
     674             :             if (start == finish) return false;
     675             :             CharT const zero = lcast_char_constants<CharT>::zero;
     676             :             CharT const plus = lcast_char_constants<CharT>::plus;
     677             :             CharT const minus = lcast_char_constants<CharT>::minus;
     678             : 
     679             :             const CharT* const dec_finish = finish - 1;
     680             :             output = Traits::eq(*dec_finish, zero + 1);
     681             :             if (!output && !Traits::eq(*dec_finish, zero)) {
     682             :                 return false; // Does not ends on '0' or '1'
     683             :             }
     684             : 
     685             :             if (start == dec_finish) return true;
     686             : 
     687             :             // We may have sign at the beginning
     688             :             if (Traits::eq(plus, *start) || (Traits::eq(minus, *start) && !output)) {
     689             :                 ++ start;
     690             :             }
     691             : 
     692             :             // Skipping zeros
     693             :             while (start != dec_finish) {
     694             :                 if (!Traits::eq(zero, *start)) {
     695             :                     return false; // Not a zero => error
     696             :                 }
     697             : 
     698             :                 ++ start;
     699             :             }
     700             : 
     701             :             return true;
     702             :         }
     703             : 
     704             :     private:
     705             :         // Not optimised converter
     706             :         template <class T>
     707             :         bool float_types_converter_internal(T& output) {
     708             :             if (parse_inf_nan(start, finish, output)) return true;
     709             :             bool const return_value = shr_using_base_class(output);
     710             : 
     711             :             /* Some compilers and libraries successfully
     712             :              * parse 'inf', 'INFINITY', '1.0E', '1.0E-'...
     713             :              * We are trying to provide a unified behaviour,
     714             :              * so we just forbid such conversions (as some
     715             :              * of the most popular compilers/libraries do)
     716             :              * */
     717             :             CharT const minus = lcast_char_constants<CharT>::minus;
     718             :             CharT const plus = lcast_char_constants<CharT>::plus;
     719             :             CharT const capital_e = lcast_char_constants<CharT>::capital_e;
     720             :             CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
     721             :             if ( return_value &&
     722             :                  (
     723             :                     Traits::eq(*(finish-1), lowercase_e)                   // 1.0e
     724             :                     || Traits::eq(*(finish-1), capital_e)                  // 1.0E
     725             :                     || Traits::eq(*(finish-1), minus)                      // 1.0e- or 1.0E-
     726             :                     || Traits::eq(*(finish-1), plus)                       // 1.0e+ or 1.0E+
     727             :                  )
     728             :             ) return false;
     729             : 
     730             :             return return_value;
     731             :         }
     732             : 
     733             :     public:
     734             :         bool stream_out(float& output) { return float_types_converter_internal(output); }
     735             :         bool stream_out(double& output) { return float_types_converter_internal(output); }
     736             :         bool stream_out(long double& output) { return float_types_converter_internal(output); }
     737             : 
     738             :         // Generic istream-based algorithm.
     739             :         // lcast_streambuf_for_target<InputStreamable>::value is true.
     740             :         template <typename InputStreamable>
     741             :         bool stream_out(InputStreamable& output) {
     742             :             return shr_using_base_class(output);
     743             :         }
     744             :     };
     745             :     
     746             : }}} // namespace boost::detail::lcast
     747             : 
     748             : #undef BOOST_LCAST_NO_WCHAR_T
     749             : 
     750             : #endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP
     751             : 

Generated by: LCOV version 1.16