]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // Copyright (c) 2013-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 | ||
8 | #ifndef BEAST_HTTP_BASIC_FIELDS_HPP | |
9 | #define BEAST_HTTP_BASIC_FIELDS_HPP | |
10 | ||
11 | #include <beast/config.hpp> | |
12 | #include <beast/core/detail/empty_base_optimization.hpp> | |
13 | #include <beast/http/detail/basic_fields.hpp> | |
14 | #include <boost/lexical_cast.hpp> | |
15 | #include <algorithm> | |
16 | #include <cctype> | |
17 | #include <memory> | |
18 | #include <string> | |
19 | #include <type_traits> | |
20 | #include <utility> | |
21 | ||
22 | namespace beast { | |
23 | namespace http { | |
24 | ||
25 | /** A container for storing HTTP header fields. | |
26 | ||
27 | This container is designed to store the field value pairs that make | |
28 | up the fields and trailers in a HTTP message. Objects of this type | |
29 | are iterable, with each element holding the field name and field | |
30 | value. | |
31 | ||
32 | Field names are stored as-is, but comparisons are case-insensitive. | |
33 | When the container is iterated, the fields are presented in the order | |
34 | of insertion. For fields with the same name, the container behaves | |
35 | as a `std::multiset`; there will be a separate value for each occurrence | |
36 | of the field name. | |
37 | ||
38 | @note Meets the requirements of @b FieldSequence. | |
39 | */ | |
40 | template<class Allocator> | |
41 | class basic_fields : | |
42 | #if ! BEAST_DOXYGEN | |
43 | private beast::detail::empty_base_optimization< | |
44 | typename std::allocator_traits<Allocator>:: | |
45 | template rebind_alloc< | |
46 | detail::basic_fields_base::element>>, | |
47 | #endif | |
48 | public detail::basic_fields_base | |
49 | { | |
50 | using alloc_type = typename | |
51 | std::allocator_traits<Allocator>:: | |
52 | template rebind_alloc< | |
53 | detail::basic_fields_base::element>; | |
54 | ||
55 | using alloc_traits = | |
56 | std::allocator_traits<alloc_type>; | |
57 | ||
58 | using size_type = | |
59 | typename std::allocator_traits<Allocator>::size_type; | |
60 | ||
61 | void | |
62 | delete_all(); | |
63 | ||
64 | void | |
65 | move_assign(basic_fields&, std::false_type); | |
66 | ||
67 | void | |
68 | move_assign(basic_fields&, std::true_type); | |
69 | ||
70 | void | |
71 | copy_assign(basic_fields const&, std::false_type); | |
72 | ||
73 | void | |
74 | copy_assign(basic_fields const&, std::true_type); | |
75 | ||
76 | template<class FieldSequence> | |
77 | void | |
78 | copy_from(FieldSequence const& fs) | |
79 | { | |
80 | for(auto const& e : fs) | |
81 | insert(e.first, e.second); | |
82 | } | |
83 | ||
84 | public: | |
85 | /// The type of allocator used. | |
86 | using allocator_type = Allocator; | |
87 | ||
88 | /** The value type of the field sequence. | |
89 | ||
90 | Meets the requirements of @b Field. | |
91 | */ | |
92 | #if BEAST_DOXYGEN | |
93 | using value_type = implementation_defined; | |
94 | #endif | |
95 | ||
96 | /// A const iterator to the field sequence | |
97 | #if BEAST_DOXYGEN | |
98 | using iterator = implementation_defined; | |
99 | #endif | |
100 | ||
101 | /// A const iterator to the field sequence | |
102 | #if BEAST_DOXYGEN | |
103 | using const_iterator = implementation_defined; | |
104 | #endif | |
105 | ||
106 | /// Default constructor. | |
107 | basic_fields() = default; | |
108 | ||
109 | /// Destructor | |
110 | ~basic_fields(); | |
111 | ||
112 | /** Construct the fields. | |
113 | ||
114 | @param alloc The allocator to use. | |
115 | */ | |
116 | explicit | |
117 | basic_fields(Allocator const& alloc); | |
118 | ||
119 | /** Move constructor. | |
120 | ||
121 | The moved-from object becomes an empty field sequence. | |
122 | ||
123 | @param other The object to move from. | |
124 | */ | |
125 | basic_fields(basic_fields&& other); | |
126 | ||
127 | /** Move assignment. | |
128 | ||
129 | The moved-from object becomes an empty field sequence. | |
130 | ||
131 | @param other The object to move from. | |
132 | */ | |
133 | basic_fields& operator=(basic_fields&& other); | |
134 | ||
135 | /// Copy constructor. | |
136 | basic_fields(basic_fields const&); | |
137 | ||
138 | /// Copy assignment. | |
139 | basic_fields& operator=(basic_fields const&); | |
140 | ||
141 | /// Copy constructor. | |
142 | template<class OtherAlloc> | |
143 | basic_fields(basic_fields<OtherAlloc> const&); | |
144 | ||
145 | /// Copy assignment. | |
146 | template<class OtherAlloc> | |
147 | basic_fields& operator=(basic_fields<OtherAlloc> const&); | |
148 | ||
149 | /// Construct from a field sequence. | |
150 | template<class FwdIt> | |
151 | basic_fields(FwdIt first, FwdIt last); | |
152 | ||
153 | /// Returns `true` if the field sequence contains no elements. | |
154 | bool | |
155 | empty() const | |
156 | { | |
157 | return set_.empty(); | |
158 | } | |
159 | ||
160 | /// Returns the number of elements in the field sequence. | |
161 | std::size_t | |
162 | size() const | |
163 | { | |
164 | return set_.size(); | |
165 | } | |
166 | ||
167 | /// Returns a const iterator to the beginning of the field sequence. | |
168 | const_iterator | |
169 | begin() const | |
170 | { | |
171 | return list_.cbegin(); | |
172 | } | |
173 | ||
174 | /// Returns a const iterator to the end of the field sequence. | |
175 | const_iterator | |
176 | end() const | |
177 | { | |
178 | return list_.cend(); | |
179 | } | |
180 | ||
181 | /// Returns a const iterator to the beginning of the field sequence. | |
182 | const_iterator | |
183 | cbegin() const | |
184 | { | |
185 | return list_.cbegin(); | |
186 | } | |
187 | ||
188 | /// Returns a const iterator to the end of the field sequence. | |
189 | const_iterator | |
190 | cend() const | |
191 | { | |
192 | return list_.cend(); | |
193 | } | |
194 | ||
195 | /// Returns `true` if the specified field exists. | |
196 | bool | |
197 | exists(boost::string_ref const& name) const | |
198 | { | |
199 | return set_.find(name, less{}) != set_.end(); | |
200 | } | |
201 | ||
202 | /// Returns the number of values for the specified field. | |
203 | std::size_t | |
204 | count(boost::string_ref const& name) const; | |
205 | ||
206 | /** Returns an iterator to the case-insensitive matching field name. | |
207 | ||
208 | If more than one field with the specified name exists, the | |
209 | first field defined by insertion order is returned. | |
210 | */ | |
211 | iterator | |
212 | find(boost::string_ref const& name) const; | |
213 | ||
214 | /** Returns the value for a case-insensitive matching header, or `""`. | |
215 | ||
216 | If more than one field with the specified name exists, the | |
217 | first field defined by insertion order is returned. | |
218 | */ | |
219 | boost::string_ref | |
220 | operator[](boost::string_ref const& name) const; | |
221 | ||
222 | /// Clear the contents of the basic_fields. | |
223 | void | |
224 | clear() noexcept; | |
225 | ||
226 | /** Remove a field. | |
227 | ||
228 | If more than one field with the specified name exists, all | |
229 | matching fields will be removed. | |
230 | ||
231 | @param name The name of the field(s) to remove. | |
232 | ||
233 | @return The number of fields removed. | |
234 | */ | |
235 | std::size_t | |
236 | erase(boost::string_ref const& name); | |
237 | ||
238 | /** Insert a field value. | |
239 | ||
240 | If a field with the same name already exists, the | |
241 | existing field is untouched and a new field value pair | |
242 | is inserted into the container. | |
243 | ||
244 | @param name The name of the field. | |
245 | ||
246 | @param value A string holding the value of the field. | |
247 | */ | |
248 | void | |
249 | insert(boost::string_ref const& name, boost::string_ref value); | |
250 | ||
251 | /** Insert a field value. | |
252 | ||
253 | If a field with the same name already exists, the | |
254 | existing field is untouched and a new field value pair | |
255 | is inserted into the container. | |
256 | ||
257 | @param name The name of the field | |
258 | ||
259 | @param value The value of the field. The object will be | |
260 | converted to a string using `boost::lexical_cast`. | |
261 | */ | |
262 | template<class T> | |
263 | typename std::enable_if< | |
264 | ! std::is_constructible<boost::string_ref, T>::value>::type | |
265 | insert(boost::string_ref name, T const& value) | |
266 | { | |
267 | insert(name, boost::lexical_cast<std::string>(value)); | |
268 | } | |
269 | ||
270 | /** Replace a field value. | |
271 | ||
272 | First removes any values with matching field names, then | |
273 | inserts the new field value. | |
274 | ||
275 | @param name The name of the field. | |
276 | ||
277 | @param value A string holding the value of the field. | |
278 | */ | |
279 | void | |
280 | replace(boost::string_ref const& name, boost::string_ref value); | |
281 | ||
282 | /** Replace a field value. | |
283 | ||
284 | First removes any values with matching field names, then | |
285 | inserts the new field value. | |
286 | ||
287 | @param name The name of the field | |
288 | ||
289 | @param value The value of the field. The object will be | |
290 | converted to a string using `boost::lexical_cast`. | |
291 | */ | |
292 | template<class T> | |
293 | typename std::enable_if< | |
294 | ! std::is_constructible<boost::string_ref, T>::value>::type | |
295 | replace(boost::string_ref const& name, T const& value) | |
296 | { | |
297 | replace(name, | |
298 | boost::lexical_cast<std::string>(value)); | |
299 | } | |
300 | }; | |
301 | ||
302 | } // http | |
303 | } // beast | |
304 | ||
305 | #include <beast/http/impl/basic_fields.ipp> | |
306 | ||
307 | #endif |