tuple_rule.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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_TUPLE_RULE_HPP
  10. #define BOOST_URL_GRAMMAR_TUPLE_RULE_HPP
  11. #include <boost/url/detail/config.hpp>
  12. #include <boost/url/error_types.hpp>
  13. #include <boost/url/grammar/error.hpp>
  14. #include <boost/url/grammar/detail/tuple.hpp>
  15. #include <boost/url/grammar/type_traits.hpp>
  16. #include <boost/mp11/algorithm.hpp>
  17. #include <boost/core/detail/static_assert.hpp>
  18. #include <boost/core/empty_value.hpp>
  19. #include <tuple>
  20. namespace boost {
  21. namespace urls {
  22. namespace grammar {
  23. namespace implementation_defined {
  24. template<
  25. class R0,
  26. class... Rn>
  27. class tuple_rule_t
  28. : empty_value<
  29. detail::tuple<R0, Rn...>>
  30. {
  31. using T = mp11::mp_remove<
  32. std::tuple<
  33. typename R0::value_type,
  34. typename Rn::value_type...>,
  35. void>;
  36. static constexpr bool IsList =
  37. mp11::mp_size<T>::value != 1;
  38. public:
  39. using value_type =
  40. mp11::mp_eval_if_c<IsList,
  41. T, mp11::mp_first, T>;
  42. constexpr
  43. tuple_rule_t(
  44. R0 const& r0,
  45. Rn const&... rn) noexcept
  46. : empty_value<
  47. detail::tuple<R0, Rn...>>(
  48. empty_init,
  49. r0, rn...)
  50. {
  51. }
  52. system::result<value_type>
  53. parse(
  54. char const*& it,
  55. char const* end) const;
  56. };
  57. } // implementation_defined
  58. /** Match a series of rules in order
  59. This matches a series of rules in the
  60. order specified. Upon success the input
  61. is adjusted to point to the first
  62. unconsumed character. There is no
  63. implicit specification of linear white
  64. space between each rule.
  65. @par Value Type
  66. @code
  67. using value_type = __see_below__;
  68. @endcode
  69. The sequence rule usually returns a
  70. `std::tuple` containing the the `value_type`
  71. of each corresponding rule in the sequence,
  72. except that `void` values are removed.
  73. However, if there is exactly one non-void
  74. value type `T`, then the sequence rule
  75. returns `system::result<T>` instead of
  76. `system::result<tuple<...>>`.
  77. @par Example
  78. Rules are used with the function @ref parse.
  79. @code
  80. system::result< std::tuple< unsigned char, unsigned char, unsigned char, unsigned char > > rv =
  81. parse( "192.168.0.1",
  82. tuple_rule(
  83. dec_octet_rule,
  84. squelch( delim_rule('.') ),
  85. dec_octet_rule,
  86. squelch( delim_rule('.') ),
  87. dec_octet_rule,
  88. squelch( delim_rule('.') ),
  89. dec_octet_rule ) );
  90. @endcode
  91. @par BNF
  92. @code
  93. sequence = rule1 rule2 rule3...
  94. @endcode
  95. @par Specification
  96. @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.1"
  97. >3.1. Concatenation (rfc5234)</a>
  98. @param r0 The first rule to match
  99. @param rn A list of one or more rules to match
  100. @return The sequence rule
  101. @see
  102. @ref dec_octet_rule,
  103. @ref delim_rule,
  104. @ref parse,
  105. @ref squelch.
  106. */
  107. template<
  108. BOOST_URL_CONSTRAINT(Rule) R0,
  109. BOOST_URL_CONSTRAINT(Rule)... Rn>
  110. constexpr
  111. auto
  112. tuple_rule(
  113. R0 const& r0,
  114. Rn const&... rn) noexcept ->
  115. implementation_defined::tuple_rule_t<
  116. R0, Rn...>
  117. {
  118. BOOST_CORE_STATIC_ASSERT(
  119. mp11::mp_all<
  120. is_rule<R0>,
  121. is_rule<Rn>...>::value);
  122. return { r0, rn... };
  123. }
  124. namespace implementation_defined {
  125. template<class Rule>
  126. struct squelch_rule_t
  127. : empty_value<Rule>
  128. {
  129. using value_type = void;
  130. constexpr
  131. squelch_rule_t(
  132. Rule const& r) noexcept
  133. : empty_value<Rule>(
  134. empty_init, r)
  135. {
  136. }
  137. system::result<value_type>
  138. parse(
  139. char const*& it,
  140. char const* end) const
  141. {
  142. auto rv = this->get().parse(it, end);
  143. if(rv.error())
  144. return rv.error();
  145. return {}; // void
  146. }
  147. };
  148. } // implementation_defined
  149. /** Squelch the value of a rule
  150. This function returns a new rule which
  151. matches the specified rule, and converts
  152. its value type to `void`. This is useful
  153. for matching delimiters in a grammar,
  154. where the value for the delimiter is not
  155. needed.
  156. @par Value Type
  157. @code
  158. using value_type = void;
  159. @endcode
  160. @par Example 1
  161. With `squelch`:
  162. @code
  163. system::result< std::tuple< decode_view, core::string_view > > rv = parse(
  164. "www.example.com:443",
  165. tuple_rule(
  166. pct_encoded_rule(unreserved_chars + '-' + '.'),
  167. squelch( delim_rule( ':' ) ),
  168. token_rule( digit_chars ) ) );
  169. @endcode
  170. @par Example 2
  171. Without `squelch`:
  172. @code
  173. system::result< std::tuple< decode_view, core::string_view, core::string_view > > rv = parse(
  174. "www.example.com:443",
  175. tuple_rule(
  176. pct_encoded_rule(unreserved_chars + '-' + '.'),
  177. delim_rule( ':' ),
  178. token_rule( digit_chars ) ) );
  179. @endcode
  180. @param r The rule to squelch
  181. @return The squelched rule
  182. @see
  183. @ref delim_rule,
  184. @ref digit_chars,
  185. @ref parse,
  186. @ref tuple_rule,
  187. @ref token_rule,
  188. @ref decode_view,
  189. @ref pct_encoded_rule,
  190. @ref unreserved_chars.
  191. */
  192. template<BOOST_URL_CONSTRAINT(Rule) R>
  193. constexpr
  194. BOOST_URL_IMPLEMENTATION_DEFINED(implementation_defined::squelch_rule_t<R>)
  195. squelch( R const& r ) noexcept
  196. {
  197. BOOST_CORE_STATIC_ASSERT(is_rule<R>::value);
  198. return { r };
  199. }
  200. } // grammar
  201. } // urls
  202. } // boost
  203. #include <boost/url/grammar/impl/tuple_rule.hpp>
  204. #endif