TLA Line data Source code
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/memcpy.hpp>
16 : #include <boost/url/detail/path.hpp>
17 : #include <boost/url/detail/url_impl.hpp>
18 : #include <boost/url/scheme.hpp>
19 : #include <boost/assert.hpp>
20 : #include <cstring>
21 :
22 : namespace boost {
23 : namespace urls {
24 : namespace detail {
25 :
26 : //------------------------------------------------
27 : //
28 : // url_impl
29 : //
30 : //------------------------------------------------
31 :
32 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
33 : void
34 HIT 2432 : url_impl::
35 : apply_scheme(
36 : core::string_view s) noexcept
37 : {
38 2432 : scheme_ = string_to_scheme(s);
39 2432 : set_size(id_scheme, s.size() + 1);
40 2432 : }
41 :
42 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
43 : void
44 405 : url_impl::
45 : apply_userinfo(
46 : pct_string_view const& user,
47 : pct_string_view const* pass) noexcept
48 : {
49 : // this function is for
50 : // authority_view_rule only
51 405 : BOOST_ASSERT(from_ == from::authority);
52 :
53 : // userinfo
54 405 : set_size(id_user, user.size());
55 405 : decoded_[id_user] =
56 405 : detail::to_size_type(
57 : user.decoded_size());
58 405 : if(pass)
59 : {
60 270 : set_size(id_pass,
61 270 : pass->size() + 2);
62 270 : decoded_[id_pass] =
63 270 : detail::to_size_type(
64 : pass->decoded_size());
65 : }
66 : else
67 : {
68 : // trailing '@'
69 135 : set_size(id_pass, 1 );
70 : }
71 405 : }
72 :
73 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
74 : void
75 2022 : url_impl::
76 : apply_host(
77 : host_type ht,
78 : pct_string_view s,
79 : unsigned char const* addr) noexcept
80 : {
81 : // this function is for
82 : // authority_view_rule only
83 2022 : BOOST_ASSERT(from_ == from::authority);
84 :
85 : // host, port
86 2022 : host_type_ = ht;
87 2022 : set_size(id_host, s.size());
88 2022 : decoded_[id_host] =
89 2022 : detail::to_size_type(
90 : s.decoded_size());
91 : detail::memcpy(
92 2022 : ip_addr_,
93 : addr,
94 : sizeof(ip_addr_));
95 2022 : }
96 :
97 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
98 : void
99 284 : url_impl::
100 : apply_port(
101 : core::string_view s,
102 : unsigned short pn) noexcept
103 : {
104 : // this function is for
105 : // authority_view_rule only
106 284 : BOOST_ASSERT(from_ == from::authority);
107 :
108 284 : port_number_ = pn;
109 284 : set_size(id_port, 1 + s.size());
110 284 : }
111 :
112 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
113 : void
114 1962 : url_impl::
115 : apply_authority(
116 : url_impl const& a) noexcept
117 : {
118 1962 : BOOST_ASSERT(from_ != from::authority);
119 :
120 : // userinfo
121 1962 : set_size(id_user,
122 1962 : a.len(id_user) +
123 1962 : (from_ == from::authority ? 0 : 2));
124 1962 : set_size(id_pass, a.len(id_pass));
125 1962 : decoded_[id_user] = a.decoded_[id_user];
126 1962 : decoded_[id_pass] = a.decoded_[id_pass];
127 :
128 : // host, port
129 1962 : host_type_ = a.host_type_;
130 1962 : port_number_ = a.port_number_;
131 1962 : set_size(id_host, a.len(id_host));
132 1962 : set_size(id_port, a.len(id_port));
133 : detail::memcpy(
134 1962 : ip_addr_,
135 1962 : a.ip_addr_,
136 : sizeof(ip_addr_));
137 1962 : decoded_[id_host] = a.decoded_[id_host];
138 1962 : }
139 :
140 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
141 : void
142 3748 : url_impl::
143 : apply_path(
144 : pct_string_view s,
145 : std::size_t nseg) noexcept
146 : {
147 3748 : set_size(id_path, s.size());
148 3748 : decoded_[id_path] =
149 3748 : detail::to_size_type(
150 : s.decoded_size());
151 3748 : nseg_ = detail::to_size_type(
152 : detail::path_segments(s, nseg));
153 3748 : }
154 :
155 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
156 : void
157 504 : url_impl::
158 : apply_query(
159 : pct_string_view s,
160 : std::size_t n) noexcept
161 : {
162 504 : nparam_ = detail::to_size_type(n);
163 504 : set_size(id_query, 1 + s.size());
164 504 : decoded_[id_query] =
165 504 : detail::to_size_type(
166 : s.decoded_size());
167 504 : }
168 :
169 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
170 : void
171 244 : url_impl::
172 : apply_frag(
173 : pct_string_view s) noexcept
174 : {
175 244 : set_size(id_frag, s.size() + 1);
176 244 : decoded_[id_frag] =
177 244 : detail::to_size_type(
178 : s.decoded_size());
179 244 : }
180 :
181 : // return length of [first, last)
182 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
183 : std::size_t
184 20955 : url_impl::
185 : len(
186 : int first,
187 : int last) const noexcept
188 : {
189 20955 : BOOST_ASSERT(first <= last);
190 20955 : BOOST_ASSERT(last <= id_end);
191 20955 : return offset(last) - offset(first);
192 : }
193 :
194 : // return length of part
195 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
196 : std::size_t
197 276636 : url_impl::
198 : len(int id) const noexcept
199 : {
200 : return id == id_end
201 553272 : ? zero_
202 276636 : : ( offset(id + 1) -
203 553272 : offset(id) );
204 : }
205 :
206 : // return offset of id
207 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
208 : std::size_t
209 723724 : url_impl::
210 : offset(int id) const noexcept
211 : {
212 : return
213 : id == id_scheme
214 723724 : ? zero_
215 723724 : : offset_[id];
216 : }
217 :
218 : // return id as string
219 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
220 : core::string_view
221 49394 : url_impl::
222 : get(int id) const noexcept
223 : {
224 : return {
225 49394 : cs_ + offset(id), len(id) };
226 : }
227 :
228 : // return [first, last) as string
229 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
230 : core::string_view
231 916 : url_impl::
232 : get(int first,
233 : int last) const noexcept
234 : {
235 916 : return { cs_ + offset(first),
236 916 : offset(last) - offset(first) };
237 : }
238 :
239 : // return id as pct-string
240 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
241 : pct_string_view
242 2318 : url_impl::
243 : pct_get(
244 : int id) const noexcept
245 : {
246 2318 : return make_pct_string_view_unsafe(
247 2318 : cs_ + offset(id),
248 : len(id),
249 4636 : decoded_[id]);
250 : }
251 :
252 : // return [first, last) as pct-string
253 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
254 : pct_string_view
255 130 : url_impl::
256 : pct_get(
257 : int first,
258 : int last) const noexcept
259 : {
260 130 : auto const pos = offset(first);
261 130 : std::size_t n = 0;
262 420 : for(auto i = first; i < last;)
263 290 : n += decoded_[i++];
264 130 : return make_pct_string_view_unsafe(
265 130 : cs_ + pos,
266 130 : offset(last) - pos,
267 130 : n);
268 : }
269 :
270 : //------------------------------------------------
271 :
272 : // change id to size n
273 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
274 : void
275 20675 : url_impl::
276 : set_size(
277 : int id,
278 : std::size_t n) noexcept
279 : {
280 20675 : auto const cur = len(id);
281 20675 : if(n >= cur)
282 : {
283 20310 : auto const d = n - cur;
284 20310 : for(auto i = id + 1;
285 123823 : i <= id_end; ++i)
286 103513 : offset_[i] += detail::to_size_type(d);
287 20310 : return;
288 : }
289 365 : auto const d = cur - n;
290 365 : for(auto i = id + 1;
291 1794 : i <= id_end; ++i)
292 1429 : offset_[i] -= detail::to_size_type(d);
293 : }
294 :
295 : // trim id to size n,
296 : // moving excess into id+1
297 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
298 : void
299 891 : url_impl::
300 : split(
301 : int id,
302 : std::size_t n) noexcept
303 : {
304 891 : BOOST_ASSERT(id < id_end - 1);
305 : //BOOST_ASSERT(n <= len(id));
306 891 : offset_[id + 1] = detail::to_size_type(
307 891 : offset(id) + n);
308 891 : }
309 :
310 : // add n to [first, last]
311 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
312 : void
313 979 : url_impl::
314 : adjust_right(
315 : int first,
316 : int last,
317 : std::size_t n) noexcept
318 : {
319 979 : for(int i = first;
320 5720 : i <= last; ++i)
321 4741 : offset_[i] += detail::to_size_type(n);
322 979 : }
323 :
324 : // remove n from [first, last]
325 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
326 : void
327 721 : url_impl::
328 : adjust_left(
329 : int first,
330 : int last,
331 : std::size_t n) noexcept
332 : {
333 721 : for(int i = first;
334 3558 : i <= last; ++i)
335 2837 : offset_[i] -= detail::to_size_type(n);
336 721 : }
337 :
338 : // set [first, last) offset
339 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
340 : void
341 1681 : url_impl::
342 : collapse(
343 : int first,
344 : int last,
345 : std::size_t n) noexcept
346 : {
347 1681 : for(int i = first + 1;
348 2228 : i < last; ++i)
349 547 : offset_[i] = detail::to_size_type(n);
350 1681 : }
351 :
352 :
353 : //------------------------------------------------
354 : //
355 : // path_ref
356 : //
357 : //------------------------------------------------
358 :
359 : inline
360 2097 : path_ref::
361 : path_ref(
362 2097 : url_impl const& impl) noexcept
363 : {
364 2097 : if(impl.from_ == url_impl::from::url)
365 : {
366 1594 : impl_ = &impl;
367 : }
368 : else
369 : {
370 503 : core::string_view s = impl.get(id_path);
371 503 : data_ = s.data();
372 503 : size_ = s.size();
373 503 : nseg_ = impl.nseg_;
374 503 : dn_ = impl.decoded_[id_path];
375 : }
376 2097 : }
377 :
378 : inline
379 181 : path_ref::
380 : path_ref(
381 : core::string_view s,
382 : std::size_t dn,
383 181 : std::size_t nseg) noexcept
384 362 : : data_(s.data())
385 181 : , size_(s.size())
386 181 : , nseg_(nseg)
387 181 : , dn_(dn)
388 : {
389 181 : }
390 :
391 : inline
392 : pct_string_view
393 4739 : path_ref::
394 : buffer() const noexcept
395 : {
396 4739 : if(impl_)
397 2392 : return make_pct_string_view_unsafe(
398 2392 : impl_->cs_ +
399 2392 : impl_->offset(id_path),
400 2392 : impl_->len(id_path),
401 4784 : impl_->decoded_[id_path]);
402 2347 : return make_pct_string_view_unsafe(
403 2347 : data_, size_, dn_);
404 : }
405 :
406 : inline
407 : std::size_t
408 4487 : path_ref::
409 : size() const noexcept
410 : {
411 4487 : if(impl_)
412 3116 : return impl_->len(id_path);
413 1371 : return size_;
414 : }
415 :
416 : inline
417 : char const*
418 12997 : path_ref::
419 : data() const noexcept
420 : {
421 12997 : if(impl_)
422 7472 : return impl_->cs_ +
423 7472 : impl_->offset(id_path);
424 5525 : return data_;
425 : }
426 :
427 : inline
428 : char const*
429 4461 : path_ref::
430 : end() const noexcept
431 : {
432 4461 : if(impl_)
433 2842 : return impl_->cs_ +
434 2842 : impl_->offset(id_query);
435 1619 : return data_ + size_;
436 : }
437 :
438 : inline
439 : std::size_t
440 9623 : path_ref::
441 : nseg() const noexcept
442 : {
443 9623 : if(impl_)
444 6161 : return impl_->nseg_;
445 3462 : return nseg_;
446 : }
447 :
448 : inline
449 : std::size_t
450 2040 : path_ref::
451 : decoded_size() const noexcept
452 : {
453 2040 : if(impl_)
454 1359 : return impl_->decoded_[id_path];
455 681 : return dn_;
456 : }
457 :
458 : //------------------------------------------------
459 : //
460 : // query_ref
461 : //
462 : //------------------------------------------------
463 :
464 : inline
465 255 : query_ref::
466 : query_ref(
467 : core::string_view s,
468 : std::size_t dn,
469 255 : std::size_t nparam) noexcept
470 510 : : data_(s.data())
471 255 : , size_(s.size())
472 255 : , nparam_(nparam)
473 255 : , dn_(dn)
474 : {
475 255 : }
476 :
477 : inline
478 493 : query_ref::
479 : query_ref(
480 493 : url_impl const& impl) noexcept
481 : {
482 493 : if(impl.from_ == url_impl::from::url)
483 : {
484 362 : impl_ = &impl;
485 : }
486 : else
487 : {
488 131 : core::string_view s = impl.get(id_query);
489 131 : if (!s.empty())
490 : {
491 125 : s.remove_prefix(1);
492 125 : question_mark_ = true;
493 : }
494 131 : data_ = s.data();
495 131 : size_ = s.size();
496 131 : nparam_ = impl.nparam_;
497 131 : dn_ = impl.decoded_[id_query];
498 : }
499 493 : }
500 :
501 : inline
502 : pct_string_view
503 24 : query_ref::
504 : buffer() const noexcept
505 : {
506 24 : if(impl_)
507 : {
508 2 : auto pos = impl_->offset_[id_query];
509 2 : auto pos1 = impl_->offset_[id_frag];
510 2 : if(pos < pos1)
511 : {
512 MIS 0 : ++pos; // no '?'
513 0 : return make_pct_string_view_unsafe(
514 0 : impl_->cs_ + pos,
515 0 : pos1 - pos,
516 0 : impl_->decoded_[id_query]);
517 : }
518 : // empty
519 HIT 2 : return make_pct_string_view_unsafe(
520 2 : impl_->cs_ + pos,
521 : 0,
522 2 : 0);
523 : }
524 : // no '?'
525 22 : return make_pct_string_view_unsafe(
526 22 : data_, size_, dn_);
527 : }
528 :
529 : // with '?'
530 : inline
531 : std::size_t
532 5650 : query_ref::
533 : size() const noexcept
534 : {
535 5650 : if(impl_)
536 2029 : return impl_->len(id_query);
537 3621 : if(size_ > 0)
538 3584 : return size_ + 1;
539 37 : return question_mark_;
540 : }
541 :
542 : // no '?'
543 : inline
544 : char const*
545 6152 : query_ref::
546 : begin() const noexcept
547 : {
548 6152 : if(impl_)
549 : {
550 : // using the offset array here
551 2288 : auto pos = impl_->offset_[id_query];
552 2288 : auto pos1 = impl_->offset_[id_frag];
553 2288 : if(pos < pos1)
554 2288 : return impl_->cs_ + pos + 1; // no '?'
555 : // empty
556 MIS 0 : return impl_->cs_ + pos;
557 : }
558 HIT 3864 : return data_;
559 :
560 : }
561 :
562 : inline
563 : char const*
564 2410 : query_ref::
565 : end() const noexcept
566 : {
567 2410 : if(impl_)
568 917 : return impl_->cs_ +
569 917 : impl_->offset(id_frag);
570 1493 : return data_ + size_;
571 : }
572 :
573 : inline
574 : std::size_t
575 9036 : query_ref::
576 : nparam() const noexcept
577 : {
578 9036 : if(impl_)
579 3171 : return impl_->nparam_;
580 5865 : return nparam_;
581 : }
582 :
583 : } // detail
584 : } // urls
585 : } // boost
586 :
587 : #endif
|