converter_lexical_streams.hpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. // Copyright Kevlin Henney, 2000-2005.
  2. // Copyright Alexander Nasonov, 2006-2010.
  3. // Copyright Antony Polukhin, 2011-2025.
  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, Nowember 2016
  17. #ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_STREAMS_HPP
  18. #define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_STREAMS_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 <cstring>
  29. #include <cstdio>
  30. #include <type_traits>
  31. #include <boost/limits.hpp>
  32. #include <boost/detail/lcast_precision.hpp>
  33. #include <boost/lexical_cast/detail/type_traits.hpp>
  34. #include <boost/config/workaround.hpp>
  35. #include <boost/core/snprintf.hpp>
  36. #ifndef BOOST_NO_STD_LOCALE
  37. # include <locale>
  38. #else
  39. # ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
  40. // Getting error at this point means, that your STL library is old/lame/misconfigured.
  41. // If nothing can be done with STL library, define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE,
  42. // but beware: lexical_cast will understand only 'C' locale delimeters and thousands
  43. // separators.
  44. # error "Unable to use <locale> header. Define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE to force "
  45. # error "boost::lexical_cast to use only 'C' locale during conversions."
  46. # endif
  47. #endif
  48. #ifdef BOOST_NO_STRINGSTREAM
  49. #include <strstream>
  50. #else
  51. #include <sstream>
  52. #endif
  53. #include <boost/lexical_cast/detail/buffer_view.hpp>
  54. #include <boost/lexical_cast/detail/lcast_char_constants.hpp>
  55. #include <boost/lexical_cast/detail/lcast_unsigned_converters.hpp>
  56. #include <boost/lexical_cast/detail/lcast_basic_unlockedbuf.hpp>
  57. #include <boost/lexical_cast/detail/inf_nan.hpp>
  58. #include <istream>
  59. #include <array>
  60. #include <boost/container/container_fwd.hpp>
  61. #ifndef BOOST_NO_CWCHAR
  62. # include <cwchar>
  63. #endif
  64. // Forward declarations
  65. namespace boost {
  66. template<class T, std::size_t N>
  67. class array;
  68. template<class IteratorT>
  69. class iterator_range;
  70. // forward declaration of boost::basic_string_view from Utility
  71. template<class Ch, class Tr> class basic_string_view;
  72. }
  73. namespace boost { namespace detail { namespace lcast {
  74. template <typename T>
  75. struct exact {
  76. static_assert(!std::is_const<T>::value, "");
  77. static_assert(!std::is_reference<T>::value, "");
  78. const T& payload;
  79. };
  80. template< class CharT // a result of widest_char transformation
  81. , class Traits
  82. , std::size_t CharacterBufferSize
  83. >
  84. class optimized_src_stream {
  85. CharT buffer[CharacterBufferSize];
  86. // After the `stream_in(` finishes, `[start, finish)` is
  87. // the range to output by `operator >>`
  88. const CharT* start;
  89. const CharT* finish;
  90. public:
  91. optimized_src_stream(optimized_src_stream&&) = delete;
  92. optimized_src_stream(const optimized_src_stream&) = delete;
  93. optimized_src_stream& operator=(optimized_src_stream&&) = delete;
  94. optimized_src_stream& operator=(const optimized_src_stream&) = delete;
  95. optimized_src_stream() noexcept
  96. : start(buffer)
  97. , finish(buffer + CharacterBufferSize)
  98. {}
  99. const CharT* cbegin() const noexcept {
  100. return start;
  101. }
  102. const CharT* cend() const noexcept {
  103. return finish;
  104. }
  105. private:
  106. bool shl_char(CharT ch) noexcept {
  107. Traits::assign(buffer[0], ch);
  108. finish = start + 1;
  109. return true;
  110. }
  111. #ifndef BOOST_LCAST_NO_WCHAR_T
  112. template <class T>
  113. bool shl_char(T ch) {
  114. static_assert(sizeof(T) <= sizeof(CharT),
  115. "boost::lexical_cast does not support narrowing of char types."
  116. "Use boost::locale instead" );
  117. #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
  118. std::locale loc;
  119. CharT const w = BOOST_USE_FACET(std::ctype<CharT>, loc).widen(ch);
  120. #else
  121. CharT const w = static_cast<CharT>(ch);
  122. #endif
  123. Traits::assign(buffer[0], w);
  124. finish = start + 1;
  125. return true;
  126. }
  127. #endif
  128. bool shl_char_array(CharT const* str_value) noexcept {
  129. start = str_value;
  130. finish = start + Traits::length(str_value);
  131. return true;
  132. }
  133. bool shl_char_array_limited(CharT const* str, std::size_t max_size) noexcept {
  134. start = str;
  135. finish = start;
  136. const auto zero = Traits::to_char_type(0);
  137. while (finish < start + max_size && zero != *finish) {
  138. ++ finish;
  139. }
  140. return true;
  141. }
  142. template <class T>
  143. inline bool shl_unsigned(const T n) {
  144. CharT* tmp_finish = buffer + CharacterBufferSize;
  145. start = lcast_put_unsigned<Traits, T, CharT>(n, tmp_finish).convert();
  146. finish = tmp_finish;
  147. return true;
  148. }
  149. template <class T>
  150. inline bool shl_signed(const T n) {
  151. CharT* tmp_finish = buffer + CharacterBufferSize;
  152. typedef typename boost::detail::lcast::make_unsigned<T>::type utype;
  153. CharT* tmp_start = lcast_put_unsigned<Traits, utype, CharT>(lcast_to_unsigned(n), tmp_finish).convert();
  154. if (n < 0) {
  155. --tmp_start;
  156. CharT const minus = lcast_char_constants<CharT>::minus;
  157. Traits::assign(*tmp_start, minus);
  158. }
  159. start = tmp_start;
  160. finish = tmp_finish;
  161. return true;
  162. }
  163. bool shl_real_type(lcast::exact<float> val, char* begin) {
  164. const double val_as_double = static_cast<double>(val.payload);
  165. finish = start +
  166. boost::core::snprintf(begin, CharacterBufferSize,
  167. "%.*g", static_cast<int>(boost::detail::lcast_precision<float>::value), val_as_double);
  168. return finish > start;
  169. }
  170. bool shl_real_type(lcast::exact<double> val, char* begin) {
  171. finish = start +
  172. boost::core::snprintf(begin, CharacterBufferSize,
  173. "%.*g", static_cast<int>(boost::detail::lcast_precision<double>::value), val.payload);
  174. return finish > start;
  175. }
  176. #ifndef __MINGW32__
  177. bool shl_real_type(lcast::exact<long double> val, char* begin) {
  178. finish = start +
  179. boost::core::snprintf(begin, CharacterBufferSize,
  180. "%.*Lg", static_cast<int>(boost::detail::lcast_precision<long double>::value), val.payload );
  181. return finish > start;
  182. }
  183. #else
  184. bool shl_real_type(lcast::exact<long double> val, char* begin) {
  185. return shl_real_type(lcast::exact<double>{static_cast<double>(val.payload)}, begin);
  186. }
  187. #endif
  188. #if !defined(BOOST_LCAST_NO_WCHAR_T)
  189. bool shl_real_type(lcast::exact<float> val, wchar_t* begin) {
  190. const double val_as_double = static_cast<double>(val.payload);
  191. finish = start + boost::core::swprintf(
  192. begin, CharacterBufferSize, L"%.*g",
  193. static_cast<int>(boost::detail::lcast_precision<float>::value),
  194. val_as_double
  195. );
  196. return finish > start;
  197. }
  198. bool shl_real_type(lcast::exact<double> val, wchar_t* begin) {
  199. finish = start + boost::core::swprintf(
  200. begin, CharacterBufferSize, L"%.*g",
  201. static_cast<int>(boost::detail::lcast_precision<double>::value),
  202. val.payload
  203. );
  204. return finish > start;
  205. }
  206. bool shl_real_type(lcast::exact<long double> val, wchar_t* begin) {
  207. finish = start + boost::core::swprintf(
  208. begin, CharacterBufferSize, L"%.*Lg",
  209. static_cast<int>(boost::detail::lcast_precision<long double>::value),
  210. val.payload
  211. );
  212. return finish > start;
  213. }
  214. #endif
  215. public:
  216. template <class C>
  217. using enable_if_compatible_char_t = typename std::enable_if<
  218. std::is_same<const C, const CharT>::value || (
  219. std::is_same<const char, const CharT>::value && (
  220. std::is_same<const C, const unsigned char>::value ||
  221. std::is_same<const C, const signed char>::value
  222. )
  223. ), bool
  224. >::type;
  225. template<class CharTraits, class Alloc>
  226. bool stream_in(lcast::exact<std::basic_string<CharT,CharTraits,Alloc>> x) noexcept {
  227. start = x.payload.data();
  228. finish = start + x.payload.length();
  229. return true;
  230. }
  231. template<class CharTraits, class Alloc>
  232. bool stream_in(lcast::exact<boost::container::basic_string<CharT,CharTraits,Alloc>> x) noexcept {
  233. start = x.payload.data();
  234. finish = start + x.payload.length();
  235. return true;
  236. }
  237. bool stream_in(lcast::exact<bool> x) noexcept {
  238. CharT const czero = lcast_char_constants<CharT>::zero;
  239. Traits::assign(buffer[0], Traits::to_char_type(czero + x.payload));
  240. finish = start + 1;
  241. return true;
  242. }
  243. bool stream_in(lcast::exact<boost::conversion::detail::buffer_view<CharT>> x) noexcept {
  244. start = x.payload.begin;
  245. finish = x.payload.end;
  246. return true;
  247. }
  248. template <class C>
  249. enable_if_compatible_char_t<C>
  250. stream_in(lcast::exact<boost::iterator_range<C*>> x) noexcept {
  251. auto buf = boost::conversion::detail::make_buffer_view(x.payload.begin(), x.payload.end());
  252. return stream_in(lcast::exact<decltype(buf)>{buf});
  253. }
  254. bool stream_in(lcast::exact<char> x) { return shl_char(x.payload); }
  255. bool stream_in(lcast::exact<unsigned char> x) { return shl_char(static_cast<char>(x.payload)); }
  256. bool stream_in(lcast::exact<signed char> x) { return shl_char(static_cast<char>(x.payload)); }
  257. #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
  258. template <class C>
  259. typename std::enable_if<boost::detail::is_character<C>::value, bool>::type
  260. stream_in(lcast::exact<C> x) { return shl_char(x.payload); }
  261. #endif
  262. template <class Type>
  263. enable_if_compatible_char_t<Type>
  264. stream_in(lcast::exact<Type*> x) { return shl_char_array(reinterpret_cast<CharT const*>(x.payload)); }
  265. template <class Type>
  266. typename std::enable_if<!std::is_floating_point<Type>::value && boost::detail::lcast::is_signed<Type>::value && !std::is_enum<Type>::value, bool>::type
  267. stream_in(lcast::exact<Type> x) { return shl_signed(x.payload); }
  268. template <class Type>
  269. typename std::enable_if<boost::detail::lcast::is_unsigned<Type>::value && !std::is_enum<Type>::value, bool>::type
  270. stream_in(lcast::exact<Type> x) { return shl_unsigned(x.payload); }
  271. template <class Type>
  272. auto stream_in(lcast::exact<Type> x) -> decltype(shl_real_type(x, buffer)) {
  273. const CharT* inf_nan = detail::get_inf_nan(x.payload, CharT());
  274. if (inf_nan) {
  275. start = inf_nan;
  276. finish = start + Traits::length(inf_nan);
  277. return true;
  278. }
  279. return shl_real_type(x, buffer);
  280. }
  281. template <class C, std::size_t N>
  282. enable_if_compatible_char_t<C>
  283. stream_in(lcast::exact<boost::array<C, N>> x) noexcept {
  284. return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), N);
  285. }
  286. template <class C, std::size_t N>
  287. enable_if_compatible_char_t<C>
  288. stream_in(lcast::exact<std::array<C, N>> x) noexcept {
  289. return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), N);
  290. }
  291. #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
  292. template <class C, class CharTraits>
  293. enable_if_compatible_char_t<C>
  294. stream_in(lcast::exact<std::basic_string_view<C, CharTraits>> x) noexcept {
  295. start = reinterpret_cast<const CharT*>(x.payload.data());
  296. finish = start + x.payload.size();
  297. return true;
  298. }
  299. #endif
  300. template <class C, class CharTraits>
  301. enable_if_compatible_char_t<C>
  302. stream_in(lcast::exact<boost::basic_string_view<C, CharTraits>> x) noexcept {
  303. start = reinterpret_cast<const CharT*>(x.payload.data());
  304. finish = start + x.payload.size();
  305. return true;
  306. }
  307. };
  308. template <class CharT, class Traits>
  309. class ios_src_stream {
  310. typedef detail::lcast::out_stream_t<CharT, Traits> deduced_out_stream_t;
  311. typedef detail::lcast::stringbuffer_t<CharT, Traits> deduced_out_buffer_t;
  312. deduced_out_buffer_t out_buffer;
  313. deduced_out_stream_t out_stream;
  314. const CharT* start = nullptr;
  315. const CharT* finish = nullptr;
  316. public:
  317. ios_src_stream(ios_src_stream&&) = delete;
  318. ios_src_stream(const ios_src_stream&) = delete;
  319. ios_src_stream& operator=(ios_src_stream&&) = delete;
  320. ios_src_stream& operator=(const ios_src_stream&) = delete;
  321. ios_src_stream(): out_buffer(), out_stream(&out_buffer) {}
  322. const CharT* cbegin() const noexcept {
  323. return start;
  324. }
  325. const CharT* cend() const noexcept {
  326. return finish;
  327. }
  328. private:
  329. const deduced_out_buffer_t* get_rdbuf() const {
  330. return static_cast<deduced_out_buffer_t*>(
  331. out_stream.rdbuf()
  332. );
  333. }
  334. template<typename InputStreamable>
  335. bool shl_input_streamable(InputStreamable& input) {
  336. #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE)
  337. // If you have compilation error at this point, than your STL library
  338. // does not support such conversions. Try updating it.
  339. static_assert(std::is_same<char, CharT>::value, "");
  340. #endif
  341. #ifndef BOOST_NO_EXCEPTIONS
  342. out_stream.exceptions(std::ios::badbit);
  343. try {
  344. #endif
  345. bool const result = !(out_stream << input).fail();
  346. const auto* const p = get_rdbuf();
  347. start = p->pbase();
  348. finish = p->pptr();
  349. return result;
  350. #ifndef BOOST_NO_EXCEPTIONS
  351. } catch (const ::std::ios_base::failure& /*f*/) {
  352. return false;
  353. }
  354. #endif
  355. }
  356. template <class T>
  357. bool shl_char_array(T const* str_value) {
  358. static_assert(sizeof(T) <= sizeof(CharT),
  359. "boost::lexical_cast does not support narrowing of char types."
  360. "Use boost::locale instead" );
  361. return shl_input_streamable(str_value);
  362. }
  363. template <class T>
  364. bool shl_real(T val) {
  365. const CharT* inf_nan = detail::get_inf_nan(val, CharT());
  366. if (inf_nan) {
  367. start = inf_nan;
  368. finish = start + Traits::length(inf_nan);
  369. return true;
  370. }
  371. boost::detail::lcast_set_precision(out_stream, &val);
  372. return shl_input_streamable(val);
  373. }
  374. public:
  375. template <class Type>
  376. typename std::enable_if<boost::detail::is_character<Type>::value && sizeof(char) == sizeof(Type), bool>::type
  377. stream_in(lcast::exact<const Type*> x) { return shl_char_array(reinterpret_cast<char const*>(x.payload)); }
  378. template <class Type>
  379. typename std::enable_if<boost::detail::is_character<Type>::value && sizeof(char) != sizeof(Type), bool>::type
  380. stream_in(lcast::exact<const Type*> x) { return shl_char_array(x.payload); }
  381. bool stream_in(lcast::exact<float> x) { return shl_real(x.payload); }
  382. bool stream_in(lcast::exact<double> x) { return shl_real(x.payload); }
  383. bool stream_in(lcast::exact<long double> x) {
  384. #ifndef __MINGW32__
  385. return shl_real(x.payload);
  386. #else
  387. return shl_real(static_cast<double>(x.payload));
  388. #endif
  389. }
  390. template <class C>
  391. typename std::enable_if<boost::detail::is_character<C>::value, bool>::type
  392. stream_in(lcast::exact<iterator_range<C*>> x) noexcept {
  393. auto buf = boost::conversion::detail::make_buffer_view(x.payload.begin(), x.payload.end());
  394. return stream_in(lcast::exact<decltype(buf)>{buf});
  395. }
  396. template <class C>
  397. typename std::enable_if<boost::detail::is_character<C>::value, bool>::type
  398. stream_in(lcast::exact<iterator_range<const C*>> x) noexcept {
  399. auto buf = boost::conversion::detail::make_buffer_view(x.payload.begin(), x.payload.end());
  400. return stream_in(lcast::exact<decltype(buf)>{buf});
  401. }
  402. template <class InStreamable>
  403. bool stream_in(lcast::exact<InStreamable> x) { return shl_input_streamable(x.payload); }
  404. };
  405. template <class CharT, class Traits>
  406. class to_target_stream {
  407. //`[start, finish)` is the range to output by `operator >>`
  408. const CharT* start;
  409. const CharT* const finish;
  410. public:
  411. to_target_stream(to_target_stream&&) = delete;
  412. to_target_stream(const to_target_stream&) = delete;
  413. to_target_stream& operator=(to_target_stream&&) = delete;
  414. to_target_stream& operator=(const to_target_stream&) = delete;
  415. to_target_stream(const CharT* begin, const CharT* end) noexcept
  416. : start(begin)
  417. , finish(end)
  418. {}
  419. private:
  420. template <typename Type>
  421. #if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6)
  422. __attribute__((no_sanitize("unsigned-integer-overflow")))
  423. #endif
  424. bool shr_unsigned(Type& output) {
  425. if (start == finish) return false;
  426. CharT const minus = lcast_char_constants<CharT>::minus;
  427. CharT const plus = lcast_char_constants<CharT>::plus;
  428. bool const has_minus = Traits::eq(minus, *start);
  429. /* We won`t use `start' any more, so no need in decrementing it after */
  430. if (has_minus || Traits::eq(plus, *start)) {
  431. ++start;
  432. }
  433. bool const succeed = lcast_ret_unsigned<Traits, Type, CharT>(output, start, finish).convert();
  434. if (has_minus) {
  435. output = static_cast<Type>(0u - output);
  436. }
  437. return succeed;
  438. }
  439. template <typename Type>
  440. #if defined(__clang__) && (__clang_major__ > 3 || __clang_minor__ > 6)
  441. __attribute__((no_sanitize("unsigned-integer-overflow")))
  442. #endif
  443. bool shr_signed(Type& output) {
  444. if (start == finish) return false;
  445. CharT const minus = lcast_char_constants<CharT>::minus;
  446. CharT const plus = lcast_char_constants<CharT>::plus;
  447. typedef typename boost::detail::lcast::make_unsigned<Type>::type utype;
  448. utype out_tmp = 0;
  449. bool const has_minus = Traits::eq(minus, *start);
  450. /* We won`t use `start' any more, so no need in decrementing it after */
  451. if (has_minus || Traits::eq(plus, *start)) {
  452. ++start;
  453. }
  454. bool succeed = lcast_ret_unsigned<Traits, utype, CharT>(out_tmp, start, finish).convert();
  455. if (has_minus) {
  456. utype const comp_val = (static_cast<utype>(1) << std::numeric_limits<Type>::digits);
  457. succeed = succeed && out_tmp<=comp_val;
  458. output = static_cast<Type>(0u - out_tmp);
  459. } else {
  460. utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)());
  461. succeed = succeed && out_tmp<=comp_val;
  462. output = static_cast<Type>(out_tmp);
  463. }
  464. return succeed;
  465. }
  466. template<typename InputStreamable>
  467. bool shr_using_base_class(InputStreamable& output)
  468. {
  469. static_assert(
  470. !std::is_pointer<InputStreamable>::value,
  471. "boost::lexical_cast can not convert to pointers"
  472. );
  473. #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE)
  474. static_assert(std::is_same<char, CharT>::value,
  475. "boost::lexical_cast can not convert, because your STL library does not "
  476. "support such conversions. Try updating it."
  477. );
  478. #endif
  479. #if defined(BOOST_NO_STRINGSTREAM)
  480. std::istrstream stream(start, static_cast<std::istrstream::streamsize>(finish - start));
  481. #else
  482. typedef detail::lcast::buffer_t<CharT, Traits> buffer_t;
  483. buffer_t buf;
  484. // Usually `istream` and `basic_istream` do not modify
  485. // content of buffer; `buffer_t` assures that this is true
  486. buf.setbuf(const_cast<CharT*>(start), static_cast<typename buffer_t::streamsize>(finish - start));
  487. #if defined(BOOST_NO_STD_LOCALE)
  488. std::istream stream(&buf);
  489. #else
  490. std::basic_istream<CharT, Traits> stream(&buf);
  491. #endif // BOOST_NO_STD_LOCALE
  492. #endif // BOOST_NO_STRINGSTREAM
  493. #ifndef BOOST_NO_EXCEPTIONS
  494. stream.exceptions(std::ios::badbit);
  495. try {
  496. #endif
  497. stream.unsetf(std::ios::skipws);
  498. boost::detail::lcast_set_precision(stream, static_cast<InputStreamable*>(0));
  499. return (stream >> output)
  500. && (stream.get() == Traits::eof());
  501. #ifndef BOOST_NO_EXCEPTIONS
  502. } catch (const ::std::ios_base::failure& /*f*/) {
  503. return false;
  504. }
  505. #endif
  506. }
  507. template<class T>
  508. inline bool shr_xchar(T& output) noexcept {
  509. static_assert(sizeof(CharT) == sizeof(T),
  510. "boost::lexical_cast does not support narrowing of character types."
  511. "Use boost::locale instead" );
  512. bool const ok = (finish - start == 1);
  513. if (ok) {
  514. CharT out;
  515. Traits::assign(out, *start);
  516. output = static_cast<T>(out);
  517. }
  518. return ok;
  519. }
  520. template <std::size_t N, class ArrayT>
  521. bool shr_std_array(ArrayT& output) noexcept {
  522. const std::size_t size = static_cast<std::size_t>(finish - start);
  523. if (size > N - 1) { // `-1` because we need to store \0 at the end
  524. return false;
  525. }
  526. std::memcpy(&output[0], start, size * sizeof(CharT));
  527. output[size] = Traits::to_char_type(0);
  528. return true;
  529. }
  530. public:
  531. bool stream_out(unsigned short& output) { return shr_unsigned(output); }
  532. bool stream_out(unsigned int& output) { return shr_unsigned(output); }
  533. bool stream_out(unsigned long int& output) { return shr_unsigned(output); }
  534. bool stream_out(short& output) { return shr_signed(output); }
  535. bool stream_out(int& output) { return shr_signed(output); }
  536. bool stream_out(long int& output) { return shr_signed(output); }
  537. #if defined(BOOST_HAS_LONG_LONG)
  538. bool stream_out(boost::ulong_long_type& output) { return shr_unsigned(output); }
  539. bool stream_out(boost::long_long_type& output) { return shr_signed(output); }
  540. #elif defined(BOOST_HAS_MS_INT64)
  541. bool stream_out(unsigned __int64& output) { return shr_unsigned(output); }
  542. bool stream_out(__int64& output) { return shr_signed(output); }
  543. #endif
  544. #ifdef BOOST_HAS_INT128
  545. bool stream_out(boost::uint128_type& output) { return shr_unsigned(output); }
  546. bool stream_out(boost::int128_type& output) { return shr_signed(output); }
  547. #endif
  548. bool stream_out(char& output) { return shr_xchar(output); }
  549. bool stream_out(unsigned char& output) { return shr_xchar(output); }
  550. bool stream_out(signed char& output) { return shr_xchar(output); }
  551. #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
  552. bool stream_out(wchar_t& output) { return shr_xchar(output); }
  553. #endif
  554. #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
  555. bool stream_out(char16_t& output) { return shr_xchar(output); }
  556. #endif
  557. #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
  558. bool stream_out(char32_t& output) { return shr_xchar(output); }
  559. #endif
  560. template<class CharTraits, class Alloc>
  561. bool stream_out(std::basic_string<CharT,CharTraits,Alloc>& str) {
  562. str.assign(start, finish); return true;
  563. }
  564. template<class CharTraits, class Alloc>
  565. bool stream_out(boost::container::basic_string<CharT,CharTraits,Alloc>& str) {
  566. str.assign(start, finish); return true;
  567. }
  568. template <class C, std::size_t N>
  569. bool stream_out(std::array<C, N>& output) noexcept {
  570. static_assert(sizeof(C) == sizeof(CharT), "");
  571. return shr_std_array<N>(output);
  572. }
  573. template <class C, std::size_t N>
  574. bool stream_out(boost::array<C, N>& output) noexcept {
  575. static_assert(sizeof(C) == sizeof(CharT), "");
  576. return shr_std_array<N>(output);
  577. }
  578. bool stream_out(bool& output) noexcept {
  579. output = false; // Suppress warning about uninitalized variable
  580. if (start == finish) return false;
  581. CharT const zero = lcast_char_constants<CharT>::zero;
  582. CharT const plus = lcast_char_constants<CharT>::plus;
  583. CharT const minus = lcast_char_constants<CharT>::minus;
  584. const CharT* const dec_finish = finish - 1;
  585. output = Traits::eq(*dec_finish, zero + 1);
  586. if (!output && !Traits::eq(*dec_finish, zero)) {
  587. return false; // Does not ends on '0' or '1'
  588. }
  589. if (start == dec_finish) return true;
  590. // We may have sign at the beginning
  591. if (Traits::eq(plus, *start) || (Traits::eq(minus, *start) && !output)) {
  592. ++ start;
  593. }
  594. // Skipping zeros
  595. while (start != dec_finish) {
  596. if (!Traits::eq(zero, *start)) {
  597. return false; // Not a zero => error
  598. }
  599. ++ start;
  600. }
  601. return true;
  602. }
  603. private:
  604. // Not optimised converter
  605. template <class T>
  606. bool float_types_converter_internal(T& output) {
  607. if (parse_inf_nan(start, finish, output)) return true;
  608. bool const return_value = shr_using_base_class(output);
  609. /* Some compilers and libraries successfully
  610. * parse 'inf', 'INFINITY', '1.0E', '1.0E-'...
  611. * We are trying to provide a unified behaviour,
  612. * so we just forbid such conversions (as some
  613. * of the most popular compilers/libraries do)
  614. * */
  615. CharT const minus = lcast_char_constants<CharT>::minus;
  616. CharT const plus = lcast_char_constants<CharT>::plus;
  617. CharT const capital_e = lcast_char_constants<CharT>::capital_e;
  618. CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
  619. if ( return_value &&
  620. (
  621. Traits::eq(*(finish-1), lowercase_e) // 1.0e
  622. || Traits::eq(*(finish-1), capital_e) // 1.0E
  623. || Traits::eq(*(finish-1), minus) // 1.0e- or 1.0E-
  624. || Traits::eq(*(finish-1), plus) // 1.0e+ or 1.0E+
  625. )
  626. ) return false;
  627. return return_value;
  628. }
  629. public:
  630. bool stream_out(float& output) { return float_types_converter_internal(output); }
  631. bool stream_out(double& output) { return float_types_converter_internal(output); }
  632. bool stream_out(long double& output) { return float_types_converter_internal(output); }
  633. // Generic istream-based algorithm.
  634. // lcast_streambuf_for_target<InputStreamable>::value is true.
  635. template <typename InputStreamable>
  636. bool stream_out(InputStreamable& output) {
  637. return shr_using_base_class(output);
  638. }
  639. };
  640. }}} // namespace boost::detail::lcast
  641. #undef BOOST_LCAST_NO_WCHAR_T
  642. #endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP