1  
//
1  
//
2  
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2022 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  

10  

11  
#include <boost/url/detail/config.hpp>
11  
#include <boost/url/detail/config.hpp>
12  
#include "path.hpp"
12  
#include "path.hpp"
13  
#include <boost/url/detail/url_impl.hpp>
13  
#include <boost/url/detail/url_impl.hpp>
14  
#include <boost/url/authority_view.hpp>
14  
#include <boost/url/authority_view.hpp>
15  
#include <boost/assert.hpp>
15  
#include <boost/assert.hpp>
16  
#include <cstring>
16  
#include <cstring>
17  

17  

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

21  

22  
#if defined(__GNUC__) && ! defined(__clang__) && defined(__MINGW32__)
22  
#if defined(__GNUC__) && ! defined(__clang__) && defined(__MINGW32__)
23  
#pragma GCC diagnostic push
23  
#pragma GCC diagnostic push
24  
#pragma GCC diagnostic ignored "-Warray-bounds"
24  
#pragma GCC diagnostic ignored "-Warray-bounds"
25  
#endif
25  
#endif
26  

26  

27  
//------------------------------------------------
27  
//------------------------------------------------
28  
//
28  
//
29  
// url_impl
29  
// url_impl
30  
//
30  
//
31  
//------------------------------------------------
31  
//------------------------------------------------
32  

32  

33  
void
33  
void
34  
url_impl::
34  
url_impl::
35  
apply_scheme(
35  
apply_scheme(
36  
    core::string_view s) noexcept
36  
    core::string_view s) noexcept
37  
{
37  
{
38  
    scheme_ = string_to_scheme(s);
38  
    scheme_ = string_to_scheme(s);
39  
    set_size(id_scheme, s.size() + 1);
39  
    set_size(id_scheme, s.size() + 1);
40  
}
40  
}
41  

41  

42  
void
42  
void
43  
url_impl::
43  
url_impl::
44  
apply_userinfo(
44  
apply_userinfo(
45  
    pct_string_view const& user,
45  
    pct_string_view const& user,
46  
    pct_string_view const* pass) noexcept
46  
    pct_string_view const* pass) noexcept
47  
{
47  
{
48  
    // this function is for
48  
    // this function is for
49  
    // authority_view_rule only
49  
    // authority_view_rule only
50  
    BOOST_ASSERT(from_ == from::authority);
50  
    BOOST_ASSERT(from_ == from::authority);
51  

51  

52  
    // userinfo
52  
    // userinfo
53  
    set_size(id_user, user.size());
53  
    set_size(id_user, user.size());
54  
    decoded_[id_user] =
54  
    decoded_[id_user] =
55 -
        user.decoded_size();
55 +
        detail::to_size_type(
 
56 +
            user.decoded_size());
56  
    if(pass)
57  
    if(pass)
57  
    {
58  
    {
58  
        set_size(id_pass,
59  
        set_size(id_pass,
59  
            pass->size() + 2);
60  
            pass->size() + 2);
60  
        decoded_[id_pass] =
61  
        decoded_[id_pass] =
61 -
            pass->decoded_size();
62 +
            detail::to_size_type(
 
63 +
                pass->decoded_size());
62  
    }
64  
    }
63  
    else
65  
    else
64  
    {
66  
    {
65  
        // trailing '@'
67  
        // trailing '@'
66  
        set_size(id_pass, 1 );
68  
        set_size(id_pass, 1 );
67  
    }
69  
    }
68  
}
70  
}
69  

71  

70  
void
72  
void
71  
url_impl::
73  
url_impl::
72  
apply_host(
74  
apply_host(
73  
    host_type ht,
75  
    host_type ht,
74  
    pct_string_view s,
76  
    pct_string_view s,
75  
    unsigned char const* addr) noexcept
77  
    unsigned char const* addr) noexcept
