GCC Code Coverage Report


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