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