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  
    virtual
57  
    virtual
58  
    ~any_params_iter() noexcept = 0;
58  
    ~any_params_iter() noexcept = 0;
59  

59  

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

64  

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

72  

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

82  

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

88  

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

99  

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

105  

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

111  

112  
//------------------------------------------------
112  
//------------------------------------------------
113  
//
113  
//
114  
// param_iter
114  
// param_iter
115  
//
115  
//
116  
//------------------------------------------------
116  
//------------------------------------------------
117  

117  

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

128  

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

133  

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

138  

139  
//------------------------------------------------
139  
//------------------------------------------------
140  
//
140  
//
141  
// params_iter_base
141  
// params_iter_base
142  
//
142  
//
143  
//------------------------------------------------
143  
//------------------------------------------------
144  

144  

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

153  

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

159  

160  
    // encode to dest
160  
    // encode to dest
161  
    void
161  
    void
162  
    copy_impl(
162  
    copy_impl(
163  
        char*& dest,
163  
        char*& dest,
164  
        char const* end,
164  
        char const* end,
165  
        param_view const& v) noexcept;
165  
        param_view const& v) noexcept;
166  
};
166  
};
167  

167  

168  
//------------------------------------------------
168  
//------------------------------------------------
169  

169  

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

181  

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

194  

195  
private:
195  
private:
196  
    FwdIt it0_;
196  
    FwdIt it0_;
197  
    FwdIt it_;
197  
    FwdIt it_;
198  
    FwdIt end_;
198  
    FwdIt end_;
199  

199  

200  
    void
200  
    void
201  
    rewind() noexcept override
201  
    rewind() noexcept override
202  
    {
202  
    {
203  
        it_ = it0_;
203  
        it_ = it0_;
204  
    }
204  
    }
205  

205  

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

216  

217  
    void
217  
    void
218  
    copy(
218  
    copy(
219  
        char*& dest,
219  
        char*& dest,
220  
        char const* end) noexcept override
220  
        char const* end) noexcept override
221  
    {
221  
    {
222  
        copy_impl(dest, end,
222  
        copy_impl(dest, end,
223  
            param_view(*it_++));
223  
            param_view(*it_++));
224  
    }
224  
    }
225  
};
225  
};
226  

226  

227  
//------------------------------------------------
227  
//------------------------------------------------
228  
//
228  
//
229  
// param_encoded_iter
229  
// param_encoded_iter
230  
//
230  
//
231  
//------------------------------------------------
231  
//------------------------------------------------
232  

232  

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

242  

243  
private:
243  
private:
244  
    bool has_value_;
244  
    bool has_value_;
245  
    bool at_end_ = false;
245  
    bool at_end_ = false;
246  

246  

247  
    void rewind() noexcept override;
247  
    void rewind() noexcept override;
248  
    bool measure(std::size_t&) noexcept override;
248  
    bool measure(std::size_t&) noexcept override;
249  
    void copy(char*&, char const*) noexcept override;
249  
    void copy(char*&, char const*) noexcept override;
250  
};
250  
};
251  

251  

252  
//------------------------------------------------
252  
//------------------------------------------------
253  
//
253  
//
254  
// params_encoded_iter
254  
// params_encoded_iter
255  
//
255  
//
256  
//------------------------------------------------
256  
//------------------------------------------------
257  

257  

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

268  

269  
    static
269  
    static
270  
    void
270  
    void
271  
    copy_impl(
271  
    copy_impl(
272  
        char*& dest,
272  
        char*& dest,
273  
        char const* end,
273  
        char const* end,
274  
        param_view const& v) noexcept;
274  
        param_view const& v) noexcept;
275  
};
275  
};
276  

276  

277  
//------------------------------------------------
277  
//------------------------------------------------
278  

278  

279  
// A range of encoded query params_ref
279  
// A range of encoded query params_ref
280  
template<class FwdIt>
280  
template<class FwdIt>
281  
struct params_encoded_iter
281  
struct params_encoded_iter
282  
    : any_params_iter
282  
    : any_params_iter
283  
    , private params_encoded_iter_base
283  
    , private params_encoded_iter_base
