98.25% Lines (56/57) 100.00% Functions (6/6)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 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) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/cppalliance/http 7   // Official repository: https://github.com/cppalliance/http
8   // 8   //
9   9  
10   #ifndef BOOST_HTTP_RFC_IMPL_LIST_RULE_HPP 10   #ifndef BOOST_HTTP_RFC_IMPL_LIST_RULE_HPP
11   #define BOOST_HTTP_RFC_IMPL_LIST_RULE_HPP 11   #define BOOST_HTTP_RFC_IMPL_LIST_RULE_HPP
12   12  
13   #include <boost/http/rfc/detail/ws.hpp> 13   #include <boost/http/rfc/detail/ws.hpp>
14   14  
15   #include <boost/url/grammar/parse.hpp> 15   #include <boost/url/grammar/parse.hpp>
16   #include <boost/url/grammar/charset.hpp> 16   #include <boost/url/grammar/charset.hpp>
17   #include <boost/url/grammar/range_rule.hpp> 17   #include <boost/url/grammar/range_rule.hpp>
18   #include <boost/core/empty_value.hpp> 18   #include <boost/core/empty_value.hpp>
19   19  
20   namespace boost { 20   namespace boost {
21   namespace http { 21   namespace http {
22   22  
23   namespace detail { 23   namespace detail {
24   24  
25   /* Peter: 25   /* Peter:
26   26  
27   So, to put everything together, this is what I propose 27   So, to put everything together, this is what I propose
28   28  
29   - make range2_rule that takes first and next with 29   - make range2_rule that takes first and next with
30   value types of optional<E> rather than E like the current rule 30   value types of optional<E> rather than E like the current rule
31   - make variant_rule produce an optional<X> when otherwise 31   - make variant_rule produce an optional<X> when otherwise
32   the value type would have been variant<void, void, X, void> 32   the value type would have been variant<void, void, X, void>
33   - add operators for combining the rules so that one can 33   - add operators for combining the rules so that one can
34   write *( OWS >> !literal(",") >> -( OWS >> element ) ) 34   write *( OWS >> !literal(",") >> -( OWS >> element ) )
35   - profit 35   - profit
36   */ 36   */
37   37  
38   // *( OWS "," ) 38   // *( OWS "," )
39   struct ows_comma_t 39   struct ows_comma_t
40   { 40   {
41   using value_type = void; 41   using value_type = void;
42   42  
43   auto 43   auto
HITCBC 44   98 parse( 44   98 parse(
45   char const*& it, 45   char const*& it,
46   char const* end) const noexcept -> 46   char const* end) const noexcept ->
47   system::result<value_type> 47   system::result<value_type>
48   { 48   {
HITCBC 49   98 auto it1 = it; 49   98 auto it1 = it;
HITCBC 50   246 while(it != end) 50   246 while(it != end)
51   { 51   {
52   // SP / HT 52   // SP / HT
HITCBC 53   231 if( *it == ' ' || 53   231 if( *it == ' ' ||
HITCBC 54   173 *it == '\t') 54   173 *it == '\t')
55   { 55   {
HITCBC 56   60 ++it; 56   60 ++it;
HITCBC 57   60 continue; 57   60 continue;
58   } 58   }
HITCBC 59   171 if(*it != ',') 59   171 if(*it != ',')
HITCBC 60   83 break; 60   83 break;
61   // "," 61   // ","
HITCBC 62   88 it1 = ++it; 62   88 it1 = ++it;
63   } 63   }
HITCBC 64   98 it = it1; 64   98 it = it1;
HITCBC 65   98 return {}; 65   98 return {};
66   } 66   }
67   }; 67   };
68   68  
69   constexpr ows_comma_t ows_comma{}; 69   constexpr ows_comma_t ows_comma{};
70   70  
71   } // detail 71   } // detail
72   72  
73   /* 73   /*
74   #element => [ ( "," / element ) *( OWS "," [ OWS element ] ) ] 74   #element => [ ( "," / element ) *( OWS "," [ OWS element ] ) ]
75   75  
76   #element => first *next 76   #element => first *next
77   first => [ element / ( "," *( OWS "," ) [ OWS element ] ) ] 77   first => [ element / ( "," *( OWS "," ) [ OWS element ] ) ]
78   next => "" / ( 1*( OWS "," ) [ OWS element ] ) 78   next => "" / ( 1*( OWS "," ) [ OWS element ] )
79   */ 79   */
80   80  
81   namespace implementation_defined { 81   namespace implementation_defined {
82   template<class Rule> 82   template<class Rule>
83   struct list_rule_t<Rule>:: 83   struct list_rule_t<Rule>::
84   first_rule : empty_value<Rule> 84   first_rule : empty_value<Rule>
85   { 85   {
86   using value_type = 86   using value_type =
87   typename Rule::value_type; 87   typename Rule::value_type;
88   88  
89   constexpr 89   constexpr
90   explicit 90   explicit
HITCBC 91   4657 first_rule( 91   4659 first_rule(
92   Rule const& r) noexcept 92   Rule const& r) noexcept
93   : empty_value<Rule>( 93   : empty_value<Rule>(
HITCBC 94   4657 empty_init, r) 94   4659 empty_init, r)
95   { 95   {
HITCBC 96   4657 } 96   4659 }
97   97  
98   auto 98   auto
HITCBC 99   9252 parse( 99   9256 parse(
100   char const*& it, 100   char const*& it,
101   char const* end) const -> 101   char const* end) const ->
102   system::result<value_type> 102   system::result<value_type>
103   { 103   {
104   // first => [ element / ( "," *( OWS "," ) [ OWS element ] ) ] 104   // first => [ element / ( "," *( OWS "," ) [ OWS element ] ) ]
105   105  
HITCBC 106   9252 if(it == end) 106   9256 if(it == end)
HITCBC 107   7 return grammar::error::end_of_range; 107   7 return grammar::error::end_of_range;
108   { 108   {
109   // element 109   // element
HITCBC 110   9245 auto it0 = it; 110   9249 auto it0 = it;
HITCBC 111   9245 auto rv = this->get().parse(it, end); 111   9249 auto rv = this->get().parse(it, end);
HITCBC 112   9245 if(rv) 112   9249 if(rv)
HITCBC 113   9217 return std::move(*rv); 113   9221 return std::move(*rv);
HITCBC 114   28 it = it0; 114   28 it = it0;
HITCBC 115   8852 } 115   8856 }
116   // "," 116   // ","
HITCBC 117   28 if(*it != ',') 117   28 if(*it != ',')
HITCBC 118   15 return grammar::error::end_of_range; 118   15 return grammar::error::end_of_range;
HITCBC 119   13 ++it; 119   13 ++it;
120   // *( OWS "," ) 120   // *( OWS "," )
HITCBC 121   13 detail::ows_comma.parse(it, end); 121   13 detail::ows_comma.parse(it, end);
HITCBC 122   13 auto it1 = it; 122   13 auto it1 = it;
123   // OWS 123   // OWS
HITCBC 124   13 it = grammar::find_if_not( 124   13 it = grammar::find_if_not(
125   it, end, detail::ws); 125   it, end, detail::ws);
126   // element 126   // element
HITCBC 127   13 auto rv = this->get().parse(it, end); 127   13 auto rv = this->get().parse(it, end);
HITCBC 128   13 if(rv) 128   13 if(rv)
HITCBC 129   6 return std::move(*rv); 129   6 return std::move(*rv);
HITCBC 130   7 it = it1; 130   7 it = it1;
HITCBC 131   7 return grammar::error::end_of_range; 131   7 return grammar::error::end_of_range;
MISUBC 132   } 132   }
133   }; 133   };
134   134  
135   template<class Rule> 135   template<class Rule>
136   struct list_rule_t<Rule>:: 136   struct list_rule_t<Rule>::
137   next_rule : empty_value<Rule> 137   next_rule : empty_value<Rule>
138   { 138   {
139   using value_type = 139   using value_type =
140   typename Rule::value_type; 140   typename Rule::value_type;
141   141  
142   constexpr 142   constexpr
143   explicit 143   explicit
HITCBC 144   4657 next_rule( 144   4659 next_rule(
145   Rule const& r) noexcept 145   Rule const& r) noexcept
146   : empty_value<Rule>( 146   : empty_value<Rule>(
HITCBC 147   4657 empty_init, r) 147   4659 empty_init, r)
148   { 148   {
HITCBC 149   4657 } 149   4659 }
150   150  
151   auto 151   auto
HITCBC 152   9270 parse( 152   9274 parse(
153   char const*& it, 153   char const*& it,
154   char const* end) const -> 154   char const* end) const ->
155   system::result<value_type> 155   system::result<value_type>
156   { 156   {
157   // next => "" / ( 1*( OWS "," ) [ OWS element ] ) 157   // next => "" / ( 1*( OWS "," ) [ OWS element ] )
158   158  
159   // "" 159   // ""
HITCBC 160   9270 if(it == end) 160   9274 if(it == end)
HITCBC 161   9185 return grammar::error::end_of_range; 161   9189 return grammar::error::end_of_range;
162   162  
163   // 1*( OWS "," ) 163   // 1*( OWS "," )
164   { 164   {
HITCBC 165   85 auto it0 = it; 165   85 auto it0 = it;
HITCBC 166   85 detail::ows_comma.parse(it, end); 166   85 detail::ows_comma.parse(it, end);
HITCBC 167   85 if(it == it0) 167   85 if(it == it0)
HITCBC 168   8 return grammar::error::end_of_range; 168   8 return grammar::error::end_of_range;
169   } 169   }
HITCBC 170   77 auto it1 = it; 170   77 auto it1 = it;
171   // OWS 171   // OWS
HITCBC 172   77 it = grammar::find_if_not( 172   77 it = grammar::find_if_not(
173   it, end, detail::ws); 173   it, end, detail::ws);
HITCBC 174   77 auto rv = this->get().parse(it, end); 174   77 auto rv = this->get().parse(it, end);
HITCBC 175   77 if(rv) 175   77 if(rv)
HITCBC 176   68 return std::move(*rv); 176   68 return std::move(*rv);
HITCBC 177   9 it = it1; 177   9 it = it1;
HITCBC 178   9 return grammar::error::end_of_range; 178   9 return grammar::error::end_of_range;
HITCBC 179   25 } 179   25 }
180   }; 180   };
181   181  
182   template<class Rule> 182   template<class Rule>
183   auto 183   auto
HITCBC 184   4657 list_rule_t<Rule>:: 184   4659 list_rule_t<Rule>::
185   parse( 185   parse(
186   char const*& it, 186   char const*& it,
187   char const* end) const -> 187   char const* end) const ->
188   system::result<value_type> 188   system::result<value_type>
189   { 189   {
190   return grammar::parse(it, end, 190   return grammar::parse(it, end,
HITCBC 191   9314 grammar::range_rule( 191   9318 grammar::range_rule(
192   first_rule{this->get()}, 192   first_rule{this->get()},
193   next_rule{this->get()}, 193   next_rule{this->get()},
HITCBC 194   13971 n_, m_)); 194   13977 n_, m_));
195   } 195   }
196   } // implementation_defined 196   } // implementation_defined
197   197  
198   } // http 198   } // http
199   } // boost 199   } // boost
200   200  
201   #endif 201   #endif