numeric.hpp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  1. /*=============================================================================
  2. Copyright (c) 2001-2014 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  4. Copyright (c) 2011 Jan Frederick Eick
  5. Copyright (c) 2011 Christopher Jefferson
  6. Copyright (c) 2006 Stephen Nutt
  7. Copyright (c) 2019 T. Zachary Laine
  8. Distributed under the Boost Software License, Version 1.0. (See accompanying
  9. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  10. ==============================================================================*/
  11. #ifndef BOOST_PARSER_DETAIL_NUMERIC_HPP
  12. #define BOOST_PARSER_DETAIL_NUMERIC_HPP
  13. #include <boost/parser/detail/text/unpack.hpp>
  14. #if __has_include(<charconv>)
  15. #include <charconv>
  16. #endif
  17. #if defined(__cpp_lib_to_chars)
  18. #define BOOST_PARSER_HAVE_STD_CHARCONV
  19. #define BOOST_PARSER_NUMERIC_NS std_charconv
  20. #elif __has_include(<boost/charconv.hpp>)
  21. #include <boost/charconv.hpp>
  22. #define BOOST_PARSER_HAVE_BOOST_CHARCONV
  23. #define BOOST_PARSER_NUMERIC_NS boost_charconv
  24. #else
  25. #define BOOST_PARSER_NUMERIC_NS spirit_parsers
  26. #endif
  27. #include <type_traits>
  28. #include <cmath>
  29. #if defined(BOOST_PARSER_HAVE_STD_CHARCONV) || \
  30. defined(BOOST_PARSER_HAVE_BOOST_CHARCONV)
  31. #define BOOST_PARSER_HAVE_CHARCONV
  32. #endif
  33. namespace boost::parser::detail_spirit_x3 {
  34. struct unused_type
  35. {};
  36. // Copied from boost/spirit/home/support/char_class.hpp (Boost 1.71), and
  37. // modified not to use Boost.TypeTraits.
  38. template <typename TargetChar, typename SourceChar>
  39. TargetChar cast_char(SourceChar ch)
  40. {
  41. if (std::is_signed_v<TargetChar> != std::is_signed_v<SourceChar>)
  42. {
  43. if (std::is_signed<SourceChar>::value)
  44. {
  45. // source is signed, target is unsigned
  46. typedef std::make_unsigned_t<SourceChar> USourceChar;
  47. return TargetChar(USourceChar(ch));
  48. }
  49. else
  50. {
  51. // source is unsigned, target is signed
  52. typedef std::make_signed_t<SourceChar> SSourceChar;
  53. return TargetChar(SSourceChar(ch));
  54. }
  55. }
  56. else
  57. {
  58. // source and target has same signedness
  59. return TargetChar(ch); // just cast
  60. }
  61. }
  62. // Copied from
  63. // boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp
  64. // (Boost 1.67), and modified not to use Boost.MPL or Boost.PP.
  65. inline constexpr int log2_table[] = {
  66. 0, 0, 1000000, 1584960, 2000000, 2321920, 2584960, 2807350,
  67. 3000000, 3169920, 3321920, 3459430, 3584960, 3700430, 3807350, 3906890,
  68. 4000000, 4087460, 4169920, 4247920, 4321920, 4392310, 4459430, 4523560,
  69. 4584960, 4643850, 4700430, 4754880, 4807350, 4857980, 4906890, 4954190,
  70. 5000000, 5044390, 5087460, 5129280, 5169925};
  71. template<typename T, unsigned Radix>
  72. struct digits_traits
  73. {
  74. static_assert(std::numeric_limits<T>::radix == 2, "");
  75. constexpr static int value =
  76. int((std::numeric_limits<T>::digits * 1000000) / log2_table[Radix]);
  77. };
  78. template <typename T>
  79. struct digits_traits<T, 10>
  80. {
  81. static int constexpr value = std::numeric_limits<T>::digits10;
  82. };
  83. template<unsigned Radix>
  84. struct radix_traits
  85. {
  86. template <typename Char>
  87. inline static bool is_valid(Char ch)
  88. {
  89. if (Radix <= 10)
  90. return (ch >= '0' && ch <= static_cast<Char>('0' + Radix -1));
  91. return (ch >= '0' && ch <= '9')
  92. || (ch >= 'a' && ch <= static_cast<Char>('a' + Radix -10 -1))
  93. || (ch >= 'A' && ch <= static_cast<Char>('A' + Radix -10 -1));
  94. }
  95. template <typename Char>
  96. inline static unsigned digit(Char ch)
  97. {
  98. if (Radix <= 10 || (ch >= '0' && ch <= '9'))
  99. return ch - '0';
  100. return std::tolower(detail_spirit_x3::cast_char<char>(ch)) - 'a' + 10;
  101. }
  102. };
  103. template <unsigned Radix>
  104. struct positive_accumulator
  105. {
  106. template <typename T, typename Char>
  107. inline static void add(T& n, Char ch, std::false_type) // unchecked add
  108. {
  109. const int digit = radix_traits<Radix>::digit(ch);
  110. n = n * T(Radix) + T(digit);
  111. }
  112. template <typename T, typename Char>
  113. inline static bool add(T& n, Char ch, std::true_type) // checked add
  114. {
  115. // Ensure n *= Radix will not overflow
  116. T const max = (std::numeric_limits<T>::max)();
  117. T const val = max / Radix;
  118. if (n > val)
  119. return false;
  120. T tmp = n * Radix;
  121. // Ensure n += digit will not overflow
  122. const int digit = radix_traits<Radix>::digit(ch);
  123. if (tmp > max - digit)
  124. return false;
  125. n = tmp + static_cast<T>(digit);
  126. return true;
  127. }
  128. };
  129. template <unsigned Radix>
  130. struct negative_accumulator
  131. {
  132. template <typename T, typename Char>
  133. inline static void add(T& n, Char ch, std::false_type) // unchecked subtract
  134. {
  135. const int digit = radix_traits<Radix>::digit(ch);
  136. n = n * T(Radix) - T(digit);
  137. }
  138. template <typename T, typename Char>
  139. inline static bool add(T& n, Char ch, std::true_type) // checked subtract
  140. {
  141. // Ensure n *= Radix will not underflow
  142. T const min = (std::numeric_limits<T>::min)();
  143. T const val = min / T(Radix);
  144. if (n < val)
  145. return false;
  146. T tmp = n * Radix;
  147. // Ensure n -= digit will not underflow
  148. int const digit = radix_traits<Radix>::digit(ch);
  149. if (tmp < min + digit)
  150. return false;
  151. n = tmp - static_cast<T>(digit);
  152. return true;
  153. }
  154. };
  155. template <unsigned Radix, typename Accumulator, int MaxDigits>
  156. struct int_extractor
  157. {
  158. template <typename Char, typename T>
  159. inline static bool
  160. call(Char ch, std::size_t count, T& n, std::true_type)
  161. {
  162. std::size_t constexpr
  163. overflow_free = digits_traits<T, Radix>::value - 1;
  164. if (count < overflow_free)
  165. {
  166. Accumulator::add(n, ch, std::false_type{});
  167. }
  168. else
  169. {
  170. if (!Accumulator::add(n, ch, std::true_type{}))
  171. return false; // over/underflow!
  172. }
  173. return true;
  174. }
  175. template <typename Char, typename T>
  176. inline static bool
  177. call(Char ch, std::size_t /*count*/, T& n, std::false_type)
  178. {
  179. // no need to check for overflow
  180. Accumulator::add(n, ch, std::false_type{});
  181. return true;
  182. }
  183. template <typename Char>
  184. inline static bool
  185. call(Char /*ch*/, std::size_t /*count*/, unused_type, std::false_type)
  186. {
  187. return true;
  188. }
  189. template <typename Char, typename T>
  190. inline static bool
  191. call(Char ch, std::size_t count, T& n)
  192. {
  193. return call(ch, count, n
  194. , std::integral_constant<bool,
  195. ( (MaxDigits < 0)
  196. || (MaxDigits > digits_traits<T, Radix>::value)
  197. )
  198. && std::numeric_limits<T>::is_bounded
  199. >()
  200. );
  201. }
  202. };
  203. template <int MaxDigits>
  204. struct check_max_digits
  205. {
  206. inline static bool
  207. call(std::size_t count)
  208. {
  209. return count < MaxDigits; // bounded
  210. }
  211. };
  212. template <>
  213. struct check_max_digits<-1>
  214. {
  215. inline static bool
  216. call(std::size_t /*count*/)
  217. {
  218. return true; // unbounded
  219. }
  220. };
  221. template <
  222. typename T, unsigned Radix, unsigned MinDigits, int MaxDigits
  223. , typename Accumulator = positive_accumulator<Radix>
  224. , bool Accumulate = false
  225. >
  226. struct extract_int_impl
  227. {
  228. template <typename Iterator, typename Sentinel, typename Attribute>
  229. inline static bool
  230. parse_main(
  231. Iterator& first
  232. , Sentinel last
  233. , Attribute& attr)
  234. {
  235. typedef radix_traits<Radix> radix_check;
  236. typedef int_extractor<Radix, Accumulator, MaxDigits> extractor;
  237. typedef
  238. typename std::iterator_traits<Iterator>::value_type char_type;
  239. Iterator it = first;
  240. std::size_t leading_zeros = 0;
  241. if (!Accumulate)
  242. {
  243. // skip leading zeros
  244. while (it != last && *it == '0' && leading_zeros < MaxDigits)
  245. {
  246. ++it;
  247. ++leading_zeros;
  248. }
  249. }
  250. typedef Attribute attribute_type;
  251. attribute_type val = Accumulate ? attr : attribute_type(0);
  252. std::size_t count = 0;
  253. char_type ch;
  254. while (true)
  255. {
  256. if (!check_max_digits<MaxDigits>::call(count + leading_zeros) ||
  257. it == last)
  258. break;
  259. ch = *it;
  260. if (!radix_check::is_valid(ch) ||
  261. !extractor::call(ch, count, val))
  262. break;
  263. ++it;
  264. ++count;
  265. if (!check_max_digits<MaxDigits>::call(count + leading_zeros) ||
  266. it == last)
  267. break;
  268. ch = *it;
  269. if (!radix_check::is_valid(ch) ||
  270. !extractor::call(ch, count, val))
  271. break;
  272. ++it;
  273. ++count;
  274. if (!check_max_digits<MaxDigits>::call(count + leading_zeros) ||
  275. it == last)
  276. break;
  277. ch = *it;
  278. if (!radix_check::is_valid(ch) ||
  279. !extractor::call(ch, count, val))
  280. break;
  281. ++it;
  282. ++count;
  283. }
  284. if (count + leading_zeros >= MinDigits)
  285. {
  286. attr = val;
  287. first = it;
  288. return true;
  289. }
  290. return false;
  291. }
  292. template <typename Iterator, typename Sentinel>
  293. inline static bool
  294. parse(
  295. Iterator& first
  296. , Sentinel last
  297. , unused_type)
  298. {
  299. T n = 0; // must calculate value to detect over/underflow
  300. return parse_main(first, last, n);
  301. }
  302. template <typename Iterator, typename Sentinel, typename Attribute>
  303. inline static bool
  304. parse(
  305. Iterator& first
  306. , Sentinel last
  307. , Attribute& attr)
  308. {
  309. return parse_main(first, last, attr);
  310. }
  311. };
  312. template <typename T, unsigned Radix, typename Accumulator, bool Accumulate>
  313. struct extract_int_impl<T, Radix, 1, -1, Accumulator, Accumulate>
  314. {
  315. template <typename Iterator, typename Sentinel, typename Attribute>
  316. inline static bool
  317. parse_main(
  318. Iterator& first
  319. , Sentinel last
  320. , Attribute& attr)
  321. {
  322. typedef radix_traits<Radix> radix_check;
  323. typedef int_extractor<Radix, Accumulator, -1> extractor;
  324. typedef
  325. typename std::iterator_traits<Iterator>::value_type char_type;
  326. Iterator it = first;
  327. std::size_t count = 0;
  328. if (!Accumulate)
  329. {
  330. // skip leading zeros
  331. while (it != last && *it == '0')
  332. {
  333. ++it;
  334. ++count;
  335. }
  336. if (it == last)
  337. {
  338. if (count == 0) // must have at least one digit
  339. return false;
  340. attr = 0;
  341. first = it;
  342. return true;
  343. }
  344. }
  345. typedef Attribute attribute_type;
  346. attribute_type val = Accumulate ? attr : attribute_type(0);
  347. char_type ch = *it;
  348. if (!radix_check::is_valid(ch) || !extractor::call(ch, 0, val))
  349. {
  350. if (count == 0) // must have at least one digit
  351. return false;
  352. attr = val;
  353. first = it;
  354. return true;
  355. }
  356. count = 0;
  357. ++it;
  358. while (true)
  359. {
  360. if (it == last)
  361. break;
  362. ch = *it;
  363. if (!radix_check::is_valid(ch))
  364. break;
  365. if (!extractor::call(ch, count, val))
  366. return false;
  367. ++it;
  368. ++count;
  369. if (it == last)
  370. break;
  371. ch = *it;
  372. if (!radix_check::is_valid(ch))
  373. break;
  374. if (!extractor::call(ch, count, val))
  375. return false;
  376. ++it;
  377. ++count;
  378. if (it == last)
  379. break;
  380. ch = *it;
  381. if (!radix_check::is_valid(ch))
  382. break;
  383. if (!extractor::call(ch, count, val))
  384. return false;
  385. ++it;
  386. ++count;
  387. }
  388. attr = val;
  389. first = it;
  390. return true;
  391. }
  392. template <typename Iterator, typename Sentinel>
  393. inline static bool
  394. parse(
  395. Iterator& first
  396. , Sentinel last
  397. , unused_type)
  398. {
  399. T n = 0; // must calculate value to detect over/underflow
  400. return parse_main(first, last, n);
  401. }
  402. template <typename Iterator, typename Sentinel, typename Attribute>
  403. inline static bool
  404. parse(
  405. Iterator& first
  406. , Sentinel last
  407. , Attribute& attr)
  408. {
  409. return parse_main(first, last, attr);
  410. }
  411. };
  412. // Copied from boost/spirit/home/x3/support/numeric_utils/extract_int.hpp
  413. // (Boost 1.67), and modified for use with iterator, sentinel pairs:
  414. ///////////////////////////////////////////////////////////////////////////
  415. // Extract the prefix sign (- or +), return true if a '-' was found
  416. ///////////////////////////////////////////////////////////////////////////
  417. template<typename Iterator, typename Sentinel>
  418. inline bool extract_sign(Iterator & first, Sentinel last)
  419. {
  420. (void)last; // silence unused warnings
  421. BOOST_PARSER_DEBUG_ASSERT(first != last); // precondition
  422. // Extract the sign
  423. bool neg = *first == '-';
  424. if (neg || (*first == '+'))
  425. {
  426. ++first;
  427. return neg;
  428. }
  429. return false;
  430. }
  431. ///////////////////////////////////////////////////////////////////////////
  432. // Low level unsigned integer parser
  433. ///////////////////////////////////////////////////////////////////////////
  434. template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits
  435. , bool Accumulate = false>
  436. struct extract_uint
  437. {
  438. // check template parameter 'Radix' for validity
  439. static_assert(
  440. (Radix >= 2 && Radix <= 36),
  441. "Error Unsupported Radix");
  442. template <typename Iterator, typename Sentinel>
  443. inline static bool call(Iterator& first, Sentinel last, T& attr)
  444. {
  445. if (first == last)
  446. return false;
  447. typedef extract_int_impl<
  448. T
  449. , Radix
  450. , MinDigits
  451. , MaxDigits
  452. , positive_accumulator<Radix>
  453. , Accumulate>
  454. extract_type;
  455. Iterator save = first;
  456. if (!extract_type::parse(first, last, attr))
  457. {
  458. first = save;
  459. return false;
  460. }
  461. return true;
  462. }
  463. };
  464. ///////////////////////////////////////////////////////////////////////////
  465. // Low level signed integer parser
  466. ///////////////////////////////////////////////////////////////////////////
  467. template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
  468. struct extract_int
  469. {
  470. // check template parameter 'Radix' for validity
  471. static_assert(
  472. (Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16),
  473. "Error Unsupported Radix");
  474. template <typename Iterator, typename Sentinel>
  475. inline static bool call(Iterator& first, Sentinel last, T& attr)
  476. {
  477. if (first == last)
  478. return false;
  479. typedef extract_int_impl<
  480. T, Radix, MinDigits, MaxDigits>
  481. extract_pos_type;
  482. typedef extract_int_impl<
  483. T, Radix, MinDigits, MaxDigits, negative_accumulator<Radix> >
  484. extract_neg_type;
  485. Iterator save = first;
  486. bool hit = detail_spirit_x3::extract_sign(first, last);
  487. if (hit)
  488. hit = extract_neg_type::parse(first, last, attr);
  489. else
  490. hit = extract_pos_type::parse(first, last, attr);
  491. if (!hit)
  492. {
  493. first = save;
  494. return false;
  495. }
  496. return true;
  497. }
  498. };
  499. // Copied from boost/spirit/home/x3/support/numeric_utils/extract_real.hpp
  500. // (Boost 1.71), and modified for use with iterator, sentinel pairs:
  501. template <typename T, typename Enable = void>
  502. struct pow10_helper
  503. {
  504. static T call(unsigned dim)
  505. {
  506. return std::pow(T(10), T(dim));
  507. }
  508. };
  509. template <typename T>
  510. struct pow10_table
  511. {
  512. constexpr static std::size_t size =
  513. std::numeric_limits<T>::max_exponent10;
  514. constexpr pow10_table()
  515. : exponents()
  516. {
  517. exponents[0] = T(1);
  518. for (auto i = 1; i != size; ++i)
  519. exponents[i] = exponents[i-1] * T(10);
  520. }
  521. T exponents[size];
  522. };
  523. template <typename T>
  524. struct native_pow10_helper
  525. {
  526. constexpr static auto table = pow10_table<T>();
  527. static T call(unsigned dim)
  528. {
  529. return table.exponents[dim];
  530. }
  531. };
  532. template <>
  533. struct pow10_helper<float>
  534. : native_pow10_helper<float> {};
  535. template <>
  536. struct pow10_helper<double>
  537. : native_pow10_helper<double> {};
  538. template <>
  539. struct pow10_helper<long double>
  540. : native_pow10_helper<long double> {};
  541. template <typename T>
  542. inline T pow10(unsigned dim)
  543. {
  544. return detail_spirit_x3::pow10_helper<T>::call(dim);
  545. }
  546. template<typename T>
  547. inline bool scale(int exp, T & n)
  548. {
  549. constexpr auto max_exp = std::numeric_limits<T>::max_exponent10;
  550. constexpr auto min_exp = std::numeric_limits<T>::min_exponent10;
  551. if (exp >= 0)
  552. {
  553. // return false if exp exceeds the max_exp
  554. // do this check only for primitive types!
  555. if (std::is_floating_point_v<T> && exp > max_exp)
  556. return false;
  557. n *= detail_spirit_x3::pow10<T>(exp);
  558. }
  559. else
  560. {
  561. if (exp < min_exp)
  562. {
  563. n /= detail_spirit_x3::pow10<T>(-min_exp);
  564. // return false if exp still exceeds the min_exp
  565. // do this check only for primitive types!
  566. exp += -min_exp;
  567. if (std::is_floating_point_v<T> && exp < min_exp)
  568. return false;
  569. n /= detail_spirit_x3::pow10<T>(-exp);
  570. }
  571. else
  572. {
  573. n /= detail_spirit_x3::pow10<T>(-exp);
  574. }
  575. }
  576. return true;
  577. }
  578. template<typename T>
  579. bool scale(int exp, int frac, T & n)
  580. {
  581. return detail_spirit_x3::scale(exp - frac, n);
  582. }
  583. template<typename T>
  584. T negate(bool neg, T n)
  585. {
  586. return neg ? -n : n;
  587. }
  588. template <typename T, typename RealPolicies>
  589. struct extract_real
  590. {
  591. template <typename Iterator, typename Sentinel, typename Attribute>
  592. static bool
  593. parse(Iterator& first, Sentinel last, Attribute& attr,
  594. RealPolicies const& p)
  595. {
  596. if (first == last)
  597. return false;
  598. Iterator save = first;
  599. // Start by parsing the sign. neg will be true if
  600. // we got a "-" sign, false otherwise.
  601. bool neg = p.parse_sign(first, last);
  602. // Now attempt to parse an integer
  603. T n = 0;
  604. bool got_a_number = p.parse_n(first, last, n);
  605. // If we did not get a number it might be a NaN, Inf or a leading
  606. // dot.
  607. if (!got_a_number)
  608. {
  609. // Check whether the number to parse is a NaN or Inf
  610. if (p.parse_nan(first, last, n) ||
  611. p.parse_inf(first, last, n))
  612. {
  613. // If we got a negative sign, negate the number
  614. attr = detail_spirit_x3::negate(neg, n);
  615. return true; // got a NaN or Inf, return early
  616. }
  617. // If we did not get a number and our policies do not
  618. // allow a leading dot, fail and return early (no-match)
  619. if (!p.allow_leading_dot)
  620. {
  621. first = save;
  622. return false;
  623. }
  624. }
  625. bool e_hit = false;
  626. Iterator e_pos;
  627. int frac_digits = 0;
  628. // Try to parse the dot ('.' decimal point)
  629. if (p.parse_dot(first, last))
  630. {
  631. // We got the decimal point. Now we will try to parse
  632. // the fraction if it is there. If not, it defaults
  633. // to zero (0) only if we already got a number.
  634. Iterator savef = first;
  635. if (p.parse_frac_n(first, last, n))
  636. {
  637. // Optimization note: don't compute frac_digits if T is
  638. // an unused_type. This should be optimized away by the compiler.
  639. if (!std::is_same_v<T, unused_type>)
  640. frac_digits =
  641. static_cast<int>(std::distance(savef, first));
  642. BOOST_PARSER_DEBUG_ASSERT(frac_digits >= 0);
  643. }
  644. else if (!got_a_number || !p.allow_trailing_dot)
  645. {
  646. // We did not get a fraction. If we still haven't got a
  647. // number and our policies do not allow a trailing dot,
  648. // return no-match.
  649. first = save;
  650. return false;
  651. }
  652. // Now, let's see if we can parse the exponent prefix
  653. e_pos = first;
  654. e_hit = p.parse_exp(first, last);
  655. }
  656. else
  657. {
  658. // No dot and no number! Return no-match.
  659. if (!got_a_number)
  660. {
  661. first = save;
  662. return false;
  663. }
  664. // If we must expect a dot and we didn't see an exponent
  665. // prefix, return no-match.
  666. e_pos = first;
  667. e_hit = p.parse_exp(first, last);
  668. if (p.expect_dot && !e_hit)
  669. {
  670. first = save;
  671. return false;
  672. }
  673. }
  674. if (e_hit)
  675. {
  676. // We got the exponent prefix. Now we will try to parse the
  677. // actual exponent. It is an error if it is not there.
  678. int exp = 0;
  679. if (p.parse_exp_n(first, last, exp))
  680. {
  681. // Got the exponent value. Scale the number by
  682. // exp-frac_digits.
  683. if (!detail_spirit_x3::scale(exp, frac_digits, n))
  684. return false;
  685. }
  686. else
  687. {
  688. // If there is no number, disregard the exponent altogether.
  689. // by resetting 'first' prior to the exponent prefix (e|E)
  690. first = e_pos;
  691. // Scale the number by -frac_digits.
  692. if (!detail_spirit_x3::scale(-frac_digits, n))
  693. return false;
  694. }
  695. }
  696. else if (frac_digits)
  697. {
  698. // No exponent found. Scale the number by -frac_digits.
  699. if (!detail_spirit_x3::scale(-frac_digits, n))
  700. return false;
  701. }
  702. // If we got a negative sign, negate the number
  703. attr = detail_spirit_x3::negate(neg, n);
  704. // Success!!!
  705. return true;
  706. }
  707. };
  708. // Copied from
  709. // boost/spirit/home/x3/string/detail/string_parse.hpp
  710. // (Boost 1.47),and modified for use with iterator, sentinel pairs:
  711. struct common_type_equal
  712. {
  713. template<typename T, typename U>
  714. bool operator()(T x, U y)
  715. {
  716. using common_t = std::common_type_t<decltype(x), decltype(y)>;
  717. return (common_t)x == (common_t)y;
  718. }
  719. };
  720. template <typename Char, typename Iterator, typename Sentinel>
  721. inline bool string_parse(
  722. Char const* uc_i, Char const* lc_i
  723. , Iterator& first, Sentinel const& last)
  724. {
  725. Iterator i = first;
  726. common_type_equal eq;
  727. for (; *uc_i && *lc_i; ++uc_i, ++lc_i, ++i)
  728. if (i == last || (!eq(*uc_i, *i) && !eq(*lc_i, *i)))
  729. return false;
  730. first = i;
  731. return true;
  732. }
  733. // Copied from
  734. // boost/spirit/home/x3/numeric/real_policies.hpp
  735. // (Boost 1.47),and modified for use with iterator, sentinel pairs:
  736. ///////////////////////////////////////////////////////////////////////////
  737. // Default (unsigned) real number policies
  738. ///////////////////////////////////////////////////////////////////////////
  739. template <typename T>
  740. struct ureal_policies
  741. {
  742. // trailing dot policy suggested by Gustavo Guerra
  743. static bool const allow_leading_dot = true;
  744. static bool const allow_trailing_dot = true;
  745. static bool const expect_dot = false;
  746. template <typename Iterator, typename Sentinel>
  747. static bool
  748. parse_sign(Iterator& /*first*/, Iterator const& /*last*/)
  749. {
  750. return false;
  751. }
  752. template <typename Iterator, typename Sentinel, typename Attribute>
  753. static bool
  754. parse_n(Iterator& first, Sentinel const& last, Attribute& attr_)
  755. {
  756. return extract_uint<T, 10, 1, -1>::call(first, last, attr_);
  757. }
  758. template <typename Iterator, typename Sentinel>
  759. static bool
  760. parse_dot(Iterator& first, Sentinel const& last)
  761. {
  762. if (first == last || *first != '.')
  763. return false;
  764. ++first;
  765. return true;
  766. }
  767. template <typename Iterator, typename Sentinel, typename Attribute>
  768. static bool
  769. parse_frac_n(Iterator& first, Sentinel const& last, Attribute& attr_)
  770. {
  771. return extract_uint<T, 10, 1, -1, true>::call(first, last, attr_);
  772. }
  773. template <typename Iterator, typename Sentinel>
  774. static bool
  775. parse_exp(Iterator& first, Sentinel const& last)
  776. {
  777. if (first == last || (*first != 'e' && *first != 'E'))
  778. return false;
  779. ++first;
  780. return true;
  781. }
  782. template <typename Iterator, typename Sentinel>
  783. static bool
  784. parse_exp_n(Iterator& first, Sentinel const& last, int& attr_)
  785. {
  786. return extract_int<int, 10, 1, -1>::call(first, last, attr_);
  787. }
  788. ///////////////////////////////////////////////////////////////////////
  789. // The parse_nan() and parse_inf() functions get called whenever
  790. // a number to parse does not start with a digit (after having
  791. // successfully parsed an optional sign).
  792. //
  793. // The functions should return true if a Nan or Inf has been found. In
  794. // this case the attr should be set to the matched value (NaN or
  795. // Inf). The optional sign will be automatically applied afterwards.
  796. //
  797. // The default implementation below recognizes representations of NaN
  798. // and Inf as mandated by the C99 Standard and as proposed for
  799. // inclusion into the C++0x Standard: nan, nan(...), inf and infinity
  800. // (the matching is performed case-insensitively).
  801. ///////////////////////////////////////////////////////////////////////
  802. template <typename Iterator, typename Sentinel, typename Attribute>
  803. static bool
  804. parse_nan(Iterator& first, Sentinel const& last, Attribute& attr_)
  805. {
  806. if (first == last)
  807. return false; // end of input reached
  808. if (*first != 'n' && *first != 'N')
  809. return false; // not "nan"
  810. // nan[(...)] ?
  811. if (detail_spirit_x3::string_parse("nan", "NAN", first, last))
  812. {
  813. if (first != last && *first == '(')
  814. {
  815. // skip trailing (...) part
  816. Iterator i = first;
  817. while (++i != last && *i != ')')
  818. ;
  819. if (i == last)
  820. return false; // no trailing ')' found, give up
  821. first = ++i;
  822. }
  823. attr_ = std::numeric_limits<T>::quiet_NaN();
  824. return true;
  825. }
  826. return false;
  827. }
  828. template <typename Iterator, typename Sentinel, typename Attribute>
  829. static bool
  830. parse_inf(Iterator& first, Sentinel const& last, Attribute& attr_)
  831. {
  832. if (first == last)
  833. return false; // end of input reached
  834. if (*first != 'i' && *first != 'I')
  835. return false; // not "inf"
  836. // inf or infinity ?
  837. if (detail_spirit_x3::string_parse("inf", "INF", first, last))
  838. {
  839. // skip allowed 'inity' part of infinity
  840. detail_spirit_x3::string_parse("inity", "INITY", first, last);
  841. attr_ = std::numeric_limits<T>::infinity();
  842. return true;
  843. }
  844. return false;
  845. }
  846. };
  847. ///////////////////////////////////////////////////////////////////////////
  848. // Default (signed) real number policies
  849. ///////////////////////////////////////////////////////////////////////////
  850. template <typename T>
  851. struct real_policies : ureal_policies<T>
  852. {
  853. template <typename Iterator, typename Sentinel>
  854. static bool
  855. parse_sign(Iterator& first, Sentinel const& last)
  856. {
  857. return detail_spirit_x3::extract_sign(first, last);
  858. }
  859. };
  860. template <typename T>
  861. struct strict_ureal_policies : ureal_policies<T>
  862. {
  863. static bool const expect_dot = true;
  864. };
  865. template <typename T>
  866. struct strict_real_policies : real_policies<T>
  867. {
  868. static bool const expect_dot = true;
  869. };
  870. }
  871. namespace boost::parser::detail::numeric {
  872. template<typename I, typename S>
  873. constexpr bool common_range = std::is_same_v<I, S>;
  874. template<typename I, typename S>
  875. using unpacked_iter = decltype(text::unpack_iterator_and_sentinel(
  876. std::declval<I>(), std::declval<S>())
  877. .first);
  878. template<typename I, typename S>
  879. constexpr bool unpacks_to_chars =
  880. std::is_pointer_v<unpacked_iter<I, S>> && std::is_same_v<
  881. std::remove_cv_t<std::remove_reference_t<
  882. std::remove_pointer_t<unpacked_iter<I, S>>>>,
  883. char>;
  884. inline namespace BOOST_PARSER_NUMERIC_NS {
  885. template<int MinDigits, int MaxDigits, typename I, typename S>
  886. #if defined(BOOST_PARSER_HAVE_CHARCONV)
  887. constexpr bool use_charconv_int =
  888. MinDigits == 1 && MaxDigits == -1 &&
  889. common_range<I, S> && unpacks_to_chars<I, S>;
  890. #else
  891. constexpr bool use_charconv_int = false;
  892. #endif
  893. template<
  894. bool Signed,
  895. int Radix,
  896. int MinDigits,
  897. int MaxDigits,
  898. typename I,
  899. typename S,
  900. typename T>
  901. bool parse_int(I & first, S last, T & attr)
  902. {
  903. if constexpr (use_charconv_int<MinDigits, MaxDigits, I, S>) {
  904. #if defined(BOOST_PARSER_HAVE_CHARCONV)
  905. auto unpacked = text::unpack_iterator_and_sentinel(first, last);
  906. #if defined(BOOST_PARSER_HAVE_STD_CHARCONV)
  907. std::from_chars_result const result = std::from_chars(
  908. #else
  909. charconv::from_chars_result const result = charconv::from_chars(
  910. #endif
  911. unpacked.first, unpacked.last, attr, Radix);
  912. if (result.ec == std::errc()) {
  913. first = unpacked.repack(result.ptr);
  914. return true;
  915. }
  916. return false;
  917. #endif
  918. } else if constexpr (Signed) {
  919. using extract = detail_spirit_x3::
  920. extract_int<T, Radix, MinDigits, MaxDigits>;
  921. return extract::call(first, last, attr);
  922. } else {
  923. using extract = detail_spirit_x3::
  924. extract_uint<T, Radix, MinDigits, MaxDigits>;
  925. return extract::call(first, last, attr);
  926. }
  927. }
  928. template<typename I, typename S>
  929. #if defined(BOOST_PARSER_HAVE_CHARCONV)
  930. constexpr bool use_charconv_real =
  931. common_range<I, S> && unpacks_to_chars<I, S>;
  932. #else
  933. constexpr bool use_charconv_real = false;
  934. #endif
  935. template<typename I, typename S, typename T>
  936. bool parse_real(I & first, S last, T & attr)
  937. {
  938. if constexpr (use_charconv_real<I, S>) {
  939. #if defined(BOOST_PARSER_HAVE_CHARCONV)
  940. auto unpacked = text::unpack_iterator_and_sentinel(first, last);
  941. #if defined(BOOST_PARSER_HAVE_STD_CHARCONV)
  942. std::from_chars_result const result = std::from_chars(
  943. #else
  944. charconv::from_chars_result const result = charconv::from_chars(
  945. #endif
  946. unpacked.first, unpacked.last, attr);
  947. if (result.ec == std::errc()) {
  948. first = unpacked.repack(result.ptr);
  949. return true;
  950. }
  951. return false;
  952. #endif
  953. } else {
  954. detail_spirit_x3::real_policies<T> policies;
  955. using extract = detail_spirit_x3::
  956. extract_real<T, detail_spirit_x3::real_policies<T>>;
  957. return extract::parse(first, last, attr, policies);
  958. }
  959. }
  960. }
  961. }
  962. #endif