| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092 |
- /*=============================================================================
- Copyright (c) 2001-2014 Joel de Guzman
- Copyright (c) 2001-2011 Hartmut Kaiser
- Copyright (c) 2011 Jan Frederick Eick
- Copyright (c) 2011 Christopher Jefferson
- Copyright (c) 2006 Stephen Nutt
- Copyright (c) 2019 T. Zachary Laine
- Distributed under the Boost Software License, Version 1.0. (See accompanying
- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- ==============================================================================*/
- #ifndef BOOST_PARSER_DETAIL_NUMERIC_HPP
- #define BOOST_PARSER_DETAIL_NUMERIC_HPP
- #include <boost/parser/detail/text/unpack.hpp>
- #if __has_include(<charconv>)
- #include <charconv>
- #endif
- #if defined(__cpp_lib_to_chars)
- #define BOOST_PARSER_HAVE_STD_CHARCONV
- #define BOOST_PARSER_NUMERIC_NS std_charconv
- #elif __has_include(<boost/charconv.hpp>)
- #include <boost/charconv.hpp>
- #define BOOST_PARSER_HAVE_BOOST_CHARCONV
- #define BOOST_PARSER_NUMERIC_NS boost_charconv
- #else
- #define BOOST_PARSER_NUMERIC_NS spirit_parsers
- #endif
- #include <type_traits>
- #include <cmath>
- #if defined(BOOST_PARSER_HAVE_STD_CHARCONV) || \
- defined(BOOST_PARSER_HAVE_BOOST_CHARCONV)
- #define BOOST_PARSER_HAVE_CHARCONV
- #endif
- namespace boost::parser::detail_spirit_x3 {
- struct unused_type
- {};
- // Copied from boost/spirit/home/support/char_class.hpp (Boost 1.71), and
- // modified not to use Boost.TypeTraits.
- template <typename TargetChar, typename SourceChar>
- TargetChar cast_char(SourceChar ch)
- {
- if (std::is_signed_v<TargetChar> != std::is_signed_v<SourceChar>)
- {
- if (std::is_signed<SourceChar>::value)
- {
- // source is signed, target is unsigned
- typedef std::make_unsigned_t<SourceChar> USourceChar;
- return TargetChar(USourceChar(ch));
- }
- else
- {
- // source is unsigned, target is signed
- typedef std::make_signed_t<SourceChar> SSourceChar;
- return TargetChar(SSourceChar(ch));
- }
- }
- else
- {
- // source and target has same signedness
- return TargetChar(ch); // just cast
- }
- }
- // Copied from
- // boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp
- // (Boost 1.67), and modified not to use Boost.MPL or Boost.PP.
- inline constexpr int log2_table[] = {
- 0, 0, 1000000, 1584960, 2000000, 2321920, 2584960, 2807350,
- 3000000, 3169920, 3321920, 3459430, 3584960, 3700430, 3807350, 3906890,
- 4000000, 4087460, 4169920, 4247920, 4321920, 4392310, 4459430, 4523560,
- 4584960, 4643850, 4700430, 4754880, 4807350, 4857980, 4906890, 4954190,
- 5000000, 5044390, 5087460, 5129280, 5169925};
- template<typename T, unsigned Radix>
- struct digits_traits
- {
- static_assert(std::numeric_limits<T>::radix == 2, "");
- constexpr static int value =
- int((std::numeric_limits<T>::digits * 1000000) / log2_table[Radix]);
- };
- template <typename T>
- struct digits_traits<T, 10>
- {
- static int constexpr value = std::numeric_limits<T>::digits10;
- };
- template<unsigned Radix>
- struct radix_traits
- {
- template <typename Char>
- inline static bool is_valid(Char ch)
- {
- if (Radix <= 10)
- return (ch >= '0' && ch <= static_cast<Char>('0' + Radix -1));
- return (ch >= '0' && ch <= '9')
- || (ch >= 'a' && ch <= static_cast<Char>('a' + Radix -10 -1))
- || (ch >= 'A' && ch <= static_cast<Char>('A' + Radix -10 -1));
- }
- template <typename Char>
- inline static unsigned digit(Char ch)
- {
- if (Radix <= 10 || (ch >= '0' && ch <= '9'))
- return ch - '0';
- return std::tolower(detail_spirit_x3::cast_char<char>(ch)) - 'a' + 10;
- }
- };
- template <unsigned Radix>
- struct positive_accumulator
- {
- template <typename T, typename Char>
- inline static void add(T& n, Char ch, std::false_type) // unchecked add
- {
- const int digit = radix_traits<Radix>::digit(ch);
- n = n * T(Radix) + T(digit);
- }
- template <typename T, typename Char>
- inline static bool add(T& n, Char ch, std::true_type) // checked add
- {
- // Ensure n *= Radix will not overflow
- T const max = (std::numeric_limits<T>::max)();
- T const val = max / Radix;
- if (n > val)
- return false;
- T tmp = n * Radix;
- // Ensure n += digit will not overflow
- const int digit = radix_traits<Radix>::digit(ch);
- if (tmp > max - digit)
- return false;
- n = tmp + static_cast<T>(digit);
- return true;
- }
- };
- template <unsigned Radix>
- struct negative_accumulator
- {
- template <typename T, typename Char>
- inline static void add(T& n, Char ch, std::false_type) // unchecked subtract
- {
- const int digit = radix_traits<Radix>::digit(ch);
- n = n * T(Radix) - T(digit);
- }
- template <typename T, typename Char>
- inline static bool add(T& n, Char ch, std::true_type) // checked subtract
- {
- // Ensure n *= Radix will not underflow
- T const min = (std::numeric_limits<T>::min)();
- T const val = min / T(Radix);
- if (n < val)
- return false;
- T tmp = n * Radix;
- // Ensure n -= digit will not underflow
- int const digit = radix_traits<Radix>::digit(ch);
- if (tmp < min + digit)
- return false;
- n = tmp - static_cast<T>(digit);
- return true;
- }
- };
- template <unsigned Radix, typename Accumulator, int MaxDigits>
- struct int_extractor
- {
- template <typename Char, typename T>
- inline static bool
- call(Char ch, std::size_t count, T& n, std::true_type)
- {
- std::size_t constexpr
- overflow_free = digits_traits<T, Radix>::value - 1;
- if (count < overflow_free)
- {
- Accumulator::add(n, ch, std::false_type{});
- }
- else
- {
- if (!Accumulator::add(n, ch, std::true_type{}))
- return false; // over/underflow!
- }
- return true;
- }
- template <typename Char, typename T>
- inline static bool
- call(Char ch, std::size_t /*count*/, T& n, std::false_type)
- {
- // no need to check for overflow
- Accumulator::add(n, ch, std::false_type{});
- return true;
- }
- template <typename Char>
- inline static bool
- call(Char /*ch*/, std::size_t /*count*/, unused_type, std::false_type)
- {
- return true;
- }
- template <typename Char, typename T>
- inline static bool
- call(Char ch, std::size_t count, T& n)
- {
- return call(ch, count, n
- , std::integral_constant<bool,
- ( (MaxDigits < 0)
- || (MaxDigits > digits_traits<T, Radix>::value)
- )
- && std::numeric_limits<T>::is_bounded
- >()
- );
- }
- };
- template <int MaxDigits>
- struct check_max_digits
- {
- inline static bool
- call(std::size_t count)
- {
- return count < MaxDigits; // bounded
- }
- };
- template <>
- struct check_max_digits<-1>
- {
- inline static bool
- call(std::size_t /*count*/)
- {
- return true; // unbounded
- }
- };
- template <
- typename T, unsigned Radix, unsigned MinDigits, int MaxDigits
- , typename Accumulator = positive_accumulator<Radix>
- , bool Accumulate = false
- >
- struct extract_int_impl
- {
- template <typename Iterator, typename Sentinel, typename Attribute>
- inline static bool
- parse_main(
- Iterator& first
- , Sentinel last
- , Attribute& attr)
- {
- typedef radix_traits<Radix> radix_check;
- typedef int_extractor<Radix, Accumulator, MaxDigits> extractor;
- typedef
- typename std::iterator_traits<Iterator>::value_type char_type;
- Iterator it = first;
- std::size_t leading_zeros = 0;
- if (!Accumulate)
- {
- // skip leading zeros
- while (it != last && *it == '0' && leading_zeros < MaxDigits)
- {
- ++it;
- ++leading_zeros;
- }
- }
- typedef Attribute attribute_type;
- attribute_type val = Accumulate ? attr : attribute_type(0);
- std::size_t count = 0;
- char_type ch;
- while (true)
- {
- if (!check_max_digits<MaxDigits>::call(count + leading_zeros) ||
- it == last)
- break;
- ch = *it;
- if (!radix_check::is_valid(ch) ||
- !extractor::call(ch, count, val))
- break;
- ++it;
- ++count;
- if (!check_max_digits<MaxDigits>::call(count + leading_zeros) ||
- it == last)
- break;
- ch = *it;
- if (!radix_check::is_valid(ch) ||
- !extractor::call(ch, count, val))
- break;
- ++it;
- ++count;
- if (!check_max_digits<MaxDigits>::call(count + leading_zeros) ||
- it == last)
- break;
- ch = *it;
- if (!radix_check::is_valid(ch) ||
- !extractor::call(ch, count, val))
- break;
- ++it;
- ++count;
- }
- if (count + leading_zeros >= MinDigits)
- {
- attr = val;
- first = it;
- return true;
- }
- return false;
- }
- template <typename Iterator, typename Sentinel>
- inline static bool
- parse(
- Iterator& first
- , Sentinel last
- , unused_type)
- {
- T n = 0; // must calculate value to detect over/underflow
- return parse_main(first, last, n);
- }
- template <typename Iterator, typename Sentinel, typename Attribute>
- inline static bool
- parse(
- Iterator& first
- , Sentinel last
- , Attribute& attr)
- {
- return parse_main(first, last, attr);
- }
- };
- template <typename T, unsigned Radix, typename Accumulator, bool Accumulate>
- struct extract_int_impl<T, Radix, 1, -1, Accumulator, Accumulate>
- {
- template <typename Iterator, typename Sentinel, typename Attribute>
- inline static bool
- parse_main(
- Iterator& first
- , Sentinel last
- , Attribute& attr)
- {
- typedef radix_traits<Radix> radix_check;
- typedef int_extractor<Radix, Accumulator, -1> extractor;
- typedef
- typename std::iterator_traits<Iterator>::value_type char_type;
- Iterator it = first;
- std::size_t count = 0;
- if (!Accumulate)
- {
- // skip leading zeros
- while (it != last && *it == '0')
- {
- ++it;
- ++count;
- }
- if (it == last)
- {
- if (count == 0) // must have at least one digit
- return false;
- attr = 0;
- first = it;
- return true;
- }
- }
- typedef Attribute attribute_type;
- attribute_type val = Accumulate ? attr : attribute_type(0);
- char_type ch = *it;
- if (!radix_check::is_valid(ch) || !extractor::call(ch, 0, val))
- {
- if (count == 0) // must have at least one digit
- return false;
- attr = val;
- first = it;
- return true;
- }
- count = 0;
- ++it;
- while (true)
- {
- if (it == last)
- break;
- ch = *it;
- if (!radix_check::is_valid(ch))
- break;
- if (!extractor::call(ch, count, val))
- return false;
- ++it;
- ++count;
- if (it == last)
- break;
- ch = *it;
- if (!radix_check::is_valid(ch))
- break;
- if (!extractor::call(ch, count, val))
- return false;
- ++it;
- ++count;
- if (it == last)
- break;
- ch = *it;
- if (!radix_check::is_valid(ch))
- break;
- if (!extractor::call(ch, count, val))
- return false;
- ++it;
- ++count;
- }
- attr = val;
- first = it;
- return true;
- }
- template <typename Iterator, typename Sentinel>
- inline static bool
- parse(
- Iterator& first
- , Sentinel last
- , unused_type)
- {
- T n = 0; // must calculate value to detect over/underflow
- return parse_main(first, last, n);
- }
- template <typename Iterator, typename Sentinel, typename Attribute>
- inline static bool
- parse(
- Iterator& first
- , Sentinel last
- , Attribute& attr)
- {
- return parse_main(first, last, attr);
- }
- };
- // Copied from boost/spirit/home/x3/support/numeric_utils/extract_int.hpp
- // (Boost 1.67), and modified for use with iterator, sentinel pairs:
- ///////////////////////////////////////////////////////////////////////////
- // Extract the prefix sign (- or +), return true if a '-' was found
- ///////////////////////////////////////////////////////////////////////////
- template<typename Iterator, typename Sentinel>
- inline bool extract_sign(Iterator & first, Sentinel last)
- {
- (void)last; // silence unused warnings
- BOOST_PARSER_DEBUG_ASSERT(first != last); // precondition
- // Extract the sign
- bool neg = *first == '-';
- if (neg || (*first == '+'))
- {
- ++first;
- return neg;
- }
- return false;
- }
- ///////////////////////////////////////////////////////////////////////////
- // Low level unsigned integer parser
- ///////////////////////////////////////////////////////////////////////////
- template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits
- , bool Accumulate = false>
- struct extract_uint
- {
- // check template parameter 'Radix' for validity
- static_assert(
- (Radix >= 2 && Radix <= 36),
- "Error Unsupported Radix");
- template <typename Iterator, typename Sentinel>
- inline static bool call(Iterator& first, Sentinel last, T& attr)
- {
- if (first == last)
- return false;
- typedef extract_int_impl<
- T
- , Radix
- , MinDigits
- , MaxDigits
- , positive_accumulator<Radix>
- , Accumulate>
- extract_type;
- Iterator save = first;
- if (!extract_type::parse(first, last, attr))
- {
- first = save;
- return false;
- }
- return true;
- }
- };
- ///////////////////////////////////////////////////////////////////////////
- // Low level signed integer parser
- ///////////////////////////////////////////////////////////////////////////
- template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
- struct extract_int
- {
- // check template parameter 'Radix' for validity
- static_assert(
- (Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16),
- "Error Unsupported Radix");
- template <typename Iterator, typename Sentinel>
- inline static bool call(Iterator& first, Sentinel last, T& attr)
- {
- if (first == last)
- return false;
- typedef extract_int_impl<
- T, Radix, MinDigits, MaxDigits>
- extract_pos_type;
- typedef extract_int_impl<
- T, Radix, MinDigits, MaxDigits, negative_accumulator<Radix> >
- extract_neg_type;
- Iterator save = first;
- bool hit = detail_spirit_x3::extract_sign(first, last);
- if (hit)
- hit = extract_neg_type::parse(first, last, attr);
- else
- hit = extract_pos_type::parse(first, last, attr);
- if (!hit)
- {
- first = save;
- return false;
- }
- return true;
- }
- };
- // Copied from boost/spirit/home/x3/support/numeric_utils/extract_real.hpp
- // (Boost 1.71), and modified for use with iterator, sentinel pairs:
- template <typename T, typename Enable = void>
- struct pow10_helper
- {
- static T call(unsigned dim)
- {
- return std::pow(T(10), T(dim));
- }
- };
- template <typename T>
- struct pow10_table
- {
- constexpr static std::size_t size =
- std::numeric_limits<T>::max_exponent10;
-
- constexpr pow10_table()
- : exponents()
- {
- exponents[0] = T(1);
- for (auto i = 1; i != size; ++i)
- exponents[i] = exponents[i-1] * T(10);
- }
-
- T exponents[size];
- };
- template <typename T>
- struct native_pow10_helper
- {
- constexpr static auto table = pow10_table<T>();
- static T call(unsigned dim)
- {
- return table.exponents[dim];
- }
- };
- template <>
- struct pow10_helper<float>
- : native_pow10_helper<float> {};
- template <>
- struct pow10_helper<double>
- : native_pow10_helper<double> {};
- template <>
- struct pow10_helper<long double>
- : native_pow10_helper<long double> {};
- template <typename T>
- inline T pow10(unsigned dim)
- {
- return detail_spirit_x3::pow10_helper<T>::call(dim);
- }
- template<typename T>
- inline bool scale(int exp, T & n)
- {
- constexpr auto max_exp = std::numeric_limits<T>::max_exponent10;
- constexpr auto min_exp = std::numeric_limits<T>::min_exponent10;
- if (exp >= 0)
- {
- // return false if exp exceeds the max_exp
- // do this check only for primitive types!
- if (std::is_floating_point_v<T> && exp > max_exp)
- return false;
- n *= detail_spirit_x3::pow10<T>(exp);
- }
- else
- {
- if (exp < min_exp)
- {
- n /= detail_spirit_x3::pow10<T>(-min_exp);
- // return false if exp still exceeds the min_exp
- // do this check only for primitive types!
- exp += -min_exp;
- if (std::is_floating_point_v<T> && exp < min_exp)
- return false;
- n /= detail_spirit_x3::pow10<T>(-exp);
- }
- else
- {
- n /= detail_spirit_x3::pow10<T>(-exp);
- }
- }
- return true;
- }
- template<typename T>
- bool scale(int exp, int frac, T & n)
- {
- return detail_spirit_x3::scale(exp - frac, n);
- }
- template<typename T>
- T negate(bool neg, T n)
- {
- return neg ? -n : n;
- }
- template <typename T, typename RealPolicies>
- struct extract_real
- {
- template <typename Iterator, typename Sentinel, typename Attribute>
- static bool
- parse(Iterator& first, Sentinel last, Attribute& attr,
- RealPolicies const& p)
- {
- if (first == last)
- return false;
- Iterator save = first;
- // Start by parsing the sign. neg will be true if
- // we got a "-" sign, false otherwise.
- bool neg = p.parse_sign(first, last);
- // Now attempt to parse an integer
- T n = 0;
- bool got_a_number = p.parse_n(first, last, n);
- // If we did not get a number it might be a NaN, Inf or a leading
- // dot.
- if (!got_a_number)
- {
- // Check whether the number to parse is a NaN or Inf
- if (p.parse_nan(first, last, n) ||
- p.parse_inf(first, last, n))
- {
- // If we got a negative sign, negate the number
- attr = detail_spirit_x3::negate(neg, n);
- return true; // got a NaN or Inf, return early
- }
- // If we did not get a number and our policies do not
- // allow a leading dot, fail and return early (no-match)
- if (!p.allow_leading_dot)
- {
- first = save;
- return false;
- }
- }
- bool e_hit = false;
- Iterator e_pos;
- int frac_digits = 0;
- // Try to parse the dot ('.' decimal point)
- if (p.parse_dot(first, last))
- {
- // We got the decimal point. Now we will try to parse
- // the fraction if it is there. If not, it defaults
- // to zero (0) only if we already got a number.
- Iterator savef = first;
- if (p.parse_frac_n(first, last, n))
- {
- // Optimization note: don't compute frac_digits if T is
- // an unused_type. This should be optimized away by the compiler.
- if (!std::is_same_v<T, unused_type>)
- frac_digits =
- static_cast<int>(std::distance(savef, first));
- BOOST_PARSER_DEBUG_ASSERT(frac_digits >= 0);
- }
- else if (!got_a_number || !p.allow_trailing_dot)
- {
- // We did not get a fraction. If we still haven't got a
- // number and our policies do not allow a trailing dot,
- // return no-match.
- first = save;
- return false;
- }
- // Now, let's see if we can parse the exponent prefix
- e_pos = first;
- e_hit = p.parse_exp(first, last);
- }
- else
- {
- // No dot and no number! Return no-match.
- if (!got_a_number)
- {
- first = save;
- return false;
- }
- // If we must expect a dot and we didn't see an exponent
- // prefix, return no-match.
- e_pos = first;
- e_hit = p.parse_exp(first, last);
- if (p.expect_dot && !e_hit)
- {
- first = save;
- return false;
- }
- }
- if (e_hit)
- {
- // We got the exponent prefix. Now we will try to parse the
- // actual exponent. It is an error if it is not there.
- int exp = 0;
- if (p.parse_exp_n(first, last, exp))
- {
- // Got the exponent value. Scale the number by
- // exp-frac_digits.
- if (!detail_spirit_x3::scale(exp, frac_digits, n))
- return false;
- }
- else
- {
- // If there is no number, disregard the exponent altogether.
- // by resetting 'first' prior to the exponent prefix (e|E)
- first = e_pos;
- // Scale the number by -frac_digits.
- if (!detail_spirit_x3::scale(-frac_digits, n))
- return false;
- }
- }
- else if (frac_digits)
- {
- // No exponent found. Scale the number by -frac_digits.
- if (!detail_spirit_x3::scale(-frac_digits, n))
- return false;
- }
- // If we got a negative sign, negate the number
- attr = detail_spirit_x3::negate(neg, n);
- // Success!!!
- return true;
- }
- };
- // Copied from
- // boost/spirit/home/x3/string/detail/string_parse.hpp
- // (Boost 1.47),and modified for use with iterator, sentinel pairs:
- struct common_type_equal
- {
- template<typename T, typename U>
- bool operator()(T x, U y)
- {
- using common_t = std::common_type_t<decltype(x), decltype(y)>;
- return (common_t)x == (common_t)y;
- }
- };
- template <typename Char, typename Iterator, typename Sentinel>
- inline bool string_parse(
- Char const* uc_i, Char const* lc_i
- , Iterator& first, Sentinel const& last)
- {
- Iterator i = first;
- common_type_equal eq;
- for (; *uc_i && *lc_i; ++uc_i, ++lc_i, ++i)
- if (i == last || (!eq(*uc_i, *i) && !eq(*lc_i, *i)))
- return false;
- first = i;
- return true;
- }
- // Copied from
- // boost/spirit/home/x3/numeric/real_policies.hpp
- // (Boost 1.47),and modified for use with iterator, sentinel pairs:
- ///////////////////////////////////////////////////////////////////////////
- // Default (unsigned) real number policies
- ///////////////////////////////////////////////////////////////////////////
- template <typename T>
- struct ureal_policies
- {
- // trailing dot policy suggested by Gustavo Guerra
- static bool const allow_leading_dot = true;
- static bool const allow_trailing_dot = true;
- static bool const expect_dot = false;
- template <typename Iterator, typename Sentinel>
- static bool
- parse_sign(Iterator& /*first*/, Iterator const& /*last*/)
- {
- return false;
- }
- template <typename Iterator, typename Sentinel, typename Attribute>
- static bool
- parse_n(Iterator& first, Sentinel const& last, Attribute& attr_)
- {
- return extract_uint<T, 10, 1, -1>::call(first, last, attr_);
- }
- template <typename Iterator, typename Sentinel>
- static bool
- parse_dot(Iterator& first, Sentinel const& last)
- {
- if (first == last || *first != '.')
- return false;
- ++first;
- return true;
- }
- template <typename Iterator, typename Sentinel, typename Attribute>
- static bool
- parse_frac_n(Iterator& first, Sentinel const& last, Attribute& attr_)
- {
- return extract_uint<T, 10, 1, -1, true>::call(first, last, attr_);
- }
- template <typename Iterator, typename Sentinel>
- static bool
- parse_exp(Iterator& first, Sentinel const& last)
- {
- if (first == last || (*first != 'e' && *first != 'E'))
- return false;
- ++first;
- return true;
- }
- template <typename Iterator, typename Sentinel>
- static bool
- parse_exp_n(Iterator& first, Sentinel const& last, int& attr_)
- {
- return extract_int<int, 10, 1, -1>::call(first, last, attr_);
- }
- ///////////////////////////////////////////////////////////////////////
- // The parse_nan() and parse_inf() functions get called whenever
- // a number to parse does not start with a digit (after having
- // successfully parsed an optional sign).
- //
- // The functions should return true if a Nan or Inf has been found. In
- // this case the attr should be set to the matched value (NaN or
- // Inf). The optional sign will be automatically applied afterwards.
- //
- // The default implementation below recognizes representations of NaN
- // and Inf as mandated by the C99 Standard and as proposed for
- // inclusion into the C++0x Standard: nan, nan(...), inf and infinity
- // (the matching is performed case-insensitively).
- ///////////////////////////////////////////////////////////////////////
- template <typename Iterator, typename Sentinel, typename Attribute>
- static bool
- parse_nan(Iterator& first, Sentinel const& last, Attribute& attr_)
- {
- if (first == last)
- return false; // end of input reached
- if (*first != 'n' && *first != 'N')
- return false; // not "nan"
- // nan[(...)] ?
- if (detail_spirit_x3::string_parse("nan", "NAN", first, last))
- {
- if (first != last && *first == '(')
- {
- // skip trailing (...) part
- Iterator i = first;
- while (++i != last && *i != ')')
- ;
- if (i == last)
- return false; // no trailing ')' found, give up
- first = ++i;
- }
- attr_ = std::numeric_limits<T>::quiet_NaN();
- return true;
- }
- return false;
- }
- template <typename Iterator, typename Sentinel, typename Attribute>
- static bool
- parse_inf(Iterator& first, Sentinel const& last, Attribute& attr_)
- {
- if (first == last)
- return false; // end of input reached
- if (*first != 'i' && *first != 'I')
- return false; // not "inf"
- // inf or infinity ?
- if (detail_spirit_x3::string_parse("inf", "INF", first, last))
- {
- // skip allowed 'inity' part of infinity
- detail_spirit_x3::string_parse("inity", "INITY", first, last);
- attr_ = std::numeric_limits<T>::infinity();
- return true;
- }
- return false;
- }
- };
- ///////////////////////////////////////////////////////////////////////////
- // Default (signed) real number policies
- ///////////////////////////////////////////////////////////////////////////
- template <typename T>
- struct real_policies : ureal_policies<T>
- {
- template <typename Iterator, typename Sentinel>
- static bool
- parse_sign(Iterator& first, Sentinel const& last)
- {
- return detail_spirit_x3::extract_sign(first, last);
- }
- };
- template <typename T>
- struct strict_ureal_policies : ureal_policies<T>
- {
- static bool const expect_dot = true;
- };
- template <typename T>
- struct strict_real_policies : real_policies<T>
- {
- static bool const expect_dot = true;
- };
- }
- namespace boost::parser::detail::numeric {
- template<typename I, typename S>
- constexpr bool common_range = std::is_same_v<I, S>;
- template<typename I, typename S>
- using unpacked_iter = decltype(text::unpack_iterator_and_sentinel(
- std::declval<I>(), std::declval<S>())
- .first);
- template<typename I, typename S>
- constexpr bool unpacks_to_chars =
- std::is_pointer_v<unpacked_iter<I, S>> && std::is_same_v<
- std::remove_cv_t<std::remove_reference_t<
- std::remove_pointer_t<unpacked_iter<I, S>>>>,
- char>;
- inline namespace BOOST_PARSER_NUMERIC_NS {
- template<int MinDigits, int MaxDigits, typename I, typename S>
- #if defined(BOOST_PARSER_HAVE_CHARCONV)
- constexpr bool use_charconv_int =
- MinDigits == 1 && MaxDigits == -1 &&
- common_range<I, S> && unpacks_to_chars<I, S>;
- #else
- constexpr bool use_charconv_int = false;
- #endif
- template<
- bool Signed,
- int Radix,
- int MinDigits,
- int MaxDigits,
- typename I,
- typename S,
- typename T>
- bool parse_int(I & first, S last, T & attr)
- {
- if constexpr (use_charconv_int<MinDigits, MaxDigits, I, S>) {
- #if defined(BOOST_PARSER_HAVE_CHARCONV)
- auto unpacked = text::unpack_iterator_and_sentinel(first, last);
- #if defined(BOOST_PARSER_HAVE_STD_CHARCONV)
- std::from_chars_result const result = std::from_chars(
- #else
- charconv::from_chars_result const result = charconv::from_chars(
- #endif
- unpacked.first, unpacked.last, attr, Radix);
- if (result.ec == std::errc()) {
- first = unpacked.repack(result.ptr);
- return true;
- }
- return false;
- #endif
- } else if constexpr (Signed) {
- using extract = detail_spirit_x3::
- extract_int<T, Radix, MinDigits, MaxDigits>;
- return extract::call(first, last, attr);
- } else {
- using extract = detail_spirit_x3::
- extract_uint<T, Radix, MinDigits, MaxDigits>;
- return extract::call(first, last, attr);
- }
- }
- template<typename I, typename S>
- #if defined(BOOST_PARSER_HAVE_CHARCONV)
- constexpr bool use_charconv_real =
- common_range<I, S> && unpacks_to_chars<I, S>;
- #else
- constexpr bool use_charconv_real = false;
- #endif
- template<typename I, typename S, typename T>
- bool parse_real(I & first, S last, T & attr)
- {
- if constexpr (use_charconv_real<I, S>) {
- #if defined(BOOST_PARSER_HAVE_CHARCONV)
- auto unpacked = text::unpack_iterator_and_sentinel(first, last);
- #if defined(BOOST_PARSER_HAVE_STD_CHARCONV)
- std::from_chars_result const result = std::from_chars(
- #else
- charconv::from_chars_result const result = charconv::from_chars(
- #endif
- unpacked.first, unpacked.last, attr);
- if (result.ec == std::errc()) {
- first = unpacked.repack(result.ptr);
- return true;
- }
- return false;
- #endif
- } else {
- detail_spirit_x3::real_policies<T> policies;
- using extract = detail_spirit_x3::
- extract_real<T, detail_spirit_x3::real_policies<T>>;
- return extract::parse(first, last, attr, policies);
- }
- }
- }
- }
- #endif
|