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