LCOV - code coverage report
Current view: top level - opt/homebrew/include/boost/lexical_cast/detail - converter_lexical.hpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 7 9 77.8 %
Date: 2026-06-25 07:23:51 Functions: 2 3 66.7 %

          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
      17             : 
      18             : #ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP
      19             : #define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP
      20             : 
      21             : #include <boost/config.hpp>
      22             : #ifdef BOOST_HAS_PRAGMA_ONCE
      23             : #   pragma once
      24             : #endif
      25             : 
      26             : #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
      27             : #define BOOST_LCAST_NO_WCHAR_T
      28             : #endif
      29             : 
      30             : #include <cstddef>
      31             : #include <string>
      32             : #include <type_traits>
      33             : #include <boost/limits.hpp>
      34             : #include <boost/detail/lcast_precision.hpp>
      35             : 
      36             : #include <boost/lexical_cast/detail/widest_char.hpp>
      37             : #include <boost/lexical_cast/detail/is_character.hpp>
      38             : #include <boost/lexical_cast/detail/type_traits.hpp>
      39             : 
      40             : #include <array>
      41             : 
      42             : #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
      43             : #include <string_view>
      44             : #endif
      45             : 
      46             : #include <boost/lexical_cast/detail/buffer_view.hpp>
      47             : #include <boost/container/container_fwd.hpp>
      48             : 
      49             : #include <boost/lexical_cast/detail/converter_lexical_streams.hpp>
      50             : 
      51             : namespace boost {
      52             : 
      53             :     // Forward declaration
      54             :     template<class T, std::size_t N>
      55             :     class array;
      56             :     template<class IteratorT>
      57             :     class iterator_range;
      58             : 
      59             :     // Forward declaration of boost::basic_string_view from Utility
      60             :     template<class Ch, class Tr> class basic_string_view;
      61             : 
      62             :     namespace detail // normalize_single_byte_char<Char>
      63             :     {
      64             :         // Converts signed/unsigned char to char
      65             :         template < class Char >
      66             :         struct normalize_single_byte_char
      67             :         {
      68             :             using type = Char;
      69             :         };
      70             : 
      71             :         template <>
      72             :         struct normalize_single_byte_char< signed char >
      73             :         {
      74             :             using type = char;
      75             :         };
      76             : 
      77             :         template <>
      78             :         struct normalize_single_byte_char< unsigned char >
      79             :         {
      80             :             using type = char;
      81             :         };
      82             :     }
      83             : 
      84             :     namespace detail // deduce_character_type_later<T>
      85             :     {
      86             :         // Helper type, meaning that stram character for T must be deduced
      87             :         // at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
      88             :         template < class T > struct deduce_character_type_later {};
      89             :     }
      90             : 
      91             :     namespace detail // stream_char_common<T>
      92             :     {
      93             :         // Selectors to choose stream character type (common for Source and Target)
      94             :         // Returns one of char, wchar_t, char16_t, char32_t or deduce_character_type_later<T> types
      95             :         // Executed on Stage 1 (See deduce_source_char<T> and deduce_target_char<T>)
      96             :         template < typename Type >
      97             :         struct stream_char_common: public std::conditional<
      98             :             boost::detail::is_character< Type >::value,
      99             :             Type,
     100             :             boost::detail::deduce_character_type_later< Type >
     101             :         > {};
     102             : 
     103             :         template < typename Char >
     104             :         struct stream_char_common< Char* >: public std::conditional<
     105             :             boost::detail::is_character< Char >::value,
     106             :             Char,
     107             :             boost::detail::deduce_character_type_later< Char* >
     108             :         > {};
     109             : 
     110             :         template < typename Char >
     111             :         struct stream_char_common< const Char* >: public std::conditional<
     112             :             boost::detail::is_character< Char >::value,
     113             :             Char,
     114             :             boost::detail::deduce_character_type_later< const Char* >
     115             :         > {};
     116             : 
     117             :         template < typename Char >
     118             :         struct stream_char_common< boost::conversion::detail::buffer_view< Char > >
     119             :         {
     120             :             using type = Char;
     121             :         };
     122             : 
     123             :         template < typename Char >
     124             :         struct stream_char_common< boost::iterator_range< Char* > >: public std::conditional<
     125             :             boost::detail::is_character< Char >::value,
     126             :             Char,
     127             :             boost::detail::deduce_character_type_later< boost::iterator_range< Char* > >
     128             :         > {};
     129             : 
     130             :         template < typename Char >
     131             :         struct stream_char_common< boost::iterator_range< const Char* > >: public std::conditional<
     132             :             boost::detail::is_character< Char >::value,
     133             :             Char,
     134             :             boost::detail::deduce_character_type_later< boost::iterator_range< const Char* > >
     135             :         > {};
     136             : 
     137             :         template < class Char, class Traits, class Alloc >
     138             :         struct stream_char_common< std::basic_string< Char, Traits, Alloc > >
     139             :         {
     140             :             using type = Char;
     141             :         };
     142             : 
     143             :         template < class Char, class Traits, class Alloc >
     144             :         struct stream_char_common< boost::container::basic_string< Char, Traits, Alloc > >
     145             :         {
     146             :             using type = Char;
     147             :         };
     148             : 
     149             :         template < typename Char, std::size_t N >
     150             :         struct stream_char_common< boost::array< Char, N > >: public std::conditional<
     151             :             boost::detail::is_character< Char >::value,
     152             :             Char,
     153             :             boost::detail::deduce_character_type_later< boost::array< Char, N > >
     154             :         > {};
     155             : 
     156             :         template < typename Char, std::size_t N >
     157             :         struct stream_char_common< boost::array< const Char, N > >: public std::conditional<
     158             :             boost::detail::is_character< Char >::value,
     159             :             Char,
     160             :             boost::detail::deduce_character_type_later< boost::array< const Char, N > >
     161             :         > {};
     162             : 
     163             : #ifndef BOOST_NO_CXX11_HDR_ARRAY
     164             :         template < typename Char, std::size_t N >
     165             :         struct stream_char_common< std::array<Char, N > >: public std::conditional<
     166             :             boost::detail::is_character< Char >::value,
     167             :             Char,
     168             :             boost::detail::deduce_character_type_later< std::array< Char, N > >
     169             :         > {};
     170             : 
     171             :         template < typename Char, std::size_t N >
     172             :         struct stream_char_common< std::array< const Char, N > >: public std::conditional<
     173             :             boost::detail::is_character< Char >::value,
     174             :             Char,
     175             :             boost::detail::deduce_character_type_later< std::array< const Char, N > >
     176             :         > {};
     177             : #endif
     178             : 
     179             : #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
     180             :         template < class Char, class Traits >
     181             :         struct stream_char_common< std::basic_string_view< Char, Traits > >
     182             :         {
     183             :             using type = Char;
     184             :         };
     185             : #endif
     186             :         template < class Char, class Traits >
     187             :         struct stream_char_common< boost::basic_string_view< Char, Traits > >
     188             :         {
     189             :             using type = Char;
     190             :         };
     191             : 
     192             : #ifdef BOOST_HAS_INT128
     193             :         template <> struct stream_char_common< boost::int128_type >
     194             :         {
     195             :             using type = char;
     196             :         };
     197             :         template <> struct stream_char_common< boost::uint128_type >
     198             :         {
     199             :             using type = char;
     200             :         };
     201             : #endif
     202             : 
     203             : #if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T)
     204             :         template <>
     205             :         struct stream_char_common< wchar_t >
     206             :         {
     207             :             using type = char;
     208             :         };
     209             : #endif
     210             :     }
     211             : 
     212             :     namespace detail // deduce_source_char_impl<T>
     213             :     {
     214             :         // If type T is `deduce_character_type_later` type, then tries to deduce
     215             :         // character type using streaming metafunctions.
     216             :         // Otherwise supplied type T is a character type, that must be normalized
     217             :         // using normalize_single_byte_char<Char>.
     218             :         // Executed at Stage 2  (See deduce_source_char<T> and deduce_target_char<T>)
     219             :         template < class Char >
     220             :         struct deduce_source_char_impl
     221             :         {
     222             :             typedef typename boost::detail::normalize_single_byte_char< Char >::type type;
     223             :         };
     224             : 
     225             :         template < class T >
     226             :         struct deduce_source_char_impl< deduce_character_type_later< T > >
     227             :         {
     228             :             template <class U>
     229             :             static auto left_shift_type(long)
     230             :                 -> decltype( std::declval<std::basic_ostream< char >&>() << std::declval<const U&>(), char{});
     231             : 
     232             : #if !defined(BOOST_LCAST_NO_WCHAR_T)
     233             :             template <class U>
     234             :             static auto left_shift_type(int)
     235             :                 -> decltype( std::declval<std::basic_ostream< wchar_t >&>() << std::declval<const U&>(), wchar_t{});
     236             : #endif
     237             : 
     238             :             template <class U>
     239             :             static void left_shift_type(...);
     240             : 
     241             :             using type = decltype(left_shift_type<T>(1L));
     242             : 
     243             :             static_assert(!std::is_same<type, void>::value,
     244             : #if defined(BOOST_LCAST_NO_WCHAR_T)
     245             :                 "Source type is not std::ostream`able and std::wostream`s are "
     246             :                 "not supported by your STL implementation"
     247             : #else
     248             :                 "Source type is neither std::ostream`able nor std::wostream`able"
     249             : #endif
     250             :             );
     251             :         };
     252             :     }
     253             : 
     254             :     namespace detail  // deduce_target_char_impl<T>
     255             :     {
     256             :         // If type T is `deduce_character_type_later` type, then tries to deduce
     257             :         // character type using boost::has_right_shift<T> metafunction.
     258             :         // Otherwise supplied type T is a character type, that must be normalized
     259             :         // using normalize_single_byte_char<Char>.
     260             :         // Executed at Stage 2  (See deduce_source_char<T> and deduce_target_char<T>)
     261             :         template < class Char >
     262             :         struct deduce_target_char_impl
     263             :         {
     264             :             typedef typename normalize_single_byte_char< Char >::type type;
     265             :         };
     266             : 
     267             :         template < class T >
     268             :         struct deduce_target_char_impl< deduce_character_type_later<T> >
     269             :         {
     270             :             template <class U>
     271             :             static auto right_shift_type(long)
     272             :                 -> decltype( std::declval<std::basic_istream< char >&>() >> std::declval<U&>(), char{});
     273             : 
     274             : #if !defined(BOOST_LCAST_NO_WCHAR_T)
     275             :             template <class U>
     276             :             static auto right_shift_type(int)
     277             :                 -> decltype( std::declval<std::basic_istream< wchar_t >&>() >> std::declval<U&>(), wchar_t{});
     278             : #endif
     279             : 
     280             :             template <class U>
     281             :             static void right_shift_type(...);
     282             : 
     283             :             using type = decltype(right_shift_type<T>(1L));
     284             : 
     285             :             static_assert(!std::is_same<type, void>::value,
     286             : #if defined(BOOST_LCAST_NO_WCHAR_T)
     287             :                "Target type is not std::istream`able and std::wistream`s are "
     288             :                "not supported by your STL implementation"
     289             : #else
     290             :                "Target type is neither std::istream`able nor std::wistream`able"
     291             : #endif
     292             :             );
     293             :         };
     294             :     }
     295             : 
     296             :     namespace detail  // deduce_target_char<T> and deduce_source_char<T>
     297             :     {
     298             :         // We deduce stream character types in two stages.
     299             :         //
     300             :         // Stage 1 is common for Target and Source. At Stage 1 we get
     301             :         // non normalized character type (may contain unsigned/signed char)
     302             :         // or deduce_character_type_later<T> where T is the original type.
     303             :         // Stage 1 is executed by stream_char_common<T>
     304             :         //
     305             :         // At Stage 2 we normalize character types or try to deduce character
     306             :         // type using metafunctions.
     307             :         // Stage 2 is executed by deduce_target_char_impl<T> and
     308             :         // deduce_source_char_impl<T>
     309             :         //
     310             :         // deduce_target_char<T> and deduce_source_char<T> functions combine
     311             :         // both stages
     312             : 
     313             :         template < class T >
     314             :         struct deduce_target_char
     315             :         {
     316             :             typedef typename stream_char_common< T >::type stage1_type;
     317             :             typedef typename deduce_target_char_impl< stage1_type >::type type;
     318             :         };
     319             : 
     320             :         template < class T >
     321             :         struct deduce_source_char
     322             :         {
     323             :             typedef typename stream_char_common< T >::type stage1_type;
     324             :             typedef typename deduce_source_char_impl< stage1_type >::type type;
     325             :         };
     326             :     }
     327             : 
     328             :     namespace detail // array_to_pointer_decay<T>
     329             :     {
     330             :         template<class T>
     331             :         struct array_to_pointer_decay
     332             :         {
     333             :             typedef T type;
     334             :         };
     335             : 
     336             :         template<class T, std::size_t N>
     337             :         struct array_to_pointer_decay<T[N]>
     338             :         {
     339             :             typedef const T * type;
     340             :         };
     341             :     }
     342             : 
     343             :     namespace detail // lcast_src_length
     344             :     {
     345             :         // Return max. length of string representation of Source;
     346             :         template< class Source,         // Source type of lexical_cast.
     347             :                   class Enable = void   // helper type
     348             :                 >
     349             :         struct lcast_src_length
     350             :         {
     351             :             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
     352             :         };
     353             : 
     354             :         // Helper for integral types.
     355             :         // Notes on length calculation:
     356             :         // Max length for 32bit int with grouping "\1" and thousands_sep ',':
     357             :         // "-2,1,4,7,4,8,3,6,4,7"
     358             :         //  ^                    - is_signed
     359             :         //   ^                   - 1 digit not counted by digits10
     360             :         //    ^^^^^^^^^^^^^^^^^^ - digits10 * 2
     361             :         //
     362             :         // Constant is_specialized is used instead of constant 1
     363             :         // to prevent buffer overflow in a rare case when
     364             :         // <boost/limits.hpp> doesn't add missing specialization for
     365             :         // numeric_limits<T> for some integral type T.
     366             :         // When is_specialized is false, the whole expression is 0.
     367             :         template <class Source>
     368             :         struct lcast_src_length<
     369             :                     Source, typename std::enable_if<boost::detail::lcast::is_integral<Source>::value >::type
     370             :                 >
     371             :         {
     372             :             BOOST_STATIC_CONSTANT(std::size_t, value =
     373             :                   std::numeric_limits<Source>::is_signed +
     374             :                   std::numeric_limits<Source>::is_specialized + /* == 1 */
     375             :                   std::numeric_limits<Source>::digits10 * 2
     376             :               );
     377             :         };
     378             : 
     379             :         // Helper for floating point types.
     380             :         // -1.23456789e-123456
     381             :         // ^                   sign
     382             :         //  ^                  leading digit
     383             :         //   ^                 decimal point
     384             :         //    ^^^^^^^^         lcast_precision<Source>::value
     385             :         //            ^        "e"
     386             :         //             ^       exponent sign
     387             :         //              ^^^^^^ exponent (assumed 6 or less digits)
     388             :         // sign + leading digit + decimal point + "e" + exponent sign == 5
     389             :         template<class Source>
     390             :         struct lcast_src_length<
     391             :                 Source, typename std::enable_if<std::is_floating_point<Source>::value >::type
     392             :             >
     393             :         {
     394             :             static_assert(
     395             :                     std::numeric_limits<Source>::max_exponent10 <=  999999L &&
     396             :                     std::numeric_limits<Source>::min_exponent10 >= -999999L
     397             :                 , "");
     398             : 
     399             :             BOOST_STATIC_CONSTANT(std::size_t, value =
     400             :                     5 + lcast_precision<Source>::value + 6
     401             :                 );
     402             :         };
     403             :     }
     404             : 
     405             :     namespace detail // lexical_cast_stream_traits<Source, Target>
     406             :     {
     407             :         template <class Source, class Target>
     408             :         struct lexical_cast_stream_traits {
     409             :             typedef typename boost::detail::array_to_pointer_decay<Source>::type src;
     410             :             typedef typename std::remove_cv<src>::type            no_cv_src;
     411             : 
     412             :             typedef boost::detail::deduce_source_char<no_cv_src>                           deduce_src_char_metafunc;
     413             :             typedef typename deduce_src_char_metafunc::type           src_char_t;
     414             :             typedef typename boost::detail::deduce_target_char<Target>::type target_char_t;
     415             : 
     416             :             typedef typename boost::detail::widest_char<
     417             :                 target_char_t, src_char_t
     418             :             >::type char_type;
     419             : 
     420             : #if !defined(BOOST_NO_CXX11_CHAR16_T) && defined(BOOST_NO_CXX11_UNICODE_LITERALS)
     421             :             static_assert(!std::is_same<char16_t, src_char_t>::value
     422             :                                         && !std::is_same<char16_t, target_char_t>::value,
     423             :                 "Your compiler does not have full support for char16_t" );
     424             : #endif
     425             : #if !defined(BOOST_NO_CXX11_CHAR32_T) && defined(BOOST_NO_CXX11_UNICODE_LITERALS)
     426             :             static_assert(!std::is_same<char32_t, src_char_t>::value
     427             :                                         && !std::is_same<char32_t, target_char_t>::value,
     428             :                 "Your compiler does not have full support for char32_t" );
     429             : #endif
     430             : 
     431             :             typedef std::char_traits<char_type> traits;
     432             : 
     433             :             typedef boost::detail::lcast_src_length<no_cv_src> len_t;
     434             :         };
     435             :     }
     436             : 
     437             :     namespace detail
     438             :     {
     439             :         template<typename Target, typename Source>
     440             :         struct lexical_converter_impl
     441             :         {
     442             :             typedef lexical_cast_stream_traits<Source, Target>  stream_trait;
     443             : 
     444             :             typedef detail::lcast::optimized_src_stream<
     445             :                 typename stream_trait::char_type,
     446             :                 typename stream_trait::traits,
     447             :                 stream_trait::len_t::value + 1
     448             :             > optimized_src_stream;
     449             :             
     450             :             template <class T>
     451             :             static auto detect_type(int)
     452             :                 -> decltype(std::declval<optimized_src_stream&>().stream_in(std::declval<lcast::exact<T>>()), optimized_src_stream{});
     453             : 
     454             :             template <class T>
     455             :             static lcast::ios_src_stream<typename stream_trait::char_type, typename stream_trait::traits> detect_type(...);
     456             : 
     457             :             using from_src_stream = decltype(detect_type<Source>(1));
     458             : 
     459             :             typedef detail::lcast::to_target_stream<
     460             :                 typename stream_trait::char_type,
     461             :                 typename stream_trait::traits
     462             :             > to_target_stream;
     463             : 
     464          36 :             static inline bool try_convert(const Source& arg, Target& result) {
     465          36 :                 from_src_stream src_stream;
     466          36 :                 if (!src_stream.stream_in(lcast::exact<Source>{arg}))
     467           0 :                     return false;
     468             : 
     469          36 :                 to_target_stream out(src_stream.cbegin(), src_stream.cend());
     470          36 :                 if (!out.stream_out(result))
     471           0 :                     return false;
     472             : 
     473          36 :                 return true;
     474          36 :             }
     475             :         };
     476             :     }
     477             : 
     478             : } // namespace boost
     479             : 
     480             : #undef BOOST_LCAST_NO_WCHAR_T
     481             : 
     482             : #endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP
     483             : 

Generated by: LCOV version 1.16