]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/http/fields.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / beast / http / fields.hpp
1 //
2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot 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/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_HTTP_FIELDS_HPP
11 #define BOOST_BEAST_HTTP_FIELDS_HPP
12
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/string_param.hpp>
15 #include <boost/beast/core/string.hpp>
16 #include <boost/beast/core/detail/allocator.hpp>
17 #include <boost/beast/http/field.hpp>
18 #include <boost/asio/buffer.hpp>
19 #include <boost/intrusive/list.hpp>
20 #include <boost/intrusive/set.hpp>
21 #include <boost/optional.hpp>
22 #include <algorithm>
23 #include <cctype>
24 #include <cstring>
25 #include <memory>
26 #include <string>
27 #include <type_traits>
28 #include <utility>
29
30 namespace boost {
31 namespace beast {
32 namespace http {
33
34 /** A container for storing HTTP header fields.
35
36 This container is designed to store the field value pairs that make
37 up the fields and trailers in an HTTP message. Objects of this type
38 are iterable, with each element holding the field name and field
39 value.
40
41 Field names are stored as-is, but comparisons are case-insensitive.
42 The container behaves as a `std::multiset`; there will be a separate
43 value for each occurrence of the same field name. When the container
44 is iterated the fields are presented in the order of insertion, with
45 fields having the same name following each other consecutively.
46
47 Meets the requirements of @b Fields
48
49 @tparam Allocator The allocator to use. This must meet the
50 requirements of @b Allocator.
51 */
52 template<class Allocator>
53 class basic_fields
54 {
55 friend class fields_test; // for `header`
56
57 static std::size_t constexpr max_static_buffer = 4096;
58
59 using off_t = std::uint16_t;
60
61 public:
62 /// The type of allocator used.
63 using allocator_type = Allocator;
64
65 /// The type of element used to represent a field
66 class value_type
67 {
68 friend class basic_fields;
69
70 boost::asio::const_buffer
71 buffer() const;
72
73 value_type(field name,
74 string_view sname, string_view value);
75
76 boost::intrusive::list_member_hook<
77 boost::intrusive::link_mode<
78 boost::intrusive::normal_link>>
79 list_hook_;
80 boost::intrusive::set_member_hook<
81 boost::intrusive::link_mode<
82 boost::intrusive::normal_link>>
83 set_hook_;
84 off_t off_;
85 off_t len_;
86 field f_;
87
88 public:
89 /// Constructor (deleted)
90 value_type(value_type const&) = delete;
91
92 /// Assignment (deleted)
93 value_type& operator=(value_type const&) = delete;
94
95 /// Returns the field enum, which can be @ref field::unknown
96 field const
97 name() const;
98
99 /// Returns the field name as a string
100 string_view const
101 name_string() const;
102
103 /// Returns the value of the field
104 string_view const
105 value() const;
106 };
107
108 /** A strictly less predicate for comparing keys, using a case-insensitive comparison.
109
110 The case-comparison operation is defined only for low-ASCII characters.
111 */
112 struct key_compare : beast::iless
113 {
114 /// Returns `true` if lhs is less than rhs using a strict ordering
115 template<class String>
116 bool
117 operator()(
118 String const& lhs,
119 value_type const& rhs) const noexcept
120 {
121 if(lhs.size() < rhs.name_string().size())
122 return true;
123 if(lhs.size() > rhs.name_string().size())
124 return false;
125 return iless::operator()(lhs, rhs.name_string());
126 }
127
128 /// Returns `true` if lhs is less than rhs using a strict ordering
129 template<class String>
130 bool
131 operator()(
132 value_type const& lhs,
133 String const& rhs) const noexcept
134 {
135 if(lhs.name_string().size() < rhs.size())
136 return true;
137 if(lhs.name_string().size() > rhs.size())
138 return false;
139 return iless::operator()(lhs.name_string(), rhs);
140 }
141
142 /// Returns `true` if lhs is less than rhs using a strict ordering
143 bool
144 operator()(
145 value_type const& lhs,
146 value_type const& rhs) const noexcept
147 {
148 if(lhs.name_string().size() < rhs.name_string().size())
149 return true;
150 if(lhs.name_string().size() > rhs.name_string().size())
151 return false;
152 return iless::operator()(lhs.name_string(), rhs.name_string());
153 }
154 };
155
156 /// The algorithm used to serialize the header
157 #if BOOST_BEAST_DOXYGEN
158 using writer = implementation_defined;
159 #else
160 class writer;
161 #endif
162
163 private:
164 using list_t = typename boost::intrusive::make_list<
165 value_type, boost::intrusive::member_hook<
166 value_type, boost::intrusive::list_member_hook<
167 boost::intrusive::link_mode<
168 boost::intrusive::normal_link>>,
169 &value_type::list_hook_>,
170 boost::intrusive::constant_time_size<
171 false>>::type;
172
173 using set_t = typename boost::intrusive::make_multiset<
174 value_type, boost::intrusive::member_hook<value_type,
175 boost::intrusive::set_member_hook<
176 boost::intrusive::link_mode<
177 boost::intrusive::normal_link>>,
178 &value_type::set_hook_>,
179 boost::intrusive::constant_time_size<true>,
180 boost::intrusive::compare<key_compare>>::type;
181
182
183 public:
184 /// Destructor
185 ~basic_fields();
186
187 /// Constructor.
188 basic_fields() = default;
189
190 /** Constructor.
191
192 @param alloc The allocator to use.
193 */
194 explicit
195 basic_fields(Allocator const& alloc);
196
197 /** Move constructor.
198
199 The state of the moved-from object is
200 as if constructed using the same allocator.
201 */
202 basic_fields(basic_fields&&);
203
204 /** Move constructor.
205
206 The state of the moved-from object is
207 as if constructed using the same allocator.
208
209 @param alloc The allocator to use.
210 */
211 basic_fields(basic_fields&&, Allocator const& alloc);
212
213 /// Copy constructor.
214 basic_fields(basic_fields const&);
215
216 /** Copy constructor.
217
218 @param alloc The allocator to use.
219 */
220 basic_fields(basic_fields const&, Allocator const& alloc);
221
222 /// Copy constructor.
223 template<class OtherAlloc>
224 basic_fields(basic_fields<OtherAlloc> const&);
225
226 /** Copy constructor.
227
228 @param alloc The allocator to use.
229 */
230 template<class OtherAlloc>
231 basic_fields(basic_fields<OtherAlloc> const&,
232 Allocator const& alloc);
233
234 /** Move assignment.
235
236 The state of the moved-from object is
237 as if constructed using the same allocator.
238 */
239 basic_fields& operator=(basic_fields&&);
240
241 /// Copy assignment.
242 basic_fields& operator=(basic_fields const&);
243
244 /// Copy assignment.
245 template<class OtherAlloc>
246 basic_fields& operator=(basic_fields<OtherAlloc> const&);
247
248 public:
249 /// A constant iterator to the field sequence.
250 #if BOOST_BEAST_DOXYGEN
251 using const_iterator = implementation_defined;
252 #else
253 using const_iterator = typename list_t::const_iterator;
254 #endif
255
256 /// A constant iterator to the field sequence.
257 using iterator = const_iterator;
258
259 /// Return a copy of the allocator associated with the container.
260 allocator_type
261 get_allocator() const
262 {
263 return alloc_;
264 }
265
266 //--------------------------------------------------------------------------
267 //
268 // Element access
269 //
270 //--------------------------------------------------------------------------
271
272 /** Returns the value for a field, or throws an exception.
273
274 If more than one field with the specified name exists, the
275 first field defined by insertion order is returned.
276
277 @param name The name of the field.
278
279 @return The field value.
280
281 @throws std::out_of_range if the field is not found.
282 */
283 string_view const
284 at(field name) const;
285
286 /** Returns the value for a field, or throws an exception.
287
288 If more than one field with the specified name exists, the
289 first field defined by insertion order is returned.
290
291 @param name The name of the field.
292
293 @return The field value.
294
295 @throws std::out_of_range if the field is not found.
296 */
297 string_view const
298 at(string_view name) const;
299
300 /** Returns the value for a field, or `""` if it does not exist.
301
302 If more than one field with the specified name exists, the
303 first field defined by insertion order is returned.
304
305 @param name The name of the field.
306 */
307 string_view const
308 operator[](field name) const;
309
310 /** Returns the value for a case-insensitive matching header, or `""` if it does not exist.
311
312 If more than one field with the specified name exists, the
313 first field defined by insertion order is returned.
314
315 @param name The name of the field.
316 */
317 string_view const
318 operator[](string_view name) const;
319
320 //--------------------------------------------------------------------------
321 //
322 // Iterators
323 //
324 //--------------------------------------------------------------------------
325
326 /// Return a const iterator to the beginning of the field sequence.
327 const_iterator
328 begin() const
329 {
330 return list_.cbegin();
331 }
332
333 /// Return a const iterator to the end of the field sequence.
334 const_iterator
335 end() const
336 {
337 return list_.cend();
338 }
339
340 /// Return a const iterator to the beginning of the field sequence.
341 const_iterator
342 cbegin() const
343 {
344 return list_.cbegin();
345 }
346
347 /// Return a const iterator to the end of the field sequence.
348 const_iterator
349 cend() const
350 {
351 return list_.cend();
352 }
353
354 //--------------------------------------------------------------------------
355 //
356 // Capacity
357 //
358 //--------------------------------------------------------------------------
359
360 private:
361 // VFALCO Since the header and message derive from Fields,
362 // what does the expression m.empty() mean? Its confusing.
363 bool
364 empty() const
365 {
366 return list_.empty();
367 }
368 public:
369
370 //--------------------------------------------------------------------------
371 //
372 // Modifiers
373 //
374 //--------------------------------------------------------------------------
375
376 /** Remove all fields from the container
377
378 All references, pointers, or iterators referring to contained
379 elements are invalidated. All past-the-end iterators are also
380 invalidated.
381
382 @par Postconditions:
383 @code
384 std::distance(this->begin(), this->end()) == 0
385 @endcode
386 */
387 void
388 clear();
389
390 /** Insert a field.
391
392 If one or more fields with the same name already exist,
393 the new field will be inserted after the last field with
394 the matching name, in serialization order.
395
396 @param name The field name.
397
398 @param value The value of the field, as a @ref string_param
399 */
400 void
401 insert(field name, string_param const& value);
402
403 /** Insert a field.
404
405 If one or more fields with the same name already exist,
406 the new field will be inserted after the last field with
407 the matching name, in serialization order.
408
409 @param name The field name.
410
411 @param value The value of the field, as a @ref string_param
412 */
413 void
414 insert(string_view name, string_param const& value);
415
416 /** Insert a field.
417
418 If one or more fields with the same name already exist,
419 the new field will be inserted after the last field with
420 the matching name, in serialization order.
421
422 @param name The field name.
423
424 @param name_string The literal text corresponding to the
425 field name. If `name != field::unknown`, then this value
426 must be equal to `to_string(name)` using a case-insensitive
427 comparison, otherwise the behavior is undefined.
428
429 @param value The value of the field, as a @ref string_param
430 */
431 void
432 insert(field name, string_view name_string,
433 string_param const& value);
434
435 /** Set a field value, removing any other instances of that field.
436
437 First removes any values with matching field names, then
438 inserts the new field value.
439
440 @param name The field name.
441
442 @param value The value of the field, as a @ref string_param
443
444 @return The field value.
445 */
446 void
447 set(field name, string_param const& value);
448
449 /** Set a field value, removing any other instances of that field.
450
451 First removes any values with matching field names, then
452 inserts the new field value.
453
454 @param name The field name.
455
456 @param value The value of the field, as a @ref string_param
457 */
458 void
459 set(string_view name, string_param const& value);
460
461 /** Remove a field.
462
463 References and iterators to the erased elements are
464 invalidated. Other references and iterators are not
465 affected.
466
467 @param pos An iterator to the element to remove.
468
469 @return An iterator following the last removed element.
470 If the iterator refers to the last element, the end()
471 iterator is returned.
472 */
473 const_iterator
474 erase(const_iterator pos);
475
476 /** Remove all fields with the specified name.
477
478 All fields with the same field name are erased from the
479 container.
480 References and iterators to the erased elements are
481 invalidated. Other references and iterators are not
482 affected.
483
484 @param name The field name.
485
486 @return The number of fields removed.
487 */
488 std::size_t
489 erase(field name);
490
491 /** Remove all fields with the specified name.
492
493 All fields with the same field name are erased from the
494 container.
495 References and iterators to the erased elements are
496 invalidated. Other references and iterators are not
497 affected.
498
499 @param name The field name.
500
501 @return The number of fields removed.
502 */
503 std::size_t
504 erase(string_view name);
505
506 /** Return a buffer sequence representing the trailers.
507
508 This function returns a buffer sequence holding the
509 serialized representation of the trailer fields promised
510 in the Accept field. Before calling this function the
511 Accept field must contain the exact trailer fields
512 desired. Each field must also exist.
513 */
514
515
516 /// Swap this container with another
517 void
518 swap(basic_fields& other);
519
520 /// Swap two field containers
521 template<class Alloc>
522 friend
523 void
524 swap(basic_fields<Alloc>& lhs, basic_fields<Alloc>& rhs);
525
526 //--------------------------------------------------------------------------
527 //
528 // Lookup
529 //
530 //--------------------------------------------------------------------------
531
532 /** Return the number of fields with the specified name.
533
534 @param name The field name.
535 */
536 std::size_t
537 count(field name) const;
538
539 /** Return the number of fields with the specified name.
540
541 @param name The field name.
542 */
543 std::size_t
544 count(string_view name) const;
545
546 /** Returns an iterator to the case-insensitive matching field.
547
548 If more than one field with the specified name exists, the
549 first field defined by insertion order is returned.
550
551 @param name The field name.
552
553 @return An iterator to the matching field, or `end()` if
554 no match was found.
555 */
556 const_iterator
557 find(field name) const;
558
559 /** Returns an iterator to the case-insensitive matching field name.
560
561 If more than one field with the specified name exists, the
562 first field defined by insertion order is returned.
563
564 @param name The field name.
565
566 @return An iterator to the matching field, or `end()` if
567 no match was found.
568 */
569 const_iterator
570 find(string_view name) const;
571
572 /** Returns a range of iterators to the fields with the specified name.
573
574 @param name The field name.
575
576 @return A range of iterators to fields with the same name,
577 otherwise an empty range.
578 */
579 std::pair<const_iterator, const_iterator>
580 equal_range(field name) const;
581
582 /** Returns a range of iterators to the fields with the specified name.
583
584 @param name The field name.
585
586 @return A range of iterators to fields with the same name,
587 otherwise an empty range.
588 */
589 std::pair<const_iterator, const_iterator>
590 equal_range(string_view name) const;
591
592 //--------------------------------------------------------------------------
593 //
594 // Observers
595 //
596 //--------------------------------------------------------------------------
597
598 /// Returns a copy of the key comparison function
599 key_compare
600 key_comp() const
601 {
602 return key_compare{};
603 }
604
605 protected:
606 /** Returns the request-method string.
607
608 @note Only called for requests.
609 */
610 string_view
611 get_method_impl() const;
612
613 /** Returns the request-target string.
614
615 @note Only called for requests.
616 */
617 string_view
618 get_target_impl() const;
619
620 /** Returns the response reason-phrase string.
621
622 @note Only called for responses.
623 */
624 string_view
625 get_reason_impl() const;
626
627 /** Returns the chunked Transfer-Encoding setting
628 */
629 bool
630 get_chunked_impl() const;
631
632 /** Returns the keep-alive setting
633 */
634 bool
635 get_keep_alive_impl(unsigned version) const;
636
637 /** Returns `true` if the Content-Length field is present.
638 */
639 bool
640 has_content_length_impl() const;
641
642 /** Set or clear the method string.
643
644 @note Only called for requests.
645 */
646 void
647 set_method_impl(string_view s);
648
649 /** Set or clear the target string.
650
651 @note Only called for requests.
652 */
653 void
654 set_target_impl(string_view s);
655
656 /** Set or clear the reason string.
657
658 @note Only called for responses.
659 */
660 void
661 set_reason_impl(string_view s);
662
663 /** Adjusts the chunked Transfer-Encoding value
664 */
665 void
666 set_chunked_impl(bool value);
667
668 /** Sets or clears the Content-Length field
669 */
670 void
671 set_content_length_impl(
672 boost::optional<std::uint64_t> const& value);
673
674 /** Adjusts the Connection field
675 */
676 void
677 set_keep_alive_impl(
678 unsigned version, bool keep_alive);
679
680 private:
681 template<class OtherAlloc>
682 friend class basic_fields;
683
684 using base_alloc_type = typename
685 beast::detail::allocator_traits<Allocator>::
686 template rebind_alloc<value_type>;
687
688 using alloc_traits =
689 beast::detail::allocator_traits<base_alloc_type>;
690
691 using size_type = typename
692 beast::detail::allocator_traits<Allocator>::size_type;
693
694 value_type&
695 new_element(field name,
696 string_view sname, string_view value);
697
698 void
699 delete_element(value_type& e);
700
701 void
702 set_element(value_type& e);
703
704 void
705 realloc_string(string_view& dest, string_view s);
706
707 void
708 realloc_target(
709 string_view& dest, string_view s);
710
711 template<class OtherAlloc>
712 void
713 copy_all(basic_fields<OtherAlloc> const&);
714
715 void
716 clear_all();
717
718 void
719 delete_list();
720
721 void
722 move_assign(basic_fields&, std::true_type);
723
724 void
725 move_assign(basic_fields&, std::false_type);
726
727 void
728 copy_assign(basic_fields const&, std::true_type);
729
730 void
731 copy_assign(basic_fields const&, std::false_type);
732
733 void
734 swap(basic_fields& other, std::true_type);
735
736 void
737 swap(basic_fields& other, std::false_type);
738
739 base_alloc_type alloc_;
740 set_t set_;
741 list_t list_;
742 string_view method_;
743 string_view target_or_reason_;
744 };
745
746 /// A typical HTTP header fields container
747 using fields = basic_fields<std::allocator<char>>;
748
749 } // http
750 } // beast
751 } // boost
752
753 #include <boost/beast/http/impl/fields.ipp>
754
755 #endif