76  
{
78  
{
77  
    // this function is for
79  
    // this function is for
78  
    // authority_view_rule only
80  
    // authority_view_rule only
79  
    BOOST_ASSERT(from_ == from::authority);
81  
    BOOST_ASSERT(from_ == from::authority);
80  

82  

81  
    // host, port
83  
    // host, port
82  
    host_type_ = ht;
84  
    host_type_ = ht;
83  
    set_size(id_host, s.size());
85  
    set_size(id_host, s.size());
84  
    decoded_[id_host] =
86  
    decoded_[id_host] =
85 -
        s.decoded_size();
87 +
        detail::to_size_type(
 
88 +
            s.decoded_size());
86  
    std::memcpy(
89  
    std::memcpy(
87  
        ip_addr_,
90  
        ip_addr_,
88  
        addr,
91  
        addr,
89  
        sizeof(ip_addr_));
92  
        sizeof(ip_addr_));
90  
}
93  
}
91  

94  

92  
void
95  
void
93  
url_impl::
96  
url_impl::
94  
apply_port(
97  
apply_port(
95  
    core::string_view s,
98  
    core::string_view s,
96  
    unsigned short pn) noexcept
99  
    unsigned short pn) noexcept
97  
{
100  
{
98  
    // this function is for
101  
    // this function is for
99  
    // authority_view_rule only
102  
    // authority_view_rule only
100  
    BOOST_ASSERT(from_ == from::authority);
103  
    BOOST_ASSERT(from_ == from::authority);
101  

104  

102  
    port_number_ = pn;
105  
    port_number_ = pn;
103  
    set_size(id_port, 1 + s.size());
106  
    set_size(id_port, 1 + s.size());
104  
}
107  
}
105  

108  

106  
void
109  
void
107  
url_impl::
110  
url_impl::
108  
apply_authority(
111  
apply_authority(
109  
    authority_view const& a) noexcept
112  
    authority_view const& a) noexcept
110  
{
113  
{
111  
    BOOST_ASSERT(from_ != from::authority);
114  
    BOOST_ASSERT(from_ != from::authority);
112  

115  

113  
    // userinfo
116  
    // userinfo
114  
    set_size(id_user,
117  
    set_size(id_user,
115  
        a.u_.len(id_user) +
118  
        a.u_.len(id_user) +
116  
        (from_ == from::authority ? 0 : 2));
119  
        (from_ == from::authority ? 0 : 2));
117  
    set_size(id_pass, a.u_.len(id_pass));
120  
    set_size(id_pass, a.u_.len(id_pass));
118  
    decoded_[id_user] = a.u_.decoded_[id_user];
121  
    decoded_[id_user] = a.u_.decoded_[id_user];
119  
    decoded_[id_pass] = a.u_.decoded_[id_pass];
122  
    decoded_[id_pass] = a.u_.decoded_[id_pass];
120  

123  

121  
    // host, port
124  
    // host, port
122  
    host_type_ = a.u_.host_type_;
125  
    host_type_ = a.u_.host_type_;
123  
    port_number_ = a.u_.port_number_;
126  
    port_number_ = a.u_.port_number_;
124  
    set_size(id_host, a.u_.len(id_host));
127  
    set_size(id_host, a.u_.len(id_host));
125  
    set_size(id_port, a.u_.len(id_port));
128  
    set_size(id_port, a.u_.len(id_port));
126  
    std::memcpy(
129  
    std::memcpy(
127  
        ip_addr_,
130  
        ip_addr_,
128  
        a.u_.ip_addr_,
131  
        a.u_.ip_addr_,
129  
        sizeof(ip_addr_));
132  
        sizeof(ip_addr_));
130  
    decoded_[id_host] = a.u_.decoded_[id_host];
133  
    decoded_[id_host] = a.u_.decoded_[id_host];
131  
}
134  
}
132  

135  

133  
void
136  
void
134  
url_impl::
137  
url_impl::
135  
apply_path(
138  
apply_path(
136  
    pct_string_view s,
139  
    pct_string_view s,
137  
    std::size_t nseg) noexcept
140  
    std::size_t nseg) noexcept
138  
{
141  
{
139  
    set_size(id_path, s.size());
142  
    set_size(id_path, s.size());
140 -
    decoded_[id_path] = s.decoded_size();
143 +
    decoded_[id_path] =
141 -
    nseg_ = detail::path_segments(s, nseg);
144 +
        detail::to_size_type(
 
145 +
            s.decoded_size());
 
146 +
    nseg_ = detail::to_size_type(
 
147 +
        detail::path_segments(s, nseg));
142  
}
148  
}
143  

149  

