Back to home page

EIC code displayed by LXR

 
 

    


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