![]() |
|
|||
File indexing completed on 2025-09-17 08:52:41
0001 // 0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 0003 // 0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0006 // 0007 // Official repository: https://github.com/boostorg/url 0008 // 0009 0010 #ifndef BOOST_URL_GRAMMAR_RANGE_RULE_HPP 0011 #define BOOST_URL_GRAMMAR_RANGE_RULE_HPP 0012 0013 #include <boost/url/detail/config.hpp> 0014 #include <boost/url/error.hpp> 0015 #include <boost/core/detail/string_view.hpp> 0016 #include <boost/url/grammar/parse.hpp> 0017 #include <boost/url/grammar/type_traits.hpp> 0018 #include <boost/static_assert.hpp> 0019 #include <cstddef> 0020 #include <iterator> 0021 #include <type_traits> 0022 #include <stddef.h> // ::max_align_t 0023 0024 namespace boost { 0025 namespace urls { 0026 namespace grammar { 0027 namespace implementation_defined { 0028 template<class R0, class R1> 0029 struct range_rule_t; 0030 } // implementation_defined 0031 0032 /** A forward range of parsed elements 0033 0034 Objects of this type are forward ranges 0035 returned when parsing using the 0036 @ref range_rule. 0037 Iteration is performed by re-parsing the 0038 underlying character buffer. Ownership 0039 of the buffer is not transferred; the 0040 caller is responsible for ensuring that 0041 the lifetime of the buffer extends until 0042 it is no longer referenced by the range. 0043 0044 @note 0045 0046 The implementation may use temporary, 0047 recycled storage for type-erasure. Objects 0048 of type `range` are intended to be used 0049 ephemerally. That is, for short durations 0050 such as within a function scope. If it is 0051 necessary to store the range for a long 0052 period of time or with static storage 0053 duration, it is necessary to copy the 0054 contents to an object of a different type. 0055 0056 @tparam T The value type of the range 0057 0058 @see 0059 @ref parse, 0060 @ref range_rule. 0061 */ 0062 template<class T> 0063 class range 0064 { 0065 // buffer size for type-erased rule 0066 static constexpr 0067 std::size_t BufferSize = 128; 0068 0069 struct small_buffer 0070 { 0071 alignas(alignof(::max_align_t)) 0072 unsigned char buf[BufferSize]; 0073 0074 void const* addr() const noexcept 0075 { 0076 return buf; 0077 } 0078 0079 void* addr() noexcept 0080 { 0081 return buf; 0082 } 0083 }; 0084 0085 small_buffer sb_; 0086 core::string_view s_; 0087 std::size_t n_ = 0; 0088 0089 //-------------------------------------------- 0090 0091 struct any_rule; 0092 0093 template<class R, bool> 0094 struct impl1; 0095 0096 template< 0097 class R0, class R1, bool> 0098 struct impl2; 0099 0100 template< 0101 class R0, class R1> 0102 friend struct implementation_defined::range_rule_t; 0103 0104 any_rule& 0105 get() noexcept 0106 { 0107 return *reinterpret_cast< 0108 any_rule*>(sb_.addr()); 0109 } 0110 0111 any_rule const& 0112 get() const noexcept 0113 { 0114 return *reinterpret_cast< 0115 any_rule const*>( 0116 sb_.addr()); 0117 } 0118 0119 template<class R> 0120 range( 0121 core::string_view s, 0122 std::size_t n, 0123 R const& r); 0124 0125 template< 0126 class R0, class R1> 0127 range( 0128 core::string_view s, 0129 std::size_t n, 0130 R0 const& first, 0131 R1 const& next); 0132 0133 public: 0134 /** The type of each element of the range 0135 */ 0136 using value_type = T; 0137 0138 /** The type of each element of the range 0139 */ 0140 using reference = T const&; 0141 0142 /** The type of each element of the range 0143 */ 0144 using const_reference = T const&; 0145 0146 /** Provided for compatibility, unused 0147 */ 0148 using pointer = void const*; 0149 0150 /** The type used to represent unsigned integers 0151 */ 0152 using size_type = std::size_t; 0153 0154 /** The type used to represent signed integers 0155 */ 0156 using difference_type = std::ptrdiff_t; 0157 0158 /** A constant, forward iterator to elements of the range 0159 */ 0160 class iterator; 0161 0162 /** A constant, forward iterator to elements of the range 0163 */ 0164 using const_iterator = iterator; 0165 0166 /** Destructor 0167 */ 0168 ~range(); 0169 0170 /** Constructor 0171 0172 Default-constructed ranges have 0173 zero elements. 0174 0175 @par Exception Safety 0176 Throws nothing. 0177 */ 0178 range() noexcept; 0179 0180 /** Constructor 0181 0182 The new range references the 0183 same underlying character buffer. 0184 Ownership is not transferred; the 0185 caller is responsible for ensuring 0186 that the lifetime of the buffer 0187 extends until it is no longer 0188 referenced. The moved-from object 0189 becomes as if default-constructed. 0190 0191 @par Exception Safety 0192 Throws nothing. 0193 */ 0194 range(range&&) noexcept; 0195 0196 /** Constructor 0197 0198 The copy references the same 0199 underlying character buffer. 0200 Ownership is not transferred; the 0201 caller is responsible for ensuring 0202 that the lifetime of the buffer 0203 extends until it is no longer 0204 referenced. 0205 0206 @par Exception Safety 0207 Throws nothing. 0208 */ 0209 range(range const&) noexcept; 0210 0211 /** Assignment 0212 0213 After the move, this references the 0214 same underlying character buffer. Ownership 0215 is not transferred; the caller is responsible 0216 for ensuring that the lifetime of the buffer 0217 extends until it is no longer referenced. 0218 The moved-from object becomes as if 0219 default-constructed. 0220 0221 @par Exception Safety 0222 Throws nothing. 0223 0224 @return `*this` 0225 */ 0226 range& 0227 operator=(range&&) noexcept; 0228 0229 /** Assignment 0230 0231 The copy references the same 0232 underlying character buffer. 0233 Ownership is not transferred; the 0234 caller is responsible for ensuring 0235 that the lifetime of the buffer 0236 extends until it is no longer 0237 referenced. 0238 0239 @par Exception Safety 0240 Throws nothing. 0241 0242 @return `*this` 0243 */ 0244 range& 0245 operator=(range const&) noexcept; 0246 0247 /** Return an iterator to the beginning 0248 0249 @return An iterator to the first element 0250 */ 0251 iterator begin() const noexcept; 0252 0253 /** Return an iterator to the end 0254 0255 @return An iterator to one past the last element 0256 */ 0257 iterator end() const noexcept; 0258 0259 /** Return true if the range is empty 0260 0261 @return `true` if the range is empty 0262 */ 0263 bool 0264 empty() const noexcept 0265 { 0266 return n_ == 0; 0267 } 0268 0269 /** Return the number of elements in the range 0270 0271 @return The number of elements 0272 */ 0273 std::size_t 0274 size() const noexcept 0275 { 0276 return n_; 0277 } 0278 0279 /** Return the matching part of the string 0280 0281 @return A string view representing the range 0282 */ 0283 core::string_view 0284 string() const noexcept 0285 { 0286 return s_; 0287 } 0288 }; 0289 0290 //------------------------------------------------ 0291 0292 namespace implementation_defined { 0293 template< 0294 class R0, 0295 class R1 = void> 0296 struct range_rule_t; 0297 } 0298 0299 //------------------------------------------------ 0300 0301 namespace implementation_defined { 0302 template<class R> 0303 struct range_rule_t<R> 0304 { 0305 using value_type = 0306 range<typename R::value_type>; 0307 0308 system::result<value_type> 0309 parse( 0310 char const*& it, 0311 char const* end) const; 0312 0313 constexpr 0314 range_rule_t( 0315 R const& next, 0316 std::size_t N, 0317 std::size_t M) noexcept 0318 : next_(next) 0319 , N_(N) 0320 , M_(M) 0321 { 0322 } 0323 0324 private: 0325 R const next_; 0326 std::size_t N_; 0327 std::size_t M_; 0328 }; 0329 } // implementation_defined 0330 0331 /** Match a repeating number of elements 0332 0333 Elements are matched using the passed rule. 0334 <br> 0335 Normally when the rule returns an error, 0336 the range ends and the input is rewound to 0337 one past the last character that matched 0338 successfully. However, if the rule returns 0339 the special value @ref error::end_of_range, the 0340 input is not rewound. This allows for rules 0341 which consume input without producing 0342 elements in the range. For example, to 0343 relax the grammar for a comma-delimited 0344 list by allowing extra commas in between 0345 elements. 0346 0347 @par Value Type 0348 @code 0349 using value_type = range< typename Rule::value_type >; 0350 @endcode 0351 0352 @par Example 0353 Rules are used with the function @ref parse. 0354 @code 0355 // range = 1*( ";" token ) 0356 0357 system::result< range<core::string_view> > rv = parse( ";alpha;xray;charlie", 0358 range_rule( 0359 tuple_rule( 0360 squelch( delim_rule( ';' ) ), 0361 token_rule( alpha_chars ) ), 0362 1 ) ); 0363 @endcode 0364 0365 @par BNF 0366 @code 0367 range = <N>*<M>next 0368 @endcode 0369 0370 @par Specification 0371 @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.6" 0372 >3.6. Variable Repetition (rfc5234)</a> 0373 0374 @param next The rule to use for matching 0375 each element. The range extends until this 0376 rule returns an error. 0377 0378 @param N The minimum number of elements for 0379 the range to be valid. If omitted, this 0380 defaults to zero. 0381 0382 @param M The maximum number of elements for 0383 the range to be valid. If omitted, this 0384 defaults to unlimited. 0385 0386 @return A rule that matches the range. 0387 0388 @see 0389 @ref alpha_chars, 0390 @ref delim_rule, 0391 @ref error::end_of_range, 0392 @ref parse, 0393 @ref range, 0394 @ref tuple_rule, 0395 @ref squelch. 0396 */ 0397 template<BOOST_URL_CONSTRAINT(Rule) R> 0398 constexpr 0399 implementation_defined::range_rule_t<R> 0400 range_rule( 0401 R const& next, 0402 std::size_t N = 0, 0403 std::size_t M = 0404 std::size_t(-1)) noexcept 0405 { 0406 // If you get a compile error here it 0407 // means that your rule does not meet 0408 // the type requirements. Please check 0409 // the documentation. 0410 static_assert( 0411 is_rule<R>::value, 0412 "Rule requirements not met"); 0413 0414 return implementation_defined::range_rule_t<R>{ 0415 next, N, M}; 0416 } 0417 0418 //------------------------------------------------ 0419 0420 namespace implementation_defined { 0421 template<class R0, class R1> 0422 struct range_rule_t 0423 { 0424 using value_type = 0425 range<typename R0::value_type>; 0426 0427 system::result<value_type> 0428 parse( 0429 char const*& it, 0430 char const* end) const; 0431 0432 constexpr 0433 range_rule_t( 0434 R0 const& first, 0435 R1 const& next, 0436 std::size_t N, 0437 std::size_t M) noexcept 0438 : first_(first) 0439 , next_(next) 0440 , N_(N) 0441 , M_(M) 0442 { 0443 } 0444 0445 private: 0446 R0 const first_; 0447 R1 const next_; 0448 std::size_t N_; 0449 std::size_t M_; 0450 }; 0451 } // implementation_defined 0452 0453 /** Match a repeating number of elements 0454 0455 Two rules are used for match. The rule 0456 `first` is used for matching the first 0457 element, while the `next` rule is used 0458 to match every subsequent element. 0459 <br> 0460 Normally when the rule returns an error, 0461 the range ends and the input is rewound to 0462 one past the last character that matched 0463 successfully. However, if the rule returns 0464 the special value @ref error::end_of_range, the 0465 input is not rewound. This allows for rules 0466 which consume input without producing 0467 elements in the range. For example, to 0468 relax the grammar for a comma-delimited 0469 list by allowing extra commas in between 0470 elements. 0471 0472 @par Value Type 0473 @code 0474 using value_type = range< typename Rule::value_type >; 0475 @endcode 0476 0477 @par Example 0478 Rules are used with the function @ref parse. 0479 @code 0480 // range = [ token ] *( "," token ) 0481 0482 system::result< range< core::string_view > > rv = parse( "whiskey,tango,foxtrot", 0483 range_rule( 0484 token_rule( alpha_chars ), // first 0485 tuple_rule( // next 0486 squelch( delim_rule(',') ), 0487 token_rule( alpha_chars ) ) ) ); 0488 @endcode 0489 0490 @par BNF 0491 @code 0492 range = <1>*<1>first 0493 / first <N-1>*<M-1>next 0494 @endcode 0495 0496 @par Specification 0497 @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.6" 0498 >3.6. Variable Repetition (rfc5234)</a> 0499 0500 @param first The rule to use for matching 0501 the first element. If this rule returns 0502 an error, the range is empty. 0503 0504 @param next The rule to use for matching 0505 each subsequent element. The range extends 0506 until this rule returns an error. 0507 0508 @param N The minimum number of elements for 0509 the range to be valid. If omitted, this 0510 defaults to zero. 0511 0512 @param M The maximum number of elements for 0513 the range to be valid. If omitted, this 0514 defaults to unlimited. 0515 0516 @return A rule that matches the range. 0517 0518 @see 0519 @ref alpha_chars, 0520 @ref delim_rule, 0521 @ref error::end_of_range, 0522 @ref parse, 0523 @ref range, 0524 @ref tuple_rule, 0525 @ref squelch. 0526 */ 0527 template< 0528 BOOST_URL_CONSTRAINT(Rule) R1, 0529 BOOST_URL_CONSTRAINT(Rule) R2> 0530 constexpr 0531 auto 0532 range_rule( 0533 R1 const& first, 0534 R2 const& next, 0535 std::size_t N = 0, 0536 std::size_t M = 0537 std::size_t(-1)) noexcept -> 0538 #if 1 0539 typename std::enable_if< 0540 ! std::is_integral<R2>::value, 0541 implementation_defined::range_rule_t<R1, R2>>::type 0542 #else 0543 range_rule_t<R1, R2> 0544 #endif 0545 { 0546 // If you get a compile error here it 0547 // means that your rule does not meet 0548 // the type requirements. Please check 0549 // the documentation. 0550 static_assert( 0551 is_rule<R1>::value, 0552 "Rule requirements not met"); 0553 static_assert( 0554 is_rule<R2>::value, 0555 "Rule requirements not met"); 0556 0557 // If you get a compile error here it 0558 // means that your rules do not have 0559 // the exact same value_type. Please 0560 // check the documentation. 0561 static_assert( 0562 std::is_same< 0563 typename R1::value_type, 0564 typename R2::value_type>::value, 0565 "Rule requirements not met"); 0566 0567 return implementation_defined::range_rule_t<R1, R2>{ 0568 first, next, N, M}; 0569 } 0570 0571 } // grammar 0572 } // urls 0573 } // boost 0574 0575 #include <boost/url/grammar/impl/range_rule.hpp> 0576 0577 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |