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