Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-06 08:17:55

0001 // Copyright Kevlin Henney, 2000-2005.
0002 // Copyright Alexander Nasonov, 2006-2010.
0003 // Copyright Antony Polukhin, 2011-2024.
0004 //
0005 // Distributed under the Boost Software License, Version 1.0. (See
0006 // accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 // what:  lexical_cast custom keyword cast
0010 // who:   contributed by Kevlin Henney,
0011 //        enhanced with contributions from Terje Slettebo,
0012 //        with additional fixes and suggestions from Gennaro Prota,
0013 //        Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
0014 //        Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
0015 //        Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
0016 // when:  November 2000, March 2003, June 2005, June 2006, March 2011 - 2014
0017 
0018 #ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP
0019 #define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP
0020 
0021 #include <boost/config.hpp>
0022 #ifdef BOOST_HAS_PRAGMA_ONCE
0023 #   pragma once
0024 #endif
0025 
0026 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
0027 #define BOOST_LCAST_NO_WCHAR_T
0028 #endif
0029 
0030 #include <cstddef>
0031 #include <string>
0032 #include <boost/limits.hpp>
0033 #include <boost/type_traits/integral_constant.hpp>
0034 #include <boost/type_traits/type_identity.hpp>
0035 #include <boost/type_traits/conditional.hpp>
0036 #include <boost/type_traits/is_integral.hpp>
0037 #include <boost/type_traits/is_float.hpp>
0038 #include <boost/detail/lcast_precision.hpp>
0039 
0040 #include <boost/lexical_cast/detail/widest_char.hpp>
0041 #include <boost/lexical_cast/detail/is_character.hpp>
0042 
0043 #include <array>
0044 
0045 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
0046 #include <string_view>
0047 #endif
0048 
0049 #include <boost/lexical_cast/detail/buffer_view.hpp>
0050 #include <boost/container/container_fwd.hpp>
0051 
0052 #include <boost/lexical_cast/detail/converter_lexical_streams.hpp>
0053 
0054 namespace boost {
0055 
0056     // Forward declaration
0057     template<class T, std::size_t N>
0058     class array;
0059     template<class IteratorT>
0060     class iterator_range;
0061 
0062     // Forward declaration of boost::basic_string_view from Utility
0063     template<class Ch, class Tr> class basic_string_view;
0064 
0065     namespace detail // normalize_single_byte_char<Char>
0066     {
0067         // Converts signed/unsigned char to char
0068         template < class Char >
0069         struct normalize_single_byte_char
0070         {
0071             typedef Char type;
0072         };
0073 
0074         template <>
0075         struct normalize_single_byte_char< signed char >
0076         {
0077             typedef char type;
0078         };
0079 
0080         template <>
0081         struct normalize_single_byte_char< unsigned char >
0082         {
0083             typedef char type;
0084         };
0085     }
0086 
0087     namespace detail // deduce_character_type_later<T>
0088     {
0089         // Helper type, meaning that stram character for T must be deduced
0090         // at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
0091         template < class T > struct deduce_character_type_later {};
0092     }
0093 
0094     namespace detail // stream_char_common<T>
0095     {
0096         // Selectors to choose stream character type (common for Source and Target)
0097         // Returns one of char, wchar_t, char16_t, char32_t or deduce_character_type_later<T> types
0098         // Executed on Stage 1 (See deduce_source_char<T> and deduce_target_char<T>)
0099         template < typename Type >
0100         struct stream_char_common: public boost::conditional<
0101             boost::detail::is_character< Type >::value,
0102             Type,
0103             boost::detail::deduce_character_type_later< Type >
0104         > {};
0105 
0106         template < typename Char >
0107         struct stream_char_common< Char* >: public boost::conditional<
0108             boost::detail::is_character< Char >::value,
0109             Char,
0110             boost::detail::deduce_character_type_later< Char* >
0111         > {};
0112 
0113         template < typename Char >
0114         struct stream_char_common< const Char* >: public boost::conditional<
0115             boost::detail::is_character< Char >::value,
0116             Char,
0117             boost::detail::deduce_character_type_later< const Char* >
0118         > {};
0119 
0120         template < typename Char >
0121         struct stream_char_common< boost::conversion::detail::buffer_view< Char > >
0122         {
0123             typedef Char type;
0124         };
0125 
0126         template < typename Char >
0127         struct stream_char_common< boost::iterator_range< Char* > >: public boost::conditional<
0128             boost::detail::is_character< Char >::value,
0129             Char,
0130             boost::detail::deduce_character_type_later< boost::iterator_range< Char* > >
0131         > {};
0132 
0133         template < typename Char >
0134         struct stream_char_common< boost::iterator_range< const Char* > >: public boost::conditional<
0135             boost::detail::is_character< Char >::value,
0136             Char,
0137             boost::detail::deduce_character_type_later< boost::iterator_range< const Char* > >
0138         > {};
0139 
0140         template < class Char, class Traits, class Alloc >
0141         struct stream_char_common< std::basic_string< Char, Traits, Alloc > >
0142         {
0143             typedef Char type;
0144         };
0145 
0146         template < class Char, class Traits, class Alloc >
0147         struct stream_char_common< boost::container::basic_string< Char, Traits, Alloc > >
0148         {
0149             typedef Char type;
0150         };
0151 
0152         template < typename Char, std::size_t N >
0153         struct stream_char_common< boost::array< Char, N > >: public boost::conditional<
0154             boost::detail::is_character< Char >::value,
0155             Char,
0156             boost::detail::deduce_character_type_later< boost::array< Char, N > >
0157         > {};
0158 
0159         template < typename Char, std::size_t N >
0160         struct stream_char_common< boost::array< const Char, N > >: public boost::conditional<
0161             boost::detail::is_character< Char >::value,
0162             Char,
0163             boost::detail::deduce_character_type_later< boost::array< const Char, N > >
0164         > {};
0165 
0166 #ifndef BOOST_NO_CXX11_HDR_ARRAY
0167         template < typename Char, std::size_t N >
0168         struct stream_char_common< std::array<Char, N > >: public boost::conditional<
0169             boost::detail::is_character< Char >::value,
0170             Char,
0171             boost::detail::deduce_character_type_later< std::array< Char, N > >
0172         > {};
0173 
0174         template < typename Char, std::size_t N >
0175         struct stream_char_common< std::array< const Char, N > >: public boost::conditional<
0176             boost::detail::is_character< Char >::value,
0177             Char,
0178             boost::detail::deduce_character_type_later< std::array< const Char, N > >
0179         > {};
0180 #endif
0181 
0182 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
0183         template < class Char, class Traits >
0184         struct stream_char_common< std::basic_string_view< Char, Traits > >
0185         {
0186             typedef Char type;
0187         };
0188 #endif
0189         template < class Char, class Traits >
0190         struct stream_char_common< boost::basic_string_view< Char, Traits > >
0191         {
0192             typedef Char type;
0193         };
0194 
0195 #ifdef BOOST_HAS_INT128
0196         template <> struct stream_char_common< boost::int128_type >: public boost::type_identity< char > {};
0197         template <> struct stream_char_common< boost::uint128_type >: public boost::type_identity< char > {};
0198 #endif
0199 
0200 #if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T)
0201         template <>
0202         struct stream_char_common< wchar_t >
0203         {
0204             typedef char type;
0205         };
0206 #endif
0207     }
0208 
0209     namespace detail // deduce_source_char_impl<T>
0210     {
0211         // If type T is `deduce_character_type_later` type, then tries to deduce
0212         // character type using streaming metafunctions.
0213         // Otherwise supplied type T is a character type, that must be normalized
0214         // using normalize_single_byte_char<Char>.
0215         // Executed at Stage 2  (See deduce_source_char<T> and deduce_target_char<T>)
0216         template < class Char >
0217         struct deduce_source_char_impl
0218         {
0219             typedef typename boost::detail::normalize_single_byte_char< Char >::type type;
0220         };
0221 
0222         template < class T >
0223         struct deduce_source_char_impl< deduce_character_type_later< T > >
0224         {
0225             template <class U>
0226             static auto left_shift_type(long)
0227                 -> decltype( std::declval<std::basic_ostream< char >&>() << std::declval<const U&>(), char{});
0228 
0229 #if !defined(BOOST_LCAST_NO_WCHAR_T)
0230             template <class U>
0231             static auto left_shift_type(int)
0232                 -> decltype( std::declval<std::basic_ostream< wchar_t >&>() << std::declval<const U&>(), wchar_t{});
0233 #endif
0234 
0235             template <class U>
0236             static void left_shift_type(...);
0237 
0238             using type = decltype(left_shift_type<T>(1L));
0239 
0240             static_assert(!std::is_same<type, void>::value,
0241 #if defined(BOOST_LCAST_NO_WCHAR_T)
0242                 "Source type is not std::ostream`able and std::wostream`s are "
0243                 "not supported by your STL implementation"
0244 #else
0245                 "Source type is neither std::ostream`able nor std::wostream`able"
0246 #endif
0247             );
0248         };
0249     }
0250 
0251     namespace detail  // deduce_target_char_impl<T>
0252     {
0253         // If type T is `deduce_character_type_later` type, then tries to deduce
0254         // character type using boost::has_right_shift<T> metafunction.
0255         // Otherwise supplied type T is a character type, that must be normalized
0256         // using normalize_single_byte_char<Char>.
0257         // Executed at Stage 2  (See deduce_source_char<T> and deduce_target_char<T>)
0258         template < class Char >
0259         struct deduce_target_char_impl
0260         {
0261             typedef typename normalize_single_byte_char< Char >::type type;
0262         };
0263 
0264         template < class T >
0265         struct deduce_target_char_impl< deduce_character_type_later<T> >
0266         {
0267             template <class U>
0268             static auto right_shift_type(long)
0269                 -> decltype( std::declval<std::basic_istream< char >&>() >> std::declval<U&>(), char{});
0270 
0271 #if !defined(BOOST_LCAST_NO_WCHAR_T)
0272             template <class U>
0273             static auto right_shift_type(int)
0274                 -> decltype( std::declval<std::basic_istream< wchar_t >&>() >> std::declval<U&>(), wchar_t{});
0275 #endif
0276 
0277             template <class U>
0278             static void right_shift_type(...);
0279 
0280             using type = decltype(right_shift_type<T>(1L));
0281 
0282             static_assert(!std::is_same<type, void>::value,
0283 #if defined(BOOST_LCAST_NO_WCHAR_T)
0284                "Target type is not std::istream`able and std::wistream`s are "
0285                "not supported by your STL implementation"
0286 #else
0287                "Target type is neither std::istream`able nor std::wistream`able"
0288 #endif
0289             );
0290         };
0291     }
0292 
0293     namespace detail  // deduce_target_char<T> and deduce_source_char<T>
0294     {
0295         // We deduce stream character types in two stages.
0296         //
0297         // Stage 1 is common for Target and Source. At Stage 1 we get
0298         // non normalized character type (may contain unsigned/signed char)
0299         // or deduce_character_type_later<T> where T is the original type.
0300         // Stage 1 is executed by stream_char_common<T>
0301         //
0302         // At Stage 2 we normalize character types or try to deduce character
0303         // type using metafunctions.
0304         // Stage 2 is executed by deduce_target_char_impl<T> and
0305         // deduce_source_char_impl<T>
0306         //
0307         // deduce_target_char<T> and deduce_source_char<T> functions combine
0308         // both stages
0309 
0310         template < class T >
0311         struct deduce_target_char
0312         {
0313             typedef typename stream_char_common< T >::type stage1_type;
0314             typedef typename deduce_target_char_impl< stage1_type >::type type;
0315         };
0316 
0317         template < class T >
0318         struct deduce_source_char
0319         {
0320             typedef typename stream_char_common< T >::type stage1_type;
0321             typedef typename deduce_source_char_impl< stage1_type >::type type;
0322         };
0323     }
0324 
0325     namespace detail // array_to_pointer_decay<T>
0326     {
0327         template<class T>
0328         struct array_to_pointer_decay
0329         {
0330             typedef T type;
0331         };
0332 
0333         template<class T, std::size_t N>
0334         struct array_to_pointer_decay<T[N]>
0335         {
0336             typedef const T * type;
0337         };
0338     }
0339 
0340     namespace detail // lcast_src_length
0341     {
0342         // Return max. length of string representation of Source;
0343         template< class Source,         // Source type of lexical_cast.
0344                   class Enable = void   // helper type
0345                 >
0346         struct lcast_src_length
0347         {
0348             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
0349         };
0350 
0351         // Helper for integral types.
0352         // Notes on length calculation:
0353         // Max length for 32bit int with grouping "\1" and thousands_sep ',':
0354         // "-2,1,4,7,4,8,3,6,4,7"
0355         //  ^                    - is_signed
0356         //   ^                   - 1 digit not counted by digits10
0357         //    ^^^^^^^^^^^^^^^^^^ - digits10 * 2
0358         //
0359         // Constant is_specialized is used instead of constant 1
0360         // to prevent buffer overflow in a rare case when
0361         // <boost/limits.hpp> doesn't add missing specialization for
0362         // numeric_limits<T> for some integral type T.
0363         // When is_specialized is false, the whole expression is 0.
0364         template <class Source>
0365         struct lcast_src_length<
0366                     Source, typename boost::enable_if<boost::is_integral<Source> >::type
0367                 >
0368         {
0369             BOOST_STATIC_CONSTANT(std::size_t, value =
0370                   std::numeric_limits<Source>::is_signed +
0371                   std::numeric_limits<Source>::is_specialized + /* == 1 */
0372                   std::numeric_limits<Source>::digits10 * 2
0373               );
0374         };
0375 
0376         // Helper for floating point types.
0377         // -1.23456789e-123456
0378         // ^                   sign
0379         //  ^                  leading digit
0380         //   ^                 decimal point
0381         //    ^^^^^^^^         lcast_precision<Source>::value
0382         //            ^        "e"
0383         //             ^       exponent sign
0384         //              ^^^^^^ exponent (assumed 6 or less digits)
0385         // sign + leading digit + decimal point + "e" + exponent sign == 5
0386         template<class Source>
0387         struct lcast_src_length<
0388                 Source, typename boost::enable_if<boost::is_float<Source> >::type
0389             >
0390         {
0391             static_assert(
0392                     std::numeric_limits<Source>::max_exponent10 <=  999999L &&
0393                     std::numeric_limits<Source>::min_exponent10 >= -999999L
0394                 , "");
0395 
0396             BOOST_STATIC_CONSTANT(std::size_t, value =
0397                     5 + lcast_precision<Source>::value + 6
0398                 );
0399         };
0400     }
0401 
0402     namespace detail // lexical_cast_stream_traits<Source, Target>
0403     {
0404         template <class Source, class Target>
0405         struct lexical_cast_stream_traits {
0406             typedef typename boost::detail::array_to_pointer_decay<Source>::type src;
0407             typedef typename boost::remove_cv<src>::type            no_cv_src;
0408 
0409             typedef boost::detail::deduce_source_char<no_cv_src>                           deduce_src_char_metafunc;
0410             typedef typename deduce_src_char_metafunc::type           src_char_t;
0411             typedef typename boost::detail::deduce_target_char<Target>::type target_char_t;
0412 
0413             typedef typename boost::detail::widest_char<
0414                 target_char_t, src_char_t
0415             >::type char_type;
0416 
0417 #if !defined(BOOST_NO_CXX11_CHAR16_T) && defined(BOOST_NO_CXX11_UNICODE_LITERALS)
0418             static_assert(!boost::is_same<char16_t, src_char_t>::value
0419                                         && !boost::is_same<char16_t, target_char_t>::value,
0420                 "Your compiler does not have full support for char16_t" );
0421 #endif
0422 #if !defined(BOOST_NO_CXX11_CHAR32_T) && defined(BOOST_NO_CXX11_UNICODE_LITERALS)
0423             static_assert(!boost::is_same<char32_t, src_char_t>::value
0424                                         && !boost::is_same<char32_t, target_char_t>::value,
0425                 "Your compiler does not have full support for char32_t" );
0426 #endif
0427 
0428             typedef std::char_traits<char_type> traits;
0429 
0430             typedef boost::detail::lcast_src_length<no_cv_src> len_t;
0431         };
0432     }
0433 
0434     namespace detail
0435     {
0436         template<typename Target, typename Source>
0437         struct lexical_converter_impl
0438         {
0439             typedef lexical_cast_stream_traits<Source, Target>  stream_trait;
0440 
0441             typedef detail::lcast::optimized_src_stream<
0442                 typename stream_trait::char_type,
0443                 typename stream_trait::traits,
0444                 stream_trait::len_t::value + 1
0445             > optimized_src_stream;
0446             
0447             template <class T>
0448             static auto detect_type(int)
0449                 -> decltype(std::declval<optimized_src_stream&>().stream_in(std::declval<lcast::exact<T>>()), optimized_src_stream{});
0450 
0451             template <class T>
0452             static lcast::ios_src_stream<typename stream_trait::char_type, typename stream_trait::traits> detect_type(...);
0453 
0454             using from_src_stream = decltype(detect_type<Source>(1));
0455 
0456             typedef detail::lcast::to_target_stream<
0457                 typename stream_trait::char_type,
0458                 typename stream_trait::traits
0459             > to_target_stream;
0460 
0461             static inline bool try_convert(const Source& arg, Target& result) {
0462                 from_src_stream src_stream;
0463                 if (!src_stream.stream_in(lcast::exact<Source>{arg}))
0464                     return false;
0465 
0466                 to_target_stream out(src_stream.cbegin(), src_stream.cend());
0467                 if (!out.stream_out(result))
0468                     return false;
0469 
0470                 return true;
0471             }
0472         };
0473     }
0474 
0475 } // namespace boost
0476 
0477 #undef BOOST_LCAST_NO_WCHAR_T
0478 
0479 #endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP
0480