LCOV - code coverage report
Current view: top level - boost/url/grammar/impl/range_rule.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 99.3 % 269 267
Test Date: 2025-11-10 19:06:20 Functions: 80.8 % 167 135

            Line data    Source code
       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              : 
      10              : #ifndef BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
      11              : #define BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
      12              : 
      13              : #include <boost/url/detail/except.hpp>
      14              : #include <boost/url/grammar/error.hpp>
      15              : #include <boost/url/grammar/recycled.hpp>
      16              : #include <boost/core/empty_value.hpp>
      17              : #include <boost/assert.hpp>
      18              : #include <boost/core/detail/static_assert.hpp>
      19              : #include <exception>
      20              : #include <iterator>
      21              : #include <new>
      22              : #include <utility>
      23              : #include <type_traits>
      24              : 
      25              : #include <stddef.h> // ::max_align_t
      26              : 
      27              : namespace boost {
      28              : namespace urls {
      29              : namespace grammar {
      30              : 
      31              : //------------------------------------------------
      32              : //
      33              : // any_rule
      34              : //
      35              : //------------------------------------------------
      36              : 
      37              : template<class T>
      38              : struct any_rule<T>::impl_base
      39              : {
      40              :     virtual
      41         1068 :     ~impl_base() = default;
      42              : 
      43              :     virtual
      44              :     void
      45            1 :     move(void* dest) noexcept
      46              :     {
      47            2 :         ::new(dest) impl_base(
      48            1 :             std::move(*this));
      49            1 :     }
      50              : 
      51              :     virtual
      52              :     void
      53            1 :     copy(void* dest) const noexcept
      54              :     {
      55            1 :         ::new(dest) impl_base(*this);
      56            1 :     }
      57              : 
      58              :     virtual
      59              :     system::result<T>
      60            1 :     first(
      61              :         char const*&,
      62              :         char const*) const noexcept
      63              :     {
      64            1 :         return system::error_code{};
      65              :     }
      66              : 
      67              :     virtual
      68              :     system::result<T>
      69            1 :     next(
      70              :         char const*&,
      71              :         char const*) const noexcept
      72              :     {
      73            1 :         return system::error_code{};
      74              :     }
      75              : };
      76              : 
      77              : //------------------------------------------------
      78              : 
      79              : // small
      80              : template<class T>
      81              : template<class R, bool Small>
      82              : struct any_rule<T>::impl1
      83              :     : impl_base
      84              :     , private empty_value<R>
      85              : {
      86              :     explicit
      87           25 :     impl1(R const& next) noexcept
      88              :         : empty_value<R>(
      89              :             empty_init,
      90           25 :             next)
      91              :     {
      92           25 :     }
      93              : 
      94              : private:
      95           71 :     impl1(impl1&&) noexcept = default;
      96            2 :     impl1(impl1 const&) noexcept = default;
      97              : 
      98              :     void
      99           71 :     move(void* dest
     100              :         ) noexcept override
     101              :     {
     102          142 :         ::new(dest) impl1(
     103           71 :             std::move(*this));
     104           71 :     }
     105              : 
     106              :     void
     107            2 :     copy(void* dest
     108              :         ) const noexcept override
     109              :     {
     110            2 :         ::new(dest) impl1(*this);
     111            2 :     }
     112              : 
     113              :     system::result<T>
     114            5 :     first(
     115              :         char const*& it,
     116              :         char const* end)
     117              :             const noexcept override
     118              :     {
     119            5 :         return grammar::parse(
     120            5 :             it, end, this->get());
     121              :     }
     122              : 
     123              :     system::result<T>
     124            8 :     next(
     125              :         char const*& it,
     126              :         char const* end)
     127              :             const noexcept override
     128              :     {
     129            8 :         return grammar::parse(
     130            8 :             it, end, this->get());
     131              :     }
     132              : };
     133              : 
     134              : //------------------------------------------------
     135              : 
     136              : // big
     137              : template<class T>
     138              : template<class R>
     139              : struct any_rule<T>::impl1<R, false>
     140              :     : impl_base
     141              : {
     142              :     explicit
     143            5 :     impl1(R const& next) noexcept
     144            5 :     {
     145            5 :         ::new(p_->addr()) impl{next};
     146            5 :     }
     147              : 
     148              : private:
     149              :     struct impl
     150              :     {
     151              :         R r;
     152              :     };
     153              : 
     154              :     recycled_ptr<
     155              :         aligned_storage<impl>> p_;
     156              : 
     157           14 :     impl1(impl1&&) noexcept = default;
     158            2 :     impl1(impl1 const&) noexcept = default;
     159              : 
     160              :     impl const&
     161           14 :     get() const noexcept
     162              :     {
     163              :         return *reinterpret_cast<
     164           14 :             impl const*>(p_->addr());
     165              :     }
     166              : 
     167           21 :     ~impl1()
     168              :     {
     169           21 :         if(p_)
     170            7 :             get().~impl();
     171           42 :     }
     172              : 
     173              :     void
     174           14 :     move(void* dest
     175              :         ) noexcept override
     176              :     {
     177           28 :         ::new(dest) impl1(
     178           14 :             std::move(*this));
     179           14 :     }
     180              : 
     181              :     void
     182            2 :     copy(void* dest
     183              :         ) const noexcept override
     184              :     {
     185            2 :         ::new(dest) impl1(*this);
     186            2 :     }
     187              : 
     188              :     system::result<T>
     189            2 :     first(
     190              :         char const*& it,
     191              :         char const* end)
     192              :             const noexcept override
     193              :     {
     194            2 :         return grammar::parse(
     195            2 :             it, end, this->get().r);
     196              :     }
     197              : 
     198              :     system::result<T>
     199            5 :     next(
     200              :         char const*& it,
     201              :         char const* end)
     202              :             const noexcept override
     203              :     {
     204            5 :         return grammar::parse(
     205            5 :             it, end, this->get().r);
     206              :     }
     207              : };
     208              : 
     209              : //------------------------------------------------
     210              : 
     211              : // small
     212              : template<class T>
     213              : template<
     214              :     class R0, class R1, bool Small>
     215              : struct any_rule<T>::impl2
     216              :     : impl_base
     217              :     , private empty_value<R0, 0>
     218              :     , private empty_value<R1, 1>
     219              : {
     220          119 :     impl2(
     221              :         R0 const& first,
     222              :         R1 const& next) noexcept
     223              :         : empty_value<R0,0>(
     224              :             empty_init, first)
     225              :         , empty_value<R1,1>(
     226          119 :             empty_init, next)
     227              :     {
     228          119 :     }
     229              : 
     230              : private:
     231          582 :     impl2(impl2&&) noexcept = default;
     232          225 :     impl2(impl2 const&) noexcept = default;
     233              : 
     234              :     void
     235          582 :     move(void* dest
     236              :         ) noexcept override
     237              :     {
     238         1164 :         ::new(dest) impl2(
     239          582 :             std::move(*this));
     240          582 :     }
     241              : 
     242              :     void
     243          225 :     copy(void* dest
     244              :         ) const noexcept override
     245              :     {
     246          225 :         ::new(dest) impl2(*this);
     247          225 :     }
     248              : 
     249              :     system::result<T>
     250          117 :     first(
     251              :         char const*& it,
     252              :         char const* end)
     253              :             const noexcept override
     254              :     {
     255            5 :         return grammar::parse(it, end,
     256              :             empty_value<
     257          117 :                 R0,0>::get());
     258              :     }
     259              : 
     260              :     system::result<T>
     261          335 :     next(
     262              :         char const*& it,
     263              :         char const* end)
     264              :             const noexcept override
     265              :     {
     266            9 :         return grammar::parse(it, end,
     267              :             empty_value<
     268          335 :                 R1,1>::get());
     269              :     }
     270              : };
     271              : 
     272              : //------------------------------------------------
     273              : 
     274              : // big
     275              : template<class T>
     276              : template<
     277              :     class R0, class R1>
     278              : struct any_rule<T>::impl2<R0, R1, false>
     279              :     : impl_base
     280              : {
     281            4 :     impl2(
     282              :         R0 const& first,
     283              :         R1 const& next) noexcept
     284            4 :     {
     285            4 :         ::new(p_->addr()) impl{
     286              :             first, next};
     287            4 :     }
     288              : 
     289              : private:
     290              :     struct impl
     291              :     {
     292              :         R0 first;
     293              :         R1 next;
     294              :     };
     295              : 
     296              :     recycled_ptr<
     297              :         aligned_storage<impl>> p_;
     298              : 
     299           14 :     impl2(impl2&&) noexcept = default;
     300            2 :     impl2(impl2 const&) noexcept = default;
     301              : 
     302              :     impl const&
     303           13 :     get() const noexcept
     304              :     {
     305              :         return *reinterpret_cast<
     306           13 :             impl const*>(p_->addr());
     307              :     }
     308              : 
     309           20 :     ~impl2()
     310              :     {
     311           20 :         if(p_)
     312            6 :             get().~impl();
     313           40 :     }
     314              : 
     315              :     void
     316           14 :     move(void* dest
     317              :         ) noexcept override
     318              :     {
     319           28 :         ::new(dest) impl2(
     320           14 :             std::move(*this));
     321           14 :     }
     322              : 
     323              :     void
     324            2 :     copy(void* dest
     325              :         ) const noexcept override
     326              :     {
     327            2 :         ::new(dest) impl2(*this);
     328            2 :     }
     329              : 
     330              :     system::result<T>
     331            2 :     first(
     332              :         char const*& it,
     333              :         char const* end)
     334              :             const noexcept override
     335              :     {
     336            2 :         return grammar::parse(
     337            2 :             it, end, get().first);
     338              :     }
     339              : 
     340              :     system::result<T>
     341            5 :     next(
     342              :         char const*& it,
     343              :         char const* end)
     344              :             const noexcept override
     345              :     {
     346            5 :         return grammar::parse(
     347            5 :             it, end, get().next);
     348              :     }
     349              : };
     350              : 
     351              : //------------------------------------------------
     352              : 
     353              : template<class T>
     354              : typename any_rule<T>::impl_base&
     355         1752 : any_rule<T>::
     356              : get() noexcept
     357              : {
     358              :     return *reinterpret_cast<
     359         1752 :         impl_base*>(sb_.addr());
     360              : }
     361              : 
     362              : template<class T>
     363              : typename any_rule<T>::impl_base const&
     364          711 : any_rule<T>::
     365              : get() const noexcept
     366              : {
     367              :     return *reinterpret_cast<
     368          711 :         impl_base const*>(sb_.addr());
     369              : }
     370              : 
     371              : 
     372              : template<class T>
     373            1 : any_rule<T>::
     374              : any_rule() noexcept
     375              : {
     376            1 :     ::new(sb_.addr()) impl_base{};
     377            1 :     char const* it = nullptr;
     378            1 :     get().first(it, nullptr);
     379            1 :     get().next(it, nullptr);
     380            1 : }
     381              : 
     382              : 
     383              : template<class T>
     384          681 : any_rule<T>::
     385              : any_rule(any_rule&& other) noexcept
     386              : {
     387          681 :     other.get().move(sb_.addr());
     388          681 : }
     389              : 
     390              : 
     391              : template<class T>
     392          229 : any_rule<T>::
     393              : any_rule(any_rule const& other) noexcept
     394              : {
     395          229 :     other.get().copy(sb_.addr());
     396          229 : }
     397              : 
     398              : 
     399              : template<class T>
     400              : any_rule<T>&
     401            1 : any_rule<T>::
     402              : operator=(any_rule&& other) noexcept
     403              : {
     404            1 :     if(this == &other)
     405            0 :         return *this;
     406            1 :     get().~impl_base();
     407            1 :     other.get().move(sb_.addr());
     408            1 :     return *this;
     409              : }
     410              : 
     411              : 
     412              : template<class T>
     413              : any_rule<T>&
     414            4 : any_rule<T>::
     415              : operator=(any_rule const& other) noexcept
     416              : {
     417            4 :     if(this == &other)
     418            1 :         return *this;
     419            3 :     get().~impl_base();
     420            3 :     other.get().copy(sb_.addr());
     421            3 :     return *this;
     422              : }
     423              : 
     424              : 
     425              : template<class T>
     426         1064 : any_rule<T>::
     427              : ~any_rule()
     428              : {
     429         1064 :     get().~impl_base();
     430         1064 : }
     431              : 
     432              : 
     433              : template<class T>
     434              : template<class R>
     435           30 : any_rule<T>::
     436              : any_rule(
     437              :     R const& next)
     438              : {
     439              :     static_assert(
     440              :         ::boost::urls::grammar::is_rule<R>::value,
     441              :         "Rule requirements not met");
     442              :     static_assert(
     443              :         std::is_same<typename R::value_type, T>::value,
     444              :         "Rule value_type mismatch");
     445              : 
     446              :     BOOST_CORE_STATIC_ASSERT(
     447              :         sizeof(impl1<R, false>) <=
     448              :             BufferSize);
     449              : 
     450           30 :     ::new(sb_.addr()) impl1<R,
     451              :         sizeof(impl1<R, true>) <=
     452              :             BufferSize>(next);
     453           30 : }
     454              : 
     455              : //------------------------------------------------
     456              : 
     457              : template<class T>
     458              : template<
     459              :     class R0, class R1>
     460          123 : any_rule<T>::
     461              : any_rule(
     462              :     R0 const& first,
     463              :     R1 const& next)
     464              : {
     465              :     static_assert(
     466              :         ::boost::urls::grammar::is_rule<R0>::value,
     467              :         "Rule requirements not met");
     468              :     static_assert(
     469              :         ::boost::urls::grammar::is_rule<R1>::value,
     470              :         "Rule requirements not met");
     471              :     static_assert(
     472              :         std::is_same<typename R0::value_type, T>::value,
     473              :         "First rule value_type mismatch");
     474              :     static_assert(
     475              :         std::is_same<typename R1::value_type, T>::value,
     476              :         "Next rule value_type mismatch");
     477              : 
     478              :     BOOST_CORE_STATIC_ASSERT(
     479              :         sizeof(impl2<R0, R1, false>) <=
     480              :             BufferSize);
     481              : 
     482          123 :     ::new(sb_.addr()) impl2<R0, R1,
     483              :         sizeof(impl2<R0, R1, true>
     484              :             ) <= BufferSize>(
     485              :                 first, next);
     486          123 : }
     487              : 
     488              : //------------------------------------------------
     489              : 
     490              : template<class T>
     491              : system::result<T>
     492          126 : any_rule<T>::
     493              : first(
     494              :     char const*& it,
     495              :     char const* end) const noexcept
     496              : {
     497          126 :     return get().first(it, end);
     498              : }
     499              : 
     500              : //------------------------------------------------
     501              : 
     502              : template<class T>
     503              : system::result<T>
     504          353 : any_rule<T>::
     505              : next(
     506              :     char const*& it,
     507              :     char const* end) const noexcept
     508              : {
     509          353 :     return get().next(it, end);
     510              : }
     511              : 
     512              : //------------------------------------------------
     513              : //
     514              : // range
     515              : //
     516              : //------------------------------------------------
     517              : 
     518              : template<class T, class RangeRule>
     519          911 : range<T, RangeRule>::
     520              : ~range() = default;
     521              : 
     522              : template<class T, class RangeRule>
     523            1 : range<T, RangeRule>::
     524              : range() noexcept = default;
     525              : 
     526              : template<class T, class RangeRule>
     527          529 : range<T, RangeRule>::
     528              : range(
     529              :     range&& other) noexcept
     530              :     : detail::range_base_storage<
     531          529 :         RangeRule>(std::move(other.rule()))
     532          529 :     , s_(other.s_)
     533         1058 :     , n_(other.n_)
     534              : {
     535          529 :     other.s_ = {};
     536          529 :     other.n_ = 0;
     537          529 : }
     538              : 
     539              : template<class T, class RangeRule>
     540          229 : range<T, RangeRule>::
     541              : range(
     542              :     range const& other) noexcept
     543              :     : detail::range_base_storage<
     544              :         RangeRule>(other.rule())
     545          229 :     , s_(other.s_)
     546          229 :     , n_(other.n_)
     547              : {
     548          229 : }
     549              : 
     550              : template<class T, class RangeRule>
     551              : auto
     552            1 : range<T, RangeRule>::
     553              : operator=(range&& other) noexcept
     554              :     -> range&
     555              : {
     556            1 :     if(this == &other)
     557            0 :         return *this;
     558              :     static_cast<
     559              :         detail::range_base_storage<
     560            1 :             RangeRule>&>(*this) =
     561            1 :         std::move(static_cast<
     562              :             detail::range_base_storage<
     563              :                 RangeRule>&>(other));
     564            1 :     s_ = other.s_;
     565            1 :     n_ = other.n_;
     566            1 :     other.s_ = {};
     567            1 :     other.n_ = 0;
     568            1 :     return *this;
     569              : }
     570              : 
     571              : template<class T, class RangeRule>
     572              : auto
     573            4 : range<T, RangeRule>::
     574              : operator=(range const& other) noexcept
     575              :     -> range&
     576              : {
     577            4 :     if(this == &other)
     578            1 :         return *this;
     579              :     static_cast<
     580              :         detail::range_base_storage<
     581            3 :             RangeRule>&>(*this) =
     582              :         static_cast<
     583              :             detail::range_base_storage<
     584              :                 RangeRule> const&>(other);
     585            3 :     s_ = other.s_;
     586            3 :     n_ = other.n_;
     587            3 :     return *this;
     588              : }
     589              : 
     590              : //------------------------------------------------
     591              : //
     592              : // iterator
     593              : //
     594              : //------------------------------------------------
     595              : 
     596              : template<class T, class RangeRule>
     597              : class range<T, RangeRule>::
     598              :     iterator
     599              : {
     600              : public:
     601              :     using value_type = T;
     602              :     using reference = T const&;
     603              :     using pointer = void const*;
     604              :     using difference_type =
     605              :         std::ptrdiff_t;
     606              :     using iterator_category =
     607              :         std::forward_iterator_tag;
     608              : 
     609              :     iterator() = default;
     610              :     iterator(
     611              :         iterator const&) = default;
     612              :     iterator& operator=(
     613              :         iterator const&) = default;
     614              : 
     615              :     reference
     616          734 :     operator*() const noexcept
     617              :     {
     618          734 :         return *rv_;
     619              :     }
     620              : 
     621              :     bool
     622          479 :     operator==(
     623              :         iterator const& other) const noexcept
     624              :     {
     625              :         // can't compare iterators
     626              :         // from different containers!
     627          479 :         BOOST_ASSERT(r_ == other.r_);
     628              : 
     629          479 :         return p_ == other.p_;
     630              :     }
     631              : 
     632              :     bool
     633          477 :     operator!=(
     634              :         iterator const& other) const noexcept
     635              :     {
     636          477 :         return !(*this == other);
     637              :     }
     638              : 
     639              :     iterator&
     640          353 :     operator++() noexcept
     641              :     {
     642          353 :         BOOST_ASSERT(
     643              :             p_ != nullptr);
     644          353 :         auto const end =
     645          353 :             r_->s_.data() +
     646          353 :             r_->s_.size();
     647          353 :         rv_ = r_->rule().next(p_, end);
     648          353 :         if( !rv_ )
     649          123 :             p_ = nullptr;
     650          353 :         return *this;
     651              :     }
     652              : 
     653              :     iterator
     654              :     operator++(int) noexcept
     655              :     {
     656              :         auto tmp = *this;
     657              :         ++*this;
     658              :         return tmp;
     659              :     }
     660              : 
     661              : private:
     662              :     friend class range<T, RangeRule>;
     663              : 
     664              :     range<T, RangeRule> const* r_ = nullptr;
     665              :     char const* p_ = nullptr;
     666              :     system::result<T> rv_;
     667              : 
     668          126 :     iterator(
     669              :         range<T, RangeRule> const& r) noexcept
     670          126 :         : r_(&r)
     671          126 :         , p_(r.s_.data())
     672              :     {
     673          126 :         auto const end =
     674          126 :             r_->s_.data() +
     675          126 :             r_->s_.size();
     676          126 :         rv_ = r_->rule().first(p_, end);
     677          126 :         if( !rv_ )
     678            3 :             p_ = nullptr;
     679          126 :     }
     680              : 
     681              :     constexpr
     682          126 :     iterator(
     683              :         range<T, RangeRule> const& r,
     684              :         int) noexcept
     685          126 :         : r_(&r)
     686          126 :         , p_(nullptr)
     687              :     {
     688          126 :     }
     689              : };
     690              : 
     691              : //------------------------------------------------
     692              : 
     693              : template<class T, class RangeRule>
     694              : typename range<T, RangeRule>::iterator
     695          126 : range<T, RangeRule>::
     696              : begin() const noexcept
     697              : {
     698          126 :     return iterator(*this);
     699              : }
     700              : 
     701              : //------------------------------------------------
     702              : 
     703              : template<class T, class RangeRule>
     704              : typename range<T, RangeRule>::iterator
     705          126 : range<T, RangeRule>::
     706              : end() const noexcept
     707              : {
     708          126 :     return iterator(*this, 0);
     709              : }
     710              : 
     711              : //------------------------------------------------
     712              : 
     713              : template<class T, class RangeRule>
     714              : range<T, RangeRule>::
     715              : range(
     716              :     core::string_view s,
     717              :     std::size_t n,
     718              :     RangeRule const& rule) noexcept
     719              :     : detail::range_base_storage<
     720              :         RangeRule>(rule)
     721              :     , s_(s)
     722              :     , n_(n)
     723              : {
     724              : }
     725              : 
     726              : //------------------------------------------------
     727              : 
     728              : template<class T, class RangeRule>
     729          152 : range<T, RangeRule>::
     730              : range(
     731              :     core::string_view s,
     732              :     std::size_t n,
     733              :     RangeRule&& rule) noexcept
     734              :     : detail::range_base_storage<
     735          152 :         RangeRule>(std::move(rule))
     736          152 :     , s_(s)
     737          152 :     , n_(n)
     738              : {
     739          152 : }
     740              : 
     741              : //------------------------------------------------
     742              : 
     743              : template<class R>
     744              : auto
     745           41 : implementation_defined::range_rule_t<R>::
     746              : parse(
     747              :     char const*& it,
     748              :     char const* end) const ->
     749              :         system::result<value_type>
     750              : {
     751              :     using T = typename R::value_type;
     752              : 
     753           41 :     std::size_t n = 0;
     754           41 :     auto const it0 = it;
     755           41 :     auto it1 = it;
     756           41 :     auto rv = (grammar::parse)(
     757           41 :         it, end, next_);
     758           41 :     if( !rv )
     759              :     {
     760            7 :         if(rv.error() != error::end_of_range)
     761              :         {
     762              :             // rewind unless error::end_of_range
     763            7 :             it = it1;
     764              :         }
     765            7 :         if(n < N_)
     766              :         {
     767              :             // too few
     768            6 :             BOOST_URL_RETURN_EC(
     769              :                 error::mismatch);
     770              :         }
     771              :         // good
     772            2 :         return range<T>(
     773            1 :             core::string_view(it0, it - it0),
     774            3 :                 n, any_rule<T>(next_));
     775              :     }
     776           34 :     for(;;)
     777              :     {
     778           68 :         ++n;
     779           68 :         it1 = it;
     780           68 :         rv = (grammar::parse)(
     781           68 :             it, end, next_);
     782           68 :         if( !rv )
     783              :         {
     784           30 :             if(rv.error() != error::end_of_range)
     785              :             {
     786              :                 // rewind unless error::end_of_range
     787           30 :                 it = it1;
     788              :             }
     789           30 :             break;
     790              :         }
     791           38 :         if(n >= M_)
     792              :         {
     793              :             // too many
     794            4 :             BOOST_URL_RETURN_EC(
     795              :                 error::mismatch);
     796              :         }
     797              :     }
     798           30 :     if(n < N_)
     799              :     {
     800              :         // too few
     801            2 :         BOOST_URL_RETURN_EC(
     802              :             error::mismatch);
     803              :     }
     804              :     // good
     805           56 :     return range<T>(
     806           28 :         core::string_view(it0, it - it0),
     807           84 :             n, any_rule<T>(next_));
     808              : }
     809              : 
     810              : //------------------------------------------------
     811              : 
     812              : template<class R0, class R1>
     813              : auto
     814          131 : implementation_defined::range_rule_t<R0, R1>::
     815              : parse(
     816              :     char const*& it,
     817              :     char const* end) const ->
     818              :         system::result<range<typename
     819              :             R0::value_type>>
     820              : {
     821              :     using T = typename R0::value_type;
     822              : 
     823          131 :     std::size_t n = 0;
     824          131 :     auto const it0 = it;
     825          131 :     auto it1 = it;
     826          131 :     auto rv = (grammar::parse)(
     827          131 :         it, end, first_);
     828          131 :     if( !rv )
     829              :     {
     830            4 :         if(rv.error() != error::end_of_range)
     831              :         {
     832            4 :             it = it1;
     833              :         }
     834            4 :         if(n < N_)
     835              :         {
     836            3 :             BOOST_URL_RETURN_EC(
     837              :                 error::mismatch);
     838              :         }
     839            2 :         return range<T>(
     840            1 :             core::string_view(it0, it - it0),
     841            3 :                 n, any_rule<T>(first_, next_));
     842              :     }
     843          236 :     for(;;)
     844              :     {
     845          363 :         ++n;
     846          363 :         it1 = it;
     847          363 :         rv = (grammar::parse)(
     848          363 :             it, end, next_);
     849          363 :         if( !rv )
     850              :         {
     851          123 :             if(rv.error() != error::end_of_range)
     852              :             {
     853              :                 // rewind unless error::end_of_range
     854          123 :                 it = it1;
     855              :             }
     856          123 :             break;
     857              :         }
     858          240 :         if(n >= M_)
     859              :         {
     860              :             // too many
     861            4 :             BOOST_URL_RETURN_EC(
     862              :                 error::mismatch);
     863              :         }
     864              :     }
     865          123 :     if(n < N_)
     866              :     {
     867              :         // too few
     868            1 :         BOOST_URL_RETURN_EC(
     869              :             error::mismatch);
     870              :     }
     871              :     // good
     872          244 :     return range<T>(
     873          122 :         core::string_view(it0, it - it0),
     874          366 :             n, any_rule<T>(first_, next_));
     875          113 : }
     876              : 
     877              : } // grammar
     878              : } // urls
     879              : } // boost
     880              : 
     881              : #endif
        

Generated by: LCOV version 2.1