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