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