LCOV - code coverage report
Current view: top level - usr/include/boost/lexical_cast/detail - converter_lexical.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 5 6 83.3 %
Date: 2022-12-08 13:48:47 Functions: 2 6 33.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14