File indexing completed on 2025-01-18 09:53:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP
0011 #define BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP
0012
0013 #include <boost/url/grammar/parse.hpp>
0014 #include <boost/mp11/integral.hpp>
0015 #include <boost/mp11/list.hpp>
0016 #include <boost/mp11/tuple.hpp>
0017 #include <type_traits>
0018
0019 namespace boost {
0020 namespace urls {
0021 namespace grammar {
0022
0023 namespace detail {
0024
0025
0026 template<
0027 bool IsList,
0028 class R0, class... Rn>
0029 struct parse_sequence
0030 {
0031 using R = detail::tuple<R0, Rn...>;
0032
0033 using L = mp11::mp_list<
0034 typename R0::value_type,
0035 typename Rn::value_type...>;
0036
0037 using V = mp11::mp_remove<
0038 std::tuple<
0039 system::result<typename R0::value_type>,
0040 system::result<typename Rn::value_type>...>,
0041 system::result<void>>;
0042
0043 template<std::size_t I>
0044 using is_void = std::is_same<
0045 mp11::mp_at_c<L, I>, void>;
0046
0047 system::error_code ec;
0048 R const& rn;
0049 V vn;
0050
0051 explicit
0052 parse_sequence(
0053 R const& rn_) noexcept
0054 : rn(rn_)
0055 , vn(mp11::mp_fill<
0056 V, system::error_code>{})
0057 {
0058 }
0059
0060 void
0061 apply(
0062 char const*&,
0063 char const*,
0064 ...) const noexcept
0065 {
0066 }
0067
0068
0069 template<
0070 std::size_t Ir,
0071 std::size_t Iv>
0072 void
0073 apply(
0074 char const*& it,
0075 char const* end,
0076 mp11::mp_size_t<Ir> const&,
0077 mp11::mp_size_t<Iv> const&,
0078 mp11::mp_true const&)
0079 {
0080 system::result<void> rv =
0081 grammar::parse(
0082 it, end, get<Ir>(rn));
0083 if( !rv )
0084 {
0085 ec = rv.error();
0086 return;
0087 }
0088 apply(it, end,
0089 mp11::mp_size_t<Ir+1>{},
0090 mp11::mp_size_t<Iv>{});
0091 }
0092
0093 template<
0094 std::size_t Ir,
0095 std::size_t Iv>
0096 void
0097 apply(
0098 char const*& it,
0099 char const* end,
0100 mp11::mp_size_t<Ir> const&,
0101 mp11::mp_size_t<Iv> const&,
0102 mp11::mp_false const&)
0103 {
0104 auto& rv = get<Iv>(vn);
0105 rv = grammar::parse(
0106 it, end, get<Ir>(rn));
0107 if( !rv )
0108 {
0109 ec = rv.error();
0110 return;
0111 }
0112 apply(it, end,
0113 mp11::mp_size_t<Ir+1>{},
0114 mp11::mp_size_t<Iv+1>{});
0115 }
0116
0117 template<
0118 std::size_t Ir = 0,
0119 std::size_t Iv = 0>
0120 typename std::enable_if<
0121 Ir < 1 + sizeof...(Rn)>::type
0122 apply(
0123 char const*& it,
0124 char const* end,
0125 mp11::mp_size_t<Ir> const& ir = {},
0126 mp11::mp_size_t<Iv> const& iv = {}
0127 ) noexcept
0128 {
0129 apply(it, end, ir, iv, is_void<Ir>{});
0130 }
0131
0132 struct deref
0133 {
0134 template<class R>
0135 auto
0136 operator()(R const& r) const ->
0137 decltype(*r)
0138 {
0139 return *r;
0140 }
0141 };
0142
0143 auto
0144 make_result() noexcept ->
0145 system::result<typename tuple_rule_t<
0146 R0, Rn...>::value_type>
0147 {
0148 if(ec.failed())
0149 return ec;
0150 return mp11::tuple_transform(
0151 deref{}, vn);
0152 }
0153 };
0154
0155
0156 template<class R0, class... Rn>
0157 struct parse_sequence<false, R0, Rn...>
0158 {
0159 using R = detail::tuple<R0, Rn...>;
0160
0161 using L = mp11::mp_list<
0162 typename R0::value_type,
0163 typename Rn::value_type...>;
0164
0165 using V = mp11::mp_first<
0166 mp11::mp_remove<
0167 mp11::mp_list<
0168 system::result<typename R0::value_type>,
0169 system::result<typename Rn::value_type>...>,
0170 system::result<void>>>;
0171
0172 template<std::size_t I>
0173 using is_void = std::is_same<
0174 mp11::mp_at_c<L, I>, void>;
0175
0176 R const& rn;
0177 V v;
0178
0179 explicit
0180 parse_sequence(
0181 R const& rn_) noexcept
0182 : rn(rn_)
0183 , v(system::error_code{})
0184 {
0185 }
0186
0187 void
0188 apply(
0189 char const*&,
0190 char const*,
0191 ...) const noexcept
0192 {
0193 }
0194
0195
0196 template<
0197 std::size_t Ir,
0198 std::size_t Iv>
0199 BOOST_URL_NO_INLINE
0200 void
0201 apply(
0202 char const*& it,
0203 char const* end,
0204 mp11::mp_size_t<Ir> const&,
0205 mp11::mp_size_t<Iv> const&,
0206 mp11::mp_true const&)
0207 {
0208 system::result<void> rv =
0209 grammar::parse(
0210 it, end, get<Ir>(rn));
0211 if( !rv )
0212 {
0213 v = rv.error();
0214 return;
0215 }
0216 apply(it, end,
0217 mp11::mp_size_t<Ir+1>{},
0218 mp11::mp_size_t<Iv>{});
0219 }
0220
0221 template<
0222 std::size_t Ir,
0223 std::size_t Iv>
0224 void
0225 apply(
0226 char const*& it,
0227 char const* end,
0228 mp11::mp_size_t<Ir> const&,
0229 mp11::mp_size_t<Iv> const&,
0230 mp11::mp_false const&)
0231 {
0232 v = grammar::parse(
0233 it, end, get<Ir>(rn));
0234 if( !v )
0235 return;
0236 apply(it, end,
0237 mp11::mp_size_t<Ir+1>{},
0238 mp11::mp_size_t<Iv+1>{});
0239 }
0240
0241 template<
0242 std::size_t Ir = 0,
0243 std::size_t Iv = 0>
0244 typename std::enable_if<
0245 Ir < 1 + sizeof...(Rn)>::type
0246 apply(
0247 char const*& it,
0248 char const* end,
0249 mp11::mp_size_t<Ir> const& ir = {},
0250 mp11::mp_size_t<Iv> const& iv = {}
0251 ) noexcept
0252 {
0253 apply(it, end, ir, iv, is_void<Ir>{});
0254 }
0255
0256 V
0257 make_result() noexcept
0258 {
0259 return v;
0260 }
0261 };
0262
0263 }
0264
0265 template<
0266 class R0,
0267 class... Rn>
0268 auto
0269 tuple_rule_t<R0, Rn...>::
0270 parse(
0271 char const*& it,
0272 char const* end) const ->
0273 system::result<value_type>
0274 {
0275 detail::parse_sequence<
0276 IsList, R0, Rn...> t(this->get());
0277 t.apply(it, end);
0278 return t.make_result();
0279 }
0280
0281 }
0282 }
0283 }
0284
0285 #endif