1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/url
7  
// Official repository: https://github.com/boostorg/url
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_URL_DETAIL_ANY_PARAMS_ITER_HPP
10  
#ifndef BOOST_URL_DETAIL_ANY_PARAMS_ITER_HPP
11  
#define BOOST_URL_DETAIL_ANY_PARAMS_ITER_HPP
11  
#define BOOST_URL_DETAIL_ANY_PARAMS_ITER_HPP
12  

12  

13  
#include <boost/url/param.hpp>
13  
#include <boost/url/param.hpp>
14  
#include <boost/url/pct_string_view.hpp>
14  
#include <boost/url/pct_string_view.hpp>
15  
#include <boost/core/detail/static_assert.hpp>
15  
#include <boost/core/detail/static_assert.hpp>
16  
#include <cstddef>
16  
#include <cstddef>
17  
#include <iterator>
17  
#include <iterator>
18  
#include <type_traits>
18  
#include <type_traits>
19  

19  

20  
namespace boost {
20  
namespace boost {
21  
namespace urls {
21  
namespace urls {
22  
namespace detail {
22  
namespace detail {
23  

23  

24  
//------------------------------------------------
24  
//------------------------------------------------
25  
//
25  
//
26  
// any_params_iter
26  
// any_params_iter
27  
//
27  
//
28  
//------------------------------------------------
28  
//------------------------------------------------
29  

29  

30  
/*  An iterator to a type-erased,
30  
/*  An iterator to a type-erased,
31  
    possibly encoded sequence of
31  
    possibly encoded sequence of
32  
    query params_ref.
32  
    query params_ref.
33  
*/  
33  
*/  
34  
struct BOOST_SYMBOL_VISIBLE
34  
struct BOOST_SYMBOL_VISIBLE
35  
    any_params_iter
35  
    any_params_iter
36  
{
36  
{
37  
protected:
37  
protected:
38  
    any_params_iter(
38  
    any_params_iter(
39  
        bool empty_,
39  
        bool empty_,
40  
        core::string_view s0_ = {},
40  
        core::string_view s0_ = {},
41  
        core::string_view s1_ = {}) noexcept
41  
        core::string_view s1_ = {}) noexcept
42  
        : s0(s0_)
42  
        : s0(s0_)
43  
        , s1(s1_)
43  
        , s1(s1_)
44  
        , empty(empty_)
44  
        , empty(empty_)
45  
    {
45  
    {
46  
    }
46  
    }
47  

47  

48  
public:
48  
public:
49  
    // these are adjusted
49  
    // these are adjusted
50  
    // when self-intersecting
50  
    // when self-intersecting
51  
    core::string_view s0;
51  
    core::string_view s0;
52  
    core::string_view s1;
52  
    core::string_view s1;
53  

53  

54  
    // True if the sequence is empty
54  
    // True if the sequence is empty
55  
    bool empty = false;
55  
    bool empty = false;
56  

56  

57  
    BOOST_URL_DECL
57  
    BOOST_URL_DECL
58  
    virtual
58  
    virtual
59  
    ~any_params_iter() noexcept = 0;
59  
    ~any_params_iter() noexcept = 0;
60  

60  

61  
    // Rewind the iterator to the beginning
61  
    // Rewind the iterator to the beginning
62  
    virtual
62  
    virtual
63  
    void
63  
    void
64  
    rewind() noexcept = 0;
64  
    rewind() noexcept = 0;
65  

65  

66  
    // Measure and increment current element.
66  
    // Measure and increment current element.
67  
    // Returns false on end of range.
67  
    // Returns false on end of range.
68  
    // n is increased by encoded size.
68  
    // n is increased by encoded size.
69  
    // Can throw on bad percent-escape
69  
    // Can throw on bad percent-escape
70  
    virtual
70  
    virtual
71  
    bool
71  
    bool
72  
    measure(std::size_t& n) = 0;
72  
    measure(std::size_t& n) = 0;
73  

73  

74  
    // Copy and increment the current
74  
    // Copy and increment the current
75  
    // element. encoding is performed
75  
    // element. encoding is performed
76  
    // if needed.
76  
    // if needed.
77  
    virtual
77  
    virtual
78  
    void
78  
    void
79  
    copy(
79  
    copy(
80  
        char*& dest,
80  
        char*& dest,
81  
        char const* end) noexcept = 0;
81  
        char const* end) noexcept = 0;
82  
};
82  
};
83  

83  

84  
//------------------------------------------------
84  
//------------------------------------------------
85  
//
85  
//
86  
// query_string_iter
86  
// query_string_iter
87  
//
87  
//
88  
//------------------------------------------------
88  
//------------------------------------------------
89  

89  

90  
// A string of plain query params
90  
// A string of plain query params
91  
struct BOOST_SYMBOL_VISIBLE
91  
struct BOOST_SYMBOL_VISIBLE
92  
    query_string_iter
92  
    query_string_iter
93  
    : any_params_iter
93  
    : any_params_iter
94  
{
94  
{
95  
    // ne = never empty
95  
    // ne = never empty
96  
    BOOST_URL_DECL
96  
    BOOST_URL_DECL
97  
    explicit
97  
    explicit
98  
    query_string_iter(
98  
    query_string_iter(
99  
        core::string_view s,
99  
        core::string_view s,
100  
        bool ne = false) noexcept;
100  
        bool ne = false) noexcept;
101  

101  

102  
private:
102  
private:
103  
    core::string_view s_;
103  
    core::string_view s_;
104  
    std::size_t n_;
104  
    std::size_t n_;
105  
    char const* p_;
105  
    char const* p_;
106  
    bool at_end_;
106  
    bool at_end_;
107  

107  

108  
    void rewind() noexcept override;
108  
    void rewind() noexcept override;
109  
    bool measure(std::size_t&) noexcept override;
109  
    bool measure(std::size_t&) noexcept override;
110  
    void copy(char*&, char const*) noexcept override;
110  
    void copy(char*&, char const*) noexcept override;
111  
    void increment() noexcept;
111  
    void increment() noexcept;
112  
};
112  
};
113  

113  

114  
//------------------------------------------------
114  
//------------------------------------------------
115  
//
115  
//
116  
// param_iter
116  
// param_iter
117  
//
117  
//
118  
//------------------------------------------------
118  
//------------------------------------------------
119  

119  

120  
// A 1-param range allowing
120  
// A 1-param range allowing
121  
// self-intersection
121  
// self-intersection
122  
struct BOOST_SYMBOL_VISIBLE
122  
struct BOOST_SYMBOL_VISIBLE
123  
    single_param_iter
123  
    single_param_iter
124  
    : any_params_iter
124  
    : any_params_iter
125  
{
125  
{
126  
    explicit
126  
    explicit
127  
    single_param_iter(
127  
    single_param_iter(
128  
        param_view const&,
128  
        param_view const&,
129  
        bool space_as_plus) noexcept;
129  
        bool space_as_plus) noexcept;
130  

130  

131  
private:
131  
private:
132  
    bool has_value_;
132  
    bool has_value_;
133  
    bool at_end_ = false;
133  
    bool at_end_ = false;
134  
    bool space_as_plus_ = false;
134  
    bool space_as_plus_ = false;
135  

135  

136  
    void rewind() noexcept override;
136  
    void rewind() noexcept override;
137  
    bool measure(std::size_t&) noexcept override;
137  
    bool measure(std::size_t&) noexcept override;
138  
    void copy(char*&, char const*) noexcept override;
138  
    void copy(char*&, char const*) noexcept override;
139  
};
139  
};
140  

140  

141  
//------------------------------------------------
141  
//------------------------------------------------
142  
//
142  
//
143  
// params_iter_base
143  
// params_iter_base
144  
//
144  
//
145  
//------------------------------------------------
145  
//------------------------------------------------
146  

146  

147  
struct params_iter_base
147  
struct params_iter_base
148  
{
148  
{
149  
    bool space_as_plus_ = true;
149  
    bool space_as_plus_ = true;
150  
protected:
150  
protected:
151  
    explicit params_iter_base(
151  
    explicit params_iter_base(
152  
        bool space_as_plus) noexcept
152  
        bool space_as_plus) noexcept
153  
        : space_as_plus_(space_as_plus)
153  
        : space_as_plus_(space_as_plus)
154  
        {}
154  
        {}
155  

155  

156  
    // return encoded size
156  
    // return encoded size
157  
    BOOST_URL_DECL
157  
    BOOST_URL_DECL
158  
    void
158  
    void
159  
    measure_impl(
159  
    measure_impl(
160  
        std::size_t& n,
160  
        std::size_t& n,
161  
        param_view const& p) noexcept;
161  
        param_view const& p) noexcept;
162  

162  

163  
    // encode to dest
163  
    // encode to dest
164  
    BOOST_URL_DECL
164  
    BOOST_URL_DECL
165  
    void
165  
    void
166  
    copy_impl(
166  
    copy_impl(
167  
        char*& dest,
167  
        char*& dest,
168  
        char const* end,
168  
        char const* end,
169  
        param_view const& v) noexcept;
169  
        param_view const& v) noexcept;
170  
};
170  
};
171  

171  

172  
//------------------------------------------------
172  
//------------------------------------------------
173  

173  

174  
// A range of plain query params_ref
174  
// A range of plain query params_ref
175  
template<class FwdIt>
175  
template<class FwdIt>
176  
struct params_iter
176  
struct params_iter
177  
    : any_params_iter
177  
    : any_params_iter
178  
    , private params_iter_base
178  
    , private params_iter_base
179  
{
179  
{
180  
    BOOST_CORE_STATIC_ASSERT(
180  
    BOOST_CORE_STATIC_ASSERT(
181  
        std::is_convertible<
181  
        std::is_convertible<
182  
            typename std::iterator_traits<
182  
            typename std::iterator_traits<
183  
                FwdIt>::reference,
183  
                FwdIt>::reference,
184  
            param_view>::value);
184  
            param_view>::value);
185  

185  

186  
    params_iter(
186  
    params_iter(
187  
        FwdIt first,
187  
        FwdIt first,
188  
        FwdIt last,
188  
        FwdIt last,
189  
        bool space_as_plus) noexcept
189  
        bool space_as_plus) noexcept
190  
        : any_params_iter(
190  
        : any_params_iter(
191  
            first == last)
191  
            first == last)
192  
        , params_iter_base(space_as_plus)
192  
        , params_iter_base(space_as_plus)
193  
        , it0_(first)
193  
        , it0_(first)
194  
        , it_(first)
194  
        , it_(first)
195  
        , end_(last)
195  
        , end_(last)
196  
    {
196  
    {
197  
    }
197  
    }
198  

198  

199  
private:
199  
private:
200  
    FwdIt it0_;
200  
    FwdIt it0_;
201  
    FwdIt it_;
201  
    FwdIt it_;
202  
    FwdIt end_;
202  
    FwdIt end_;
203  

203  

204  
    void
204  
    void
205  
    rewind() noexcept override
205  
    rewind() noexcept override
206  
    {
206  
    {
207  
        it_ = it0_;
207  
        it_ = it0_;
208  
    }
208  
    }
209  

209  

210  
    bool
210  
    bool
211  
    measure(
211  
    measure(
212  
        std::size_t& n) noexcept override
212  
        std::size_t& n) noexcept override
213  
    {
213  
    {
214  
        if(it_ == end_)
214  
        if(it_ == end_)
215  
            return false;
215  
            return false;
216  
       measure_impl(n,
216  
       measure_impl(n,
217  
           param_view(*it_++));
217  
           param_view(*it_++));
218  
        return true;
218  
        return true;
219  
    }
219  
    }
220  

220  

221  
    void
221  
    void
222  
    copy(
222  
    copy(
223  
        char*& dest,
223  
        char*& dest,
224  
        char const* end) noexcept override
224  
        char const* end) noexcept override
225  
    {
225  
    {
226  
        copy_impl(dest, end,
226  
        copy_impl(dest, end,
227  
            param_view(*it_++));
227  
            param_view(*it_++));
228  
    }
228  
    }
229  
};
229  
};
230  

230  

231  
//------------------------------------------------
231  
//------------------------------------------------
232  
//
232  
//
233  
// param_encoded_iter
233  
// param_encoded_iter
234  
//
234  
//
235  
//------------------------------------------------
235  
//------------------------------------------------
236  

236  

237  
// A 1-param encoded range
237  
// A 1-param encoded range
238  
// allowing self-intersection
238  
// allowing self-intersection
239  
struct BOOST_SYMBOL_VISIBLE
239  
struct BOOST_SYMBOL_VISIBLE
240  
    param_encoded_iter
240  
    param_encoded_iter
241  
    : any_params_iter
241  
    : any_params_iter
242  
{
242  
{
243  
    explicit
243  
    explicit
244  
    param_encoded_iter(
244  
    param_encoded_iter(
245  
        param_pct_view const&) noexcept;
245  
        param_pct_view const&) noexcept;
246  

246  

247  
private:
247  
private:
248  
    bool has_value_;
248  
    bool has_value_;
249  
    bool at_end_ = false;
249  
    bool at_end_ = false;
250  

250  

251  
    void rewind() noexcept override;
251  
    void rewind() noexcept override;
252  
    bool measure(std::size_t&) noexcept override;
252  
    bool measure(std::size_t&) noexcept override;
253  
    void copy(char*&, char const*) noexcept override;
253  
    void copy(char*&, char const*) noexcept override;
254  
};
254  
};
255  

255  

256  
//------------------------------------------------
256  
//------------------------------------------------
257  
//
257  
//
258  
// params_encoded_iter
258  
// params_encoded_iter
259  
//
259  
//
260  
//------------------------------------------------
260  
//------------------------------------------------
261  

261  

262  
// Validating and copying from
262  
// Validating and copying from
263  
// a string of encoded params
263  
// a string of encoded params
264  
struct params_encoded_iter_base
264  
struct params_encoded_iter_base
265  
{
265  
{
266  
protected:
266  
protected:
267  
    BOOST_URL_DECL
267  
    BOOST_URL_DECL
268  
    static
268  
    static
269  
    void
269  
    void
270  
    measure_impl(
270  
    measure_impl(
271  
        std::size_t& n,
271  
        std::size_t& n,
272  
        param_view const& v) noexcept;
272  
        param_view const& v) noexcept;
273  

273  

274  
    BOOST_URL_DECL
274  
    BOOST_URL_DECL
275  
    static
275  
    static
276  
    void
276  
    void
277  
    copy_impl(
277  
    copy_impl(
278  
        char*& dest,
278  
        char*& dest,
279  
        char const* end,
279  
        char const* end,
280  
        param_view const& v) noexcept;
280  
        param_view const& v) noexcept;
281  
};
281  
};
282  

282  

283  
//------------------------------------------------
283  
//------------------------------------------------
284  

284  

285  
// A range of encoded query params_ref
285  
// A range of encoded query params_ref
286  
template<class FwdIt>
286  
template<class FwdIt>
287  
struct params_encoded_iter
287  
struct params_encoded_iter
288  
    : any_params_iter
288  
    : any_params_iter
289  
    , private params_encoded_iter_base
289  
    , private params_encoded_iter_base
290  
{
290  
{
291  
    BOOST_CORE_STATIC_ASSERT(
291  
    BOOST_CORE_STATIC_ASSERT(
292  
        std::is_convertible<
292  
        std::is_convertible<
293  
            typename std::iterator_traits<
293  
            typename std::iterator_traits<
294  
                FwdIt>::reference,
294  
                FwdIt>::reference,
295  
            param_view>::value);
295  
            param_view>::value);
296  

296  

297  
    params_encoded_iter(
297  
    params_encoded_iter(
298  
        FwdIt first,
298  
        FwdIt first,
299  
        FwdIt last) noexcept
299  
        FwdIt last) noexcept
300  
        : any_params_iter(
300  
        : any_params_iter(
301  
            first == last)
301  
            first == last)
302  
        , it0_(first)
302  
        , it0_(first)
303  
        , it_(first)
303  
        , it_(first)
304  
        , end_(last)
304  
        , end_(last)
305  
    {
305  
    {
306  
    }
306  
    }
307  

307  

308  
private:
308  
private:
309  
    FwdIt it0_;
309  
    FwdIt it0_;
310  
    FwdIt it_;
310  
    FwdIt it_;
311  
    FwdIt end_;
311  
    FwdIt end_;
312  

312  

313  
    void
313  
    void
314  
    rewind() noexcept override
314  
    rewind() noexcept override
315  
    {
315  
    {
316  
        it_ = it0_;
316  
        it_ = it0_;
317  
    }
317  
    }
318  

318  

319  
    bool
319  
    bool
320  
    measure(
320  
    measure(
321  
        std::size_t& n) override
321  
        std::size_t& n) override
322  
    {
322  
    {
323  
        if(it_ == end_)
323  
        if(it_ == end_)
324  
            return false;
324  
            return false;
325  
        // throw on invalid input
325  
        // throw on invalid input
326  
        measure_impl(n,
326  
        measure_impl(n,
327  
            param_pct_view(
327  
            param_pct_view(
328  
                param_view(*it_++)));
328  
                param_view(*it_++)));
329  
        return true;
329  
        return true;
330  
    }
330  
    }
331  

331  

332  
    void
332  
    void
333  
    copy(
333  
    copy(
334  
        char*& dest,
334  
        char*& dest,
335  
        char const* end
335  
        char const* end
336  
            ) noexcept override
336  
            ) noexcept override
337  
    {
337  
    {
338  
        copy_impl(dest, end,
338  
        copy_impl(dest, end,
339  
            param_view(*it_++));
339  
            param_view(*it_++));
340  
    }
340  
    }
341  
};
341  
};
342  

342  

343  
//------------------------------------------------
343  
//------------------------------------------------
344  
//
344  
//
345  
// param_value_iter
345  
// param_value_iter
346  
//
346  
//
347  
//------------------------------------------------
347  
//------------------------------------------------
348  

348  

349  
// An iterator which outputs
349  
// An iterator which outputs
350  
// one value on an existing key
350  
// one value on an existing key
351  
struct param_value_iter
351  
struct param_value_iter
352  
    : any_params_iter
352  
    : any_params_iter
353  
{
353  
{
354  
    param_value_iter(
354  
    param_value_iter(
355  
        std::size_t nk,
355  
        std::size_t nk,
356  
        core::string_view const& value,
356  
        core::string_view const& value,
357  
        bool has_value) noexcept
357  
        bool has_value) noexcept
358  
        : any_params_iter(
358  
        : any_params_iter(
359  
            false,
359  
            false,
360  
            value)
360  
            value)
361  
        , nk_(nk)
361  
        , nk_(nk)
362  
        , has_value_(has_value)
362  
        , has_value_(has_value)
363  
    {
363  
    {
364  
    }
364  
    }
365  

365  

366  
private:
366  
private:
367  
    std::size_t nk_ = 0;
367  
    std::size_t nk_ = 0;
368  
    bool has_value_ = false;
368  
    bool has_value_ = false;
369  
    bool at_end_ = false;
369  
    bool at_end_ = false;
370  

370  

371  
    void rewind() noexcept override;
371  
    void rewind() noexcept override;
372  
    bool measure(std::size_t&) noexcept override;
372  
    bool measure(std::size_t&) noexcept override;
373  
    void copy(char*&, char const*) noexcept override;
373  
    void copy(char*&, char const*) noexcept override;
374  
};
374  
};
375  

375  

376  
//------------------------------------------------
376  
//------------------------------------------------
377  
//
377  
//
378  
// param_encoded_value_iter
378  
// param_encoded_value_iter
379  
//
379  
//
380  
//------------------------------------------------
380  
//------------------------------------------------
381  

381  

382  
// An iterator which outputs one
382  
// An iterator which outputs one
383  
// encoded value on an existing key
383  
// encoded value on an existing key
384  
struct param_encoded_value_iter
384  
struct param_encoded_value_iter
385  
    : any_params_iter
385  
    : any_params_iter
386  
{
386  
{
387  
    param_encoded_value_iter(
387  
    param_encoded_value_iter(
388  
        std::size_t nk,
388  
        std::size_t nk,
389  
        pct_string_view const& value,
389  
        pct_string_view const& value,
390  
        bool has_value) noexcept
390  
        bool has_value) noexcept
391  
        : any_params_iter(
391  
        : any_params_iter(
392  
            false,
392  
            false,
393  
            value)
393  
            value)
394  
        , nk_(nk)
394  
        , nk_(nk)
395  
        , has_value_(has_value)
395  
        , has_value_(has_value)
396  
    {
396  
    {
397  
    }
397  
    }
398  

398  

399  
private:
399  
private:
400  
    std::size_t nk_ = 0;
400  
    std::size_t nk_ = 0;
401  
    bool has_value_ = false;
401  
    bool has_value_ = false;
402  
    bool at_end_ = false;
402  
    bool at_end_ = false;
403  

403  

404  
    void rewind() noexcept override;
404  
    void rewind() noexcept override;
405  
    bool measure(std::size_t&) noexcept override;
405  
    bool measure(std::size_t&) noexcept override;
406  
    void copy(char*&, char const*) noexcept override;
406  
    void copy(char*&, char const*) noexcept override;
407  
};
407  
};
408  

408  

409  
//------------------------------------------------
409  
//------------------------------------------------
410  

410  

411  
template<class FwdIt>
411  
template<class FwdIt>
412  
params_iter<FwdIt>
412  
params_iter<FwdIt>
413  
make_params_iter(
413  
make_params_iter(
414  
    FwdIt first, FwdIt last, bool space_as_plus)
414  
    FwdIt first, FwdIt last, bool space_as_plus)
415  
{
415  
{
416  
    return params_iter<
416  
    return params_iter<
417  
        FwdIt>(first, last, space_as_plus);
417  
        FwdIt>(first, last, space_as_plus);
418  
}
418  
}
419  

419  

420  
template<class FwdIt>
420  
template<class FwdIt>
421  
params_encoded_iter<FwdIt>
421  
params_encoded_iter<FwdIt>
422  
make_params_encoded_iter(
422  
make_params_encoded_iter(
423  
    FwdIt first, FwdIt last)
423  
    FwdIt first, FwdIt last)
424  
{
424  
{
425  
    return params_encoded_iter<
425  
    return params_encoded_iter<
426  
        FwdIt>(first, last);
426  
        FwdIt>(first, last);
427  
}
427  
}
428  

428  

429  
} // detail
429  
} // detail
430  
} // urls
430  
} // urls
431  
} // boost
431  
} // boost
432  

432  

433  
#endif
433  
#endif