1  
//
1  
//
2  
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
3  
// Copyright (c) 2023 Alan de Freitas (alandefreitas@gmail.com)
3  
// Copyright (c) 2023 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_DETAIL_IMPL_URL_IMPL_HPP
11  
#ifndef BOOST_URL_DETAIL_IMPL_URL_IMPL_HPP
12  
#define BOOST_URL_DETAIL_IMPL_URL_IMPL_HPP
12  
#define BOOST_URL_DETAIL_IMPL_URL_IMPL_HPP
13  

13  

14  
#include <boost/url/detail/config.hpp>
14  
#include <boost/url/detail/config.hpp>
15  
#include <boost/url/detail/memcpy.hpp>
15  
#include <boost/url/detail/memcpy.hpp>
16  
#include <boost/url/detail/path.hpp>
16  
#include <boost/url/detail/path.hpp>
17  
#include <boost/url/detail/url_impl.hpp>
17  
#include <boost/url/detail/url_impl.hpp>
18  
#include <boost/url/scheme.hpp>
18  
#include <boost/url/scheme.hpp>
19  
#include <boost/assert.hpp>
19  
#include <boost/assert.hpp>
20  
#include <cstring>
20  
#include <cstring>
21  

21  

22  
namespace boost {
22  
namespace boost {
23  
namespace urls {
23  
namespace urls {
24  
namespace detail {
24  
namespace detail {
25  

25  

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

31  

32  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
32  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
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  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
42  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
43  
void
43  
void
44  
url_impl::
44  
url_impl::
45  
apply_userinfo(
45  
apply_userinfo(
46  
    pct_string_view const& user,
46  
    pct_string_view const& user,
47  
    pct_string_view const* pass) noexcept
47  
    pct_string_view const* pass) noexcept
48  
{
48  
{
49  
    // this function is for
49  
    // this function is for
50  
    // authority_view_rule only
50  
    // authority_view_rule only
51  
    BOOST_ASSERT(from_ == from::authority);
51  
    BOOST_ASSERT(from_ == from::authority);
52  

52  

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

72  

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

84  

85  
    // host, port
85  
    // host, port
86  
    host_type_ = ht;
86  
    host_type_ = ht;
87  
    set_size(id_host, s.size());
87  
    set_size(id_host, s.size());
88  
    decoded_[id_host] =
88  
    decoded_[id_host] =
89  
        detail::to_size_type(
89  
        detail::to_size_type(
90  
            s.decoded_size());
90  
            s.decoded_size());
91  
    detail::memcpy(
91  
    detail::memcpy(
92  
        ip_addr_,
92  
        ip_addr_,
93  
        addr,
93  
        addr,
94  
        sizeof(ip_addr_));
94  
        sizeof(ip_addr_));
95  
}
95  
}
96  

96  

97  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
97  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
98  
void
98  
void
99  
url_impl::
99  
url_impl::
100  
apply_port(
100  
apply_port(
101  
    core::string_view s,
101  
    core::string_view s,
102  
    unsigned short pn) noexcept
102  
    unsigned short pn) noexcept
103  
{
103  
{
104  
    // this function is for
104  
    // this function is for
105  
    // authority_view_rule only
105  
    // authority_view_rule only
106  
    BOOST_ASSERT(from_ == from::authority);
106  
    BOOST_ASSERT(from_ == from::authority);
107  

107  

108  
    port_number_ = pn;
108  
    port_number_ = pn;
109  
    set_size(id_port, 1 + s.size());
109  
    set_size(id_port, 1 + s.size());
110  
}
110  
}
111  

111  

112  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
112  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
113  
void
113  
void
114  
url_impl::
114  
url_impl::
115  
apply_authority(
115  
apply_authority(
116  
    url_impl const& a) noexcept
116  
    url_impl const& a) noexcept
117  
{
117  
{
118  
    BOOST_ASSERT(from_ != from::authority);
118  
    BOOST_ASSERT(from_ != from::authority);
119  

119  

120  
    // userinfo
120  
    // userinfo
121  
    set_size(id_user,
121  
    set_size(id_user,
122  
        a.len(id_user) +
122  
        a.len(id_user) +
123  
        (from_ == from::authority ? 0 : 2));
123  
        (from_ == from::authority ? 0 : 2));
124  
    set_size(id_pass, a.len(id_pass));
124  
    set_size(id_pass, a.len(id_pass));
125  
    decoded_[id_user] = a.decoded_[id_user];
125  
    decoded_[id_user] = a.decoded_[id_user];
126  
    decoded_[id_pass] = a.decoded_[id_pass];
126  
    decoded_[id_pass] = a.decoded_[id_pass];
127  

127  

128  
    // host, port
128  
    // host, port
129  
    host_type_ = a.host_type_;
129  
    host_type_ = a.host_type_;
130  
    port_number_ = a.port_number_;
130  
    port_number_ = a.port_number_;
131  
    set_size(id_host, a.len(id_host));
131  
    set_size(id_host, a.len(id_host));
132  
    set_size(id_port, a.len(id_port));
132  
    set_size(id_port, a.len(id_port));
133  
    detail::memcpy(
133  
    detail::memcpy(
134  
        ip_addr_,
134  
        ip_addr_,
135  
        a.ip_addr_,
135  
        a.ip_addr_,
136  
        sizeof(ip_addr_));
136  
        sizeof(ip_addr_));
137  
    decoded_[id_host] = a.decoded_[id_host];
137  
    decoded_[id_host] = a.decoded_[id_host];
138  
}
138  
}
139  

139  

140  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
140  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
141  
void
141  
void
142  
url_impl::
142  
url_impl::
143  
apply_path(
143  
apply_path(
144  
    pct_string_view s,
144  
    pct_string_view s,
145  
    std::size_t nseg) noexcept
145  
    std::size_t nseg) noexcept
146  
{
146  
{
147  
    set_size(id_path, s.size());
147  
    set_size(id_path, s.size());
148  
    decoded_[id_path] =
148  
    decoded_[id_path] =
149  
        detail::to_size_type(
149  
        detail::to_size_type(
150  
            s.decoded_size());
150  
            s.decoded_size());
151  
    nseg_ = detail::to_size_type(
151  
    nseg_ = detail::to_size_type(
152  
        detail::path_segments(s, nseg));
152  
        detail::path_segments(s, nseg));
153  
}
153  
}
154  

154  

155  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
155  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
156  
void
156  
void
157  
url_impl::
157  
url_impl::
158  
apply_query(
158  
apply_query(
159  
    pct_string_view s,
159  
    pct_string_view s,
160  
    std::size_t n) noexcept
160  
    std::size_t n) noexcept
161  
{
161  
{
162  
    nparam_ = detail::to_size_type(n);
162  
    nparam_ = detail::to_size_type(n);
163  
    set_size(id_query, 1 + s.size());
163  
    set_size(id_query, 1 + s.size());
164  
    decoded_[id_query] =
164  
    decoded_[id_query] =
165  
        detail::to_size_type(
165  
        detail::to_size_type(
166  
            s.decoded_size());
166  
            s.decoded_size());
167  
}
167  
}
168  

168  

169  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
169  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
170  
void
170  
void
171  
url_impl::
171  
url_impl::
172  
apply_frag(
172  
apply_frag(
173  
    pct_string_view s) noexcept
173  
    pct_string_view s) noexcept
174  
{
174  
{
175  
    set_size(id_frag, s.size() + 1);
175  
    set_size(id_frag, s.size() + 1);
176  
    decoded_[id_frag] =
176  
    decoded_[id_frag] =
177  
        detail::to_size_type(
177  
        detail::to_size_type(
178  
            s.decoded_size());
178  
            s.decoded_size());
179  
}
179  
}
180  

180  

181  
// return length of [first, last)
181  
// return length of [first, last)
182  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
182  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
183  
std::size_t
183  
std::size_t
184  
url_impl::
184  
url_impl::
185  
len(
185  
len(
186  
    int first,
186  
    int first,
187  
    int last) const noexcept
187  
    int last) const noexcept
188  
{
188  
{
189  
    BOOST_ASSERT(first <= last);
189  
    BOOST_ASSERT(first <= last);
190  
    BOOST_ASSERT(last <= id_end);
190  
    BOOST_ASSERT(last <= id_end);
191  
    return offset(last) - offset(first);
191  
    return offset(last) - offset(first);
192  
}
192  
}
193  

193  

194  
// return length of part
194  
// return length of part
195  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
195  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
196  
std::size_t
196  
std::size_t
197  
url_impl::
197  
url_impl::
198  
len(int id) const noexcept
198  
len(int id) const noexcept
199  
{
199  
{
200  
    return id == id_end
200  
    return id == id_end
201  
        ? zero_
201  
        ? zero_
202  
        : ( offset(id + 1) -
202  
        : ( offset(id + 1) -
203  
            offset(id) );
203  
            offset(id) );
204  
}
204  
}
205  

205  

206  
// return offset of id
206  
// return offset of id
207  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
207  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
208  
std::size_t
208  
std::size_t
209  
url_impl::
209  
url_impl::
210  
offset(int id) const noexcept
210  
offset(int id) const noexcept
211  
{
211  
{
212  
    return
212  
    return
213  
        id == id_scheme
213  
        id == id_scheme
214  
        ? zero_
214  
        ? zero_
215  
        : offset_[id];
215  
        : offset_[id];
216  
}
216  
}
217  

217  

218  
// return id as string
218  
// return id as string
219  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
219  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
220  
core::string_view
220  
core::string_view
221  
url_impl::
221  
url_impl::
222  
get(int id) const noexcept
222  
get(int id) const noexcept
223  
{
223  
{
224  
    return {
224  
    return {
225  
        cs_ + offset(id), len(id) };
225  
        cs_ + offset(id), len(id) };
226  
}
226  
}
227  

227  

228  
// return [first, last) as string
228  
// return [first, last) as string
229  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
229  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
230  
core::string_view
230  
core::string_view
231  
url_impl::
231  
url_impl::
232  
get(int first,
232  
get(int first,
233  
    int last) const noexcept
233  
    int last) const noexcept
234  
{
234  
{
235  
    return { cs_ + offset(first),
235  
    return { cs_ + offset(first),
236  
        offset(last) - offset(first) };
236  
        offset(last) - offset(first) };
237  
}
237  
}
238  

238  

239  
// return id as pct-string
239  
// return id as pct-string
240  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
240  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
241  
pct_string_view
241  
pct_string_view
242  
url_impl::
242  
url_impl::
243  
pct_get(
243  
pct_get(
244  
    int id) const noexcept
244  
    int id) const noexcept
245  
{
245  
{
246  
    return make_pct_string_view_unsafe(
246  
    return make_pct_string_view_unsafe(
247  
        cs_ + offset(id),
247  
        cs_ + offset(id),
248  
        len(id),
248  
        len(id),
249  
        decoded_[id]);
249  
        decoded_[id]);
250  
}
250  
}
251  

251  

252  
// return [first, last) as pct-string
252  
// return [first, last) as pct-string
253  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
253  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
254  
pct_string_view
254  
pct_string_view
255  
url_impl::
255  
url_impl::
256  
pct_get(
256  
pct_get(
257  
    int first,
257  
    int first,
258  
    int last) const noexcept
258  
    int last) const noexcept
259  
{
259  
{
260  
    auto const pos = offset(first);
260  
    auto const pos = offset(first);
261  
    std::size_t n = 0;
261  
    std::size_t n = 0;
262  
    for(auto i = first; i < last;)
262  
    for(auto i = first; i < last;)
263  
        n += decoded_[i++];
263  
        n += decoded_[i++];
264  
    return make_pct_string_view_unsafe(
264  
    return make_pct_string_view_unsafe(
265  
        cs_ + pos,
265  
        cs_ + pos,
266  
        offset(last) - pos,
266  
        offset(last) - pos,
267  
        n);
267  
        n);
268  
}
268  
}
269  

269  

270  
//------------------------------------------------
270  
//------------------------------------------------
271  

271  

272  
// change id to size n
272  
// change id to size n
273  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
273  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
274  
void
274  
void
275  
url_impl::
275  
url_impl::
276  
set_size(
276  
set_size(
277  
    int id,
277  
    int id,
278  
    std::size_t n) noexcept
278  
    std::size_t n) noexcept
279  
{
279  
{
280  
    auto const cur = len(id);
280  
    auto const cur = len(id);
281  
    if(n >= cur)
281  
    if(n >= cur)
282  
    {
282  
    {
283  
        auto const d = n - cur;
283  
        auto const d = n - cur;
284  
        for(auto i = id + 1;
284  
        for(auto i = id + 1;
285  
            i <= id_end; ++i)
285  
            i <= id_end; ++i)
286  
            offset_[i] += detail::to_size_type(d);
286  
            offset_[i] += detail::to_size_type(d);
287  
        return;
287  
        return;
288  
    }
288  
    }
289  
    auto const d = cur - n;
289  
    auto const d = cur - n;
290  
    for(auto i = id + 1;
290  
    for(auto i = id + 1;
291  
        i <= id_end; ++i)
291  
        i <= id_end; ++i)
292  
        offset_[i] -= detail::to_size_type(d);
292  
        offset_[i] -= detail::to_size_type(d);
293  
}
293  
}
294  

294  

295  
// trim id to size n,
295  
// trim id to size n,
296  
// moving excess into id+1
296  
// moving excess into id+1
297  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
297  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
298  
void
298  
void
299  
url_impl::
299  
url_impl::
300  
split(
300  
split(
301  
    int id,
301  
    int id,
302  
    std::size_t n) noexcept
302  
    std::size_t n) noexcept
303  
{
303  
{
304  
    BOOST_ASSERT(id < id_end - 1);
304  
    BOOST_ASSERT(id < id_end - 1);
305  
    //BOOST_ASSERT(n <= len(id));
305  
    //BOOST_ASSERT(n <= len(id));
306  
    offset_[id + 1] = detail::to_size_type(
306  
    offset_[id + 1] = detail::to_size_type(
307  
        offset(id) + n);
307  
        offset(id) + n);
308  
}
308  
}
309  

309  

310  
// add n to [first, last]
310  
// add n to [first, last]
311  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
311  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
312  
void
312  
void
313  
url_impl::
313  
url_impl::
314  
adjust_right(
314  
adjust_right(
315  
    int first,
315  
    int first,
316  
    int last,
316  
    int last,
317  
    std::size_t n) noexcept
317  
    std::size_t n) noexcept
318  
{
318  
{
319  
    for(int i = first;
319  
    for(int i = first;
320  
            i <= last; ++i)
320  
            i <= last; ++i)
321  
        offset_[i] += detail::to_size_type(n);
321  
        offset_[i] += detail::to_size_type(n);
322  
}
322  
}
323  

323  

324  
// remove n from [first, last]
324  
// remove n from [first, last]
325  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
325  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
326  
void
326  
void
327  
url_impl::
327  
url_impl::
328  
adjust_left(
328  
adjust_left(
329  
    int first,
329  
    int first,
330  
    int last,
330  
    int last,
331  
    std::size_t n) noexcept
331  
    std::size_t n) noexcept
332  
{
332  
{
333  
    for(int i = first;
333  
    for(int i = first;
334  
            i <= last; ++i)
334  
            i <= last; ++i)
335  
        offset_[i] -= detail::to_size_type(n);
335  
        offset_[i] -= detail::to_size_type(n);
336  
}
336  
}
337  

337  

338  
// set [first, last) offset
338  
// set [first, last) offset
339  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
339  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
340  
void
340  
void
341  
url_impl::
341  
url_impl::
342  
collapse(
342  
collapse(
343  
    int first,
343  
    int first,
344  
    int last,
344  
    int last,
345  
    std::size_t n) noexcept
345  
    std::size_t n) noexcept
346  
{
346  
{
347  
    for(int i = first + 1;
347  
    for(int i = first + 1;
348  
            i < last; ++i)
348  
            i < last; ++i)
349  
        offset_[i] = detail::to_size_type(n);
349  
        offset_[i] = detail::to_size_type(n);
350  
}
350  
}
351  

351  

352  

352  

353  
//------------------------------------------------
353  
//------------------------------------------------
354  
//
354  
//
355  
// path_ref
355  
// path_ref
356  
//
356  
//
357  
//------------------------------------------------
357  
//------------------------------------------------
358  

358  

359  
inline
359  
inline
360  
path_ref::
360  
path_ref::
361  
path_ref(
361  
path_ref(
362  
    url_impl const& impl) noexcept
362  
    url_impl const& impl) noexcept
363  
{
363  
{
364  
    if(impl.from_ == url_impl::from::url)
364  
    if(impl.from_ == url_impl::from::url)
365  
    {
365  
    {
366  
        impl_ = &impl;
366  
        impl_ = &impl;
367  
    }
367  
    }
368  
    else
368  
    else
369  
    {
369  
    {
370  
        core::string_view s = impl.get(id_path);
370  
        core::string_view s = impl.get(id_path);
371  
        data_ = s.data();
371  
        data_ = s.data();
372  
        size_ = s.size();
372  
        size_ = s.size();
373  
        nseg_ = impl.nseg_;
373  
        nseg_ = impl.nseg_;
374  
        dn_ = impl.decoded_[id_path];
374  
        dn_ = impl.decoded_[id_path];
375  
    }
375  
    }
376  
}
376  
}
377  

377  

378  
inline
378  
inline
379  
path_ref::
379  
path_ref::
380  
path_ref(
380  
path_ref(
381  
    core::string_view s,
381  
    core::string_view s,
382  
    std::size_t dn,
382  
    std::size_t dn,
383  
    std::size_t nseg) noexcept
383  
    std::size_t nseg) noexcept
384  
    : data_(s.data())
384  
    : data_(s.data())
385  
    , size_(s.size())
385  
    , size_(s.size())
386  
    , nseg_(nseg)
386  
    , nseg_(nseg)
387  
    , dn_(dn)
387  
    , dn_(dn)
388  
{
388  
{
389  
}
389  
}
390  

390  

391  
inline
391  
inline
392  
pct_string_view
392  
pct_string_view
393  
path_ref::
393  
path_ref::
394  
buffer() const noexcept
394  
buffer() const noexcept
395  
{
395  
{
396  
    if(impl_)
396  
    if(impl_)
397  
        return make_pct_string_view_unsafe(
397  
        return make_pct_string_view_unsafe(
398  
            impl_->cs_ +
398  
            impl_->cs_ +
399  
                impl_->offset(id_path),
399  
                impl_->offset(id_path),
400  
            impl_->len(id_path),
400  
            impl_->len(id_path),
401  
            impl_->decoded_[id_path]);
401  
            impl_->decoded_[id_path]);
402  
    return make_pct_string_view_unsafe(
402  
    return make_pct_string_view_unsafe(
403  
        data_, size_, dn_);
403  
        data_, size_, dn_);
404  
}
404  
}
405  

405  

406  
inline
406  
inline
407  
std::size_t
407  
std::size_t
408  
path_ref::
408  
path_ref::
409  
size() const noexcept
409  
size() const noexcept
410  
{
410  
{
411  
    if(impl_)
411  
    if(impl_)
412  
        return impl_->len(id_path);
412  
        return impl_->len(id_path);
413  
    return size_;
413  
    return size_;
414  
}
414  
}
415  

415  

416  
inline
416  
inline
417  
char const*
417  
char const*
418  
path_ref::
418  
path_ref::
419  
data() const noexcept
419  
data() const noexcept
420  
{
420  
{
421  
    if(impl_)
421  
    if(impl_)
422  
        return impl_->cs_ +
422  
        return impl_->cs_ +
423  
            impl_->offset(id_path);
423  
            impl_->offset(id_path);
424  
    return data_;
424  
    return data_;
425  
}
425  
}
426  

426  

427  
inline
427  
inline
428  
char const*
428  
char const*
429  
path_ref::
429  
path_ref::
430  
end() const noexcept
430  
end() const noexcept
431  
{
431  
{
432  
    if(impl_)
432  
    if(impl_)
433  
        return impl_->cs_ +
433  
        return impl_->cs_ +
434  
            impl_->offset(id_query);
434  
            impl_->offset(id_query);
435  
    return data_ + size_;
435  
    return data_ + size_;
436  
}
436  
}
437  

437  

438  
inline
438  
inline
439  
std::size_t
439  
std::size_t
440  
path_ref::
440  
path_ref::
441  
nseg() const noexcept
441  
nseg() const noexcept
442  
{
442  
{
443  
    if(impl_)
443  
    if(impl_)
444  
        return impl_->nseg_;
444  
        return impl_->nseg_;
445  
    return nseg_;
445  
    return nseg_;
446  
}
446  
}
447  

447  

448  
inline
448  
inline
449  
std::size_t
449  
std::size_t
450  
path_ref::
450  
path_ref::
451  
decoded_size() const noexcept
451  
decoded_size() const noexcept
452  
{
452  
{
453  
    if(impl_)
453  
    if(impl_)
454  
        return impl_->decoded_[id_path];
454  
        return impl_->decoded_[id_path];
455  
    return dn_;
455  
    return dn_;
456  
}
456  
}
457  

457  

458  
//------------------------------------------------
458  
//------------------------------------------------
459  
//
459  
//
460  
// query_ref
460  
// query_ref
461  
//
461  
//
462  
//------------------------------------------------
462  
//------------------------------------------------
463  

463  

464  
inline
464  
inline
465  
query_ref::
465  
query_ref::
466  
query_ref(
466  
query_ref(
467  
    core::string_view s,
467  
    core::string_view s,
468  
    std::size_t dn,
468  
    std::size_t dn,
469  
    std::size_t nparam) noexcept
469  
    std::size_t nparam) noexcept
470  
    : data_(s.data())
470  
    : data_(s.data())
471  
    , size_(s.size())
471  
    , size_(s.size())
472  
    , nparam_(nparam)
472  
    , nparam_(nparam)
473  
    , dn_(dn)
473  
    , dn_(dn)
474  
{
474  
{
475  
}
475  
}
476  

476  

477  
inline
477  
inline
478  
query_ref::
478  
query_ref::
479  
query_ref(
479  
query_ref(
480  
    url_impl const& impl) noexcept
480  
    url_impl const& impl) noexcept
481  
{
481  
{
482  
    if(impl.from_ == url_impl::from::url)
482  
    if(impl.from_ == url_impl::from::url)
483  
    {
483  
    {
484  
        impl_ = &impl;
484  
        impl_ = &impl;
485  
    }
485  
    }
486  
    else
486  
    else
487  
    {
487  
    {
488  
        core::string_view s = impl.get(id_query);
488  
        core::string_view s = impl.get(id_query);
489  
        if (!s.empty())
489  
        if (!s.empty())
490  
        {
490  
        {
491  
            s.remove_prefix(1);
491  
            s.remove_prefix(1);
492  
            question_mark_ = true;
492  
            question_mark_ = true;
493  
        }
493  
        }
494  
        data_ = s.data();
494  
        data_ = s.data();
495  
        size_ = s.size();
495  
        size_ = s.size();
496  
        nparam_ = impl.nparam_;
496  
        nparam_ = impl.nparam_;
497  
        dn_ = impl.decoded_[id_query];
497  
        dn_ = impl.decoded_[id_query];
498  
    }
498  
    }
499  
}
499  
}
500  

500  

501  
inline
501  
inline
502  
pct_string_view
502  
pct_string_view
503  
query_ref::
503  
query_ref::
504  
buffer() const noexcept
504  
buffer() const noexcept
505  
{
505  
{
506  
    if(impl_)
506  
    if(impl_)
507  
    {
507  
    {
508  
        auto pos = impl_->offset_[id_query];
508  
        auto pos = impl_->offset_[id_query];
509  
        auto pos1 = impl_->offset_[id_frag];
509  
        auto pos1 = impl_->offset_[id_frag];
510  
        if(pos < pos1)
510  
        if(pos < pos1)
511  
        {
511  
        {
512  
            ++pos; // no '?'
512  
            ++pos; // no '?'
513  
            return make_pct_string_view_unsafe(
513  
            return make_pct_string_view_unsafe(
514  
                impl_->cs_ + pos,
514  
                impl_->cs_ + pos,
515  
                pos1 - pos,
515  
                pos1 - pos,
516  
                impl_->decoded_[id_query]);
516  
                impl_->decoded_[id_query]);
517  
        }
517  
        }
518  
        // empty
518  
        // empty
519  
        return make_pct_string_view_unsafe(
519  
        return make_pct_string_view_unsafe(
520  
            impl_->cs_ + pos,
520  
            impl_->cs_ + pos,
521  
            0,
521  
            0,
522  
            0);
522  
            0);
523  
    }
523  
    }
524  
    // no '?'
524  
    // no '?'
525  
    return make_pct_string_view_unsafe(
525  
    return make_pct_string_view_unsafe(
526  
        data_, size_, dn_);
526  
        data_, size_, dn_);
527  
}
527  
}
528  

528  

529  
// with '?'
529  
// with '?'
530  
inline
530  
inline
531  
std::size_t
531  
std::size_t
532  
query_ref::
532  
query_ref::
533  
size() const noexcept
533  
size() const noexcept
534  
{
534  
{
535  
    if(impl_)
535  
    if(impl_)
536  
        return impl_->len(id_query);
536  
        return impl_->len(id_query);
537  
    if(size_ > 0)
537  
    if(size_ > 0)
538  
        return size_ + 1;
538  
        return size_ + 1;
539  
    return question_mark_;
539  
    return question_mark_;
540  
}
540  
}
541  

541  

542  
// no '?'
542  
// no '?'
543  
inline
543  
inline
544  
char const*
544  
char const*
545  
query_ref::
545  
query_ref::
546  
begin() const noexcept
546  
begin() const noexcept
547  
{
547  
{
548  
    if(impl_)
548  
    if(impl_)
549  
    {
549  
    {
550  
        // using the offset array here
550  
        // using the offset array here
551  
        auto pos = impl_->offset_[id_query];
551  
        auto pos = impl_->offset_[id_query];
552  
        auto pos1 = impl_->offset_[id_frag];
552  
        auto pos1 = impl_->offset_[id_frag];
553  
        if(pos < pos1)
553  
        if(pos < pos1)
554  
            return impl_->cs_ + pos + 1; // no '?'
554  
            return impl_->cs_ + pos + 1; // no '?'
555  
        // empty
555  
        // empty
556  
        return impl_->cs_ + pos;
556  
        return impl_->cs_ + pos;
557  
    }
557  
    }
558  
    return data_;
558  
    return data_;
559  

559  

560  
}
560  
}
561  

561  

562  
inline
562  
inline
563  
char const*
563  
char const*
564  
query_ref::
564  
query_ref::
565  
end() const noexcept
565  
end() const noexcept
566  
{
566  
{
567  
    if(impl_)
567  
    if(impl_)
568  
        return impl_->cs_ +
568  
        return impl_->cs_ +
569  
            impl_->offset(id_frag);
569  
            impl_->offset(id_frag);
570  
    return data_ + size_;
570  
    return data_ + size_;
571  
}
571  
}
572  

572  

573  
inline
573  
inline
574  
std::size_t
574  
std::size_t
575  
query_ref::
575  
query_ref::
576  
nparam() const noexcept
576  
nparam() const noexcept
577  
{
577  
{
578  
    if(impl_)
578  
    if(impl_)
579  
        return impl_->nparam_;
579  
        return impl_->nparam_;
580  
    return nparam_;
580  
    return nparam_;
581  
}
581  
}
582  

582  

583  
} // detail
583  
} // detail
584  
} // urls
584  
} // urls
585  
} // boost
585  
} // boost
586  

586  

587  
#endif
587  
#endif