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) 2023 Alan de Freitas (alandefreitas@gmail.com)
3  
//
4  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// 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)
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
7  
//
7  
// Official repository: https://github.com/boostorg/url
8  
// Official repository: https://github.com/boostorg/url
8  
//
9  
//
9  

10  

10  

11  

11  
#include <boost/url/detail/config.hpp>
12  
#include <boost/url/detail/config.hpp>
12  
#include <boost/url/detail/any_params_iter.hpp>
13  
#include <boost/url/detail/any_params_iter.hpp>
13  
#include <boost/url/encode.hpp>
14  
#include <boost/url/encode.hpp>
14  
#include <boost/core/detail/string_view.hpp>
15  
#include <boost/core/detail/string_view.hpp>
15 -
#include "../rfc/detail/charsets.hpp"
16 +
#include <boost/url/rfc/detail/charsets.hpp>
16  

17  

17  
namespace boost {
18  
namespace boost {
18  
namespace urls {
19  
namespace urls {
19  
namespace detail {
20  
namespace detail {
20  

21  

21  
/*
22  
/*
22  
    When a string is transformed into a range of
23  
    When a string is transformed into a range of
23  
    params, the empty string becomes ambiguous:
24  
    params, the empty string becomes ambiguous:
24  
    it can be an empty range, or a range with
25  
    it can be an empty range, or a range with
25  
    one param. The value `not_empty` is used on
26  
    one param. The value `not_empty` is used on
26  
    construction to inform the transformation
27  
    construction to inform the transformation
27  
    that the empty string should be treated as
28  
    that the empty string should be treated as
28  
    a one-element range. This simplifies
29  
    a one-element range. This simplifies
29  
    edit_params().
30  
    edit_params().
30  
*/
31  
*/
31  

32  

32  
//------------------------------------------------
33  
//------------------------------------------------
33  
//
34  
//
34  
// any_params_iter
35  
// any_params_iter
35  
//
36  
//
36  
//------------------------------------------------
37  
//------------------------------------------------
37  

38  

38  
any_params_iter::
39  
any_params_iter::
39 -

 
40 -
//------------------------------------------------
 
41 -
//
 
42 -
// query_iter
 
43 -
//
 
44 -
//------------------------------------------------
 
45 -

 
46 -
query_string_iter::
 
47 -
query_string_iter(
 
48 -
    core::string_view s,
 
49 -
    bool ne) noexcept
 
50 -
    : any_params_iter(
 
51 -
        s.empty() && ! ne, s)
 
52 -
{
 
53 -
    rewind();
 
54 -
}
 
55 -

 
56 -
void
 
57 -
query_string_iter::
 
58 -
rewind() noexcept
 
59 -
{
 
60 -
    if(empty)
 
61 -
    {
 
62 -
        at_end_ = true;
 
63 -
        return;
 
64 -
    }
 
65 -
    p_ = s0.begin();
 
66 -
    if(! s0.empty())
 
67 -
    {
 
68 -
        auto pos =
 
69 -
            s0.find_first_of('&');
 
70 -
        if(pos != core::string_view::npos)
 
71 -
            n_ = pos;
 
72 -
        else
 
73 -
            n_ = s0.size();
 
74 -
    }
 
75 -
    else
 
76 -
    {
 
77 -
        n_ = 0;
 
78 -
    }
 
79 -
    at_end_ = false;
 
80 -
}
 
81 -

 
82 -
bool
 
83 -
query_string_iter::
 
84 -
measure(
 
85 -
    std::size_t& n) noexcept
 
86 -
{
 
87 -
    if(at_end_)
 
88 -
        return false;
 
89 -
    // When interacting with the query as
 
90 -
    // an intact string, we do not treat
 
91 -
    // the plus sign as an encoded space.
 
92 -
    encoding_opts opt;
 
93 -
    opt.space_as_plus = false;
 
94 -
    n += encoded_size(
 
95 -
        core::string_view(p_, n_),
 
96 -
        query_chars,
 
97 -
        opt);
 
98 -
    increment();
 
99 -
    return true;
 
100 -
}
 
101 -

 
102 -
void
 
103 -
query_string_iter::
 
104 -
copy(
 
105 -
    char*& dest,
 
106 -
    char const* end) noexcept
 
107 -
{
 
108 -
    BOOST_ASSERT(! at_end_);
 
109 -
    // When interacting with the query as
 
110 -
    // an intact string, we do not treat
 
111 -
    // the plus sign as an encoded space.
 
112 -
    encoding_opts opt;
 
113 -
    opt.space_as_plus = false;
 
114 -
    dest += encode_unsafe(
 
115 -
        dest,
 
116 -
        end - dest,
 
117 -
        core::string_view(p_, n_),
 
118 -
        query_chars,
 
119 -
        opt);
 
120 -
    increment();
 
121 -
}
 
122 -

 
123 -
void
 
124 -
query_string_iter::
 
125 -
increment() noexcept
 
126 -
{
 
127 -
    p_ += n_;
 
128 -
    if(p_ == s0.end())
 
129 -
    {
 
130 -
        at_end_ = true;
 
131 -
        return;
 
132 -
    }
 
133 -
    ++p_;
 
134 -
    core::string_view s(p_, s0.end() - p_);
 
135 -
    auto pos = s.find_first_of('&');
 
136 -
    if(pos != core::string_view::npos)
 
137 -
        n_ = pos;
 
138 -
    else
 
139 -
        n_ = s.size();
 
140 -
}
 
141  
~any_params_iter() noexcept = default;
40  
~any_params_iter() noexcept = default;
142  

41  

143  
//------------------------------------------------
42  
//------------------------------------------------
144  
//
43  
//
145  
// param_iter
44  
// param_iter
146  
//
45  
//
147  
//------------------------------------------------
46  
//------------------------------------------------
148  

47  

149  
single_param_iter::
48  
single_param_iter::
150  
single_param_iter(
49  
single_param_iter(
151  
    param_view const& p,
50  
    param_view const& p,
152  
    bool space_as_plus) noexcept
51  
    bool space_as_plus) noexcept
153  
    : any_params_iter(
52  
    : any_params_iter(
154  
        false,
53  
        false,
155  
        p.key,
54  
        p.key,
156  
        p.value)
55  
        p.value)
157  
    , has_value_(p.has_value)
56  
    , has_value_(p.has_value)
158  
    , space_as_plus_(space_as_plus)
57  
    , space_as_plus_(space_as_plus)
159  
{
58  
{
160  
}
59  
}
161  

60  

162  
void
61  
void
163  
single_param_iter::
62  
single_param_iter::
164  
rewind() noexcept
63  
rewind() noexcept
165  
{
64  
{
166  
    at_end_ = false;
65  
    at_end_ = false;
167  
}
66  
}
168  

67  

169  
bool
68  
bool
170  
single_param_iter::
69  
single_param_iter::
171  
measure(std::size_t& n) noexcept
70  
measure(std::size_t& n) noexcept
172  
{
71  
{
173  
    if(at_end_)
72  
    if(at_end_)
174  
        return false;
73  
        return false;
175  
    encoding_opts opt;
74  
    encoding_opts opt;
176  
    opt.space_as_plus = space_as_plus_;
75  
    opt.space_as_plus = space_as_plus_;
177  
    n += encoded_size(
76  
    n += encoded_size(
178  
        s0,
77  
        s0,
179  
        detail::param_key_chars,
78  
        detail::param_key_chars,
180  
        opt);
79  
        opt);
181  
    if(has_value_)
80  
    if(has_value_)
182  
    {
81  
    {
183  
        ++n; // '='
82  
        ++n; // '='
184  
        n += encoded_size(
83  
        n += encoded_size(
185  
            s1,
84  
            s1,
186  
            detail::param_value_chars,
85  
            detail::param_value_chars,
187  
            opt);
86  
            opt);
188  
    }
87  
    }
189  
    at_end_ = true;
88  
    at_end_ = true;
190  
    return true;
89  
    return true;
191  
}
90  
}
192  

91  

193  
void
92  
void
194  
single_param_iter::
93  
single_param_iter::
195  
copy(
94  
copy(
196  
    char*& dest,
95  
    char*& dest,
197  
    char const* end) noexcept
96  
    char const* end) noexcept
198  
{
97  
{
199  
    BOOST_ASSERT(! at_end_);
98  
    BOOST_ASSERT(! at_end_);
200  
    encoding_opts opt;
99  
    encoding_opts opt;
201  
    opt.space_as_plus = space_as_plus_;
100  
    opt.space_as_plus = space_as_plus_;
202  
    dest += encode(
101  
    dest += encode(
203  
        dest,
102  
        dest,
204  
        end - dest,
103  
        end - dest,
205  
        s0,
104  
        s0,
206  
        detail::param_key_chars,
105  
        detail::param_key_chars,
207  
        opt);
106  
        opt);
208  
    if (has_value_)
107  
    if (has_value_)
209  
    {
108  
    {
210  
        *dest++ = '=';
109  
        *dest++ = '=';
211  
        dest += encode(
110  
        dest += encode(
212  
            dest,
111  
            dest,
213  
            end - dest,
112  
            end - dest,
214  
            s1,
113  
            s1,
215  
            detail::param_value_chars,
114  
            detail::param_value_chars,
216  
            opt);
115  
            opt);
217  
    }
116  
    }
218  
}
117  
}
219  

118  

220  
//------------------------------------------------
119  
//------------------------------------------------
221  
//
120  
//
222  
// params_iter_base
121  
// params_iter_base
223  
//
122  
//
224  
//------------------------------------------------
123  
//------------------------------------------------
225  

124  

226  
void
125  
void
227  
params_iter_base::
126  
params_iter_base::
228  
measure_impl(
127  
measure_impl(
229  
    std::size_t& n,
128  
    std::size_t& n,
230  
    param_view const& p) noexcept
129  
    param_view const& p) noexcept
231  
{
130  
{
232  
    encoding_opts opt;
131  
    encoding_opts opt;
233  
    opt.space_as_plus = space_as_plus_;
132  
    opt.space_as_plus = space_as_plus_;
234  
    n += encoded_size(
133  
    n += encoded_size(
235  
        p.key,
134  
        p.key,
236  
        detail::param_key_chars,
135  
        detail::param_key_chars,
237  
        opt);
136  
        opt);
238  
    if(p.has_value)
137  
    if(p.has_value)
239  
    {
138  
    {
240  
        ++n; // '='
139  
        ++n; // '='
241  
        n += encoded_size(
140  
        n += encoded_size(
242  
            p.value,
141  
            p.value,
243  
            detail::param_value_chars,
142  
            detail::param_value_chars,
244  
            opt);
143  
            opt);
245  
    }
144  
    }
246  
}
145  
}
247  

146  

248  
void
147  
void
249  
params_iter_base::
148  
params_iter_base::
250  
copy_impl(
149  
copy_impl(
251  
    char*& dest,
150  
    char*& dest,
252  
    char const* end,
151  
    char const* end,
253  
    param_view const& p) noexcept
152  
    param_view const& p) noexcept
254  
{
153  
{
255  
    encoding_opts opt;
154  
    encoding_opts opt;
256  
    opt.space_as_plus = space_as_plus_;
155  
    opt.space_as_plus = space_as_plus_;
257  
    dest += encode(
156  
    dest += encode(
258  
        dest,
157  
        dest,
259  
        end - dest,
158  
        end - dest,
260  
        p.key,
159  
        p.key,
261  
        detail::param_key_chars,
160  
        detail::param_key_chars,
262  
        opt);
161  
        opt);
263  
    if(p.has_value)
162  
    if(p.has_value)
264  
    {
163  
    {
265  
        *dest++ = '=';
164  
        *dest++ = '=';
266  
        dest += encode(
165  
        dest += encode(
267  
            dest,
166  
            dest,
268  
            end - dest,
167  
            end - dest,
269  
            p.value,
168  
            p.value,
270  
            detail::param_value_chars,
169  
            detail::param_value_chars,
271  
            opt);
170  
            opt);
272  
    }
171  
    }
273  
}
172  
}
274  

173  

275  
//------------------------------------------------
174  
//------------------------------------------------
276  
//
175  
//
277  
// param_encoded_iter
176  
// param_encoded_iter
278  
//
177  
//
279  
//------------------------------------------------
178  
//------------------------------------------------
280  

179  

281  
param_encoded_iter::
180  
param_encoded_iter::
282  
param_encoded_iter(
181  
param_encoded_iter(
283  
    param_pct_view const& p) noexcept
182  
    param_pct_view const& p) noexcept
284  
    : any_params_iter(
183  
    : any_params_iter(
285  
        false,
184  
        false,
286  
        p.key,
185  
        p.key,
287  
        p.value)
186  
        p.value)
288  
    , has_value_(p.has_value)
187  
    , has_value_(p.has_value)
289  
{
188  
{
290  
}
189  
}
291  

190  

292  
void
191  
void
293  
param_encoded_iter::
192  
param_encoded_iter::
294  
rewind() noexcept
193  
rewind() noexcept
295  
{
194  
{
296  
    at_end_ = false;
195  
    at_end_ = false;
297  
}
196  
}
298  

197  

299  
bool
198  
bool
300  
param_encoded_iter::
199  
param_encoded_iter::
301  
measure(std::size_t& n) noexcept
200  
measure(std::size_t& n) noexcept
302  
{
201  
{
303  
    if(at_end_)
202  
    if(at_end_)
304  
        return false;
203  
        return false;
305  
    n += detail::re_encoded_size_unsafe(
204  
    n += detail::re_encoded_size_unsafe(
306  
        s0,
205  
        s0,
307  
        detail::param_key_chars);
206  
        detail::param_key_chars);
308  
    if(has_value_)
207  
    if(has_value_)
309  
        n += detail::re_encoded_size_unsafe(
208  
        n += detail::re_encoded_size_unsafe(
310  
            s1,
209  
            s1,
311  
            detail::param_value_chars) + 1; // for '='
210  
            detail::param_value_chars) + 1; // for '='
312  
    at_end_ = true;
211  
    at_end_ = true;
313  
    return true;
212  
    return true;
314  
}
213  
}
315  

214  

316  
void
215  
void
317  
param_encoded_iter::
216  
param_encoded_iter::
318  
copy(
217  
copy(
319  
    char*& dest,
218  
    char*& dest,
320  
    char const* end) noexcept
219  
    char const* end) noexcept
321  
{
220  
{
322  
    detail::re_encode_unsafe(
221  
    detail::re_encode_unsafe(
323  
        dest,
222  
        dest,
324  
        end,
223  
        end,
325  
        s0,
224  
        s0,
326  
        detail::param_key_chars);
225  
        detail::param_key_chars);
327  
    if(has_value_)
226  
    if(has_value_)
328  
    {
227  
    {
329  
        *dest++ = '=';
228  
        *dest++ = '=';
330  
        detail::re_encode_unsafe(
229  
        detail::re_encode_unsafe(
331  
            dest,
230  
            dest,
332  
            end,
231  
            end,
333  
            s1,
232  
            s1,
334  
            detail::param_value_chars);
233  
            detail::param_value_chars);
335  
    }
234  
    }
336  
}
235  
}
337  

236  

338  

237  

339  
//------------------------------------------------
238  
//------------------------------------------------
340  
//
239  
//
341  
// params_encoded_iter_base
240  
// params_encoded_iter_base
342  
//
241  
//
343  
//------------------------------------------------
242  
//------------------------------------------------
344  

243  

345  
void
244  
void
346  
params_encoded_iter_base::
245  
params_encoded_iter_base::
347  
measure_impl(
246  
measure_impl(
348  
    std::size_t& n,
247  
    std::size_t& n,
349  
    param_view const& p) noexcept
248  
    param_view const& p) noexcept
350  
{
249  
{
351  
    n += detail::re_encoded_size_unsafe(
250  
    n += detail::re_encoded_size_unsafe(
352  
        p.key,
251  
        p.key,
353  
        detail::param_key_chars);
252  
        detail::param_key_chars);
354  
    if(p.has_value)
253  
    if(p.has_value)
355  
        n += detail::re_encoded_size_unsafe(
254  
        n += detail::re_encoded_size_unsafe(
356  
            p.value,
255  
            p.value,
357  
            detail::param_value_chars) + 1; // for '='
256  
            detail::param_value_chars) + 1; // for '='
358  
}
257  
}
359  

258  

360  
void
259  
void
361  
params_encoded_iter_base::
260  
params_encoded_iter_base::
362  
copy_impl(
261  
copy_impl(
363  
    char*& dest,
262  
    char*& dest,
364  
    char const* end,
263  
    char const* end,
365  
    param_view const& p) noexcept
264  
    param_view const& p) noexcept
366  
{
265  
{
367  
    detail::re_encode_unsafe(
266  
    detail::re_encode_unsafe(
368  
        dest,
267  
        dest,
369  
        end,
268  
        end,
370  
        p.key,
269  
        p.key,
371  
        detail::param_key_chars);
270  
        detail::param_key_chars);
372  
    if(p.has_value)
271  
    if(p.has_value)
373  
    {
272  
    {
374  
        *dest++ = '=';
273  
        *dest++ = '=';
375  
        detail::re_encode_unsafe(
274  
        detail::re_encode_unsafe(
376  
            dest,
275  
            dest,
377  
            end,
276  
            end,
378  
            p.value,
277  
            p.value,
379  
            detail::param_value_chars);
278  
            detail::param_value_chars);
380  
    }
279  
    }
381  
}
280  
}
382  

281  

383  
//------------------------------------------------
282  
//------------------------------------------------
384  
//
283  
//
385  
// param_value_iter
284  
// param_value_iter
386  
//
285  
//
387  
//------------------------------------------------
286  
//------------------------------------------------
388  

287  

389  
void
288  
void
390  
param_value_iter::
289  
param_value_iter::
391  
rewind() noexcept
290  
rewind() noexcept
392  
{
291  
{
393  
    at_end_ = false;
292  
    at_end_ = false;
394  
}
293  
}
395  

294  

396  
bool
295  
bool
397  
param_value_iter::
296  
param_value_iter::
398  
measure(
297  
measure(
399  
    std::size_t& n) noexcept
298  
    std::size_t& n) noexcept
400  
{
299  
{
401  
    if(at_end_)
300  
    if(at_end_)
402  
        return false;
301  
        return false;
403  
    n += nk_; // skip key
302  
    n += nk_; // skip key
404  
    if(has_value_)
303  
    if(has_value_)
405  
    {
304  
    {
406  
        encoding_opts opt;
305  
        encoding_opts opt;
407  
        opt.space_as_plus = false;
306  
        opt.space_as_plus = false;
408  
        n += encoded_size(
307  
        n += encoded_size(
409  
            s0,
308  
            s0,
410  
            detail::param_value_chars,
309  
            detail::param_value_chars,
411  
            opt) + 1; // for '='
310  
            opt) + 1; // for '='
412  
    }
311  
    }
413  
    at_end_ = true;
312  
    at_end_ = true;
414  
    return true;
313  
    return true;
415  
}
314  
}
416  

315  

417  
void
316  
void
418  
param_value_iter::
317  
param_value_iter::
419  
copy(char*& it, char const* end) noexcept
318  
copy(char*& it, char const* end) noexcept
420  
{
319  
{
421  
    it += nk_; // skip key
320  
    it += nk_; // skip key
422  
    if(! has_value_)
321  
    if(! has_value_)
423  
        return;
322  
        return;
424  
    *it++ = '=';
323  
    *it++ = '=';
425  
    encoding_opts opt;
324  
    encoding_opts opt;
426  
    opt.space_as_plus = false;
325  
    opt.space_as_plus = false;
427  
    it += encode(
326  
    it += encode(
428  
        it,
327  
        it,
429  
        end - it,
328  
        end - it,
430  
        s0,
329  
        s0,
431  
        detail::param_value_chars,
330  
        detail::param_value_chars,
432  
        opt);
331  
        opt);
433  
}
332  
}
434  

333  

435  
//------------------------------------------------
334  
//------------------------------------------------
436  
//
335  
//
437  
// param_encoded_value_iter
336  
// param_encoded_value_iter
438  
//
337  
//
439  
//------------------------------------------------
338  
//------------------------------------------------
440  

339  

441  
void
340  
void
442  
param_encoded_value_iter::
341  
param_encoded_value_iter::
443  
rewind() noexcept
342  
rewind() noexcept
444  
{
343  
{
445  
    at_end_ = false;
344  
    at_end_ = false;
446  
}
345  
}
447  

346  

448  
bool
347  
bool
449  
param_encoded_value_iter::
348  
param_encoded_value_iter::
450  
measure(
349  
measure(
451  
    std::size_t& n) noexcept
350  
    std::size_t& n) noexcept
452  
{
351  
{
453  
    if(at_end_)
352  
    if(at_end_)
454  
        return false;
353  
        return false;
455  
    n += nk_; // skip key
354  
    n += nk_; // skip key
456  
    if(has_value_)
355  
    if(has_value_)
457  
    {
356  
    {
458  
        n += detail::re_encoded_size_unsafe(
357  
        n += detail::re_encoded_size_unsafe(
459  
            s0,
358  
            s0,
460  
            detail::param_value_chars) + 1; // for '='
359  
            detail::param_value_chars) + 1; // for '='
461  
    }
360  
    }
462  
    at_end_ = true;
361  
    at_end_ = true;
463  
    return true;
362  
    return true;
464  
}
363  
}
465  

364  

466  
void
365  
void
467  
param_encoded_value_iter::
366  
param_encoded_value_iter::
468  
copy(
367  
copy(
469  
    char*& dest,
368  
    char*& dest,
470  
    char const* end) noexcept
369  
    char const* end) noexcept
471  
{
370  
{
472  
    dest += nk_; // skip key
371  
    dest += nk_; // skip key
473  
    if(! has_value_)
372  
    if(! has_value_)
474  
        return;
373  
        return;
475  
    *dest++ = '=';
374  
    *dest++ = '=';
476  
    detail::re_encode_unsafe(
375  
    detail::re_encode_unsafe(
477  
        dest,
376  
        dest,
478  
        end,
377  
        end,
479  
        s0,
378  
        s0,
480  
        detail::param_value_chars);
379  
        detail::param_value_chars);
481  
}
380  
}
482  

381  

483  
} // detail
382  
} // detail
484  
} // urls
383  
} // urls
485  
} // boost
384  
} // boost
486  

385