/*============================================================================= Copyright (c) 2001-2010 Joel de Guzman Copyright (c) 2001-2010 Hartmut Kaiser Use, modification and distribution is subject to 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) =============================================================================*/ #if !defined(BOOST_SPIRIT_TEST_QI_REAL_HPP) #define BOOST_SPIRIT_TEST_QI_REAL_HPP #include #include #include #include #include #include #include #include #include "test.hpp" /////////////////////////////////////////////////////////////////////////////// // These policies can be used to parse thousand separated // numbers with at most 2 decimal digits after the decimal // point. e.g. 123,456,789.01 /////////////////////////////////////////////////////////////////////////////// template struct ts_real_policies : boost::spirit::qi::ureal_policies { // 2 decimal places Max template static bool parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr, int& frac_digits) { namespace qi = boost::spirit::qi; Iterator savef = first; bool r = qi::extract_uint::call(first, last, attr); frac_digits = static_cast(std::distance(savef, first)); return r; } // No exponent template static bool parse_exp(Iterator&, Iterator const&) { return false; } // No exponent template static bool parse_exp_n(Iterator&, Iterator const&, Attribute&) { return false; } // Thousands separated numbers template static bool parse_n(Iterator& first, Iterator const& last, Accumulator& result) { using boost::spirit::qi::uint_parser; namespace qi = boost::spirit::qi; uint_parser uint3; uint_parser uint3_3; if (parse(first, last, uint3, result)) { Accumulator n; Iterator iter = first; while (qi::parse(iter, last, ',') && qi::parse(iter, last, uint3_3, n)) { result = result * 1000 + n; first = iter; } return true; } return false; } }; template struct no_trailing_dot_policy : boost::spirit::qi::real_policies { static bool const allow_trailing_dot = false; }; template struct no_leading_dot_policy : boost::spirit::qi::real_policies { static bool const allow_leading_dot = false; }; template bool compare(T n, double expected , T const eps = std::pow(10.0, -std::numeric_limits::digits10)) { T delta = n - expected; return (delta >= -eps) && (delta <= eps); } /////////////////////////////////////////////////////////////////////////////// // A custom real type struct custom_real { double n; custom_real() : n(0) {} custom_real(double n_) : n(n_) {} friend bool operator==(custom_real a, custom_real b) { return a.n == b.n; } friend custom_real operator*(custom_real a, custom_real b) { return custom_real(a.n * b.n); } friend custom_real operator+(custom_real a, custom_real b) { return custom_real(a.n + b.n); } friend custom_real operator-(custom_real a, custom_real b) { return custom_real(a.n - b.n); } }; #endif