include/boost/url/detail/impl/url_impl.hpp

97.4% Lines (223/229) 100.0% Functions (35/35)
include/boost/url/detail/impl/url_impl.hpp
Line TLA Hits 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 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 ++pos; // no '?'
513 return make_pct_string_view_unsafe(
514 impl_->cs_ + pos,
515 pos1 - pos,
516 impl_->decoded_[id_query]);
517 }
518 // empty
519 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 return impl_->cs_ + pos;
557 }
558 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
588