100.00% Lines (269/269) 100.00% Functions (66/66)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 2   // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3   // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com) 3   // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
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/boostorg/url 8   // Official repository: https://github.com/boostorg/url
9   // 9   //
10   10  
11   #ifndef BOOST_URL_GRAMMAR_IMPL_RANGE_HPP 11   #ifndef BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
12   #define BOOST_URL_GRAMMAR_IMPL_RANGE_HPP 12   #define BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
13   13  
14   #include <boost/url/detail/except.hpp> 14   #include <boost/url/detail/except.hpp>
15   #include <boost/url/grammar/error.hpp> 15   #include <boost/url/grammar/error.hpp>
16   #include <boost/url/grammar/recycled.hpp> 16   #include <boost/url/grammar/recycled.hpp>
17   #include <boost/core/empty_value.hpp> 17   #include <boost/core/empty_value.hpp>
18   #include <boost/assert.hpp> 18   #include <boost/assert.hpp>
19   #include <boost/core/detail/static_assert.hpp> 19   #include <boost/core/detail/static_assert.hpp>
20   #include <exception> 20   #include <exception>
21   #include <iterator> 21   #include <iterator>
22   #include <new> 22   #include <new>
23   #include <utility> 23   #include <utility>
24   #include <type_traits> 24   #include <type_traits>
25   25  
26   #include <stddef.h> // ::max_align_t 26   #include <stddef.h> // ::max_align_t
27   27  
28   namespace boost { 28   namespace boost {
29   namespace urls { 29   namespace urls {
30   namespace grammar { 30   namespace grammar {
31   31  
32   //------------------------------------------------ 32   //------------------------------------------------
33   // 33   //
34   // any_rule 34   // any_rule
35   // 35   //
36   //------------------------------------------------ 36   //------------------------------------------------
37   37  
38   template<class T> 38   template<class T>
39   struct any_rule<T>::impl_base 39   struct any_rule<T>::impl_base
40   { 40   {
41   virtual 41   virtual
HITCBC 42   1035 ~impl_base() = default; 42   1035 ~impl_base() = default;
43   43  
44   virtual 44   virtual
45   void 45   void
HITCBC 46   1 move(void* dest) noexcept 46   1 move(void* dest) noexcept
47   { 47   {
HITCBC 48   2 ::new(dest) impl_base( 48   2 ::new(dest) impl_base(
HITCBC 49   1 std::move(*this)); 49   1 std::move(*this));
HITCBC 50   1 } 50   1 }
51   51  
52   virtual 52   virtual
53   void 53   void
HITCBC 54   1 copy(void* dest) const noexcept 54   1 copy(void* dest) const noexcept
55   { 55   {
HITCBC 56   1 ::new(dest) impl_base(*this); 56   1 ::new(dest) impl_base(*this);
HITCBC 57   1 } 57   1 }
58   58  
59   virtual 59   virtual
60   system::result<T> 60   system::result<T>
HITCBC 61   1 first( 61   1 first(
62   char const*&, 62   char const*&,
63   char const*) const noexcept 63   char const*) const noexcept
64   { 64   {
HITCBC 65   1 return system::error_code{}; 65   1 return system::error_code{};
66   } 66   }
67   67  
68   virtual 68   virtual
69   system::result<T> 69   system::result<T>
HITCBC 70   1 next( 70   1 next(
71   char const*&, 71   char const*&,
72   char const*) const noexcept 72   char const*) const noexcept
73   { 73   {
HITCBC 74   1 return system::error_code{}; 74   1 return system::error_code{};
75   } 75   }
76   }; 76   };
77   77  
78   //------------------------------------------------ 78   //------------------------------------------------
79   79  
80   // small 80   // small
81   template<class T> 81   template<class T>
82   template<class R, bool Small> 82   template<class R, bool Small>
83   struct any_rule<T>::impl1 83   struct any_rule<T>::impl1
84   : impl_base 84   : impl_base
85   , private empty_value<R> 85   , private empty_value<R>
86   { 86   {
87   explicit 87   explicit
HITCBC 88   13 impl1(R const& next) noexcept 88   13 impl1(R const& next) noexcept
89   : empty_value<R>( 89   : empty_value<R>(
90   empty_init, 90   empty_init,
HITCBC 91   13 next) 91   13 next)
92   { 92   {
HITCBC 93   13 } 93   13 }
94   94  
95   private: 95   private:
HITCBC 96   49 impl1(impl1&&) noexcept = default; 96   49 impl1(impl1&&) noexcept = default;
HITCBC 97   2 impl1(impl1 const&) noexcept = default; 97   2 impl1(impl1 const&) noexcept = default;
98   98  
99   void 99   void
HITCBC 100   49 move(void* dest 100   49 move(void* dest
101   ) noexcept override 101   ) noexcept override
102   { 102   {
HITCBC 103   98 ::new(dest) impl1( 103   98 ::new(dest) impl1(
HITCBC 104   49 std::move(*this)); 104   49 std::move(*this));
HITCBC 105   49 } 105   49 }
106   106  
107   void 107   void
HITCBC 108   2 copy(void* dest 108   2 copy(void* dest
109   ) const noexcept override 109   ) const noexcept override
110   { 110   {
HITCBC 111   2 ::new(dest) impl1(*this); 111   2 ::new(dest) impl1(*this);
HITCBC 112   2 } 112   2 }
113   113  
114   system::result<T> 114   system::result<T>
HITCBC 115   5 first( 115   5 first(
116   char const*& it, 116   char const*& it,
117   char const* end) 117   char const* end)
118   const noexcept override 118   const noexcept override
119   { 119   {
HITCBC 120   5 return grammar::parse( 120   5 return grammar::parse(
HITCBC 121   5 it, end, this->get()); 121   5 it, end, this->get());
122   } 122   }
123   123  
124   system::result<T> 124   system::result<T>
HITCBC 125   8 next( 125   8 next(
126   char const*& it, 126   char const*& it,
127   char const* end) 127   char const* end)
128   const noexcept override 128   const noexcept override
129   { 129   {
HITCBC 130   8 return grammar::parse( 130   8 return grammar::parse(
HITCBC 131   8 it, end, this->get()); 131   8 it, end, this->get());
132   } 132   }
133   }; 133   };
134   134  
135   //------------------------------------------------ 135   //------------------------------------------------
136   136  
137   // big 137   // big
138   template<class T> 138   template<class T>
139   template<class R> 139   template<class R>
140   struct any_rule<T>::impl1<R, false> 140   struct any_rule<T>::impl1<R, false>
141   : impl_base 141   : impl_base
142   { 142   {
143   explicit 143   explicit
HITCBC 144   6 impl1(R const& next) noexcept 144   6 impl1(R const& next) noexcept
HITCBC 145   6 { 145   6 {
HITCBC 146   6 ::new(p_->addr()) impl{next}; 146   6 ::new(p_->addr()) impl{next};
HITCBC 147   6 } 147   6 }
148   148  
149   private: 149   private:
150   struct impl 150   struct impl
151   { 151   {
152   R r; 152   R r;
153   }; 153   };
154   154  
155   recycled_ptr< 155   recycled_ptr<
156   aligned_storage<impl>> p_; 156   aligned_storage<impl>> p_;
157   157  
HITCBC 158   14 impl1(impl1&&) noexcept = default; 158   14 impl1(impl1&&) noexcept = default;
HITCBC 159   2 impl1(impl1 const&) noexcept = default; 159   2 impl1(impl1 const&) noexcept = default;
160   160  
161   impl const& 161   impl const&
HITCBC 162   15 get() const noexcept 162   15 get() const noexcept
163   { 163   {
164   return *reinterpret_cast< 164   return *reinterpret_cast<
HITCBC 165   15 impl const*>(p_->addr()); 165   15 impl const*>(p_->addr());
166   } 166   }
167   167  
HITCBC 168   22 ~impl1() 168   22 ~impl1()
169   { 169   {
HITCBC 170   22 if(p_) 170   22 if(p_)
HITCBC 171   8 get().~impl(); 171   8 get().~impl();
HITCBC 172   44 } 172   44 }
173   173  
174   void 174   void
HITCBC 175   14 move(void* dest 175   14 move(void* dest
176   ) noexcept override 176   ) noexcept override
177   { 177   {
HITCBC 178   28 ::new(dest) impl1( 178   28 ::new(dest) impl1(
HITCBC 179   14 std::move(*this)); 179   14 std::move(*this));
HITCBC 180   14 } 180   14 }
181   181  
182   void 182   void
HITCBC 183   2 copy(void* dest 183   2 copy(void* dest
184   ) const noexcept override 184   ) const noexcept override
185   { 185   {
HITCBC 186   2 ::new(dest) impl1(*this); 186   2 ::new(dest) impl1(*this);
HITCBC 187   2 } 187   2 }
188   188  
189   system::result<T> 189   system::result<T>
HITCBC 190   2 first( 190   2 first(
191   char const*& it, 191   char const*& it,
192   char const* end) 192   char const* end)
193   const noexcept override 193   const noexcept override
194   { 194   {
HITCBC 195   2 return grammar::parse( 195   2 return grammar::parse(
HITCBC 196   2 it, end, this->get().r); 196   2 it, end, this->get().r);
197   } 197   }
198   198  
199   system::result<T> 199   system::result<T>
HITCBC 200   5 next( 200   5 next(
201   char const*& it, 201   char const*& it,
202   char const* end) 202   char const* end)
203   const noexcept override 203   const noexcept override
204   { 204   {
HITCBC 205   5 return grammar::parse( 205   5 return grammar::parse(
HITCBC 206   5 it, end, this->get().r); 206   5 it, end, this->get().r);
207   } 207   }
208   }; 208   };
209   209  
210   //------------------------------------------------ 210   //------------------------------------------------
211   211  
212   // small 212   // small
213   template<class T> 213   template<class T>
214   template< 214   template<
215   class R0, class R1, bool Small> 215   class R0, class R1, bool Small>
216   struct any_rule<T>::impl2 216   struct any_rule<T>::impl2
217   : impl_base 217   : impl_base
218   , private empty_value<R0, 0> 218   , private empty_value<R0, 0>
219   , private empty_value<R1, 1> 219   , private empty_value<R1, 1>
220   { 220   {
HITCBC 221   119 impl2( 221   119 impl2(
222   R0 const& first, 222   R0 const& first,
223   R1 const& next) noexcept 223   R1 const& next) noexcept
224   : empty_value<R0,0>( 224   : empty_value<R0,0>(
225   empty_init, first) 225   empty_init, first)
226   , empty_value<R1,1>( 226   , empty_value<R1,1>(
HITCBC 227   119 empty_init, next) 227   119 empty_init, next)
228   { 228   {
HITCBC 229   119 } 229   119 }
230   230  
231   private: 231   private:
HITCBC 232   582 impl2(impl2&&) noexcept = default; 232   582 impl2(impl2&&) noexcept = default;
HITCBC 233   225 impl2(impl2 const&) noexcept = default; 233   225 impl2(impl2 const&) noexcept = default;
234   234  
235   void 235   void
HITCBC 236   582 move(void* dest 236   582 move(void* dest
237   ) noexcept override 237   ) noexcept override
238   { 238   {
HITCBC 239   1164 ::new(dest) impl2( 239   1164 ::new(dest) impl2(
HITCBC 240   582 std::move(*this)); 240   582 std::move(*this));
HITCBC 241   582 } 241   582 }
242   242  
243   void 243   void
HITCBC 244   225 copy(void* dest 244   225 copy(void* dest
245   ) const noexcept override 245   ) const noexcept override
246   { 246   {
HITCBC 247   225 ::new(dest) impl2(*this); 247   225 ::new(dest) impl2(*this);
HITCBC 248   225 } 248   225 }
249   249  
250   system::result<T> 250   system::result<T>
HITCBC 251   117 first( 251   117 first(
252   char const*& it, 252   char const*& it,
253   char const* end) 253   char const* end)
254   const noexcept override 254   const noexcept override
255   { 255   {
HITCBC 256   5 return grammar::parse(it, end, 256   5 return grammar::parse(it, end,
257   empty_value< 257   empty_value<
HITCBC 258   117 R0,0>::get()); 258   117 R0,0>::get());
259   } 259   }
260   260  
261   system::result<T> 261   system::result<T>
HITCBC 262   335 next( 262   335 next(
263   char const*& it, 263   char const*& it,
264   char const* end) 264   char const* end)
265   const noexcept override 265   const noexcept override
266   { 266   {
HITCBC 267   9 return grammar::parse(it, end, 267   9 return grammar::parse(it, end,
268   empty_value< 268   empty_value<
HITCBC 269   335 R1,1>::get()); 269   335 R1,1>::get());
270   } 270   }
271   }; 271   };
272   272  
273   //------------------------------------------------ 273   //------------------------------------------------
274   274  
275   // big 275   // big
276   template<class T> 276   template<class T>
277   template< 277   template<
278   class R0, class R1> 278   class R0, class R1>
279   struct any_rule<T>::impl2<R0, R1, false> 279   struct any_rule<T>::impl2<R0, R1, false>
280   : impl_base 280   : impl_base
281   { 281   {
HITCBC 282   4 impl2( 282   4 impl2(
283   R0 const& first, 283   R0 const& first,
284   R1 const& next) noexcept 284   R1 const& next) noexcept
HITCBC 285   4 { 285   4 {
HITCBC 286   4 ::new(p_->addr()) impl{ 286   4 ::new(p_->addr()) impl{
287   first, next}; 287   first, next};
HITCBC 288   4 } 288   4 }
289   289  
290   private: 290   private:
291   struct impl 291   struct impl
292   { 292   {
293   R0 first; 293   R0 first;
294   R1 next; 294   R1 next;
295   }; 295   };
296   296  
297   recycled_ptr< 297   recycled_ptr<
298   aligned_storage<impl>> p_; 298   aligned_storage<impl>> p_;
299   299  
HITCBC 300   14 impl2(impl2&&) noexcept = default; 300   14 impl2(impl2&&) noexcept = default;
HITCBC 301   2 impl2(impl2 const&) noexcept = default; 301   2 impl2(impl2 const&) noexcept = default;
302   302  
303   impl const& 303   impl const&
HITCBC 304   13 get() const noexcept 304   13 get() const noexcept
305   { 305   {
306   return *reinterpret_cast< 306   return *reinterpret_cast<
HITCBC 307   13 impl const*>(p_->addr()); 307   13 impl const*>(p_->addr());
308   } 308   }
309   309  
HITCBC 310   20 ~impl2() 310   20 ~impl2()
311   { 311   {
HITCBC 312   20 if(p_) 312   20 if(p_)
HITCBC 313   6 get().~impl(); 313   6 get().~impl();
HITCBC 314   40 } 314   40 }
315   315  
316   void 316   void
HITCBC 317   14 move(void* dest 317   14 move(void* dest
318   ) noexcept override 318   ) noexcept override
319   { 319   {
HITCBC 320   28 ::new(dest) impl2( 320   28 ::new(dest) impl2(
HITCBC 321   14 std::move(*this)); 321   14 std::move(*this));
HITCBC 322   14 } 322   14 }
323   323  
324   void 324   void
HITCBC 325   2 copy(void* dest 325   2 copy(void* dest
326   ) const noexcept override 326   ) const noexcept override
327   { 327   {
HITCBC 328   2 ::new(dest) impl2(*this); 328   2 ::new(dest) impl2(*this);
HITCBC 329   2 } 329   2 }
330   330  
331   system::result<T> 331   system::result<T>
HITCBC 332   2 first( 332   2 first(
333   char const*& it, 333   char const*& it,
334   char const* end) 334   char const* end)
335   const noexcept override 335   const noexcept override
336   { 336   {
HITCBC 337   2 return grammar::parse( 337   2 return grammar::parse(
HITCBC 338   2 it, end, get().first); 338   2 it, end, get().first);
339   } 339   }
340   340  
341   system::result<T> 341   system::result<T>
HITCBC 342   5 next( 342   5 next(
343   char const*& it, 343   char const*& it,
344   char const* end) 344   char const* end)
345   const noexcept override 345   const noexcept override
346   { 346   {
HITCBC 347   5 return grammar::parse( 347   5 return grammar::parse(
HITCBC 348   5 it, end, get().next); 348   5 it, end, get().next);
349   } 349   }
350   }; 350   };
351   351  
352   //------------------------------------------------ 352   //------------------------------------------------
353   353  
354   template<class T> 354   template<class T>
355   typename any_rule<T>::impl_base& 355   typename any_rule<T>::impl_base&
HITCBC 356   1697 any_rule<T>:: 356   1697 any_rule<T>::
357   get() noexcept 357   get() noexcept
358   { 358   {
359   return *reinterpret_cast< 359   return *reinterpret_cast<
HITCBC 360   1697 impl_base*>(sb_.addr()); 360   1697 impl_base*>(sb_.addr());
361   } 361   }
362   362  
363   template<class T> 363   template<class T>
364   typename any_rule<T>::impl_base const& 364   typename any_rule<T>::impl_base const&
HITCBC 365   711 any_rule<T>:: 365   711 any_rule<T>::
366   get() const noexcept 366   get() const noexcept
367   { 367   {
368   return *reinterpret_cast< 368   return *reinterpret_cast<
HITCBC 369   711 impl_base const*>(sb_.addr()); 369   711 impl_base const*>(sb_.addr());
370   } 370   }
371   371  
372   372  
373   template<class T> 373   template<class T>
HITCBC 374   1 any_rule<T>:: 374   1 any_rule<T>::
375   any_rule() noexcept 375   any_rule() noexcept
376   { 376   {
HITCBC 377   1 ::new(sb_.addr()) impl_base{}; 377   1 ::new(sb_.addr()) impl_base{};
HITCBC 378   1 char const* it = nullptr; 378   1 char const* it = nullptr;
HITCBC 379   1 get().first(it, nullptr); 379   1 get().first(it, nullptr);
HITCBC 380   1 get().next(it, nullptr); 380   1 get().next(it, nullptr);
HITCBC 381   1 } 381   1 }
382   382  
383   383  
384   template<class T> 384   template<class T>
HITCBC 385   659 any_rule<T>:: 385   659 any_rule<T>::
386   any_rule(any_rule&& other) noexcept 386   any_rule(any_rule&& other) noexcept
387   { 387   {
HITCBC 388   659 other.get().move(sb_.addr()); 388   659 other.get().move(sb_.addr());
HITCBC 389   659 } 389   659 }
390   390  
391   391  
392   template<class T> 392   template<class T>
HITCBC 393   229 any_rule<T>:: 393   229 any_rule<T>::
394   any_rule(any_rule const& other) noexcept 394   any_rule(any_rule const& other) noexcept
395   { 395   {
HITCBC 396   229 other.get().copy(sb_.addr()); 396   229 other.get().copy(sb_.addr());
HITCBC 397   229 } 397   229 }
398   398  
399   399  
400   template<class T> 400   template<class T>
401   any_rule<T>& 401   any_rule<T>&
HITCBC 402   2 any_rule<T>:: 402   2 any_rule<T>::
403   operator=(any_rule&& other) noexcept 403   operator=(any_rule&& other) noexcept
404   { 404   {
HITCBC 405   2 if(this == &other) 405   2 if(this == &other)
HITCBC 406   1 return *this; 406   1 return *this;
HITCBC 407   1 get().~impl_base(); 407   1 get().~impl_base();
HITCBC 408   1 other.get().move(sb_.addr()); 408   1 other.get().move(sb_.addr());
HITCBC 409   1 return *this; 409   1 return *this;
410   } 410   }
411   411  
412   412  
413   template<class T> 413   template<class T>
414   any_rule<T>& 414   any_rule<T>&
HITCBC 415   4 any_rule<T>:: 415   4 any_rule<T>::
416   operator=(any_rule const& other) noexcept 416   operator=(any_rule const& other) noexcept
417   { 417   {
HITCBC 418   4 if(this == &other) 418   4 if(this == &other)
HITCBC 419   1 return *this; 419   1 return *this;
HITCBC 420   3 get().~impl_base(); 420   3 get().~impl_base();
HITCBC 421   3 other.get().copy(sb_.addr()); 421   3 other.get().copy(sb_.addr());
HITCBC 422   3 return *this; 422   3 return *this;
423   } 423   }
424   424  
425   425  
426   template<class T> 426   template<class T>
HITCBC 427   1031 any_rule<T>:: 427   1031 any_rule<T>::
428   ~any_rule() 428   ~any_rule()
429   { 429   {
HITCBC 430   1031 get().~impl_base(); 430   1031 get().~impl_base();
HITCBC 431   1031 } 431   1031 }
432   432  
433   433  
434   template<class T> 434   template<class T>
435   template<class R> 435   template<class R>
HITCBC 436   19 any_rule<T>:: 436   19 any_rule<T>::
437   any_rule( 437   any_rule(
438   R const& next) 438   R const& next)
439   { 439   {
440   static_assert( 440   static_assert(
441   ::boost::urls::grammar::is_rule<R>::value, 441   ::boost::urls::grammar::is_rule<R>::value,
442   "Rule requirements not met"); 442   "Rule requirements not met");
443   static_assert( 443   static_assert(
444   std::is_same<typename R::value_type, T>::value, 444   std::is_same<typename R::value_type, T>::value,
445   "Rule value_type mismatch"); 445   "Rule value_type mismatch");
446   446  
447   BOOST_CORE_STATIC_ASSERT( 447   BOOST_CORE_STATIC_ASSERT(
448   sizeof(impl1<R, false>) <= 448   sizeof(impl1<R, false>) <=
449   BufferSize); 449   BufferSize);
450   450  
HITCBC 451   19 ::new(sb_.addr()) impl1<R, 451   19 ::new(sb_.addr()) impl1<R,
452   sizeof(impl1<R, true>) <= 452   sizeof(impl1<R, true>) <=
453   BufferSize>(next); 453   BufferSize>(next);
HITCBC 454   19 } 454   19 }
455   455  
456   //------------------------------------------------ 456   //------------------------------------------------
457   457  
458   template<class T> 458   template<class T>
459   template< 459   template<
460   class R0, class R1> 460   class R0, class R1>
HITCBC 461   123 any_rule<T>:: 461   123 any_rule<T>::
462   any_rule( 462   any_rule(
463   R0 const& first, 463   R0 const& first,
464   R1 const& next) 464   R1 const& next)
465   { 465   {
466   static_assert( 466   static_assert(
467   ::boost::urls::grammar::is_rule<R0>::value, 467   ::boost::urls::grammar::is_rule<R0>::value,
468   "Rule requirements not met"); 468   "Rule requirements not met");
469   static_assert( 469   static_assert(
470   ::boost::urls::grammar::is_rule<R1>::value, 470   ::boost::urls::grammar::is_rule<R1>::value,
471   "Rule requirements not met"); 471   "Rule requirements not met");
472   static_assert( 472   static_assert(
473   std::is_same<typename R0::value_type, T>::value, 473   std::is_same<typename R0::value_type, T>::value,
474   "First rule value_type mismatch"); 474   "First rule value_type mismatch");
475   static_assert( 475   static_assert(
476   std::is_same<typename R1::value_type, T>::value, 476   std::is_same<typename R1::value_type, T>::value,
477   "Next rule value_type mismatch"); 477   "Next rule value_type mismatch");
478   478  
479   BOOST_CORE_STATIC_ASSERT( 479   BOOST_CORE_STATIC_ASSERT(
480   sizeof(impl2<R0, R1, false>) <= 480   sizeof(impl2<R0, R1, false>) <=
481   BufferSize); 481   BufferSize);
482   482  
HITCBC 483   123 ::new(sb_.addr()) impl2<R0, R1, 483   123 ::new(sb_.addr()) impl2<R0, R1,
484   sizeof(impl2<R0, R1, true> 484   sizeof(impl2<R0, R1, true>
485   ) <= BufferSize>( 485   ) <= BufferSize>(
486   first, next); 486   first, next);
HITCBC 487   123 } 487   123 }
488   488  
489   //------------------------------------------------ 489   //------------------------------------------------
490   490  
491   template<class T> 491   template<class T>
492   system::result<T> 492   system::result<T>
HITCBC 493   126 any_rule<T>:: 493   126 any_rule<T>::
494   first( 494   first(
495   char const*& it, 495   char const*& it,
496   char const* end) const noexcept 496   char const* end) const noexcept
497   { 497   {
HITCBC 498   126 return get().first(it, end); 498   126 return get().first(it, end);
499   } 499   }
500   500  
501   //------------------------------------------------ 501   //------------------------------------------------
502   502  
503   template<class T> 503   template<class T>
504   system::result<T> 504   system::result<T>
HITCBC 505   353 any_rule<T>:: 505   353 any_rule<T>::
506   next( 506   next(
507   char const*& it, 507   char const*& it,
508   char const* end) const noexcept 508   char const* end) const noexcept
509   { 509   {
HITCBC 510   353 return get().next(it, end); 510   353 return get().next(it, end);
511   } 511   }
512   512  
513   //------------------------------------------------ 513   //------------------------------------------------
514   // 514   //
515   // range 515   // range
516   // 516   //
517   //------------------------------------------------ 517   //------------------------------------------------
518   518  
519   template<class T, class RangeRule> 519   template<class T, class RangeRule>
HITCBC 520   889 range<T, RangeRule>:: 520   889 range<T, RangeRule>::
521   ~range() = default; 521   ~range() = default;
522   522  
523   template<class T, class RangeRule> 523   template<class T, class RangeRule>
HITCBC 524   1 range<T, RangeRule>:: 524   1 range<T, RangeRule>::
525   range() noexcept = default; 525   range() noexcept = default;
526   526  
527   template<class T, class RangeRule> 527   template<class T, class RangeRule>
HITCBC 528   519 range<T, RangeRule>:: 528   519 range<T, RangeRule>::
529   range( 529   range(
530   range&& other) noexcept 530   range&& other) noexcept
531   : detail::range_base_storage< 531   : detail::range_base_storage<
HITCBC 532   519 RangeRule>(std::move(other.rule())) 532   519 RangeRule>(std::move(other.rule()))
HITCBC 533   519 , s_(other.s_) 533   519 , s_(other.s_)
HITCBC 534   1038 , n_(other.n_) 534   1038 , n_(other.n_)
535   { 535   {
HITCBC 536   519 other.s_ = {}; 536   519 other.s_ = {};
HITCBC 537   519 other.n_ = 0; 537   519 other.n_ = 0;
HITCBC 538   519 } 538   519 }
539   539  
540   template<class T, class RangeRule> 540   template<class T, class RangeRule>
HITCBC 541   229 range<T, RangeRule>:: 541   229 range<T, RangeRule>::
542   range( 542   range(
543   range const& other) noexcept 543   range const& other) noexcept
544   : detail::range_base_storage< 544   : detail::range_base_storage<
545   RangeRule>(other.rule()) 545   RangeRule>(other.rule())
HITCBC 546   229 , s_(other.s_) 546   229 , s_(other.s_)
HITCBC 547   229 , n_(other.n_) 547   229 , n_(other.n_)
548   { 548   {
HITCBC 549   229 } 549   229 }
550   550  
551   template<class T, class RangeRule> 551   template<class T, class RangeRule>
552   auto 552   auto
HITCBC 553   2 range<T, RangeRule>:: 553   2 range<T, RangeRule>::
554   operator=(range&& other) noexcept 554   operator=(range&& other) noexcept
555   -> range& 555   -> range&
556   { 556   {
HITCBC 557   2 if(this == &other) 557   2 if(this == &other)
HITCBC 558   1 return *this; 558   1 return *this;
559   static_cast< 559   static_cast<
560   detail::range_base_storage< 560   detail::range_base_storage<
HITCBC 561   1 RangeRule>&>(*this) = 561   1 RangeRule>&>(*this) =
HITCBC 562   1 std::move(static_cast< 562   1 std::move(static_cast<
563   detail::range_base_storage< 563   detail::range_base_storage<
564   RangeRule>&>(other)); 564   RangeRule>&>(other));
HITCBC 565   1 s_ = other.s_; 565   1 s_ = other.s_;
HITCBC 566   1 n_ = other.n_; 566   1 n_ = other.n_;
HITCBC 567   1 other.s_ = {}; 567   1 other.s_ = {};
HITCBC 568   1 other.n_ = 0; 568   1 other.n_ = 0;
HITCBC 569   1 return *this; 569   1 return *this;
570   } 570   }
571   571  
572   template<class T, class RangeRule> 572   template<class T, class RangeRule>
573   auto 573   auto
HITCBC 574   4 range<T, RangeRule>:: 574   4 range<T, RangeRule>::
575   operator=(range const& other) noexcept 575   operator=(range const& other) noexcept
576   -> range& 576   -> range&
577   { 577   {
HITCBC 578   4 if(this == &other) 578   4 if(this == &other)
HITCBC 579   1 return *this; 579   1 return *this;
580   static_cast< 580   static_cast<
581   detail::range_base_storage< 581   detail::range_base_storage<
HITCBC 582   3 RangeRule>&>(*this) = 582   3 RangeRule>&>(*this) =
583   static_cast< 583   static_cast<
584   detail::range_base_storage< 584   detail::range_base_storage<
585   RangeRule> const&>(other); 585   RangeRule> const&>(other);
HITCBC 586   3 s_ = other.s_; 586   3 s_ = other.s_;
HITCBC 587   3 n_ = other.n_; 587   3 n_ = other.n_;
HITCBC 588   3 return *this; 588   3 return *this;
589   } 589   }
590   590  
591   //------------------------------------------------ 591   //------------------------------------------------
592   // 592   //
593   // iterator 593   // iterator
594   // 594   //
595   //------------------------------------------------ 595   //------------------------------------------------
596   596  
597   template<class T, class RangeRule> 597   template<class T, class RangeRule>
598   class range<T, RangeRule>:: 598   class range<T, RangeRule>::
599   iterator 599   iterator
600   { 600   {
601   public: 601   public:
602   using value_type = T; 602   using value_type = T;
603   using reference = T const&; 603   using reference = T const&;
604   using pointer = void const*; 604   using pointer = void const*;
605   using difference_type = 605   using difference_type =
606   std::ptrdiff_t; 606   std::ptrdiff_t;
607   using iterator_category = 607   using iterator_category =
608   std::forward_iterator_tag; 608   std::forward_iterator_tag;
609   609  
610   iterator() = default; 610   iterator() = default;
611   iterator( 611   iterator(
612   iterator const&) = default; 612   iterator const&) = default;
613   iterator& operator=( 613   iterator& operator=(
614   iterator const&) = default; 614   iterator const&) = default;
615   615  
616   reference 616   reference
HITCBC 617   734 operator*() const noexcept 617   734 operator*() const noexcept
618   { 618   {
HITCBC 619   734 return *rv_; 619   734 return *rv_;
620   } 620   }
621   621  
622   bool 622   bool
HITCBC 623   479 operator==( 623   479 operator==(
624   iterator const& other) const noexcept 624   iterator const& other) const noexcept
625   { 625   {
626   // can't compare iterators 626   // can't compare iterators
627   // from different containers! 627   // from different containers!
HITCBC 628   479 BOOST_ASSERT(r_ == other.r_); 628   479 BOOST_ASSERT(r_ == other.r_);
629   629  
HITCBC 630   479 return p_ == other.p_; 630   479 return p_ == other.p_;
631   } 631   }
632   632  
633   bool 633   bool
HITCBC 634   477 operator!=( 634   477 operator!=(
635   iterator const& other) const noexcept 635   iterator const& other) const noexcept
636   { 636   {
HITCBC 637   477 return !(*this == other); 637   477 return !(*this == other);
638   } 638   }
639   639  
640   iterator& 640   iterator&
HITCBC 641   353 operator++() noexcept 641   353 operator++() noexcept
642   { 642   {
HITCBC 643   353 BOOST_ASSERT( 643   353 BOOST_ASSERT(
644   p_ != nullptr); 644   p_ != nullptr);
HITCBC 645   353 auto const end = 645   353 auto const end =
HITCBC 646   353 r_->s_.data() + 646   353 r_->s_.data() +
HITCBC 647   353 r_->s_.size(); 647   353 r_->s_.size();
HITCBC 648   353 rv_ = r_->rule().next(p_, end); 648   353 rv_ = r_->rule().next(p_, end);
HITCBC 649   353 if( !rv_ ) 649   353 if( !rv_ )
HITCBC 650   123 p_ = nullptr; 650   123 p_ = nullptr;
HITCBC 651   353 return *this; 651   353 return *this;
652   } 652   }
653   653  
654   iterator 654   iterator
655   operator++(int) noexcept 655   operator++(int) noexcept
656   { 656   {
657   auto tmp = *this; 657   auto tmp = *this;
658   ++*this; 658   ++*this;
659   return tmp; 659   return tmp;
660   } 660   }
661   661  
662   private: 662   private:
663   friend class range<T, RangeRule>; 663   friend class range<T, RangeRule>;
664   664  
665   range<T, RangeRule> const* r_ = nullptr; 665   range<T, RangeRule> const* r_ = nullptr;
666   char const* p_ = nullptr; 666   char const* p_ = nullptr;
667   system::result<T> rv_; 667   system::result<T> rv_;
668   668  
HITCBC 669   126 iterator( 669   126 iterator(
670   range<T, RangeRule> const& r) noexcept 670   range<T, RangeRule> const& r) noexcept
HITCBC 671   126 : r_(&r) 671   126 : r_(&r)
HITCBC 672   126 , p_(r.s_.data()) 672   126 , p_(r.s_.data())
673   { 673   {
HITCBC 674   126 auto const end = 674   126 auto const end =
HITCBC 675   126 r_->s_.data() + 675   126 r_->s_.data() +
HITCBC 676   126 r_->s_.size(); 676   126 r_->s_.size();
HITCBC 677   126 rv_ = r_->rule().first(p_, end); 677   126 rv_ = r_->rule().first(p_, end);
HITCBC 678   126 if( !rv_ ) 678   126 if( !rv_ )
HITCBC 679   3 p_ = nullptr; 679   3 p_ = nullptr;
HITCBC 680   126 } 680   126 }
681   681  
682   constexpr 682   constexpr
HITCBC 683   126 iterator( 683   126 iterator(
684   range<T, RangeRule> const& r, 684   range<T, RangeRule> const& r,
685   int) noexcept 685   int) noexcept
HITCBC 686   126 : r_(&r) 686   126 : r_(&r)
HITCBC 687   126 , p_(nullptr) 687   126 , p_(nullptr)
688   { 688   {
HITCBC 689   126 } 689   126 }
690   }; 690   };
691   691  
692   //------------------------------------------------ 692   //------------------------------------------------
693   693  
694   template<class T, class RangeRule> 694   template<class T, class RangeRule>
695   typename range<T, RangeRule>::iterator 695   typename range<T, RangeRule>::iterator
HITCBC 696   126 range<T, RangeRule>:: 696   126 range<T, RangeRule>::
697   begin() const noexcept 697   begin() const noexcept
698   { 698   {
HITCBC 699   126 return iterator(*this); 699   126 return iterator(*this);
700   } 700   }
701   701  
702   //------------------------------------------------ 702   //------------------------------------------------
703   703  
704   template<class T, class RangeRule> 704   template<class T, class RangeRule>
705   typename range<T, RangeRule>::iterator 705   typename range<T, RangeRule>::iterator
HITCBC 706   126 range<T, RangeRule>:: 706   126 range<T, RangeRule>::
707   end() const noexcept 707   end() const noexcept
708   { 708   {
HITCBC 709   126 return iterator(*this, 0); 709   126 return iterator(*this, 0);
710   } 710   }
711   711  
712   //------------------------------------------------ 712   //------------------------------------------------
713   713  
714   template<class T, class RangeRule> 714   template<class T, class RangeRule>
715   range<T, RangeRule>:: 715   range<T, RangeRule>::
716   range( 716   range(
717   core::string_view s, 717   core::string_view s,
718   std::size_t n, 718   std::size_t n,
719   RangeRule const& rule) noexcept 719   RangeRule const& rule) noexcept
720   : detail::range_base_storage< 720   : detail::range_base_storage<
721   RangeRule>(rule) 721   RangeRule>(rule)
722   , s_(s) 722   , s_(s)
723   , n_(n) 723   , n_(n)
724   { 724   {
725   } 725   }
726   726  
727   //------------------------------------------------ 727   //------------------------------------------------
728   728  
729   template<class T, class RangeRule> 729   template<class T, class RangeRule>
HITCBC 730   140 range<T, RangeRule>:: 730   140 range<T, RangeRule>::
731   range( 731   range(
732   core::string_view s, 732   core::string_view s,
733   std::size_t n, 733   std::size_t n,
734   RangeRule&& rule) noexcept 734   RangeRule&& rule) noexcept
735   : detail::range_base_storage< 735   : detail::range_base_storage<
HITCBC 736   140 RangeRule>(std::move(rule)) 736   140 RangeRule>(std::move(rule))
HITCBC 737   140 , s_(s) 737   140 , s_(s)
HITCBC 738   140 , n_(n) 738   140 , n_(n)
739   { 739   {
HITCBC 740   140 } 740   140 }
741   741  
742   //------------------------------------------------ 742   //------------------------------------------------
743   743  
744   template<class R> 744   template<class R>
745   BOOST_URL_CXX20_CONSTEXPR 745   BOOST_URL_CXX20_CONSTEXPR
746   auto 746   auto
HITCBC 747   25 implementation_defined::range_rule_t<R>:: 747   25 implementation_defined::range_rule_t<R>::
748   parse( 748   parse(
749   char const*& it, 749   char const*& it,
750   char const* end) const -> 750   char const* end) const ->
751   system::result<value_type> 751   system::result<value_type>
752   { 752   {
753   using T = typename R::value_type; 753   using T = typename R::value_type;
754   754  
HITCBC 755   25 std::size_t n = 0; 755   25 std::size_t n = 0;
HITCBC 756   25 auto const it0 = it; 756   25 auto const it0 = it;
HITCBC 757   25 auto it1 = it; 757   25 auto it1 = it;
HITCBC 758   25 auto rv = (grammar::parse)( 758   25 auto rv = (grammar::parse)(
HITCBC 759   25 it, end, next_); 759   25 it, end, next_);
HITCBC 760   25 if( !rv ) 760   25 if( !rv )
761   { 761   {
HITCBC 762   3 if(rv.error() != error::end_of_range) 762   3 if(rv.error() != error::end_of_range)
763   { 763   {
764   // rewind unless error::end_of_range 764   // rewind unless error::end_of_range
HITCBC 765   3 it = it1; 765   3 it = it1;
766   } 766   }
HITCBC 767   3 if(n < N_) 767   3 if(n < N_)
768   { 768   {
769   // too few 769   // too few
HITCBC 770   2 BOOST_URL_CONSTEXPR_RETURN_EC( 770   2 BOOST_URL_CONSTEXPR_RETURN_EC(
771   error::mismatch); 771   error::mismatch);
772   } 772   }
773   // good 773   // good
HITCBC 774   2 return range<T>( 774   2 return range<T>(
HITCBC 775   1 core::string_view(it0, it - it0), 775   1 core::string_view(it0, it - it0),
HITCBC 776   3 n, any_rule<T>(next_)); 776   3 n, any_rule<T>(next_));
777   } 777   }
HITCBC 778   31 for(;;) 778   31 for(;;)
779   { 779   {
HITCBC 780   53 ++n; 780   53 ++n;
HITCBC 781   53 it1 = it; 781   53 it1 = it;
HITCBC 782   53 rv = (grammar::parse)( 782   53 rv = (grammar::parse)(
HITCBC 783   53 it, end, next_); 783   53 it, end, next_);
HITCBC 784   53 if( !rv ) 784   53 if( !rv )
785   { 785   {
HITCBC 786   18 if(rv.error() != error::end_of_range) 786   18 if(rv.error() != error::end_of_range)
787   { 787   {
788   // rewind unless error::end_of_range 788   // rewind unless error::end_of_range
HITCBC 789   18 it = it1; 789   18 it = it1;
790   } 790   }
HITCBC 791   18 break; 791   18 break;
792   } 792   }
HITCBC 793   35 if(n >= M_) 793   35 if(n >= M_)
794   { 794   {
795   // too many 795   // too many
HITCBC 796   4 BOOST_URL_CONSTEXPR_RETURN_EC( 796   4 BOOST_URL_CONSTEXPR_RETURN_EC(
797   error::mismatch); 797   error::mismatch);
798   } 798   }
799   } 799   }
HITCBC 800   18 if(n < N_) 800   18 if(n < N_)
801   { 801   {
802   // too few 802   // too few
HITCBC 803   2 BOOST_URL_CONSTEXPR_RETURN_EC( 803   2 BOOST_URL_CONSTEXPR_RETURN_EC(
804   error::mismatch); 804   error::mismatch);
805   } 805   }
806   // good 806   // good
HITCBC 807   32 return range<T>( 807   32 return range<T>(
HITCBC 808   16 core::string_view(it0, it - it0), 808   16 core::string_view(it0, it - it0),
HITCBC 809   48 n, any_rule<T>(next_)); 809   48 n, any_rule<T>(next_));
810   } 810   }
811   811  
812   //------------------------------------------------ 812   //------------------------------------------------
813   813  
814   template<class R0, class R1> 814   template<class R0, class R1>
815   BOOST_URL_CXX20_CONSTEXPR 815   BOOST_URL_CXX20_CONSTEXPR
816   auto 816   auto
HITCBC 817   131 implementation_defined::range_rule_t<R0, R1>:: 817   131 implementation_defined::range_rule_t<R0, R1>::
818   parse( 818   parse(
819   char const*& it, 819   char const*& it,
820   char const* end) const -> 820   char const* end) const ->
821   system::result<range<typename 821   system::result<range<typename
822   R0::value_type>> 822   R0::value_type>>
823   { 823   {
824   using T = typename R0::value_type; 824   using T = typename R0::value_type;
825   825  
HITCBC 826   131 std::size_t n = 0; 826   131 std::size_t n = 0;
HITCBC 827   131 auto const it0 = it; 827   131 auto const it0 = it;
HITCBC 828   131 auto it1 = it; 828   131 auto it1 = it;
HITCBC 829   131 auto rv = (grammar::parse)( 829   131 auto rv = (grammar::parse)(
HITCBC 830   131 it, end, first_); 830   131 it, end, first_);
HITCBC 831   131 if( !rv ) 831   131 if( !rv )
832   { 832   {
HITCBC 833   4 if(rv.error() != error::end_of_range) 833   4 if(rv.error() != error::end_of_range)
834   { 834   {
HITCBC 835   4 it = it1; 835   4 it = it1;
836   } 836   }
HITCBC 837   4 if(n < N_) 837   4 if(n < N_)
838   { 838   {
HITCBC 839   3 BOOST_URL_CONSTEXPR_RETURN_EC( 839   3 BOOST_URL_CONSTEXPR_RETURN_EC(
840   error::mismatch); 840   error::mismatch);
841   } 841   }
HITCBC 842   2 return range<T>( 842   2 return range<T>(
HITCBC 843   1 core::string_view(it0, it - it0), 843   1 core::string_view(it0, it - it0),
HITCBC 844   3 n, any_rule<T>(first_, next_)); 844   3 n, any_rule<T>(first_, next_));
845   } 845   }
HITCBC 846   236 for(;;) 846   236 for(;;)
847   { 847   {
HITCBC 848   363 ++n; 848   363 ++n;
HITCBC 849   363 it1 = it; 849   363 it1 = it;
HITCBC 850   363 rv = (grammar::parse)( 850   363 rv = (grammar::parse)(
HITCBC 851   363 it, end, next_); 851   363 it, end, next_);
HITCBC 852   363 if( !rv ) 852   363 if( !rv )
853   { 853   {
HITCBC 854   123 if(rv.error() != error::end_of_range) 854   123 if(rv.error() != error::end_of_range)
855   { 855   {
856   // rewind unless error::end_of_range 856   // rewind unless error::end_of_range
HITCBC 857   123 it = it1; 857   123 it = it1;
858   } 858   }
HITCBC 859   123 break; 859   123 break;
860   } 860   }
HITCBC 861   240 if(n >= M_) 861   240 if(n >= M_)
862   { 862   {
863   // too many 863   // too many
HITCBC 864   4 BOOST_URL_CONSTEXPR_RETURN_EC( 864   4 BOOST_URL_CONSTEXPR_RETURN_EC(
865   error::mismatch); 865   error::mismatch);
866   } 866   }
867   } 867   }
HITCBC 868   123 if(n < N_) 868   123 if(n < N_)
869   { 869   {
870   // too few 870   // too few
HITCBC 871   1 BOOST_URL_CONSTEXPR_RETURN_EC( 871   1 BOOST_URL_CONSTEXPR_RETURN_EC(
872   error::mismatch); 872   error::mismatch);
873   } 873   }
874   // good 874   // good
HITCBC 875   244 return range<T>( 875   244 return range<T>(
HITCBC 876   122 core::string_view(it0, it - it0), 876   122 core::string_view(it0, it - it0),
HITCBC 877   366 n, any_rule<T>(first_, next_)); 877   366 n, any_rule<T>(first_, next_));
HITCBC 878   113 } 878   113 }
879   879  
880   } // grammar 880   } // grammar
881   } // urls 881   } // urls
882   } // boost 882   } // boost
883   883  
884   #endif 884   #endif