98.51% Lines (66/67) 100.00% Functions (14/14)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2019 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/boostorg/url 7   // Official repository: https://github.com/boostorg/url
8   // 8   //
9   9  
10   #ifndef BOOST_URL_DETAIL_ANY_SEGMENTS_ITER_HPP 10   #ifndef BOOST_URL_DETAIL_ANY_SEGMENTS_ITER_HPP
11   #define BOOST_URL_DETAIL_ANY_SEGMENTS_ITER_HPP 11   #define BOOST_URL_DETAIL_ANY_SEGMENTS_ITER_HPP
12   12  
13   #include <boost/url/pct_string_view.hpp> 13   #include <boost/url/pct_string_view.hpp>
14   #include <boost/core/detail/static_assert.hpp> 14   #include <boost/core/detail/static_assert.hpp>
15   #include <cstddef> 15   #include <cstddef>
16   #include <iterator> 16   #include <iterator>
17   #include <type_traits> 17   #include <type_traits>
18   18  
19   namespace boost { 19   namespace boost {
20   namespace urls { 20   namespace urls {
21   namespace detail { 21   namespace detail {
22   22  
23   struct BOOST_SYMBOL_VISIBLE 23   struct BOOST_SYMBOL_VISIBLE
24   any_segments_iter 24   any_segments_iter
25   { 25   {
26   protected: 26   protected:
27   explicit 27   explicit
HITCBC 28   2328 any_segments_iter( 28   2328 any_segments_iter(
29   core::string_view s_ = {}) noexcept 29   core::string_view s_ = {}) noexcept
HITCBC 30   2328 : s(s_) 30   2328 : s(s_)
31   { 31   {
HITCBC 32   2328 } 32   2328 }
33   33  
HITCBC 34   2328 virtual ~any_segments_iter() = default; 34   2328 virtual ~any_segments_iter() = default;
35   35  
36   public: 36   public:
37   // this is adjusted 37   // this is adjusted
38   // when self-intersecting 38   // when self-intersecting
39   core::string_view s; 39   core::string_view s;
40   40  
41   // the first segment, 41   // the first segment,
42   // to handle special cases 42   // to handle special cases
43   core::string_view front; 43   core::string_view front;
44   44  
45   // quick number of segments 45   // quick number of segments
46   // 0 = zero 46   // 0 = zero
47   // 1 = one 47   // 1 = one
48   // 2 = two, or more 48   // 2 = two, or more
49   int fast_nseg = 0; 49   int fast_nseg = 0;
50   50  
51   // whether the segments should encode colons 51   // whether the segments should encode colons
52   // when we measure and copy. the calling 52   // when we measure and copy. the calling
53   // function uses this for the first 53   // function uses this for the first
54   // segment in some cases, such as: 54   // segment in some cases, such as:
55   // "x:y:z" -> remove_scheme -> "y%3Az" 55   // "x:y:z" -> remove_scheme -> "y%3Az"
56   // as "y:z" would no longer represent a path 56   // as "y:z" would no longer represent a path
57   bool encode_colons = false; 57   bool encode_colons = false;
58   58  
59   // Rewind the iterator to the beginning 59   // Rewind the iterator to the beginning
60   virtual void rewind() noexcept = 0; 60   virtual void rewind() noexcept = 0;
61   61  
62   // Measure and increment the current 62   // Measure and increment the current
63   // element. n is increased by the 63   // element. n is increased by the
64   // encoded size. Returns false on 64   // encoded size. Returns false on
65   // end of range. 65   // end of range.
66   virtual bool measure(std::size_t& n) = 0; 66   virtual bool measure(std::size_t& n) = 0;
67   67  
68   // Copy and increment the current 68   // Copy and increment the current
69   // element, encoding as needed. 69   // element, encoding as needed.
70   virtual void copy(char*& dest, 70   virtual void copy(char*& dest,
71   char const* end) noexcept = 0; 71   char const* end) noexcept = 0;
72   }; 72   };
73   73  
74   //------------------------------------------------ 74   //------------------------------------------------
75   // 75   //
76   // segment_iter 76   // segment_iter
77   // 77   //
78   //------------------------------------------------ 78   //------------------------------------------------
79   79  
80   // A 1-segment range 80   // A 1-segment range
81   // allowing self-intersection 81   // allowing self-intersection
82   struct BOOST_SYMBOL_VISIBLE 82   struct BOOST_SYMBOL_VISIBLE
83   segment_iter 83   segment_iter
84   : any_segments_iter 84   : any_segments_iter
85   { 85   {
HITCBC 86   920 virtual ~segment_iter() = default; 86   920 virtual ~segment_iter() = default;
87   87  
88   explicit 88   explicit
89   segment_iter( 89   segment_iter(
90   core::string_view s) noexcept; 90   core::string_view s) noexcept;
91   91  
92   private: 92   private:
93   bool at_end_ = false; 93   bool at_end_ = false;
94   void rewind() noexcept override; 94   void rewind() noexcept override;
95   bool measure(std::size_t&) noexcept override; 95   bool measure(std::size_t&) noexcept override;
96   void copy(char*&, char const*) noexcept override; 96   void copy(char*&, char const*) noexcept override;
97   }; 97   };
98   98  
99   //------------------------------------------------ 99   //------------------------------------------------
100   // 100   //
101   // segments_iter 101   // segments_iter
102   // 102   //
103   //------------------------------------------------ 103   //------------------------------------------------
104   104  
105   struct segments_iter_base 105   struct segments_iter_base
106   { 106   {
107   protected: 107   protected:
108   static void 108   static void
109   measure_impl(std::size_t&, 109   measure_impl(std::size_t&,
110   core::string_view, bool) noexcept; 110   core::string_view, bool) noexcept;
111   static void 111   static void
112   copy_impl(char*&, char const*, 112   copy_impl(char*&, char const*,
113   core::string_view, bool) noexcept; 113   core::string_view, bool) noexcept;
114   }; 114   };
115   115  
116   // iterates segments in a 116   // iterates segments in a
117   // plain segment range 117   // plain segment range
118   template<class FwdIt> 118   template<class FwdIt>
119   struct segments_iter 119   struct segments_iter
120   : any_segments_iter 120   : any_segments_iter
121   , segments_iter_base 121   , segments_iter_base
122   { 122   {
123   BOOST_CORE_STATIC_ASSERT( 123   BOOST_CORE_STATIC_ASSERT(
124   std::is_convertible< 124   std::is_convertible<
125   typename std::iterator_traits< 125   typename std::iterator_traits<
126   FwdIt>::reference, 126   FwdIt>::reference,
127   core::string_view>::value); 127   core::string_view>::value);
128   128  
HITCBC 129   79 segments_iter( 129   79 segments_iter(
130   FwdIt first, 130   FwdIt first,
131   FwdIt last) noexcept 131   FwdIt last) noexcept
HITCBC 132   79 : it_(first) 132   79 : it_(first)
HITCBC 133   79 , it0_(first) 133   79 , it0_(first)
HITCBC 134   79 , end_(last) 134   79 , end_(last)
135   { 135   {
HITCBC 136   79 if(first != last) 136   79 if(first != last)
137   { 137   {
HITCBC 138   79 front = *first; 138   79 front = *first;
HITCBC 139   79 auto it = first; 139   79 auto it = first;
HITCBC 140   79 if(++it == last) 140   79 if(++it == last)
HITCBC 141   8 fast_nseg = 1; 141   8 fast_nseg = 1;
142   else 142   else
HITCBC 143   71 fast_nseg = 2; 143   71 fast_nseg = 2;
144   } 144   }
145   else 145   else
146   { 146   {
MISUBC 147   fast_nseg = 0; 147   fast_nseg = 0;
148   } 148   }
HITCBC 149   79 } 149   79 }
150   150  
151   private: 151   private:
152   FwdIt it_; 152   FwdIt it_;
153   FwdIt it0_; 153   FwdIt it0_;
154   FwdIt end_; 154   FwdIt end_;
155   155  
156   void 156   void
HITCBC 157   79 rewind() noexcept override 157   79 rewind() noexcept override
158   { 158   {
HITCBC 159   79 it_ = it0_; 159   79 it_ = it0_;
HITCBC 160   79 } 160   79 }
161   161  
162   bool 162   bool
HITCBC 163   267 measure( 163   267 measure(
164   std::size_t& n) noexcept override 164   std::size_t& n) noexcept override
165   { 165   {
HITCBC 166   267 if(it_ == end_) 166   267 if(it_ == end_)
HITCBC 167   79 return false; 167   79 return false;
HITCBC 168   188 measure_impl(n, 168   188 measure_impl(n,
HITCBC 169   182 detail::to_sv(*it_), 169   182 detail::to_sv(*it_),
HITCBC 170   188 encode_colons); 170   188 encode_colons);
HITCBC 171   188 ++it_; 171   188 ++it_;
HITCBC 172   188 return true; 172   188 return true;
173   } 173   }
174   174  
175   void 175   void
HITCBC 176   188 copy( 176   188 copy(
177   char*& dest, 177   char*& dest,
178   char const* end) noexcept override 178   char const* end) noexcept override
179   { 179   {
HITCBC 180   188 copy_impl(dest, end, 180   188 copy_impl(dest, end,
HITCBC 181   194 detail::to_sv(*it_++), 181   194 detail::to_sv(*it_++),
HITCBC 182   188 encode_colons); 182   188 encode_colons);
HITCBC 183   188 } 183   188 }
184   }; 184   };
185   185  
186   //------------------------------------------------ 186   //------------------------------------------------
187   // 187   //
188   // segment_encoded_iter 188   // segment_encoded_iter
189   // 189   //
190   //------------------------------------------------ 190   //------------------------------------------------
191   191  
192   // A 1-segment range 192   // A 1-segment range
193   // allowing self-intersection 193   // allowing self-intersection
194   struct BOOST_SYMBOL_VISIBLE 194   struct BOOST_SYMBOL_VISIBLE
195   segment_encoded_iter 195   segment_encoded_iter
196   : any_segments_iter 196   : any_segments_iter
197   { 197   {
HITCBC 198   72 virtual ~segment_encoded_iter() = default; 198   72 virtual ~segment_encoded_iter() = default;
199   199  
200   explicit 200   explicit
201   segment_encoded_iter( 201   segment_encoded_iter(
202   pct_string_view const& s) noexcept; 202   pct_string_view const& s) noexcept;
203   203  
204   private: 204   private:
205   bool at_end_ = false; 205   bool at_end_ = false;
206   void rewind() noexcept override; 206   void rewind() noexcept override;
207   bool measure(std::size_t&) noexcept override; 207   bool measure(std::size_t&) noexcept override;
208   void copy(char*&, char const*) noexcept override; 208   void copy(char*&, char const*) noexcept override;
209   }; 209   };
210   210  
211   //------------------------------------------------ 211   //------------------------------------------------
212   // 212   //
213   // segments_encoded_iter 213   // segments_encoded_iter
214   // 214   //
215   //------------------------------------------------ 215   //------------------------------------------------
216   216  
217   // Validating and copying from 217   // Validating and copying from
218   // a string of encoded segments 218   // a string of encoded segments
219   struct segments_encoded_iter_base 219   struct segments_encoded_iter_base
220   { 220   {
221   protected: 221   protected:
222   static void 222   static void
223   measure_impl(std::size_t&, 223   measure_impl(std::size_t&,
224   core::string_view, bool) noexcept; 224   core::string_view, bool) noexcept;
225   static void 225   static void
226   copy_impl(char*&, char const*, 226   copy_impl(char*&, char const*,
227   core::string_view, bool) noexcept; 227   core::string_view, bool) noexcept;
228   }; 228   };
229   229  
230   // iterates segments in an 230   // iterates segments in an
231   // encoded segment range 231   // encoded segment range
232   template<class FwdIt> 232   template<class FwdIt>
233   struct segments_encoded_iter 233   struct segments_encoded_iter
234   : public any_segments_iter 234   : public any_segments_iter
235   , public segments_encoded_iter_base 235   , public segments_encoded_iter_base
236   { 236   {
237   BOOST_CORE_STATIC_ASSERT( 237   BOOST_CORE_STATIC_ASSERT(
238   std::is_convertible< 238   std::is_convertible<
239   typename std::iterator_traits< 239   typename std::iterator_traits<
240   FwdIt>::reference, 240   FwdIt>::reference,
241   core::string_view>::value); 241   core::string_view>::value);
242   242  
HITCBC 243   1257 segments_encoded_iter( 243   1257 segments_encoded_iter(
244   FwdIt first, 244   FwdIt first,
245   FwdIt last) 245   FwdIt last)
HITCBC 246   1257 : it_(first) 246   1257 : it_(first)
HITCBC 247   1257 , it0_(first) 247   1257 , it0_(first)
HITCBC 248   1257 , end_(last) 248   1257 , end_(last)
249   { 249   {
HITCBC 250   1257 if(it_ != end_) 250   1257 if(it_ != end_)
251   { 251   {
252   // throw on invalid input 252   // throw on invalid input
HITCBC 253   221 front = pct_string_view( 253   221 front = pct_string_view(
HITCBC 254   150 detail::to_sv(*first)); 254   150 detail::to_sv(*first));
HITCBC 255   208 auto it = first; 255   208 auto it = first;
HITCBC 256   208 if(++it == last) 256   208 if(++it == last)
HITCBC 257   89 fast_nseg = 1; 257   89 fast_nseg = 1;
258   else 258   else
HITCBC 259   119 fast_nseg = 2; 259   119 fast_nseg = 2;
260   } 260   }
261   else 261   else
262   { 262   {
HITCBC 263   1036 fast_nseg = 0; 263   1036 fast_nseg = 0;
264   } 264   }
HITCBC 265   1257 } 265   1257 }
266   266  
267   private: 267   private:
268   FwdIt it_; 268   FwdIt it_;
269   FwdIt it0_; 269   FwdIt it0_;
270   FwdIt end_; 270   FwdIt end_;
271   271  
272   void 272   void
HITCBC 273   1242 rewind() noexcept override 273   1242 rewind() noexcept override
274   { 274   {
HITCBC 275   1242 it_ = it0_; 275   1242 it_ = it0_;
HITCBC 276   1242 } 276   1242 }
277   277  
278   bool 278   bool
HITCBC 279   1669 measure( 279   1669 measure(
280   std::size_t& n) override 280   std::size_t& n) override
281   { 281   {
HITCBC 282   1669 if(it_ == end_) 282   1669 if(it_ == end_)
HITCBC 283   1242 return false; 283   1242 return false;
284   // throw on invalid input 284   // throw on invalid input
HITCBC 285   425 measure_impl(n, 285   425 measure_impl(n,
HITCBC 286   427 pct_string_view( 286   427 pct_string_view(
HITCBC 287   427 detail::to_sv(*it_++)), 287   427 detail::to_sv(*it_++)),
HITCBC 288   427 encode_colons); 288   427 encode_colons);
HITCBC 289   425 return true; 289   425 return true;
290   } 290   }
291   291  
292   void 292   void
HITCBC 293   423 copy( 293   423 copy(
294   char*& dest, 294   char*& dest,
295   char const* end) noexcept override 295   char const* end) noexcept override
296   { 296   {
HITCBC 297   423 copy_impl(dest, end, 297   423 copy_impl(dest, end,
HITCBC 298   423 detail::to_sv(*it_++), 298   423 detail::to_sv(*it_++),
HITCBC 299   423 encode_colons); 299   423 encode_colons);
HITCBC 300   423 } 300   423 }
301   }; 301   };
302   302  
303   //------------------------------------------------ 303   //------------------------------------------------
304   304  
305   template<class FwdIt> 305   template<class FwdIt>
306   segments_iter<FwdIt> 306   segments_iter<FwdIt>
HITCBC 307   79 make_segments_iter( 307   79 make_segments_iter(
308   FwdIt first, FwdIt last) 308   FwdIt first, FwdIt last)
309   { 309   {
310   return segments_iter< 310   return segments_iter<
HITCBC 311   79 FwdIt>(first, last); 311   79 FwdIt>(first, last);
312   } 312   }
313   313  
314   template<class FwdIt> 314   template<class FwdIt>
315   segments_encoded_iter<FwdIt> 315   segments_encoded_iter<FwdIt>
HITCBC 316   1257 make_segments_encoded_iter( 316   1257 make_segments_encoded_iter(
317   FwdIt first, FwdIt last) 317   FwdIt first, FwdIt last)
318   { 318   {
319   return segments_encoded_iter< 319   return segments_encoded_iter<
HITCBC 320   1257 FwdIt>(first, last); 320   1257 FwdIt>(first, last);
321   } 321   }
322   322  
323   } // detail 323   } // detail
324   } // urls 324   } // urls
325   } // boost 325   } // boost
326   326  
327   #include <boost/url/detail/impl/any_segments_iter.hpp> 327   #include <boost/url/detail/impl/any_segments_iter.hpp>
328   328  
329   #endif 329   #endif