converter_lexical.hpp 19 KB

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