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 -
    BOOST_URL_DECL
 
96  
    // ne = never empty
95  
    // ne = never empty
97  
    explicit
96  
    explicit
98  
    query_string_iter(
97  
    query_string_iter(
99  
        core::string_view s,
98  
        core::string_view s,
100  
        bool ne = false) noexcept;
99  
        bool ne = false) noexcept;
101  

100  

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

106  

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

112  

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

118  

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

129  

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

134  

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

139  

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

145  

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

154  

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

161  

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

170  

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

172  

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

184  

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

197  

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

202  

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

208  

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

219  

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

229  

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

235  

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

245  

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

249  

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

254  

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

260  

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

272  

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

281  

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

283  

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

295  

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

306  

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

311  

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

317  

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

330  

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

341  

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

347  

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

364  

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

369  

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

374  

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

380  

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

397  

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

402  

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

407  

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

409  

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

418  

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

427  

429  
} // detail
428  
} // detail
430  
} // urls
429  
} // urls
431  
} // boost
430  
} // boost
 
431 +

 
432 +
#include <boost/url/detail/impl/any_params_iter.hpp>
432  

433  

433  
#endif
434  
#endif