144  
void
150  
void
145  
url_impl::
151  
url_impl::
146  
apply_query(
152  
apply_query(
147  
    pct_string_view s,
153  
    pct_string_view s,
148  
    std::size_t n) noexcept
154  
    std::size_t n) noexcept
149  
{
155  
{
150 -
    nparam_ = n;
156 +
    nparam_ = detail::to_size_type(n);
151  
    set_size(id_query, 1 + s.size());
157  
    set_size(id_query, 1 + s.size());
152 -
    decoded_[id_query] = s.decoded_size();
158 +
    decoded_[id_query] =
 
159 +
        detail::to_size_type(
 
160 +
            s.decoded_size());
153  
}
161  
}
154  

162  

155  
void
163  
void
156  
url_impl::
164  
url_impl::
157  
apply_frag(
165  
apply_frag(
158  
    pct_string_view s) noexcept
166  
    pct_string_view s) noexcept
159  
{
167  
{
160  
    set_size(id_frag, s.size() + 1);
168  
    set_size(id_frag, s.size() + 1);
161 -
    decoded_[id_frag] = s.decoded_size();
169 +
    decoded_[id_frag] =
 
170 +
        detail::to_size_type(
 
171 +
            s.decoded_size());
162  
}
172  
}
163  

173  

164  
// return length of [first, last)
174  
// return length of [first, last)
165  
auto
175  
auto
166  
url_impl::
176  
url_impl::
167  
len(
177  
len(
168  
    int first,
178  
    int first,
169  
    int last) const noexcept ->
179  
    int last) const noexcept ->
170  
        std::size_t
180  
        std::size_t
171  
{
181  
{
172  
    BOOST_ASSERT(first <= last);
182  
    BOOST_ASSERT(first <= last);
173  
    BOOST_ASSERT(last <= id_end);
183  
    BOOST_ASSERT(last <= id_end);
174  
    return offset(last) - offset(first);
184  
    return offset(last) - offset(first);
175  
}
185  
}
176  

186  

177  
// return length of part
187  
// return length of part
178  
auto
188  
auto
179  
url_impl::
189  
url_impl::
180  
len(int id) const noexcept ->
190  
len(int id) const noexcept ->
181  
    std::size_t
191  
    std::size_t
182  
{
192  
{
183  
    return id == id_end
193  
    return id == id_end
184  
        ? zero_
194  
        ? zero_
185  
        : ( offset(id + 1) -
195  
        : ( offset(id + 1) -
186  
            offset(id) );
196  
            offset(id) );
187  
}
197  
}
188  

198  

189  
// return offset of id
199  
// return offset of id
190  
auto
200  
auto
191  
url_impl::
201  
url_impl::
192  
offset(int id) const noexcept ->
202  
offset(int id) const noexcept ->
193  
    std::size_t
203  
    std::size_t
194  
{
204  
{
195  
    return
205  
    return
196  
        id == id_scheme
206  
        id == id_scheme
197  
        ? zero_
207  
        ? zero_
198  
        : offset_[id];
208  
        : offset_[id];
199  
}
209  
}
200  

210  

201  
// return id as string
211  
// return id as string
202  
core::string_view
212  
core::string_view
203  
url_impl::
213  
url_impl::
204  
get(int id) const noexcept
214  
get(int id) const noexcept
205  
{
215  
{
206  
    return {
216  
    return {
207  
        cs_ + offset(id), len(id) };
217  
        cs_ + offset(id), len(id) };
208  
}
218  
}
209  

219  

210  
// return [first, last) as string
220  
// return [first, last) as string
211  
core::string_view
221  
core::string_view
212  
url_impl::
222  
url_impl::
213  
get(int first,
223  
get(int first,
214  
    int last) const noexcept
224  
    int last) const noexcept
215  
{
225  
{
216  
    return { cs_ + offset(first),
226  
    return { cs_ + offset(first),
217  
        offset(last) - offset(first) };
227  
        offset(last) - offset(first) };
218  
}
228  
}
219  

229  

220  
// return id as pct-string
230  
// return id as pct-string
221  
pct_string_view
231  
pct_string_view
222  
url_impl::
232  
url_impl::
223  
pct_get(
233  
pct_get(
224  
    int id) const noexcept
234  
    int id) const noexcept
