File indexing completed on 2025-01-31 10:02:38
0001
0002
0003
0004
0005
0006
0007
0008
0009 #if !defined(BOOST_SPIRIT_X3_EXTRACT_REAL_APRIL_18_2006_0901AM)
0010 #define BOOST_SPIRIT_X3_EXTRACT_REAL_APRIL_18_2006_0901AM
0011
0012 #include <cmath>
0013 #include <boost/limits.hpp>
0014 #include <boost/type_traits/is_same.hpp>
0015 #include <boost/spirit/home/x3/support/unused.hpp>
0016 #include <boost/spirit/home/x3/support/numeric_utils/pow10.hpp>
0017 #include <boost/spirit/home/x3/support/traits/move_to.hpp>
0018 #include <boost/assert.hpp>
0019
0020 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0021 # pragma warning(push)
0022 # pragma warning(disable: 4100)
0023 # pragma warning(disable: 4127)
0024 #endif
0025
0026 namespace boost { namespace spirit { namespace x3 { namespace extension
0027 {
0028 using x3::traits::pow10;
0029
0030 template <typename T>
0031 inline bool
0032 scale(int exp, T& n)
0033 {
0034 constexpr auto max_exp = std::numeric_limits<T>::max_exponent10;
0035 constexpr auto min_exp = std::numeric_limits<T>::min_exponent10;
0036
0037 if (exp >= 0)
0038 {
0039
0040
0041 if (is_floating_point<T>() && exp > max_exp)
0042 return false;
0043 n *= pow10<T>(exp);
0044 }
0045 else
0046 {
0047 if (exp < min_exp)
0048 {
0049 n /= pow10<T>(-min_exp);
0050
0051
0052
0053 exp += -min_exp;
0054 if (is_floating_point<T>() && exp < min_exp)
0055 return false;
0056
0057 n /= pow10<T>(-exp);
0058 }
0059 else
0060 {
0061 n /= pow10<T>(-exp);
0062 }
0063 }
0064 return true;
0065 }
0066
0067 inline bool
0068 scale(int , unused_type )
0069 {
0070
0071 return true;
0072 }
0073
0074 template <typename T>
0075 inline bool
0076 scale(int exp, int frac, T& n)
0077 {
0078 return scale(exp - frac, n);
0079 }
0080
0081 inline bool
0082 scale(int , int , unused_type )
0083 {
0084
0085 return true;
0086 }
0087
0088 inline float
0089 negate(bool neg, float n)
0090 {
0091 return neg ? (std::copysignf)(n, -1.f) : n;
0092 }
0093
0094 inline double
0095 negate(bool neg, double n)
0096 {
0097 return neg ? (std::copysign)(n, -1.) : n;
0098 }
0099
0100 inline long double
0101 negate(bool neg, long double n)
0102 {
0103 return neg ? (std::copysignl)(n, -1.) : n;
0104 }
0105
0106 template <typename T>
0107 inline T
0108 negate(bool neg, T const& n)
0109 {
0110 return neg ? -n : n;
0111 }
0112
0113 inline unused_type
0114 negate(bool , unused_type n)
0115 {
0116
0117 return n;
0118 }
0119 }}}}
0120
0121 namespace boost { namespace spirit { namespace x3
0122 {
0123 template <typename T, typename RealPolicies>
0124 struct extract_real
0125 {
0126 template <typename Iterator, typename Attribute>
0127 static bool
0128 parse(Iterator& first, Iterator const& last, Attribute& attr,
0129 RealPolicies const& p)
0130 {
0131 if (first == last)
0132 return false;
0133 Iterator save = first;
0134
0135
0136
0137 bool neg = p.parse_sign(first, last);
0138
0139
0140 T n = 0;
0141 bool got_a_number = p.parse_n(first, last, n);
0142
0143
0144
0145 if (!got_a_number)
0146 {
0147
0148 if (p.parse_nan(first, last, n) ||
0149 p.parse_inf(first, last, n))
0150 {
0151
0152 traits::move_to(extension::negate(neg, n), attr);
0153 return true;
0154 }
0155
0156
0157
0158 if (!p.allow_leading_dot)
0159 {
0160 first = save;
0161 return false;
0162 }
0163 }
0164
0165 bool e_hit = false;
0166 Iterator e_pos;
0167 int frac_digits = 0;
0168
0169
0170 if (p.parse_dot(first, last))
0171 {
0172
0173
0174
0175 Iterator savef = first;
0176 if (p.parse_frac_n(first, last, n))
0177 {
0178
0179
0180 if (!is_same<T, unused_type>::value)
0181 frac_digits =
0182 static_cast<int>(std::distance(savef, first));
0183 BOOST_ASSERT(frac_digits >= 0);
0184 }
0185 else if (!got_a_number || !p.allow_trailing_dot)
0186 {
0187
0188
0189
0190 first = save;
0191 return false;
0192 }
0193
0194
0195 e_pos = first;
0196 e_hit = p.parse_exp(first, last);
0197 }
0198 else
0199 {
0200
0201 if (!got_a_number)
0202 {
0203 first = save;
0204 return false;
0205 }
0206
0207
0208
0209 e_pos = first;
0210 e_hit = p.parse_exp(first, last);
0211 if (p.expect_dot && !e_hit)
0212 {
0213 first = save;
0214 return false;
0215 }
0216 }
0217
0218 if (e_hit)
0219 {
0220
0221
0222 int exp = 0;
0223 if (p.parse_exp_n(first, last, exp))
0224 {
0225
0226
0227 if (!extension::scale(exp, frac_digits, n))
0228 return false;
0229 }
0230 else
0231 {
0232
0233
0234 first = e_pos;
0235
0236
0237 if (!extension::scale(-frac_digits, n))
0238 return false;
0239 }
0240 }
0241 else if (frac_digits)
0242 {
0243
0244 if (!extension::scale(-frac_digits, n))
0245 return false;
0246 }
0247
0248
0249 traits::move_to(extension::negate(neg, n), attr);
0250
0251
0252 return true;
0253 }
0254 };
0255
0256 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0257 # pragma warning(pop)
0258 #endif
0259
0260 }}}
0261
0262 #endif