libs/http/include/boost/http/rfc/impl/list_rule.hpp

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