225  
{
235  
{
226  
    return make_pct_string_view_unsafe(
236  
    return make_pct_string_view_unsafe(
227  
        cs_ + offset(id),
237  
        cs_ + offset(id),
228  
        len(id),
238  
        len(id),
229  
        decoded_[id]);
239  
        decoded_[id]);
230  
}
240  
}
231  

241  

232  
// return [first, last) as pct-string
242  
// return [first, last) as pct-string
233  
pct_string_view
243  
pct_string_view
234  
url_impl::
244  
url_impl::
235  
pct_get(
245  
pct_get(
236  
    int first,
246  
    int first,
237  
    int last) const noexcept
247  
    int last) const noexcept
238  
{
248  
{
239  
    auto const pos = offset(first);
249  
    auto const pos = offset(first);
240  
    std::size_t n = 0;
250  
    std::size_t n = 0;
241  
    for(auto i = first; i < last;)
251  
    for(auto i = first; i < last;)
242  
        n += decoded_[i++];
252  
        n += decoded_[i++];
243  
    return make_pct_string_view_unsafe(
253  
    return make_pct_string_view_unsafe(
244  
        cs_ + pos,
254  
        cs_ + pos,
245  
        offset(last) - pos,
255  
        offset(last) - pos,
246  
        n);
256  
        n);
247  
}
257  
}
248  

258  

249  
//------------------------------------------------
259  
//------------------------------------------------
250  

260  

251  
// change id to size n
261  
// change id to size n
252  
void
262  
void
253  
url_impl::
263  
url_impl::
254  
set_size(
264  
set_size(
255  
    int id,
265  
    int id,
256  
    std::size_t n) noexcept
266  
    std::size_t n) noexcept
257  
{
267  
{
258 -
    auto d = n - len(id);
268 +
    auto const cur = len(id);
 
269 +
    if(n >= cur)
 
270 +
    {
 
271 +
        auto const d = n - cur;
 
272 +
        for(auto i = id + 1;
 
273 +
            i <= id_end; ++i)
 
274 +
            offset_[i] += detail::to_size_type(d);
 
275 +
        return;
 
276 +
    }
 
277 +
    auto const d = cur - n;
259  
    for(auto i = id + 1;
278  
    for(auto i = id + 1;
260  
        i <= id_end; ++i)
279  
        i <= id_end; ++i)
261 -
        offset_[i] += d;
280 +
        offset_[i] -= detail::to_size_type(d);
262  
}
281  
}
263  

282  

264  
// trim id to size n,
283  
// trim id to size n,
265  
// moving excess into id+1
284  
// moving excess into id+1
266  
void
285  
void
267  
url_impl::
286  
url_impl::
268  
split(
287  
split(
269  
    int id,
288  
    int id,
270  
    std::size_t n) noexcept
289  
    std::size_t n) noexcept
271  
{
290  
{
272  
    BOOST_ASSERT(id < id_end - 1);
291  
    BOOST_ASSERT(id < id_end - 1);
273  
    //BOOST_ASSERT(n <= len(id));
292  
    //BOOST_ASSERT(n <= len(id));
274 -
    offset_[id + 1] = offset(id) + n;
293 +
    offset_[id + 1] = detail::to_size_type(
 
294 +
        offset(id) + n);
275  
}
295  
}
276  

296  

277  
// add n to [first, last]
297  
// add n to [first, last]
278  
void
298  
void
279  
url_impl::
299  
url_impl::
280  
adjust_right(
300  
adjust_right(
281  
    int first,
301  
    int first,
282  
    int last,
302  
    int last,
283  
    std::size_t n) noexcept
303  
    std::size_t n) noexcept
284  
{
304  
{
285  
    for(int i = first;
305  
    for(int i = first;
286  
            i <= last; ++i)
306  
            i <= last; ++i)
287 -
        offset_[i] += n;
307 +
        offset_[i] += detail::to_size_type(n);
288  
}
308  
}
289  

309  

290  
// remove n from [first, last]
310  
// remove n from [first, last]
291  
void
311  
void
292  
url_impl::
312  
url_impl::
293  
adjust_left(
313  
adjust_left(
294  
    int first,
314  
    int first,
295  
    int last,
315  
    int last,
296  
    std::size_t n) noexcept
316  
    std::size_t n) noexcept
