GCC Code Coverage Report


Directory: libs/http_proto/
File: libs/http_proto/src/message_base.cpp
Date: 2024-02-07 16:12:48
Exec Total Coverage
Lines: 98 115 85.2%
Functions: 3 6 50.0%
Branches: 56 90 62.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 #include <boost/http_proto/message_base.hpp>
11 #include <boost/http_proto/rfc/list_rule.hpp>
12 #include <boost/http_proto/rfc/token_rule.hpp>
13 #include <boost/http_proto/detail/except.hpp>
14 #include "detail/number_string.hpp"
15 #include <boost/url/grammar/parse.hpp>
16 #include <boost/url/grammar/ci_string.hpp>
17
18 namespace boost {
19 namespace http_proto {
20
21 void
22 message_base::
23 set_payload_size(
24 std::uint64_t n)
25 {
26 //if(! is_head_response())
27 if(true)
28 {
29 // comes first for exception safety
30 set_content_length(n);
31
32 set_chunked(false);
33 }
34 else
35 {
36 // VFALCO ?
37 }
38 }
39
40 void
41 message_base::
42 set_content_length(
43 std::uint64_t n)
44 {
45 set(field::content_length,
46 detail::number_string(n));
47 }
48
49 void
50 message_base::
51 set_chunked(bool value)
52 {
53 if(value)
54 {
55 // set chunked
56 if(! h_.md.transfer_encoding.is_chunked )
57 {
58 append(
59 field::transfer_encoding,
60 "chunked");
61 return;
62 }
63 }
64 else
65 {
66 // clear chunked
67 // VFALCO ?
68 }
69 }
70
71 void
72 12 message_base::
73 set_keep_alive(bool value)
74 {
75
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 if(ph_->md.connection.ec.failed())
76 {
77 // throw? return false?
78 5 return;
79 }
80
81
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7 times.
12 if(ph_->md.connection.count == 0)
82 {
83 // no Connection field
84
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 switch(ph_->version)
85 {
86 3 default:
87 case version::http_1_1:
88
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if(! value)
89
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 set(field::connection, "close");
90 3 break;
91
92 2 case version::http_1_0:
93
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(value)
94
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 set(field::connection, "keep-alive");
95 2 break;
96 }
97 5 return;
98 }
99
100 // VFALCO TODO iterate in reverse order,
101 // and cache the last iterator to use
102 // for appending
103
104 // one or more Connection fields
105 7 auto it = begin();
106 auto const erase_token =
107 14 [&](core::string_view token)
108 {
109
2/2
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 6 times.
14 while(it != end())
110 {
111
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if(it->id != field::connection)
112 {
113 ++it;
114 4 continue;
115 }
116 auto rv = grammar::parse(
117 8 it->value,
118
1/2
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
16 list_rule(token_rule, 1));
119
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 BOOST_ASSERT(! rv.has_error());
120
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 BOOST_ASSERT(! rv->empty());
121 8 auto itv = rv->begin();
122
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
8 if(urls::grammar::ci_is_equal(
123 8 *itv, token))
124 {
125
2/2
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 times.
4 if(rv->size() == 1)
126 {
127 // only one token
128 3 it = erase(it);
129 }
130 else
131 {
132 // first token matches
133 1 ++itv;
134
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 set(it,
135 1 it->value.substr(
136
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 (*itv).data() -
137 1 it->value.data()));
138 1 ++it;
139 }
140 4 continue;
141 }
142 // search remaining tokens
143
1/2
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
8 std::string s = *itv++;
144
2/2
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 4 times.
7 while(itv != rv->end())
145 {
146
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if(! urls::grammar::ci_is_equal(
147 3 *itv, token))
148
3/6
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
1 s += ", " + std::string(*itv);
149 3 ++itv;
150 }
151
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 set(it, s);
152 4 ++it;
153 }
154 6 };
155
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 if(value)
156 {
157
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 if(ph_->md.connection.close)
158
1/2
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 erase_token("close");
159 }
160 else
161 {
162
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(ph_->md.connection.keep_alive)
163
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 erase_token("keep-alive");
164 }
165
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
7 switch(ph_->version)
166 {
167 5 default:
168 case version::http_1_1:
169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(! value)
170 {
171 // add one "close" token if needed
172 if(! ph_->md.connection.close)
173 append(field::connection, "close");
174 }
175 5 break;
176
177 2 case version::http_1_0:
178
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(value)
179 {
180 // add one "keep-alive" token if needed
181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(! ph_->md.connection.keep_alive)
182 append(field::connection, "keep-alive");
183 }
184 2 break;
185 }
186 }
187
188 //------------------------------------------------
189
190 char*
191 10 message_base::
192 set_prefix_impl(
193 std::size_t n)
194 {
195
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
10 if( n > h_.prefix ||
196
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 h_.buf == nullptr)
197 {
198 // allocate or grow
199
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 if( n > h_.prefix &&
200 static_cast<std::size_t>(
201 7 n - h_.prefix) >
202 7 static_cast<std::size_t>(
203
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 max_offset - h_.size))
204 1 detail::throw_length_error();
205
206 7 auto n0 = detail::header::bytes_needed(
207 7 n + h_.size - h_.prefix,
208 7 h_.count);
209 7 auto buf = new char[n0];
210
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if(h_.buf != nullptr)
211 {
212 3 std::memcpy(
213 3 buf + n,
214 3 h_.buf + h_.prefix,
215 3 h_.size - h_.prefix);
216 detail::header::table ft(
217 3 h_.buf + h_.cap);
218 3 h_.copy_table(buf + n0);
219
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 delete[] h_.buf;
220 }
221 else
222 {
223 4 std::memcpy(
224 4 buf + n,
225 4 h_.cbuf + h_.prefix,
226 4 h_.size - h_.prefix);
227 }
228 7 h_.buf = buf;
229 7 h_.cbuf = buf;
230 7 h_.size = static_cast<
231 7 offset_type>(h_.size +
232 7 n - h_.prefix);
233 7 h_.prefix = static_cast<
234 offset_type>(n);
235 7 h_.cap = n0;
236 7 return h_.buf;
237 }
238
239 // shrink
240 2 std::memmove(
241 2 h_.buf + n,
242 2 h_.buf + h_.prefix,
243 2 h_.size - h_.prefix);
244 2 h_.size = static_cast<
245 2 offset_type>(h_.size -
246 2 h_.prefix + n);
247 2 h_.prefix = static_cast<
248 offset_type>(n);
249 2 return h_.buf;
250 }
251
252 } // http_proto
253 } // boost
254