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

77  

78  
//------------------------------------------------
78  
//------------------------------------------------
79  

79  

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

89  

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

97  

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

115  

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

152  

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

162  

163  
//------------------------------------------------
163  
//------------------------------------------------
164  

164  

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

177  

178  
} // urls
178  
} // urls
179  
} // boost
179  
} // boost
180  

180  

181  
#endif
181  
#endif