Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / spirit / home / qi / numeric / real_policies.hpp
1 /*=============================================================================
2     Copyright (c) 2001-2019 Joel de Guzman
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 ==============================================================================*/
8 #if !defined(SPIRIT_REAL_POLICIES_APRIL_17_2006_1158PM)
9 #define SPIRIT_REAL_POLICIES_APRIL_17_2006_1158PM
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>
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 }}}
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     {
49         // Versioning
50         typedef mpl::int_<2> version;
51
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         {
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))
82                 return std::distance(save, first);
83             return 0;
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             {
104 #if defined(_MSC_VER) && _MSC_VER < 1900
105 # pragma warning(push)
106 # pragma warning(disable: 4127) // conditional expression is constant
107 #endif
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));
113 #if defined(_MSC_VER) && _MSC_VER < 1900
114 # pragma warning(pop)
115 #endif
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         ///////////////////////////////////////////////////////////////////////
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).
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