LCOV - code coverage report
Current view: top level - url/grammar/impl - range_rule.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 100.0 % 269 269
Test Date: 2026-02-25 21:00:01 Functions: 84.2 % 146 123 23

           TLA  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 HIT        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                 : BOOST_URL_CXX20_CONSTEXPR
     746                 : auto
     747              25 : implementation_defined::range_rule_t<R>::
     748                 : parse(
     749                 :     char const*& it,
     750                 :     char const* end) const ->
     751                 :         system::result<value_type>
     752                 : {
     753                 :     using T = typename R::value_type;
     754                 : 
     755              25 :     std::size_t n = 0;
     756              25 :     auto const it0 = it;
     757              25 :     auto it1 = it;
     758              25 :     auto rv = (grammar::parse)(
     759              25 :         it, end, next_);
     760              25 :     if( !rv )
     761                 :     {
     762               3 :         if(rv.error() != error::end_of_range)
     763                 :         {
     764                 :             // rewind unless error::end_of_range
     765               3 :             it = it1;
     766                 :         }
     767               3 :         if(n < N_)
     768                 :         {
     769                 :             // too few
     770               2 :             BOOST_URL_CONSTEXPR_RETURN_EC(
     771                 :                 error::mismatch);
     772                 :         }
     773                 :         // good
     774               2 :         return range<T>(
     775               1 :             core::string_view(it0, it - it0),
     776               3 :                 n, any_rule<T>(next_));
     777                 :     }
     778              31 :     for(;;)
     779                 :     {
     780              53 :         ++n;
     781              53 :         it1 = it;
     782              53 :         rv = (grammar::parse)(
     783              53 :             it, end, next_);
     784              53 :         if( !rv )
     785                 :         {
     786              18 :             if(rv.error() != error::end_of_range)
     787                 :             {
     788                 :                 // rewind unless error::end_of_range
     789              18 :                 it = it1;
     790                 :             }
     791              18 :             break;
     792                 :         }
     793              35 :         if(n >= M_)
     794                 :         {
     795                 :             // too many
     796               4 :             BOOST_URL_CONSTEXPR_RETURN_EC(
     797                 :                 error::mismatch);
     798                 :         }
     799                 :     }
     800              18 :     if(n < N_)
     801                 :     {
     802                 :         // too few
     803               2 :         BOOST_URL_CONSTEXPR_RETURN_EC(
     804                 :             error::mismatch);
     805                 :     }
     806                 :     // good
     807              32 :     return range<T>(
     808              16 :         core::string_view(it0, it - it0),
     809              48 :             n, any_rule<T>(next_));
     810                 : }
     811                 : 
     812                 : //------------------------------------------------
     813                 : 
     814                 : template<class R0, class R1>
     815                 : BOOST_URL_CXX20_CONSTEXPR
     816                 : auto
     817             131 : implementation_defined::range_rule_t<R0, R1>::
     818                 : parse(
     819                 :     char const*& it,
     820                 :     char const* end) const ->
     821                 :         system::result<range<typename
     822                 :             R0::value_type>>
     823                 : {
     824                 :     using T = typename R0::value_type;
     825                 : 
     826             131 :     std::size_t n = 0;
     827             131 :     auto const it0 = it;
     828             131 :     auto it1 = it;
     829             131 :     auto rv = (grammar::parse)(
     830             131 :         it, end, first_);
     831             131 :     if( !rv )
     832                 :     {
     833               4 :         if(rv.error() != error::end_of_range)
     834                 :         {
     835               4 :             it = it1;
     836                 :         }
     837               4 :         if(n < N_)
     838                 :         {
     839               3 :             BOOST_URL_CONSTEXPR_RETURN_EC(
     840                 :                 error::mismatch);
     841                 :         }
     842               2 :         return range<T>(
     843               1 :             core::string_view(it0, it - it0),
     844               3 :                 n, any_rule<T>(first_, next_));
     845                 :     }
     846             236 :     for(;;)
     847                 :     {
     848             363 :         ++n;
     849             363 :         it1 = it;
     850             363 :         rv = (grammar::parse)(
     851             363 :             it, end, next_);
     852             363 :         if( !rv )
     853                 :         {
     854             123 :             if(rv.error() != error::end_of_range)
     855                 :             {
     856                 :                 // rewind unless error::end_of_range
     857             123 :                 it = it1;
     858                 :             }
     859             123 :             break;
     860                 :         }
     861             240 :         if(n >= M_)
     862                 :         {
     863                 :             // too many
     864               4 :             BOOST_URL_CONSTEXPR_RETURN_EC(
     865                 :                 error::mismatch);
     866                 :         }
     867                 :     }
     868             123 :     if(n < N_)
     869                 :     {
     870                 :         // too few
     871               1 :         BOOST_URL_CONSTEXPR_RETURN_EC(
     872                 :             error::mismatch);
     873                 :     }
     874                 :     // good
     875             244 :     return range<T>(
     876             122 :         core::string_view(it0, it - it0),
     877             366 :             n, any_rule<T>(first_, next_));
     878             113 : }
     879                 : 
     880                 : } // grammar
     881                 : } // urls
     882                 : } // boost
     883                 : 
     884                 : #endif
        

Generated by: LCOV version 2.3