1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
3  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4  
//
4  
//
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  
//
7  
//
8  
// Official repository: https://github.com/boostorg/url
8  
// Official repository: https://github.com/boostorg/url
9  
//
9  
//
10  

10  

11  
#ifndef BOOST_URL_IMPL_PARAMS_ENCODED_BASE_HPP
11  
#ifndef BOOST_URL_IMPL_PARAMS_ENCODED_BASE_HPP
12  
#define BOOST_URL_IMPL_PARAMS_ENCODED_BASE_HPP
12  
#define BOOST_URL_IMPL_PARAMS_ENCODED_BASE_HPP
13  

13  

14  
#include <boost/url/detail/params_iter_impl.hpp>
14  
#include <boost/url/detail/params_iter_impl.hpp>
15  
#include <boost/url/grammar/ci_string.hpp>
15  
#include <boost/url/grammar/ci_string.hpp>
16  
#include <ostream>
16  
#include <ostream>
17  

17  

18  
namespace boost {
18  
namespace boost {
19  
namespace urls {
19  
namespace urls {
20  

20  

21  
#ifndef BOOST_URL_DOCS
21  
#ifndef BOOST_URL_DOCS
22  
class params_ref;
22  
class params_ref;
23  
#endif
23  
#endif
24  

24  

25  
//------------------------------------------------
25  
//------------------------------------------------
26  

26  

27  
class params_encoded_base::iterator
27  
class params_encoded_base::iterator
28  
{
28  
{
29  
    detail::params_iter_impl it_;
29  
    detail::params_iter_impl it_;
30  

30  

31  
    friend class params_encoded_base;
31  
    friend class params_encoded_base;
32  
    friend class params_encoded_ref;
32  
    friend class params_encoded_ref;
33  

33  

34  
    iterator(detail::query_ref const& ref) noexcept;
34  
    iterator(detail::query_ref const& ref) noexcept;
35  
    iterator(detail::query_ref const& ref, int) noexcept;
35  
    iterator(detail::query_ref const& ref, int) noexcept;
36  
    iterator(
36  
    iterator(
37  
        detail::params_iter_impl const& it)
37  
        detail::params_iter_impl const& it)
38  
        : it_(it)
38  
        : it_(it)
39  
    {
39  
    {
40  
    }
40  
    }
41  

41  

42  
public:
42  
public:
43  
    using value_type =
43  
    using value_type =
44  
        params_encoded_base::value_type;
44  
        params_encoded_base::value_type;
45  
    using reference =
45  
    using reference =
46  
        params_encoded_base::reference;
46  
        params_encoded_base::reference;
47  
    using pointer = reference;
47  
    using pointer = reference;
48  
    using difference_type = std::ptrdiff_t;
48  
    using difference_type = std::ptrdiff_t;
49  
    using iterator_category =
49  
    using iterator_category =
50  
        std::bidirectional_iterator_tag;
50  
        std::bidirectional_iterator_tag;
51  

51  

52  
    iterator() = default;
52  
    iterator() = default;
53  
    iterator(iterator const&) = default;
53  
    iterator(iterator const&) = default;
54  
    iterator& operator=(
54  
    iterator& operator=(
55  
        iterator const&) = default;
55  
        iterator const&) = default;
56  

56  

57  
    iterator&
57  
    iterator&
58  
    operator++() noexcept
58  
    operator++() noexcept
59  
    {
59  
    {
60  
        it_.increment();
60  
        it_.increment();
61  
        return *this;
61  
        return *this;
62  
    }
62  
    }
63  

63  

64  
    iterator
64  
    iterator
65  
    operator++(int) noexcept
65  
    operator++(int) noexcept
66  
    {
66  
    {
67  
        auto tmp = *this;
67  
        auto tmp = *this;
68  
        ++*this;
68  
        ++*this;
69  
        return tmp;
69  
        return tmp;
70  
    }
70  
    }
71  

71  

72  
    iterator&
72  
    iterator&
73  
    operator--() noexcept
73  
    operator--() noexcept
74  
    {
74  
    {
75  
        it_.decrement();
75  
        it_.decrement();
76  
        return *this;
76  
        return *this;
77  
    }
77  
    }
78  

78  

79  
    iterator
79  
    iterator
80  
    operator--(int) noexcept
80  
    operator--(int) noexcept
81  
    {
81  
    {
82  
        auto tmp = *this;
82  
        auto tmp = *this;
83  
        --*this;
83  
        --*this;
84  
        return tmp;
84  
        return tmp;
85  
    }
85  
    }
86  

86  

87  
    reference
87  
    reference
88  
    operator*() const
88  
    operator*() const
89  
    {
89  
    {
90  
        return it_.dereference();
90  
        return it_.dereference();
91  
    }
91  
    }
92  

92  

93  
    pointer
93  
    pointer
94  
    operator->() const
94  
    operator->() const
95  
    {
95  
    {
96  
        return it_.dereference();
96  
        return it_.dereference();
97  
    }
97  
    }
98  

98  

99  
    friend
99  
    friend
100  
    bool
100  
    bool
101  
    operator==(
101  
    operator==(
102  
        iterator const& it0,
102  
        iterator const& it0,
103  
        iterator const& it1) noexcept
103  
        iterator const& it1) noexcept
104  
    {
104  
    {
105  
        return it0.it_.equal(it1.it_);
105  
        return it0.it_.equal(it1.it_);
106  
    }
106  
    }
107  

107  

108  
    friend
108  
    friend
109  
    bool
109  
    bool
110  
    operator!=(
110  
    operator!=(
111  
        iterator const& it0,
111  
        iterator const& it0,
112  
        iterator const& it1) noexcept
112  
        iterator const& it1) noexcept
113  
    {
113  
    {
114  
        return ! it0.it_.equal(it1.it_);
114  
        return ! it0.it_.equal(it1.it_);
115  
    }
115  
    }
116  
};
116  
};
117  

117  

118  
//------------------------------------------------
118  
//------------------------------------------------
119  
//
119  
//
120  
// Observers
120  
// Observers
121  
//
121  
//
122  
//------------------------------------------------
122  
//------------------------------------------------
123  

123  

124  
inline
124  
inline
125  
bool
125  
bool
126  
params_encoded_base::
126  
params_encoded_base::
127  
contains(
127  
contains(
128  
    pct_string_view key,
128  
    pct_string_view key,
129  
    ignore_case_param ic) const noexcept
129  
    ignore_case_param ic) const noexcept
130  
{
130  
{
131  
    return find_impl(
131  
    return find_impl(
132  
        begin().it_, key, ic) != end();
132  
        begin().it_, key, ic) != end();
133  
}
133  
}
134  

134  

135  
inline
135  
inline
136  
pct_string_view
136  
pct_string_view
137  
params_encoded_base::
137  
params_encoded_base::
138  
get_or(
138  
get_or(
139  
    pct_string_view key,
139  
    pct_string_view key,
140  
    pct_string_view value,
140  
    pct_string_view value,
141  
    ignore_case_param ic) const noexcept
141  
    ignore_case_param ic) const noexcept
142  
{
142  
{
143  
    auto it = find_impl(
143  
    auto it = find_impl(
144  
        begin().it_, key, ic);
144  
        begin().it_, key, ic);
145  
    detail::params_iter_impl end_(ref_, 0);
145  
    detail::params_iter_impl end_(ref_, 0);
146  
    if(it.equal(end_))
146  
    if(it.equal(end_))
147  
        return value;
147  
        return value;
148  

148  

149  
    param_pct_view const p = it.dereference();
149  
    param_pct_view const p = it.dereference();
150  
    if(! p.has_value)
150  
    if(! p.has_value)
151  
        return pct_string_view();
151  
        return pct_string_view();
152  

152  

153  
    return p.value;
153  
    return p.value;
154  
}
154  
}
155  

155  

156  
inline
156  
inline
157  
auto
157  
auto
158  
params_encoded_base::
158  
params_encoded_base::
159  
find(
159  
find(
160  
    pct_string_view key,
160  
    pct_string_view key,
161  
    ignore_case_param ic) const noexcept ->
161  
    ignore_case_param ic) const noexcept ->
162  
        iterator
162  
        iterator
163  
{
163  
{
164  
    return find_impl(
164  
    return find_impl(
165  
        begin().it_, key, ic);
165  
        begin().it_, key, ic);
166  
}
166  
}
167  

167  

168  
inline
168  
inline
169  
auto
169  
auto
170  
params_encoded_base::
170  
params_encoded_base::
171  
find(
171  
find(
172  
    iterator it,
172  
    iterator it,
173  
    pct_string_view key,
173  
    pct_string_view key,
174  
    ignore_case_param ic) const noexcept ->
174  
    ignore_case_param ic) const noexcept ->
175  
        iterator
175  
        iterator
176  
{
176  
{
177  
    return find_impl(
177  
    return find_impl(
178  
        it.it_, key, ic);
178  
        it.it_, key, ic);
179  
}
179  
}
180  

180  

181  
inline
181  
inline
182  
auto
182  
auto
183  
params_encoded_base::
183  
params_encoded_base::
184  
find_last(
184  
find_last(
185  
    pct_string_view key,
185  
    pct_string_view key,
186  
    ignore_case_param ic) const noexcept ->
186  
    ignore_case_param ic) const noexcept ->
187  
        iterator
187  
        iterator
188  
{
188  
{
189  
    return find_last_impl(
189  
    return find_last_impl(
190  
        end().it_, key, ic);
190  
        end().it_, key, ic);
191  
}
191  
}
192  

192  

193  
inline
193  
inline
194  
auto
194  
auto
195  
params_encoded_base::
195  
params_encoded_base::
196  
find_last(
196  
find_last(
197  
    iterator it,
197  
    iterator it,
198  
    pct_string_view key,
198  
    pct_string_view key,
199  
    ignore_case_param ic) const noexcept ->
199  
    ignore_case_param ic) const noexcept ->
200  
        iterator
200  
        iterator
201  
{
201  
{
202  
    return find_last_impl(
202  
    return find_last_impl(
203  
        it.it_, key, ic);
203  
        it.it_, key, ic);
204  
}
204  
}
205  

205  

206  
//------------------------------------------------
206  
//------------------------------------------------
207  

207  

208  
inline
208  
inline
209  
params_encoded_base::
209  
params_encoded_base::
210  
iterator::
210  
iterator::
211  
iterator(
211  
iterator(
212  
    detail::query_ref const& ref) noexcept
212  
    detail::query_ref const& ref) noexcept
213  
    : it_(ref)
213  
    : it_(ref)
214  
{
214  
{
215  
}
215  
}
216  

216  

217  
inline
217  
inline
218  
params_encoded_base::
218  
params_encoded_base::
219  
iterator::
219  
iterator::
220  
iterator(
220  
iterator(
221  
    detail::query_ref const& ref, int) noexcept
221  
    detail::query_ref const& ref, int) noexcept
222  
    : it_(ref, 0)
222  
    : it_(ref, 0)
223  
{
223  
{
224  
}
224  
}
225  

225  

226  
//------------------------------------------------
226  
//------------------------------------------------
227  
//
227  
//
228  
// params_encoded_base
228  
// params_encoded_base
229  
//
229  
//
230  
//------------------------------------------------
230  
//------------------------------------------------
231  

231  

232  
inline
232  
inline
233  
params_encoded_base::
233  
params_encoded_base::
234  
params_encoded_base(
234  
params_encoded_base(
235  
    detail::query_ref const& ref) noexcept
235  
    detail::query_ref const& ref) noexcept
236  
    : ref_(ref)
236  
    : ref_(ref)
237  
{
237  
{
238  
}
238  
}
239  

239  

240  
//------------------------------------------------
240  
//------------------------------------------------
241  
//
241  
//
242  
// Observers
242  
// Observers
243  
//
243  
//
244  
//------------------------------------------------
244  
//------------------------------------------------
245  

245  

246  
inline
246  
inline
247  
pct_string_view
247  
pct_string_view
248  
params_encoded_base::
248  
params_encoded_base::
249  
buffer() const noexcept
249  
buffer() const noexcept
250  
{
250  
{
251  
    return ref_.buffer();
251  
    return ref_.buffer();
252  
}
252  
}
253  

253  

254  
inline
254  
inline
255  
bool
255  
bool
256  
params_encoded_base::
256  
params_encoded_base::
257  
empty() const noexcept
257  
empty() const noexcept
258  
{
258  
{
259  
    return ref_.nparam() == 0;
259  
    return ref_.nparam() == 0;
260  
}
260  
}
261  

261  

262  
inline
262  
inline
263  
std::size_t
263  
std::size_t
264  
params_encoded_base::
264  
params_encoded_base::
265  
size() const noexcept
265  
size() const noexcept
266  
{
266  
{
267  
    return ref_.nparam();
267  
    return ref_.nparam();
268  
}
268  
}
269  

269  

270  
inline
270  
inline
271  
auto
271  
auto
272  
params_encoded_base::
272  
params_encoded_base::
273  
begin() const noexcept ->
273  
begin() const noexcept ->
274  
    iterator
274  
    iterator
275  
{
275  
{
276  
    return { ref_ };
276  
    return { ref_ };
277  
}
277  
}
278  

278  

279  
inline
279  
inline
280  
auto
280  
auto
281  
params_encoded_base::
281  
params_encoded_base::
282  
end() const noexcept ->
282  
end() const noexcept ->
283  
    iterator
283  
    iterator
284  
{
284  
{
285  
    return { ref_, 0 };
285  
    return { ref_, 0 };
286  
}
286  
}
287  

287  

288  
//------------------------------------------------
288  
//------------------------------------------------
289  

289  

290  
inline
290  
inline
291  
std::size_t
291  
std::size_t
292  
params_encoded_base::
292  
params_encoded_base::
293  
count(
293  
count(
294  
    pct_string_view key,
294  
    pct_string_view key,
295  
    ignore_case_param ic) const noexcept
295  
    ignore_case_param ic) const noexcept
296  
{
296  
{
297  
    std::size_t n = 0;
297  
    std::size_t n = 0;
298  
    auto it = find(key, ic);
298  
    auto it = find(key, ic);
299  
    auto const end_ = end();
299  
    auto const end_ = end();
300  
    while(it != end_)
300  
    while(it != end_)
301  
    {
301  
    {
302  
        ++n;
302  
        ++n;
303  
        ++it;
303  
        ++it;
304  
        it = find(it, key, ic);
304  
        it = find(it, key, ic);
305  
    }
305  
    }
306  
    return n;
306  
    return n;
307  
}
307  
}
308  

308  

309  
//------------------------------------------------
309  
//------------------------------------------------
310  
//
310  
//
311  
// (implementation)
311  
// (implementation)
312  
//
312  
//
313  
//------------------------------------------------
313  
//------------------------------------------------
314  

314  

315  
inline
315  
inline
316  
detail::params_iter_impl
316  
detail::params_iter_impl
317  
params_encoded_base::
317  
params_encoded_base::
318  
find_impl(
318  
find_impl(
319  
    detail::params_iter_impl it,
319  
    detail::params_iter_impl it,
320  
    pct_string_view key,
320  
    pct_string_view key,
321  
    ignore_case_param ic) const noexcept
321  
    ignore_case_param ic) const noexcept
322  
{
322  
{
323  
    detail::params_iter_impl end_(ref_, 0);
323  
    detail::params_iter_impl end_(ref_, 0);
324  
    if(! ic)
324  
    if(! ic)
325  
    {
325  
    {
326  
        for(;;)
326  
        for(;;)
327  
        {
327  
        {
328  
            if(it.equal(end_))
328  
            if(it.equal(end_))
329  
                return it;
329  
                return it;
330  
            if(*it.key() == *key)
330  
            if(*it.key() == *key)
331  
                return it;
331  
                return it;
332  
            it.increment();
332  
            it.increment();
333  
        }
333  
        }
334  
    }
334  
    }
335  
    for(;;)
335  
    for(;;)
336  
    {
336  
    {
337  
        if(it.equal(end_))
337  
        if(it.equal(end_))
338  
            return it;
338  
            return it;
339  
        if( grammar::ci_is_equal(
339  
        if( grammar::ci_is_equal(
340  
                *it.key(), *key))
340  
                *it.key(), *key))
341  
            return it;
341  
            return it;
342  
        it.increment();
342  
        it.increment();
343  
    }
343  
    }
344  
}
344  
}
345  

345  

346  
inline
346  
inline
347  
detail::params_iter_impl
347  
detail::params_iter_impl
348  
params_encoded_base::
348  
params_encoded_base::
349  
find_last_impl(
349  
find_last_impl(
350  
    detail::params_iter_impl it,
350  
    detail::params_iter_impl it,
351  
    pct_string_view key,
351  
    pct_string_view key,
352  
    ignore_case_param ic) const noexcept
352  
    ignore_case_param ic) const noexcept
353  
{
353  
{
354  
    detail::params_iter_impl begin_(ref_);
354  
    detail::params_iter_impl begin_(ref_);
355  
    if(! ic)
355  
    if(! ic)
356  
    {
356  
    {
357  
        for(;;)
357  
        for(;;)
358  
        {
358  
        {
359  
            if(it.equal(begin_))
359  
            if(it.equal(begin_))
360  
                return { ref_, 0 };
360  
                return { ref_, 0 };
361  
            it.decrement();
361  
            it.decrement();
362  
            if(*it.key() == *key)
362  
            if(*it.key() == *key)
363  
                return it;
363  
                return it;
364  
        }
364  
        }
365  
    }
365  
    }
366  
    for(;;)
366  
    for(;;)
367  
    {
367  
    {
368  
        if(it.equal(begin_))
368  
        if(it.equal(begin_))
369  
            return { ref_, 0 };
369  
            return { ref_, 0 };
370  
        it.decrement();
370  
        it.decrement();
371  
        if(grammar::ci_is_equal(
371  
        if(grammar::ci_is_equal(
372  
                *it.key(), *key))
372  
                *it.key(), *key))
373  
            return it;
373  
            return it;
374  
    }
374  
    }
375  
}
375  
}
376  

376  

377  
//------------------------------------------------
377  
//------------------------------------------------
378  

378  

379  
inline
379  
inline
380  
std::ostream&
380  
std::ostream&
381  
operator<<(
381  
operator<<(
382  
    std::ostream& os,
382  
    std::ostream& os,
383  
    params_encoded_base const& qp)
383  
    params_encoded_base const& qp)
384  
{
384  
{
385  
    os << qp.buffer();
385  
    os << qp.buffer();
386  
    return os;
386  
    return os;
387  
}
387  
}
388  

388  

389  
} // urls
389  
} // urls
390  
} // boost
390  
} // boost
391  

391  

392  
#endif
392  
#endif