Line data Source code
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_BASE_HPP
13 : #define BOOST_HTTP_PROTO_FIELDS_BASE_HPP
14 :
15 : #include <boost/http_proto/detail/config.hpp>
16 : #include <boost/http_proto/detail/except.hpp>
17 : #include <boost/http_proto/detail/header.hpp>
18 : #include <boost/core/detail/string_view.hpp>
19 :
20 : #include <iosfwd>
21 :
22 : namespace boost {
23 : namespace http_proto {
24 :
25 : /** Mixin for modifiable HTTP fields.
26 :
27 : @par Iterators
28 :
29 : Iterators obtained from @ref fields
30 : containers are not invalidated when
31 : the underlying container is modified.
32 :
33 : @note HTTP field names are case-insensitive.
34 : */
35 : class fields_base
36 : {
37 : detail::header h_;
38 : std::size_t max_cap_ =
39 : std::numeric_limits<std::size_t>::max();
40 : bool external_storage_ = false;
41 :
42 : using entry =
43 : detail::header::entry;
44 : using offset_type =
45 : detail::header::offset_type;
46 : using table =
47 : detail::header::table;
48 :
49 : class op_t;
50 : class prefix_op_t
51 : {
52 : fields_base& self_;
53 : offset_type new_prefix_;
54 : char* buf_ = nullptr;
55 :
56 : public:
57 : prefix_op_t(
58 : fields_base& self,
59 : std::size_t new_prefix,
60 : core::string_view* s0 = nullptr,
61 : core::string_view* s1 = nullptr);
62 :
63 : ~prefix_op_t();
64 : };
65 :
66 : friend class fields;
67 : friend class message_base;
68 : friend class request_base;
69 : friend class request;
70 : friend class static_request;
71 : friend class response_base;
72 : friend class response;
73 : friend class static_response;
74 : friend class parser;
75 : friend class serializer;
76 :
77 : BOOST_HTTP_PROTO_DECL
78 : explicit
79 : fields_base(
80 : detail::kind k) noexcept;
81 :
82 : BOOST_HTTP_PROTO_DECL
83 : fields_base(
84 : detail::kind k,
85 : void* storage,
86 : std::size_t cap) noexcept;
87 :
88 : BOOST_HTTP_PROTO_DECL
89 : fields_base(
90 : detail::kind k,
91 : core::string_view s);
92 :
93 : BOOST_HTTP_PROTO_DECL
94 : explicit
95 : fields_base(
96 : detail::header const& h);
97 :
98 : BOOST_HTTP_PROTO_DECL
99 : fields_base(
100 : fields_base const&);
101 :
102 : BOOST_HTTP_PROTO_DECL
103 : fields_base(
104 : detail::header const& h,
105 : void* storage,
106 : std::size_t cap);
107 :
108 : public:
109 : //--------------------------------------------
110 : //
111 : // Types
112 : //
113 : //--------------------------------------------
114 :
115 : /** A view to an HTTP field.
116 :
117 : The view will be invalidated when the
118 : underlying container is modified.
119 :
120 : The caller is responsible for ensuring
121 : that the lifetime of the container extends
122 : until it is no longer referenced.
123 : */
124 : struct reference
125 : {
126 : /** Field name constant.
127 :
128 : Set to `boost::none` if the constant
129 : does not exist in @ref field.
130 : */
131 : boost::optional<field> const id;
132 :
133 : /// A view to the field name.
134 : core::string_view const name;
135 :
136 : /// A view to the field value.
137 : core::string_view const value;
138 :
139 : reference const*
140 1731 : operator->() const noexcept
141 : {
142 1731 : return this;
143 : }
144 : };
145 :
146 : /// @copydoc reference
147 : typedef reference const_reference;
148 :
149 : /** A value type which represent an HTTP field.
150 :
151 : This type allows for making a copy of
152 : a field where ownership is retained
153 : in the copy.
154 : */
155 : struct value_type
156 : {
157 : /** Field name constant.
158 :
159 : Set to `boost::none` if the
160 : constant does not exist in @ref field.
161 : */
162 : boost::optional<field> id;
163 :
164 : /// Field name.
165 : std::string name;
166 :
167 : /// Field value.
168 : std::string value;
169 :
170 : /// Constructor.
171 : BOOST_HTTP_PROTO_DECL
172 : value_type(
173 : reference const& other);
174 :
175 : /** Conversion.
176 :
177 : @see
178 : @ref reference.
179 :
180 : @return A view to the fields.
181 : */
182 : operator reference() const noexcept;
183 : };
184 :
185 : /** A bidirectional iterator to HTTP fields.
186 : */
187 : class iterator;
188 :
189 : /// @copydoc iterator
190 : using const_iterator = iterator;
191 :
192 : /** A bidirectional reverse iterator to HTTP fields.
193 : */
194 : class reverse_iterator;
195 :
196 : /// @copydoc iterator
197 : using const_reverse_iterator = reverse_iterator;
198 :
199 : /** A forward range of matching fields.
200 :
201 : Objects of this type are returned by
202 : the function @ref find_all.
203 : */
204 : class subrange;
205 :
206 : //--------------------------------------------
207 : //
208 : // Special Members
209 : //
210 : //--------------------------------------------
211 :
212 : /** Destructor.
213 : */
214 : BOOST_HTTP_PROTO_DECL
215 : ~fields_base();
216 :
217 : //--------------------------------------------
218 : //
219 : // Observers
220 : //
221 : //--------------------------------------------
222 :
223 : /** Return the largest possible serialized message.
224 : */
225 : static
226 : constexpr
227 : std::size_t
228 : max_size() noexcept
229 : {
230 : // TODO: this doesn't take into account
231 : // the start-line
232 : return detail::header::max_offset;
233 : }
234 :
235 : /** Return an iterator to the beginning.
236 : */
237 : iterator
238 : begin() const noexcept;
239 :
240 : /** Return an iterator to the end.
241 : */
242 : iterator
243 : end() const noexcept;
244 :
245 : /** Return a reverse iterator to the beginning.
246 : */
247 : reverse_iterator
248 : rbegin() const noexcept;
249 :
250 : /** Return a reverse iterator to the end.
251 : */
252 : reverse_iterator
253 : rend() const noexcept;
254 :
255 : /** Return a string view representing the serialized data.
256 : */
257 : core::string_view
258 685 : buffer() const noexcept
259 : {
260 1370 : return core::string_view(
261 685 : h_.cbuf, h_.size);
262 : }
263 :
264 : /** Return the number of fields in the container.
265 : */
266 : std::size_t
267 185 : size() const noexcept
268 : {
269 185 : return h_.count;
270 : }
271 :
272 : /** Return the value of a field, or throws an exception.
273 :
274 : If more than one field with the specified
275 : name exists, the first field defined by
276 : insertion order is returned.
277 :
278 : @par Exception Safety
279 : Strong guarantee.
280 :
281 : @throw std::out_of_range
282 : Field is not found.
283 :
284 : @param id The field name constant.
285 : */
286 : BOOST_HTTP_PROTO_DECL
287 : core::string_view
288 : at(field id) const;
289 :
290 : /** Return the value of a field, or throws an exception.
291 :
292 : If more than one field with the specified
293 : name exists, the first field defined by
294 : insertion order is returned.
295 :
296 : If `name` refers to a known field, it is
297 : faster to call @ref at with a field id
298 : instead of a string.
299 :
300 : @par Exception Safety
301 : Strong guarantee.
302 :
303 : @throw std::out_of_range
304 : Field is not found.
305 :
306 : @param name The field name.
307 : */
308 : BOOST_HTTP_PROTO_DECL
309 : core::string_view
310 : at(core::string_view name) const;
311 :
312 : /** Return true if a field exists.
313 : */
314 : BOOST_HTTP_PROTO_DECL
315 : bool
316 : exists(field id) const noexcept;
317 :
318 : /** Return true if a field exists.
319 :
320 : If `name` refers to a known field,
321 : it is faster to call @ref exists
322 : with a field id instead of a string.
323 :
324 : @param name The field name.
325 : */
326 : BOOST_HTTP_PROTO_DECL
327 : bool
328 : exists(
329 : core::string_view name) const noexcept;
330 :
331 : /** Return the number of matching fields.
332 :
333 : @param id The field name constant.
334 : */
335 : BOOST_HTTP_PROTO_DECL
336 : std::size_t
337 : count(field id) const noexcept;
338 :
339 : /** Return the number of matching fields.
340 :
341 : If `name` refers to a known field,
342 : it is faster to call @ref count
343 : with a field id instead of a string.
344 :
345 : @param name The field name.
346 : */
347 : BOOST_HTTP_PROTO_DECL
348 : std::size_t
349 : count(
350 : core::string_view name) const noexcept;
351 :
352 : /** Return an iterator to the matching element if it exists.
353 :
354 : @param id The field name constant.
355 : */
356 : BOOST_HTTP_PROTO_DECL
357 : iterator
358 : find(field id) const noexcept;
359 :
360 : /** Return an iterator to the matching element if it exists.
361 :
362 : If `name` refers to a known field,
363 : it is faster to call @ref find
364 : with a field id instead of a string.
365 :
366 : @param name The field name.
367 : */
368 : BOOST_HTTP_PROTO_DECL
369 : iterator
370 : find(
371 : core::string_view name) const noexcept;
372 :
373 : /** Return an iterator to the matching element if it exists.
374 :
375 : @param from The position to begin the
376 : search from. This can be `end()`.
377 :
378 : @param id The field name constant.
379 : */
380 : BOOST_HTTP_PROTO_DECL
381 : iterator
382 : find(
383 : iterator from,
384 : field id) const noexcept;
385 :
386 : /** Return an iterator to the matching element if it exists.
387 :
388 : If `name` refers to a known field,
389 : it is faster to call @ref find
390 : with a field id instead of a string.
391 :
392 : @param from The position to begin the
393 : search from. This can be `end()`.
394 :
395 : @param name The field name.
396 : */
397 : BOOST_HTTP_PROTO_DECL
398 : iterator
399 : find(
400 : iterator from,
401 : core::string_view name) const noexcept;
402 :
403 : /** Return an iterator to the matching element if it exists.
404 :
405 : @param before One past the position
406 : to begin the search from. This can
407 : be `end()`.
408 :
409 : @param id The field name constant.
410 : */
411 : BOOST_HTTP_PROTO_DECL
412 : iterator
413 : find_last(
414 : iterator before,
415 : field id) const noexcept;
416 :
417 : /** Return an iterator to the matching element if it exists.
418 :
419 : If `name` refers to a known field,
420 : it is faster to call @ref find_last
421 : with a field id instead of a string.
422 :
423 : @param before One past the position
424 : to begin the search from. This can
425 : be `end()`.
426 :
427 : @param name The field name.
428 : */
429 : BOOST_HTTP_PROTO_DECL
430 : iterator
431 : find_last(
432 : iterator before,
433 : core::string_view name) const noexcept;
434 :
435 : /** Return the value of a field or a default if missing.
436 :
437 : @param id The field name constant.
438 :
439 : @param s The value to be returned if
440 : field does not exist.
441 : */
442 : BOOST_HTTP_PROTO_DECL
443 : core::string_view
444 : value_or(
445 : field id,
446 : core::string_view s) const noexcept;
447 :
448 : /** Return the value of a field or a default if missing.
449 :
450 : If `name` refers to a known field,
451 : it is faster to call @ref value_or
452 : with a field id instead of a string.
453 :
454 : @param name The field name.
455 :
456 : @param s The value to be returned if
457 : field does not exist.
458 : */
459 : BOOST_HTTP_PROTO_DECL
460 : core::string_view
461 : value_or(
462 : core::string_view name,
463 : core::string_view s) const noexcept;
464 :
465 : /** Return a forward range containing values for all matching fields.
466 :
467 : @param id The field name constant.
468 : */
469 : BOOST_HTTP_PROTO_DECL
470 : subrange
471 : find_all(field id) const noexcept;
472 :
473 : /** Return a forward range containing values for all matching fields.
474 :
475 : If `name` refers to a known field,
476 : it is faster to call @ref find_all
477 : with a field id instead of a string.
478 :
479 : @param name The field name.
480 : */
481 : BOOST_HTTP_PROTO_DECL
482 : subrange
483 : find_all(
484 : core::string_view name) const noexcept;
485 :
486 : //--------------------------------------------
487 : //
488 : // Capacity
489 : //
490 : //--------------------------------------------
491 :
492 : /** Return the maximum allowed capacity in bytes.
493 : */
494 : std::size_t
495 24 : max_capacity_in_bytes() noexcept
496 : {
497 24 : return max_cap_;
498 : }
499 :
500 : /** Return the total number of bytes allocated by the container.
501 : */
502 : std::size_t
503 105 : capacity_in_bytes() const noexcept
504 : {
505 105 : return h_.cap;
506 : }
507 :
508 : /** Clear contents while preserving the capacity.
509 :
510 : In the case of response and request
511 : containers the start-line also resets to
512 : default.
513 :
514 : @par Postconditions
515 : @code
516 : this->size() == 0
517 : @endcode
518 :
519 : @par Complexity
520 : Constant.
521 : */
522 : BOOST_HTTP_PROTO_DECL
523 : void
524 : clear() noexcept;
525 :
526 : /** Adjust the capacity without changing the size.
527 :
528 : This function adjusts the capacity
529 : of the container in bytes, without
530 : affecting the current contents. Has
531 : no effect if `n <= this->capacity_in_bytes()`.
532 :
533 : @par Postconditions
534 : @code
535 : this->capacity_in_bytes() >= n
536 : @endcode
537 :
538 : @par Exception Safety
539 : Strong guarantee.
540 : Calls to allocate may throw.
541 : Exception thrown if max capacity exceeded.
542 :
543 : @throw std::length_error
544 : Max capacity would be exceeded.
545 :
546 : @param n The capacity in bytes.
547 : */
548 : BOOST_HTTP_PROTO_DECL
549 : void
550 : reserve_bytes(std::size_t n);
551 :
552 : /** Set the maximum allowed capacity in bytes.
553 :
554 : Prevents the container from growing beyond
555 : `n` bytes. Exceeding this limit will throw
556 : an exception.
557 :
558 : @par Preconditions
559 : @code
560 : this->capacity_in_bytes() <= n
561 : @endcode
562 :
563 : @par Postconditions
564 : @code
565 : this->max_capacity_in_bytes() == n
566 : @endcode
567 :
568 : @par Exception Safety
569 : Strong guarantee.
570 : Exception thrown on invalid input.
571 :
572 : @throw std::invalid_argument
573 : `n < this->capacity_in_bytes()`
574 :
575 : @param n The maximum allowed capacity in bytes.
576 : */
577 : BOOST_HTTP_PROTO_DECL
578 : void
579 : set_max_capacity_in_bytes(std::size_t n);
580 :
581 : /** Remove excess capacity.
582 :
583 : @par Exception Safety
584 : Strong guarantee.
585 : Calls to allocate may throw.
586 : */
587 : BOOST_HTTP_PROTO_DECL
588 : void
589 : shrink_to_fit();
590 :
591 : //--------------------------------------------
592 : //
593 : // Modifiers
594 : //
595 : //--------------------------------------------
596 :
597 : /** Append a header.
598 :
599 : This function appends a new header.
600 : Existing headers with the same name are
601 : not changed.
602 :
603 : Any leading or trailing whitespace in the
604 : value is ignored.
605 :
606 : No iterators are invalidated.
607 :
608 : @par Example
609 : @code
610 : request req;
611 :
612 : req.append( field::user_agent, "Boost" );
613 : @endcode
614 :
615 : @par Complexity
616 : Linear in `to_string( id ).size() + value.size()`.
617 :
618 : @par Exception Safety
619 : Strong guarantee.
620 : Calls to allocate may throw.
621 : Exception thrown on invalid input.
622 : Exception thrown if max capacity exceeded.
623 :
624 : @throw system_error
625 : Input is invalid.
626 :
627 : @throw std::length_error
628 : Max capacity would be exceeded.
629 :
630 : @param id The field name constant.
631 :
632 : @param value The value which must be semantically
633 : valid for the message.
634 : */
635 : void
636 93 : append(
637 : field id,
638 : core::string_view value)
639 : {
640 93 : system::error_code ec;
641 93 : append(id, value, ec);
642 89 : if(ec.failed())
643 3 : detail::throw_system_error(ec);
644 86 : }
645 :
646 : /** Append a header.
647 :
648 : This function appends a new header.
649 : Existing headers with the same name are
650 : not changed.
651 :
652 : Any leading or trailing whitespace in the
653 : value is ignored.
654 :
655 : No iterators are invalidated.
656 :
657 : @par Example
658 : @code
659 : request req;
660 :
661 : req.append( field::user_agent, "Boost" );
662 : @endcode
663 :
664 : @par Complexity
665 : Linear in `to_string( id ).size() + value.size()`.
666 :
667 : @par Exception Safety
668 : Strong guarantee.
669 : Calls to allocate may throw.
670 : Exception thrown if max capacity exceeded.
671 :
672 : @throw std::length_error
673 : Max capacity would be exceeded.
674 :
675 : @param id The field name constant.
676 :
677 : @param value The value which must be semantically
678 : valid for the message.
679 :
680 : @param ec Set to the error if input is invalid.
681 : */
682 : void
683 93 : append(
684 : field id,
685 : core::string_view value,
686 : system::error_code& ec)
687 : {
688 93 : insert_impl(
689 : id,
690 : to_string(id),
691 : value,
692 93 : h_.count,
693 : ec);
694 89 : }
695 :
696 : /** Append a header.
697 :
698 : This function appends a new header.
699 : Existing headers with the same name are
700 : not changed.
701 :
702 : Any leading or trailing whitespace in the
703 : value is ignored.
704 :
705 : No iterators are invalidated.
706 :
707 : @par Example
708 : @code
709 : request req;
710 :
711 : req.append( "User-Agent", "Boost" );
712 : @endcode
713 :
714 : @par Complexity
715 : Linear in `name.size() + value.size()`.
716 :
717 : @par Exception Safety
718 : Strong guarantee.
719 : Calls to allocate may throw.
720 : Exception thrown on invalid input.
721 : Exception thrown if max capacity exceeded.
722 :
723 : @throw system_error
724 : Input is invalid.
725 :
726 : @throw std::length_error
727 : Max capacity would be exceeded.
728 :
729 : @param name The header name.
730 :
731 : @param value The header value, which must
732 : be semantically valid for the message.
733 : */
734 : void
735 48 : append(
736 : core::string_view name,
737 : core::string_view value)
738 : {
739 48 : system::error_code ec;
740 48 : append(name, value, ec);
741 46 : if(ec.failed())
742 1 : detail::throw_system_error(ec);
743 45 : }
744 :
745 : /** Append a header.
746 :
747 : This function appends a new header.
748 : Existing headers with the same name are
749 : not changed.
750 :
751 : Any leading or trailing whitespace in the
752 : value is ignored.
753 :
754 : No iterators are invalidated.
755 :
756 : @par Example
757 : @code
758 : request req;
759 :
760 : req.append( "User-Agent", "Boost" );
761 : @endcode
762 :
763 : @par Complexity
764 : Linear in `name.size() + value.size()`.
765 :
766 : @par Exception Safety
767 : Strong guarantee.
768 : Calls to allocate may throw.
769 : Exception thrown if max capacity exceeded.
770 :
771 : @throw std::length_error
772 : Max capacity would be exceeded.
773 :
774 : @param name The header name.
775 :
776 : @param value The value which must be semantically
777 : valid for the message.
778 :
779 : @param ec Set to the error if input is invalid.
780 : */
781 : void
782 61 : append(
783 : core::string_view name,
784 : core::string_view value,
785 : system::error_code& ec)
786 : {
787 61 : insert_impl(
788 : string_to_field(name),
789 : name,
790 : value,
791 61 : h_.count,
792 : ec);
793 59 : }
794 :
795 : /** Insert a header.
796 :
797 : If a matching header with the same name
798 : exists, it is not replaced. Instead, an
799 : additional header with the same name is
800 : inserted. Names are not case-sensitive.
801 : Any leading or trailing whitespace in
802 : the new value is ignored.
803 :
804 : All iterators that are equal to `before`
805 : or come after are invalidated.
806 :
807 : @par Example
808 : @code
809 : request req;
810 :
811 : req.insert( req.begin(), field::user_agent, "Boost" );
812 : @endcode
813 :
814 : @par Complexity
815 : Linear in `to_string( id ).size() + value.size()`.
816 :
817 : @par Exception Safety
818 : Strong guarantee.
819 : Calls to allocate may throw.
820 : Exception thrown on invalid input.
821 : Exception thrown if max capacity exceeded.
822 :
823 : @throw system_error
824 : Input is invalid.
825 :
826 : @throw std::length_error
827 : Max capacity would be exceeded.
828 :
829 : @return An iterator to the newly inserted header.
830 :
831 : @param before Position to insert before.
832 :
833 : @param id The field name constant.
834 :
835 : @param value The value which must be semantically
836 : valid for the message.
837 : */
838 : BOOST_HTTP_PROTO_DECL
839 : iterator
840 : insert(
841 : iterator before,
842 : field id,
843 : core::string_view value);
844 :
845 : /** Insert a header.
846 :
847 : If a matching header with the same name
848 : exists, it is not replaced. Instead, an
849 : additional header with the same name is
850 : inserted. Names are not case-sensitive.
851 :
852 : Any leading or trailing whitespace in
853 : the new value is ignored.
854 :
855 : All iterators that are equal to `before`
856 : or come after are invalidated.
857 :
858 : @par Example
859 : @code
860 : request req;
861 :
862 : req.insert( req.begin(), field::user_agent, "Boost" );
863 : @endcode
864 :
865 : @par Complexity
866 : Linear in `to_string( id ).size() + value.size()`.
867 :
868 : @par Exception Safety
869 : Strong guarantee.
870 : Calls to allocate may throw.
871 : Exception thrown if max capacity exceeded.
872 :
873 : @throw std::length_error
874 : Max capacity would be exceeded.
875 :
876 : @return An iterator to the newly inserted header.
877 :
878 : @param before Position to insert before.
879 :
880 : @param id The field name constant.
881 :
882 : @param value The value which must be semantically
883 : valid for the message.
884 :
885 : @param ec Set to the error if input is invalid.
886 : */
887 : BOOST_HTTP_PROTO_DECL
888 : iterator
889 : insert(
890 : iterator before,
891 : field id,
892 : core::string_view value,
893 : system::error_code& ec);
894 :
895 : /** Insert a header.
896 :
897 : If a matching header with the same name
898 : exists, it is not replaced. Instead, an
899 : additional header with the same name is
900 : inserted. Names are not case-sensitive.
901 :
902 : Any leading or trailing whitespace in
903 : the new value is ignored.
904 :
905 : All iterators that are equal to `before`
906 : or come after are invalidated.
907 :
908 : @par Example
909 : @code
910 : request req;
911 :
912 : req.insert( req.begin(), "User-Agent", "Boost" );
913 : @endcode
914 :
915 : @par Complexity
916 : Linear in `name.size() + value.size()`.
917 :
918 : @par Exception Safety
919 : Strong guarantee.
920 : Calls to allocate may throw.
921 : Exception thrown on invalid input.
922 : Exception thrown if max capacity exceeded.
923 :
924 : @throw system_error
925 : Input is invalid.
926 :
927 : @throw std::length_error
928 : Max capacity would be exceeded.
929 :
930 : @return An iterator to the newly inserted header.
931 :
932 : @param before Position to insert before.
933 :
934 : @param name The header name.
935 :
936 : @param value The value which must be semantically
937 : valid for the message.
938 : */
939 : BOOST_HTTP_PROTO_DECL
940 : iterator
941 : insert(
942 : iterator before,
943 : core::string_view name,
944 : core::string_view value);
945 :
946 : /** Insert a header.
947 :
948 : If a matching header with the same name
949 : exists, it is not replaced. Instead, an
950 : additional header with the same name is
951 : inserted. Names are not case-sensitive.
952 :
953 : Any leading or trailing whitespace in
954 : the new value is ignored.
955 :
956 : All iterators that are equal to `before`
957 : or come after are invalidated.
958 :
959 : @par Example
960 : @code
961 : request req;
962 :
963 : req.insert( req.begin(), "User-Agent", "Boost" );
964 : @endcode
965 :
966 : @par Complexity
967 : Linear in `name.size() + value.size()`.
968 :
969 : @par Exception Safety
970 : Strong guarantee.
971 : Calls to allocate may throw.
972 : Exception thrown if max capacity exceeded.
973 :
974 : @throw std::length_error
975 : Max capacity would be exceeded.
976 :
977 : @return An iterator to the newly inserted header.
978 :
979 : @param before Position to insert before.
980 :
981 : @param name The header name.
982 :
983 : @param value The value which must be semantically
984 : valid for the message.
985 :
986 : @param ec Set to the error if input is invalid.
987 : */
988 : BOOST_HTTP_PROTO_DECL
989 : iterator
990 : insert(
991 : iterator before,
992 : core::string_view name,
993 : core::string_view value,
994 : system::error_code& ec);
995 :
996 : //--------------------------------------------
997 :
998 : /** Erase headers.
999 :
1000 : This function removes the header pointed
1001 : to by `it`.
1002 :
1003 : All iterators that are equal to `it`
1004 : or come after are invalidated.
1005 :
1006 : @par Complexity
1007 : Linear in `name.size() + value.size()`.
1008 :
1009 : @return An iterator to one past the
1010 : removed element.
1011 :
1012 : @param it The iterator to the element
1013 : to erase.
1014 : */
1015 : BOOST_HTTP_PROTO_DECL
1016 : iterator
1017 : erase(iterator it) noexcept;
1018 :
1019 : /** Erase headers.
1020 :
1021 : This removes all headers whose name
1022 : constant is equal to `id`.
1023 :
1024 : If any headers are erased, then all
1025 : iterators equal to or that come after
1026 : the first erased element are invalidated.
1027 : Otherwise, no iterators are invalidated.
1028 :
1029 : @par Complexity
1030 : Linear in `this->string().size()`.
1031 :
1032 : @return The number of headers erased.
1033 :
1034 : @param id The field name constant.
1035 : */
1036 : BOOST_HTTP_PROTO_DECL
1037 : std::size_t
1038 : erase(field id) noexcept;
1039 :
1040 : /** Erase all matching fields.
1041 :
1042 : This removes all headers with a matching
1043 : name, using a case-insensitive comparison.
1044 :
1045 : If any headers are erased, then all
1046 : iterators equal to or that come after
1047 : the first erased element are invalidated.
1048 : Otherwise, no iterators are invalidated.
1049 :
1050 : @par Complexity
1051 : Linear in `this->string().size()`.
1052 :
1053 : @return The number of fields erased
1054 :
1055 : @param name The header name.
1056 : */
1057 : BOOST_HTTP_PROTO_DECL
1058 : std::size_t
1059 : erase(
1060 : core::string_view name) noexcept;
1061 :
1062 : //--------------------------------------------
1063 :
1064 : /** Set a header value.
1065 :
1066 : Uses the given value to overwrite the
1067 : current one in the header field pointed to
1068 : by the iterator. The value must be
1069 : syntactically valid or else an error is
1070 : returned.
1071 :
1072 : Any leading or trailing whitespace in the
1073 : new value is ignored.
1074 :
1075 : @par Complexity
1076 :
1077 : @par Exception Safety
1078 : Strong guarantee.
1079 : Calls to allocate may throw.
1080 : Exception thrown on invalid input.
1081 : Exception thrown if max capacity exceeded.
1082 :
1083 : @throw system_error
1084 : Input is invalid.
1085 :
1086 : @throw std::length_error
1087 : Max capacity would be exceeded.
1088 :
1089 : @param it The iterator to the header.
1090 :
1091 : @param value The value which must be semantically
1092 : valid for the message.
1093 : */
1094 : BOOST_HTTP_PROTO_DECL
1095 : void
1096 : set(iterator it, core::string_view value);
1097 :
1098 : /** Set a header value.
1099 :
1100 : Uses the given value to overwrite the
1101 : current one in the header field pointed to
1102 : by the iterator. The value must be
1103 : syntactically valid or else an error is
1104 : returned.
1105 :
1106 : Any leading or trailing whitespace in the
1107 : new value is ignored.
1108 :
1109 : @par Complexity
1110 :
1111 : @par Exception Safety
1112 : Strong guarantee.
1113 : Calls to allocate may throw.
1114 : Exception thrown if max capacity exceeded.
1115 :
1116 : @throw std::length_error
1117 : Max capacity would be exceeded.
1118 :
1119 : @param it The iterator to the header.
1120 :
1121 : @param value The value which must be semantically
1122 : valid for the message.
1123 :
1124 : @param ec Set to the error if input is invalid.
1125 : */
1126 : BOOST_HTTP_PROTO_DECL
1127 : void
1128 : set(
1129 : iterator it,
1130 : core::string_view value,
1131 : system::error_code& ec);
1132 :
1133 : /** Set a header value.
1134 :
1135 : The container is modified to contain
1136 : exactly one field with the specified id
1137 : set to the given value, which must be
1138 : syntactically valid or else an error is
1139 : returned.
1140 :
1141 : Any leading or trailing whitespace in the
1142 : new value is ignored.
1143 :
1144 : @par Postconditions
1145 : @code
1146 : this->count( id ) == 1 && this->at( id ) == value
1147 : @endcode
1148 :
1149 : @par Complexity
1150 :
1151 : @par Exception Safety
1152 : Strong guarantee.
1153 : Calls to allocate may throw.
1154 : Exception thrown on invalid input.
1155 : Exception thrown if max capacity exceeded.
1156 :
1157 : @throw system_error
1158 : Input is invalid.
1159 :
1160 : @throw std::length_error
1161 : Max capacity would be exceeded.
1162 :
1163 : @param id The field constant of the header
1164 : to set.
1165 :
1166 : @param value The value which must be semantically
1167 : valid for the message.
1168 : */
1169 : void
1170 105 : set(
1171 : field id,
1172 : core::string_view value)
1173 : {
1174 105 : system::error_code ec;
1175 105 : set(id, value, ec);
1176 105 : if(ec.failed())
1177 2 : detail::throw_system_error(ec);
1178 103 : }
1179 :
1180 : /** Set a header value.
1181 :
1182 : The container is modified to contain
1183 : exactly one field with the specified id
1184 : set to the given value, which must be
1185 : syntactically valid or else an error is
1186 : returned.
1187 :
1188 : Any leading or trailing whitespace in the
1189 : new value is ignored.
1190 :
1191 : @par Postconditions
1192 : @code
1193 : this->count( id ) == 1 && this->at( id ) == value
1194 : @endcode
1195 :
1196 : @par Complexity
1197 :
1198 : @par Exception Safety
1199 : Strong guarantee.
1200 : Calls to allocate may throw.
1201 : Exception thrown if max capacity exceeded.
1202 :
1203 : @throw std::length_error
1204 : Max capacity would be exceeded.
1205 :
1206 : @param id The field name constant.
1207 :
1208 : @param value The value which must be semantically
1209 : valid for the message.
1210 :
1211 : @param ec Set to the error if input is invalid.
1212 : */
1213 : BOOST_HTTP_PROTO_DECL
1214 : void
1215 : set(
1216 : field id,
1217 : core::string_view value,
1218 : system::error_code& ec);
1219 :
1220 : /** Set a header value.
1221 :
1222 : The container is modified to contain
1223 : exactly one field with the specified name
1224 : set to the given value, which must be
1225 : syntactically valid or else an error is
1226 : returned.
1227 :
1228 : Any leading or trailing whitespace in the
1229 : new value is ignored.
1230 :
1231 : @par Postconditions
1232 : @code
1233 : this->count( name ) == 1 && this->at( name ) == value
1234 : @endcode
1235 :
1236 : @par Complexity
1237 :
1238 : @par Exception Safety
1239 : Strong guarantee.
1240 : Calls to allocate may throw.
1241 : Exception thrown on invalid input.
1242 : Exception thrown if max capacity exceeded.
1243 :
1244 : @throw system_error
1245 : Input is invalid.
1246 :
1247 : @throw std::length_error
1248 : Max capacity would be exceeded.
1249 :
1250 : @param name The field name.
1251 :
1252 : @param value The value which must be semantically
1253 : valid for the message.
1254 : */
1255 : void
1256 28 : set(
1257 : core::string_view name,
1258 : core::string_view value)
1259 : {
1260 28 : system::error_code ec;
1261 28 : set(name, value, ec);
1262 27 : if(ec.failed())
1263 4 : detail::throw_system_error(ec);
1264 23 : }
1265 :
1266 : /** Set a header value.
1267 :
1268 : The container is modified to contain
1269 : exactly one field with the specified name
1270 : set to the given value, which must be
1271 : syntactically valid or else an error is
1272 : returned.
1273 :
1274 : Any leading or trailing whitespace in the
1275 : new value is ignored.
1276 :
1277 : @par Postconditions
1278 : @code
1279 : this->count( name ) == 1 && this->at( name ) == value
1280 : @endcode
1281 :
1282 : @par Complexity
1283 :
1284 : @par Exception Safety
1285 : Strong guarantee.
1286 : Calls to allocate may throw.
1287 : Exception thrown if max capacity exceeded.
1288 :
1289 : @throw std::length_error
1290 : Max capacity would be exceeded.
1291 :
1292 : @param name The field name.
1293 :
1294 : @param value The value which must be semantically
1295 : valid for the message.
1296 :
1297 : @param ec Set to the error if input is invalid.
1298 : */
1299 : BOOST_HTTP_PROTO_DECL
1300 : void
1301 : set(
1302 : core::string_view name,
1303 : core::string_view value,
1304 : system::error_code& ec);
1305 :
1306 : private:
1307 : BOOST_HTTP_PROTO_DECL
1308 : void
1309 : copy_impl(
1310 : detail::header const&);
1311 :
1312 : BOOST_HTTP_PROTO_DECL
1313 : void
1314 : insert_impl(
1315 : optional<field> id,
1316 : core::string_view name,
1317 : core::string_view value,
1318 : std::size_t before,
1319 : system::error_code& ec);
1320 :
1321 : void
1322 : insert_unchecked(
1323 : optional<field> id,
1324 : core::string_view name,
1325 : core::string_view value,
1326 : std::size_t before,
1327 : bool has_obs_fold);
1328 :
1329 : void
1330 : raw_erase(
1331 : std::size_t) noexcept;
1332 :
1333 : void
1334 : raw_erase_n(field, std::size_t) noexcept;
1335 :
1336 : std::size_t
1337 : erase_all(
1338 : std::size_t i0,
1339 : field id) noexcept;
1340 :
1341 : std::size_t
1342 : erase_all(
1343 : std::size_t i0,
1344 : core::string_view name) noexcept;
1345 :
1346 : std::size_t
1347 : offset(
1348 : std::size_t i) const noexcept;
1349 :
1350 : std::size_t
1351 : length(
1352 : std::size_t i) const noexcept;
1353 : };
1354 :
1355 : /** Format the container to the output stream
1356 :
1357 : This function serializes the container to
1358 : the specified output stream.
1359 :
1360 : @par Example
1361 : @code
1362 : request req;
1363 : std::stringstream ss;
1364 : ss << req;
1365 : assert( ss.str() == "GET / HTTP/1.1\r\n\r\n" );
1366 : @endcode
1367 :
1368 : @par Effects
1369 : @code
1370 : return os << f.buffer();
1371 : @endcode
1372 :
1373 : @par Complexity
1374 : Linear in `f.buffer().size()`
1375 :
1376 : @par Exception Safety
1377 : Basic guarantee.
1378 :
1379 : @return A reference to the output stream, for chaining
1380 :
1381 : @param os The output stream to write to.
1382 :
1383 : @param f The container to write.
1384 : */
1385 : BOOST_HTTP_PROTO_DECL
1386 : std::ostream&
1387 : operator<<(
1388 : std::ostream& os,
1389 : const fields_base& f);
1390 :
1391 : } // http_proto
1392 : } // boost
1393 :
1394 : #include <boost/http_proto/impl/fields_base.hpp>
1395 :
1396 : #endif
|