numeric_utils.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2011 Jan Frederick Eick
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. #if !defined(BOOST_SPIRIT_NUMERIC_UTILS_APRIL_17_2006_0830AM)
  8. #define BOOST_SPIRIT_NUMERIC_UTILS_APRIL_17_2006_0830AM
  9. #if defined(_MSC_VER)
  10. #pragma once
  11. #endif
  12. #include <boost/spirit/home/support/assert_msg.hpp>
  13. #include <boost/spirit/home/qi/detail/assign_to.hpp>
  14. #include <boost/spirit/home/qi/numeric/detail/numeric_utils.hpp>
  15. #include <boost/assert.hpp>
  16. #include <boost/mpl/assert.hpp>
  17. namespace boost { namespace spirit { namespace qi
  18. {
  19. ///////////////////////////////////////////////////////////////////////////
  20. // Extract the prefix sign (- or +), return true if a '-' was found
  21. ///////////////////////////////////////////////////////////////////////////
  22. template <typename Iterator>
  23. inline bool
  24. extract_sign(Iterator& first, Iterator const& last)
  25. {
  26. (void)last; // silence unused warnings
  27. BOOST_ASSERT(first != last); // precondition
  28. // Extract the sign
  29. bool neg = *first == '-';
  30. if (neg || (*first == '+'))
  31. {
  32. ++first;
  33. return neg;
  34. }
  35. return false;
  36. }
  37. ///////////////////////////////////////////////////////////////////////////
  38. // Low level unsigned integer parser
  39. ///////////////////////////////////////////////////////////////////////////
  40. template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits
  41. , bool Accumulate = false, bool IgnoreOverflowDigits = false>
  42. struct extract_uint
  43. {
  44. // check template parameter 'Radix' for validity
  45. BOOST_SPIRIT_ASSERT_MSG(
  46. Radix >= 2 && Radix <= 36,
  47. not_supported_radix, ());
  48. template <typename Iterator>
  49. inline static bool call(Iterator& first, Iterator const& last, T& attr_)
  50. {
  51. if (first == last)
  52. return false;
  53. typedef detail::extract_int<
  54. T
  55. , Radix
  56. , MinDigits
  57. , MaxDigits
  58. , detail::positive_accumulator<Radix>
  59. , Accumulate
  60. , IgnoreOverflowDigits>
  61. extract_type;
  62. Iterator save = first;
  63. if (!extract_type::parse(first, last, attr_))
  64. {
  65. first = save;
  66. return false;
  67. }
  68. return true;
  69. }
  70. template <typename Iterator, typename Attribute>
  71. inline static bool call(Iterator& first, Iterator const& last, Attribute& attr_)
  72. {
  73. // this case is called when Attribute is not T
  74. T attr_local;
  75. if (call(first, last, attr_local))
  76. {
  77. traits::assign_to(attr_local, attr_);
  78. return true;
  79. }
  80. return false;
  81. }
  82. };
  83. ///////////////////////////////////////////////////////////////////////////
  84. // Low level signed integer parser
  85. ///////////////////////////////////////////////////////////////////////////
  86. template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
  87. struct extract_int
  88. {
  89. // check template parameter 'Radix' for validity
  90. BOOST_SPIRIT_ASSERT_MSG(
  91. Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
  92. not_supported_radix, ());
  93. template <typename Iterator>
  94. inline static bool call(Iterator& first, Iterator const& last, T& attr_)
  95. {
  96. if (first == last)
  97. return false;
  98. typedef detail::extract_int<
  99. T, Radix, MinDigits, MaxDigits>
  100. extract_pos_type;
  101. typedef detail::extract_int<
  102. T, Radix, MinDigits, MaxDigits, detail::negative_accumulator<Radix> >
  103. extract_neg_type;
  104. Iterator save = first;
  105. bool hit = extract_sign(first, last);
  106. if (hit)
  107. hit = extract_neg_type::parse(first, last, attr_);
  108. else
  109. hit = extract_pos_type::parse(first, last, attr_);
  110. if (!hit)
  111. {
  112. first = save;
  113. return false;
  114. }
  115. return true;
  116. }
  117. template <typename Iterator, typename Attribute>
  118. inline static bool call(Iterator& first, Iterator const& last, Attribute& attr_)
  119. {
  120. // this case is called when Attribute is not T
  121. T attr_local;
  122. if (call(first, last, attr_local))
  123. {
  124. traits::assign_to(attr_local, attr_);
  125. return true;
  126. }
  127. return false;
  128. }
  129. };
  130. }}}
  131. #endif