tuple_rule.hpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. //
  2. // Copyright (c) 2022 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_TUPLE_RULE_HPP
  10. #define BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP
  11. #include <boost/url/grammar/parse.hpp>
  12. #include <boost/mp11/integral.hpp>
  13. #include <boost/mp11/list.hpp>
  14. #include <boost/mp11/tuple.hpp>
  15. #include <type_traits>
  16. namespace boost {
  17. namespace urls {
  18. namespace grammar {
  19. namespace detail {
  20. // returns a tuple
  21. template<
  22. bool IsList,
  23. class R0, class... Rn>
  24. struct parse_sequence
  25. {
  26. using R = detail::tuple<R0, Rn...>;
  27. using L = mp11::mp_list<
  28. typename R0::value_type,
  29. typename Rn::value_type...>;
  30. using V = mp11::mp_remove<
  31. std::tuple<
  32. system::result<typename R0::value_type>,
  33. system::result<typename Rn::value_type>...>,
  34. system::result<void>>;
  35. template<std::size_t I>
  36. using is_void = std::is_same<
  37. mp11::mp_at_c<L, I>, void>;
  38. system::error_code ec;
  39. R const& rn;
  40. V vn;
  41. explicit
  42. parse_sequence(
  43. R const& rn_) noexcept
  44. : rn(rn_)
  45. , vn(mp11::mp_fill<
  46. V, system::error_code>{})
  47. {
  48. }
  49. void
  50. apply(
  51. char const*&,
  52. char const*,
  53. ...) const noexcept
  54. {
  55. }
  56. // for system::result<void>
  57. template<
  58. std::size_t Ir,
  59. std::size_t Iv>
  60. void
  61. apply(
  62. char const*& it,
  63. char const* end,
  64. mp11::mp_size_t<Ir> const&,
  65. mp11::mp_size_t<Iv> const&,
  66. mp11::mp_true const&)
  67. {
  68. system::result<void> rv =
  69. grammar::parse(
  70. it, end, get<Ir>(rn));
  71. if( !rv )
  72. {
  73. ec = rv.error();
  74. return;
  75. }
  76. apply(it, end,
  77. mp11::mp_size_t<Ir+1>{},
  78. mp11::mp_size_t<Iv>{});
  79. }
  80. template<
  81. std::size_t Ir,
  82. std::size_t Iv>
  83. void
  84. apply(
  85. char const*& it,
  86. char const* end,
  87. mp11::mp_size_t<Ir> const&,
  88. mp11::mp_size_t<Iv> const&,
  89. mp11::mp_false const&)
  90. {
  91. auto& rv = get<Iv>(vn);
  92. rv = grammar::parse(
  93. it, end, get<Ir>(rn));
  94. if( !rv )
  95. {
  96. ec = rv.error();
  97. return;
  98. }
  99. apply(it, end,
  100. mp11::mp_size_t<Ir+1>{},
  101. mp11::mp_size_t<Iv+1>{});
  102. }
  103. template<
  104. std::size_t Ir = 0,
  105. std::size_t Iv = 0>
  106. typename std::enable_if<
  107. Ir < 1 + sizeof...(Rn)>::type
  108. apply(
  109. char const*& it,
  110. char const* end,
  111. mp11::mp_size_t<Ir> const& ir = {},
  112. mp11::mp_size_t<Iv> const& iv = {}
  113. ) noexcept
  114. {
  115. apply(it, end, ir, iv, is_void<Ir>{});
  116. }
  117. struct deref
  118. {
  119. template<class R>
  120. auto
  121. operator()(R const& r) const ->
  122. decltype(*r)
  123. {
  124. return *r;
  125. }
  126. };
  127. auto
  128. make_result() noexcept ->
  129. system::result<typename tuple_rule_t<
  130. R0, Rn...>::value_type>
  131. {
  132. if(ec.failed())
  133. return ec;
  134. return mp11::tuple_transform(
  135. deref{}, vn);
  136. }
  137. };
  138. // returns a value_type
  139. template<class R0, class... Rn>
  140. struct parse_sequence<false, R0, Rn...>
  141. {
  142. using R = detail::tuple<R0, Rn...>;
  143. using L = mp11::mp_list<
  144. typename R0::value_type,
  145. typename Rn::value_type...>;
  146. using V = mp11::mp_first<
  147. mp11::mp_remove<
  148. mp11::mp_list<
  149. system::result<typename R0::value_type>,
  150. system::result<typename Rn::value_type>...>,
  151. system::result<void>>>;
  152. template<std::size_t I>
  153. using is_void = std::is_same<
  154. mp11::mp_at_c<L, I>, void>;
  155. R const& rn;
  156. V v;
  157. explicit
  158. parse_sequence(
  159. R const& rn_) noexcept
  160. : rn(rn_)
  161. , v(system::error_code{})
  162. {
  163. }
  164. void
  165. apply(
  166. char const*&,
  167. char const*,
  168. ...) const noexcept
  169. {
  170. }
  171. // for system::result<void>
  172. template<
  173. std::size_t Ir,
  174. std::size_t Iv>
  175. BOOST_URL_NO_INLINE
  176. void
  177. apply(
  178. char const*& it,
  179. char const* end,
  180. mp11::mp_size_t<Ir> const&,
  181. mp11::mp_size_t<Iv> const&,
  182. mp11::mp_true const&)
  183. {
  184. system::result<void> rv =
  185. grammar::parse(
  186. it, end, get<Ir>(rn));
  187. if( !rv )
  188. {
  189. v = rv.error();
  190. return;
  191. }
  192. apply(it, end,
  193. mp11::mp_size_t<Ir+1>{},
  194. mp11::mp_size_t<Iv>{});
  195. }
  196. template<
  197. std::size_t Ir,
  198. std::size_t Iv>
  199. void
  200. apply(
  201. char const*& it,
  202. char const* end,
  203. mp11::mp_size_t<Ir> const&,
  204. mp11::mp_size_t<Iv> const&,
  205. mp11::mp_false const&)
  206. {
  207. v = grammar::parse(
  208. it, end, get<Ir>(rn));
  209. if( !v )
  210. return;
  211. apply(it, end,
  212. mp11::mp_size_t<Ir+1>{},
  213. mp11::mp_size_t<Iv+1>{});
  214. }
  215. template<
  216. std::size_t Ir = 0,
  217. std::size_t Iv = 0>
  218. typename std::enable_if<
  219. Ir < 1 + sizeof...(Rn)>::type
  220. apply(
  221. char const*& it,
  222. char const* end,
  223. mp11::mp_size_t<Ir> const& ir = {},
  224. mp11::mp_size_t<Iv> const& iv = {}
  225. ) noexcept
  226. {
  227. apply(it, end, ir, iv, is_void<Ir>{});
  228. }
  229. V
  230. make_result() noexcept
  231. {
  232. return v;
  233. }
  234. };
  235. } // detail
  236. template<
  237. class R0,
  238. class... Rn>
  239. auto
  240. tuple_rule_t<R0, Rn...>::
  241. parse(
  242. char const*& it,
  243. char const* end) const ->
  244. system::result<value_type>
  245. {
  246. detail::parse_sequence<
  247. IsList, R0, Rn...> t(this->get());
  248. t.apply(it, end);
  249. return t.make_result();
  250. }
  251. } // grammar
  252. } // urls
  253. } // boost
  254. #endif