GCC Code Coverage Report


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