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 143 : any_params_iter(
39 : bool empty_,
40 : core::string_view s0_ = {},
41 : core::string_view s1_ = {}) noexcept
42 143 : : s0(s0_)
43 143 : , s1(s1_)
44 143 : , empty(empty_)
45 : {
46 143 : }
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 : BOOST_URL_DECL
97 : explicit
98 : query_string_iter(
99 : core::string_view s,
100 : bool ne = false) noexcept;
101 :
102 : private:
103 : core::string_view s_;
104 : std::size_t n_;
105 : char const* p_;
106 : bool at_end_;
107 :
108 : void rewind() noexcept override;
109 : bool measure(std::size_t&) noexcept override;
110 : void copy(char*&, char const*) noexcept override;
111 : void increment() noexcept;
112 : };
113 :
114 : //------------------------------------------------
115 : //
116 : // param_iter
117 : //
118 : //------------------------------------------------
119 :
120 : // A 1-param range allowing
121 : // self-intersection
122 : struct BOOST_SYMBOL_VISIBLE
123 : single_param_iter
124 : : any_params_iter
125 : {
126 : explicit
127 : single_param_iter(
128 : param_view const&,
129 : bool space_as_plus) noexcept;
130 :
131 : private:
132 : bool has_value_;
133 : bool at_end_ = false;
134 : bool space_as_plus_ = false;
135 :
136 : void rewind() noexcept override;
137 : bool measure(std::size_t&) noexcept override;
138 : void copy(char*&, char const*) noexcept override;
139 : };
140 :
141 : //------------------------------------------------
142 : //
143 : // params_iter_base
144 : //
145 : //------------------------------------------------
146 :
147 : struct params_iter_base
148 : {
149 : bool space_as_plus_ = true;
150 : protected:
151 32 : explicit params_iter_base(
152 : bool space_as_plus) noexcept
153 32 : : space_as_plus_(space_as_plus)
154 32 : {}
155 :
156 : // return encoded size
157 : BOOST_URL_DECL
158 : void
159 : measure_impl(
160 : std::size_t& n,
161 : param_view const& p) noexcept;
162 :
163 : // encode to dest
164 : BOOST_URL_DECL
165 : void
166 : copy_impl(
167 : char*& dest,
168 : char const* end,
169 : param_view const& v) noexcept;
170 : };
171 :
172 : //------------------------------------------------
173 :
174 : // A range of plain query params_ref
175 : template<class FwdIt>
176 : struct params_iter
177 : : any_params_iter
178 : , private params_iter_base
179 : {
180 : BOOST_CORE_STATIC_ASSERT(
181 : std::is_convertible<
182 : typename std::iterator_traits<
183 : FwdIt>::reference,
184 : param_view>::value);
185 :
186 32 : params_iter(
187 : FwdIt first,
188 : FwdIt last,
189 : bool space_as_plus) noexcept
190 : : any_params_iter(
191 1 : first == last)
192 : , params_iter_base(space_as_plus)
193 32 : , it0_(first)
194 32 : , it_(first)
195 33 : , end_(last)
196 : {
197 32 : }
198 :
199 : private:
200 : FwdIt it0_;
201 : FwdIt it_;
202 : FwdIt end_;
203 :
204 : void
205 32 : rewind() noexcept override
206 : {
207 32 : it_ = it0_;
208 32 : }
209 :
210 : bool
211 102 : measure(
212 : std::size_t& n) noexcept override
213 : {
214 102 : if(it_ == end_)
215 32 : return false;
216 70 : measure_impl(n,
217 71 : param_view(*it_++));
218 70 : return true;
219 : }
220 :
221 : void
222 70 : copy(
223 : char*& dest,
224 : char const* end) noexcept override
225 : {
226 70 : copy_impl(dest, end,
227 71 : param_view(*it_++));
228 70 : }
229 : };
230 :
231 : //------------------------------------------------
232 : //
233 : // param_encoded_iter
234 : //
235 : //------------------------------------------------
236 :
237 : // A 1-param encoded range
238 : // allowing self-intersection
239 : struct BOOST_SYMBOL_VISIBLE
240 : param_encoded_iter
241 : : any_params_iter
242 : {
243 : explicit
244 : param_encoded_iter(
245 : param_pct_view const&) noexcept;
246 :
247 : private:
248 : bool has_value_;
249 : bool at_end_ = false;
250 :
251 : void rewind() noexcept override;
252 : bool measure(std::size_t&) noexcept override;
253 : void copy(char*&, char const*) noexcept override;
254 : };
255 :
256 : //------------------------------------------------
257 : //
258 : // params_encoded_iter
259 : //
260 : //------------------------------------------------
261 :
262 : // Validating and copying from
263 : // a string of encoded params
264 : struct params_encoded_iter_base
265 : {
266 : protected:
267 : BOOST_URL_DECL
268 : static
269 : void
270 : measure_impl(
271 : std::size_t& n,
272 : param_view const& v) noexcept;
273 :
274 : BOOST_URL_DECL
275 : static
276 : void
277 : copy_impl(
278 : char*& dest,
279 : char const* end,
280 : param_view const& v) noexcept;
281 : };
282 :
283 : //------------------------------------------------
284 :
285 : // A range of encoded query params_ref
286 : template<class FwdIt>
287 : struct params_encoded_iter
288 : : any_params_iter
289 : , private params_encoded_iter_base
290 : {
291 : BOOST_CORE_STATIC_ASSERT(
292 : std::is_convertible<
293 : typename std::iterator_traits<
294 : FwdIt>::reference,
295 : param_view>::value);
296 :
297 29 : params_encoded_iter(
298 : FwdIt first,
299 : FwdIt last) noexcept
300 : : any_params_iter(
301 1 : first == last)
302 29 : , it0_(first)
303 29 : , it_(first)
304 30 : , end_(last)
305 : {
306 29 : }
307 :
308 : private:
309 : FwdIt it0_;
310 : FwdIt it_;
311 : FwdIt end_;
312 :
313 : void
314 24 : rewind() noexcept override
315 : {
316 24 : it_ = it0_;
317 24 : }
318 :
319 : bool
320 80 : measure(
321 : std::size_t& n) override
322 : {
323 80 : if(it_ == end_)
324 24 : return false;
325 : // throw on invalid input
326 51 : measure_impl(n,
327 43 : param_pct_view(
328 56 : param_view(*it_++)));
329 51 : return true;
330 : }
331 :
332 : void
333 51 : copy(
334 : char*& dest,
335 : char const* end
336 : ) noexcept override
337 : {
338 51 : copy_impl(dest, end,
339 51 : param_view(*it_++));
340 51 : }
341 : };
342 :
343 : //------------------------------------------------
344 : //
345 : // param_value_iter
346 : //
347 : //------------------------------------------------
348 :
349 : // An iterator which outputs
350 : // one value on an existing key
351 : struct param_value_iter
352 : : any_params_iter
353 : {
354 9 : param_value_iter(
355 : std::size_t nk,
356 : core::string_view const& value,
357 : bool has_value) noexcept
358 9 : : any_params_iter(
359 : false,
360 : value)
361 9 : , nk_(nk)
362 9 : , has_value_(has_value)
363 : {
364 9 : }
365 :
366 : private:
367 : std::size_t nk_ = 0;
368 : bool has_value_ = false;
369 : bool at_end_ = false;
370 :
371 : void rewind() noexcept override;
372 : bool measure(std::size_t&) noexcept override;
373 : void copy(char*&, char const*) noexcept override;
374 : };
375 :
376 : //------------------------------------------------
377 : //
378 : // param_encoded_value_iter
379 : //
380 : //------------------------------------------------
381 :
382 : // An iterator which outputs one
383 : // encoded value on an existing key
384 : struct param_encoded_value_iter
385 : : any_params_iter
386 : {
387 8 : param_encoded_value_iter(
388 : std::size_t nk,
389 : pct_string_view const& value,
390 : bool has_value) noexcept
391 8 : : any_params_iter(
392 : false,
393 : value)
394 8 : , nk_(nk)
395 8 : , has_value_(has_value)
396 : {
397 8 : }
398 :
399 : private:
400 : std::size_t nk_ = 0;
401 : bool has_value_ = false;
402 : bool at_end_ = false;
403 :
404 : void rewind() noexcept override;
405 : bool measure(std::size_t&) noexcept override;
406 : void copy(char*&, char const*) noexcept override;
407 : };
408 :
409 : //------------------------------------------------
410 :
411 : template<class FwdIt>
412 : params_iter<FwdIt>
413 32 : make_params_iter(
414 : FwdIt first, FwdIt last, bool space_as_plus)
415 : {
416 : return params_iter<
417 32 : FwdIt>(first, last, space_as_plus);
418 : }
419 :
420 : template<class FwdIt>
421 : params_encoded_iter<FwdIt>
422 29 : make_params_encoded_iter(
423 : FwdIt first, FwdIt last)
424 : {
425 : return params_encoded_iter<
426 29 : FwdIt>(first, last);
427 : }
428 :
429 : } // detail
430 : } // urls
431 : } // boost
432 :
433 : #endif
|