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  

11  

12  
#include <boost/url/detail/config.hpp>
12  
#include <boost/url/detail/config.hpp>
13  
#include <boost/url/decode_view.hpp>
13  
#include <boost/url/decode_view.hpp>
14  
#include <boost/url/params_ref.hpp>
14  
#include <boost/url/params_ref.hpp>
15  
#include <boost/url/params_view.hpp>
15  
#include <boost/url/params_view.hpp>
16  
#include <boost/url/url_base.hpp>
16  
#include <boost/url/url_base.hpp>
17  
#include <boost/url/grammar/ci_string.hpp>
17  
#include <boost/url/grammar/ci_string.hpp>
18  
#include <boost/assert.hpp>
18  
#include <boost/assert.hpp>
19  
#include <utility>
19  
#include <utility>
20  

20  

21  
namespace boost {
21  
namespace boost {
22  
namespace urls {
22  
namespace urls {
23  

23  

24  
//------------------------------------------------
24  
//------------------------------------------------
25  
//
25  
//
26  
// Special Members
26  
// Special Members
27  
//
27  
//
28  
//------------------------------------------------
28  
//------------------------------------------------
29  

29  

30  
auto
30  
auto
31  
params_ref::
31  
params_ref::
32  
operator=(params_ref const& other) ->
32  
operator=(params_ref const& other) ->
33  
    params_ref&
33  
    params_ref&
34  
{
34  
{
35  
    if (!ref_.alias_of(other.ref_))
35  
    if (!ref_.alias_of(other.ref_))
36  
        assign(other.begin(), other.end());
36  
        assign(other.begin(), other.end());
37  
    return *this;
37  
    return *this;
38  
}
38  
}
39  

39  

40  
params_ref::
40  
params_ref::
41  
operator
41  
operator
42  
params_view() const noexcept
42  
params_view() const noexcept
43  
{
43  
{
44  
    return { ref_, opt_ };
44  
    return { ref_, opt_ };
45  
}
45  
}
46  

46  

47  
//------------------------------------------------
47  
//------------------------------------------------
48  
//
48  
//
49  
// Modifiers
49  
// Modifiers
50  
//
50  
//
51  
//------------------------------------------------
51  
//------------------------------------------------
52  

52  

53  
void
53  
void
54  
params_ref::
54  
params_ref::
55  
assign(
55  
assign(
56  
    std::initializer_list<
56  
    std::initializer_list<
57  
        param_view> init)
57  
        param_view> init)
58  
{
58  
{
59  
    assign(init.begin(), init.end());
59  
    assign(init.begin(), init.end());
60  
}
60  
}
61  

61  

62  
auto
62  
auto
63  
params_ref::
63  
params_ref::
64  
insert(
64  
insert(
65  
    iterator before,
65  
    iterator before,
66  
    param_view const& p) ->
66  
    param_view const& p) ->
67  
        iterator
67  
        iterator
68  
{
68  
{
69  
    return {
69  
    return {
70  
        u_->edit_params(
70  
        u_->edit_params(
71  
            before.it_,
71  
            before.it_,
72  
            before.it_,
72  
            before.it_,
73  
            detail::single_param_iter(p, opt_.space_as_plus)),
73  
            detail::single_param_iter(p, opt_.space_as_plus)),
74  
        opt_};
74  
        opt_};
75  
}
75  
}
76  

76  

77  
auto
77  
auto
78  
params_ref::
78  
params_ref::
79  
insert(
79  
insert(
80  
    iterator before,
80  
    iterator before,
81  
    std::initializer_list<
81  
    std::initializer_list<
82  
        param_view> init) ->
82  
        param_view> init) ->
83  
    iterator
83  
    iterator
84  
{
84  
{
85  
    return insert(
85  
    return insert(
86  
        before,
86  
        before,
87  
        init.begin(),
87  
        init.begin(),
88  
        init.end());
88  
        init.end());
89  
}
89  
}
90  

90  

91  
std::size_t
91  
std::size_t
92  
params_ref::
92  
params_ref::
93  
erase(
93  
erase(
94  
    core::string_view key,
94  
    core::string_view key,
95  
    ignore_case_param ic) noexcept
95  
    ignore_case_param ic) noexcept
96  
{
96  
{
97  
    // end() can't be fully cached,
97  
    // end() can't be fully cached,
98  
    // since erase invalidates it.
98  
    // since erase invalidates it.
99  
    iterator it;
99  
    iterator it;
100  
    {
100  
    {
101  
        auto const end_ = end();
101  
        auto const end_ = end();
102  
        it = find_last(end_, key, ic);
102  
        it = find_last(end_, key, ic);
103  
        if(it == end_)
103  
        if(it == end_)
104  
            return 0;
104  
            return 0;
105  
    }
105  
    }
106  
    std::size_t n = 0;
106  
    std::size_t n = 0;
107  
    for(;;)
107  
    for(;;)
108  
    {
108  
    {
109  
        ++n;
109  
        ++n;
110  
        // Use it->key instead of key,
110  
        // Use it->key instead of key,
111  
        // to handle self-intersection
111  
        // to handle self-intersection
112  
        auto prev = find_last(it, (*it).key, ic);
112  
        auto prev = find_last(it, (*it).key, ic);
113  
        if(prev == end())
113  
        if(prev == end())
114  
            break;
114  
            break;
115  
        erase(it);
115  
        erase(it);
116  
        it = prev;
116  
        it = prev;
117  
    }
117  
    }
118  
    erase(it);
118  
    erase(it);
119  
    return n;
119  
    return n;
120  
}
120  
}
121  

121  

122  
auto
122  
auto
123  
params_ref::
123  
params_ref::
124  
replace(
124  
replace(
125  
    iterator pos,
125  
    iterator pos,
126  
    param_view const& p) ->
126  
    param_view const& p) ->
127  
        iterator
127  
        iterator
128  
{
128  
{
129  
    return iterator(
129  
    return iterator(
130  
        u_->edit_params(
130  
        u_->edit_params(
131  
            pos.it_,
131  
            pos.it_,
132  
            std::next(pos).it_,
132  
            std::next(pos).it_,
133  
            detail::single_param_iter(p, opt_.space_as_plus)),
133  
            detail::single_param_iter(p, opt_.space_as_plus)),
134  
        opt_);
134  
        opt_);
135  
}
135  
}
136  

136  

137  
auto
137  
auto
138  
params_ref::
138  
params_ref::
139  
replace(
139  
replace(
140  
    iterator from,
140  
    iterator from,
141  
    iterator to,
141  
    iterator to,
142  
    std::initializer_list<
142  
    std::initializer_list<
143  
        param_view> init) ->
143  
        param_view> init) ->
144  
    iterator
144  
    iterator
145  
{
145  
{
146  
    return replace(
146  
    return replace(
147  
        from,
147  
        from,
148  
        to,
148  
        to,
149  
        init.begin(),
149  
        init.begin(),
150  
        init.end());
150  
        init.end());
151  
}
151  
}
152  

152  

153  
auto
153  
auto
154  
params_ref::
154  
params_ref::
155  
unset(
155  
unset(
156  
    iterator pos) noexcept ->
156  
    iterator pos) noexcept ->
157  
        iterator
157  
        iterator
158  
{
158  
{
159  
    BOOST_ASSERT(pos.it_.nk > 0);
159  
    BOOST_ASSERT(pos.it_.nk > 0);
160  
    core::string_view s;
160  
    core::string_view s;
161  
    return iterator(
161  
    return iterator(
162  
        u_->edit_params(
162  
        u_->edit_params(
163  
            pos.it_,
163  
            pos.it_,
164  
            pos.it_.next(),
164  
            pos.it_.next(),
165  
            detail::param_value_iter(
165  
            detail::param_value_iter(
166  
                pos.it_.nk - 1, s, false)),
166  
                pos.it_.nk - 1, s, false)),
167  
        opt_);
167  
        opt_);
168  
}
168  
}
169  

169  

170  
auto
170  
auto
171  
params_ref::
171  
params_ref::
172  
set(
172  
set(
173  
    iterator pos,
173  
    iterator pos,
174  
    core::string_view value) ->
174  
    core::string_view value) ->
175  
        iterator
175  
        iterator
176  
{
176  
{
177  
    BOOST_ASSERT(pos.it_.nk > 0);
177  
    BOOST_ASSERT(pos.it_.nk > 0);
178  
    return iterator(
178  
    return iterator(
179  
        u_->edit_params(
179  
        u_->edit_params(
180  
            pos.it_,
180  
            pos.it_,
181  
            pos.it_.next(),
181  
            pos.it_.next(),
182  
            detail::param_value_iter(
182  
            detail::param_value_iter(
183  
                pos.it_.nk - 1, value, true)),
183  
                pos.it_.nk - 1, value, true)),
184  
        opt_);
184  
        opt_);
185  
}
185  
}
186  

186  

187  
auto
187  
auto
188  
params_ref::
188  
params_ref::
189  
set(
189  
set(
190  
    core::string_view key,
190  
    core::string_view key,
191  
    core::string_view value,
191  
    core::string_view value,
192  
    ignore_case_param ic) ->
192  
    ignore_case_param ic) ->
193  
        iterator
193  
        iterator
194  
{
194  
{
195  
    // VFALCO we can't cache end() here
195  
    // VFALCO we can't cache end() here
196  
    // because it is invalidated
196  
    // because it is invalidated
197  
    // every time we set or erase.
197  
    // every time we set or erase.
198  
    auto it0 = find(key, ic);
198  
    auto it0 = find(key, ic);
199  
    if(it0 == end())
199  
    if(it0 == end())
200  
        return append({key, value});
200  
        return append({key, value});
201  
    it0 = set(it0, value);
201  
    it0 = set(it0, value);
202  
    auto it = end();
202  
    auto it = end();
203  
    for(;;)
203  
    for(;;)
204  
    {
204  
    {
205  
        it = find_last(it, key, ic);
205  
        it = find_last(it, key, ic);
206  
        if(it == it0)
206  
        if(it == it0)
207  
            return it0;
207  
            return it0;
208  
        it = erase(it);
208  
        it = erase(it);
209  
    }
209  
    }
210  
}
210  
}
211  

211  

212  
auto
212  
auto
213  
params_ref::
213  
params_ref::
214  
erase(
214  
erase(
215  
    iterator pos) noexcept ->
215  
    iterator pos) noexcept ->
216  
    iterator
216  
    iterator
217  
{
217  
{
218  
    return erase(
218  
    return erase(
219  
        pos,
219  
        pos,
220  
        std::next(pos));
220  
        std::next(pos));
221  
}
221  
}
222  

222  

223  
auto
223  
auto
224  
params_ref::
224  
params_ref::
225  
erase(
225  
erase(
226  
    iterator first,
226  
    iterator first,
227  
    iterator last) noexcept ->
227  
    iterator last) noexcept ->
228  
        iterator
228  
        iterator
229  
{
229  
{
230  
    core::string_view s("", 0);
230  
    core::string_view s("", 0);
231  
    return iterator(
231  
    return iterator(
232  
        u_->edit_params(
232  
        u_->edit_params(
233  
            first.it_,
233  
            first.it_,
234  
            last.it_,
234  
            last.it_,
235  
            detail::query_string_iter(s)),
235  
            detail::query_string_iter(s)),
236  
        opt_);
236  
        opt_);
237  
}
237  
}
238  

238  

239  
} // urls
239  
} // urls
240  
} // boost
240  
} // boost
241  

241