297  
{
317  
{
298  
    for(int i = first;
318  
    for(int i = first;
299  
            i <= last; ++i)
319  
            i <= last; ++i)
300 -
        offset_[i] -= n;
320 +
        offset_[i] -= detail::to_size_type(n);
301  
}
321  
}
302  

322  

303  
// set [first, last) offset
323  
// set [first, last) offset
304  
void
324  
void
305  
url_impl::
325  
url_impl::
306  
collapse(
326  
collapse(
307  
    int first,
327  
    int first,
308  
    int last,
328  
    int last,
309  
    std::size_t n) noexcept
329  
    std::size_t n) noexcept
310  
{
330  
{
311  
    for(int i = first + 1;
331  
    for(int i = first + 1;
312  
            i < last; ++i)
332  
            i < last; ++i)
313 -
        offset_[i] = n;
333 +
        offset_[i] = detail::to_size_type(n);
314  
}
334  
}
315  

335  

316  

336  

317  
//------------------------------------------------
337  
//------------------------------------------------
318  
//
338  
//
319  
// path_ref
339  
// path_ref
320  
//
340  
//
321  
//------------------------------------------------
341  
//------------------------------------------------
322  

342  

323  
path_ref::
343  
path_ref::
324  
path_ref(
344  
path_ref(
325  
    url_impl const& impl) noexcept
345  
    url_impl const& impl) noexcept
326  
{
346  
{
327  
    if(impl.from_ == url_impl::from::url)
347  
    if(impl.from_ == url_impl::from::url)
328  
    {
348  
    {
329  
        impl_ = &impl;
349  
        impl_ = &impl;
330  
    }
350  
    }
331  
    else
351  
    else
332  
    {
352  
    {
333  
        core::string_view s = impl.get(id_path);
353  
        core::string_view s = impl.get(id_path);
334  
        data_ = s.data();
354  
        data_ = s.data();
335  
        size_ = s.size();
355  
        size_ = s.size();
336  
        nseg_ = impl.nseg_;
356  
        nseg_ = impl.nseg_;
337  
        dn_ = impl.decoded_[id_path];
357  
        dn_ = impl.decoded_[id_path];
338  
    }
358  
    }
339  
}
359  
}
340  

360  

341  
path_ref::
361  
path_ref::
342  
path_ref(
362  
path_ref(
343  
    core::string_view s,
363  
    core::string_view s,
344  
    std::size_t dn,
364  
    std::size_t dn,
345  
    std::size_t nseg) noexcept
365  
    std::size_t nseg) noexcept
346  
    : data_(s.data())
366  
    : data_(s.data())
347  
    , size_(s.size())
367  
    , size_(s.size())
348  
    , nseg_(nseg)
368  
    , nseg_(nseg)
349  
    , dn_(dn)
369  
    , dn_(dn)
350  
{
370  
{
351  
}
371  
}
352  

372  

353  
pct_string_view
373  
pct_string_view
354  
path_ref::
374  
path_ref::
355  
buffer() const noexcept
375  
buffer() const noexcept
356  
{
376  
{
357  
    if(impl_)
377  
    if(impl_)
358  
        return make_pct_string_view_unsafe(
378  
        return make_pct_string_view_unsafe(
359  
            impl_->cs_ +
379  
            impl_->cs_ +
360  
                impl_->offset(id_path),
380  
                impl_->offset(id_path),
361  
            impl_->len(id_path),
381  
            impl_->len(id_path),
362  
            impl_->decoded_[id_path]);
382  
            impl_->decoded_[id_path]);
363  
    return make_pct_string_view_unsafe(
383  
    return make_pct_string_view_unsafe(
364  
        data_, size_, dn_);
384  
        data_, size_, dn_);
365  
}
385  
}
366  

386  

367  
std::size_t
387  
std::size_t
368  
path_ref::
388  
path_ref::
369  
size() const noexcept
389  
size() const noexcept
370  
{
390  
{
371  
    if(impl_)
391  
    if(impl_)
372  
        return impl_->len(id_path);
392  
        return impl_->len(id_path);
373  
    return size_;
393  
    return size_;
374  
}
394  
}
375  

395  

