]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | /*============================================================================= |
92f5a8d4 | 2 | Copyright (c) 2001-2019 Joel de Guzman |
7c673cae FG |
3 | Copyright (c) 2001-2011 Hartmut Kaiser |
4 | ||
5 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
6 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
7 | ==============================================================================*/ | |
f67539c2 TL |
8 | #ifndef BOOST_SPIRIT_QI_NUMERIC_REAL_POLICIES_HPP |
9 | #define BOOST_SPIRIT_QI_NUMERIC_REAL_POLICIES_HPP | |
7c673cae FG |
10 | |
11 | #if defined(_MSC_VER) | |
12 | #pragma once | |
13 | #endif | |
14 | ||
15 | #include <boost/spirit/home/qi/numeric/numeric_utils.hpp> | |
16 | #include <boost/spirit/home/qi/detail/string_parse.hpp> | |
92f5a8d4 TL |
17 | #include <boost/type_traits/is_floating_point.hpp> |
18 | ||
19 | namespace boost { namespace spirit { namespace traits | |
20 | { | |
21 | // So that we won't exceed the capacity of the underlying type T, | |
22 | // we limit the number of digits parsed to its max_digits10. | |
23 | // By default, the value is -1 which tells spirit to parse an | |
24 | // unbounded number of digits. | |
25 | ||
26 | template <typename T, typename Enable = void> | |
27 | struct max_digits10 | |
28 | { | |
29 | static int const value = -1; // unbounded | |
30 | }; | |
31 | ||
32 | template <typename T> | |
33 | struct max_digits10<T | |
34 | , typename enable_if_c<(is_floating_point<T>::value)>::type> | |
35 | { | |
36 | static int const digits = std::numeric_limits<T>::digits; | |
37 | static int const value = 2 + (digits * 30103l) / 100000l; | |
38 | }; | |
39 | }}} | |
7c673cae FG |
40 | |
41 | namespace boost { namespace spirit { namespace qi | |
42 | { | |
43 | /////////////////////////////////////////////////////////////////////////// | |
44 | // Default (unsigned) real number policies | |
45 | /////////////////////////////////////////////////////////////////////////// | |
46 | template <typename T> | |
47 | struct ureal_policies | |
48 | { | |
92f5a8d4 TL |
49 | // Versioning |
50 | typedef mpl::int_<2> version; | |
51 | ||
7c673cae FG |
52 | // trailing dot policy suggested by Gustavo Guerra |
53 | static bool const allow_leading_dot = true; | |
54 | static bool const allow_trailing_dot = true; | |
55 | static bool const expect_dot = false; | |
56 | ||
57 | template <typename Iterator> | |
58 | static bool | |
59 | parse_sign(Iterator& /*first*/, Iterator const& /*last*/) | |
60 | { | |
61 | return false; | |
62 | } | |
63 | ||
64 | template <typename Iterator, typename Attribute> | |
65 | static bool | |
66 | parse_n(Iterator& first, Iterator const& last, Attribute& attr_) | |
67 | { | |
92f5a8d4 TL |
68 | typedef extract_uint<Attribute, 10, 1 |
69 | , traits::max_digits10<T>::value // See notes on max_digits10 above | |
70 | , false, true> | |
71 | extract_uint; | |
72 | return extract_uint::call(first, last, attr_); | |
73 | } | |
74 | ||
75 | // ignore_excess_digits (required for version > 1 API) | |
76 | template <typename Iterator> | |
77 | static std::size_t | |
78 | ignore_excess_digits(Iterator& first, Iterator const& last) | |
79 | { | |
80 | Iterator save = first; | |
81 | if (extract_uint<unused_type, 10, 1, -1>::call(first, last, unused)) | |
1e59de90 | 82 | return static_cast<std::size_t>(std::distance(save, first)); |
92f5a8d4 | 83 | return 0; |
7c673cae FG |
84 | } |
85 | ||
86 | template <typename Iterator> | |
87 | static bool | |
88 | parse_dot(Iterator& first, Iterator const& last) | |
89 | { | |
90 | if (first == last || *first != '.') | |
91 | return false; | |
92 | ++first; | |
93 | return true; | |
94 | } | |
95 | ||
96 | template <typename Iterator, typename Attribute> | |
97 | static bool | |
98 | parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr_, int& frac_digits) | |
99 | { | |
100 | Iterator savef = first; | |
101 | bool r = extract_uint<Attribute, 10, 1, -1, true, true>::call(first, last, attr_); | |
102 | if (r) | |
103 | { | |
92f5a8d4 TL |
104 | #if defined(_MSC_VER) && _MSC_VER < 1900 |
105 | # pragma warning(push) | |
106 | # pragma warning(disable: 4127) // conditional expression is constant | |
107 | #endif | |
7c673cae FG |
108 | // Optimization note: don't compute frac_digits if T is |
109 | // an unused_type. This should be optimized away by the compiler. | |
110 | if (!is_same<T, unused_type>::value) | |
111 | frac_digits = | |
112 | static_cast<int>(std::distance(savef, first)); | |
92f5a8d4 TL |
113 | #if defined(_MSC_VER) && _MSC_VER < 1900 |
114 | # pragma warning(pop) | |
115 | #endif | |
7c673cae FG |
116 | // ignore extra (non-significant digits) |
117 | extract_uint<unused_type, 10, 1, -1>::call(first, last, unused); | |
118 | } | |
119 | return r; | |
120 | } | |
121 | ||
122 | template <typename Iterator> | |
123 | static bool | |
124 | parse_exp(Iterator& first, Iterator const& last) | |
125 | { | |
126 | if (first == last || (*first != 'e' && *first != 'E')) | |
127 | return false; | |
128 | ++first; | |
129 | return true; | |
130 | } | |
131 | ||
132 | template <typename Iterator> | |
133 | static bool | |
134 | parse_exp_n(Iterator& first, Iterator const& last, int& attr_) | |
135 | { | |
136 | return extract_int<int, 10, 1, -1>::call(first, last, attr_); | |
137 | } | |
138 | ||
139 | /////////////////////////////////////////////////////////////////////// | |
92f5a8d4 TL |
140 | // The parse_nan() and parse_inf() functions get called whenever |
141 | // a number to parse does not start with a digit (after having | |
142 | // successfully parsed an optional sign). | |
7c673cae FG |
143 | // |
144 | // The functions should return true if a Nan or Inf has been found. In | |
145 | // this case the attr should be set to the matched value (NaN or | |
146 | // Inf). The optional sign will be automatically applied afterwards. | |
147 | // | |
148 | // The default implementation below recognizes representations of NaN | |
149 | // and Inf as mandated by the C99 Standard and as proposed for | |
150 | // inclusion into the C++0x Standard: nan, nan(...), inf and infinity | |
151 | // (the matching is performed case-insensitively). | |
152 | /////////////////////////////////////////////////////////////////////// | |
153 | template <typename Iterator, typename Attribute> | |
154 | static bool | |
155 | parse_nan(Iterator& first, Iterator const& last, Attribute& attr_) | |
156 | { | |
157 | if (first == last) | |
158 | return false; // end of input reached | |
159 | ||
160 | if (*first != 'n' && *first != 'N') | |
161 | return false; // not "nan" | |
162 | ||
163 | // nan[(...)] ? | |
164 | if (detail::string_parse("nan", "NAN", first, last, unused)) | |
165 | { | |
166 | if (first != last && *first == '(') | |
167 | { | |
168 | // skip trailing (...) part | |
169 | Iterator i = first; | |
170 | ||
171 | while (++i != last && *i != ')') | |
172 | ; | |
173 | if (i == last) | |
174 | return false; // no trailing ')' found, give up | |
175 | ||
176 | first = ++i; | |
177 | } | |
178 | attr_ = std::numeric_limits<T>::quiet_NaN(); | |
179 | return true; | |
180 | } | |
181 | return false; | |
182 | } | |
183 | ||
184 | template <typename Iterator, typename Attribute> | |
185 | static bool | |
186 | parse_inf(Iterator& first, Iterator const& last, Attribute& attr_) | |
187 | { | |
188 | if (first == last) | |
189 | return false; // end of input reached | |
190 | ||
191 | if (*first != 'i' && *first != 'I') | |
192 | return false; // not "inf" | |
193 | ||
194 | // inf or infinity ? | |
195 | if (detail::string_parse("inf", "INF", first, last, unused)) | |
196 | { | |
197 | // skip allowed 'inity' part of infinity | |
198 | detail::string_parse("inity", "INITY", first, last, unused); | |
199 | attr_ = std::numeric_limits<T>::infinity(); | |
200 | return true; | |
201 | } | |
202 | return false; | |
203 | } | |
204 | }; | |
205 | ||
206 | /////////////////////////////////////////////////////////////////////////// | |
207 | // Default (signed) real number policies | |
208 | /////////////////////////////////////////////////////////////////////////// | |
209 | template <typename T> | |
210 | struct real_policies : ureal_policies<T> | |
211 | { | |
212 | template <typename Iterator> | |
213 | static bool | |
214 | parse_sign(Iterator& first, Iterator const& last) | |
215 | { | |
216 | return extract_sign(first, last); | |
217 | } | |
218 | }; | |
219 | ||
220 | template <typename T> | |
221 | struct strict_ureal_policies : ureal_policies<T> | |
222 | { | |
223 | static bool const expect_dot = true; | |
224 | }; | |
225 | ||
226 | template <typename T> | |
227 | struct strict_real_policies : real_policies<T> | |
228 | { | |
229 | static bool const expect_dot = true; | |
230 | }; | |
231 | }}} | |
232 | ||
233 | #endif |