/*============================================================================= Copyright (c) 2011-2016 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout Distributed under 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) =============================================================================*/ #ifndef SPROUT_WEED_PARSER_NUMERIC_INT_P_HPP #define SPROUT_WEED_PARSER_NUMERIC_INT_P_HPP #include #include #include #include #include #include #include #include #include #include #include namespace sprout { namespace weed { // // int_p // template< typename IntType, std::size_t Radix = 10, std::size_t MinDigits = 1, std::size_t MaxDigits = sprout::integer_digits::value > struct int_p : public sprout::weed::parser_base { private: SPROUT_STATIC_CONSTEXPR std::size_t limit_digits = MaxDigits <= sprout::integer_digits::value ? MaxDigits : sprout::integer_digits::value ; public: template struct attribute : public sprout::identity {}; template struct result : public sprout::identity::type> > {}; private: template SPROUT_CONSTEXPR typename result::type make_result( typename result::type const& res, int sign = 0 ) const { typedef typename result::type result_type; return res.success() && sign < 0 ? result_type(true, res.current(), -res.attr()) : res ; } template SPROUT_CONSTEXPR typename std::enable_if< N == limit_digits, typename result::type >::type call_1( Iterator first, Iterator last, Iterator temp_first, IntType t, std::size_t n, PResult const& res ) const { typedef typename result::type result_type; typedef typename attribute::type attribute_type; return sprout::tuples::get<1>(res) ? n < MaxDigits ? call_0( sprout::next(first), last, temp_first, static_cast(t * Radix + sprout::tuples::get<0>(res)), n ) : result_type( true, sprout::next(first), static_cast(t * Radix + sprout::tuples::get<0>(res)) ) : N < MinDigits ? result_type(false, temp_first, attribute_type()) : result_type(true, first, t) ; } template SPROUT_CONSTEXPR typename std::enable_if< N != limit_digits, typename result::type >::type call_1( Iterator first, Iterator last, Iterator temp_first, IntType t, std::size_t n, PResult const& res ) const { typedef typename result::type result_type; typedef typename attribute::type attribute_type; return sprout::tuples::get<1>(res) ? call_0( sprout::next(first), last, temp_first, static_cast(t * Radix + sprout::tuples::get<0>(res)), n ) : N < MinDigits ? result_type(false, temp_first, attribute_type()) : result_type(true, first, t) ; } template SPROUT_CONSTEXPR typename result::type call_0( Iterator first, Iterator last, Iterator temp_first, IntType t, std::size_t n ) const { typedef typename result::type result_type; typedef typename attribute::type attribute_type; return first != last ? call_1( first, last, temp_first, t, n + 1, sprout::weed::detail::from_ndigit(*first) ) : N < MinDigits ? result_type(false, temp_first, attribute_type()) : result_type(true, first, t) ; } template SPROUT_CONSTEXPR typename result::type call_i( Iterator first, Iterator last, Iterator temp_first, PResult const& res ) const { typedef typename result::type result_type; typedef typename attribute::type attribute_type; return sprout::tuples::get<1>(res) ? call_0<1, Context>( sprout::next(first), last, temp_first, sprout::tuples::get<0>(res), 1 ) : result_type(false, temp_first, attribute_type()) ; } template SPROUT_CONSTEXPR typename result::type call( Iterator first, Iterator last, Iterator temp_first, int sign = 0 ) const { typedef typename result::type result_type; typedef typename attribute::type attribute_type; return first != last ? make_result( call_i( first, last, temp_first, sprout::weed::detail::from_ndigit(*first) ), sign ) : result_type(false, temp_first, attribute_type()) ; } public: template SPROUT_CONSTEXPR typename result::type operator()( Iterator first, Iterator last, Context const& ) const { typedef typename std::iterator_traits::value_type elem_type; typedef typename result::type result_type; typedef typename attribute::type attribute_type; return first != last ? *first == SPROUT_CHAR_LITERAL('+', elem_type) ? call( sprout::next(first), last, first, 1 ) : *first == SPROUT_CHAR_LITERAL('-', elem_type) ? call( sprout::next(first), last, first, -1 ) : call( first, last, first ) : result_type(false, first, attribute_type()) ; } }; } // namespace weed } // namespace sprout #endif // #ifndef SPROUT_WEED_PARSER_NUMERIC_INT_P_HPP