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