extract_int.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*=============================================================================
  2. Copyright (c) 2001-2014 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_X3_EXTRACT_INT_APRIL_17_2006_0830AM)
  8. #define BOOST_SPIRIT_X3_EXTRACT_INT_APRIL_17_2006_0830AM
  9. #include <boost/spirit/home/x3/support/traits/move_to.hpp>
  10. #include <boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp>
  11. #include <boost/assert.hpp>
  12. namespace boost { namespace spirit { namespace x3
  13. {
  14. ///////////////////////////////////////////////////////////////////////////
  15. // Extract the prefix sign (- or +), return true if a '-' was found
  16. ///////////////////////////////////////////////////////////////////////////
  17. template <typename Iterator>
  18. inline bool
  19. extract_sign(Iterator& first, Iterator const& last)
  20. {
  21. (void)last; // silence unused warnings
  22. BOOST_ASSERT(first != last); // precondition
  23. // Extract the sign
  24. bool neg = *first == '-';
  25. if (neg || (*first == '+'))
  26. {
  27. ++first;
  28. return neg;
  29. }
  30. return false;
  31. }
  32. ///////////////////////////////////////////////////////////////////////////
  33. // Low level unsigned integer parser
  34. ///////////////////////////////////////////////////////////////////////////
  35. template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits
  36. , bool Accumulate = false>
  37. struct extract_uint
  38. {
  39. // check template parameter 'Radix' for validity
  40. static_assert(
  41. (Radix >= 2 && Radix <= 36),
  42. "Error Unsupported Radix");
  43. template <typename Iterator>
  44. inline static bool call(Iterator& first, Iterator const& last, T& attr)
  45. {
  46. if (first == last)
  47. return false;
  48. typedef detail::extract_int<
  49. T
  50. , Radix
  51. , MinDigits
  52. , MaxDigits
  53. , detail::positive_accumulator<Radix>
  54. , Accumulate>
  55. extract_type;
  56. Iterator save = first;
  57. if (!extract_type::parse(first, last, attr))
  58. {
  59. first = save;
  60. return false;
  61. }
  62. return true;
  63. }
  64. template <typename Iterator, typename Attribute>
  65. inline static bool call(Iterator& first, Iterator const& last, Attribute& attr_)
  66. {
  67. // this case is called when Attribute is not T
  68. T attr;
  69. if (call(first, last, attr))
  70. {
  71. traits::move_to(attr, attr_);
  72. return true;
  73. }
  74. return false;
  75. }
  76. };
  77. ///////////////////////////////////////////////////////////////////////////
  78. // Low level signed integer parser
  79. ///////////////////////////////////////////////////////////////////////////
  80. template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
  81. struct extract_int
  82. {
  83. // check template parameter 'Radix' for validity
  84. static_assert(
  85. (Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16),
  86. "Error Unsupported Radix");
  87. template <typename Iterator>
  88. inline static bool call(Iterator& first, Iterator const& last, T& attr)
  89. {
  90. if (first == last)
  91. return false;
  92. typedef detail::extract_int<
  93. T, Radix, MinDigits, MaxDigits>
  94. extract_pos_type;
  95. typedef detail::extract_int<
  96. T, Radix, MinDigits, MaxDigits, detail::negative_accumulator<Radix> >
  97. extract_neg_type;
  98. Iterator save = first;
  99. bool hit = extract_sign(first, last);
  100. if (hit)
  101. hit = extract_neg_type::parse(first, last, attr);
  102. else
  103. hit = extract_pos_type::parse(first, last, attr);
  104. if (!hit)
  105. {
  106. first = save;
  107. return false;
  108. }
  109. return true;
  110. }
  111. template <typename Iterator, typename Attribute>
  112. inline static bool call(Iterator& first, Iterator const& last, Attribute& attr_)
  113. {
  114. // this case is called when Attribute is not T
  115. T attr;
  116. if (call(first, last, attr))
  117. {
  118. traits::move_to(attr, attr_);
  119. return true;
  120. }
  121. return false;
  122. }
  123. };
  124. }}}
  125. #endif