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(s_)
65  
    if(s_)
66  
        deallocate(s_);
66  
        deallocate(s_);
67  
    impl_ = u.impl_;
67  
    impl_ = u.impl_;
68  
    s_ = u.s_;
68  
    s_ = u.s_;
69  
    cap_ = u.cap_;
69  
    cap_ = u.cap_;
70  
    u.s_ = nullptr;
70  
    u.s_ = nullptr;
71  
    u.cap_ = 0;
71  
    u.cap_ = 0;
72  
    u.impl_ = {from::url};
72  
    u.impl_ = {from::url};
73  
    return *this;
73  
    return *this;
74  
}
74  
}
75  

75  

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

77  

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

87  

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

95  

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

113  

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

150  

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

160  

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

162  

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

175  

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

178  

179  
#endif
179  
#endif