284  
{
284  
{
285  
    BOOST_CORE_STATIC_ASSERT(
285  
    BOOST_CORE_STATIC_ASSERT(
286  
        std::is_convertible<
286  
        std::is_convertible<
287  
            typename std::iterator_traits<
287  
            typename std::iterator_traits<
288  
                FwdIt>::reference,
288  
                FwdIt>::reference,
289  
            param_view>::value);
289  
            param_view>::value);
290  

290  

291  
    params_encoded_iter(
291  
    params_encoded_iter(
292  
        FwdIt first,
292  
        FwdIt first,
293  
        FwdIt last) noexcept
293  
        FwdIt last) noexcept
294  
        : any_params_iter(
294  
        : any_params_iter(
295  
            first == last)
295  
            first == last)
296  
        , it0_(first)
296  
        , it0_(first)
297  
        , it_(first)
297  
        , it_(first)
298  
        , end_(last)
298  
        , end_(last)
299  
    {
299  
    {
300  
    }
300  
    }
301  

301  

302  
private:
302  
private:
303  
    FwdIt it0_;
303  
    FwdIt it0_;
304  
    FwdIt it_;
304  
    FwdIt it_;
305  
    FwdIt end_;
305  
    FwdIt end_;
306  

306  

307  
    void
307  
    void
308  
    rewind() noexcept override
308  
    rewind() noexcept override
309  
    {
309  
    {
310  
        it_ = it0_;
310  
        it_ = it0_;
311  
    }
311  
    }
312  

312  

313  
    bool
313  
    bool
314  
    measure(
314  
    measure(
315  
        std::size_t& n) override
315  
        std::size_t& n) override
316  
    {
316  
    {
317  
        if(it_ == end_)
317  
        if(it_ == end_)
318  
            return false;
318  
            return false;
319  
        // throw on invalid input
319  
        // throw on invalid input
320  
        measure_impl(n,
320  
        measure_impl(n,
321  
            param_pct_view(
321  
            param_pct_view(
322  
                param_view(*it_++)));
322  
                param_view(*it_++)));
323  
        return true;
323  
        return true;
324  
    }
324  
    }
325  

325  

326  
    void
326  
    void
327  
    copy(
327  
    copy(
328  
        char*& dest,
328  
        char*& dest,
329  
        char const* end
329  
        char const* end
330  
            ) noexcept override
330  
            ) noexcept override
331  
    {
331  
    {
332  
        copy_impl(dest, end,
332  
        copy_impl(dest, end,
333  
            param_view(*it_++));
333  
            param_view(*it_++));
334  
    }
334  
    }
335  
};
335  
};
336  

336  

337  
//------------------------------------------------
337  
//------------------------------------------------
338  
//
338  
//
339  
// param_value_iter
339  
// param_value_iter
340  
//
340  
//
341  
//------------------------------------------------
341  
//------------------------------------------------
342  

342  

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

359  

360  
private:
360  
private:
361  
    std::size_t nk_ = 0;
361  
    std::size_t nk_ = 0;
362  
    bool has_value_ = false;
362  
    bool has_value_ = false;
363  
    bool at_end_ = false;
363  
    bool at_end_ = false;
364  

364  

365  
    void rewind() noexcept override;
365  
    void rewind() noexcept override;
366  
    bool measure(std::size_t&) noexcept override;
366  
    bool measure(std::size_t&) noexcept override;
367  
    void copy(char*&, char const*) noexcept override;
367  
    void copy(char*&, char const*) noexcept override;
368  
};
368  
};
369  

369  

370  
//------------------------------------------------
370  
//------------------------------------------------
371  
//
371  
//
372  
// param_encoded_value_iter
372  
// param_encoded_value_iter
373  
//
373  
//
374  
//------------------------------------------------
374  
//------------------------------------------------
375  

375  

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

392  

393  
private:
393  
private:
394  
    std::size_t nk_ = 0;
394  
    std::size_t nk_ = 0;
395  
    bool has_value_ = false;
395  
    bool has_value_ = false;
396  
    bool at_end_ = false;
396  
    bool at_end_ = false;
397  

397  

398  
    void rewind() noexcept override;
398  
    void rewind() noexcept override;
399  
    bool measure(std::size_t&) noexcept override;
399  
    bool measure(std::size_t&) noexcept override;
400  
    void copy(char*&, char const*) noexcept override;
400  
    void copy(char*&, char const*) noexcept override;
401  
};
401  
};
402  

402  

403  
//------------------------------------------------
403  
//------------------------------------------------
404  

404  

405  
template<class FwdIt>
405  
template<class FwdIt>
406  
params_iter<FwdIt>
406  
params_iter<FwdIt>
407  
make_params_iter(
407  
make_params_iter(
408  
    FwdIt first, FwdIt last, bool space_as_plus)
408  
    FwdIt first, FwdIt last, bool space_as_plus)
409  
{
409  
{
410  
    return params_iter<
410  
    return params_iter<
411  
        FwdIt>(first, last, space_as_plus);
411  
        FwdIt>(first, last, space_as_plus);
412  
}
412  
}
413  

413  

414  
template<class FwdIt>
414  
template<class FwdIt>
415  
params_encoded_iter<FwdIt>
415  
params_encoded_iter<FwdIt>
416  
make_params_encoded_iter(
416  
make_params_encoded_iter(
417  
    FwdIt first, FwdIt last)
417  
    FwdIt first, FwdIt last)
418  
{
418  
{
419  
    return params_encoded_iter<
419  
    return params_encoded_iter<
420  
        FwdIt>(first, last);
420  
        FwdIt>(first, last);
421  
}
421  
}
422  

422  

423  
} // detail
423  
} // detail
424  
} // urls
424  
} // urls
425  
} // boost
425  
} // boost
426  

426  

427  
#include <boost/url/detail/impl/any_params_iter.hpp>
427  
#include <boost/url/detail/impl/any_params_iter.hpp>
428  

428  

429  
#endif
429  
#endif