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_encoded_ref.hpp>
14  
#include <boost/url/params_encoded_ref.hpp>
15  
#include <boost/url/params_encoded_view.hpp>
15  
#include <boost/url/params_encoded_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  
params_encoded_ref::
30  
params_encoded_ref::
31  
params_encoded_ref(
31  
params_encoded_ref(
32  
    url_base& u) noexcept
32  
    url_base& u) noexcept
33  
    : params_encoded_base(u.impl_)
33  
    : params_encoded_base(u.impl_)
34  
    , u_(&u)
34  
    , u_(&u)
35  
{
35  
{
36  
}
36  
}
37  

37  

38  
params_encoded_ref&
38  
params_encoded_ref&
39  
params_encoded_ref::
39  
params_encoded_ref::
40  
operator=(
40  
operator=(
41  
    params_encoded_ref const& other)
41  
    params_encoded_ref const& other)
42  
{
42  
{
43  
    if (!ref_.alias_of( other.ref_ ))
43  
    if (!ref_.alias_of( other.ref_ ))
44  
        assign(other.begin(), other.end());
44  
        assign(other.begin(), other.end());
45  
    return *this;
45  
    return *this;
46  
}
46  
}
47  

47  

48  
params_encoded_ref&
48  
params_encoded_ref&
49  
params_encoded_ref::
49  
params_encoded_ref::
50  
operator=(std::initializer_list<
50  
operator=(std::initializer_list<
51  
    param_pct_view> init)
51  
    param_pct_view> init)
52  
{
52  
{
53  
    assign(init.begin(), init.end());
53  
    assign(init.begin(), init.end());
54  
    return *this;
54  
    return *this;
55  
}
55  
}
56  

56  

57  
params_encoded_ref::
57  
params_encoded_ref::
58  
operator
58  
operator
59  
params_encoded_view() const noexcept
59  
params_encoded_view() const noexcept
60  
{
60  
{
61  
    return {ref_};
61  
    return {ref_};
62  
}
62  
}
63  

63  

64  
//------------------------------------------------
64  
//------------------------------------------------
65  
//
65  
//
66  
// Modifiers
66  
// Modifiers
67  
//
67  
//
68  
//------------------------------------------------
68  
//------------------------------------------------
69  

69  

70  
void
70  
void
71  
params_encoded_ref::
71  
params_encoded_ref::
72  
assign(
72  
assign(
73  
    std::initializer_list<
73  
    std::initializer_list<
74  
        param_pct_view> init)
74  
        param_pct_view> init)
75  
{
75  
{
76  
    assign(init.begin(), init.end());
76  
    assign(init.begin(), init.end());
77  
}
77  
}
78  

78  

79  
auto
79  
auto
80  
params_encoded_ref::
80  
params_encoded_ref::
81  
insert(
81  
insert(
82  
    iterator before,
82  
    iterator before,
83  
    param_pct_view const& p) ->
83  
    param_pct_view const& p) ->
84  
        iterator
84  
        iterator
85  
{
85  
{
86  
    return u_->edit_params(
86  
    return u_->edit_params(
87  
        before.it_,
87  
        before.it_,
88  
        before.it_,
88  
        before.it_,
89  
        detail::param_encoded_iter(p));
89  
        detail::param_encoded_iter(p));
90  
}
90  
}
91  

91  

92  
auto
92  
auto
93  
params_encoded_ref::
93  
params_encoded_ref::
94  
insert(
94  
insert(
95  
    iterator before,
95  
    iterator before,
96  
    std::initializer_list<
96  
    std::initializer_list<
97  
        param_pct_view> init) ->
97  
        param_pct_view> init) ->
98  
    iterator
98  
    iterator
99  
{
99  
{
100  
    return insert(
100  
    return insert(
101  
        before,
101  
        before,
102  
        init.begin(),
102  
        init.begin(),
103  
        init.end());
103  
        init.end());
104  
}
104  
}
105  

105  

106  
std::size_t
106  
std::size_t
107  
params_encoded_ref::
107  
params_encoded_ref::
108  
erase(
108  
erase(
109  
    pct_string_view key,
109  
    pct_string_view key,
110  
    ignore_case_param ic) noexcept
110  
    ignore_case_param ic) noexcept
111  
{
111  
{
112  
    // end() can't be fully cached,
112  
    // end() can't be fully cached,
113  
    // since erase invalidates it.
113  
    // since erase invalidates it.
114  
    iterator it;
114  
    iterator it;
115  
    {
115  
    {
116  
        auto const end_ = end();
116  
        auto const end_ = end();
117  
        it = find_last(end_, key, ic);
117  
        it = find_last(end_, key, ic);
118  
        if(it == end_)
118  
        if(it == end_)
119  
            return 0;
119  
            return 0;
120  
    }
120  
    }
121  
    std::size_t n = 0;
121  
    std::size_t n = 0;
122  
    for(;;)
122  
    for(;;)
123  
    {
123  
    {
124  
        ++n;
124  
        ++n;
125  
        // Use it->key instead of key,
125  
        // Use it->key instead of key,
126  
        // to handle self-intersection
126  
        // to handle self-intersection
127  
        auto prev = find_last(it, it->key, ic);
127  
        auto prev = find_last(it, it->key, ic);
128  
        if(prev == end())
128  
        if(prev == end())
129  
            break;
129  
            break;
130  
        erase(it);
130  
        erase(it);
131  
        it = prev;
131  
        it = prev;
132  
    }
132  
    }
133  
    erase(it);
133  
    erase(it);
134  
    return n;
134  
    return n;
135  
}
135  
}
136  

136  

