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 7223 : url_impl::
35 : apply_scheme(
36 : core::string_view s) noexcept
37 : {
38 7223 : scheme_ = string_to_scheme(s);
39 7223 : set_size(id_scheme, s.size() + 1);
40 7223 : }
41 :
42 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
43 : void
44 423 : 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 423 : BOOST_ASSERT(from_ == from::authority);
52 :
53 : // userinfo
54 423 : set_size(id_user, user.size());
55 423 : decoded_[id_user] =
56 423 : detail::to_size_type(
57 : user.decoded_size());
58 423 : if(pass)
59 : {
60 286 : set_size(id_pass,
61 286 : pass->size() + 2);
62 286 : decoded_[id_pass] =
63 286 : detail::to_size_type(
64 : pass->decoded_size());
65 : }
66 : else
67 : {
68 : // trailing '@'
69 137 : set_size(id_pass, 1 );
70 : }
71 423 : }
72 :
73 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
74 : void
75 6613 : 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 6613 : BOOST_ASSERT(from_ == from::authority);
84 :
85 : // host, port
86 6613 : host_type_ = ht;
87 6613 : set_size(id_host, s.size());
88 6613 : decoded_[id_host] =
89 6613 : detail::to_size_type(
90 : s.decoded_size());
91 : detail::memcpy(
92 6613 : ip_addr_,
93 : addr,
94 : sizeof(ip_addr_));
95 6613 : }
96 :
97 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
98 : void
99 378 : 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 378 : BOOST_ASSERT(from_ == from::authority);
107 :
108 378 : port_number_ = pn;
109 378 : set_size(id_port, 1 + s.size());
110 378 : }
111 :
112 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
113 : void
114 6541 : url_impl::
115 : apply_authority(
116 : url_impl const& a) noexcept
117 : {
118 6541 : BOOST_ASSERT(from_ != from::authority);
119 :
120 : // userinfo
121 6541 : set_size(id_user,
122 6541 : a.len(id_user) +
123 6541 : (from_ == from::authority ? 0 : 2));
124 6541 : set_size(id_pass, a.len(id_pass));
125 6541 : decoded_[id_user] = a.decoded_[id_user];
126 6541 : decoded_[id_pass] = a.decoded_[id_pass];
127 :
128 : // host, port
129 6541 : host_type_ = a.host_type_;
130 6541 : port_number_ = a.port_number_;
131 6541 : set_size(id_host, a.len(id_host));
132 6541 : set_size(id_port, a.len(id_port));
133 : detail::memcpy(
134 6541 : ip_addr_,
135 6541 : a.ip_addr_,
136 : sizeof(ip_addr_));
137 6541 : decoded_[id_host] = a.decoded_[id_host];
138 6541 : }
139 :
140 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
141 : void
142 19787 : url_impl::
143 : apply_path(
144 : pct_string_view s,
145 : std::size_t nseg) noexcept
146 : {
147 19787 : set_size(id_path, s.size());
148 19787 : decoded_[id_path] =
149 19787 : detail::to_size_type(
150 : s.decoded_size());
151 19787 : nseg_ = detail::to_size_type(
152 : detail::path_segments(s, nseg));
153 19787 : }
154 :
155 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
156 : void
157 4568 : url_impl::
158 : apply_query(
159 : pct_string_view s,
160 : std::size_t n) noexcept
161 : {
162 4568 : nparam_ = detail::to_size_type(n);
163 4568 : set_size(id_query, 1 + s.size());
164 4568 : decoded_[id_query] =
165 4568 : detail::to_size_type(
166 : s.decoded_size());
167 4568 : }
168 :
169 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
170 : void
171 1242 : url_impl::
172 : apply_frag(
173 : pct_string_view s) noexcept
174 : {
175 1242 : set_size(id_frag, s.size() + 1);
176 1242 : decoded_[id_frag] =
177 1242 : detail::to_size_type(
178 : s.decoded_size());
179 1242 : }
180 :
181 : // return length of [first, last)
182 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
183 : std::size_t
184 51909 : url_impl::
185 : len(
186 : int first,
187 : int last) const noexcept
188 : {
189 51909 : BOOST_ASSERT(first <= last);
190 51909 : BOOST_ASSERT(last <= id_end);
191 51909 : return offset(last) - offset(first);
192 : }
193 :
194 : // return length of part
195 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
196 : std::size_t
197 783644 : url_impl::
198 : len(int id) const noexcept
199 : {
200 : return id == id_end
201 1567288 : ? zero_
202 783644 : : ( offset(id + 1) -
203 1567288 : offset(id) );
204 : }
205 :
206 : // return offset of id
207 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
208 : std::size_t
209 2066682 : url_impl::
210 : offset(int id) const noexcept
211 : {
212 : return
213 : id == id_scheme
214 2066682 : ? zero_
215 2066682 : : offset_[id];
216 : }
217 :
218 : // return id as string
219 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
220 : core::string_view
221 155745 : url_impl::
222 : get(int id) const noexcept
223 : {
224 : return {
225 155745 : 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 1186 : url_impl::
232 : get(int first,
233 : int last) const noexcept
234 : {
235 1186 : return { cs_ + offset(first),
236 1186 : offset(last) - offset(first) };
237 : }
238 :
239 : // return id as pct-string
240 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
241 : pct_string_view
242 2440 : url_impl::
243 : pct_get(
244 : int id) const noexcept
245 : {
246 2440 : return make_pct_string_view_unsafe(
247 2440 : cs_ + offset(id),
248 : len(id),
249 4880 : 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 73205 : url_impl::
276 : set_size(
277 : int id,
278 : std::size_t n) noexcept
279 : {
280 73205 : auto const cur = len(id);
281 73205 : if(n >= cur)
282 : {
283 71817 : auto const d = n - cur;
284 71817 : for(auto i = id + 1;
285 402536 : i <= id_end; ++i)
286 330719 : offset_[i] += detail::to_size_type(d);
287 71817 : return;
288 : }
289 1388 : auto const d = cur - n;
290 1388 : for(auto i = id + 1;
291 5580 : i <= id_end; ++i)
292 4192 : 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 1914 : url_impl::
300 : split(
301 : int id,
302 : std::size_t n) noexcept
303 : {
304 1914 : BOOST_ASSERT(id < id_end - 1);
305 : //BOOST_ASSERT(n <= len(id));
306 1914 : offset_[id + 1] = detail::to_size_type(
307 1914 : offset(id) + n);
308 1914 : }
309 :
310 : // add n to [first, last]
311 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
312 : void
313 2936 : url_impl::
314 : adjust_right(
315 : int first,
316 : int last,
317 : std::size_t n) noexcept
318 : {
319 2936 : for(int i = first;
320 17583 : i <= last; ++i)
321 14647 : offset_[i] += detail::to_size_type(n);
322 2936 : }
323 :
324 : // remove n from [first, last]
325 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
326 : void
327 2385 : url_impl::
328 : adjust_left(
329 : int first,
330 : int last,
331 : std::size_t n) noexcept
332 : {
333 2385 : for(int i = first;
334 12041 : i <= last; ++i)
335 9656 : offset_[i] -= detail::to_size_type(n);
336 2385 : }
337 :
338 : // set [first, last) offset
339 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
340 : void
341 5302 : url_impl::
342 : collapse(
343 : int first,
344 : int last,
345 : std::size_t n) noexcept
346 : {
347 5302 : for(int i = first + 1;
348 6643 : i < last; ++i)
349 1341 : offset_[i] = detail::to_size_type(n);
350 5302 : }
351 :
352 :
353 : //------------------------------------------------
354 : //
355 : // path_ref
356 : //
357 : //------------------------------------------------
358 :
359 : inline
360 10616 : path_ref::
361 : path_ref(
362 10616 : url_impl const& impl) noexcept
363 : {
364 10616 : if(impl.from_ == url_impl::from::url)
365 : {
366 10054 : impl_ = &impl;
367 : }
368 : else
369 : {
370 562 : core::string_view s = impl.get(id_path);
371 562 : data_ = s.data();
372 562 : size_ = s.size();
373 562 : nseg_ = impl.nseg_;
374 562 : dn_ = impl.decoded_[id_path];
375 : }
376 10616 : }
377 :
378 : inline
379 222 : path_ref::
380 : path_ref(
381 : core::string_view s,
382 : std::size_t dn,
383 222 : std::size_t nseg) noexcept
384 444 : : data_(s.data())
385 222 : , size_(s.size())
386 222 : , nseg_(nseg)
387 222 : , dn_(dn)
388 : {
389 222 : }
390 :
391 : inline
392 : pct_string_view
393 12780 : path_ref::
394 : buffer() const noexcept
395 : {
396 12780 : if(impl_)
397 10336 : return make_pct_string_view_unsafe(
398 10336 : impl_->cs_ +
399 10336 : impl_->offset(id_path),
400 10336 : impl_->len(id_path),
401 20672 : impl_->decoded_[id_path]);
402 2444 : return make_pct_string_view_unsafe(
403 2444 : data_, size_, dn_);
404 : }
405 :
406 : inline
407 : std::size_t
408 35915 : path_ref::
409 : size() const noexcept
410 : {
411 35915 : if(impl_)
412 34354 : return impl_->len(id_path);
413 1561 : return size_;
414 : }
415 :
416 : inline
417 : char const*
418 39066 : path_ref::
419 : data() const noexcept
420 : {
421 39066 : if(impl_)
422 33342 : return impl_->cs_ +
423 33342 : impl_->offset(id_path);
424 5724 : return data_;
425 : }
426 :
427 : inline
428 : char const*
429 16785 : path_ref::
430 : end() const noexcept
431 : {
432 16785 : if(impl_)
433 15072 : return impl_->cs_ +
434 15072 : impl_->offset(id_query);
435 1713 : return data_ + size_;
436 : }
437 :
438 : inline
439 : std::size_t
440 44197 : path_ref::
441 : nseg() const noexcept
442 : {
443 44197 : if(impl_)
444 40398 : return impl_->nseg_;
445 3799 : return nseg_;
446 : }
447 :
448 : inline
449 : std::size_t
450 17364 : path_ref::
451 : decoded_size() const noexcept
452 : {
453 17364 : if(impl_)
454 16588 : return impl_->decoded_[id_path];
455 776 : return dn_;
456 : }
457 :
458 : //------------------------------------------------
459 : //
460 : // query_ref
461 : //
462 : //------------------------------------------------
463 :
464 : inline
465 3333 : query_ref::
466 : query_ref(
467 : core::string_view s,
468 : std::size_t dn,
469 3333 : std::size_t nparam) noexcept
470 6666 : : data_(s.data())
471 3333 : , size_(s.size())
472 3333 : , nparam_(nparam)
473 3333 : , dn_(dn)
474 : {
475 3333 : }
476 :
477 : inline
478 8962 : query_ref::
479 : query_ref(
480 8962 : url_impl const& impl) noexcept
481 : {
482 8962 : if(impl.from_ == url_impl::from::url)
483 : {
484 8831 : 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 8962 : }
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 32286 : query_ref::
533 : size() const noexcept
534 : {
535 32286 : if(impl_)
536 28517 : return impl_->len(id_query);
537 3769 : if(size_ > 0)
538 3727 : return size_ + 1;
539 42 : return question_mark_;
540 : }
541 :
542 : // no '?'
543 : inline
544 : char const*
545 19117 : query_ref::
546 : begin() const noexcept
547 : {
548 19117 : if(impl_)
549 : {
550 : // using the offset array here
551 15173 : auto pos = impl_->offset_[id_query];
552 15173 : auto pos1 = impl_->offset_[id_frag];
553 15173 : if(pos < pos1)
554 15173 : return impl_->cs_ + pos + 1; // no '?'
555 : // empty
556 MIS 0 : return impl_->cs_ + pos;
557 : }
558 HIT 3944 : return data_;
559 :
560 : }
561 :
562 : inline
563 : char const*
564 10123 : query_ref::
565 : end() const noexcept
566 : {
567 10123 : if(impl_)
568 8590 : return impl_->cs_ +
569 8590 : impl_->offset(id_frag);
570 1533 : return data_ + size_;
571 : }
572 :
573 : inline
574 : std::size_t
575 48601 : query_ref::
576 : nparam() const noexcept
577 : {
578 48601 : if(impl_)
579 42461 : return impl_->nparam_;
580 6140 : return nparam_;
581 : }
582 :
583 : } // detail
584 : } // urls
585 : } // boost
586 :
587 : #endif
|