#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/seq/elem.hpp>
-#include <boost/detail/iterator.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/mpl/and.hpp>
#include <boost/limits.hpp>
+#include <iterator> // for std::iterator_traits
+
#if !defined(SPIRIT_NUMERICS_LOOP_UNROLL)
# define SPIRIT_NUMERICS_LOOP_UNROLL 3
#endif
template <typename T, unsigned Radix>
struct digits_traits;
+ template <int Digits, unsigned Radix>
+ struct digits2_to_n;
+
// lookup table for log2(x) : 2 <= x <= 36
#define BOOST_SPIRIT_X3_LOG2 (#error)(#error) \
(1000000)(1584960)(2000000)(2321920)(2584960)(2807350) \
/***/
#define BOOST_PP_LOCAL_MACRO(Radix) \
- template <typename T> struct digits_traits<T, Radix> \
+ template <int Digits> struct digits2_to_n<Digits, Radix> \
{ \
- typedef std::numeric_limits<T> numeric_limits_type; \
BOOST_STATIC_CONSTANT(int, value = static_cast<int>( \
- (numeric_limits_type::digits * 1000000) / \
+ (Digits * 1000000) / \
BOOST_PP_SEQ_ELEM(Radix, BOOST_SPIRIT_X3_LOG2))); \
}; \
/***/
#undef BOOST_SPIRIT_X3_LOG2
+ template <typename T, unsigned Radix>
+ struct digits_traits : digits2_to_n<std::numeric_limits<T>::digits, Radix>
+ {
+ static_assert(std::numeric_limits<T>::radix == 2, "");
+ };
+
+ template <typename T>
+ struct digits_traits<T, 10>
+ {
+ static int constexpr value = std::numeric_limits<T>::digits10;
+ };
+
///////////////////////////////////////////////////////////////////////////
//
// Traits class for radix specific number conversion
template <typename Char>
inline static bool is_valid(Char ch)
{
- if (Radix <= 10)
- return (ch >= '0' && ch <= static_cast<Char>('0' + Radix -1));
- return (ch >= '0' && ch <= '9')
- || (ch >= 'a' && ch <= static_cast<Char>('a' + Radix -10 -1))
- || (ch >= 'A' && ch <= static_cast<Char>('A' + Radix -10 -1));
+ return (ch >= '0' && ch <= (Radix > 10 ? '9' : static_cast<Char>('0' + Radix -1)))
+ || (Radix > 10 && ch >= 'a' && ch <= static_cast<Char>('a' + Radix -10 -1))
+ || (Radix > 10 && ch >= 'A' && ch <= static_cast<Char>('A' + Radix -10 -1));
}
template <typename Char>
inline static unsigned digit(Char ch)
{
- if (Radix <= 10 || (ch >= '0' && ch <= '9'))
- return ch - '0';
- return char_encoding::ascii::tolower(ch) - 'a' + 10;
+ return (Radix <= 10 || (ch >= '0' && ch <= '9'))
+ ? ch - '0'
+ : char_encoding::ascii::tolower(ch) - 'a' + 10;
}
};
inline static bool add(T& n, Char ch, mpl::true_) // checked add
{
// Ensure n *= Radix will not overflow
- static T const max = (std::numeric_limits<T>::max)();
- static T const val = max / Radix;
+ T const max = (std::numeric_limits<T>::max)();
+ T const val = max / Radix;
if (n > val)
return false;
- n *= Radix;
+ T tmp = n * Radix;
// Ensure n += digit will not overflow
const int digit = radix_traits<Radix>::digit(ch);
- if (n > max - digit)
+ if (tmp > max - digit)
return false;
- n += static_cast<T>(digit);
+ n = tmp + static_cast<T>(digit);
return true;
}
};
inline static bool add(T& n, Char ch, mpl::true_) // checked subtract
{
// Ensure n *= Radix will not underflow
- static T const min = (std::numeric_limits<T>::min)();
- static T const val = (min + 1) / T(Radix);
+ T const min = (std::numeric_limits<T>::min)();
+ T const val = min / T(Radix);
if (n < val)
return false;
- n *= Radix;
+ T tmp = n * Radix;
// Ensure n -= digit will not underflow
int const digit = radix_traits<Radix>::digit(ch);
- if (n < min + digit)
+ if (tmp < min + digit)
return false;
- n -= static_cast<T>(digit);
+ n = tmp - static_cast<T>(digit);
return true;
}
};
inline static bool
call(Char ch, std::size_t count, T& n, mpl::true_)
{
- static std::size_t const
+ std::size_t constexpr
overflow_free = digits_traits<T, Radix>::value - 1;
if (count < overflow_free)
typedef radix_traits<Radix> radix_check;
typedef int_extractor<Radix, Accumulator, MaxDigits> extractor;
typedef typename
- boost::detail::iterator_traits<Iterator>::value_type
+ std::iterator_traits<Iterator>::value_type
char_type;
Iterator it = first;
typedef radix_traits<Radix> radix_check;
typedef int_extractor<Radix, Accumulator, -1> extractor;
typedef typename
- boost::detail::iterator_traits<Iterator>::value_type
+ std::iterator_traits<Iterator>::value_type
char_type;
Iterator it = first;