137  
auto
137  
auto
138  
params_encoded_ref::
138  
params_encoded_ref::
139  
replace(
139  
replace(
140  
    iterator pos,
140  
    iterator pos,
141  
    param_pct_view const& p) ->
141  
    param_pct_view const& p) ->
142  
        iterator
142  
        iterator
143  
{
143  
{
144  
    return u_->edit_params(
144  
    return u_->edit_params(
145  
        pos.it_,
145  
        pos.it_,
146  
        std::next(pos).it_,
146  
        std::next(pos).it_,
147  
        detail::param_encoded_iter(p));
147  
        detail::param_encoded_iter(p));
148  
}
148  
}
149  

149  

150  
auto
150  
auto
151  
params_encoded_ref::
151  
params_encoded_ref::
152  
replace(
152  
replace(
153  
    iterator from,
153  
    iterator from,
154  
    iterator to,
154  
    iterator to,
155  
    std::initializer_list<
155  
    std::initializer_list<
156  
        param_pct_view> init) ->
156  
        param_pct_view> init) ->
157  
    iterator
157  
    iterator
158  
{
158  
{
159  
    return replace(
159  
    return replace(
160  
        from,
160  
        from,
161  
        to,
161  
        to,
162  
        init.begin(),
162  
        init.begin(),
163  
        init.end());
163  
        init.end());
164  
}
164  
}
165  

165  

166  
auto
166  
auto
167  
params_encoded_ref::
167  
params_encoded_ref::
168  
unset(
168  
unset(
169  
    iterator pos) noexcept ->
169  
    iterator pos) noexcept ->
170  
        iterator
170  
        iterator
171  
{
171  
{
172  
    BOOST_ASSERT(pos.it_.nk > 0);
172  
    BOOST_ASSERT(pos.it_.nk > 0);
173  
    pct_string_view s;
173  
    pct_string_view s;
174  
    return u_->edit_params(
174  
    return u_->edit_params(
175  
        pos.it_, pos.it_.next(),
175  
        pos.it_, pos.it_.next(),
176  
        detail::param_encoded_value_iter(
176  
        detail::param_encoded_value_iter(
177  
            pos.it_.nk - 1, s, false));
177  
            pos.it_.nk - 1, s, false));
178  
}
178  
}
179  

179  

180  
auto
180  
auto
181  
params_encoded_ref::
181  
params_encoded_ref::
182  
set(
182  
set(
183  
    iterator pos,
183  
    iterator pos,
184  
    pct_string_view value) ->
184  
    pct_string_view value) ->
185  
        iterator
185  
        iterator
186  
{
186  
{
187  
    BOOST_ASSERT(pos.it_.nk > 0);
187  
    BOOST_ASSERT(pos.it_.nk > 0);
188  
    return u_->edit_params(
188  
    return u_->edit_params(
189  
        pos.it_,
189  
        pos.it_,
190  
        pos.it_.next(),
190  
        pos.it_.next(),
191  
        detail::param_encoded_value_iter(
191  
        detail::param_encoded_value_iter(
192  
            pos.it_.nk - 1, value, true));
192  
            pos.it_.nk - 1, value, true));
193  
}
193  
}
194  

194  

195  
auto
195  
auto
196  
params_encoded_ref::
196  
params_encoded_ref::
197  
set(
197  
set(
198  
    pct_string_view key,
198  
    pct_string_view key,
199  
    pct_string_view value,
199  
    pct_string_view value,
200  
    ignore_case_param ic) ->
200  
    ignore_case_param ic) ->
201  
        iterator
201  
        iterator
202  
{
202  
{
203  
    // VFALCO we can't cache end() here
203  
    // VFALCO we can't cache end() here
204  
    // because it is invalidated
204  
    // because it is invalidated
205  
    // every time we set or erase.
205  
    // every time we set or erase.
206  
    auto it0 = find(key, ic);
206  
    auto it0 = find(key, ic);
207  
    if(it0 == end())
207  
    if(it0 == end())
208  
        return append({key, value});
208  
        return append({key, value});
209  
    it0 = set(it0, value);
209  
    it0 = set(it0, value);
210  
    auto it = end();
210  
    auto it = end();
211  
    for(;;)
211  
    for(;;)
212  
    {
212  
    {
213  
        it = find_last(it, key, ic);
213  
        it = find_last(it, key, ic);
214  
        if(it == it0)
214  
        if(it == it0)
215  
            return it0;
215  
            return it0;
216  
        it = erase(it);
216  
        it = erase(it);
217  
    }
217  
    }
218  
}
218  
}
219  

219  

220  
auto
220  
auto
221  
params_encoded_ref::
221  
params_encoded_ref::
222  
erase(
222  
erase(
223  
    iterator pos) noexcept ->
223  
    iterator pos) noexcept ->
224  
        iterator
224  
        iterator
225  
{
225  
{
226  
    return erase(
226  
    return erase(
227  
        pos,
227  
        pos,
228  
        std::next(pos));
228  
        std::next(pos));
229  
}
229  
}
230  

230  

231  
auto
231  
auto
232  
params_encoded_ref::
232  
params_encoded_ref::
233  
erase(
233  
erase(
234  
    iterator first,
234  
    iterator first,
235  
    iterator last) noexcept ->
235  
    iterator last) noexcept ->
236  
        iterator
236  
        iterator
237  
{
237  
{
238  
    core::string_view s("", 0);
238  
    core::string_view s("", 0);
239  
    return u_->edit_params(
239  
    return u_->edit_params(
240  
        first.it_,
240  
        first.it_,
241  
        last.it_,
241  
        last.it_,
242  
        detail::query_string_iter(s));
242  
        detail::query_string_iter(s));
243  
}
243  
}
244  

244  

245  
} // urls
245  
} // urls
246  
} // boost
246  
} // boost
247  

247