GCC Code Coverage Report


Directory: libs/http_proto/
File: include/boost/http_proto/fields.hpp
Date: 2025-10-12 23:51:57
Exec Total Coverage
Lines: 28 28 100.0%
Functions: 8 8 100.0%
Branches: 3 4 75.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2024 Christian Mazakas
4 // Copyright (c) 2025 Mohammad Nejati
5 //
6 // Distributed under the Boost Software License, Version 1.0. (See accompanying
7 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // Official repository: https://github.com/cppalliance/http_proto
10 //
11
12 #ifndef BOOST_HTTP_PROTO_FIELDS_HPP
13 #define BOOST_HTTP_PROTO_FIELDS_HPP
14
15 #include <boost/http_proto/detail/config.hpp>
16 #include <boost/http_proto/fields_base.hpp>
17
18 namespace boost {
19 namespace http_proto {
20
21 /** A modifiable container of HTTP fields.
22
23 This container owns a collection of HTTP
24 fields, represented by a buffer which is
25 managed by performing dynamic memory
26 allocations as needed. The contents may be
27 inspected and modified, and the implementation
28 maintains a useful invariant: changes to the
29 fields always leave it in a valid state.
30
31 @par Example
32 @code
33 fields fs;
34
35 fs.set(field::host, "example.com");
36 fs.set(field::accept_encoding, "gzip, deflate, br");
37 fs.set(field::cache_control, "no-cache");
38
39 assert(fs.buffer() ==
40 "Host: example.com\r\n"
41 "Accept-Encoding: gzip, deflate, br\r\n"
42 "Cache-Control: no-cache\r\n"
43 "\r\n");
44 @endcode
45
46 @see
47 @ref fields_base.
48 */
49 class fields final
50 : public fields_base
51 {
52 public:
53
54 //--------------------------------------------
55 //
56 // Special Members
57 //
58 //--------------------------------------------
59
60 /** Constructor.
61
62 A default-constructed fields container
63 contain no name-value pairs.
64
65 @par Example
66 @code
67 fields fs;
68 @endcode
69
70 @par Postconditions
71 @code
72 this->buffer() == "\r\n"
73 @endcode
74
75 @par Complexity
76 Constant.
77 */
78 27 fields() noexcept
79 27 : fields_base(detail::kind::fields)
80 {
81 27 }
82
83
84 /** Constructor.
85
86 Constructs a fields container from the string
87 `s`, which must contain valid HTTP headers or
88 else an exception is thrown.
89 The new fields container retains ownership by
90 allocating a copy of the passed string.
91
92 @par Example
93 @code
94 fields f(
95 "Server: Boost.HttpProto\r\n"
96 "Content-Type: text/plain\r\n"
97 "Connection: close\r\n"
98 "Content-Length: 73\r\n"
99 "\r\n");
100 @endcode
101
102 @par Postconditions
103 @code
104 this->buffer() == s && this->buffer().data() != s.data()
105 @endcode
106
107 @par Complexity
108 Linear in `s.size()`.
109
110 @par Exception Safety
111 Calls to allocate may throw.
112 Exception thrown on invalid input.
113
114 @throw system_error
115 Input is invalid.
116
117 @param s The string to parse.
118 */
119 explicit
120 235 fields(
121 core::string_view s)
122 235 : fields_base(detail::kind::fields, s)
123 {
124 234 }
125
126 /** Constructor.
127
128 Allocates `cap` bytes initially, with an
129 upper limit of `max_cap`. Growing beyond
130 `max_cap` will throw an exception.
131
132 Useful when an estimated initial size is
133 known, but further growth up to a
134 maximum is allowed.
135
136 @par Preconditions
137 @code
138 max_cap >= cap
139 @endcode
140
141 @par Exception Safety
142 Calls to allocate may throw.
143 Exception thrown on invalid input.
144
145 @throw system_error
146 Input is invalid.
147
148 @param cap Initial capacity in bytes (may be `0`).
149
150 @param max_cap Maximum allowed capacity in bytes.
151 */
152 explicit
153 10 fields(
154 std::size_t cap,
155 std::size_t max_cap = std::size_t(-1))
156 10 : fields()
157 {
158
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 reserve_bytes(cap);
159
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
10 set_max_capacity_in_bytes(max_cap);
160 10 }
161
162 /** Constructor.
163
164 The contents of `f` are transferred
165 to the newly constructed object,
166 which includes the underlying
167 character buffer.
168 After construction, the moved-from
169 object is as if default-constructed.
170
171 @par Postconditions
172 @code
173 f.buffer() == "\r\n"
174 @endcode
175
176 @par Complexity
177 Constant.
178
179 @param f The fields to move from.
180 */
181 6 fields(fields&& f) noexcept
182 6 : fields_base(f.h_.kind)
183 {
184 6 swap(f);
185 6 }
186
187
188 /** Constructor.
189
190 The newly constructed object contains
191 a copy of `f`.
192
193 @par Postconditions
194 @code
195 this->buffer() == f.buffer() && this->buffer().data() != f.buffer().data()
196 @endcode
197
198 @par Complexity
199 Linear in `f.size()`.
200
201 @par Exception Safety
202 Calls to allocate may throw.
203
204 @param f The fields to copy.
205 */
206 2 fields(fields const& f) = default;
207
208 /** Assignment.
209
210 The contents of `f` are transferred to
211 `this`, including the underlying
212 character buffer. The previous contents
213 of `this` are destroyed.
214 After assignment, the moved-from
215 object is as if default-constructed.
216
217 @par Postconditions
218 @code
219 f.buffer() == "\r\n"
220 @endcode
221
222 @par Complexity
223 Constant.
224
225 @param f The fields to assign from.
226
227 @return A reference to this object.
228 */
229 fields&
230 4 operator=(fields&& f) noexcept
231 {
232 4 fields tmp(std::move(f));
233 4 tmp.swap(*this);
234 8 return *this;
235 4 }
236
237 /** Assignment.
238
239 The contents of `f` are copied and
240 the previous contents of `this` are
241 discarded.
242
243 @par Postconditions
244 @code
245 this->buffer() == f.buffer() && this->buffer().data() != f.buffer().data()
246 @endcode
247
248 @par Complexity
249 Linear in `f.size()`.
250
251 @par Exception Safety
252 Strong guarantee.
253 Calls to allocate may throw.
254 Exception thrown if max capacity exceeded.
255
256 @throw std::length_error
257 Max capacity would be exceeded.
258
259 @return A reference to this object.
260
261 @param f The fields to copy.
262 */
263 fields&
264 4 operator=(fields const& f) noexcept
265 {
266 4 copy_impl(f.h_);
267 4 return *this;
268 }
269
270 //--------------------------------------------
271
272 /** Swap.
273
274 Exchanges the contents of this fields
275 object with another. All views, iterators
276 and references remain valid.
277
278 If `this == &other`, this function call has no effect.
279
280 @par Example
281 @code
282 fields f1;
283 f1.set(field::accept, "text/html");
284 fields f2;
285 f2.set(field::connection, "keep-alive");
286 f1.swap(f2);
287 assert(f1.buffer() == "Connection: keep-alive\r\n\r\n" );
288 assert(f2.buffer() == "Accept: text/html\r\n\r\n" );
289 @endcode
290
291 @par Complexity
292 Constant.
293
294 @param other The object to swap with.
295 */
296 void
297 10 swap(fields& other) noexcept
298 {
299 10 h_.swap(other.h_);
300 10 std::swap(max_cap_, other.max_cap_);
301 10 }
302
303 /** Swap.
304
305 Exchanges the contents of `v0` with
306 another `v1`. All views, iterators and
307 references remain valid.
308
309 If `&v0 == &v1`, this function call has no effect.
310
311 @par Example
312 @code
313 fields f1;
314 f1.set(field::accept, "text/html");
315 fields f2;
316 f2.set(field::connection, "keep-alive");
317 std::swap(f1, f2);
318 assert(f1.buffer() == "Connection: keep-alive\r\n\r\n" );
319 assert(f2.buffer() == "Accept: text/html\r\n\r\n" );
320 @endcode
321
322 @par Effects
323 @code
324 v0.swap(v1);
325 @endcode
326
327 @par Complexity
328 Constant.
329
330 @param v0 The first object to swap.
331 @param v1 The second object to swap.
332
333 @see
334 @ref fields::swap.
335 */
336 friend
337 void
338 swap(
339 fields& v0,
340 fields& v1) noexcept
341 {
342 v0.swap(v1);
343 }
344 };
345
346 } // http_proto
347 } // boost
348
349 #endif
350