95.78% Lines (159/166) 100.00% Functions (10/10)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 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) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/cppalliance/http 7   // Official repository: https://github.com/cppalliance/http
8   // 8   //
9   9  
10   #include "src/rfc/detail/rules.hpp" 10   #include "src/rfc/detail/rules.hpp"
11   11  
12   #include <boost/http/error.hpp> 12   #include <boost/http/error.hpp>
13   #include <boost/http/detail/config.hpp> 13   #include <boost/http/detail/config.hpp>
14   #include <boost/http/rfc/token_rule.hpp> 14   #include <boost/http/rfc/token_rule.hpp>
15   15  
16   #include <boost/core/detail/string_view.hpp> 16   #include <boost/core/detail/string_view.hpp>
17   #include <boost/url/grammar/delim_rule.hpp> 17   #include <boost/url/grammar/delim_rule.hpp>
18   #include <boost/url/grammar/digit_chars.hpp> 18   #include <boost/url/grammar/digit_chars.hpp>
19   #include <boost/url/grammar/error.hpp> 19   #include <boost/url/grammar/error.hpp>
20   #include <boost/url/grammar/hexdig_chars.hpp> 20   #include <boost/url/grammar/hexdig_chars.hpp>
21   #include <boost/url/grammar/lut_chars.hpp> 21   #include <boost/url/grammar/lut_chars.hpp>
22   #include <boost/url/grammar/parse.hpp> 22   #include <boost/url/grammar/parse.hpp>
23   #include <boost/url/grammar/tuple_rule.hpp> 23   #include <boost/url/grammar/tuple_rule.hpp>
24   24  
25   #include "src/rfc/detail/rules.hpp" 25   #include "src/rfc/detail/rules.hpp"
26   26  
27   namespace boost { 27   namespace boost {
28   namespace http { 28   namespace http {
29   namespace detail { 29   namespace detail {
30   30  
31   auto 31   auto
HITCBC 32   28890 crlf_rule_t:: 32   28890 crlf_rule_t::
33   parse( 33   parse(
34   char const*& it, 34   char const*& it,
35   char const* end) const noexcept -> 35   char const* end) const noexcept ->
36   system::result<value_type> 36   system::result<value_type>
37   { 37   {
HITCBC 38   28890 if(it == end) 38   28890 if(it == end)
HITCBC 39   6535 return grammar::error::need_more; 39   6535 return grammar::error::need_more;
HITCBC 40   22355 if(*it != '\r') 40   22355 if(*it != '\r')
HITCBC 41   29 return grammar::error::mismatch; 41   29 return grammar::error::mismatch;
HITCBC 42   22326 ++it; 42   22326 ++it;
HITCBC 43   22326 if(it == end) 43   22326 if(it == end)
HITCBC 44   961 return grammar::error::need_more; 44   961 return grammar::error::need_more;
HITCBC 45   21365 if(*it != '\n') 45   21365 if(*it != '\n')
HITCBC 46   51 return grammar::error::mismatch; 46   51 return grammar::error::mismatch;
HITCBC 47   21314 ++it; 47   21314 ++it;
HITCBC 48   21314 return {}; 48   21314 return {};
49   } 49   }
50   50  
51   //------------------------------------------------ 51   //------------------------------------------------
52   52  
53   auto 53   auto
HITCBC 54   28506 version_rule_t:: 54   28506 version_rule_t::
55   parse( 55   parse(
56   char const*& it, 56   char const*& it,
57   char const* end) const noexcept -> 57   char const* end) const noexcept ->
58   system::result<value_type> 58   system::result<value_type>
59   { 59   {
HITCBC 60   28506 value_type v = 0; 60   28506 value_type v = 0;
HITCBC 61   28506 if(it == end) 61   28506 if(it == end)
62   { 62   {
63   // expected "HTTP/" 63   // expected "HTTP/"
HITCBC 64 - 1619 BOOST_HTTP_RETURN_EC( 64 + 1619 return grammar::error::need_more;
65 - grammar::error::need_more);  
66   } 65   }
HITCBC 67   26887 if(end - it >= 5) 66   26887 if(end - it >= 5)
68   { 67   {
HITCBC 69   22177 if(std::memcmp( 68   22177 if(std::memcmp(
70   it, "HTTP/", 5) != 0) 69   it, "HTTP/", 5) != 0)
71   { 70   {
MISUBC 72 - BOOST_HTTP_RETURN_EC( 71 + return grammar::error::mismatch;
73 - grammar::error::mismatch);  
74   } 72   }
HITCBC 75   22177 it += 5; 73   22177 it += 5;
76   } 74   }
HITCBC 77   26887 if(it == end) 75   26887 if(it == end)
78   { 76   {
79   // expected DIGIT 77   // expected DIGIT
HITCBC 80 - 1087 BOOST_HTTP_RETURN_EC( 78 + 1087 return grammar::error::need_more;
81 - grammar::error::need_more);  
82   } 79   }
HITCBC 83   25800 if(! grammar::digit_chars(*it)) 80   25800 if(! grammar::digit_chars(*it))
84   { 81   {
85   // expected DIGIT 82   // expected DIGIT
HITCBC 86 - 4710 BOOST_HTTP_RETURN_EC( 83 + 4710 return grammar::error::need_more;
87 - grammar::error::need_more);  
88   } 84   }
HITCBC 89   21090 v = 10 * (*it++ - '0'); 85   21090 v = 10 * (*it++ - '0');
HITCBC 90   21090 if(it == end) 86   21090 if(it == end)
91   { 87   {
92   // expected "." 88   // expected "."
HITCBC 93 - 1213 BOOST_HTTP_RETURN_EC( 89 + 1213 return grammar::error::need_more;
94 - grammar::error::need_more);  
95   } 90   }
HITCBC 96   19877 if(*it != '.') 91   19877 if(*it != '.')
97   { 92   {
98   // expected "." 93   // expected "."
MISUBC 99 - BOOST_HTTP_RETURN_EC( 94 + return grammar::error::need_more;
100 - grammar::error::need_more);  
101   } 95   }
HITCBC 102   19877 ++it; 96   19877 ++it;
HITCBC 103   19877 if(it == end) 97   19877 if(it == end)
104   { 98   {
105   // expected DIGIT 99   // expected DIGIT
HITCBC 106 - 1051 BOOST_HTTP_RETURN_EC( 100 + 1051 return grammar::error::need_more;
107 - grammar::error::need_more);  
108   } 101   }
HITCBC 109   18826 if(! grammar::digit_chars(*it)) 102   18826 if(! grammar::digit_chars(*it))
110   { 103   {
111   // expected DIGIT 104   // expected DIGIT
MISUBC 112 - BOOST_HTTP_RETURN_EC( 105 + return grammar::error::need_more;
113 - grammar::error::need_more);  
114   } 106   }
HITCBC 115   18826 v += *it++ - '0'; 107   18826 v += *it++ - '0';
HITCBC 116   18826 return v; 108   18826 return v;
117   } 109   }
118   110  
119   //------------------------------------------------ 111   //------------------------------------------------
120   112  
121   auto 113   auto
HITCBC 122   8184 status_code_rule_t:: 114   8184 status_code_rule_t::
123   parse( 115   parse(
124   char const*& it, 116   char const*& it,
125   char const* end) const noexcept -> 117   char const* end) const noexcept ->
126   system::result<value_type> 118   system::result<value_type>
127   { 119   {
128   auto const dig = 120   auto const dig =
HITCBC 129   19020 [](char c) -> int 121   19020 [](char c) -> int
130   { 122   {
HITCBC 131   19020 unsigned char uc(c - '0'); 123   19020 unsigned char uc(c - '0');
HITCBC 132   19020 if(uc > 9) 124   19020 if(uc > 9)
MISUBC 133   return -1; 125   return -1;
HITCBC 134   19020 return uc; 126   19020 return uc;
135   }; 127   };
136   128  
HITCBC 137   8184 if(it == end) 129   8184 if(it == end)
138   { 130   {
139   // end 131   // end
HITCBC 140 - 934 BOOST_HTTP_RETURN_EC( 132 + 934 return grammar::error::need_more;
141 - grammar::error::need_more);  
142   } 133   }
HITCBC 143   7250 auto it0 = it; 134   7250 auto it0 = it;
HITCBC 144   7250 int v = dig(*it); 135   7250 int v = dig(*it);
HITCBC 145   7250 if(v == -1) 136   7250 if(v == -1)
146   { 137   {
147   // expected DIGIT 138   // expected DIGIT
MISUBC 148 - BOOST_HTTP_RETURN_EC( 139 + return grammar::error::mismatch;
149 - grammar::error::mismatch);  
150   } 140   }
HITCBC 151   7250 value_type t; 141   7250 value_type t;
HITCBC 152   7250 t.v = 100 * v; 142   7250 t.v = 100 * v;
HITCBC 153   7250 ++it; 143   7250 ++it;
HITCBC 154   7250 if(it == end) 144   7250 if(it == end)
155   { 145   {
156   // end 146   // end
HITCBC 157 - 916 BOOST_HTTP_RETURN_EC( 147 + 916 return grammar::error::need_more;
158 - grammar::error::need_more);  
159   } 148   }
HITCBC 160   6334 v = dig(*it); 149   6334 v = dig(*it);
HITCBC 161   6334 if(v == -1) 150   6334 if(v == -1)
162   { 151   {
163   // expected DIGIT 152   // expected DIGIT
MISUBC 164 - BOOST_HTTP_RETURN_EC( 153 + return grammar::error::mismatch;
165 - grammar::error::mismatch);  
166   } 154   }
HITCBC 167   6334 t.v = t.v + (10 * v); 155   6334 t.v = t.v + (10 * v);
HITCBC 168   6334 ++it; 156   6334 ++it;
HITCBC 169   6334 if(it == end) 157   6334 if(it == end)
170   { 158   {
171   // end 159   // end
HITCBC 172 - 898 BOOST_HTTP_RETURN_EC( 160 + 898 return grammar::error::need_more;
173 - grammar::error::need_more);  
174   } 161   }
HITCBC 175   5436 v = dig(*it); 162   5436 v = dig(*it);
HITCBC 176   5436 if(v == -1) 163   5436 if(v == -1)
177   { 164   {
178   // expected DIGIT 165   // expected DIGIT
MISUBC 179 - BOOST_HTTP_RETURN_EC( 166 + return grammar::error::need_more;
180 - grammar::error::need_more);  
181   } 167   }
HITCBC 182   5436 t.v = t.v + v; 168   5436 t.v = t.v + v;
HITCBC 183   5436 ++it; 169   5436 ++it;
184   170  
HITCBC 185   5436 t.s = core::string_view(it0, it - it0); 171   5436 t.s = core::string_view(it0, it - it0);
HITCBC 186   5436 t.st = int_to_status(t.v); 172   5436 t.st = int_to_status(t.v);
HITCBC 187   5436 return t; 173   5436 return t;
188   } 174   }
189   175  
190   //------------------------------------------------ 176   //------------------------------------------------
191   177  
192   auto 178   auto
HITCBC 193   4556 reason_phrase_rule_t:: 179   4556 reason_phrase_rule_t::
194   parse( 180   parse(
195   char const*& it, 181   char const*& it,
196   char const* end) const noexcept -> 182   char const* end) const noexcept ->
197   system::result<value_type> 183   system::result<value_type>
198   { 184   {
HITCBC 199   4556 auto begin = it; 185   4556 auto begin = it;
HITCBC 200   4556 it = grammar::find_if_not(it, end, ws_vchars); 186   4556 it = grammar::find_if_not(it, end, ws_vchars);
HITCBC 201   4556 return core::string_view(begin, it); 187   4556 return core::string_view(begin, it);
202   } 188   }
203   189  
204   //------------------------------------------------ 190   //------------------------------------------------
205   191  
206   auto 192   auto
HITCBC 207   26365 field_name_rule_t:: 193   26365 field_name_rule_t::
208   parse( 194   parse(
209   char const*& it, 195   char const*& it,
210   char const* end) const noexcept -> 196   char const* end) const noexcept ->
211   system::result<value_type> 197   system::result<value_type>
212   { 198   {
HITCBC 213   26365 if( it == end ) 199   26365 if( it == end )
HITCBC 214 - 1 BOOST_HTTP_RETURN_EC( 200 + 1 return grammar::error::need_more;
215 - grammar::error::need_more);  
216   201  
HITCBC 217   26364 value_type v; 202   26364 value_type v;
218   203  
HITCBC 219   26364 auto begin = it; 204   26364 auto begin = it;
HITCBC 220   26364 auto rv = grammar::parse( 205   26364 auto rv = grammar::parse(
221   it, end, token_rule); 206   it, end, token_rule);
HITCBC 222   26364 if( rv.has_error() || (it != end) ) 207   26364 if( rv.has_error() || (it != end) )
223   { 208   {
HITCBC 224   15941 if( it != begin ) 209   15941 if( it != begin )
225   { 210   {
HITCBC 226   15875 v = core::string_view(begin, it - begin); 211   15875 v = core::string_view(begin, it - begin);
HITCBC 227   15875 return v; 212   15875 return v;
228   } 213   }
HITCBC 229 - 66 return error::bad_field_name; 214 + 132 return make_error_code(
HITGNC   215 + 66 error::bad_field_name);
230   } 216   }
231   217  
HITCBC 232   10423 v = core::string_view(begin, end - begin); 218   10423 v = core::string_view(begin, end - begin);
HITCBC 233   10423 return v; 219   10423 return v;
234   } 220   }
235   221  
236   auto 222   auto
HITCBC 237   16144 field_value_rule_t:: 223   16144 field_value_rule_t::
238   parse( 224   parse(
239   char const*& it, 225   char const*& it,
240   char const* end) const noexcept -> 226   char const* end) const noexcept ->
241   system::result<value_type> 227   system::result<value_type>
242   { 228   {
HITCBC 243   16144 value_type v; 229   16144 value_type v;
HITCBC 244   16144 if( it == end ) 230   16144 if( it == end )
245   { 231   {
HITCBC 246   693 v.value = core::string_view(it, 0); 232   693 v.value = core::string_view(it, 0);
HITCBC 247   693 return v; 233   693 return v;
248   } 234   }
249   235  
250   // field-line = field-name ":" OWS field-value OWS 236   // field-line = field-name ":" OWS field-value OWS
251   // field-value = *field-content 237   // field-value = *field-content
252   // field-content = field-vchar 238   // field-content = field-vchar
253   // [ 1*( SP / HTAB / field-vchar ) field-vchar ] 239   // [ 1*( SP / HTAB / field-vchar ) field-vchar ]
254   // field-vchar = VCHAR / obs-text 240   // field-vchar = VCHAR / obs-text
255   // obs-text = %x80-FF 241   // obs-text = %x80-FF
256   // VCHAR = %x21-7E 242   // VCHAR = %x21-7E
257   // ; visible (printing) characters 243   // ; visible (printing) characters
258   244  
HITCBC 259   66585 auto is_field_vchar = [](unsigned char ch) 245   66585 auto is_field_vchar = [](unsigned char ch)
260   { 246   {
HITCBC 261   66585 return (ch >= 0x21 && ch <= 0x7e) || ch >= 0x80; 247   66585 return (ch >= 0x21 && ch <= 0x7e) || ch >= 0x80;
262   }; 248   };
263   249  
HITCBC 264   15451 char const* s0 = nullptr; 250   15451 char const* s0 = nullptr;
HITCBC 265   15451 char const* s1 = nullptr; 251   15451 char const* s1 = nullptr;
266   252  
HITCBC 267   15451 bool has_crlf = false; 253   15451 bool has_crlf = false;
HITCBC 268   15451 bool has_obs_fold = false; 254   15451 bool has_obs_fold = false;
269   255  
HITCBC 270   100095 while( it < end ) 256   100095 while( it < end )
271   { 257   {
HITCBC 272   96599 auto ch = *it; 258   96599 auto ch = *it;
HITCBC 273   96599 if( ws(ch) ) 259   96599 if( ws(ch) )
274   { 260   {
HITCBC 275   17363 ++it; 261   17363 ++it;
HITCBC 276   17363 continue; 262   17363 continue;
277   } 263   }
278   264  
HITCBC 279   79236 if( ch == '\r' ) 265   79236 if( ch == '\r' )
280   { 266   {
281   // too short to know if we have a potential obs-fold 267   // too short to know if we have a potential obs-fold
282   // occurrence 268   // occurrence
HITCBC 283   12651 if( end - it < 2 ) 269   12651 if( end - it < 2 )
HITCBC 284 - 592 BOOST_HTTP_RETURN_EC( 270 + 592 return grammar::error::need_more;
285 - grammar::error::need_more);  
286   271  
HITCBC 287   12059 if( it[1] != '\n' ) 272   12059 if( it[1] != '\n' )
HITCBC 288   53 goto done; 273   53 goto done;
289   274  
HITCBC 290   12006 if( end - it < 3 ) 275   12006 if( end - it < 3 )
HITCBC 291 - 546 BOOST_HTTP_RETURN_EC( 276 + 546 return grammar::error::need_more;
292 - grammar::error::need_more);  
293   277  
HITCBC 294   11460 if(! ws(it[2]) ) 278   11460 if(! ws(it[2]) )
295   { 279   {
HITCBC 296   10730 has_crlf = true; 280   10730 has_crlf = true;
HITCBC 297   10730 goto done; 281   10730 goto done;
298   } 282   }
299   283  
HITCBC 300   730 has_obs_fold = true; 284   730 has_obs_fold = true;
HITCBC 301   730 it = it + 3; 285   730 it = it + 3;
HITCBC 302   730 continue; 286   730 continue;
ECB 303   730 } 287   }
304   288  
HITCBC 305   66585 if(! is_field_vchar(ch) ) 289   66585 if(! is_field_vchar(ch) )
306   { 290   {
HITCBC 307   34 goto done; 291   34 goto done;
308   } 292   }
309   293  
HITCBC 310   66551 if(! s0 ) 294   66551 if(! s0 )
HITCBC 311   14348 s0 = it; 295   14348 s0 = it;
312   296  
HITCBC 313   66551 ++it; 297   66551 ++it;
HITCBC 314   66551 s1 = it; 298   66551 s1 = it;
315   } 299   }
316   300  
HITCBC 317   3496 done: 301   3496 done:
318   // later routines wind up doing pointer 302   // later routines wind up doing pointer
319   // subtraction using the .data() member 303   // subtraction using the .data() member
320   // of the value so we need a valid 0-len range 304   // of the value so we need a valid 0-len range
HITCBC 321   14313 if(! s0 ) 305   14313 if(! s0 )
322   { 306   {
HITCBC 323   939 s0 = it; 307   939 s0 = it;
HITCBC 324   939 s1 = s0; 308   939 s1 = s0;
325   } 309   }
326   310  
HITCBC 327   14313 v.value = core::string_view(s0, s1 - s0); 311   14313 v.value = core::string_view(s0, s1 - s0);
HITCBC 328   14313 v.has_crlf = has_crlf; 312   14313 v.has_crlf = has_crlf;
HITCBC 329   14313 v.has_obs_fold = has_obs_fold; 313   14313 v.has_obs_fold = has_obs_fold;
HITCBC 330   14313 return v; 314   14313 return v;
331   } 315   }
332   316  
333   auto 317   auto
HITCBC 334   37744 field_rule_t:: 318   37744 field_rule_t::
335   parse( 319   parse(
336   char const*& it, 320   char const*& it,
337   char const* end) const noexcept -> 321   char const* end) const noexcept ->
338   system::result<value_type> 322   system::result<value_type>
339   { 323   {
HITCBC 340   37744 if(it == end) 324   37744 if(it == end)
341   { 325   {
HITCBC 342 - 979 BOOST_HTTP_RETURN_EC( 326 + 979 return grammar::error::need_more;
343 - grammar::error::need_more);  
344   } 327   }
345   // check for leading CRLF 328   // check for leading CRLF
HITCBC 346   36765 if(it[0] == '\r') 329   36765 if(it[0] == '\r')
347   { 330   {
HITCBC 348   10641 ++it; 331   10641 ++it;
HITCBC 349   10641 if(it == end) 332   10641 if(it == end)
350   { 333   {
HITCBC 351 - 489 BOOST_HTTP_RETURN_EC( 334 + 489 return grammar::error::need_more;
352 - grammar::error::need_more);  
353   } 335   }
HITCBC 354   10152 if(*it != '\n') 336   10152 if(*it != '\n')
355   { 337   {
HITCBC 356 - 21 BOOST_HTTP_RETURN_EC( 338 + 21 return grammar::error::mismatch;
357 - grammar::error::mismatch);  
358   } 339   }
359   // end of fields 340   // end of fields
HITCBC 360   10131 ++it; 341   10131 ++it;
HITCBC 361 - 10131 BOOST_HTTP_RETURN_EC( 342 + 10131 return grammar::error::end_of_range;
362 - grammar::error::end_of_range);  
363   } 343   }
364   344  
HITCBC 365   26124 value_type v; 345   26124 value_type v;
366   auto rv = grammar::parse( 346   auto rv = grammar::parse(
HITCBC 367   26124 it, end, grammar::tuple_rule( 347   26124 it, end, grammar::tuple_rule(
368   field_name_rule, 348   field_name_rule,
HITCBC 369   26124 grammar::delim_rule(':'), 349   26124 grammar::delim_rule(':'),
370   field_value_rule, 350   field_value_rule,
HITCBC 371   26124 crlf_rule)); 351   26124 crlf_rule));
372   352  
HITCBC 373   26124 if( rv.has_error() ) 353   26124 if( rv.has_error() )
HITCBC 374   15410 return rv.error(); 354   15410 return rv.error();
375   355  
HITCBC 376   10714 auto val = rv.value(); 356   10714 auto val = rv.value();
HITCBC 377   10714 v.name = std::get<0>(val); 357   10714 v.name = std::get<0>(val);
HITCBC 378   10714 v.value = std::get<2>(val).value; 358   10714 v.value = std::get<2>(val).value;
HITCBC 379   10714 v.has_obs_fold = std::get<2>(val).has_obs_fold; 359   10714 v.has_obs_fold = std::get<2>(val).has_obs_fold;
380   360  
HITCBC 381   10714 return v; 361   10714 return v;
382   } 362   }
383   363  
384   //------------------------------------------------ 364   //------------------------------------------------
385   365  
386   void 366   void
HITCBC 387   244 remove_obs_fold( 367   244 remove_obs_fold(
388   char* it, 368   char* it,
389   char const* const end) noexcept 369   char const* const end) noexcept
390   { 370   {
HITCBC 391   2262 while(it != end) 371   2262 while(it != end)
392   { 372   {
HITCBC 393   2236 if(*it != '\r') 373   2236 if(*it != '\r')
394   { 374   {
HITCBC 395   1637 ++it; 375   1637 ++it;
HITCBC 396   1637 continue; 376   1637 continue;
397   } 377   }
HITCBC 398   599 if(end - it < 3) 378   599 if(end - it < 3)
HITCBC 399   218 break; 379   218 break;
HITCBC 400   381 BOOST_ASSERT(it[1] == '\n'); 380   381 BOOST_ASSERT(it[1] == '\n');
HITCBC 401   762 if( it[1] == '\n' && 381   762 if( it[1] == '\n' &&
HITCBC 402   381 ws(it[2])) 382   381 ws(it[2]))
403   { 383   {
HITCBC 404   378 it[0] = ' '; 384   378 it[0] = ' ';
HITCBC 405   378 it[1] = ' '; 385   378 it[1] = ' ';
HITCBC 406   378 it += 3; 386   378 it += 3;
407   } 387   }
408   else 388   else
409   { 389   {
HITCBC 410   3 ++it; 390   3 ++it;
411   } 391   }
412   } 392   }
HITCBC 413   244 } 393   244 }
414   394  
415   } // detail 395   } // detail
416   } // http 396   } // http
417   } // boost 397   } // boost