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 100 : params_ref::
175 : params_ref(
176 : url_base& u,
177 100 : encoding_opts opt) noexcept
178 100 : : params_base(u.impl_, opt)
179 100 : , u_(&u)
180 : {
181 100 : }
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 3 : params_ref::
232 : clear() noexcept
233 : {
234 3 : u_->remove_query();
235 3 : }
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 16 : params_ref::
250 : insert(
251 : iterator before,
252 : param_view const& p) ->
253 : iterator
254 : {
255 : return {
256 16 : u_->edit_params(
257 : before.it_,
258 : before.it_,
259 32 : detail::single_param_iter(p, opt_.space_as_plus)),
260 32 : 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 12 : params_ref::
281 : append(
282 : param_view const& p) ->
283 : iterator
284 : {
285 12 : 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 8 : params_ref::
334 : replace(
335 : iterator pos,
336 : param_view const& p) ->
337 : iterator
338 : {
339 : return iterator(
340 24 : u_->edit_params(
341 : pos.it_,
342 8 : std::next(pos).it_,
343 16 : detail::single_param_iter(p, opt_.space_as_plus)),
344 16 : 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_);
380 : }
381 :
382 : inline
383 : auto
384 5 : params_ref::
385 : set(
386 : iterator pos,
387 : core::string_view value) ->
388 : iterator
389 : {
390 5 : BOOST_ASSERT(pos.it_.nk > 0);
391 : return iterator(
392 5 : u_->edit_params(
393 : pos.it_,
394 5 : pos.it_.next(),
395 5 : detail::param_value_iter(
396 5 : pos.it_.nk - 1, value, true)),
397 10 : opt_);
398 : }
399 :
400 : inline
401 : auto
402 1 : params_ref::
403 : set(
404 : core::string_view key,
405 : core::string_view value,
406 : ignore_case_param ic) ->
407 : iterator
408 : {
409 : // VFALCO we can't cache end() here
410 : // because it is invalidated
411 : // every time we set or erase.
412 1 : auto it0 = find(key, ic);
413 1 : if(it0 == end())
414 MIS 0 : return append({key, value});
415 HIT 1 : it0 = set(it0, value);
416 1 : auto it = end();
417 : for(;;)
418 : {
419 2 : it = find_last(it, key, ic);
420 2 : if(it == it0)
421 1 : return it0;
422 1 : it = erase(it);
423 : }
424 : }
425 :
426 : inline
427 : auto
428 9 : params_ref::
429 : erase(
430 : iterator pos) noexcept ->
431 : iterator
432 : {
433 9 : return erase(
434 : pos,
435 9 : std::next(pos));
436 : }
437 :
438 : inline
439 : auto
440 11 : params_ref::
441 : erase(
442 : iterator first,
443 : iterator last) noexcept ->
444 : iterator
445 : {
446 11 : core::string_view s("", 0);
447 : return iterator(
448 11 : u_->edit_params(
449 : first.it_,
450 : last.it_,
451 22 : detail::query_string_iter(s)),
452 11 : opt_);
453 : }
454 :
455 : } // urls
456 : } // boost
457 :
458 : #endif
|