376  
char const*
396  
char const*
377  
path_ref::
397  
path_ref::
378  
data() const noexcept
398  
data() const noexcept
379  
{
399  
{
380  
    if(impl_)
400  
    if(impl_)
381  
        return impl_->cs_ +
401  
        return impl_->cs_ +
382  
            impl_->offset(id_path);
402  
            impl_->offset(id_path);
383  
    return data_;
403  
    return data_;
384  
}
404  
}
385  

405  

386  
char const*
406  
char const*
387  
path_ref::
407  
path_ref::
388  
end() const noexcept
408  
end() const noexcept
389  
{
409  
{
390  
    if(impl_)
410  
    if(impl_)
391  
        return impl_->cs_ +
411  
        return impl_->cs_ +
392  
            impl_->offset(id_query);
412  
            impl_->offset(id_query);
393  
    return data_ + size_;
413  
    return data_ + size_;
394  
}
414  
}
395  

415  

396  
std::size_t
416  
std::size_t
397  
path_ref::
417  
path_ref::
398  
nseg() const noexcept
418  
nseg() const noexcept
399  
{
419  
{
400  
    if(impl_)
420  
    if(impl_)
401  
        return impl_->nseg_;
421  
        return impl_->nseg_;
402  
    return nseg_;
422  
    return nseg_;
403  
}
423  
}
404  

424  

405  
std::size_t
425  
std::size_t
406  
path_ref::
426  
path_ref::
407  
decoded_size() const noexcept
427  
decoded_size() const noexcept
408  
{
428  
{
409  
    if(impl_)
429  
    if(impl_)
410  
        return impl_->decoded_[id_path];
430  
        return impl_->decoded_[id_path];
411  
    return dn_;
431  
    return dn_;
412  
}
432  
}
413  

433  

414  
//------------------------------------------------
434  
//------------------------------------------------
415  
//
435  
//
416  
// query_ref
436  
// query_ref
417  
//
437  
//
418  
//------------------------------------------------
438  
//------------------------------------------------
419  

439  

420  
query_ref::
440  
query_ref::
421  
query_ref(
441  
query_ref(
422  
    core::string_view s,
442  
    core::string_view s,
423  
    std::size_t dn,
443  
    std::size_t dn,
424  
    std::size_t nparam) noexcept
444  
    std::size_t nparam) noexcept
425  
    : data_(s.data())
445  
    : data_(s.data())
426  
    , size_(s.size())
446  
    , size_(s.size())
427  
    , nparam_(nparam)
447  
    , nparam_(nparam)
428  
    , dn_(dn)
448  
    , dn_(dn)
429  
{
449  
{
430  
}
450  
}
431  

451  

432  
query_ref::
452  
query_ref::
433  
query_ref(
453  
query_ref(
434  
    url_impl const& impl) noexcept
454  
    url_impl const& impl) noexcept
435  
{
455  
{
436  
    if(impl.from_ == url_impl::from::url)
456  
    if(impl.from_ == url_impl::from::url)
437  
    {
457  
    {
438  
        impl_ = &impl;
458  
        impl_ = &impl;
439  
    }
459  
    }
440  
    else
460  
    else
441  
    {
461  
    {
442  
        core::string_view s = impl.get(id_query);
462  
        core::string_view s = impl.get(id_query);
443  
        if (!s.empty())
463  
        if (!s.empty())
444  
        {
464  
        {
445  
            s.remove_prefix(1);
465  
            s.remove_prefix(1);
446  
            question_mark_ = true;
466  
            question_mark_ = true;
447  
        }
467  
        }
448  
        data_ = s.data();
468  
        data_ = s.data();
449  
        size_ = s.size();
469  
        size_ = s.size();
450  
        nparam_ = impl.nparam_;
470  
        nparam_ = impl.nparam_;
451  
        dn_ = impl.decoded_[id_query];
471  
        dn_ = impl.decoded_[id_query];
452  
    }
472  
    }
453  
}
473  
}
454  

474  

