99.14% Lines (115/116) 100.00% Functions (25/25)
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   // 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_IMPL_PARAMS_REF_HPP 11   #ifndef BOOST_URL_IMPL_PARAMS_REF_HPP
12   #define BOOST_URL_IMPL_PARAMS_REF_HPP 12   #define BOOST_URL_IMPL_PARAMS_REF_HPP
13   13  
14   #include <boost/url/params_view.hpp> 14   #include <boost/url/params_view.hpp>
15   #include <boost/url/url_base.hpp> 15   #include <boost/url/url_base.hpp>
16   #include <boost/url/detail/any_params_iter.hpp> 16   #include <boost/url/detail/any_params_iter.hpp>
17   #include <boost/url/detail/except.hpp> 17   #include <boost/url/detail/except.hpp>
18   #include <boost/url/grammar/ci_string.hpp> 18   #include <boost/url/grammar/ci_string.hpp>
19   #include <boost/url/grammar/recycled.hpp> 19   #include <boost/url/grammar/recycled.hpp>
20   #include <boost/assert.hpp> 20   #include <boost/assert.hpp>
21   #include <utility> 21   #include <utility>
22   22  
23   namespace boost { 23   namespace boost {
24   namespace urls { 24   namespace urls {
25   25  
26   template<class FwdIt> 26   template<class FwdIt>
27   void 27   void
HITCBC 28   8 params_ref:: 28   8 params_ref::
29   assign(FwdIt first, FwdIt last) 29   assign(FwdIt first, FwdIt last)
30   { 30   {
31   /* If you get a compile error here, it 31   /* If you get a compile error here, it
32   means that the iterators you passed 32   means that the iterators you passed
33   do not meet the requirements stated 33   do not meet the requirements stated
34   in the documentation. 34   in the documentation.
35   */ 35   */
36   static_assert( 36   static_assert(
37   std::is_convertible< 37   std::is_convertible<
38   typename std::iterator_traits< 38   typename std::iterator_traits<
39   FwdIt>::reference, 39   FwdIt>::reference,
40   param_view>::value, 40   param_view>::value,
41   "Type requirements not met"); 41   "Type requirements not met");
42   42  
HITCBC 43   8 assign(first, last, 43   8 assign(first, last,
44   typename std::iterator_traits< 44   typename std::iterator_traits<
45   FwdIt>::iterator_category{}); 45   FwdIt>::iterator_category{});
HITCBC 46   8 } 46   8 }
47   47  
48   template<class FwdIt> 48   template<class FwdIt>
49   auto 49   auto
HITCBC 50   4 params_ref:: 50   4 params_ref::
51   append(FwdIt first, FwdIt last) -> 51   append(FwdIt first, FwdIt last) ->
52   iterator 52   iterator
53   { 53   {
54   /* If you get a compile error here, it 54   /* If you get a compile error here, it
55   means that the iterators you passed 55   means that the iterators you passed
56   do not meet the requirements stated 56   do not meet the requirements stated
57   in the documentation. 57   in the documentation.
58   */ 58   */
59   static_assert( 59   static_assert(
60   std::is_convertible< 60   std::is_convertible<
61   typename std::iterator_traits< 61   typename std::iterator_traits<
62   FwdIt>::reference, 62   FwdIt>::reference,
63   param_view>::value, 63   param_view>::value,
64   "Type requirements not met"); 64   "Type requirements not met");
65   65  
HITCBC 66   4 return insert( 66   4 return insert(
HITCBC 67   4 end(), first, last); 67   4 end(), first, last);
68   } 68   }
69   69  
70   template<class FwdIt> 70   template<class FwdIt>
71   auto 71   auto
HITCBC 72   20 params_ref:: 72   20 params_ref::
73   insert( 73   insert(
74   iterator before, 74   iterator before,
75   FwdIt first, 75   FwdIt first,
76   FwdIt last) -> 76   FwdIt last) ->
77   iterator 77   iterator
78   { 78   {
79   /* If you get a compile error here, it 79   /* If you get a compile error here, it
80   means that the iterators you passed 80   means that the iterators you passed
81   do not meet the requirements stated 81   do not meet the requirements stated
82   in the documentation. 82   in the documentation.
83   */ 83   */
84   static_assert( 84   static_assert(
85   std::is_convertible< 85   std::is_convertible<
86   typename std::iterator_traits< 86   typename std::iterator_traits<
87   FwdIt>::reference, 87   FwdIt>::reference,
88   param_view>::value, 88   param_view>::value,
89   "Type requirements not met"); 89   "Type requirements not met");
90   90  
HITCBC 91   40 return insert( 91   40 return insert(
92   before, 92   before,
93   first, 93   first,
94   last, 94   last,
95   typename std::iterator_traits< 95   typename std::iterator_traits<
HITCBC 96   40 FwdIt>::iterator_category{}); 96   40 FwdIt>::iterator_category{});
97   } 97   }
98   98  
99   template<class FwdIt> 99   template<class FwdIt>
100   auto 100   auto
HITCBC 101   4 params_ref:: 101   4 params_ref::
102   replace( 102   replace(
103   iterator from, 103   iterator from,
104   iterator to, 104   iterator to,
105   FwdIt first, 105   FwdIt first,
106   FwdIt last) -> 106   FwdIt last) ->
107   iterator 107   iterator
108   { 108   {
109   /* If you get a compile error here, it 109   /* If you get a compile error here, it
110   means that the iterators you passed 110   means that the iterators you passed
111   do not meet the requirements stated 111   do not meet the requirements stated
112   in the documentation. 112   in the documentation.
113   */ 113   */
114   static_assert( 114   static_assert(
115   std::is_convertible< 115   std::is_convertible<
116   typename std::iterator_traits< 116   typename std::iterator_traits<
117   FwdIt>::reference, 117   FwdIt>::reference,
118   param_view>::value, 118   param_view>::value,
119   "Type requirements not met"); 119   "Type requirements not met");
120   120  
121   return iterator( 121   return iterator(
HITCBC 122   8 u_->edit_params( 122   8 u_->edit_params(
123   from.it_, to.it_, 123   from.it_, to.it_,
124   detail::make_params_iter( 124   detail::make_params_iter(
HITCBC 125   4 first, last, opt_.space_as_plus)), 125   4 first, last, opt_.space_as_plus)),
HITCBC 126   8 opt_); 126   8 opt_);
127   } 127   }
128   128  
129   //------------------------------------------------ 129   //------------------------------------------------
130   // 130   //
131   // implementation 131   // implementation
132   // 132   //
133   //------------------------------------------------ 133   //------------------------------------------------
134   134  
135   template<class FwdIt> 135   template<class FwdIt>
136   void 136   void
HITCBC 137   8 params_ref:: 137   8 params_ref::
138   assign(FwdIt first, FwdIt last, 138   assign(FwdIt first, FwdIt last,
139   std::forward_iterator_tag) 139   std::forward_iterator_tag)
140   { 140   {
HITCBC 141   8 u_->edit_params( 141   8 u_->edit_params(
HITCBC 142   8 begin().it_, 142   8 begin().it_,
HITCBC 143   16 end().it_, 143   16 end().it_,
144   detail::make_params_iter( 144   detail::make_params_iter(
HITCBC 145   8 first, last, opt_.space_as_plus)); 145   8 first, last, opt_.space_as_plus));
HITCBC 146   8 } 146   8 }
147   147  
148   template<class FwdIt> 148   template<class FwdIt>
149   auto 149   auto
HITCBC 150   20 params_ref:: 150   20 params_ref::
151   insert( 151   insert(
152   iterator before, 152   iterator before,
153   FwdIt first, 153   FwdIt first,
154   FwdIt last, 154   FwdIt last,
155   std::forward_iterator_tag) -> 155   std::forward_iterator_tag) ->
156   iterator 156   iterator
157   { 157   {
158   return iterator( 158   return iterator(
HITCBC 159   40 u_->edit_params( 159   40 u_->edit_params(
160   before.it_, 160   before.it_,
161   before.it_, 161   before.it_,
162   detail::make_params_iter( 162   detail::make_params_iter(
HITCBC 163   20 first, last, opt_.space_as_plus)), 163   20 first, last, opt_.space_as_plus)),
HITCBC 164   40 opt_); 164   40 opt_);
165   } 165   }
166   166  
167   //------------------------------------------------ 167   //------------------------------------------------
168   // 168   //
169   // Special Members 169   // Special Members
170   // 170   //
171   //------------------------------------------------ 171   //------------------------------------------------
172   172  
173   inline 173   inline
HITCBC 174   981 params_ref:: 174   990 params_ref::
175   params_ref( 175   params_ref(
176   url_base& u, 176   url_base& u,
HITCBC 177   981 encoding_opts opt) noexcept 177   990 encoding_opts opt) noexcept
HITCBC 178   981 : params_base(u.impl_, opt) 178   990 : params_base(u.impl_, opt)
HITCBC 179   981 , u_(&u) 179   990 , u_(&u)
180   { 180   {
HITCBC 181   981 } 181   990 }
182   182  
183   inline 183   inline
HITCBC 184   1 params_ref:: 184   1 params_ref::
185   params_ref( 185   params_ref(
186   params_ref const& other, 186   params_ref const& other,
HITCBC 187   1 encoding_opts opt) noexcept 187   1 encoding_opts opt) noexcept
HITCBC 188   1 : params_base(other.u_->impl_, opt) 188   1 : params_base(other.u_->impl_, opt)
HITCBC 189   1 , u_(other.u_) 189   1 , u_(other.u_)
190   { 190   {
HITCBC 191   1 } 191   1 }
192   192  
193   inline 193   inline
194   auto 194   auto
HITCBC 195   1 params_ref:: 195   1 params_ref::
196   operator=(params_ref const& other) -> 196   operator=(params_ref const& other) ->
197   params_ref& 197   params_ref&
198   { 198   {
HITCBC 199   1 if (!ref_.alias_of(other.ref_)) 199   1 if (!ref_.alias_of(other.ref_))
HITCBC 200   1 assign(other.begin(), other.end()); 200   1 assign(other.begin(), other.end());
HITCBC 201   1 return *this; 201   1 return *this;
202   } 202   }
203   203  
204   inline 204   inline
205   auto 205   auto
HITCBC 206   1 params_ref:: 206   1 params_ref::
207   operator=(std::initializer_list< 207   operator=(std::initializer_list<
208   param_view> init) -> 208   param_view> init) ->
209   params_ref& 209   params_ref&
210   { 210   {
HITCBC 211   1 assign(init); 211   1 assign(init);
HITCBC 212   1 return *this; 212   1 return *this;
213   } 213   }
214   214  
215   inline 215   inline
HITCBC 216   63 params_ref:: 216   63 params_ref::
217   operator 217   operator
218   params_view() const noexcept 218   params_view() const noexcept
219   { 219   {
HITCBC 220   63 return { ref_, opt_ }; 220   63 return { ref_, opt_ };
221   } 221   }
222   222  
223   //------------------------------------------------ 223   //------------------------------------------------
224   // 224   //
225   // Modifiers 225   // Modifiers
226   // 226   //
227   //------------------------------------------------ 227   //------------------------------------------------
228   228  
229   inline 229   inline
230   void 230   void
HITCBC 231   591 params_ref:: 231   591 params_ref::
232   clear() noexcept 232   clear() noexcept
233   { 233   {
HITCBC 234   591 u_->remove_query(); 234   591 u_->remove_query();
HITCBC 235   591 } 235   591 }
236   236  
237   inline 237   inline
238   void 238   void
HITCBC 239   5 params_ref:: 239   5 params_ref::
240   assign( 240   assign(
241   std::initializer_list< 241   std::initializer_list<
242   param_view> init) 242   param_view> init)
243   { 243   {
HITCBC 244   5 assign(init.begin(), init.end()); 244   5 assign(init.begin(), init.end());
HITCBC 245   5 } 245   5 }
246   246  
247   inline 247   inline
248   auto 248   auto
HITCBC 249   947 params_ref:: 249   951 params_ref::
250   insert( 250   insert(
251   iterator before, 251   iterator before,
252   param_view const& p) -> 252   param_view const& p) ->
253   iterator 253   iterator
254   { 254   {
255   return { 255   return {
HITCBC 256   947 u_->edit_params( 256   951 u_->edit_params(
257   before.it_, 257   before.it_,
258   before.it_, 258   before.it_,
HITCBC 259   1894 detail::single_param_iter(p, opt_.space_as_plus)), 259   1902 detail::single_param_iter(p, opt_.space_as_plus)),
HITCBC 260   1894 opt_}; 260   1902 opt_};
261   } 261   }
262   262  
263   inline 263   inline
264   auto 264   auto
HITCBC 265   16 params_ref:: 265   16 params_ref::
266   insert( 266   insert(
267   iterator before, 267   iterator before,
268   std::initializer_list< 268   std::initializer_list<
269   param_view> init) -> 269   param_view> init) ->
270   iterator 270   iterator
271   { 271   {
HITCBC 272   16 return insert( 272   16 return insert(
273   before, 273   before,
274   init.begin(), 274   init.begin(),
HITCBC 275   16 init.end()); 275   16 init.end());
276   } 276   }
277   277  
278   inline 278   inline
279   auto 279   auto
HITCBC 280   812 params_ref:: 280   815 params_ref::
281   append( 281   append(
282   param_view const& p) -> 282   param_view const& p) ->
283   iterator 283   iterator
284   { 284   {
HITCBC 285   812 return insert(end(), p); 285   815 return insert(end(), p);
286   } 286   }
287   287  
288   inline 288   inline
289   auto 289   auto
HITCBC 290   6 params_ref:: 290   6 params_ref::
291   append( 291   append(
292   std::initializer_list< 292   std::initializer_list<
293   param_view> init) -> 293   param_view> init) ->
294   iterator 294   iterator
295   { 295   {
HITCBC 296   6 return insert(end(), init); 296   6 return insert(end(), init);
297   } 297   }
298   298  
299   inline 299   inline
300   std::size_t 300   std::size_t
HITCBC 301   2 params_ref:: 301   2 params_ref::
302   erase( 302   erase(
303   core::string_view key, 303   core::string_view key,
304   ignore_case_param ic) noexcept 304   ignore_case_param ic) noexcept
305   { 305   {
306   // end() can't be fully cached, 306   // end() can't be fully cached,
307   // since erase invalidates it. 307   // since erase invalidates it.
HITCBC 308   2 iterator it; 308   2 iterator it;
309   { 309   {
HITCBC 310   2 auto const end_ = end(); 310   2 auto const end_ = end();
HITCBC 311   2 it = find_last(end_, key, ic); 311   2 it = find_last(end_, key, ic);
HITCBC 312   2 if(it == end_) 312   2 if(it == end_)
MISUBC 313   return 0; 313   return 0;
314   } 314   }
HITCBC 315   2 std::size_t n = 0; 315   2 std::size_t n = 0;
316   for(;;) 316   for(;;)
317   { 317   {
HITCBC 318   5 ++n; 318   5 ++n;
319   // Use it->key instead of key, 319   // Use it->key instead of key,
320   // to handle self-intersection 320   // to handle self-intersection
HITCBC 321   5 auto prev = find_last(it, (*it).key, ic); 321   5 auto prev = find_last(it, (*it).key, ic);
HITCBC 322   5 if(prev == end()) 322   5 if(prev == end())
HITCBC 323   2 break; 323   2 break;
HITCBC 324   3 erase(it); 324   3 erase(it);
HITCBC 325   3 it = prev; 325   3 it = prev;
HITCBC 326   3 } 326   3 }
HITCBC 327   2 erase(it); 327   2 erase(it);
HITCBC 328   2 return n; 328   2 return n;
329   } 329   }
330   330  
331   inline 331   inline
332   auto 332   auto
HITCBC 333   229 params_ref:: 333   229 params_ref::
334   replace( 334   replace(
335   iterator pos, 335   iterator pos,
336   param_view const& p) -> 336   param_view const& p) ->
337   iterator 337   iterator
338   { 338   {
339   return iterator( 339   return iterator(
HITCBC 340   687 u_->edit_params( 340   687 u_->edit_params(
341   pos.it_, 341   pos.it_,
HITCBC 342   229 std::next(pos).it_, 342   229 std::next(pos).it_,
HITCBC 343   458 detail::single_param_iter(p, opt_.space_as_plus)), 343   458 detail::single_param_iter(p, opt_.space_as_plus)),
HITCBC 344   458 opt_); 344   458 opt_);
345   } 345   }
346   346  
347   inline 347   inline
348   auto 348   auto
HITCBC 349   2 params_ref:: 349   2 params_ref::
350   replace( 350   replace(
351   iterator from, 351   iterator from,
352   iterator to, 352   iterator to,
353   std::initializer_list< 353   std::initializer_list<
354   param_view> init) -> 354   param_view> init) ->
355   iterator 355   iterator
356   { 356   {
HITCBC 357   2 return replace( 357   2 return replace(
358   from, 358   from,
359   to, 359   to,
360   init.begin(), 360   init.begin(),
HITCBC 361   2 init.end()); 361   2 init.end());
362   } 362   }
363   363  
364   inline 364   inline
365   auto 365   auto
HITCBC 366   4 params_ref:: 366   4 params_ref::
367   unset( 367   unset(
368   iterator pos) noexcept -> 368   iterator pos) noexcept ->
369   iterator 369   iterator
370   { 370   {
HITCBC 371   4 BOOST_ASSERT(pos.it_.nk > 0); 371   4 BOOST_ASSERT(pos.it_.nk > 0);
HITCBC 372   4 core::string_view s; 372   4 core::string_view s;
373   return iterator( 373   return iterator(
HITCBC 374   4 u_->edit_params( 374   4 u_->edit_params(
375   pos.it_, 375   pos.it_,
HITCBC 376   4 pos.it_.next(), 376   4 pos.it_.next(),
HITCBC 377   4 detail::param_value_iter( 377   4 detail::param_value_iter(
HITCBC 378   4 pos.it_.nk - 1, s, false)), 378   4 pos.it_.nk - 1, s, false)),
HITCBC 379   4 opt_); 379   4 opt_);
380   } 380   }
381   381  
382   inline 382   inline
383   auto 383   auto
HITCBC 384   5 params_ref:: 384   5 params_ref::
385   set( 385   set(
386   iterator pos, 386   iterator pos,
387   core::string_view value) -> 387   core::string_view value) ->
388   iterator 388   iterator
389   { 389   {
HITCBC 390   5 BOOST_ASSERT(pos.it_.nk > 0); 390   5 BOOST_ASSERT(pos.it_.nk > 0);
391   return iterator( 391   return iterator(
HITCBC 392   5 u_->edit_params( 392   5 u_->edit_params(
393   pos.it_, 393   pos.it_,
HITCBC 394   5 pos.it_.next(), 394   5 pos.it_.next(),
HITCBC 395   5 detail::param_value_iter( 395   5 detail::param_value_iter(
HITCBC 396   5 pos.it_.nk - 1, value, true)), 396   5 pos.it_.nk - 1, value, true)),
HITCBC 397   10 opt_); 397   10 opt_);
398   } 398   }
399   399  
400   inline 400   inline
401   auto 401   auto
HITCBC 402   1 params_ref:: 402   3 params_ref::
403   set( 403   set(
404   core::string_view key, 404   core::string_view key,
405   core::string_view value, 405   core::string_view value,
406   ignore_case_param ic) -> 406   ignore_case_param ic) ->
407   iterator 407   iterator
408   { 408   {
409   // VFALCO we can't cache end() here 409   // VFALCO we can't cache end() here
410   // because it is invalidated 410   // because it is invalidated
411   // every time we set or erase. 411   // every time we set or erase.
HITCBC 412   1 auto it0 = find(key, ic); 412   3 auto it0 = find(key, ic);
HITCBC 413   1 if(it0 == end()) 413   3 if(it0 == end())
HITGBC 414   return append({key, value}); 414   2 return append({key, value});
HITCBC 415   1 it0 = set(it0, value); 415   1 it0 = set(it0, value);
HITCBC 416   1 auto it = end(); 416   1 auto it = end();
417   for(;;) 417   for(;;)
418   { 418   {
HITCBC 419   2 it = find_last(it, key, ic); 419   2 it = find_last(it, key, ic);
HITCBC 420   2 if(it == it0) 420   2 if(it == it0)
HITCBC 421   1 return it0; 421   1 return it0;
HITCBC 422   1 it = erase(it); 422   1 it = erase(it);
423   } 423   }
424   } 424   }
425   425  
426   inline 426   inline
427   auto 427   auto
HITCBC 428   247 params_ref:: 428   249 params_ref::
429   erase( 429   erase(
430   iterator pos) noexcept -> 430   iterator pos) noexcept ->
431   iterator 431   iterator
432   { 432   {
HITCBC 433   247 return erase( 433   249 return erase(
434   pos, 434   pos,
HITCBC 435   247 std::next(pos)); 435   249 std::next(pos));
436   } 436   }
437   437  
438   inline 438   inline
439   auto 439   auto
HITCBC 440   249 params_ref:: 440   251 params_ref::
441   erase( 441   erase(
442   iterator first, 442   iterator first,
443   iterator last) noexcept -> 443   iterator last) noexcept ->
444   iterator 444   iterator
445   { 445   {
HITCBC 446   249 core::string_view s("", 0); 446   251 core::string_view s("", 0);
447   return iterator( 447   return iterator(
HITCBC 448   249 u_->edit_params( 448   251 u_->edit_params(
449   first.it_, 449   first.it_,
450   last.it_, 450   last.it_,
HITCBC 451   498 detail::query_string_iter(s)), 451   502 detail::query_string_iter(s)),
HITCBC 452   249 opt_); 452   251 opt_);
453   } 453   }
454   454  
455   } // urls 455   } // urls
456   } // boost 456   } // boost
457   457  
458   #endif 458   #endif