100.00% Lines (3/3) 100.00% Functions (1/1)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2024 Christian Mazakas 2   // Copyright (c) 2024 Christian Mazakas
3   // Copyright (c) 2025 Mohammad Nejati 3   // Copyright (c) 2025 Mohammad Nejati
4   // 4   //
5   // Distributed under the Boost Software License, Version 1.0. (See accompanying 5   // Distributed under the Boost Software License, Version 1.0. (See accompanying
6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7   // 7   //
8   // Official repository: https://github.com/cppalliance/http 8   // Official repository: https://github.com/cppalliance/http
9   // 9   //
10   10  
11   #ifndef BOOST_HTTP_SRC_RFC_DETAIL_RULES_HPP 11   #ifndef BOOST_HTTP_SRC_RFC_DETAIL_RULES_HPP
12   #define BOOST_HTTP_SRC_RFC_DETAIL_RULES_HPP 12   #define BOOST_HTTP_SRC_RFC_DETAIL_RULES_HPP
13   13  
14   #include <boost/http/detail/config.hpp> 14   #include <boost/http/detail/config.hpp>
15   #include <boost/http/rfc/detail/ws.hpp> 15   #include <boost/http/rfc/detail/ws.hpp>
16   #include <boost/http/rfc/token_rule.hpp> 16   #include <boost/http/rfc/token_rule.hpp>
17   #include <boost/http/status.hpp> 17   #include <boost/http/status.hpp>
18   #include <boost/core/detail/string_view.hpp> 18   #include <boost/core/detail/string_view.hpp>
19   #include <boost/system/result.hpp> 19   #include <boost/system/result.hpp>
20   #include <boost/url/grammar/delim_rule.hpp> 20   #include <boost/url/grammar/delim_rule.hpp>
21   #include <boost/url/grammar/error.hpp> 21   #include <boost/url/grammar/error.hpp>
22   #include <boost/url/grammar/lut_chars.hpp> 22   #include <boost/url/grammar/lut_chars.hpp>
23   #include <boost/url/grammar/token_rule.hpp> 23   #include <boost/url/grammar/token_rule.hpp>
24   #include <boost/url/grammar/tuple_rule.hpp> 24   #include <boost/url/grammar/tuple_rule.hpp>
25   25  
26   namespace boost { 26   namespace boost {
27   namespace http { 27   namespace http {
28   namespace detail { 28   namespace detail {
29   29  
30   //------------------------------------------------ 30   //------------------------------------------------
31   31  
32   /* Used with list_rule 32   /* Used with list_rule
33   33  
34   @par BNF 34   @par BNF
35   @code 35   @code
36   ows-comma = OWS "," OWS 36   ows-comma = OWS "," OWS
37   @endcode 37   @endcode
38   */ 38   */
39   struct ows_comma_ows_rule_t 39   struct ows_comma_ows_rule_t
40   { 40   {
41   using value_type = void; 41   using value_type = void;
42   42  
43   auto 43   auto
44   parse( 44   parse(
45   char const*& it, 45   char const*& it,
46   char const* end) const noexcept -> 46   char const* end) const noexcept ->
47   system::result<void> 47   system::result<void>
48   { 48   {
49   // OWS 49   // OWS
50   it = grammar::find_if_not( 50   it = grammar::find_if_not(
51   it, end, ws); 51   it, end, ws);
52   if(it == end) 52   if(it == end)
53   return grammar::error::mismatch; 53   return grammar::error::mismatch;
54   // "," 54   // ","
55   if(*it != ',') 55   if(*it != ',')
56   return grammar::error::mismatch; 56   return grammar::error::mismatch;
57   ++it; 57   ++it;
58   // OWS 58   // OWS
59   it = grammar::find_if_not( 59   it = grammar::find_if_not(
60   it, end, ws); 60   it, end, ws);
61   return {}; 61   return {};
62   } 62   }
63   }; 63   };
64   64  
65   constexpr ows_comma_ows_rule_t ows_comma_ows_rule{}; 65   constexpr ows_comma_ows_rule_t ows_comma_ows_rule{};
66   66  
67   //------------------------------------------------ 67   //------------------------------------------------
68   68  
69   // used for request-target 69   // used for request-target
70   // 70   //
71   // target-char = <any OCTET except CTLs, and excluding LWS> 71   // target-char = <any OCTET except CTLs, and excluding LWS>
72   // 72   //
73   struct target_chars_t 73   struct target_chars_t
74   { 74   {
75   constexpr 75   constexpr
76   bool 76   bool
77   operator()(char c) const noexcept 77   operator()(char c) const noexcept
78   { 78   {
79   return 79   return
80   (static_cast<unsigned char>(c) >= 0x21) && 80   (static_cast<unsigned char>(c) >= 0x21) &&
81   (static_cast<unsigned char>(c) <= 0x7e); 81   (static_cast<unsigned char>(c) <= 0x7e);
82   } 82   }
83   }; 83   };
84   84  
85   constexpr target_chars_t target_chars{}; 85   constexpr target_chars_t target_chars{};
86   86  
87   //------------------------------------------------ 87   //------------------------------------------------
88   88  
89   // WS-VCHAR = SP / HTAB / VCHAR 89   // WS-VCHAR = SP / HTAB / VCHAR
90   struct ws_vchars_t 90   struct ws_vchars_t
91   { 91   {
92   constexpr 92   constexpr
93   bool 93   bool
HITCBC 94   7963 operator()(char ch) const noexcept 94   7998 operator()(char ch) const noexcept
95   { 95   {
96   return ( 96   return (
HITCBC 97   7963 ch >= 0x20 && ch <= 0x7e) || 97   7998 ch >= 0x20 && ch <= 0x7e) ||
HITCBC 98   7963 ch == 0x09; 98   7998 ch == 0x09;
99   } 99   }
100   }; 100   };
101   101  
102   constexpr ws_vchars_t ws_vchars{}; 102   constexpr ws_vchars_t ws_vchars{};
103   103  
104   //------------------------------------------------ 104   //------------------------------------------------
105   105  
106   // OWS = *( SP / HTAB ) 106   // OWS = *( SP / HTAB )
107   inline 107   inline
108   void 108   void
109   skip_ows( 109   skip_ows(
110   char const*& it, 110   char const*& it,
111   char const* end) noexcept 111   char const* end) noexcept
112   { 112   {
113   while(it != end) 113   while(it != end)
114   { 114   {
115   if(! ws(*it)) 115   if(! ws(*it))
116   break; 116   break;
117   ++it; 117   ++it;
118   } 118   }
119   } 119   }
120   120  
121   struct ows_rule_t 121   struct ows_rule_t
122   { 122   {
123   using value_type = void; 123   using value_type = void;
124   124  
125   system::result<value_type> 125   system::result<value_type>
126   parse( 126   parse(
127   char const*& it, 127   char const*& it,
128   char const* end) noexcept 128   char const* end) noexcept
129   { 129   {
130   skip_ows(it, end); 130   skip_ows(it, end);
131   return system::error_code(); 131   return system::error_code();
132   } 132   }
133   }; 133   };
134   134  
135   constexpr ows_rule_t ows_rule{}; 135   constexpr ows_rule_t ows_rule{};
136   136  
137   //------------------------------------------------ 137   //------------------------------------------------
138   138  
139   // CRLF = CR LF 139   // CRLF = CR LF
140   struct crlf_rule_t 140   struct crlf_rule_t
141   { 141   {
142   using value_type = void; 142   using value_type = void;
143   143  
144   system::result<value_type> 144   system::result<value_type>
145   parse( 145   parse(
146   char const*& it, 146   char const*& it,
147   char const* end) const noexcept; 147   char const* end) const noexcept;
148   }; 148   };
149   149  
150   constexpr crlf_rule_t crlf_rule{}; 150   constexpr crlf_rule_t crlf_rule{};
151   151  
152   //------------------------------------------------ 152   //------------------------------------------------
153   153  
154   // HTTP-version = "HTTP/" DIGIT "." DIGIT 154   // HTTP-version = "HTTP/" DIGIT "." DIGIT
155   struct version_rule_t 155   struct version_rule_t
156   { 156   {
157   using value_type = unsigned char; 157   using value_type = unsigned char;
158   158  
159   system::result<value_type> 159   system::result<value_type>
160   parse( 160   parse(
161   char const*& it, 161   char const*& it,
162   char const* end) const noexcept; 162   char const* end) const noexcept;
163   }; 163   };
164   164  
165   constexpr version_rule_t version_rule{}; 165   constexpr version_rule_t version_rule{};
166   166  
167   //------------------------------------------------ 167   //------------------------------------------------
168   168  
169   // request-line = method SP request-target SP HTTP-version CRLF 169   // request-line = method SP request-target SP HTTP-version CRLF
170   constexpr auto 170   constexpr auto
171   request_line_rule = 171   request_line_rule =
172   grammar::tuple_rule( 172   grammar::tuple_rule(
173   token_rule, 173   token_rule,
174   grammar::squelch( 174   grammar::squelch(
175   grammar::delim_rule(' ') ), 175   grammar::delim_rule(' ') ),
176   grammar::token_rule( 176   grammar::token_rule(
177   grammar::lut_chars(target_chars) ), 177   grammar::lut_chars(target_chars) ),
178   grammar::squelch( 178   grammar::squelch(
179   grammar::delim_rule(' ') ), 179   grammar::delim_rule(' ') ),
180   version_rule, 180   version_rule,
181   crlf_rule); 181   crlf_rule);
182   182  
183   //------------------------------------------------ 183   //------------------------------------------------
184   184  
185   // status-code = 3DIGIT 185   // status-code = 3DIGIT
186   struct status_code_rule_t 186   struct status_code_rule_t
187   { 187   {
188   struct value_type 188   struct value_type
189   { 189   {
190   int v; 190   int v;
191   status st; 191   status st;
192   core::string_view s; 192   core::string_view s;
193   }; 193   };
194   194  
195   system::result<value_type> 195   system::result<value_type>
196   parse( 196   parse(
197   char const*& it, 197   char const*& it,
198   char const* end) const noexcept; 198   char const* end) const noexcept;
199   }; 199   };
200   200  
201   constexpr status_code_rule_t status_code_rule{}; 201   constexpr status_code_rule_t status_code_rule{};
202   202  
203   //------------------------------------------------ 203   //------------------------------------------------
204   204  
205   // status-code = *( HTAB / SP / VCHAR / obs-text ) 205   // status-code = *( HTAB / SP / VCHAR / obs-text )
206   struct reason_phrase_rule_t 206   struct reason_phrase_rule_t
207   { 207   {
208   using value_type = core::string_view; 208   using value_type = core::string_view;
209   209  
210   system::result<value_type> 210   system::result<value_type>
211   parse( 211   parse(
212   char const*& it, 212   char const*& it,
213   char const* end) const noexcept; 213   char const* end) const noexcept;
214   }; 214   };
215   215  
216   constexpr reason_phrase_rule_t reason_phrase_rule{}; 216   constexpr reason_phrase_rule_t reason_phrase_rule{};
217   217  
218   //------------------------------------------------ 218   //------------------------------------------------
219   219  
220   // status-line = HTTP-version SP status-code SP reason-phrase CRLF 220   // status-line = HTTP-version SP status-code SP reason-phrase CRLF
221   constexpr auto 221   constexpr auto
222   status_line_rule = 222   status_line_rule =
223   grammar::tuple_rule( 223   grammar::tuple_rule(
224   version_rule, 224   version_rule,
225   grammar::squelch( 225   grammar::squelch(
226   grammar::delim_rule(' ') ), 226   grammar::delim_rule(' ') ),
227   status_code_rule, 227   status_code_rule,
228   grammar::squelch( 228   grammar::squelch(
229   grammar::delim_rule(' ') ), 229   grammar::delim_rule(' ') ),
230   reason_phrase_rule, 230   reason_phrase_rule,
231   crlf_rule); 231   crlf_rule);
232   232  
233   //------------------------------------------------ 233   //------------------------------------------------
234   234  
235   struct field_rule_t 235   struct field_rule_t
236   { 236   {
237   struct value_type 237   struct value_type
238   { 238   {
239   core::string_view name; 239   core::string_view name;
240   core::string_view value; 240   core::string_view value;
241   bool has_obs_fold = false; 241   bool has_obs_fold = false;
242   }; 242   };
243   243  
244   system::result<value_type> 244   system::result<value_type>
245   parse( 245   parse(
246   char const*& it, 246   char const*& it,
247   char const* end) const noexcept; 247   char const* end) const noexcept;
248   }; 248   };
249   249  
250   constexpr field_rule_t field_rule{}; 250   constexpr field_rule_t field_rule{};
251   251  
252   /** Replace obs-fold with spaces 252   /** Replace obs-fold with spaces
253   */ 253   */
254   void 254   void
255   remove_obs_fold( 255   remove_obs_fold(
256   char *start, 256   char *start,
257   char const* end) noexcept; 257   char const* end) noexcept;
258   258  
259   // header-field = field-name ":" OWS field-value OWS 259   // header-field = field-name ":" OWS field-value OWS
260   struct field_name_rule_t 260   struct field_name_rule_t
261   { 261   {
262   using value_type = core::string_view; 262   using value_type = core::string_view;
263   263  
264   system::result<value_type> 264   system::result<value_type>
265   parse( 265   parse(
266   char const*& it, 266   char const*& it,
267   char const* end) const noexcept; 267   char const* end) const noexcept;
268   }; 268   };
269   269  
270   constexpr field_name_rule_t field_name_rule{}; 270   constexpr field_name_rule_t field_name_rule{};
271   271  
272   struct field_value_rule_t 272   struct field_value_rule_t
273   { 273   {
274   struct value_type 274   struct value_type
275   { 275   {
276   core::string_view value; 276   core::string_view value;
277   // detected occurrence of `\r\n `, `\r\n\t` 277   // detected occurrence of `\r\n `, `\r\n\t`
278   bool has_obs_fold = false; 278   bool has_obs_fold = false;
279   // detected `\r\nX`, attempt at field termination 279   // detected `\r\nX`, attempt at field termination
280   bool has_crlf = false; 280   bool has_crlf = false;
281   }; 281   };
282   282  
283   system::result<value_type> 283   system::result<value_type>
284   parse( 284   parse(
285   char const*& it, 285   char const*& it,
286   char const* end) const noexcept; 286   char const* end) const noexcept;
287   }; 287   };
288   288  
289   constexpr field_value_rule_t field_value_rule{}; 289   constexpr field_value_rule_t field_value_rule{};
290   290  
291   } // detail 291   } // detail
292   } // http 292   } // http
293   } // boost 293   } // boost
294   294  
295   #endif 295   #endif