1 | /*============================================================================= |
2 | Copyright (c) 2001-2010 Joel de Guzman |
3 | Copyright (c) 2001-2010 Hartmut Kaiser |
4 | |
5 | Use, modification and distribution is subject to the Boost Software |
6 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
7 | http://www.boost.org/LICENSE_1_0.txt) |
8 | =============================================================================*/ |
9 | #if !defined(BOOST_SPIRIT_TEST_QI_REAL_HPP) |
10 | #define BOOST_SPIRIT_TEST_QI_REAL_HPP |
11 | |
12 | #include <boost/spirit/include/qi_real.hpp> |
13 | |
14 | #include <boost/spirit/include/qi_char.hpp> |
15 | #include <boost/spirit/include/qi_numeric.hpp> |
16 | #include <boost/spirit/include/qi_operator.hpp> |
17 | |
18 | #include "test.hpp" |
19 | |
20 | #include <boost/core/cmath.hpp> |
21 | #include <climits> |
22 | |
23 | #ifdef _MSVC_LANG |
24 | # if _MSC_VER < 1910 || _MSVC_LANG < 201402L |
25 | # define BOOST_SPIRIT_NO_MATH_REAL_CONCEPT |
26 | # endif |
27 | #elif __cplusplus < 201402L |
28 | # define BOOST_SPIRIT_NO_MATH_REAL_CONCEPT |
29 | #endif |
30 | #ifndef BOOST_SPIRIT_NO_MATH_REAL_CONCEPT |
31 | # include <boost/math/concepts/real_concept.hpp> |
32 | #endif |
33 | |
34 | /////////////////////////////////////////////////////////////////////////////// |
35 | // These policies can be used to parse thousand separated |
36 | // numbers with at most 2 decimal digits after the decimal |
37 | // point. e.g. 123,456,789.01 |
38 | /////////////////////////////////////////////////////////////////////////////// |
39 | template <typename T> |
40 | struct ts_real_policies : boost::spirit::qi::ureal_policies<T> |
41 | { |
42 | // 2 decimal places Max |
43 | template <typename Iterator, typename Attribute> |
44 | static bool |
45 | parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr, int& frac_digits) |
46 | { |
47 | namespace qi = boost::spirit::qi; |
48 | Iterator savef = first; |
49 | bool r = qi::extract_uint<Attribute, 10, 1, 2, true>::call(first, last, attr); |
50 | frac_digits = static_cast<int>(std::distance(savef, first)); |
51 | return r; |
52 | } |
53 | |
54 | // No exponent |
55 | template <typename Iterator> |
56 | static bool |
57 | parse_exp(Iterator&, Iterator const&) |
58 | { |
59 | return false; |
60 | } |
61 | |
62 | // No exponent |
63 | template <typename Iterator, typename Attribute> |
64 | static bool |
65 | parse_exp_n(Iterator&, Iterator const&, Attribute&) |
66 | { |
67 | return false; |
68 | } |
69 | |
70 | // Thousands separated numbers |
71 | template <typename Iterator, typename Accumulator> |
72 | static bool |
73 | parse_n(Iterator& first, Iterator const& last, Accumulator& result) |
74 | { |
75 | using boost::spirit::qi::uint_parser; |
76 | namespace qi = boost::spirit::qi; |
77 | |
78 | uint_parser<unsigned, 10, 1, 3> uint3; |
79 | uint_parser<unsigned, 10, 3, 3> uint3_3; |
80 | |
81 | if (parse(first, last, uint3, result)) |
82 | { |
83 | Accumulator n; |
84 | Iterator iter = first; |
85 | |
86 | while (qi::parse(iter, last, ',') && qi::parse(iter, last, uint3_3, n)) |
87 | { |
88 | result = result * 1000 + n; |
89 | first = iter; |
90 | } |
91 | |
92 | return true; |
93 | } |
94 | return false; |
95 | } |
96 | }; |
97 | |
98 | template <typename T> |
99 | struct no_trailing_dot_policy : boost::spirit::qi::real_policies<T> |
100 | { |
101 | static bool const allow_trailing_dot = false; |
102 | }; |
103 | |
104 | template <typename T> |
105 | struct no_leading_dot_policy : boost::spirit::qi::real_policies<T> |
106 | { |
107 | static bool const allow_leading_dot = false; |
108 | }; |
109 | |
110 | template <typename T> |
111 | bool |
112 | compare(T n, double expected |
113 | , T const eps = std::pow(10.0, -std::numeric_limits<T>::digits10)) |
114 | { |
115 | T delta = n - expected; |
116 | return (delta >= -eps) && (delta <= eps); |
117 | } |
118 | |
119 | /////////////////////////////////////////////////////////////////////////////// |
120 | // A custom real type |
121 | struct custom_real |
122 | { |
123 | double n; |
124 | custom_real() : n(0) {} |
125 | custom_real(double n_) : n(n_) {} |
126 | friend bool operator==(custom_real a, custom_real b) |
127 | { return a.n == b.n; } |
128 | friend custom_real operator*(custom_real a, custom_real b) |
129 | { return custom_real(a.n * b.n); } |
130 | friend custom_real operator+(custom_real a, custom_real b) |
131 | { return custom_real(a.n + b.n); } |
132 | friend custom_real operator-(custom_real a, custom_real b) |
133 | { return custom_real(a.n - b.n); } |
134 | }; |
135 | |
136 | #endif |
137 | |