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