diff options
author | Kevin Smith <git@kismith.co.uk> | 2013-01-04 19:42:37 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2013-04-06 13:36:54 (GMT) |
commit | 3333ab69d62d1be7ae7dd7a4e56cc4bb608d3add (patch) | |
tree | 5ee630b666ae21dd4c4202703c158383de1faf91 /3rdParty/Boost/src/boost/spirit/home/classic/core/primitives/impl/numerics.ipp | |
parent | b9ef4566d31219d66a615b1eae042a01828c8b7d (diff) | |
download | swift-contrib-3333ab69d62d1be7ae7dd7a4e56cc4bb608d3add.zip swift-contrib-3333ab69d62d1be7ae7dd7a4e56cc4bb608d3add.tar.bz2 |
Add boost serialization library
We'll need it before too long
Change-Id: Ia34c7f26e1aedbc13a2fc10c980994cbcb7cb348
Diffstat (limited to '3rdParty/Boost/src/boost/spirit/home/classic/core/primitives/impl/numerics.ipp')
-rw-r--r-- | 3rdParty/Boost/src/boost/spirit/home/classic/core/primitives/impl/numerics.ipp | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/boost/spirit/home/classic/core/primitives/impl/numerics.ipp b/3rdParty/Boost/src/boost/spirit/home/classic/core/primitives/impl/numerics.ipp new file mode 100644 index 0000000..19586f1 --- /dev/null +++ b/3rdParty/Boost/src/boost/spirit/home/classic/core/primitives/impl/numerics.ipp @@ -0,0 +1,478 @@ +/*============================================================================= + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2001-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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) +=============================================================================*/ +#ifndef BOOST_SPIRIT_NUMERICS_IPP +#define BOOST_SPIRIT_NUMERICS_IPP + +#include <boost/config/no_tr1/cmath.hpp> +#include <limits> + +namespace boost { namespace spirit { + +BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN + + struct sign_parser; // forward declaration only + + namespace impl + { + /////////////////////////////////////////////////////////////////////// + // + // Extract the prefix sign (- or +) + // + /////////////////////////////////////////////////////////////////////// + template <typename ScannerT> + bool + extract_sign(ScannerT const& scan, std::size_t& count) + { + // Extract the sign + count = 0; + bool neg = *scan == '-'; + if (neg || (*scan == '+')) + { + ++scan; + ++count; + return neg; + } + + return false; + } + + /////////////////////////////////////////////////////////////////////// + // + // Traits class for radix specific number conversion + // + // Convert a digit from character representation, ch, to binary + // representation, returned in val. + // Returns whether the conversion was successful. + // + // template<typename CharT> static bool digit(CharT ch, T& val); + // + /////////////////////////////////////////////////////////////////////// + template<const int Radix> + struct radix_traits; + + ////////////////////////////////// Binary + template<> + struct radix_traits<2> + { + template<typename CharT, typename T> + static bool digit(CharT ch, T& val) + { + val = ch - '0'; + return ('0' == ch || '1' == ch); + } + }; + + ////////////////////////////////// Octal + template<> + struct radix_traits<8> + { + template<typename CharT, typename T> + static bool digit(CharT ch, T& val) + { + val = ch - '0'; + return ('0' <= ch && ch <= '7'); + } + }; + + ////////////////////////////////// Decimal + template<> + struct radix_traits<10> + { + template<typename CharT, typename T> + static bool digit(CharT ch, T& val) + { + val = ch - '0'; + return impl::isdigit_(ch); + } + }; + + ////////////////////////////////// Hexadecimal + template<> + struct radix_traits<16> + { + template<typename CharT, typename T> + static bool digit(CharT ch, T& val) + { + if (radix_traits<10>::digit(ch, val)) + return true; + + CharT lc = impl::tolower_(ch); + if ('a' <= lc && lc <= 'f') + { + val = lc - 'a' + 10; + return true; + } + return false; + } + }; + + /////////////////////////////////////////////////////////////////////// + // + // Helper templates for encapsulation of radix specific + // conversion of an input string to an integral value. + // + // main entry point: + // + // extract_int<Radix, MinDigits, MaxDigits, Accumulate> + // ::f(first, last, n, count); + // + // The template parameter Radix represents the radix of the + // number contained in the parsed string. The template + // parameter MinDigits specifies the minimum digits to + // accept. The template parameter MaxDigits specifies the + // maximum digits to parse. A -1 value for MaxDigits will + // make it parse an arbitrarilly large number as long as the + // numeric type can hold it. Accumulate is either + // positive_accumulate<Radix> (default) for parsing positive + // numbers or negative_accumulate<Radix> otherwise. + // Checking is only performed when std::numeric_limits<T>:: + // is_specialized is true. Otherwise, there's no way to + // do the check. + // + // scan.first and scan.last are iterators as usual (i.e. + // first is mutable and is moved forward when a match is + // found), n is a variable that holds the number (passed by + // reference). The number of parsed characters is added to + // count (also passed by reference) + // + // NOTE: + // Returns a non-match, if the number to parse + // overflows (or underflows) the used type. + // + // BEWARE: + // the parameters 'n' and 'count' should be properly + // initialized before calling this function. + // + /////////////////////////////////////////////////////////////////////// +#if defined(BOOST_MSVC) +#pragma warning(push) +#pragma warning(disable:4127) //conditional expression is constant +#endif + + template <typename T, int Radix> + struct positive_accumulate + { + // Use this accumulator if number is positive + static bool add(T& n, T digit) + { + if (std::numeric_limits<T>::is_specialized) + { + static T const max = (std::numeric_limits<T>::max)(); + static T const max_div_radix = max/Radix; + + if (n > max_div_radix) + return false; + n *= Radix; + + if (n > max - digit) + return false; + n += digit; + + return true; + } + else + { + n *= Radix; + n += digit; + return true; + } + } + }; + + template <typename T, int Radix> + struct negative_accumulate + { + // Use this accumulator if number is negative + static bool add(T& n, T digit) + { + if (std::numeric_limits<T>::is_specialized) + { + typedef std::numeric_limits<T> num_limits; + static T const min = + (!num_limits::is_integer && num_limits::is_signed && num_limits::has_denorm) ? + -(num_limits::max)() : (num_limits::min)(); + static T const min_div_radix = min/Radix; + + if (n < min_div_radix) + return false; + n *= Radix; + + if (n < min + digit) + return false; + n -= digit; + + return true; + } + else + { + n *= Radix; + n -= digit; + return true; + } + } + }; + + template <int MaxDigits> + inline bool allow_more_digits(std::size_t i) + { + return i < MaxDigits; + } + + template <> + inline bool allow_more_digits<-1>(std::size_t) + { + return true; + } + + ////////////////////////////////// + template < + int Radix, unsigned MinDigits, int MaxDigits, + typename Accumulate + > + struct extract_int + { + template <typename ScannerT, typename T> + static bool + f(ScannerT& scan, T& n, std::size_t& count) + { + std::size_t i = 0; + T digit; + while( allow_more_digits<MaxDigits>(i) && !scan.at_end() && + radix_traits<Radix>::digit(*scan, digit) ) + { + if (!Accumulate::add(n, digit)) + return false; // Overflow + ++i, ++scan, ++count; + } + return i >= MinDigits; + } + }; + + /////////////////////////////////////////////////////////////////////// + // + // uint_parser_impl class + // + /////////////////////////////////////////////////////////////////////// + template < + typename T = unsigned, + int Radix = 10, + unsigned MinDigits = 1, + int MaxDigits = -1 + > + struct uint_parser_impl + : parser<uint_parser_impl<T, Radix, MinDigits, MaxDigits> > + { + typedef uint_parser_impl<T, Radix, MinDigits, MaxDigits> self_t; + + template <typename ScannerT> + struct result + { + typedef typename match_result<ScannerT, T>::type type; + }; + + template <typename ScannerT> + typename parser_result<self_t, ScannerT>::type + parse(ScannerT const& scan) const + { + if (!scan.at_end()) + { + T n = 0; + std::size_t count = 0; + typename ScannerT::iterator_t save = scan.first; + if (extract_int<Radix, MinDigits, MaxDigits, + positive_accumulate<T, Radix> >::f(scan, n, count)) + { + return scan.create_match(count, n, save, scan.first); + } + // return no-match if number overflows + } + return scan.no_match(); + } + }; + + /////////////////////////////////////////////////////////////////////// + // + // int_parser_impl class + // + /////////////////////////////////////////////////////////////////////// + template < + typename T = unsigned, + int Radix = 10, + unsigned MinDigits = 1, + int MaxDigits = -1 + > + struct int_parser_impl + : parser<int_parser_impl<T, Radix, MinDigits, MaxDigits> > + { + typedef int_parser_impl<T, Radix, MinDigits, MaxDigits> self_t; + + template <typename ScannerT> + struct result + { + typedef typename match_result<ScannerT, T>::type type; + }; + + template <typename ScannerT> + typename parser_result<self_t, ScannerT>::type + parse(ScannerT const& scan) const + { + typedef extract_int<Radix, MinDigits, MaxDigits, + negative_accumulate<T, Radix> > extract_int_neg_t; + typedef extract_int<Radix, MinDigits, MaxDigits, + positive_accumulate<T, Radix> > extract_int_pos_t; + + if (!scan.at_end()) + { + T n = 0; + std::size_t count = 0; + typename ScannerT::iterator_t save = scan.first; + + bool hit = impl::extract_sign(scan, count); + + if (hit) + hit = extract_int_neg_t::f(scan, n, count); + else + hit = extract_int_pos_t::f(scan, n, count); + + if (hit) + return scan.create_match(count, n, save, scan.first); + else + scan.first = save; + // return no-match if number overflows or underflows + } + return scan.no_match(); + } + }; + + /////////////////////////////////////////////////////////////////////// + // + // real_parser_impl class + // + /////////////////////////////////////////////////////////////////////// + template <typename RT, typename T, typename RealPoliciesT> + struct real_parser_impl + { + typedef real_parser_impl<RT, T, RealPoliciesT> self_t; + + template <typename ScannerT> + RT parse_main(ScannerT const& scan) const + { + if (scan.at_end()) + return scan.no_match(); + typename ScannerT::iterator_t save = scan.first; + + typedef typename parser_result<sign_parser, ScannerT>::type + sign_match_t; + typedef typename parser_result<chlit<>, ScannerT>::type + exp_match_t; + + sign_match_t sign_match = RealPoliciesT::parse_sign(scan); + std::size_t count = sign_match ? sign_match.length() : 0; + bool neg = sign_match.has_valid_attribute() ? + sign_match.value() : false; + + RT n_match = RealPoliciesT::parse_n(scan); + T n = n_match.has_valid_attribute() ? + n_match.value() : T(0); + bool got_a_number = n_match; + exp_match_t e_hit; + + if (!got_a_number && !RealPoliciesT::allow_leading_dot) + return scan.no_match(); + else + count += n_match.length(); + + if (neg) + n = -n; + + if (RealPoliciesT::parse_dot(scan)) + { + // We got the decimal point. Now we will try to parse + // the fraction if it is there. If not, it defaults + // to zero (0) only if we already got a number. + + if (RT hit = RealPoliciesT::parse_frac_n(scan)) + { +#if !defined(BOOST_NO_STDC_NAMESPACE) + using namespace std; // allow for ADL to find pow() +#endif + hit.value(hit.value() + * pow(T(10), T(-hit.length()))); + if (neg) + n -= hit.value(); + else + n += hit.value(); + count += hit.length() + 1; + + } + + else if (!got_a_number || + !RealPoliciesT::allow_trailing_dot) + return scan.no_match(); + + e_hit = RealPoliciesT::parse_exp(scan); + } + else + { + // We have reached a point where we + // still haven't seen a number at all. + // We return early with a no-match. + if (!got_a_number) + return scan.no_match(); + + // If we must expect a dot and we didn't see + // an exponent, return early with a no-match. + e_hit = RealPoliciesT::parse_exp(scan); + if (RealPoliciesT::expect_dot && !e_hit) + return scan.no_match(); + } + + if (e_hit) + { + // We got the exponent prefix. Now we will try to parse the + // actual exponent. It is an error if it is not there. + if (RT e_n_hit = RealPoliciesT::parse_exp_n(scan)) + { +#if !defined(BOOST_NO_STDC_NAMESPACE) + using namespace std; // allow for ADL to find pow() +#endif + n *= pow(T(10), T(e_n_hit.value())); + count += e_n_hit.length() + e_hit.length(); + } + else + { + // Oops, no exponent, return a no-match + return scan.no_match(); + } + } + + return scan.create_match(count, n, save, scan.first); + } + + template <typename ScannerT> + static RT parse(ScannerT const& scan) + { + static self_t this_; + return impl::implicit_lexeme_parse<RT>(this_, scan, scan); + } + }; + +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + + } // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +BOOST_SPIRIT_CLASSIC_NAMESPACE_END + +}} // namespace boost::spirit + +#endif |