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