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 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 ++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 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 return impl_->cs_ + pos;
557 }
558 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
588