Line data Source code
1 : //
2 : // Copyright (c) 2021 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/CPPAlliance/http_proto
8 : //
9 :
10 : #ifndef BOOST_HTTP_PROTO_RFC_DETAIL_RULES_HPP
11 : #define BOOST_HTTP_PROTO_RFC_DETAIL_RULES_HPP
12 :
13 : #include <boost/http_proto/error_types.hpp>
14 : #include <boost/http_proto/status.hpp>
15 : #include <boost/http_proto/rfc/token_rule.hpp>
16 : #include <boost/url/grammar/delim_rule.hpp>
17 : #include <boost/url/grammar/error.hpp>
18 : #include <boost/url/grammar/lut_chars.hpp>
19 : #include <boost/url/grammar/token_rule.hpp>
20 : #include <boost/url/grammar/tuple_rule.hpp>
21 :
22 : namespace boost {
23 : namespace http_proto {
24 : namespace detail {
25 :
26 : //------------------------------------------------
27 :
28 : // WS = SP / HTAB
29 : struct ws_t
30 : {
31 : constexpr
32 : bool
33 3040 : operator()(char c) const noexcept
34 : {
35 3040 : return c == ' ' || c == '\t';
36 : }
37 : };
38 :
39 : constexpr ws_t ws{};
40 :
41 : //------------------------------------------------
42 :
43 : /* Used with list_rule
44 :
45 : @par BNF
46 : @code
47 : ows-comma = OWS "," OWS
48 : @endcode
49 : */
50 : struct ows_comma_ows_rule_t
51 : {
52 : using value_type = void;
53 :
54 : auto
55 : parse(
56 : char const*& it,
57 : char const* end) const noexcept ->
58 : result<void>
59 : {
60 : // OWS
61 : it = grammar::find_if_not(
62 : it, end, ws);
63 : if(it == end)
64 : return grammar::error::mismatch;
65 : // ","
66 : if(*it != ',')
67 : return grammar::error::mismatch;
68 : ++it;
69 : // OWS
70 : it = grammar::find_if_not(
71 : it, end, ws);
72 : return {};
73 : }
74 : };
75 :
76 : constexpr ows_comma_ows_rule_t ows_comma_ows_rule{};
77 :
78 : //------------------------------------------------
79 :
80 : // used for request-target
81 : //
82 : // target-char = <any OCTET except CTLs, and excluding LWS>
83 : //
84 : struct target_chars_t
85 : {
86 : constexpr
87 : bool
88 : operator()(char c) const noexcept
89 : {
90 : return
91 : (static_cast<unsigned char>(c) >= 0x21) &&
92 : (static_cast<unsigned char>(c) <= 0x7e);
93 : }
94 : };
95 :
96 : constexpr target_chars_t target_chars{};
97 :
98 : //------------------------------------------------
99 :
100 : // WS-VCHAR = SP / HTAB / VCHAR
101 : struct ws_vchars_t
102 : {
103 : constexpr
104 : bool
105 7464 : operator()(char ch) const noexcept
106 : {
107 : return (
108 7464 : ch >= 0x20 && ch <= 0x7e) ||
109 7464 : ch == 0x09;
110 : }
111 : };
112 :
113 : constexpr ws_vchars_t ws_vchars{};
114 :
115 : //------------------------------------------------
116 :
117 : // OWS = *( SP / HTAB )
118 : inline
119 : void
120 2820 : skip_ows(
121 : char const*& it,
122 : char const* end) noexcept
123 : {
124 2820 : while(it != end)
125 : {
126 2634 : if(! ws(*it))
127 1462 : break;
128 1172 : ++it;
129 : }
130 1648 : }
131 :
132 : struct ows_rule_t
133 : {
134 : using value_type = void;
135 :
136 : result<value_type>
137 : parse(
138 : char const*& it,
139 : char const* end) noexcept
140 : {
141 : skip_ows(it, end);
142 : return error_code();
143 : }
144 : };
145 :
146 : constexpr ows_rule_t ows_rule{};
147 :
148 : //------------------------------------------------
149 :
150 : // CRLF = CR LF
151 : struct crlf_rule_t
152 : {
153 : using value_type = void;
154 :
155 : result<value_type>
156 : parse(
157 : char const*& it,
158 : char const* end) const noexcept;
159 : };
160 :
161 : constexpr crlf_rule_t crlf_rule{};
162 :
163 : //------------------------------------------------
164 :
165 : // HTTP-version = "HTTP/" DIGIT "." DIGIT
166 : struct version_rule_t
167 : {
168 : using value_type = unsigned char;
169 :
170 : result<value_type>
171 : parse(
172 : char const*& it,
173 : char const* end) const noexcept;
174 : };
175 :
176 : constexpr version_rule_t version_rule{};
177 :
178 : //------------------------------------------------
179 :
180 : // request-line = method SP request-target SP HTTP-version CRLF
181 : constexpr auto
182 : request_line_rule =
183 : grammar::tuple_rule(
184 : token_rule,
185 : grammar::squelch(
186 : grammar::delim_rule(' ') ),
187 : grammar::token_rule(
188 : grammar::lut_chars(target_chars) ),
189 : grammar::squelch(
190 : grammar::delim_rule(' ') ),
191 : version_rule,
192 : crlf_rule);
193 :
194 : //------------------------------------------------
195 :
196 : // status-code = 3DIGIT
197 : struct status_code_rule_t
198 : {
199 : struct value_type
200 : {
201 : int v;
202 : status st;
203 : string_view s;
204 : };
205 :
206 : result<value_type>
207 : parse(
208 : char const*& it,
209 : char const* end) const noexcept;
210 : };
211 :
212 : constexpr status_code_rule_t status_code_rule{};
213 :
214 : //------------------------------------------------
215 :
216 : // status-line = HTTP-version SP status-code SP reason-phrase CRLF
217 : constexpr auto
218 : status_line_rule =
219 : grammar::tuple_rule(
220 : version_rule,
221 : grammar::squelch(
222 : grammar::delim_rule(' ') ),
223 : status_code_rule,
224 : grammar::squelch(
225 : grammar::delim_rule(' ') ),
226 : grammar::token_rule(ws_vchars),
227 : crlf_rule);
228 :
229 : //------------------------------------------------
230 :
231 : // header-field = field-name ":" OWS field-value OWS
232 : struct field_rule_t
233 : {
234 : struct value_type
235 : {
236 : string_view name;
237 : string_view value;
238 : bool has_obs_fold = false;
239 : };
240 :
241 : result<value_type>
242 : parse(
243 : char const*& it,
244 : char const* end) const noexcept;
245 : };
246 :
247 : constexpr field_rule_t field_rule{};
248 :
249 : /** Replace obs-fold with spaces
250 : */
251 : BOOST_HTTP_PROTO_DECL
252 : void
253 : remove_obs_fold(
254 : char *start,
255 : char const* end) noexcept;
256 :
257 : } // detail
258 : } // http_proto
259 : } // boost
260 :
261 : #endif
|