Line data Source code
1 : //
2 : // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2025 Mohammad Nejati
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/cppalliance/http_proto
9 : //
10 :
11 : #ifndef BOOST_HTTP_PROTO_FIELDS_VIEW_BASE_HPP
12 : #define BOOST_HTTP_PROTO_FIELDS_VIEW_BASE_HPP
13 :
14 : #include <boost/http_proto/detail/config.hpp>
15 : #include <boost/http_proto/detail/header.hpp>
16 :
17 : #include <boost/core/detail/string_view.hpp>
18 : #include <boost/url/grammar/recycled.hpp>
19 : #include <boost/url/grammar/type_traits.hpp>
20 :
21 : #include <iosfwd>
22 : #include <string>
23 :
24 : namespace boost {
25 : namespace http_proto {
26 :
27 : /** A read-only, bidirectional range of HTTP fields.
28 :
29 : This is a mix-in used to add common
30 : functionality to derived classes.
31 : */
32 : class fields_view_base
33 : {
34 : detail::header const* ph_;
35 :
36 : friend class fields;
37 : template<std::size_t>
38 : friend class static_fields;
39 : friend class fields_base;
40 : friend class fields_view;
41 : friend class message_base;
42 : friend class message_view_base;
43 : friend class request_base;
44 : friend class request;
45 : template<std::size_t>
46 : friend class static_request;
47 : friend class request_view;
48 : friend class response_base;
49 : friend class response;
50 : template<std::size_t>
51 : friend class static_response;
52 : friend class response_view;
53 : friend class serializer;
54 :
55 : explicit
56 1289 : fields_view_base(
57 : detail::header const* ph) noexcept
58 1289 : : ph_(ph)
59 : {
60 1289 : }
61 :
62 : fields_view_base(
63 : fields_view_base const&) = default;
64 : fields_view_base&
65 : operator=(fields_view_base const&) = default;
66 :
67 : public:
68 : //--------------------------------------------
69 : //
70 : // Types
71 : //
72 : //--------------------------------------------
73 :
74 : /** A view to an HTTP field.
75 :
76 : The view will be invalidated when the
77 : underlying container is modified.
78 :
79 : The caller is responsible for ensuring
80 : that the lifetime of the container extends
81 : until it is no longer referenced.
82 : */
83 : struct reference
84 : {
85 : /** Field name constant.
86 :
87 : Set to `boost::none` if the constant
88 : does not exist in @ref field.
89 : */
90 : boost::optional<field> const id;
91 :
92 : /// A view to the field name.
93 : core::string_view const name;
94 :
95 : /// A view to the field value.
96 : core::string_view const value;
97 :
98 : reference const*
99 2063 : operator->() const noexcept
100 : {
101 2063 : return this;
102 : }
103 : };
104 :
105 : /// @copydoc reference
106 : typedef reference const_reference;
107 :
108 : /** A value type which represent an HTTP field.
109 :
110 : This type allows for making a copy of
111 : a field where ownership is retained
112 : in the copy.
113 : */
114 : struct value_type
115 : {
116 : /** Field name constant.
117 :
118 : Set to `boost::none` if the
119 : constant does not exist in @ref field.
120 : */
121 : boost::optional<field> id;
122 :
123 : /// Field name.
124 : std::string name;
125 :
126 : /// Field value.
127 : std::string value;
128 :
129 : /// Constructor.
130 : BOOST_HTTP_PROTO_DECL
131 : value_type(
132 : reference const& other);
133 :
134 : /** Conversion.
135 :
136 : @see
137 : @ref reference.
138 :
139 : @return A view to the fields.
140 : */
141 : operator reference() const noexcept;
142 : };
143 :
144 : /** A bidirectional iterator to HTTP fields.
145 : */
146 : class iterator;
147 :
148 : /// @copydoc iterator
149 : using const_iterator = iterator;
150 :
151 : /** A bidirectional reverse iterator to HTTP fields.
152 : */
153 : class reverse_iterator;
154 :
155 : /// @copydoc iterator
156 : using const_reverse_iterator = reverse_iterator;
157 :
158 : /** A forward range of matching fields.
159 :
160 : Objects of this type are returned by
161 : the function @ref find_all.
162 : */
163 : class subrange;
164 :
165 : //--------------------------------------------
166 : //
167 : // Observers
168 : //
169 : //--------------------------------------------
170 :
171 : /** Return the largest possible serialized message.
172 : */
173 : static
174 : constexpr
175 : std::size_t
176 : max_size() noexcept
177 : {
178 : // TODO: this doesn't take into account
179 : // the start-line
180 : return detail::header::max_offset;
181 : }
182 :
183 : /** Return an iterator to the beginning.
184 : */
185 : iterator
186 : begin() const noexcept;
187 :
188 : /** Return an iterator to the end.
189 : */
190 : iterator
191 : end() const noexcept;
192 :
193 : /** Return a reverse iterator to the beginning.
194 : */
195 : reverse_iterator
196 : rbegin() const noexcept;
197 :
198 : /** Return a reverse iterator to the end.
199 : */
200 : reverse_iterator
201 : rend() const noexcept;
202 :
203 : /** Return a string view representing the serialized data.
204 : */
205 : core::string_view
206 766 : buffer() const noexcept
207 : {
208 1532 : return core::string_view(
209 766 : ph_->cbuf, ph_->size);
210 : }
211 :
212 : /** Return the number of fields in the container.
213 : */
214 : std::size_t
215 215 : size() const noexcept
216 : {
217 215 : return ph_->count;
218 : }
219 :
220 : /** Return the value of a field, or throws an exception.
221 :
222 : If more than one field with the specified
223 : name exists, the first field defined by
224 : insertion order is returned.
225 :
226 : @par Exception Safety
227 : Strong guarantee.
228 :
229 : @throw std::out_of_range
230 : Field is not found.
231 :
232 : @param id The field name constant.
233 : */
234 : BOOST_HTTP_PROTO_DECL
235 : core::string_view
236 : at(field id) const;
237 :
238 : /** Return the value of a field, or throws an exception.
239 :
240 : If more than one field with the specified
241 : name exists, the first field defined by
242 : insertion order is returned.
243 :
244 : If `name` refers to a known field, it is
245 : faster to call @ref at with a field id
246 : instead of a string.
247 :
248 : @par Exception Safety
249 : Strong guarantee.
250 :
251 : @throw std::out_of_range
252 : Field is not found.
253 :
254 : @param name The field name.
255 : */
256 : BOOST_HTTP_PROTO_DECL
257 : core::string_view
258 : at(core::string_view name) const;
259 :
260 : /** Return true if a field exists.
261 : */
262 : BOOST_HTTP_PROTO_DECL
263 : bool
264 : exists(field id) const noexcept;
265 :
266 : /** Return true if a field exists.
267 :
268 : If `name` refers to a known field,
269 : it is faster to call @ref exists
270 : with a field id instead of a string.
271 :
272 : @param name The field name.
273 : */
274 : BOOST_HTTP_PROTO_DECL
275 : bool
276 : exists(
277 : core::string_view name) const noexcept;
278 :
279 : /** Return the number of matching fields.
280 :
281 : @param id The field name constant.
282 : */
283 : BOOST_HTTP_PROTO_DECL
284 : std::size_t
285 : count(field id) const noexcept;
286 :
287 : /** Return the number of matching fields.
288 :
289 : If `name` refers to a known field,
290 : it is faster to call @ref count
291 : with a field id instead of a string.
292 :
293 : @param name The field name.
294 : */
295 : BOOST_HTTP_PROTO_DECL
296 : std::size_t
297 : count(
298 : core::string_view name) const noexcept;
299 :
300 : /** Return an iterator to the matching element if it exists.
301 :
302 : @param id The field name constant.
303 : */
304 : BOOST_HTTP_PROTO_DECL
305 : iterator
306 : find(field id) const noexcept;
307 :
308 : /** Return an iterator to the matching element if it exists.
309 :
310 : If `name` refers to a known field,
311 : it is faster to call @ref find
312 : with a field id instead of a string.
313 :
314 : @param name The field name.
315 : */
316 : BOOST_HTTP_PROTO_DECL
317 : iterator
318 : find(
319 : core::string_view name) const noexcept;
320 :
321 : /** Return an iterator to the matching element if it exists.
322 :
323 : @param from The position to begin the
324 : search from. This can be `end()`.
325 :
326 : @param id The field name constant.
327 : */
328 : BOOST_HTTP_PROTO_DECL
329 : iterator
330 : find(
331 : iterator from,
332 : field id) const noexcept;
333 :
334 : /** Return an iterator to the matching element if it exists.
335 :
336 : If `name` refers to a known field,
337 : it is faster to call @ref find
338 : with a field id instead of a string.
339 :
340 : @param from The position to begin the
341 : search from. This can be `end()`.
342 :
343 : @param name The field name.
344 : */
345 : BOOST_HTTP_PROTO_DECL
346 : iterator
347 : find(
348 : iterator from,
349 : core::string_view name) const noexcept;
350 :
351 : /** Return an iterator to the matching element if it exists.
352 :
353 : @param before One past the position
354 : to begin the search from. This can
355 : be `end()`.
356 :
357 : @param id The field name constant.
358 : */
359 : BOOST_HTTP_PROTO_DECL
360 : iterator
361 : find_last(
362 : iterator before,
363 : field id) const noexcept;
364 :
365 : /** Return an iterator to the matching element if it exists.
366 :
367 : If `name` refers to a known field,
368 : it is faster to call @ref find_last
369 : with a field id instead of a string.
370 :
371 : @param before One past the position
372 : to begin the search from. This can
373 : be `end()`.
374 :
375 : @param name The field name.
376 : */
377 : BOOST_HTTP_PROTO_DECL
378 : iterator
379 : find_last(
380 : iterator before,
381 : core::string_view name) const noexcept;
382 :
383 : /** Return the value of a field or a default if missing.
384 :
385 : @param id The field name constant.
386 :
387 : @param s The value to be returned if
388 : field does not exist.
389 : */
390 : BOOST_HTTP_PROTO_DECL
391 : core::string_view
392 : value_or(
393 : field id,
394 : core::string_view s) const noexcept;
395 :
396 : /** Return the value of a field or a default if missing.
397 :
398 : If `name` refers to a known field,
399 : it is faster to call @ref value_or
400 : with a field id instead of a string.
401 :
402 : @param name The field name.
403 :
404 : @param s The value to be returned if
405 : field does not exist.
406 : */
407 : BOOST_HTTP_PROTO_DECL
408 : core::string_view
409 : value_or(
410 : core::string_view name,
411 : core::string_view s) const noexcept;
412 :
413 : /** Return a forward range containing values for all matching fields.
414 :
415 : @param id The field name constant.
416 : */
417 : BOOST_HTTP_PROTO_DECL
418 : subrange
419 : find_all(field id) const noexcept;
420 :
421 : /** Return a forward range containing values for all matching fields.
422 :
423 : If `name` refers to a known field,
424 : it is faster to call @ref find_all
425 : with a field id instead of a string.
426 :
427 : @param name The field name.
428 : */
429 : BOOST_HTTP_PROTO_DECL
430 : subrange
431 : find_all(
432 : core::string_view name) const noexcept;
433 : };
434 :
435 : /** Format the container to the output stream
436 :
437 : This function serializes the container to
438 : the specified output stream.
439 :
440 : @par Example
441 : @code
442 : request req;
443 : std::stringstream ss;
444 : ss << req;
445 : assert( ss.str() == "GET / HTTP/1.1\r\n\r\n" );
446 : @endcode
447 :
448 : @par Effects
449 : @code
450 : return os << f.buffer();
451 : @endcode
452 :
453 : @par Complexity
454 : Linear in `f.buffer().size()`
455 :
456 : @par Exception Safety
457 : Basic guarantee.
458 :
459 : @return A reference to the output stream, for chaining
460 :
461 : @param os The output stream to write to.
462 :
463 : @param f The container to write.
464 : */
465 : BOOST_HTTP_PROTO_DECL
466 : std::ostream&
467 : operator<<(
468 : std::ostream& os,
469 : const fields_view_base& f);
470 :
471 : } // http_proto
472 : } // boost
473 :
474 : #include <boost/http_proto/impl/fields_view_base.hpp>
475 :
476 : #endif
|