Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/boostorg/url
8 : //
9 :
10 : #ifndef BOOST_URL_DETAIL_ANY_PARAMS_ITER_HPP
11 : #define BOOST_URL_DETAIL_ANY_PARAMS_ITER_HPP
12 :
13 : #include <boost/url/param.hpp>
14 : #include <boost/url/pct_string_view.hpp>
15 : #include <boost/core/detail/static_assert.hpp>
16 : #include <cstddef>
17 : #include <iterator>
18 : #include <type_traits>
19 :
20 : namespace boost {
21 : namespace urls {
22 : namespace detail {
23 :
24 : //------------------------------------------------
25 : //
26 : // any_params_iter
27 : //
28 : //------------------------------------------------
29 :
30 : /* An iterator to a type-erased,
31 : possibly encoded sequence of
32 : query params_ref.
33 : */
34 : struct BOOST_SYMBOL_VISIBLE
35 : any_params_iter
36 : {
37 : protected:
38 147 : any_params_iter(
39 : bool empty_,
40 : core::string_view s0_ = {},
41 : core::string_view s1_ = {}) noexcept
42 147 : : s0(s0_)
43 147 : , s1(s1_)
44 147 : , empty(empty_)
45 : {
46 147 : }
47 :
48 : public:
49 : // these are adjusted
50 : // when self-intersecting
51 : core::string_view s0;
52 : core::string_view s1;
53 :
54 : // True if the sequence is empty
55 : bool empty = false;
56 :
57 : BOOST_URL_DECL
58 : virtual
59 : ~any_params_iter() noexcept = 0;
60 :
61 : // Rewind the iterator to the beginning
62 : virtual
63 : void
64 : rewind() noexcept = 0;
65 :
66 : // Measure and increment current element.
67 : // Returns false on end of range.
68 : // n is increased by encoded size.
69 : // Can throw on bad percent-escape
70 : virtual
71 : bool
72 : measure(std::size_t& n) = 0;
73 :
74 : // Copy and increment the current
75 : // element. encoding is performed
76 : // if needed.
77 : virtual
78 : void
79 : copy(
80 : char*& dest,
81 : char const* end) noexcept = 0;
82 : };
83 :
84 : //------------------------------------------------
85 : //
86 : // query_string_iter
87 : //
88 : //------------------------------------------------
89 :
90 : // A string of plain query params
91 : struct BOOST_SYMBOL_VISIBLE
92 : query_string_iter
93 : : any_params_iter
94 : {
95 : // ne = never empty
96 : explicit
97 : query_string_iter(
98 : core::string_view s,
99 : bool ne = false) noexcept;
100 :
101 : private:
102 : core::string_view s_;
103 : std::size_t n_;
104 : char const* p_;
105 : bool at_end_;
106 :
107 : void rewind() noexcept override;
108 : bool measure(std::size_t&) noexcept override;
109 : void copy(char*&, char const*) noexcept override;
110 : void increment() noexcept;
111 : };
112 :
113 : //------------------------------------------------
114 : //
115 : // param_iter
116 : //
117 : //------------------------------------------------
118 :
119 : // A 1-param range allowing
120 : // self-intersection
121 : struct BOOST_SYMBOL_VISIBLE
122 : single_param_iter
123 : : any_params_iter
124 : {
125 : explicit
126 : single_param_iter(
127 : param_view const&,
128 : bool space_as_plus) noexcept;
129 :
130 : private:
131 : bool has_value_;
132 : bool at_end_ = false;
133 : bool space_as_plus_ = false;
134 :
135 : void rewind() noexcept override;
136 : bool measure(std::size_t&) noexcept override;
137 : void copy(char*&, char const*) noexcept override;
138 : };
139 :
140 : //------------------------------------------------
141 : //
142 : // params_iter_base
143 : //
144 : //------------------------------------------------
145 :
146 : struct params_iter_base
147 : {
148 : bool space_as_plus_ = true;
149 : protected:
150 32 : explicit params_iter_base(
151 : bool space_as_plus) noexcept
152 32 : : space_as_plus_(space_as_plus)
153 32 : {}
154 :
155 : // return encoded size
156 : BOOST_URL_DECL
157 : void
158 : measure_impl(
159 : std::size_t& n,
160 : param_view const& p) noexcept;
161 :
162 : // encode to dest
163 : BOOST_URL_DECL
164 : void
165 : copy_impl(
166 : char*& dest,
167 : char const* end,
168 : param_view const& v) noexcept;
169 : };
170 :
171 : //------------------------------------------------
172 :
173 : // A range of plain query params_ref
174 : template<class FwdIt>
175 : struct params_iter
176 : : any_params_iter
177 : , private params_iter_base
178 : {
179 : BOOST_CORE_STATIC_ASSERT(
180 : std::is_convertible<
181 : typename std::iterator_traits<
182 : FwdIt>::reference,
183 : param_view>::value);
184 :
185 32 : params_iter(
186 : FwdIt first,
187 : FwdIt last,
188 : bool space_as_plus) noexcept
189 : : any_params_iter(
190 1 : first == last)
191 : , params_iter_base(space_as_plus)
192 32 : , it0_(first)
193 32 : , it_(first)
194 33 : , end_(last)
195 : {
196 32 : }
197 :
198 : private:
199 : FwdIt it0_;
200 : FwdIt it_;
201 : FwdIt end_;
202 :
203 : void
204 32 : rewind() noexcept override
205 : {
206 32 : it_ = it0_;
207 32 : }
208 :
209 : bool
210 102 : measure(
211 : std::size_t& n) noexcept override
212 : {
213 102 : if(it_ == end_)
214 32 : return false;
215 70 : measure_impl(n,
216 71 : param_view(*it_++));
217 70 : return true;
218 : }
219 :
220 : void
221 70 : copy(
222 : char*& dest,
223 : char const* end) noexcept override
224 : {
225 70 : copy_impl(dest, end,
226 71 : param_view(*it_++));
227 70 : }
228 : };
229 :
230 : //------------------------------------------------
231 : //
232 : // param_encoded_iter
233 : //
234 : //------------------------------------------------
235 :
236 : // A 1-param encoded range
237 : // allowing self-intersection
238 : struct BOOST_SYMBOL_VISIBLE
239 : param_encoded_iter
240 : : any_params_iter
241 : {
242 : explicit
243 : param_encoded_iter(
244 : param_pct_view const&) noexcept;
245 :
246 : private:
247 : bool has_value_;
248 : bool at_end_ = false;
249 :
250 : void rewind() noexcept override;
251 : bool measure(std::size_t&) noexcept override;
252 : void copy(char*&, char const*) noexcept override;
253 : };
254 :
255 : //------------------------------------------------
256 : //
257 : // params_encoded_iter
258 : //
259 : //------------------------------------------------
260 :
261 : // Validating and copying from
262 : // a string of encoded params
263 : struct params_encoded_iter_base
264 : {
265 : protected:
266 : BOOST_URL_DECL
267 : static
268 : void
269 : measure_impl(
270 : std::size_t& n,
271 : param_view const& v) noexcept;
272 :
273 : BOOST_URL_DECL
274 : static
275 : void
276 : copy_impl(
277 : char*& dest,
278 : char const* end,
279 : param_view const& v) noexcept;
280 : };
281 :
282 : //------------------------------------------------
283 :
284 : // A range of encoded query params_ref
285 : template<class FwdIt>
286 : struct params_encoded_iter
287 : : any_params_iter
288 : , private params_encoded_iter_base
289 : {
290 : BOOST_CORE_STATIC_ASSERT(
291 : std::is_convertible<
292 : typename std::iterator_traits<
293 : FwdIt>::reference,
294 : param_view>::value);
295 :
296 29 : params_encoded_iter(
297 : FwdIt first,
298 : FwdIt last) noexcept
299 : : any_params_iter(
300 1 : first == last)
301 29 : , it0_(first)
302 29 : , it_(first)
303 30 : , end_(last)
304 : {
305 29 : }
306 :
307 : private:
308 : FwdIt it0_;
309 : FwdIt it_;
310 : FwdIt end_;
311 :
312 : void
313 24 : rewind() noexcept override
314 : {
315 24 : it_ = it0_;
316 24 : }
317 :
318 : bool
319 80 : measure(
320 : std::size_t& n) override
321 : {
322 80 : if(it_ == end_)
323 24 : return false;
324 : // throw on invalid input
325 51 : measure_impl(n,
326 43 : param_pct_view(
327 56 : param_view(*it_++)));
328 51 : return true;
329 : }
330 :
331 : void
332 51 : copy(
333 : char*& dest,
334 : char const* end
335 : ) noexcept override
336 : {
337 51 : copy_impl(dest, end,
338 51 : param_view(*it_++));
339 51 : }
340 : };
341 :
342 : //------------------------------------------------
343 : //
344 : // param_value_iter
345 : //
346 : //------------------------------------------------
347 :
348 : // An iterator which outputs
349 : // one value on an existing key
350 : struct param_value_iter
351 : : any_params_iter
352 : {
353 9 : param_value_iter(
354 : std::size_t nk,
355 : core::string_view const& value,
356 : bool has_value) noexcept
357 9 : : any_params_iter(
358 : false,
359 : value)
360 9 : , nk_(nk)
361 9 : , has_value_(has_value)
362 : {
363 9 : }
364 :
365 : private:
366 : std::size_t nk_ = 0;
367 : bool has_value_ = false;
368 : bool at_end_ = false;
369 :
370 : void rewind() noexcept override;
371 : bool measure(std::size_t&) noexcept override;
372 : void copy(char*&, char const*) noexcept override;
373 : };
374 :
375 : //------------------------------------------------
376 : //
377 : // param_encoded_value_iter
378 : //
379 : //------------------------------------------------
380 :
381 : // An iterator which outputs one
382 : // encoded value on an existing key
383 : struct param_encoded_value_iter
384 : : any_params_iter
385 : {
386 8 : param_encoded_value_iter(
387 : std::size_t nk,
388 : pct_string_view const& value,
389 : bool has_value) noexcept
390 8 : : any_params_iter(
391 : false,
392 : value)
393 8 : , nk_(nk)
394 8 : , has_value_(has_value)
395 : {
396 8 : }
397 :
398 : private:
399 : std::size_t nk_ = 0;
400 : bool has_value_ = false;
401 : bool at_end_ = false;
402 :
403 : void rewind() noexcept override;
404 : bool measure(std::size_t&) noexcept override;
405 : void copy(char*&, char const*) noexcept override;
406 : };
407 :
408 : //------------------------------------------------
409 :
410 : template<class FwdIt>
411 : params_iter<FwdIt>
412 32 : make_params_iter(
413 : FwdIt first, FwdIt last, bool space_as_plus)
414 : {
415 : return params_iter<
416 32 : FwdIt>(first, last, space_as_plus);
417 : }
418 :
419 : template<class FwdIt>
420 : params_encoded_iter<FwdIt>
421 29 : make_params_encoded_iter(
422 : FwdIt first, FwdIt last)
423 : {
424 : return params_encoded_iter<
425 29 : FwdIt>(first, last);
426 : }
427 :
428 : } // detail
429 : } // urls
430 : } // boost
431 :
432 : #include <boost/url/detail/impl/any_params_iter.hpp>
433 :
434 : #endif
|