Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:13

0001 // Copyright Kevlin Henney, 2000-2005.
0002 // Copyright Alexander Nasonov, 2006-2010.
0003 // Copyright Antony Polukhin, 2011-2023.
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/type_traits/has_left_shift.hpp>
0039 #include <boost/type_traits/has_right_shift.hpp>
0040 #include <boost/detail/lcast_precision.hpp>
0041 
0042 #include <boost/lexical_cast/detail/widest_char.hpp>
0043 #include <boost/lexical_cast/detail/is_character.hpp>
0044 
0045 #include <array>
0046 
0047 #include <boost/lexical_cast/detail/buffer_view.hpp>
0048 #include <boost/container/container_fwd.hpp>
0049 
0050 #include <boost/lexical_cast/detail/converter_lexical_streams.hpp>
0051 
0052 namespace boost {
0053 
0054     // Forward declaration
0055     template<class T, std::size_t N>
0056     class array;
0057     template<class IteratorT>
0058     class iterator_range;
0059 
0060     namespace detail // normalize_single_byte_char<Char>
0061     {
0062         // Converts signed/unsigned char to char
0063         template < class Char >
0064         struct normalize_single_byte_char
0065         {
0066             typedef Char type;
0067         };
0068 
0069         template <>
0070         struct normalize_single_byte_char< signed char >
0071         {
0072             typedef char type;
0073         };
0074 
0075         template <>
0076         struct normalize_single_byte_char< unsigned char >
0077         {
0078             typedef char type;
0079         };
0080     }
0081 
0082     namespace detail // deduce_character_type_later<T>
0083     {
0084         // Helper type, meaning that stram character for T must be deduced
0085         // at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
0086         template < class T > struct deduce_character_type_later {};
0087     }
0088 
0089     namespace detail // stream_char_common<T>
0090     {
0091         // Selectors to choose stream character type (common for Source and Target)
0092         // Returns one of char, wchar_t, char16_t, char32_t or deduce_character_type_later<T> types
0093         // Executed on Stage 1 (See deduce_source_char<T> and deduce_target_char<T>)
0094         template < typename Type >
0095         struct stream_char_common: public boost::conditional<
0096             boost::detail::is_character< Type >::value,
0097             Type,
0098             boost::detail::deduce_character_type_later< Type >
0099         > {};
0100 
0101         template < typename Char >
0102         struct stream_char_common< Char* >: public boost::conditional<
0103             boost::detail::is_character< Char >::value,
0104             Char,
0105             boost::detail::deduce_character_type_later< Char* >
0106         > {};
0107 
0108         template < typename Char >
0109         struct stream_char_common< const Char* >: public boost::conditional<
0110             boost::detail::is_character< Char >::value,
0111             Char,
0112             boost::detail::deduce_character_type_later< const Char* >
0113         > {};
0114 
0115         template < typename Char >
0116         struct stream_char_common< boost::conversion::detail::buffer_view< Char > >
0117         {
0118             typedef Char type;
0119         };
0120 
0121         template < typename Char >
0122         struct stream_char_common< boost::iterator_range< Char* > >: public boost::conditional<
0123             boost::detail::is_character< Char >::value,
0124             Char,
0125             boost::detail::deduce_character_type_later< boost::iterator_range< Char* > >
0126         > {};
0127 
0128         template < typename Char >
0129         struct stream_char_common< boost::iterator_range< const Char* > >: public boost::conditional<
0130             boost::detail::is_character< Char >::value,
0131             Char,
0132             boost::detail::deduce_character_type_later< boost::iterator_range< const Char* > >
0133         > {};
0134 
0135         template < class Char, class Traits, class Alloc >
0136         struct stream_char_common< std::basic_string< Char, Traits, Alloc > >
0137         {
0138             typedef Char type;
0139         };
0140 
0141         template < class Char, class Traits, class Alloc >
0142         struct stream_char_common< boost::container::basic_string< Char, Traits, Alloc > >
0143         {
0144             typedef Char type;
0145         };
0146 
0147         template < typename Char, std::size_t N >
0148         struct stream_char_common< boost::array< Char, N > >: public boost::conditional<
0149             boost::detail::is_character< Char >::value,
0150             Char,
0151             boost::detail::deduce_character_type_later< boost::array< Char, N > >
0152         > {};
0153 
0154         template < typename Char, std::size_t N >
0155         struct stream_char_common< boost::array< const Char, N > >: public boost::conditional<
0156             boost::detail::is_character< Char >::value,
0157             Char,
0158             boost::detail::deduce_character_type_later< boost::array< const Char, N > >
0159         > {};
0160 
0161 #ifndef BOOST_NO_CXX11_HDR_ARRAY
0162         template < typename Char, std::size_t N >
0163         struct stream_char_common< std::array<Char, N > >: public boost::conditional<
0164             boost::detail::is_character< Char >::value,
0165             Char,
0166             boost::detail::deduce_character_type_later< std::array< Char, N > >
0167         > {};
0168 
0169         template < typename Char, std::size_t N >
0170         struct stream_char_common< std::array< const Char, N > >: public boost::conditional<
0171             boost::detail::is_character< Char >::value,
0172             Char,
0173             boost::detail::deduce_character_type_later< std::array< const Char, N > >
0174         > {};
0175 #endif
0176 
0177 #ifdef BOOST_HAS_INT128
0178         template <> struct stream_char_common< boost::int128_type >: public boost::type_identity< char > {};
0179         template <> struct stream_char_common< boost::uint128_type >: public boost::type_identity< char > {};
0180 #endif
0181 
0182 #if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T)
0183         template <>
0184         struct stream_char_common< wchar_t >
0185         {
0186             typedef char type;
0187         };
0188 #endif
0189     }
0190 
0191     namespace detail // deduce_source_char_impl<T>
0192     {
0193         // If type T is `deduce_character_type_later` type, then tries to deduce
0194         // character type using boost::has_left_shift<T> metafunction.
0195         // Otherwise supplied type T is a character type, that must be normalized
0196         // using normalize_single_byte_char<Char>.
0197         // Executed at Stage 2  (See deduce_source_char<T> and deduce_target_char<T>)
0198         template < class Char >
0199         struct deduce_source_char_impl
0200         {
0201             typedef typename boost::detail::normalize_single_byte_char< Char >::type type;
0202         };
0203 
0204         template < class T >
0205         struct deduce_source_char_impl< deduce_character_type_later< T > >
0206         {
0207             typedef boost::has_left_shift< std::basic_ostream< char >, T > result_t;
0208 
0209 #if defined(BOOST_LCAST_NO_WCHAR_T)
0210             static_assert(result_t::value,
0211                 "Source type is not std::ostream`able and std::wostream`s are not supported by your STL implementation");
0212             typedef char type;
0213 #else
0214             typedef typename boost::conditional<
0215                 result_t::value, char, wchar_t
0216             >::type type;
0217 
0218             static_assert(result_t::value || boost::has_left_shift< std::basic_ostream< type >, T >::value,
0219                 "Source type is neither std::ostream`able nor std::wostream`able");
0220 #endif
0221         };
0222     }
0223 
0224     namespace detail  // deduce_target_char_impl<T>
0225     {
0226         // If type T is `deduce_character_type_later` type, then tries to deduce
0227         // character type using boost::has_right_shift<T> metafunction.
0228         // Otherwise supplied type T is a character type, that must be normalized
0229         // using normalize_single_byte_char<Char>.
0230         // Executed at Stage 2  (See deduce_source_char<T> and deduce_target_char<T>)
0231         template < class Char >
0232         struct deduce_target_char_impl
0233         {
0234             typedef typename normalize_single_byte_char< Char >::type type;
0235         };
0236 
0237         template < class T >
0238         struct deduce_target_char_impl< deduce_character_type_later<T> >
0239         {
0240             typedef boost::has_right_shift<std::basic_istream<char>, T > result_t;
0241 
0242 #if defined(BOOST_LCAST_NO_WCHAR_T)
0243             static_assert(result_t::value,
0244                 "Target type is not std::istream`able and std::wistream`s are not supported by your STL implementation");
0245             typedef char type;
0246 #else
0247             typedef typename boost::conditional<
0248                 result_t::value, char, wchar_t
0249             >::type type;
0250 
0251             static_assert(result_t::value || boost::has_right_shift<std::basic_istream<wchar_t>, T >::value,
0252                 "Target type is neither std::istream`able nor std::wistream`able");
0253 #endif
0254         };
0255     }
0256 
0257     namespace detail  // deduce_target_char<T> and deduce_source_char<T>
0258     {
0259         // We deduce stream character types in two stages.
0260         //
0261         // Stage 1 is common for Target and Source. At Stage 1 we get
0262         // non normalized character type (may contain unsigned/signed char)
0263         // or deduce_character_type_later<T> where T is the original type.
0264         // Stage 1 is executed by stream_char_common<T>
0265         //
0266         // At Stage 2 we normalize character types or try to deduce character
0267         // type using metafunctions.
0268         // Stage 2 is executed by deduce_target_char_impl<T> and
0269         // deduce_source_char_impl<T>
0270         //
0271         // deduce_target_char<T> and deduce_source_char<T> functions combine
0272         // both stages
0273 
0274         template < class T >
0275         struct deduce_target_char
0276         {
0277             typedef typename stream_char_common< T >::type stage1_type;
0278             typedef typename deduce_target_char_impl< stage1_type >::type stage2_type;
0279 
0280             typedef stage2_type type;
0281         };
0282 
0283         template < class T >
0284         struct deduce_source_char
0285         {
0286             typedef typename stream_char_common< T >::type stage1_type;
0287             typedef typename deduce_source_char_impl< stage1_type >::type stage2_type;
0288 
0289             typedef stage2_type type;
0290         };
0291     }
0292 
0293     namespace detail // extract_char_traits template
0294     {
0295         // We are attempting to get char_traits<> from T
0296         // template parameter. Otherwise we'll be using std::char_traits<Char>
0297         template < class Char, class T >
0298         struct extract_char_traits
0299                 : boost::false_type
0300         {
0301             typedef std::char_traits< Char > trait_t;
0302         };
0303 
0304         template < class Char, class Traits, class Alloc >
0305         struct extract_char_traits< Char, std::basic_string< Char, Traits, Alloc > >
0306             : boost::true_type
0307         {
0308             typedef Traits trait_t;
0309         };
0310 
0311         template < class Char, class Traits, class Alloc>
0312         struct extract_char_traits< Char, boost::container::basic_string< Char, Traits, Alloc > >
0313             : boost::true_type
0314         {
0315             typedef Traits trait_t;
0316         };
0317     }
0318 
0319     namespace detail // array_to_pointer_decay<T>
0320     {
0321         template<class T>
0322         struct array_to_pointer_decay
0323         {
0324             typedef T type;
0325         };
0326 
0327         template<class T, std::size_t N>
0328         struct array_to_pointer_decay<T[N]>
0329         {
0330             typedef const T * type;
0331         };
0332     }
0333 
0334     namespace detail // lcast_src_length
0335     {
0336         // Return max. length of string representation of Source;
0337         template< class Source,         // Source type of lexical_cast.
0338                   class Enable = void   // helper type
0339                 >
0340         struct lcast_src_length
0341         {
0342             BOOST_STATIC_CONSTANT(std::size_t, value = 1);
0343         };
0344 
0345         // Helper for integral types.
0346         // Notes on length calculation:
0347         // Max length for 32bit int with grouping "\1" and thousands_sep ',':
0348         // "-2,1,4,7,4,8,3,6,4,7"
0349         //  ^                    - is_signed
0350         //   ^                   - 1 digit not counted by digits10
0351         //    ^^^^^^^^^^^^^^^^^^ - digits10 * 2
0352         //
0353         // Constant is_specialized is used instead of constant 1
0354         // to prevent buffer overflow in a rare case when
0355         // <boost/limits.hpp> doesn't add missing specialization for
0356         // numeric_limits<T> for some integral type T.
0357         // When is_specialized is false, the whole expression is 0.
0358         template <class Source>
0359         struct lcast_src_length<
0360                     Source, typename boost::enable_if<boost::is_integral<Source> >::type
0361                 >
0362         {
0363 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
0364             BOOST_STATIC_CONSTANT(std::size_t, value =
0365                   std::numeric_limits<Source>::is_signed +
0366                   std::numeric_limits<Source>::is_specialized + /* == 1 */
0367                   std::numeric_limits<Source>::digits10 * 2
0368               );
0369 #else
0370             BOOST_STATIC_CONSTANT(std::size_t, value = 156);
0371             static_assert(sizeof(Source) * CHAR_BIT <= 256, "");
0372 #endif
0373         };
0374 
0375         // Helper for floating point types.
0376         // -1.23456789e-123456
0377         // ^                   sign
0378         //  ^                  leading digit
0379         //   ^                 decimal point
0380         //    ^^^^^^^^         lcast_precision<Source>::value
0381         //            ^        "e"
0382         //             ^       exponent sign
0383         //              ^^^^^^ exponent (assumed 6 or less digits)
0384         // sign + leading digit + decimal point + "e" + exponent sign == 5
0385         template<class Source>
0386         struct lcast_src_length<
0387                 Source, typename boost::enable_if<boost::is_float<Source> >::type
0388             >
0389         {
0390 
0391 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
0392             static_assert(
0393                     std::numeric_limits<Source>::max_exponent10 <=  999999L &&
0394                     std::numeric_limits<Source>::min_exponent10 >= -999999L
0395                 , "");
0396 
0397             BOOST_STATIC_CONSTANT(std::size_t, value =
0398                     5 + lcast_precision<Source>::value + 6
0399                 );
0400 #else // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
0401             BOOST_STATIC_CONSTANT(std::size_t, value = 156);
0402 #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
0403         };
0404     }
0405 
0406     namespace detail // lexical_cast_stream_traits<Source, Target>
0407     {
0408         template <class Source, class Target>
0409         struct lexical_cast_stream_traits {
0410             typedef typename boost::detail::array_to_pointer_decay<Source>::type src;
0411             typedef typename boost::remove_cv<src>::type            no_cv_src;
0412 
0413             typedef boost::detail::deduce_source_char<no_cv_src>                           deduce_src_char_metafunc;
0414             typedef typename deduce_src_char_metafunc::type           src_char_t;
0415             typedef typename boost::detail::deduce_target_char<Target>::type target_char_t;
0416 
0417             typedef typename boost::detail::widest_char<
0418                 target_char_t, src_char_t
0419             >::type char_type;
0420 
0421 #if !defined(BOOST_NO_CXX11_CHAR16_T) && defined(BOOST_NO_CXX11_UNICODE_LITERALS)
0422             static_assert(!boost::is_same<char16_t, src_char_t>::value
0423                                         && !boost::is_same<char16_t, target_char_t>::value,
0424                 "Your compiler does not have full support for char16_t" );
0425 #endif
0426 #if !defined(BOOST_NO_CXX11_CHAR32_T) && defined(BOOST_NO_CXX11_UNICODE_LITERALS)
0427             static_assert(!boost::is_same<char32_t, src_char_t>::value
0428                                         && !boost::is_same<char32_t, target_char_t>::value,
0429                 "Your compiler does not have full support for char32_t" );
0430 #endif
0431 
0432             typedef typename boost::conditional<
0433                 boost::detail::extract_char_traits<char_type, Target>::value,
0434                 typename boost::detail::extract_char_traits<char_type, Target>,
0435                 typename boost::detail::extract_char_traits<char_type, no_cv_src>
0436             >::type::trait_t traits;
0437 
0438             typedef boost::integral_constant<
0439               bool,
0440               boost::is_same<char, src_char_t>::value &&                                 // source is not a wide character based type
0441                 (sizeof(char) != sizeof(target_char_t)) &&  // target type is based on wide character
0442                 (!(boost::detail::is_character<no_cv_src>::value))
0443                 > is_string_widening_required_t;
0444 
0445             typedef boost::integral_constant<
0446               bool,
0447                 !(boost::is_integral<no_cv_src>::value ||
0448                   boost::detail::is_character<
0449                     typename deduce_src_char_metafunc::stage1_type          // if we did not get character type at stage1
0450                   >::value                                                           // then we have no optimization for that type
0451                  )
0452                 > is_source_input_not_optimized_t;
0453 
0454             // If we have an optimized conversion for
0455             // Source, we do not need to construct stringbuf.
0456             BOOST_STATIC_CONSTANT(bool, requires_stringbuf =
0457                 (is_string_widening_required_t::value || is_source_input_not_optimized_t::value)
0458             );
0459 
0460             typedef boost::detail::lcast_src_length<no_cv_src> len_t;
0461         };
0462     }
0463 
0464     namespace detail
0465     {
0466         template<typename Target, typename Source>
0467         struct lexical_converter_impl
0468         {
0469             typedef lexical_cast_stream_traits<Source, Target>  stream_trait;
0470 
0471             typedef detail::lexical_istream_limited_src<
0472                 typename stream_trait::char_type,
0473                 typename stream_trait::traits,
0474                 stream_trait::requires_stringbuf,
0475                 stream_trait::len_t::value + 1
0476             > i_interpreter_type;
0477 
0478             typedef detail::lexical_ostream_limited_src<
0479                 typename stream_trait::char_type,
0480                 typename stream_trait::traits
0481             > o_interpreter_type;
0482 
0483             static inline bool try_convert(const Source& arg, Target& result) {
0484                 i_interpreter_type i_interpreter;
0485 
0486                 // Disabling ADL, by directly specifying operators.
0487                 if (!(i_interpreter.operator <<(arg)))
0488                     return false;
0489 
0490                 o_interpreter_type out(i_interpreter.cbegin(), i_interpreter.cend());
0491 
0492                 // Disabling ADL, by directly specifying operators.
0493                 if(!(out.operator >>(result)))
0494                     return false;
0495 
0496                 return true;
0497             }
0498         };
0499     }
0500 
0501 } // namespace boost
0502 
0503 #undef BOOST_LCAST_NO_WCHAR_T
0504 
0505 #endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP
0506