455  
pct_string_view
475  
pct_string_view
456  
query_ref::
476  
query_ref::
457  
buffer() const noexcept
477  
buffer() const noexcept
458  
{
478  
{
459  
    if(impl_)
479  
    if(impl_)
460  
    {
480  
    {
461  
        auto pos = impl_->offset_[id_query];
481  
        auto pos = impl_->offset_[id_query];
462  
        auto pos1 = impl_->offset_[id_frag];
482  
        auto pos1 = impl_->offset_[id_frag];
463  
        if(pos < pos1)
483  
        if(pos < pos1)
464  
        {
484  
        {
465  
            ++pos; // no '?'
485  
            ++pos; // no '?'
466  
            return make_pct_string_view_unsafe(
486  
            return make_pct_string_view_unsafe(
467  
                impl_->cs_ + pos,
487  
                impl_->cs_ + pos,
468  
                pos1 - pos,
488  
                pos1 - pos,
469  
                impl_->decoded_[id_query]);
489  
                impl_->decoded_[id_query]);
470  
        }
490  
        }
471  
        // empty
491  
        // empty
472  
        return make_pct_string_view_unsafe(
492  
        return make_pct_string_view_unsafe(
473  
            impl_->cs_ + pos,
493  
            impl_->cs_ + pos,
474  
            0,
494  
            0,
475  
            0);
495  
            0);
476  
    }
496  
    }
477  
    // no '?'
497  
    // no '?'
478  
    return make_pct_string_view_unsafe(
498  
    return make_pct_string_view_unsafe(
479  
        data_, size_, dn_);
499  
        data_, size_, dn_);
480  
}
500  
}
481  

501  

482  
// with '?'
502  
// with '?'
483  
std::size_t
503  
std::size_t
484  
query_ref::
504  
query_ref::
485  
size() const noexcept
505  
size() const noexcept
486  
{
506  
{
487  
    if(impl_)
507  
    if(impl_)
488  
        return impl_->len(id_query);
508  
        return impl_->len(id_query);
489  
    if(size_ > 0)
509  
    if(size_ > 0)
490  
        return size_ + 1;
510  
        return size_ + 1;
491  
    return question_mark_;
511  
    return question_mark_;
492  
}
512  
}
493  

513  

494  
// no '?'
514  
// no '?'
495  
char const*
515  
char const*
496  
query_ref::
516  
query_ref::
497  
begin() const noexcept
517  
begin() const noexcept
498  
{
518  
{
499  
    if(impl_)
519  
    if(impl_)
500  
    {
520  
    {
501  
        // using the offset array here
521  
        // using the offset array here
502  
        auto pos = impl_->offset_[id_query];
522  
        auto pos = impl_->offset_[id_query];
503  
        auto pos1 = impl_->offset_[id_frag];
523  
        auto pos1 = impl_->offset_[id_frag];
504  
        if(pos < pos1)
524  
        if(pos < pos1)
505  
            return impl_->cs_ + pos + 1; // no '?'
525  
            return impl_->cs_ + pos + 1; // no '?'
506  
        // empty
526  
        // empty
507  
        return impl_->cs_ + pos;
527  
        return impl_->cs_ + pos;
508  
    }
528  
    }
509  
    return data_;
529  
    return data_;
510  

530  

511  
}
531  
}
512  

532  

513  
char const*
533  
char const*
514  
query_ref::
534  
query_ref::
515  
end() const noexcept
535  
end() const noexcept
516  
{
536  
{
517  
    if(impl_)
537  
    if(impl_)
518  
        return impl_->cs_ +
538  
        return impl_->cs_ +
519  
            impl_->offset(id_frag);
539  
            impl_->offset(id_frag);
520  
    return data_ + size_;
540  
    return data_ + size_;
521  
}
541  
}
522  

542  

523  
std::size_t
543  
std::size_t
524  
query_ref::
544  
query_ref::
525  
nparam() const noexcept
545  
nparam() const noexcept
526  
{
546  
{
527  
    if(impl_)
547  
    if(impl_)
528  
        return impl_->nparam_;
548  
        return impl_->nparam_;
529  
    return nparam_;
549  
    return nparam_;
530  
}
550  
}
531  

551  

532  
#if defined(__GNUC__) && ! defined(__clang__) && defined(__MINGW32__)
552  
#if defined(__GNUC__) && ! defined(__clang__) && defined(__MINGW32__)
533  
#pragma GCC diagnostic pop
553  
#pragma GCC diagnostic pop
534  
#endif
554  
#endif
535  

555  

536  
} // detail
556  
} // detail
537  
} // urls
557  
} // urls
538  
} // boost
558  
} // boost