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