1 +
//
 
2 +
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
 
3 +
// Copyright (c) 2023 Alan de Freitas (alandefreitas@gmail.com)
 
4 +
//
 
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)
 
7 +
//
 
8 +
// Official repository: https://github.com/boostorg/url
 
9 +
//
 
10 +

 
11 +
#ifndef BOOST_URL_DETAIL_IMPL_URL_IMPL_HPP
 
12 +
#define BOOST_URL_DETAIL_IMPL_URL_IMPL_HPP
 
13 +

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

 
21 +
namespace boost {
 
22 +
namespace urls {
 
23 +
namespace detail {
 
24 +

 
25 +
//------------------------------------------------
 
26 +
//
 
27 +
// url_impl
 
28 +
//
 
29 +
//------------------------------------------------
 
30 +

 
31 +
inline BOOST_URL_CXX20_CONSTEXPR
 
32 +
void
 
33 +
url_impl::
 
34 +
apply_scheme(
 
35 +
    core::string_view s) noexcept
 
36 +
{
 
37 +
    scheme_ = string_to_scheme(s);
 
38 +
    set_size(id_scheme, s.size() + 1);
 
39 +
}
 
40 +

 
41 +
inline BOOST_URL_CXX20_CONSTEXPR
 
42 +
void
 
43 +
url_impl::
 
44 +
apply_userinfo(
 
45 +
    pct_string_view const& user,
 
46 +
    pct_string_view const* pass) noexcept
 
47 +
{
 
48 +
    BOOST_ASSERT(from_ == from::authority);
 
49 +

 
50 +
    set_size(id_user, user.size());
 
51 +
    decoded_[id_user] =
 
52 +
        detail::to_size_type(
 
53 +
            user.decoded_size());
 
54 +
    if(pass)
 
55 +
    {
 
56 +
        set_size(id_pass,
 
57 +
            pass->size() + 2);
 
58 +
        decoded_[id_pass] =
 
59 +
            detail::to_size_type(
 
60 +
                pass->decoded_size());
 
61 +
    }
 
62 +
    else
 
63 +
    {
 
64 +
        set_size(id_pass, 1 );
 
65 +
    }
 
66 +
}
 
67 +

 
68 +
inline BOOST_URL_CXX20_CONSTEXPR
 
69 +
void
 
70 +
url_impl::
 
71 +
apply_host(
 
72 +
    host_type ht,
 
73 +
    pct_string_view s,
 
74 +
    unsigned char const* addr) noexcept
 
75 +
{
 
76 +
    BOOST_ASSERT(from_ == from::authority);
 
77 +

 
78 +
    host_type_ = ht;
 
79 +
    set_size(id_host, s.size());
 
80 +
    decoded_[id_host] =
 
81 +
        detail::to_size_type(
 
82 +
            s.decoded_size());
 
83 +
    for(std::size_t i = 0;
 
84 +
        i < sizeof(ip_addr_); ++i)
 
85 +
        ip_addr_[i] = addr[i];
 
86 +
}
 
87 +

 
88 +
inline BOOST_URL_CXX20_CONSTEXPR
 
89 +
void
 
90 +
url_impl::
 
91 +
apply_port(
 
92 +
    core::string_view s,
 
93 +
    unsigned short pn) noexcept
 
94 +
{
 
95 +
    BOOST_ASSERT(from_ == from::authority);
 
96 +

 
97 +
    port_number_ = pn;
 
98 +
    set_size(id_port, 1 + s.size());
 
99 +
}
 
100 +

 
101 +
inline BOOST_URL_CXX20_CONSTEXPR
 
102 +
void
 
103 +
url_impl::
 
104 +
apply_authority(
 
105 +
    authority_view const& a) noexcept
 
106 +
{
 
107 +
    BOOST_ASSERT(from_ != from::authority);
 
108 +

 
109 +
    set_size(id_user,
 
110 +
        a.u_.len(id_user) +
 
111 +
        (from_ == from::authority ? 0 : 2));
 
112 +
    set_size(id_pass, a.u_.len(id_pass));
 
113 +
    decoded_[id_user] = a.u_.decoded_[id_user];
 
114 +
    decoded_[id_pass] = a.u_.decoded_[id_pass];
 
115 +

 
116 +
    host_type_ = a.u_.host_type_;
 
117 +
    port_number_ = a.u_.port_number_;
 
118 +
    set_size(id_host, a.u_.len(id_host));
 
119 +
    set_size(id_port, a.u_.len(id_port));
 
120 +
    for(std::size_t i = 0;
 
121 +
        i < sizeof(ip_addr_); ++i)
 
122 +
        ip_addr_[i] = a.u_.ip_addr_[i];
 
123 +
    decoded_[id_host] = a.u_.decoded_[id_host];
 
124 +
}
 
125 +

 
126 +
inline BOOST_URL_CXX20_CONSTEXPR
 
127 +
void
 
128 +
url_impl::
 
129 +
apply_path(
 
130 +
    pct_string_view s,
 
131 +
    std::size_t nseg) noexcept
 
132 +
{
 
133 +
    set_size(id_path, s.size());
 
134 +
    decoded_[id_path] =
 
135 +
        detail::to_size_type(
 
136 +
            s.decoded_size());
 
137 +
    // inline path_segments logic
 
138 +
    // (original in src/detail/path.hpp)
 
139 +
    auto const sz = s.size();
 
140 +
    auto const p = s.data();
 
141 +
    std::size_t adj = nseg;
 
142 +
    switch(sz)
 
143 +
    {
 
144 +
    case 0:
 
145 +
        adj = 0;
 
146 +
        break;
 
147 +
    case 1:
 
148 +
        adj = (p[0] == '/') ? 0 : 1;
 
149 +
        break;
 
150 +
    case 2:
 
151 +
        if(p[0] == '/')
 
152 +
            adj = nseg;
 
153 +
        else if(p[0] == '.' && p[1] == '/')
 
154 +
            adj = nseg - 1;
 
155 +
        else
 
156 +
            adj = nseg;
 
157 +
        break;
 
158 +
    default:
 
159 +
        if(p[0] == '/')
 
160 +
        {
 
161 +
            if(p[1] == '.' && p[2] == '/')
 
162 +
                adj = nseg - 1;
 
163 +
            else
 
164 +
                adj = nseg;
 
165 +
        }
 
166 +
        else if(p[0] == '.' && p[1] == '/')
 
167 +
            adj = nseg - 1;
 
168 +
        else
 
169 +
            adj = nseg;
 
170 +
        break;
 
171 +
    }
 
172 +
    nseg_ = detail::to_size_type(adj);
 
173 +
}
 
174 +

 
175 +
inline BOOST_URL_CXX20_CONSTEXPR
 
176 +
void
 
177 +
url_impl::
 
178 +
apply_query(
 
179 +
    pct_string_view s,
 
180 +
    std::size_t n) noexcept
 
181 +
{
 
182 +
    nparam_ = detail::to_size_type(n);
 
183 +
    set_size(id_query, 1 + s.size());
 
184 +
    decoded_[id_query] =
 
185 +
        detail::to_size_type(
 
186 +
            s.decoded_size());
 
187 +
}
 
188 +

 
189 +
inline BOOST_URL_CXX20_CONSTEXPR
 
190 +
void
 
191 +
url_impl::
 
192 +
apply_frag(
 
193 +
    pct_string_view s) noexcept
 
194 +
{
 
195 +
    set_size(id_frag, s.size() + 1);
 
196 +
    decoded_[id_frag] =
 
197 +
        detail::to_size_type(
 
198 +
            s.decoded_size());
 
199 +
}
 
200 +

 
201 +
// return length of [first, last)
 
202 +
inline BOOST_URL_CXX20_CONSTEXPR
 
203 +
std::size_t
 
204 +
url_impl::
 
205 +
len(
 
206 +
    int first,
 
207 +
    int last) const noexcept
 
208 +
{
 
209 +
    BOOST_ASSERT(first <= last);
 
210 +
    BOOST_ASSERT(last <= id_end);
 
211 +
    return offset(last) - offset(first);
 
212 +
}
 
213 +

 
214 +
// return length of part
 
215 +
inline BOOST_URL_CXX20_CONSTEXPR
 
216 +
std::size_t
 
217 +
url_impl::
 
218 +
len(int id) const noexcept
 
219 +
{
 
220 +
    return id == id_end
 
221 +
        ? zero_
 
222 +
        : ( offset(id + 1) -
 
223 +
            offset(id) );
 
224 +
}
 
225 +

 
226 +
// return offset of id
 
227 +
inline BOOST_URL_CXX20_CONSTEXPR
 
228 +
std::size_t
 
229 +
url_impl::
 
230 +
offset(int id) const noexcept
 
231 +
{
 
232 +
    return
 
233 +
        id == id_scheme
 
234 +
        ? zero_
 
235 +
        : offset_[id];
 
236 +
}
 
237 +

 
238 +
// return id as string
 
239 +
inline BOOST_URL_CXX20_CONSTEXPR
 
240 +
core::string_view
 
241 +
url_impl::
 
242 +
get(int id) const noexcept
 
243 +
{
 
244 +
    return {
 
245 +
        cs_ + offset(id), len(id) };
 
246 +
}
 
247 +

 
248 +
// return [first, last) as string
 
249 +
inline BOOST_URL_CXX20_CONSTEXPR
 
250 +
core::string_view
 
251 +
url_impl::
 
252 +
get(int first,
 
253 +
    int last) const noexcept
 
254 +
{
 
255 +
    return { cs_ + offset(first),
 
256 +
        offset(last) - offset(first) };
 
257 +
}
 
258 +

 
259 +
// return id as pct-string
 
260 +
inline BOOST_URL_CXX20_CONSTEXPR
 
261 +
pct_string_view
 
262 +
url_impl::
 
263 +
pct_get(
 
264 +
    int id) const noexcept
 
265 +
{
 
266 +
    return make_pct_string_view_unsafe(
 
267 +
        cs_ + offset(id),
 
268 +
        len(id),
 
269 +
        decoded_[id]);
 
270 +
}
 
271 +

 
272 +
// return [first, last) as pct-string
 
273 +
inline BOOST_URL_CXX20_CONSTEXPR
 
274 +
pct_string_view
 
275 +
url_impl::
 
276 +
pct_get(
 
277 +
    int first,
 
278 +
    int last) const noexcept
 
279 +
{
 
280 +
    auto const pos = offset(first);
 
281 +
    std::size_t n = 0;
 
282 +
    for(auto i = first; i < last;)
 
283 +
        n += decoded_[i++];
 
284 +
    return make_pct_string_view_unsafe(
 
285 +
        cs_ + pos,
 
286 +
        offset(last) - pos,
 
287 +
        n);
 
288 +
}
 
289 +

 
290 +
//------------------------------------------------
 
291 +

 
292 +
// change id to size n
 
293 +
inline BOOST_URL_CXX20_CONSTEXPR
 
294 +
void
 
295 +
url_impl::
 
296 +
set_size(
 
297 +
    int id,
 
298 +
    std::size_t n) noexcept
 
299 +
{
 
300 +
    auto const cur = len(id);
 
301 +
    if(n >= cur)
 
302 +
    {
 
303 +
        auto const d = n - cur;
 
304 +
        for(auto i = id + 1;
 
305 +
            i <= id_end; ++i)
 
306 +
            offset_[i] += detail::to_size_type(d);
 
307 +
        return;
 
308 +
    }
 
309 +
    auto const d = cur - n;
 
310 +
    for(auto i = id + 1;
 
311 +
        i <= id_end; ++i)
 
312 +
        offset_[i] -= detail::to_size_type(d);
 
313 +
}
 
314 +

 
315 +
// trim id to size n,
 
316 +
// moving excess into id+1
 
317 +
inline BOOST_URL_CXX20_CONSTEXPR
 
318 +
void
 
319 +
url_impl::
 
320 +
split(
 
321 +
    int id,
 
322 +
    std::size_t n) noexcept
 
323 +
{
 
324 +
    BOOST_ASSERT(id < id_end - 1);
 
325 +
    offset_[id + 1] = detail::to_size_type(
 
326 +
        offset(id) + n);
 
327 +
}
 
328 +

 
329 +
// add n to [first, last]
 
330 +
inline BOOST_URL_CXX20_CONSTEXPR
 
331 +
void
 
332 +
url_impl::
 
333 +
adjust_right(
 
334 +
    int first,
 
335 +
    int last,
 
336 +
    std::size_t n) noexcept
 
337 +
{
 
338 +
    for(int i = first;
 
339 +
            i <= last; ++i)
 
340 +
        offset_[i] += detail::to_size_type(n);
 
341 +
}
 
342 +

 
343 +
// remove n from [first, last]
 
344 +
inline BOOST_URL_CXX20_CONSTEXPR
 
345 +
void
 
346 +
url_impl::
 
347 +
adjust_left(
 
348 +
    int first,
 
349 +
    int last,
 
350 +
    std::size_t n) noexcept
 
351 +
{
 
352 +
    for(int i = first;
 
353 +
            i <= last; ++i)
 
354 +
        offset_[i] -= detail::to_size_type(n);
 
355 +
}
 
356 +

 
357 +
// set [first, last) offset
 
358 +
inline BOOST_URL_CXX20_CONSTEXPR
 
359 +
void
 
360 +
url_impl::
 
361 +
collapse(
 
362 +
    int first,
 
363 +
    int last,
 
364 +
    std::size_t n) noexcept
 
365 +
{
 
366 +
    for(int i = first + 1;
 
367 +
            i < last; ++i)
 
368 +
        offset_[i] = detail::to_size_type(n);
 
369 +
}
 
370 +

 
371 +
//------------------------------------------------
 
372 +

 
373 +
inline BOOST_URL_CXX20_CONSTEXPR
 
374 +
authority_view
 
375 +
url_impl::
 
376 +
construct_authority() const noexcept
 
377 +
{
 
378 +
    return authority_view(*this);
 
379 +
}
 
380 +

 
381 +
// construct() is defined in url_view.hpp
 
382 +
// after the url_view type is complete
 
383 +

 
384 +
} // detail
 
385 +
} // urls
 
386 +
} // boost
 
387 +

 
388 +
#endif