100.00% Lines (128/128) 100.00% Functions (28/28)
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_BASE_HPP 11   #ifndef BOOST_URL_IMPL_PARAMS_BASE_HPP
12   #define BOOST_URL_IMPL_PARAMS_BASE_HPP 12   #define BOOST_URL_IMPL_PARAMS_BASE_HPP
13   13  
14   #include <boost/url/detail/params_iter_impl.hpp> 14   #include <boost/url/detail/params_iter_impl.hpp>
15   #include <boost/url/decode_view.hpp> 15   #include <boost/url/decode_view.hpp>
16   #include <boost/url/grammar/ci_string.hpp> 16   #include <boost/url/grammar/ci_string.hpp>
17   #include <iterator> 17   #include <iterator>
18   #include <ostream> 18   #include <ostream>
19   #include <string> 19   #include <string>
20   20  
21   namespace boost { 21   namespace boost {
22   namespace urls { 22   namespace urls {
23   23  
24   //------------------------------------------------ 24   //------------------------------------------------
25   25  
26   class BOOST_SYMBOL_VISIBLE params_base::iterator 26   class BOOST_SYMBOL_VISIBLE params_base::iterator
27   { 27   {
28   detail::params_iter_impl it_; 28   detail::params_iter_impl it_;
29   bool space_as_plus_ = true; 29   bool space_as_plus_ = true;
30   30  
31   friend class params_base; 31   friend class params_base;
32   friend class params_ref; 32   friend class params_ref;
33   33  
34   iterator( 34   iterator(
35   detail::query_ref const& ref, 35   detail::query_ref const& ref,
36   encoding_opts opt) noexcept; 36   encoding_opts opt) noexcept;
37   37  
38   iterator( 38   iterator(
39   detail::query_ref const& impl, 39   detail::query_ref const& impl,
40   encoding_opts opt, 40   encoding_opts opt,
41   int) noexcept; 41   int) noexcept;
42   42  
HITCBC 43   1724 iterator( 43   1732 iterator(
44   detail::params_iter_impl const& it, 44   detail::params_iter_impl const& it,
45   encoding_opts opt) noexcept 45   encoding_opts opt) noexcept
HITCBC 46   1724 : it_(it) 46   1732 : it_(it)
HITCBC 47   1724 , space_as_plus_(opt.space_as_plus) 47   1732 , space_as_plus_(opt.space_as_plus)
48   { 48   {
HITCBC 49   1724 } 49   1732 }
50   50  
51   public: 51   public:
52   using value_type = params_base::value_type; 52   using value_type = params_base::value_type;
53   using reference = params_base::reference; 53   using reference = params_base::reference;
54   using pointer = reference; 54   using pointer = reference;
55   using difference_type = 55   using difference_type =
56   params_base::difference_type; 56   params_base::difference_type;
57   using iterator_category = 57   using iterator_category =
58   std::bidirectional_iterator_tag; 58   std::bidirectional_iterator_tag;
59   59  
HITCBC 60   4 iterator() = default; 60   4 iterator() = default;
61   iterator(iterator const&) = default; 61   iterator(iterator const&) = default;
62   iterator& operator=( 62   iterator& operator=(
63   iterator const&) noexcept = default; 63   iterator const&) noexcept = default;
64   64  
65   iterator& 65   iterator&
HITCBC 66   6660 operator++() noexcept 66   6663 operator++() noexcept
67   { 67   {
HITCBC 68   6660 it_.increment(); 68   6663 it_.increment();
HITCBC 69   6660 return *this; 69   6663 return *this;
70   } 70   }
71   71  
72   iterator 72   iterator
HITCBC 73   367 operator++(int) noexcept 73   367 operator++(int) noexcept
74   { 74   {
HITCBC 75   367 auto tmp = *this; 75   367 auto tmp = *this;
HITCBC 76   367 ++*this; 76   367 ++*this;
HITCBC 77   367 return tmp; 77   367 return tmp;
78   } 78   }
79   79  
80   iterator& 80   iterator&
HITCBC 81   730 operator--() noexcept 81   730 operator--() noexcept
82   { 82   {
HITCBC 83   730 it_.decrement(); 83   730 it_.decrement();
HITCBC 84   730 return *this; 84   730 return *this;
85   } 85   }
86   86  
87   iterator 87   iterator
HITCBC 88   365 operator--(int) noexcept 88   365 operator--(int) noexcept
89   { 89   {
HITCBC 90   365 auto tmp = *this; 90   365 auto tmp = *this;
HITCBC 91   365 --*this; 91   365 --*this;
HITCBC 92   365 return tmp; 92   365 return tmp;
93   } 93   }
94   94  
95   reference 95   reference
96   operator*() const; 96   operator*() const;
97   97  
98   // the return value is too expensive 98   // the return value is too expensive
99   pointer operator->() const = delete; 99   pointer operator->() const = delete;
100   100  
101   bool 101   bool
HITCBC 102   768 operator==( 102   770 operator==(
103   iterator const& other) const noexcept 103   iterator const& other) const noexcept
104   { 104   {
HITCBC 105   768 return it_.equal(other.it_); 105   770 return it_.equal(other.it_);
106   } 106   }
107   107  
108   bool 108   bool
HITCBC 109   11059 operator!=( 109   11059 operator!=(
110   iterator const& other) const noexcept 110   iterator const& other) const noexcept
111   { 111   {
HITCBC 112   11059 return ! it_.equal(other.it_); 112   11059 return ! it_.equal(other.it_);
113   } 113   }
114   }; 114   };
115   115  
116   116  
117   //------------------------------------------------ 117   //------------------------------------------------
118   118  
119   inline 119   inline
HITCBC 120   6756 params_base:: 120   6761 params_base::
121   iterator:: 121   iterator::
122   iterator( 122   iterator(
123   detail::query_ref const& ref, 123   detail::query_ref const& ref,
HITCBC 124   6756 encoding_opts opt) noexcept 124   6761 encoding_opts opt) noexcept
HITCBC 125   6756 : it_(ref) 125   6761 : it_(ref)
HITCBC 126   6756 , space_as_plus_(opt.space_as_plus) 126   6761 , space_as_plus_(opt.space_as_plus)
127   { 127   {
HITCBC 128   6756 } 128   6761 }
129   129  
130   inline 130   inline
HITCBC 131   11993 params_base:: 131   11998 params_base::
132   iterator:: 132   iterator::
133   iterator( 133   iterator(
134   detail::query_ref const& ref, 134   detail::query_ref const& ref,
135   encoding_opts opt, 135   encoding_opts opt,
HITCBC 136   11993 int) noexcept 136   11998 int) noexcept
HITCBC 137   11993 : it_(ref, 0) 137   11998 : it_(ref, 0)
HITCBC 138   11993 , space_as_plus_(opt.space_as_plus) 138   11998 , space_as_plus_(opt.space_as_plus)
139   { 139   {
HITCBC 140   11993 } 140   11998 }
141   141  
142   142  
143   inline 143   inline
144   auto 144   auto
HITCBC 145   5908 params_base:: 145   5908 params_base::
146   iterator:: 146   iterator::
147   operator*() const -> 147   operator*() const ->
148   reference 148   reference
149   149  
150   { 150   {
HITCBC 151   5908 encoding_opts opt; 151   5908 encoding_opts opt;
HITCBC 152   5908 opt.space_as_plus = 152   5908 opt.space_as_plus =
HITCBC 153   5908 space_as_plus_; 153   5908 space_as_plus_;
154   param_pct_view p = 154   param_pct_view p =
HITCBC 155   5908 it_.dereference(); 155   5908 it_.dereference();
156   return reference( 156   return reference(
HITCBC 157   11816 p.key.decode(opt), 157   11816 p.key.decode(opt),
HITCBC 158   11816 p.value.decode(opt), 158   11816 p.value.decode(opt),
HITCBC 159   29540 p.has_value); 159   29540 p.has_value);
160   } 160   }
161   161  
162   //------------------------------------------------ 162   //------------------------------------------------
163   // 163   //
164   // params_base 164   // params_base
165   // 165   //
166   //------------------------------------------------ 166   //------------------------------------------------
167   167  
168   inline 168   inline
HITCBC 169   1 params_base:: 169   1 params_base::
HITCBC 170   1 params_base() noexcept 170   1 params_base() noexcept
171   // space_as_plus = true 171   // space_as_plus = true
HITCBC 172   1 : opt_(true, false, false) 172   1 : opt_(true, false, false)
173   { 173   {
HITCBC 174   1 } 174   1 }
175   175  
176   inline 176   inline
177   bool 177   bool
HITCBC 178   28 params_base:: 178   28 params_base::
179   contains( 179   contains(
180   core::string_view key, 180   core::string_view key,
181   ignore_case_param ic) const noexcept 181   ignore_case_param ic) const noexcept
182   { 182   {
HITCBC 183   28 return find( 183   28 return find(
HITCBC 184   56 begin(),key, ic) != end(); 184   56 begin(),key, ic) != end();
185   } 185   }
186   186  
187   inline 187   inline
188   auto 188   auto
HITCBC 189   189 params_base:: 189   191 params_base::
190   find( 190   find(
191   core::string_view key, 191   core::string_view key,
192   ignore_case_param ic) const noexcept -> 192   ignore_case_param ic) const noexcept ->
193   iterator 193   iterator
194   { 194   {
195   return iterator( 195   return iterator(
HITCBC 196   189 find_impl( 196   191 find_impl(
HITCBC 197   378 begin().it_, key, ic), 197   382 begin().it_, key, ic),
HITCBC 198   189 opt_); 198   191 opt_);
199   } 199   }
200   200  
201   inline 201   inline
202   auto 202   auto
HITCBC 203   64 params_base:: 203   64 params_base::
204   find( 204   find(
205   iterator it, 205   iterator it,
206   core::string_view key, 206   core::string_view key,
207   ignore_case_param ic) const noexcept -> 207   ignore_case_param ic) const noexcept ->
208   iterator 208   iterator
209   { 209   {
210   return iterator( 210   return iterator(
HITCBC 211   128 find_impl( 211   128 find_impl(
212   it.it_, key, ic), 212   it.it_, key, ic),
HITCBC 213   64 opt_); 213   64 opt_);
214   } 214   }
215   215  
216   inline 216   inline
217   auto 217   auto
HITCBC 218   4 params_base:: 218   4 params_base::
219   find_last( 219   find_last(
220   core::string_view key, 220   core::string_view key,
221   ignore_case_param ic) const noexcept -> 221   ignore_case_param ic) const noexcept ->
222   iterator 222   iterator
223   { 223   {
224   return iterator( 224   return iterator(
HITCBC 225   4 find_last_impl( 225   4 find_last_impl(
HITCBC 226   8 end().it_, key, ic), 226   8 end().it_, key, ic),
HITCBC 227   4 opt_); 227   4 opt_);
228   } 228   }
229   229  
230   inline 230   inline
231   auto 231   auto
HITCBC 232   9 params_base:: 232   9 params_base::
233   find_last( 233   find_last(
234   iterator it, 234   iterator it,
235   core::string_view key, 235   core::string_view key,
236   ignore_case_param ic) const noexcept -> 236   ignore_case_param ic) const noexcept ->
237   iterator 237   iterator
238   { 238   {
239   return iterator( 239   return iterator(
HITCBC 240   18 find_last_impl( 240   18 find_last_impl(
241   it.it_, key, ic), 241   it.it_, key, ic),
HITCBC 242   9 opt_); 242   9 opt_);
243   } 243   }
244   244  
245   inline 245   inline
HITCBC 246   6917 params_base:: 246   6926 params_base::
247   params_base( 247   params_base(
248   detail::query_ref const& ref, 248   detail::query_ref const& ref,
HITCBC 249   6917 encoding_opts opt) noexcept 249   6926 encoding_opts opt) noexcept
HITCBC 250   6917 : ref_(ref) 250   6926 : ref_(ref)
HITCBC 251   6917 , opt_(opt) 251   6926 , opt_(opt)
252   { 252   {
HITCBC 253   6917 } 253   6926 }
254   254  
255   inline 255   inline
256   pct_string_view 256   pct_string_view
HITCBC 257   13 params_base:: 257   13 params_base::
258   buffer() const noexcept 258   buffer() const noexcept
259   { 259   {
HITCBC 260   13 return ref_.buffer(); 260   13 return ref_.buffer();
261   } 261   }
262   262  
263   inline 263   inline
264   bool 264   bool
HITCBC 265   1551 params_base:: 265   1551 params_base::
266   empty() const noexcept 266   empty() const noexcept
267   { 267   {
HITCBC 268   1551 return ref_.nparam() == 0; 268   1551 return ref_.nparam() == 0;
269   } 269   }
270   270  
271   inline 271   inline
272   std::size_t 272   std::size_t
HITCBC 273   781 params_base:: 273   781 params_base::
274   size() const noexcept 274   size() const noexcept
275   { 275   {
HITCBC 276   781 return ref_.nparam(); 276   781 return ref_.nparam();
277   } 277   }
278   278  
279   inline 279   inline
280   auto 280   auto
HITCBC 281   6756 params_base:: 281   6761 params_base::
282   begin() const noexcept -> 282   begin() const noexcept ->
283   iterator 283   iterator
284   { 284   {
HITCBC 285   6756 return iterator(ref_, opt_); 285   6761 return iterator(ref_, opt_);
286   } 286   }
287   287  
288   inline 288   inline
289   auto 289   auto
HITCBC 290   11993 params_base:: 290   11998 params_base::
291   end() const noexcept -> 291   end() const noexcept ->
292   iterator 292   iterator
293   { 293   {
HITCBC 294   11993 return {ref_, opt_, 0}; 294   11998 return {ref_, opt_, 0};
295   } 295   }
296   296  
297   //------------------------------------------------ 297   //------------------------------------------------
298   298  
299   inline 299   inline
300   std::size_t 300   std::size_t
HITCBC 301   32 params_base:: 301   32 params_base::
302   count( 302   count(
303   core::string_view key, 303   core::string_view key,
304   ignore_case_param ic) const noexcept 304   ignore_case_param ic) const noexcept
305   { 305   {
HITCBC 306   32 std::size_t n = 0; 306   32 std::size_t n = 0;
HITCBC 307   32 auto it = find(key, ic); 307   32 auto it = find(key, ic);
HITCBC 308   32 auto const end_ = end(); 308   32 auto const end_ = end();
HITCBC 309   64 while(it != end_) 309   64 while(it != end_)
310   { 310   {
HITCBC 311   32 ++n; 311   32 ++n;
HITCBC 312   32 ++it; 312   32 ++it;
HITCBC 313   32 it = find(it, key, ic); 313   32 it = find(it, key, ic);
314   } 314   }
HITCBC 315   32 return n; 315   32 return n;
316   } 316   }
317   317  
318   inline 318   inline
319   std::string 319   std::string
HITCBC 320   8 params_base:: 320   8 params_base::
321   get_or( 321   get_or(
322   core::string_view key, 322   core::string_view key,
323   core::string_view value, 323   core::string_view value,
324   ignore_case_param ic) const 324   ignore_case_param ic) const
325   { 325   {
HITCBC 326   8 auto it = find_impl( 326   8 auto it = find_impl(
HITCBC 327   8 begin().it_, key, ic); 327   8 begin().it_, key, ic);
HITCBC 328   8 detail::params_iter_impl end_(ref_, 0); 328   8 detail::params_iter_impl end_(ref_, 0);
HITCBC 329   8 if(it.equal(end_)) 329   8 if(it.equal(end_))
HITCBC 330   2 return std::string(value); 330   2 return std::string(value);
331   331  
HITCBC 332   6 param_pct_view const p = it.dereference(); 332   6 param_pct_view const p = it.dereference();
HITCBC 333   6 if(! p.has_value) 333   6 if(! p.has_value)
HITCBC 334   1 return std::string(); 334   1 return std::string();
335   335  
HITCBC 336   5 auto opt = opt_; 336   5 auto opt = opt_;
HITCBC 337   5 return p.value.decode(opt); 337   5 return p.value.decode(opt);
338   } 338   }
339   339  
340   //------------------------------------------------ 340   //------------------------------------------------
341   // 341   //
342   // (implementation) 342   // (implementation)
343   // 343   //
344   //------------------------------------------------ 344   //------------------------------------------------
345   345  
346   inline 346   inline
347   detail::params_iter_impl 347   detail::params_iter_impl
HITCBC 348   261 params_base:: 348   263 params_base::
349   find_impl( 349   find_impl(
350   detail::params_iter_impl it, 350   detail::params_iter_impl it,
351   core::string_view key, 351   core::string_view key,
352   ignore_case_param ic) const noexcept 352   ignore_case_param ic) const noexcept
353   { 353   {
HITCBC 354   261 detail::params_iter_impl end_(ref_, 0); 354   263 detail::params_iter_impl end_(ref_, 0);
HITCBC 355   261 if(! ic) 355   263 if(! ic)
356   { 356   {
357   for(;;) 357   for(;;)
358   { 358   {
HITCBC 359   566 if(it.equal(end_)) 359   569 if(it.equal(end_))
HITCBC 360   146 return it; 360   148 return it;
HITCBC 361   420 if(*it.key() == key) 361   421 if(*it.key() == key)
HITCBC 362   77 return it; 362   77 return it;
HITCBC 363   343 it.increment(); 363   344 it.increment();
364   } 364   }
365   } 365   }
366   for(;;) 366   for(;;)
367   { 367   {
HITCBC 368   129 if(it.equal(end_)) 368   129 if(it.equal(end_))
HITCBC 369   10 return it; 369   10 return it;
HITCBC 370   119 if( grammar::ci_is_equal( 370   119 if( grammar::ci_is_equal(
HITCBC 371   238 *it.key(), key)) 371   238 *it.key(), key))
HITCBC 372   28 return it; 372   28 return it;
HITCBC 373   91 it.increment(); 373   91 it.increment();
374   } 374   }
375   } 375   }
376   376  
377   inline 377   inline
378   detail::params_iter_impl 378   detail::params_iter_impl
HITCBC 379   13 params_base:: 379   13 params_base::
380   find_last_impl( 380   find_last_impl(
381   detail::params_iter_impl it, 381   detail::params_iter_impl it,
382   core::string_view key, 382   core::string_view key,
383   ignore_case_param ic) const noexcept 383   ignore_case_param ic) const noexcept
384   { 384   {
HITCBC 385   13 detail::params_iter_impl begin_(ref_); 385   13 detail::params_iter_impl begin_(ref_);
HITCBC 386   13 if(! ic) 386   13 if(! ic)
387   { 387   {
388   for(;;) 388   for(;;)
389   { 389   {
HITCBC 390   13 if(it.equal(begin_)) 390   13 if(it.equal(begin_))
HITCBC 391   2 return { ref_, 0 }; 391   2 return { ref_, 0 };
HITCBC 392   11 it.decrement(); 392   11 it.decrement();
HITCBC 393   11 if(*it.key() == key) 393   11 if(*it.key() == key)
HITCBC 394   5 return it; 394   5 return it;
395   } 395   }
396   } 396   }
397   for(;;) 397   for(;;)
398   { 398   {
HITCBC 399   9 if(it.equal(begin_)) 399   9 if(it.equal(begin_))
HITCBC 400   1 return { ref_, 0 }; 400   1 return { ref_, 0 };
HITCBC 401   8 it.decrement(); 401   8 it.decrement();
HITCBC 402   8 if(grammar::ci_is_equal( 402   8 if(grammar::ci_is_equal(
HITCBC 403   16 *it.key(), key)) 403   16 *it.key(), key))
HITCBC 404   5 return it; 404   5 return it;
405   } 405   }
406   } 406   }
407   407  
408   //------------------------------------------------ 408   //------------------------------------------------
409   409  
410   inline 410   inline
411   std::ostream& 411   std::ostream&
HITCBC 412   1 operator<<( 412   1 operator<<(
413   std::ostream& os, 413   std::ostream& os,
414   params_base const& qp) 414   params_base const& qp)
415   { 415   {
HITCBC 416   1 os << qp.buffer(); 416   1 os << qp.buffer();
HITCBC 417   1 return os; 417   1 return os;
418   } 418   }
419   419  
420   } // urls 420   } // urls
421   } // boost 421   } // boost
422   422  
423   #endif 423   #endif