variant_rule.hpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco 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_VARIANT_RULE_HPP
  10. #define BOOST_URL_GRAMMAR_IMPL_VARIANT_RULE_HPP
  11. #include <boost/url/grammar/error.hpp>
  12. #include <boost/url/grammar/parse.hpp>
  13. #include <boost/core/detail/static_assert.hpp>
  14. #include <cstdint>
  15. #include <type_traits>
  16. namespace boost {
  17. namespace urls {
  18. namespace grammar {
  19. namespace detail {
  20. // must come first
  21. template<
  22. class R0,
  23. class... Rn,
  24. std::size_t I>
  25. auto
  26. parse_variant(
  27. char const*&,
  28. char const*,
  29. detail::tuple<
  30. R0, Rn...> const&,
  31. std::integral_constant<
  32. std::size_t, I> const&,
  33. std::false_type const&) ->
  34. system::result<variant2::variant<
  35. typename R0::value_type,
  36. typename Rn::value_type...>>
  37. {
  38. // no match
  39. BOOST_URL_RETURN_EC(
  40. error::mismatch);
  41. }
  42. template<
  43. class R0,
  44. class... Rn,
  45. std::size_t I>
  46. auto
  47. parse_variant(
  48. char const*& it,
  49. char const* const end,
  50. detail::tuple<
  51. R0, Rn...> const& rn,
  52. std::integral_constant<
  53. std::size_t, I> const&,
  54. std::true_type const&) ->
  55. system::result<variant2::variant<
  56. typename R0::value_type,
  57. typename Rn::value_type...>>
  58. {
  59. auto const it0 = it;
  60. auto rv = parse(
  61. it, end, get<I>(rn));
  62. if( rv )
  63. return variant2::variant<
  64. typename R0::value_type,
  65. typename Rn::value_type...>{
  66. variant2::in_place_index_t<I>{}, *rv};
  67. it = it0;
  68. return parse_variant(
  69. it, end, rn,
  70. std::integral_constant<
  71. std::size_t, I+1>{},
  72. std::integral_constant<bool,
  73. ((I + 1) < (1 +
  74. sizeof...(Rn)))>{});
  75. }
  76. } // detail
  77. template<class R0, class... Rn>
  78. auto
  79. implementation_defined::variant_rule_t<R0, Rn...>::
  80. parse(
  81. char const*& it,
  82. char const* end) const ->
  83. system::result<value_type>
  84. {
  85. return detail::parse_variant(
  86. it, end, rn_,
  87. std::integral_constant<
  88. std::size_t, 0>{},
  89. std::true_type{});
  90. }
  91. //------------------------------------------------
  92. template<BOOST_URL_CONSTRAINT(Rule) R0, BOOST_URL_CONSTRAINT(Rule)... Rn>
  93. auto
  94. constexpr
  95. variant_rule(
  96. R0 const& r0,
  97. Rn const&... rn) noexcept ->
  98. implementation_defined::variant_rule_t<R0, Rn...>
  99. {
  100. BOOST_CORE_STATIC_ASSERT(
  101. mp11::mp_all<
  102. is_rule<R0>,
  103. is_rule<Rn>...>::value);
  104. return { r0, rn... };
  105. }
  106. } // grammar
  107. } // urls
  108. } // boost
  109. #endif