unsigned_rule.hpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. //
  2. // Copyright (c) 2022 Alan de Freitas (alandefreitas at gmail dot com)
  3. //
  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. // Official repository: https://github.com/boostorg/url
  8. //
  9. #ifndef BOOST_URL_GRAMMAR_IMPL_UNSIGNED_RULE_HPP
  10. #define BOOST_URL_GRAMMAR_IMPL_UNSIGNED_RULE_HPP
  11. #include <boost/url/grammar/error.hpp>
  12. #include <boost/url/grammar/digit_chars.hpp>
  13. #include <algorithm> // VFALCO grr..
  14. namespace boost {
  15. namespace urls {
  16. namespace grammar {
  17. template<class U>
  18. auto
  19. unsigned_rule<U>::
  20. parse(
  21. char const*& it,
  22. char const* end
  23. ) const noexcept ->
  24. system::result<value_type>
  25. {
  26. if(it == end)
  27. {
  28. // end
  29. BOOST_URL_RETURN_EC(
  30. error::mismatch);
  31. }
  32. if(*it == '0')
  33. {
  34. ++it;
  35. if( it == end ||
  36. ! digit_chars(*it))
  37. {
  38. return U(0);
  39. }
  40. // bad leading zero
  41. BOOST_URL_RETURN_EC(
  42. error::invalid);
  43. }
  44. if(! digit_chars(*it))
  45. {
  46. // expected digit
  47. BOOST_URL_RETURN_EC(
  48. error::mismatch);
  49. }
  50. static constexpr U Digits10 =
  51. std::numeric_limits<
  52. U>::digits10;
  53. static constexpr U ten = 10;
  54. char const* safe_end;
  55. if(static_cast<std::size_t>(
  56. end - it) >= Digits10)
  57. safe_end = it + Digits10;
  58. else
  59. safe_end = end;
  60. U u = *it - '0';
  61. ++it;
  62. while(it != safe_end &&
  63. digit_chars(*it))
  64. {
  65. char const dig = *it - '0';
  66. u = u * ten + dig;
  67. ++it;
  68. }
  69. if( it != end &&
  70. digit_chars(*it))
  71. {
  72. static constexpr U Max = (
  73. std::numeric_limits<
  74. U>::max)();
  75. static constexpr
  76. auto div = (Max / ten);
  77. static constexpr
  78. char rem = (Max % ten);
  79. char const dig = *it - '0';
  80. if( u > div || (
  81. u == div && dig > rem))
  82. {
  83. // integer overflow
  84. BOOST_URL_RETURN_EC(
  85. error::invalid);
  86. }
  87. u = u * ten + dig;
  88. ++it;
  89. if( it < end &&
  90. digit_chars(*it))
  91. {
  92. // integer overflow
  93. BOOST_URL_RETURN_EC(
  94. error::invalid);
  95. }
  96. }
  97. return u;
  98. }
  99. } // grammar
  100. } // urls
  101. } // boost
  102. #endif