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_IPP
12 : #define BOOST_URL_IMPL_PARAMS_ENCODED_REF_IPP
13 :
14 : #include <boost/url/detail/config.hpp>
15 : #include <boost/url/decode_view.hpp>
16 : #include <boost/url/params_encoded_ref.hpp>
17 : #include <boost/url/params_encoded_view.hpp>
18 : #include <boost/url/url_base.hpp>
19 : #include <boost/url/grammar/ci_string.hpp>
20 : #include <boost/assert.hpp>
21 : #include <utility>
22 :
23 : namespace boost {
24 : namespace urls {
25 :
26 : //------------------------------------------------
27 : //
28 : // Special Members
29 : //
30 : //------------------------------------------------
31 :
32 77 : params_encoded_ref::
33 : params_encoded_ref(
34 77 : url_base& u) noexcept
35 77 : : params_encoded_base(u.impl_)
36 77 : , u_(&u)
37 : {
38 77 : }
39 :
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 : params_encoded_ref&
51 2 : params_encoded_ref::
52 : operator=(std::initializer_list<
53 : param_pct_view> init)
54 : {
55 2 : assign(init.begin(), init.end());
56 2 : return *this;
57 : }
58 :
59 58 : params_encoded_ref::
60 : operator
61 : params_encoded_view() const noexcept
62 : {
63 58 : return {ref_};
64 : }
65 :
66 : //------------------------------------------------
67 : //
68 : // Modifiers
69 : //
70 : //------------------------------------------------
71 :
72 : void
73 3 : params_encoded_ref::
74 : assign(
75 : std::initializer_list<
76 : param_pct_view> init)
77 : {
78 3 : assign(init.begin(), init.end());
79 3 : }
80 :
81 : auto
82 7 : params_encoded_ref::
83 : insert(
84 : iterator before,
85 : param_pct_view const& p) ->
86 : iterator
87 : {
88 14 : return u_->edit_params(
89 : before.it_,
90 : before.it_,
91 7 : detail::param_encoded_iter(p));
92 : }
93 :
94 : auto
95 12 : params_encoded_ref::
96 : insert(
97 : iterator before,
98 : std::initializer_list<
99 : param_pct_view> init) ->
100 : iterator
101 : {
102 : return insert(
103 : before,
104 : init.begin(),
105 12 : init.end());
106 : }
107 :
108 : std::size_t
109 2 : params_encoded_ref::
110 : erase(
111 : pct_string_view key,
112 : ignore_case_param ic) noexcept
113 : {
114 : // end() can't be fully cached,
115 : // since erase invalidates it.
116 2 : iterator it;
117 : {
118 2 : auto const end_ = end();
119 2 : it = find_last(end_, key, ic);
120 2 : if(it == end_)
121 0 : return 0;
122 : }
123 2 : std::size_t n = 0;
124 : for(;;)
125 : {
126 5 : ++n;
127 : // Use it->key instead of key,
128 : // to handle self-intersection
129 5 : auto prev = find_last(it, it->key, ic);
130 5 : if(prev == end())
131 2 : break;
132 3 : erase(it);
133 3 : it = prev;
134 3 : }
135 2 : erase(it);
136 2 : return n;
137 : }
138 :
139 : auto
140 5 : params_encoded_ref::
141 : replace(
142 : iterator pos,
143 : param_pct_view const& p) ->
144 : iterator
145 : {
146 10 : return u_->edit_params(
147 : pos.it_,
148 5 : std::next(pos).it_,
149 10 : detail::param_encoded_iter(p));
150 : }
151 :
152 : auto
153 1 : params_encoded_ref::
154 : replace(
155 : iterator from,
156 : iterator to,
157 : std::initializer_list<
158 : param_pct_view> init) ->
159 : iterator
160 : {
161 : return replace(
162 : from,
163 : to,
164 : init.begin(),
165 1 : init.end());
166 : }
167 :
168 : auto
169 4 : params_encoded_ref::
170 : unset(
171 : iterator pos) noexcept ->
172 : iterator
173 : {
174 4 : BOOST_ASSERT(pos.it_.nk > 0);
175 4 : pct_string_view s;
176 8 : return u_->edit_params(
177 4 : pos.it_, pos.it_.next(),
178 4 : detail::param_encoded_value_iter(
179 8 : pos.it_.nk - 1, s, false));
180 : }
181 :
182 : auto
183 4 : params_encoded_ref::
184 : set(
185 : iterator pos,
186 : pct_string_view value) ->
187 : iterator
188 : {
189 4 : BOOST_ASSERT(pos.it_.nk > 0);
190 8 : return u_->edit_params(
191 : pos.it_,
192 4 : pos.it_.next(),
193 4 : detail::param_encoded_value_iter(
194 12 : pos.it_.nk - 1, value, true));
195 : }
196 :
197 : auto
198 1 : params_encoded_ref::
199 : set(
200 : pct_string_view key,
201 : pct_string_view value,
202 : ignore_case_param ic) ->
203 : iterator
204 : {
205 : // VFALCO we can't cache end() here
206 : // because it is invalidated
207 : // every time we set or erase.
208 1 : auto it0 = find(key, ic);
209 1 : if(it0 == end())
210 0 : return append({key, value});
211 1 : it0 = set(it0, value);
212 1 : auto it = end();
213 : for(;;)
214 : {
215 2 : it = find_last(it, key, ic);
216 2 : if(it == it0)
217 1 : return it0;
218 1 : it = erase(it);
219 : }
220 : }
221 :
222 : auto
223 9 : params_encoded_ref::
224 : erase(
225 : iterator pos) noexcept ->
226 : iterator
227 : {
228 : return erase(
229 : pos,
230 9 : std::next(pos));
231 : }
232 :
233 : auto
234 11 : params_encoded_ref::
235 : erase(
236 : iterator first,
237 : iterator last) noexcept ->
238 : iterator
239 : {
240 11 : core::string_view s("", 0);
241 22 : return u_->edit_params(
242 : first.it_,
243 : last.it_,
244 11 : detail::query_iter(s));
245 : }
246 :
247 :
248 : //------------------------------------------------
249 : //
250 : // (implementation)
251 : //
252 : //------------------------------------------------
253 :
254 : detail::params_iter_impl
255 0 : params_encoded_ref::
256 : find_impl(
257 : detail::params_iter_impl it,
258 : pct_string_view key,
259 : ignore_case_param ic) const noexcept
260 : {
261 0 : detail::params_iter_impl end_(u_->impl_, 0);
262 0 : if(! ic)
263 : {
264 : for(;;)
265 : {
266 0 : if(it.equal(end_))
267 0 : return it;
268 0 : if(*it.key() == *key)
269 0 : return it;
270 0 : it.increment();
271 : }
272 : }
273 : for(;;)
274 : {
275 0 : if(it.equal(end_))
276 0 : return it;
277 0 : if( grammar::ci_is_equal(
278 0 : *it.key(), *key))
279 0 : return it;
280 0 : it.increment();
281 : }
282 : }
283 :
284 : detail::params_iter_impl
285 0 : params_encoded_ref::
286 : find_last_impl(
287 : detail::params_iter_impl it,
288 : pct_string_view key,
289 : ignore_case_param ic) const noexcept
290 : {
291 0 : detail::params_iter_impl begin_(u_->impl_);
292 0 : if(! ic)
293 : {
294 : for(;;)
295 : {
296 0 : if(it.equal(begin_))
297 0 : return { u_->impl_, 0 };
298 0 : it.decrement();
299 0 : if(*it.key() == *key)
300 0 : return it;
301 : }
302 : }
303 : for(;;)
304 : {
305 0 : if(it.equal(begin_))
306 0 : return { u_->impl_, 0 };
307 0 : it.decrement();
308 0 : if(grammar::ci_is_equal(
309 0 : *it.key(), *key))
310 0 : return it;
311 : }
312 : }
313 :
314 : } // urls
315 : } // boost
316 :
317 : #endif
|