GCC Code Coverage Report


Directory: libs/url/
File: src/detail/url_impl.cpp
Date: 2025-11-12 22:47:45
Exec Total Coverage
Lines: 215 220 97.7%
Functions: 35 35 100.0%
Branches: 55 66 83.3%

Line Branch Exec Source
1 //
2 // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/url
8 //
9
10
11 #include <boost/url/detail/config.hpp>
12 #include "path.hpp"
13 #include <boost/url/detail/url_impl.hpp>
14 #include <boost/url/authority_view.hpp>
15 #include <boost/assert.hpp>
16 #include <cstring>
17
18 namespace boost {
19 namespace urls {
20 namespace detail {
21
22 #if defined(__GNUC__) && ! defined(__clang__) && defined(__MINGW32__)
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Warray-bounds"
25 #endif
26
27 //------------------------------------------------
28 //
29 // url_impl
30 //
31 //------------------------------------------------
32
33 void
34 2287 url_impl::
35 apply_scheme(
36 core::string_view s) noexcept
37 {
38 2287 scheme_ = string_to_scheme(s);
39 2287 set_size(id_scheme, s.size() + 1);
40 2287 }
41
42 void
43 381 url_impl::
44 apply_userinfo(
45 pct_string_view const& user,
46 pct_string_view const* pass) noexcept
47 {
48 // this function is for
49 // authority_view_rule only
50
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 381 times.
381 BOOST_ASSERT(from_ == from::authority);
51
52 // userinfo
53 381 set_size(id_user, user.size());
54 381 decoded_[id_user] =
55 381 user.decoded_size();
56
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 129 times.
381 if(pass)
57 {
58 252 set_size(id_pass,
59 252 pass->size() + 2);
60 252 decoded_[id_pass] =
61 252 pass->decoded_size();
62 }
63 else
64 {
65 // trailing '@'
66 129 set_size(id_pass, 1 );
67 }
68 381 }
69
70 void
71 1888 url_impl::
72 apply_host(
73 host_type ht,
74 pct_string_view s,
75 unsigned char const* addr) noexcept
76 {
77 // this function is for
78 // authority_view_rule only
79
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 BOOST_ASSERT(from_ == from::authority);
80
81 // host, port
82 1888 host_type_ = ht;
83 1888 set_size(id_host, s.size());
84 1888 decoded_[id_host] =
85 1888 s.decoded_size();
86 1888 std::memcpy(
87 1888 ip_addr_,
88 addr,
89 sizeof(ip_addr_));
90 1888 }
91
92 void
93 260 url_impl::
94 apply_port(
95 core::string_view s,
96 unsigned short pn) noexcept
97 {
98 // this function is for
99 // authority_view_rule only
100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 260 times.
260 BOOST_ASSERT(from_ == from::authority);
101
102 260 port_number_ = pn;
103 260 set_size(id_port, 1 + s.size());
104 260 }
105
106 void
107 1830 url_impl::
108 apply_authority(
109 authority_view const& a) noexcept
110 {
111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1830 times.
1830 BOOST_ASSERT(from_ != from::authority);
112
113 // userinfo
114 1830 set_size(id_user,
115 1830 a.u_.len(id_user) +
116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1830 times.
1830 (from_ == from::authority ? 0 : 2));
117 1830 set_size(id_pass, a.u_.len(id_pass));
118 1830 decoded_[id_user] = a.u_.decoded_[id_user];
119 1830 decoded_[id_pass] = a.u_.decoded_[id_pass];
120
121 // host, port
122 1830 host_type_ = a.u_.host_type_;
123 1830 port_number_ = a.u_.port_number_;
124 1830 set_size(id_host, a.u_.len(id_host));
125 1830 set_size(id_port, a.u_.len(id_port));
126 1830 std::memcpy(
127 1830 ip_addr_,
128 1830 a.u_.ip_addr_,
129 sizeof(ip_addr_));
130 1830 decoded_[id_host] = a.u_.decoded_[id_host];
131 1830 }
132
133 void
134 3573 url_impl::
135 apply_path(
136 pct_string_view s,
137 std::size_t nseg) noexcept
138 {
139 3573 set_size(id_path, s.size());
140 3573 decoded_[id_path] = s.decoded_size();
141 3573 nseg_ = detail::path_segments(s, nseg);
142 3573 }
143
144 void
145 447 url_impl::
146 apply_query(
147 pct_string_view s,
148 std::size_t n) noexcept
149 {
150 447 nparam_ = n;
151 447 set_size(id_query, 1 + s.size());
152 447 decoded_[id_query] = s.decoded_size();
153 447 }
154
155 void
156 214 url_impl::
157 apply_frag(
158 pct_string_view s) noexcept
159 {
160 214 set_size(id_frag, s.size() + 1);
161 214 decoded_[id_frag] = s.decoded_size();
162 214 }
163
164 // return length of [first, last)
165 auto
166 20450 url_impl::
167 len(
168 int first,
169 int last) const noexcept ->
170 std::size_t
171 {
172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20450 times.
20450 BOOST_ASSERT(first <= last);
173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20450 times.
20450 BOOST_ASSERT(last <= id_end);
174 20450 return offset(last) - offset(first);
175 }
176
177 // return length of part
178 auto
179 269128 url_impl::
180 len(int id) const noexcept ->
181 std::size_t
182 {
183 return id == id_end
184
1/2
✓ Branch 0 taken 269128 times.
✗ Branch 1 not taken.
538256 ? zero_
185 269128 : ( offset(id + 1) -
186 538256 offset(id) );
187 }
188
189 // return offset of id
190 auto
191 704415 url_impl::
192 offset(int id) const noexcept ->
193 std::size_t
194 {
195 return
196 id == id_scheme
197
2/2
✓ Branch 0 taken 651438 times.
✓ Branch 1 taken 52977 times.
704415 ? zero_
198 704415 : offset_[id];
199 }
200
201 // return id as string
202 core::string_view
203 47922 url_impl::
204 get(int id) const noexcept
205 {
206 return {
207 47922 cs_ + offset(id), len(id) };
208 }
209
210 // return [first, last) as string
211 core::string_view
212 889 url_impl::
213 get(int first,
214 int last) const noexcept
215 {
216 889 return { cs_ + offset(first),
217 889 offset(last) - offset(first) };
218 }
219
220 // return id as pct-string
221 pct_string_view
222 2203 url_impl::
223 pct_get(
224 int id) const noexcept
225 {
226 2203 return make_pct_string_view_unsafe(
227 2203 cs_ + offset(id),
228 len(id),
229 4406 decoded_[id]);
230 }
231
232 // return [first, last) as pct-string
233 pct_string_view
234 120 url_impl::
235 pct_get(
236 int first,
237 int last) const noexcept
238 {
239 120 auto const pos = offset(first);
240 120 std::size_t n = 0;
241
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 120 times.
360 for(auto i = first; i < last;)
242 240 n += decoded_[i++];
243 120 return make_pct_string_view_unsafe(
244 120 cs_ + pos,
245 120 offset(last) - pos,
246 120 n);
247 }
248
249 //------------------------------------------------
250
251 // change id to size n
252 void
253 19467 url_impl::
254 set_size(
255 int id,
256 std::size_t n) noexcept
257 {
258 19467 auto d = n - len(id);
259 19467 for(auto i = id + 1;
260
2/2
✓ Branch 0 taken 98776 times.
✓ Branch 1 taken 19467 times.
118243 i <= id_end; ++i)
261 98776 offset_[i] += d;
262 19467 }
263
264 // trim id to size n,
265 // moving excess into id+1
266 void
267 831 url_impl::
268 split(
269 int id,
270 std::size_t n) noexcept
271 {
272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 831 times.
831 BOOST_ASSERT(id < id_end - 1);
273 //BOOST_ASSERT(n <= len(id));
274 831 offset_[id + 1] = offset(id) + n;
275 831 }
276
277 // add n to [first, last]
278 void
279 921 url_impl::
280 adjust_right(
281 int first,
282 int last,
283 std::size_t n) noexcept
284 {
285 921 for(int i = first;
286
2/2
✓ Branch 0 taken 4442 times.
✓ Branch 1 taken 921 times.
5363 i <= last; ++i)
287 4442 offset_[i] += n;
288 921 }
289
290 // remove n from [first, last]
291 void
292 690 url_impl::
293 adjust_left(
294 int first,
295 int last,
296 std::size_t n) noexcept
297 {
298 690 for(int i = first;
299
2/2
✓ Branch 0 taken 2704 times.
✓ Branch 1 taken 690 times.
3394 i <= last; ++i)
300 2704 offset_[i] -= n;
301 690 }
302
303 // set [first, last) offset
304 void
305 1592 url_impl::
306 collapse(
307 int first,
308 int last,
309 std::size_t n) noexcept
310 {
311 1592 for(int i = first + 1;
312
2/2
✓ Branch 0 taken 545 times.
✓ Branch 1 taken 1592 times.
2137 i < last; ++i)
313 545 offset_[i] = n;
314 1592 }
315
316
317 //------------------------------------------------
318 //
319 // path_ref
320 //
321 //------------------------------------------------
322
323 2044 path_ref::
324 path_ref(
325 2044 url_impl const& impl) noexcept
326 {
327
2/2
✓ Branch 0 taken 1587 times.
✓ Branch 1 taken 457 times.
2044 if(impl.from_ == url_impl::from::url)
328 {
329 1587 impl_ = &impl;
330 }
331 else
332 {
333 457 core::string_view s = impl.get(id_path);
334 457 data_ = s.data();
335 457 size_ = s.size();
336 457 nseg_ = impl.nseg_;
337 457 dn_ = impl.decoded_[id_path];
338 }
339 2044 }
340
341 181 path_ref::
342 path_ref(
343 core::string_view s,
344 std::size_t dn,
345 181 std::size_t nseg) noexcept
346 362 : data_(s.data())
347 181 , size_(s.size())
348 181 , nseg_(nseg)
349 181 , dn_(dn)
350 {
351 181 }
352
353 pct_string_view
354 4701 path_ref::
355 buffer() const noexcept
356 {
357
2/2
✓ Branch 0 taken 2389 times.
✓ Branch 1 taken 2312 times.
4701 if(impl_)
358 2389 return make_pct_string_view_unsafe(
359 2389 impl_->cs_ +
360 2389 impl_->offset(id_path),
361 2389 impl_->len(id_path),
362 4778 impl_->decoded_[id_path]);
363 2312 return make_pct_string_view_unsafe(
364 2312 data_, size_, dn_);
365 }
366
367 std::size_t
368 4431 path_ref::
369 size() const noexcept
370 {
371
2/2
✓ Branch 0 taken 3116 times.
✓ Branch 1 taken 1315 times.
4431 if(impl_)
372 3116 return impl_->len(id_path);
373 1315 return size_;
374 }
375
376 char const*
377 12801 path_ref::
378 data() const noexcept
379 {
380
2/2
✓ Branch 0 taken 7466 times.
✓ Branch 1 taken 5335 times.
12801 if(impl_)
381 7466 return impl_->cs_ +
382 7466 impl_->offset(id_path);
383 5335 return data_;
384 }
385
386 char const*
387 4363 path_ref::
388 end() const noexcept
389 {
390
2/2
✓ Branch 0 taken 2839 times.
✓ Branch 1 taken 1524 times.
4363 if(impl_)
391 2839 return impl_->cs_ +
392 2839 impl_->offset(id_query);
393 1524 return data_ + size_;
394 }
395
396 std::size_t
397 9398 path_ref::
398 nseg() const noexcept
399 {
400
2/2
✓ Branch 0 taken 6155 times.
✓ Branch 1 taken 3243 times.
9398 if(impl_)
401 6155 return impl_->nseg_;
402 3243 return nseg_;
403 }
404
405 std::size_t
406 2012 path_ref::
407 decoded_size() const noexcept
408 {
409
2/2
✓ Branch 0 taken 1359 times.
✓ Branch 1 taken 653 times.
2012 if(impl_)
410 1359 return impl_->decoded_[id_path];
411 653 return dn_;
412 }
413
414 //------------------------------------------------
415 //
416 // query_ref
417 //
418 //------------------------------------------------
419
420 701 query_ref::
421 query_ref(
422 core::string_view s,
423 std::size_t dn,
424 701 std::size_t nparam) noexcept
425 1402 : data_(s.data())
426 701 , size_(s.size())
427 701 , nparam_(nparam)
428 701 , dn_(dn)
429 {
430 701 }
431
432 450 query_ref::
433 query_ref(
434 450 url_impl const& impl) noexcept
435 {
436
2/2
✓ Branch 0 taken 353 times.
✓ Branch 1 taken 97 times.
450 if(impl.from_ == url_impl::from::url)
437 {
438 353 impl_ = &impl;
439 }
440 else
441 {
442 97 core::string_view s = impl.get(id_query);
443
2/2
✓ Branch 1 taken 91 times.
✓ Branch 2 taken 6 times.
97 if (!s.empty())
444 {
445 91 s.remove_prefix(1);
446 91 question_mark_ = true;
447 }
448 97 data_ = s.data();
449 97 size_ = s.size();
450 97 nparam_ = impl.nparam_;
451 97 dn_ = impl.decoded_[id_query];
452 }
453 450 }
454
455 pct_string_view
456 471 query_ref::
457 buffer() const noexcept
458 {
459
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 469 times.
471 if(impl_)
460 {
461 2 auto pos = impl_->offset_[id_query];
462 2 auto pos1 = impl_->offset_[id_frag];
463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(pos < pos1)
464 {
465 ++pos; // no '?'
466 return make_pct_string_view_unsafe(
467 impl_->cs_ + pos,
468 pos1 - pos,
469 impl_->decoded_[id_query]);
470 }
471 // empty
472 2 return make_pct_string_view_unsafe(
473 2 impl_->cs_ + pos,
474 0,
475 2 0);
476 }
477 // no '?'
478 469 return make_pct_string_view_unsafe(
479 469 data_, size_, dn_);
480 }
481
482 // with '?'
483 std::size_t
484 5331 query_ref::
485 size() const noexcept
486 {
487
2/2
✓ Branch 0 taken 2011 times.
✓ Branch 1 taken 3320 times.
5331 if(impl_)
488 2011 return impl_->len(id_query);
489
2/2
✓ Branch 0 taken 3284 times.
✓ Branch 1 taken 36 times.
3320 if(size_ > 0)
490 3284 return size_ + 1;
491 36 return question_mark_;
492 }
493
494 // no '?'
495 char const*
496 5854 query_ref::
497 begin() const noexcept
498 {
499
2/2
✓ Branch 0 taken 2278 times.
✓ Branch 1 taken 3576 times.
5854 if(impl_)
500 {
501 // using the offset array here
502 2278 auto pos = impl_->offset_[id_query];
503 2278 auto pos1 = impl_->offset_[id_frag];
504
1/2
✓ Branch 0 taken 2278 times.
✗ Branch 1 not taken.
2278 if(pos < pos1)
505 2278 return impl_->cs_ + pos + 1; // no '?'
506 // empty
507 return impl_->cs_ + pos;
508 }
509 3576 return data_;
510
511 }
512
513 char const*
514 2298 query_ref::
515 end() const noexcept
516 {
517
2/2
✓ Branch 0 taken 910 times.
✓ Branch 1 taken 1388 times.
2298 if(impl_)
518 910 return impl_->cs_ +
519 910 impl_->offset(id_frag);
520 1388 return data_ + size_;
521 }
522
523 std::size_t
524 8992 query_ref::
525 nparam() const noexcept
526 {
527
2/2
✓ Branch 0 taken 3151 times.
✓ Branch 1 taken 5841 times.
8992 if(impl_)
528 3151 return impl_->nparam_;
529 5841 return nparam_;
530 }
531
532 #if defined(__GNUC__) && ! defined(__clang__) && defined(__MINGW32__)
533 #pragma GCC diagnostic pop
534 #endif
535
536 } // detail
537 } // urls
538 } // boost
539