GCC Code Coverage Report


Directory: libs/http_proto/include/boost/http_proto/
File: boost/http_proto/fields_base.hpp
Date: 2023-01-09 16:11:13
Exec Total Coverage
Lines: 23 23 100.0%
Functions: 7 7 100.0%
Branches: 2 4 50.0%

Line Branch Exec Source
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_FIELDS_BASE_HPP
11 #define BOOST_HTTP_PROTO_FIELDS_BASE_HPP
12
13 #include <boost/http_proto/detail/config.hpp>
14 #include <boost/http_proto/fields_view_base.hpp>
15
16 namespace boost {
17 namespace http_proto {
18
19 /** Mixin for modifiable HTTP fields
20
21 @par Iterators
22
23 Iterators obtained from @ref fields
24 containers are not invalidated when
25 the underlying container is modified.
26
27 @note HTTP field names are case-insensitive.
28 */
29 class BOOST_SYMBOL_VISIBLE
30 fields_base
31 : public virtual fields_view_base
32 {
33 detail::header h_;
34
35 class op_t;
36 using entry =
37 detail::header::entry;
38 using table =
39 detail::header::table;
40
41 friend class fields;
42 friend class request;
43 friend class response;
44 friend class serializer;
45 friend class message_base;
46 friend struct detail::header;
47
48 BOOST_HTTP_PROTO_DECL
49 explicit fields_base(
50 detail::kind) noexcept;
51
52 fields_base(detail::header const&);
53
54 public:
55 /** Destructor
56 */
57 BOOST_HTTP_PROTO_DECL
58 ~fields_base();
59
60 //--------------------------------------------
61 //
62 // Capacity
63 //
64 //--------------------------------------------
65
66 /** Returns the largest permissible capacity in bytes
67 */
68 static
69 constexpr
70 std::size_t
71 847 max_capacity_in_bytes() noexcept
72 {
73 using T = detail::header::entry;
74 return alignof(T) *
75 (((max_off_t - 2 + sizeof(T) * (
76 max_off_t / 4)) +
77 alignof(T) - 1) /
78 847 alignof(T));
79 }
80
81 /** Returns the total number of bytes allocated by the container
82 */
83 std::size_t
84 38 capacity_in_bytes() const noexcept
85 {
86 38 return h_.cap;
87 }
88
89 /** Clear the contents, but not the capacity
90 */
91 BOOST_HTTP_PROTO_DECL
92 void
93 clear() noexcept;
94
95 /** Reserve a minimum capacity
96 */
97 BOOST_HTTP_PROTO_DECL
98 void
99 reserve_bytes(std::size_t n);
100
101 /** Remove excess capacity
102 */
103 BOOST_HTTP_PROTO_DECL
104 void
105 shrink_to_fit() noexcept;
106
107 //--------------------------------------------
108 //
109 // Modifiers
110 //
111 //--------------------------------------------
112
113 /** Append a header
114
115 This function appends a new header.
116 Existing headers with the same name are
117 not changed. Names are not case-sensitive.
118 <br>
119 No iterators are invalidated.
120
121 @par Example
122 @code
123 request req;
124
125 req.append( field::user_agent, "Boost" );
126 @endcode
127
128 @par Complexity
129 Linear in `to_string( id ).size() + value.size()`.
130
131 @par Exception Safety
132 Strong guarantee.
133 Calls to allocate may throw.
134
135 @param id The field name constant,
136 which may not be @ref field::unknown.
137
138 @param value A value, which
139 @li Must be syntactically valid for the header,
140 @li Must be semantically valid for the message, and
141 @li May not contain leading or trailing whitespace.
142 */
143 void
144 20 append(
145 field id,
146 string_view value)
147 {
148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 BOOST_ASSERT(
149 id != field::unknown);
150 20 insert_impl(
151 id,
152 to_string(id),
153 value,
154 20 h_.count);
155 20 }
156
157 /** Append a header
158
159 This function appends a new header.
160 Existing headers with the same name are
161 not changed. Names are not case-sensitive.
162 <br>
163 No iterators are invalidated.
164
165 @par Example
166 @code
167 request req;
168
169 req.append( "User-Agent", "Boost" );
170 @endcode
171
172 @par Complexity
173 Linear in `name.size() + value.size()`.
174
175 @par Exception Safety
176 Strong guarantee.
177 Calls to allocate may throw.
178
179 @param name The header name.
180
181 @param value A value, which
182 @li Must be syntactically valid for the header,
183 @li Must be semantically valid for the message, and
184 @li May not contain leading or trailing whitespace.
185 */
186 void
187 723 append(
188 string_view name,
189 string_view value)
190 {
191 723 insert_impl(
192 string_to_field(
193 name),
194 name,
195 value,
196 723 h_.count);
197 722 }
198
199 /** Insert a header
200
201 If a matching header with the same name
202 exists, it is not replaced. Instead, an
203 additional header with the same name is
204 inserted. Names are not case-sensitive.
205 <br>
206 All iterators that are equal to `before`
207 or come after are invalidated.
208
209 @par Example
210 @code
211 request req;
212
213 req.insert( req.begin(), field::user_agent, "Boost" );
214 @endcode
215
216 @par Complexity
217 Linear in `to_string( id ).size() + value.size()`.
218
219 @par Exception Safety
220 Strong guarantee.
221 Calls to allocate may throw.
222
223 @return An iterator to the inserted
224 element.
225
226 @param before Position to insert before.
227
228 @param id The field name constant,
229 which may not be @ref field::unknown.
230
231 @param value A value, which
232 @li Must be syntactically valid for the header,
233 @li Must be semantically valid for the message, and
234 @li May not contain leading or trailing whitespace.
235 */
236 iterator
237 6 insert(
238 iterator before,
239 field id,
240 string_view value)
241 {
242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 BOOST_ASSERT(
243 id != field::unknown);
244 6 insert_impl(
245 id,
246 to_string(id),
247 value,
248 before.i_);
249 6 return before;
250 }
251
252 /** Insert a header
253
254 If a matching header with the same name
255 exists, it is not replaced. Instead, an
256 additional header with the same name is
257 inserted. Names are not case-sensitive.
258 <br>
259 All iterators that are equal to `before`
260 or come after are invalidated.
261
262 @par Example
263 @code
264 request req;
265
266 req.insert( req.begin(), "User-Agent", "Boost" );
267 @endcode
268
269 @par Complexity
270 Linear in `name.size() + value.size()`.
271
272 @par Exception Safety
273 Strong guarantee.
274 Calls to allocate may throw.
275
276 @return An iterator to the inserted
277 element.
278
279 @param before Position to insert before.
280
281 @param name The header name.
282
283 @param value A value, which
284 @li Must be syntactically valid for the header,
285 @li Must be semantically valid for the message, and
286 @li May not contain leading or trailing whitespace.
287 */
288 iterator
289 12 insert(
290 iterator before,
291 string_view name,
292 string_view value)
293 {
294 12 insert_impl(
295 string_to_field(
296 name),
297 name,
298 value,
299 before.i_);
300 12 return before;
301 }
302
303 //--------------------------------------------
304
305 /** Erase headers
306
307 This function removes the header pointed
308 to by `it`.
309 <br>
310 All iterators that are equal to `it`
311 or come after are invalidated.
312
313 @par Complexity
314 Linear in `name.size() + value.size()`.
315
316 @par Exception Safety
317 Throws nothing.
318
319 @return An iterator to the inserted
320 element.
321
322 @param it An iterator to the element
323 to erase.
324 */
325 iterator
326 31 erase(iterator it) noexcept
327 {
328 31 erase_impl(it.i_, it->id);
329 31 return it;
330 }
331
332 /** Erase headers
333
334 This removes all headers whose name
335 constant is equal to `id`.
336 <br>
337 If any headers are erased, then all
338 iterators equal to or that come after
339 the first erased element are invalidated.
340 Otherwise, no iterators are invalidated.
341
342 @par Complexity
343 Linear in `this->string().size()`.
344
345 @par Exception Safety
346 Throws nothing.
347
348 @return The number of headers erased.
349
350 @param id The field name constant,
351 which may not be @ref field::unknown.
352 */
353 BOOST_HTTP_PROTO_DECL
354 std::size_t
355 erase(field id) noexcept;
356
357 /** Erase all matching fields
358
359 This removes all headers with a matching
360 name, using a case-insensitive comparison.
361 <br>
362 If any headers are erased, then all
363 iterators equal to or that come after
364 the first erased element are invalidated.
365 Otherwise, no iterators are invalidated.
366
367 @par Complexity
368 Linear in `this->string().size()`.
369
370 @par Exception Safety
371 Throws nothing.
372
373 @return The number of fields erased
374
375 @param name The header name.
376 */
377 BOOST_HTTP_PROTO_DECL
378 std::size_t
379 erase(string_view name) noexcept;
380
381 //--------------------------------------------
382
383 /** Set a header value
384
385 This sets the value of the header
386 at `it`. The name is not changed.
387 <br>
388 No iterators are invalidated.
389
390 @par Complexity
391
392 @par Exception Safety
393 Strong guarantee.
394 Calls to allocate may throw.
395
396 @param it An iterator to the header.
397
398 @param value A value, which
399 @li Must be syntactically valid for the header,
400 @li Must be semantically valid for the message, and
401 @li May not contain leading or trailing whitespace.
402 */
403 BOOST_HTTP_PROTO_DECL
404 void
405 set(
406 iterator it,
407 string_view value);
408
409 /** Set a header value
410
411 This function sets the value of the
412 header with the specified field id.
413 Other headers with the same name
414 are removed first.
415
416 @par Postconditions
417 @code
418 this->count( id ) == 1 && this->at( id ) == value
419 @endcode
420
421 @par Complexity
422
423 @param id The field constant of the
424 header to set.
425
426 @param value A value, which
427 @li Must be syntactically valid for the header,
428 @li Must be semantically valid for the message, and
429 @li May not contain leading or trailing whitespace.
430 */
431 BOOST_HTTP_PROTO_DECL
432 void
433 set(
434 field id,
435 string_view value);
436
437 /** Set a header value
438
439 This function sets the value of the
440 header with the specified name. Other
441 headers with the same name are removed
442 first.
443
444 @par Postconditions
445 @code
446 this->count( name ) == 1 && this->at( name ) == value
447 @endcode
448
449 @param name The field name.
450
451 @param value The corresponding value, which
452 @li must be syntactically valid for the field,
453 @li must be semantically valid for the message, and
454 @li may not contain leading or trailing whitespace.
455 */
456 BOOST_HTTP_PROTO_DECL
457 void
458 set(
459 string_view name,
460 string_view value);
461
462 //--------------------------------------------
463
464 private:
465 BOOST_HTTP_PROTO_DECL
466 void
467 copy_impl(
468 detail::header const&);
469
470 BOOST_HTTP_PROTO_DECL
471 void
472 insert_impl(
473 field id,
474 string_view name,
475 string_view value,
476 std::size_t before);
477
478 BOOST_HTTP_PROTO_DECL
479 void
480 erase_impl(
481 std::size_t i,
482 field id) noexcept;
483
484 void raw_erase(
485 std::size_t) noexcept;
486
487 std::size_t
488 erase_all_impl(
489 std::size_t i0,
490 field id) noexcept;
491
492 std::size_t
493 offset(
494 std::size_t i) const noexcept;
495
496 std::size_t
497 length(
498 std::size_t i) const noexcept;
499
500 void raw_erase_n(field, std::size_t) noexcept;
501 };
502
503 //------------------------------------------------
504
505 #ifndef BOOST_HTTP_PROTO_DOCS
506 namespace detail {
507 inline
508 header&
509 header::
510 get(fields_base& f) noexcept
511 {
512 return f.h_;
513 }
514 } // detail
515 #endif
516
517 } // http_proto
518 } // boost
519
520 #endif
521