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