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  
#ifndef BOOST_URL_IMPL_URL_HPP
11  
#ifndef BOOST_URL_IMPL_URL_HPP
12  
#define BOOST_URL_IMPL_URL_HPP
12  
#define BOOST_URL_IMPL_URL_HPP
13  

13  

14  
#include <boost/url/detail/except.hpp>
14  
#include <boost/url/detail/except.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  

20  

21  
//------------------------------------------------
21  
//------------------------------------------------
22  

22  

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

34  

35  
// construct empty
35  
// construct empty
36  
inline
36  
inline
37  
url::
37  
url::
38  
url() noexcept = default;
38  
url() noexcept = default;
39  

39  

40  
inline
40  
inline
41  
url::
41  
url::
42  
url(core::string_view s)
42  
url(core::string_view s)
43  
    : url(parse_uri_reference(s
43  
    : url(parse_uri_reference(s
44  
        ).value(BOOST_URL_POS))
44  
        ).value(BOOST_URL_POS))
45  
{
45  
{
46  
}
46  
}
47  

47  

48  
inline
48  
inline
49  
url::
49  
url::
50  
url(url&& u) noexcept
50  
url(url&& u) noexcept
51  
    : url_base(u.impl_)
51  
    : url_base(u.impl_)
52  
{
52  
{
53  
    s_ = u.s_;
53  
    s_ = u.s_;
54  
    cap_ = u.cap_;
54  
    cap_ = u.cap_;
55  
    u.s_ = nullptr;
55  
    u.s_ = nullptr;
56  
    u.cap_ = 0;
56  
    u.cap_ = 0;
57  
    u.impl_ = {from::url};
57  
    u.impl_ = {from::url};
58  
}
58  
}
59  

59  

60  
inline
60  
inline
61  
url&
61  
url&
62  
url::
62  
url::
63  
operator=(url&& u) noexcept
63  
operator=(url&& u) noexcept
64  
{
64  
{
 
65 +
    if(this == &u)
 
66 +
        return *this;
65  
    if(s_)
67  
    if(s_)
66  
        deallocate(s_);
68  
        deallocate(s_);
67  
    impl_ = u.impl_;
69  
    impl_ = u.impl_;
68  
    s_ = u.s_;
70  
    s_ = u.s_;
69  
    cap_ = u.cap_;
71  
    cap_ = u.cap_;
70  
    u.s_ = nullptr;
72  
    u.s_ = nullptr;
71  
    u.cap_ = 0;
73  
    u.cap_ = 0;
72  
    u.impl_ = {from::url};
74  
    u.impl_ = {from::url};
73  
    return *this;
75  
    return *this;
74  
}
76  
}
75  

77  

76  
//------------------------------------------------
78  
//------------------------------------------------
77  

79  

78  
inline
80  
inline
79  
char*
81  
char*
80  
url::
82  
url::
81  
allocate(std::size_t n)
83  
allocate(std::size_t n)
82  
{
84  
{
83  
    auto s = new char[n + 1];
85  
    auto s = new char[n + 1];
84  
    cap_ = n;
86  
    cap_ = n;
85  
    return s;
87  
    return s;
86  
}
88  
}
87  

89  

88  
inline
90  
inline
89  
void
91  
void
90  
url::
92  
url::
91  
deallocate(char* s)
93  
deallocate(char* s)
92  
{
94  
{
93  
    delete[] s;
95  
    delete[] s;
94  
}
96  
}
95  

97  

96  
inline
98  
inline
97  
void
99  
void
98  
url::
100  
url::
99  
clear_impl() noexcept
101  
clear_impl() noexcept
100  
{
102  
{
101  
    if(s_)
103  
    if(s_)
102  
    {
104  
    {
103  
        // preserve capacity
105  
        // preserve capacity
104  
        impl_ = {from::url};
106  
        impl_ = {from::url};
105  
        s_[0] = '\0';
107  
        s_[0] = '\0';
106  
        impl_.cs_ = s_;
108  
        impl_.cs_ = s_;
107  
    }
109  
    }
108  
    else
110  
    else
109  
    {
111  
    {
110  
        BOOST_ASSERT(impl_.cs_[0] == 0);
112  
        BOOST_ASSERT(impl_.cs_[0] == 0);
111  
    }
113  
    }
112  
}
114  
}
113  

115  

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

152  

151  
inline
153  
inline
152  
void
154  
void
153  
url::
155  
url::
154  
cleanup(
156  
cleanup(
155  
    op_t& op)
157  
    op_t& op)
156  
{
158  
{
157  
    if(op.old)
159  
    if(op.old)
158  
        deallocate(op.old);
160  
        deallocate(op.old);
159  
}
161  
}
160  

162  

161  
//------------------------------------------------
163  
//------------------------------------------------
162  

164  

163  
inline
165  
inline
164  
void
166  
void
165  
url::
167  
url::
166  
swap(url& other) noexcept
168  
swap(url& other) noexcept
167  
{
169  
{
168  
    if (this == &other)
170  
    if (this == &other)
169  
        return;
171  
        return;
170  
    std::swap(s_, other.s_);
172  
    std::swap(s_, other.s_);
171  
    std::swap(cap_, other.cap_);
173  
    std::swap(cap_, other.cap_);
172  
    std::swap(impl_, other.impl_);
174  
    std::swap(impl_, other.impl_);
173  
    std::swap(external_impl_, other.external_impl_);
175  
    std::swap(external_impl_, other.external_impl_);
174  
}
176  
}
175  

177  

176  
} // urls
178  
} // urls
177  
} // boost
179  
} // boost
178  

180  

179  
#endif
181  
#endif