ゴミ箱
rfc7230.hpp
Go to the documentation of this file.
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 
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
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
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
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
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
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 
318 {
319  using iter_type = string_view::const_iterator;
320 
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
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();
358  first = it;
359  if(it == last)
360  return err();
361  if(*it != ';')
362  return err();
363  ++it;
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) };
375  if(it == last)
376  return;
377  if(*it == ';')
378  return;
379  if(*it != '=')
380  return err();
381  ++it;
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 */
424 {
426 
427  bool
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 
std::int8_t unhex(char c)
Definition: rfc7230.hpp:206
std::pair< string_view, string_view > v
Definition: rfc7230.hpp:324
Definition: async_result.hpp:20
iter_type last
Definition: rfc7230.hpp:323
string_view::const_iterator iter_type
Definition: rfc7230.hpp:319
char is_token_char(char c)
Definition: rfc7230.hpp:84
char is_qpchar(char c)
Definition: rfc7230.hpp:145
Definition: beast_common.hpp:6
void increment()
Definition: rfc7230.hpp:340
bool operator()(value_type &v, char const *&it, string_view s) const
Definition: rfc7230.hpp:428
char is_text(char c)
Definition: rfc7230.hpp:57
void skip_token(FwdIt &it, FwdIt const &last)
Definition: rfc7230.hpp:291
iter_type it
Definition: rfc7230.hpp:321
void skip_ows_rev(RanIt &it, RanIt const &first)
Definition: rfc7230.hpp:246
string_view value_type
Definition: rfc7230.hpp:425
bool empty() const
Definition: rfc7230.hpp:327
boost::string_ref string_view
The type of string view used by the library.
Definition: string.hpp:36
iter_type first
Definition: rfc7230.hpp:322
char is_alpha(char c)
Definition: rfc7230.hpp:31
bool skip_obs_fold(FwdIt &it, FwdIt const &last)
Definition: rfc7230.hpp:264
char to_value_char(char c)
Definition: rfc7230.hpp:178
string_view trim(string_view s)
Definition: rfc7230.hpp:299
char is_qdchar(char c)
Definition: rfc7230.hpp:116
void skip_ows(FwdIt &it, FwdIt const &end)
Definition: rfc7230.hpp:233
Definition: rfc7230.hpp:317
bool is_digit(char c)
Definition: rfc7230.hpp:24