]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/http/detail/rfc7230.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / beast / http / detail / rfc7230.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_DETAIL_RFC7230_HPP
11 #define BOOST_BEAST_HTTP_DETAIL_RFC7230_HPP
12
13 #include <boost/beast/core/string.hpp>
14 #include <iterator>
15 #include <utility>
16
17 namespace boost {
18 namespace beast {
19 namespace http {
20 namespace detail {
21
22 inline
23 bool
24 is_digit(char c)
25 {
26 return c >= '0' && c <= '9';
27 }
28
29 inline
30 char
31 is_alpha(char c)
32 {
33 static char constexpr tab[] = {
34 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32
37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 48
38 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
39 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 80
40 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
41 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 112
42 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128
43 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144
44 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
45 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176
46 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
47 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208
48 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224
49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 240
50 };
51 BOOST_STATIC_ASSERT(sizeof(tab) == 256);
52 return tab[static_cast<unsigned char>(c)];
53 }
54
55 inline
56 char
57 is_text(char c)
58 {
59 // TEXT = <any OCTET except CTLs, but including LWS>
60 static char constexpr tab[] = {
61 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
62 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
63 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
64 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
65 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
66 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
67 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
68 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
69 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
70 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
71 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
72 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
73 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
74 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
75 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
76 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
77 };
78 BOOST_STATIC_ASSERT(sizeof(tab) == 256);
79 return tab[static_cast<unsigned char>(c)];
80 }
81
82 inline
83 char
84 is_token_char(char c)
85 {
86 /*
87 tchar = "!" | "#" | "$" | "%" | "&" |
88 "'" | "*" | "+" | "-" | "." |
89 "^" | "_" | "`" | "|" | "~" |
90 DIGIT | ALPHA
91 */
92 static char constexpr tab[] = {
93 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
94 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
95 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32
96 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48
97 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
98 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80
99 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
100 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, // 112
101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144
103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
104 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176
105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
106 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208
107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224
108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 240
109 };
110 BOOST_STATIC_ASSERT(sizeof(tab) == 256);
111 return tab[static_cast<unsigned char>(c)];
112 }
113
114 inline
115 char
116 is_qdchar(char c)
117 {
118 /*
119 qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
120 */
121 static char constexpr tab[] = {
122 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
124 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
125 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
126 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
127 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 80
128 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
129 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
130 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
131 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
132 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
133 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
134 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
135 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
136 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
137 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
138 };
139 BOOST_STATIC_ASSERT(sizeof(tab) == 256);
140 return tab[static_cast<unsigned char>(c)];
141 }
142
143 inline
144 char
145 is_qpchar(char c)
146 {
147 /*
148 quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
149 obs-text = %x80-FF
150 */
151 static char constexpr tab[] = {
152 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
153 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
154 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
155 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
156 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
157 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
158 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
159 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
160 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
161 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
162 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
163 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
164 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
165 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
166 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
167 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
168 };
169 BOOST_STATIC_ASSERT(sizeof(tab) == 256);
170 return tab[static_cast<unsigned char>(c)];
171 }
172
173 // converts to lower case,
174 // returns 0 if not a valid text char
175 //
176 inline
177 char
178 to_value_char(char c)
179 {
180 // TEXT = <any OCTET except CTLs, but including LWS>
181 static unsigned char constexpr tab[] = {
182 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, // 0
183 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
184 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 32
185 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 48
186 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 64
187 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, // 80
188 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 96
189 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 0, // 112
190 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, // 128
191 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, // 144
192 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, // 160
193 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, // 176
194 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, // 192
195 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, // 208
196 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, // 224
197 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 // 240
198 };
199 BOOST_STATIC_ASSERT(sizeof(tab) == 256);
200 return static_cast<char>(tab[static_cast<unsigned char>(c)]);
201 }
202
203 // VFALCO TODO Make this return unsigned?
204 inline
205 std::int8_t
206 unhex(char c)
207 {
208 static signed char constexpr tab[] = {
209 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0
210 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16
211 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32
212 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 48
213 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 64
214 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80
215 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 96
216 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 112
217 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128
218 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144
219 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160
220 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176
221 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192
222 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208
223 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224
224 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 240
225 };
226 BOOST_STATIC_ASSERT(sizeof(tab) == 256);
227 return tab[static_cast<unsigned char>(c)];
228 }
229
230 template<class FwdIt>
231 inline
232 void
233 skip_ows(FwdIt& it, FwdIt const& end)
234 {
235 while(it != end)
236 {
237 if(*it != ' ' && *it != '\t')
238 break;
239 ++it;
240 }
241 }
242
243 template<class RanIt>
244 inline
245 void
246 skip_ows_rev(
247 RanIt& it, RanIt const& first)
248 {
249 while(it != first)
250 {
251 auto const c = it[-1];
252 if(c != ' ' && c != '\t')
253 break;
254 --it;
255 }
256 }
257
258 // obs-fold = CRLF 1*( SP / HTAB )
259 // return `false` on parse error
260 //
261 template<class FwdIt>
262 inline
263 bool
264 skip_obs_fold(
265 FwdIt& it, FwdIt const& last)
266 {
267 for(;;)
268 {
269 if(*it != '\r')
270 return true;
271 if(++it == last)
272 return false;
273 if(*it != '\n')
274 return false;
275 if(++it == last)
276 return false;
277 if(*it != ' ' && *it != '\t')
278 return false;
279 for(;;)
280 {
281 if(++it == last)
282 return true;
283 if(*it != ' ' && *it != '\t')
284 return true;
285 }
286 }
287 }
288
289 template<class FwdIt>
290 void
291 skip_token(FwdIt& it, FwdIt const& last)
292 {
293 while(it != last && is_token_char(*it))
294 ++it;
295 }
296
297 inline
298 string_view
299 trim(string_view s)
300 {
301 auto first = s.begin();
302 auto last = s.end();
303 skip_ows(first, last);
304 while(first != last)
305 {
306 auto const c = *std::prev(last);
307 if(c != ' ' && c != '\t')
308 break;
309 --last;
310 }
311 if(first == last)
312 return {};
313 return {&*first,
314 static_cast<std::size_t>(last - first)};
315 }
316
317 struct param_iter
318 {
319 using iter_type = string_view::const_iterator;
320
321 iter_type it;
322 iter_type first;
323 iter_type last;
324 std::pair<string_view, string_view> v;
325
326 bool
327 empty() const
328 {
329 return first == it;
330 }
331
332 template<class = void>
333 void
334 increment();
335 };
336
337 template<class>
338 void
339 param_iter::
340 increment()
341 {
342 /*
343 param-list = *( OWS ";" OWS param )
344 param = token OWS [ "=" OWS ( token / quoted-string ) ]
345 quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
346 qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
347 quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
348 obs-text = %x80-FF
349 */
350 auto const err =
351 [&]
352 {
353 it = first;
354 };
355 v.first.clear();
356 v.second.clear();
357 detail::skip_ows(it, last);
358 first = it;
359 if(it == last)
360 return err();
361 if(*it != ';')
362 return err();
363 ++it;
364 detail::skip_ows(it, last);
365 if(it == last)
366 return err();
367 // param
368 if(! detail::is_token_char(*it))
369 return err();
370 auto const p0 = it;
371 skip_token(++it, last);
372 auto const p1 = it;
373 v.first = { &*p0, static_cast<std::size_t>(p1 - p0) };
374 detail::skip_ows(it, last);
375 if(it == last)
376 return;
377 if(*it == ';')
378 return;
379 if(*it != '=')
380 return err();
381 ++it;
382 detail::skip_ows(it, last);
383 if(it == last)
384 return;
385 if(*it == '"')
386 {
387 // quoted-string
388 auto const p2 = it;
389 ++it;
390 for(;;)
391 {
392 if(it == last)
393 return err();
394 auto c = *it++;
395 if(c == '"')
396 break;
397 if(detail::is_qdchar(c))
398 continue;
399 if(c != '\\')
400 return err();
401 if(it == last)
402 return err();
403 c = *it++;
404 if(! detail::is_qpchar(c))
405 return err();
406 }
407 v.second = { &*p2, static_cast<std::size_t>(it - p2) };
408 }
409 else
410 {
411 // token
412 if(! detail::is_token_char(*it))
413 return err();
414 auto const p2 = it;
415 skip_token(++it, last);
416 v.second = { &*p2, static_cast<std::size_t>(it - p2) };
417 }
418 }
419
420 /*
421 #token = [ ( "," / token ) *( OWS "," [ OWS token ] ) ]
422 */
423 struct opt_token_list_policy
424 {
425 using value_type = string_view;
426
427 bool
428 operator()(value_type& v,
429 char const*& it, string_view s) const
430 {
431 v = {};
432 auto need_comma = it != s.begin();
433 for(;;)
434 {
435 detail::skip_ows(it, s.end());
436 if(it == s.end())
437 {
438 it = nullptr;
439 return true;
440 }
441 auto const c = *it;
442 if(detail::is_token_char(c))
443 {
444 if(need_comma)
445 return false;
446 auto const p0 = it;
447 for(;;)
448 {
449 ++it;
450 if(it == s.end())
451 break;
452 if(! detail::is_token_char(*it))
453 break;
454 }
455 v = string_view{&*p0,
456 static_cast<std::size_t>(it - p0)};
457 return true;
458 }
459 if(c != ',')
460 return false;
461 need_comma = false;
462 ++it;
463 }
464 }
465 };
466
467 } // detail
468 } // http
469 } // beast
470 } // boost
471
472 #endif
473