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_base.hpp>
15 : #include <boost/url/grammar/ci_string.hpp>
16 : #include <ostream>
17 : #include <string>
18 :
19 : namespace boost {
20 : namespace urls {
21 :
22 : //------------------------------------------------
23 :
24 310 : params_base::
25 : iterator::
26 : iterator(
27 : detail::query_ref const& ref,
28 310 : encoding_opts opt) noexcept
29 310 : : it_(ref)
30 310 : , space_as_plus_(opt.space_as_plus)
31 : {
32 310 : }
33 :
34 234 : params_base::
35 : iterator::
36 : iterator(
37 : detail::query_ref const& ref,
38 : encoding_opts opt,
39 234 : int) noexcept
40 234 : : it_(ref, 0)
41 234 : , space_as_plus_(opt.space_as_plus)
42 : {
43 234 : }
44 :
45 :
46 : auto
47 775 : params_base::
48 : iterator::
49 : operator*() const ->
50 : reference
51 :
52 : {
53 775 : encoding_opts opt;
54 775 : opt.space_as_plus =
55 775 : space_as_plus_;
56 : param_pct_view p =
57 775 : it_.dereference();
58 : return reference(
59 1550 : p.key.decode(opt),
60 1550 : p.value.decode(opt),
61 3875 : p.has_value);
62 : }
63 :
64 : //------------------------------------------------
65 : //
66 : // params_base
67 : //
68 : //------------------------------------------------
69 :
70 1 : params_base::
71 1 : params_base() noexcept
72 : // space_as_plus = true
73 1 : : opt_(true, false, false)
74 : {
75 1 : }
76 :
77 : bool
78 28 : params_base::
79 : contains(
80 : core::string_view key,
81 : ignore_case_param ic) const noexcept
82 : {
83 28 : return find(
84 56 : begin(),key, ic) != end();
85 : }
86 :
87 : auto
88 40 : params_base::
89 : find(
90 : core::string_view key,
91 : ignore_case_param ic) const noexcept ->
92 : iterator
93 : {
94 : return iterator(
95 40 : find_impl(
96 80 : begin().it_, key, ic),
97 40 : opt_);
98 : }
99 :
100 : auto
101 60 : params_base::
102 : find(
103 : iterator it,
104 : core::string_view key,
105 : ignore_case_param ic) const noexcept ->
106 : iterator
107 : {
108 : return iterator(
109 120 : find_impl(
110 : it.it_, key, ic),
111 60 : opt_);
112 : }
113 :
114 : auto
115 4 : params_base::
116 : find_last(
117 : core::string_view key,
118 : ignore_case_param ic) const noexcept ->
119 : iterator
120 : {
121 : return iterator(
122 4 : find_last_impl(
123 8 : end().it_, key, ic),
124 4 : opt_);
125 : }
126 :
127 : auto
128 9 : params_base::
129 : find_last(
130 : iterator it,
131 : core::string_view key,
132 : ignore_case_param ic) const noexcept ->
133 : iterator
134 : {
135 : return iterator(
136 18 : find_last_impl(
137 : it.it_, key, ic),
138 9 : opt_);
139 : }
140 :
141 295 : params_base::
142 : params_base(
143 : detail::query_ref const& ref,
144 295 : encoding_opts opt) noexcept
145 295 : : ref_(ref)
146 295 : , opt_(opt)
147 : {
148 295 : }
149 :
150 : pct_string_view
151 13 : params_base::
152 : buffer() const noexcept
153 : {
154 13 : return ref_.buffer();
155 : }
156 :
157 : bool
158 5 : params_base::
159 : empty() const noexcept
160 : {
161 5 : return ref_.nparam() == 0;
162 : }
163 :
164 : std::size_t
165 213 : params_base::
166 : size() const noexcept
167 : {
168 213 : return ref_.nparam();
169 : }
170 :
171 : auto
172 310 : params_base::
173 : begin() const noexcept ->
174 : iterator
175 : {
176 310 : return iterator(ref_, opt_);
177 : }
178 :
179 : auto
180 234 : params_base::
181 : end() const noexcept ->
182 : iterator
183 : {
184 234 : return {ref_, opt_, 0};
185 : }
186 :
187 : //------------------------------------------------
188 :
189 : std::size_t
190 29 : params_base::
191 : count(
192 : core::string_view key,
193 : ignore_case_param ic) const noexcept
194 : {
195 29 : std::size_t n = 0;
196 29 : auto it = find(key, ic);
197 29 : auto const end_ = end();
198 57 : while(it != end_)
199 : {
200 28 : ++n;
201 28 : ++it;
202 28 : it = find(it, key, ic);
203 : }
204 29 : return n;
205 : }
206 :
207 : std::string
208 8 : params_base::
209 : get_or(
210 : core::string_view key,
211 : core::string_view value,
212 : ignore_case_param ic) const
213 : {
214 8 : auto it = find_impl(
215 8 : begin().it_, key, ic);
216 8 : detail::params_iter_impl end_(ref_, 0);
217 8 : if(it.equal(end_))
218 2 : return std::string(value);
219 :
220 6 : param_pct_view const p = it.dereference();
221 6 : if(! p.has_value)
222 1 : return std::string();
223 :
224 5 : auto opt = opt_;
225 5 : return p.value.decode(opt);
226 : }
227 :
228 : //------------------------------------------------
229 : //
230 : // (implementation)
231 : //
232 : //------------------------------------------------
233 :
234 : detail::params_iter_impl
235 108 : params_base::
236 : find_impl(
237 : detail::params_iter_impl it,
238 : core::string_view key,
239 : ignore_case_param ic) const noexcept
240 : {
241 108 : detail::params_iter_impl end_(ref_, 0);
242 108 : if(! ic)
243 : {
244 : for(;;)
245 : {
246 320 : if(it.equal(end_))
247 33 : return it;
248 287 : if(*it.key() == key)
249 37 : return it;
250 250 : it.increment();
251 : }
252 : }
253 : for(;;)
254 : {
255 129 : if(it.equal(end_))
256 10 : return it;
257 119 : if( grammar::ci_is_equal(
258 238 : *it.key(), key))
259 28 : return it;
260 91 : it.increment();
261 : }
262 : }
263 :
264 : detail::params_iter_impl
265 13 : params_base::
266 : find_last_impl(
267 : detail::params_iter_impl it,
268 : core::string_view key,
269 : ignore_case_param ic) const noexcept
270 : {
271 13 : detail::params_iter_impl begin_(ref_);
272 13 : if(! ic)
273 : {
274 : for(;;)
275 : {
276 13 : if(it.equal(begin_))
277 2 : return { ref_, 0 };
278 11 : it.decrement();
279 11 : if(*it.key() == key)
280 5 : return it;
281 : }
282 : }
283 : for(;;)
284 : {
285 9 : if(it.equal(begin_))
286 1 : return { ref_, 0 };
287 8 : it.decrement();
288 8 : if(grammar::ci_is_equal(
289 16 : *it.key(), key))
290 5 : return it;
291 : }
292 : }
293 :
294 : //------------------------------------------------
295 :
296 : std::ostream&
297 1 : operator<<(
298 : std::ostream& os,
299 : params_base const& qp)
300 : {
301 1 : os << qp.buffer();
302 1 : return os;
303 : }
304 :
305 : } // urls
306 : } // boost
|