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