GCC Code Coverage Report


Directory: libs/http_proto/
File: include/boost/http_proto/rfc/impl/list_rule.hpp
Date: 2025-09-21 18:08:15
Exec Total Coverage
Lines: 56 57 98.2%
Functions: 14 14 100.0%
Branches: 25 26 96.2%

Line Branch Exec Source
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_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/http_proto/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_proto {
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 81 parse(
45 char const*& it,
46 char const* end) const noexcept ->
47 system::result<value_type>
48 {
49 81 auto it1 = it;
50
2/2
✓ Branch 0 taken 191 times.
✓ Branch 1 taken 11 times.
202 while(it != end)
51 {
52 // SP / HT
53
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 48 times.
191 if( *it == ' ' ||
54
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 141 times.
143 *it == '\t')
55 {
56 50 ++it;
57 50 continue;
58 }
59
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 71 times.
141 if(*it != ',')
60 70 break;
61 // ","
62 71 it1 = ++it;
63 }
64 81 it = it1;
65 81 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 8808 first_rule(
92 Rule const& r) noexcept
93 : empty_value<Rule>(
94 8808 empty_init, r)
95 {
96 8808 }
97
98 auto
99 17644 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 4 times.
✓ Branch 1 taken 9144 times.
17644 if(it == end)
107 4 return grammar::error::end_of_range;
108 {
109 // element
110 17640 auto it0 = it;
111 17640 auto rv = this->get().parse(it, end);
112
2/2
✓ Branch 1 taken 9120 times.
✓ Branch 2 taken 24 times.
17640 if(rv)
113 17612 return std::move(*rv);
114 28 it = it0;
115
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 8454 times.
16912 }
116 // ","
117
2/2
✓ Branch 0 taken 11 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 8808 next_rule(
145 Rule const& r) noexcept
146 : empty_value<Rule>(
147 8808 empty_init, r)
148 {
149 8808 }
150
151 auto
152 17471 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 8910 times.
✓ Branch 1 taken 68 times.
17471 if(it == end)
161 17386 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 3 times.
✓ Branch 1 taken 65 times.
85 if(it == it0)
168 5 return grammar::error::end_of_range;
169 }
170 80 auto it1 = it;
171 // OWS
172 80 it = grammar::find_if_not(
173 it, end, detail::ws);
174 80 auto rv = this->get().parse(it, end);
175
2/2
✓ Branch 1 taken 59 times.
✓ Branch 2 taken 6 times.
80 if(rv)
176 73 return std::move(*rv);
177 7 it = it1;
178 7 return grammar::error::end_of_range;
179 28 }
180 };
181
182 template<class Rule>
183 auto
184 4554 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 9108 grammar::range_rule(
192 first_rule{this->get()},
193 next_rule{this->get()},
194
1/2
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
13662 n_, m_));
195 }
196 } // implementation_defined
197
198 } // http_proto
199 } // boost
200
201 #endif
202