LCOV - code coverage report
Current view: top level - http_proto/rfc/impl - list_rule.hpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 54 54 100.0 %
Date: 2023-01-09 16:11:12 Functions: 16 16 100.0 %

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2021 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/CPPAlliance/http_proto
       8             : //
       9             : 
      10             : #ifndef BOOST_HTTP_PROTO_RFC_IMPL_LIST_RULE_HPP
      11             : #define BOOST_HTTP_PROTO_RFC_IMPL_LIST_RULE_HPP
      12             : 
      13             : #include <boost/url/grammar/parse.hpp>
      14             : #include <boost/url/grammar/range_rule.hpp>
      15             : #include <boost/core/empty_value.hpp>
      16             : #include <type_traits>
      17             : 
      18             : namespace boost {
      19             : namespace http_proto {
      20             : 
      21             : namespace detail {
      22             : 
      23             : /*  Peter:
      24             : 
      25             :     So, to put everything together, this is what I propose
      26             : 
      27             :     - make range2_rule that takes first and next with
      28             :       value types of optional<E> rather than E like the current rule
      29             :     - make variant_rule produce an optional<X> when otherwise
      30             :       the value type would have been variant<void, void, X, void>
      31             :     - add operators for combining the rules so that one can
      32             :       write *( OWS >> !literal(",") >> -( OWS >> element ) )
      33             :     - profit
      34             : */
      35             : 
      36             : // *( OWS "," )
      37             : struct ows_comma_t
      38             : {
      39             :     using value_type = void;
      40             : 
      41             :     auto
      42          99 :     parse(
      43             :         char const*& it,
      44             :         char const* end) const noexcept ->
      45             :             result<value_type>
      46             :     {
      47          99 :         auto it1 = it;
      48         247 :         while(it != end)
      49             :         {
      50             :             // SP / HT
      51         232 :             if( *it == ' ' ||
      52         176 :                 *it == '\t')
      53             :             {
      54          58 :                 ++it;
      55          58 :                 continue;
      56             :             }
      57         174 :             if(*it != ',')
      58          84 :                 break;
      59             :             // ","
      60          90 :             it1 = ++it;
      61             :         }
      62          99 :         it = it1;
      63          99 :         return {};
      64             :     }
      65             : };
      66             : 
      67             : constexpr ows_comma_t ows_comma{};
      68             : 
      69             : } // detail
      70             : 
      71             : /*
      72             :     #element    => [ ( "," / element ) *( OWS "," [ OWS element ] ) ]
      73             : 
      74             :     #element    => first *next
      75             :     first       => [ element / ( "," *( OWS "," ) [ OWS element ] ) ]
      76             :     next        => "" / ( 1*( OWS "," ) [ OWS element ] )
      77             : */
      78             : 
      79             : template<class Rule>
      80             : struct list_rule_t<Rule>::
      81             :     first_rule : empty_value<Rule>
      82             : {
      83             :     using value_type =
      84             :         typename Rule::value_type;
      85             : 
      86             :     constexpr
      87             :     explicit
      88         244 :     first_rule(
      89             :         Rule const& r) noexcept
      90             :         : empty_value<Rule>(
      91         244 :             empty_init, r)
      92             :     {
      93         244 :     }
      94             : 
      95             :     auto
      96         434 :     parse(
      97             :         char const*& it,
      98             :         char const* end) const ->
      99             :             result<value_type>
     100             :     {
     101             :     //  first       => [ element / ( "," *( OWS "," ) [ OWS element ] ) ]
     102             : 
     103         434 :         if(it == end)
     104           5 :             return grammar::error::end_of_range;
     105             :         {
     106             :             // element
     107         429 :             auto it0 = it;
     108         429 :             auto rv = this->get().parse(it, end);
     109         429 :             if(rv)
     110         402 :                 return std::move(*rv);
     111          27 :             it = it0;
     112             :         }
     113             :         // ","
     114          27 :         if(*it != ',')
     115          14 :             return grammar::error::end_of_range;
     116          13 :         ++it;
     117             :         // *( OWS "," )
     118          13 :         detail::ows_comma.parse(it, end);
     119          13 :         auto it1 = it;
     120             :         // OWS
     121          13 :         it = grammar::find_if_not(
     122             :             it, end, detail::ws);
     123             :         // element
     124          13 :         auto rv = this->get().parse(it, end);
     125          13 :         if(rv)
     126           6 :             return std::move(*rv);
     127           7 :         it = it1;
     128           7 :         return grammar::error::end_of_range;
     129             :     }
     130             : };
     131             : 
     132             : template<class Rule>
     133             : struct list_rule_t<Rule>::
     134             :     next_rule : empty_value<Rule>
     135             : {
     136             :     using value_type =
     137             :         typename Rule::value_type;
     138             : 
     139             :     constexpr
     140             :     explicit
     141         244 :     next_rule(
     142             :         Rule const& r) noexcept
     143             :         : empty_value<Rule>(
     144         244 :             empty_init, r)
     145             :     {
     146         244 :     }
     147             : 
     148             :     auto
     149         461 :     parse(
     150             :         char const*& it,
     151             :         char const* end) const ->
     152             :             result<value_type>
     153             :     {
     154             :     //  next        => "" / ( 1*( OWS "," ) [ OWS element ] )
     155             : 
     156             :         // ""
     157         461 :         if(it == end)
     158         375 :             return grammar::error::end_of_range;
     159             : 
     160             :         // 1*( OWS "," )
     161             :         {
     162          86 :             auto it0 = it;
     163          86 :             detail::ows_comma.parse(it, end);
     164          86 :             if(it == it0)
     165           7 :                 return grammar::error::end_of_range;
     166             :         }
     167          79 :         auto it1 = it;
     168             :         // OWS
     169          79 :         it = grammar::find_if_not(
     170             :             it, end, detail::ws);
     171         108 :         auto rv = this->get().parse(it, end);
     172          79 :         if(rv)
     173          70 :             return std::move(*rv);
     174           9 :         it = it1;
     175           9 :         return grammar::error::end_of_range;
     176             :     }
     177             : };
     178             : 
     179             : template<class Rule>
     180             : auto
     181         244 : list_rule_t<Rule>::
     182             : parse(
     183             :     char const*& it,
     184             :     char const* end) const ->
     185             :         result<value_type>
     186             : {
     187             :     return grammar::parse(it, end,
     188         488 :         grammar::range_rule(
     189             :             first_rule{this->get()},
     190             :             next_rule{this->get()},
     191         732 :                 n_, m_));
     192             : }
     193             : 
     194             : } // http_proto
     195             : } // boost
     196             : 
     197             : #endif

Generated by: LCOV version 1.15