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/url.hpp>
13  
#include <boost/url/url.hpp>
14  
#include <boost/url/parse.hpp>
14  
#include <boost/url/parse.hpp>
15  
#include <boost/assert.hpp>
15  
#include <boost/assert.hpp>
16  

16  

17  
namespace boost {
17  
namespace boost {
18  
namespace urls {
18  
namespace urls {
19  

19  

20  
//------------------------------------------------
20  
//------------------------------------------------
21  

21  

22  
url::
22  
url::
23  
~url()
23  
~url()
24  
{
24  
{
25  
    if(s_)
25  
    if(s_)
26  
    {
26  
    {
27  
        BOOST_ASSERT(
27  
        BOOST_ASSERT(
28  
            cap_ != 0);
28  
            cap_ != 0);
29  
        deallocate(s_);
29  
        deallocate(s_);
30  
    }
30  
    }
31  
}
31  
}
32  

32  

33  
// construct empty
33  
// construct empty
34  
url::
34  
url::
35  
url() noexcept = default;
35  
url() noexcept = default;
36  

36  

37  
url::
37  
url::
38  
url(core::string_view s)
38  
url(core::string_view s)
39  
    : url(parse_uri_reference(s
39  
    : url(parse_uri_reference(s
40  
        ).value(BOOST_URL_POS))
40  
        ).value(BOOST_URL_POS))
41  
{
41  
{
42  
}
42  
}
43  

43  

44  
url::
44  
url::
45  
url(url&& u) noexcept
45  
url(url&& u) noexcept
46  
    : url_base(u.impl_)
46  
    : url_base(u.impl_)
47  
{
47  
{
48  
    s_ = u.s_;
48  
    s_ = u.s_;
49  
    cap_ = u.cap_;
49  
    cap_ = u.cap_;
50  
    u.s_ = nullptr;
50  
    u.s_ = nullptr;
51  
    u.cap_ = 0;
51  
    u.cap_ = 0;
52  
    u.impl_ = {from::url};
52  
    u.impl_ = {from::url};
53  
}
53  
}
54  

54  

55  
url&
55  
url&
56  
url::
56  
url::
57  
operator=(url&& u) noexcept
57  
operator=(url&& u) noexcept
58  
{
58  
{
59  
    if(s_)
59  
    if(s_)
60  
        deallocate(s_);
60  
        deallocate(s_);
61  
    impl_ = u.impl_;
61  
    impl_ = u.impl_;
62  
    s_ = u.s_;
62  
    s_ = u.s_;
63  
    cap_ = u.cap_;
63  
    cap_ = u.cap_;
64  
    u.s_ = nullptr;
64  
    u.s_ = nullptr;
65  
    u.cap_ = 0;
65  
    u.cap_ = 0;
66  
    u.impl_ = {from::url};
66  
    u.impl_ = {from::url};
67  
    return *this;
67  
    return *this;
68  
}
68  
}
69  

69  

70  
//------------------------------------------------
70  
//------------------------------------------------
71  

71  

72  
char*
72  
char*
73  
url::
73  
url::
74  
allocate(std::size_t n)
74  
allocate(std::size_t n)
75  
{
75  
{
76  
    auto s = new char[n + 1];
76  
    auto s = new char[n + 1];
77  
    cap_ = n;
77  
    cap_ = n;
78  
    return s;
78  
    return s;
79  
}
79  
}
80  

80  

81  
void
81  
void
82  
url::
82  
url::
83  
deallocate(char* s)
83  
deallocate(char* s)
84  
{
84  
{
85  
    delete[] s;
85  
    delete[] s;
86  
}
86  
}
87  

87  

88  
void
88  
void
89  
url::
89  
url::
90  
clear_impl() noexcept
90  
clear_impl() noexcept
91  
{
91  
{
92  
    if(s_)
92  
    if(s_)
93  
    {
93  
    {
94  
        // preserve capacity
94  
        // preserve capacity
95  
        impl_ = {from::url};
95  
        impl_ = {from::url};
96  
        s_[0] = '\0';
96  
        s_[0] = '\0';
97  
        impl_.cs_ = s_;
97  
        impl_.cs_ = s_;
98  
    }
98  
    }
99  
    else
99  
    else
100  
    {
100  
    {
101  
        BOOST_ASSERT(impl_.cs_[0] == 0);
101  
        BOOST_ASSERT(impl_.cs_[0] == 0);
102  
    }
102  
    }
103  
}
103  
}
104  

104  

105  
void
105  
void
106  
url::
106  
url::
107  
reserve_impl(
107  
reserve_impl(
108  
    std::size_t n,
108  
    std::size_t n,
109  
    op_t& op)
109  
    op_t& op)
110  
{
110  
{
111  
    if(n > max_size())
111  
    if(n > max_size())
112  
        detail::throw_length_error();
112  
        detail::throw_length_error();
113  
    if(n <= cap_)
113  
    if(n <= cap_)
114  
        return;
114  
        return;
115  
    char* s;
115  
    char* s;
116  
    if(s_ != nullptr)
116  
    if(s_ != nullptr)
117  
    {
117  
    {
118  
        // 50% growth policy
118  
        // 50% growth policy
119  
        auto const h = cap_ / 2;
119  
        auto const h = cap_ / 2;
120  
        std::size_t new_cap;
120  
        std::size_t new_cap;
121  
        if(cap_ <= max_size() - h)
121  
        if(cap_ <= max_size() - h)
122  
            new_cap = cap_ + h;
122  
            new_cap = cap_ + h;
123  
        else
123  
        else
124  
            new_cap = max_size();
124  
            new_cap = max_size();
125  
        if( new_cap < n)
125  
        if( new_cap < n)
126  
            new_cap = n;
126  
            new_cap = n;
127  
        s = allocate(new_cap);
127  
        s = allocate(new_cap);
128  
        std::memcpy(s, s_, size() + 1);
128  
        std::memcpy(s, s_, size() + 1);
129  
        BOOST_ASSERT(! op.old);
129  
        BOOST_ASSERT(! op.old);
130  
        op.old = s_;
130  
        op.old = s_;
131  
        s_ = s;
131  
        s_ = s;
132  
    }
132  
    }
133  
    else
133  
    else
134  
    {
134  
    {
135  
        s_ = allocate(n);
135  
        s_ = allocate(n);
136  
        s_[0] = '\0';
136  
        s_[0] = '\0';
137  
    }
137  
    }
138  
    impl_.cs_ = s_;
138  
    impl_.cs_ = s_;
139  
}
139  
}
140  

140  

141  
void
141  
void
142  
url::
142  
url::
143  
cleanup(
143  
cleanup(
144  
    op_t& op)
144  
    op_t& op)
145  
{
145  
{
146  
    if(op.old)
146  
    if(op.old)
147  
        deallocate(op.old);
147  
        deallocate(op.old);
148  
}
148  
}
149  

149  

150  
//------------------------------------------------
150  
//------------------------------------------------
151  

151  

152  
void
152  
void
153  
url::
153  
url::
154  
swap(url& other) noexcept
154  
swap(url& other) noexcept
155  
{
155  
{
156  
    if (this == &other)
156  
    if (this == &other)
157  
        return;
157  
        return;
158  
    std::swap(s_, other.s_);
158  
    std::swap(s_, other.s_);
159  
    std::swap(cap_, other.cap_);
159  
    std::swap(cap_, other.cap_);
160  
    std::swap(impl_, other.impl_);
160  
    std::swap(impl_, other.impl_);
161  
    std::swap(pi_, other.pi_);
161  
    std::swap(pi_, other.pi_);
162  
    if (pi_ == &other.impl_)
162  
    if (pi_ == &other.impl_)
163  
        pi_ = &impl_;
163  
        pi_ = &impl_;
164  
    if (other.pi_ == &impl_)
164  
    if (other.pi_ == &impl_)
165  
        other.pi_ = &other.impl_;
165  
        other.pi_ = &other.impl_;
166  
}
166  
}
167  

167  

168  
} // urls
168  
} // urls
169  
} // boost
169  
} // boost
170  

170