File indexing completed on 2025-07-06 08:17:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
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
0057 template<class T, std::size_t N>
0058 class array;
0059 template<class IteratorT>
0060 class iterator_range;
0061
0062
0063 template<class Ch, class Tr> class basic_string_view;
0064
0065 namespace detail
0066 {
0067
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
0088 {
0089
0090
0091 template < class T > struct deduce_character_type_later {};
0092 }
0093
0094 namespace detail
0095 {
0096
0097
0098
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
0210 {
0211
0212
0213
0214
0215
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
0252 {
0253
0254
0255
0256
0257
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
0294 {
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
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
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
0341 {
0342
0343 template< class Source,
0344 class Enable = void
0345 >
0346 struct lcast_src_length
0347 {
0348 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
0349 };
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
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 +
0372 std::numeric_limits<Source>::digits10 * 2
0373 );
0374 };
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
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
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 }
0476
0477 #undef BOOST_LCAST_NO_WCHAR_T
0478
0479 #endif
0480