LCOV - code coverage report
Current view: top level - url/grammar/impl - range_rule.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 267 267
Test Date: 2026-02-13 15:53:22 Functions: 84.2 % 146 123

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

Generated by: LCOV version 2.3