GCC Code Coverage Report


Directory: libs/url/
File: libs/url/src/authority_view.cpp
Date: 2024-08-19 20:08:56
Exec Total Coverage
Lines: 164 164 100.0%
Functions: 24 24 100.0%
Branches: 63 86 73.3%

Line Branch Exec Source
1 //
2 // Copyright (c) 2019 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 <boost/url/authority_view.hpp>
13 #include "detail/normalize.hpp"
14 #include <boost/url/grammar/parse.hpp>
15 #include <boost/url/rfc/authority_rule.hpp>
16 #include <boost/url/rfc/pct_encoded_rule.hpp>
17 #include <array>
18 #include <ostream>
19
20 namespace boost {
21 namespace urls {
22
23 //------------------------------------------------
24
25 namespace detail {
26
27 authority_view
28 2349 url_impl::
29 construct_authority() const noexcept
30 {
31 2349 return authority_view(*this);
32 }
33
34 } // detail
35
36 //------------------------------------------------
37
38 2349 authority_view::
39 authority_view(
40 2349 detail::url_impl const& u) noexcept
41 2349 : u_(u)
42 {
43 2349 }
44
45 //------------------------------------------------
46
47 23358 authority_view::
48 23358 ~authority_view()
49 {
50 23358 }
51
52 3612 authority_view::
53 3612 authority_view() noexcept
54 3612 : u_(from::authority)
55 {
56 3612 }
57
58 2 authority_view::
59 authority_view(
60 2 core::string_view s)
61 : authority_view(
62 2 parse_authority(s
63
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 ).value(BOOST_URL_POS))
64 {
65 2 }
66
67 5718 authority_view::
68 authority_view(
69 authority_view const&) noexcept = default;
70
71 authority_view&
72 1708 authority_view::
73 operator=(
74 authority_view const&) noexcept = default;
75
76 //------------------------------------------------
77 //
78 // Userinfo
79 //
80 //------------------------------------------------
81
82 bool
83 568 authority_view::
84 has_userinfo() const noexcept
85 {
86 568 auto n = u_.len(id_pass);
87
2/2
✓ Branch 0 taken 476 times.
✓ Branch 1 taken 92 times.
568 if(n == 0)
88 476 return false;
89
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 92 times.
92 BOOST_ASSERT(u_.get(
90 id_pass).ends_with('@'));
91 92 return true;
92 }
93
94 pct_string_view
95 52 authority_view::
96 encoded_userinfo() const noexcept
97 {
98 52 auto s = u_.get(
99 id_user, id_host);
100
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 50 times.
52 if(s.empty())
101 2 return s;
102
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
50 BOOST_ASSERT(
103 s.ends_with('@'));
104 50 s.remove_suffix(1);
105 50 return make_pct_string_view_unsafe(
106 s.data(),
107 s.size(),
108 50 u_.decoded_[id_user] +
109 50 u_.decoded_[id_pass] +
110 100 has_password());
111 }
112
113 pct_string_view
114 73 authority_view::
115 encoded_user() const noexcept
116 {
117 73 auto s = u_.get(id_user);
118 73 return make_pct_string_view_unsafe(
119 s.data(),
120 s.size(),
121 146 u_.decoded_[id_user]);
122 }
123
124 bool
125 112 authority_view::
126 has_password() const noexcept
127 {
128 112 auto const n = u_.len(id_pass);
129
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 33 times.
112 if(n > 1)
130 {
131
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 79 times.
79 BOOST_ASSERT(u_.get(id_pass
132 ).starts_with(':'));
133
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 79 times.
79 BOOST_ASSERT(u_.get(id_pass
134 ).ends_with('@'));
135 79 return true;
136 }
137
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 33 times.
33 BOOST_ASSERT(n == 0 || u_.get(
138 id_pass).ends_with('@'));
139 33 return false;
140 }
141
142 pct_string_view
143 57 authority_view::
144 encoded_password() const noexcept
145 {
146 57 auto s = u_.get(id_pass);
147
2/3
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
57 switch(s.size())
148 {
149 8 case 1:
150
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 BOOST_ASSERT(
151 s.starts_with('@'));
152 8 s.remove_prefix(1);
153 BOOST_FALLTHROUGH;
154 8 case 0:
155 8 return make_pct_string_view_unsafe(
156 8 s.data(), s.size(), 0);
157 49 default:
158 49 break;
159 }
160
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
49 BOOST_ASSERT(s.ends_with('@'));
161
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
49 BOOST_ASSERT(s.starts_with(':'));
162 49 return make_pct_string_view_unsafe(
163 49 s.data() + 1,
164 49 s.size() - 2,
165 98 u_.decoded_[id_pass]);
166 }
167
168 //------------------------------------------------
169 //
170 // Host
171 //
172 //------------------------------------------------
173 /*
174 host_type host_type() // ipv4, ipv6, ipvfuture, name
175
176 std::string host() // return encoded_host().decode()
177 pct_string_view encoded_host() // return host part, as-is
178 std::string host_address() // return encoded_host_address().decode()
179 pct_string_view encoded_host_address() // ipv4, ipv6, ipvfut, or encoded name, no brackets
180
181 ipv4_address host_ipv4_address() // return ipv4_address or {}
182 ipv6_address host_ipv6_address() // return ipv6_address or {}
183 core::string_view host_ipvfuture() // return ipvfuture or {}
184 std::string host_name() // return decoded name or ""
185 pct_string_view encoded_host_name() // return encoded host name or ""
186 */
187
188 pct_string_view
189 330 authority_view::
190 encoded_host() const noexcept
191 {
192 330 return u_.pct_get(id_host);
193 }
194
195 pct_string_view
196 7 authority_view::
197 encoded_host_address() const noexcept
198 {
199 7 core::string_view s = u_.get(id_host);
200 std::size_t n;
201
2/3
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
7 switch(u_.host_type_)
202 {
203 5 case urls::host_type::name:
204 case urls::host_type::ipv4:
205 5 n = u_.decoded_[id_host];
206 5 break;
207
208 2 case urls::host_type::ipv6:
209 case urls::host_type::ipvfuture:
210 {
211
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 BOOST_ASSERT(
212 u_.decoded_[id_host] ==
213 s.size());
214
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 BOOST_ASSERT(s.size() >= 2);
215
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 BOOST_ASSERT(s.front() == '[');
216
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 BOOST_ASSERT(s.back() == ']');
217 2 s = s.substr(1, s.size() - 2);
218 2 n = u_.decoded_[id_host] - 2;
219 2 break;
220 }
221 // LCOV_EXCL_START
222 default:
223 case urls::host_type::none:
224 /*
225 * This condition is for correctness
226 * only.
227 * This should never happen, because
228 * the `host_rule` will set the host
229 * type to `name` when it's empty.
230 * This is correct because `reg-name`
231 * accepts empty strings.
232 */
233 BOOST_ASSERT(s.empty());
234 n = 0;
235 break;
236 // LCOV_EXCL_STOP
237 }
238 7 return make_pct_string_view_unsafe(
239 7 s.data(), s.size(), n);
240 }
241
242 urls::ipv4_address
243 2 authority_view::
244 host_ipv4_address() const noexcept
245 {
246
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(u_.host_type_ !=
247 urls::host_type::ipv4)
248 1 return {};
249 1 ipv4_address::bytes_type b{{}};
250 1 std::memcpy(
251 1 &b[0], &u_.ip_addr_[0], b.size());
252 1 return urls::ipv4_address(b);
253 }
254
255 urls::ipv6_address
256 2 authority_view::
257 host_ipv6_address() const noexcept
258 {
259
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(u_.host_type_ !=
260 urls::host_type::ipv6)
261 1 return {};
262 1 ipv6_address::bytes_type b{{}};
263 1 std::memcpy(
264 1 &b[0], &u_.ip_addr_[0], b.size());
265 1 return urls::ipv6_address(b);
266 }
267
268 core::string_view
269 2 authority_view::
270 host_ipvfuture() const noexcept
271 {
272
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(u_.host_type_ !=
273 urls::host_type::ipvfuture)
274 1 return {};
275 1 core::string_view s = u_.get(id_host);
276
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 BOOST_ASSERT(s.size() >= 6);
277
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 BOOST_ASSERT(s.front() == '[');
278
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 BOOST_ASSERT(s.back() == ']');
279 1 s = s.substr(1, s.size() - 2);
280 1 return s;
281 }
282
283 pct_string_view
284 3 authority_view::
285 encoded_host_name() const noexcept
286 {
287
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if(u_.host_type_ !=
288 urls::host_type::name)
289 1 return {};
290 2 return u_.pct_get(id_host);
291 }
292
293 //------------------------------------------------
294 //
295 // Port
296 //
297 //------------------------------------------------
298
299 bool
300 567 authority_view::
301 has_port() const noexcept
302 {
303 567 auto const n = u_.len(id_port);
304
2/2
✓ Branch 0 taken 282 times.
✓ Branch 1 taken 285 times.
567 if(n == 0)
305 282 return false;
306
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 285 times.
285 BOOST_ASSERT(
307 u_.get(id_port).starts_with(':'));
308 285 return true;
309 }
310
311 core::string_view
312 112 authority_view::
313 port() const noexcept
314 {
315 112 auto s = u_.get(id_port);
316
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 108 times.
112 if(s.empty())
317 4 return s;
318
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
108 BOOST_ASSERT(has_port());
319 108 return s.substr(1);
320 }
321
322 std::uint16_t
323 20 authority_view::
324 port_number() const noexcept
325 {
326
3/4
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
20 BOOST_ASSERT(
327 has_port() ||
328 u_.port_number_ == 0);
329 20 return u_.port_number_;
330 }
331
332 pct_string_view
333 10 authority_view::
334 encoded_host_and_port() const noexcept
335 {
336 10 return u_.get(id_host, id_end);
337 }
338
339 //------------------------------------------------
340 //
341 // Parsing
342 //
343 //------------------------------------------------
344
345 system::result<authority_view>
346 44 parse_authority(
347 core::string_view s) noexcept
348 {
349 44 return grammar::parse(s, authority_rule);
350 }
351
352 //------------------------------------------------
353 //
354 // Comparisons
355 //
356 //------------------------------------------------
357
358 int
359 182 authority_view::
360 compare(const authority_view& other) const noexcept
361 {
362 182 auto comp = static_cast<int>(has_userinfo()) -
363 182 static_cast<int>(other.has_userinfo());
364
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 181 times.
182 if ( comp != 0 )
365 1 return comp;
366
367
2/2
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 158 times.
181 if (has_userinfo())
368 {
369 46 comp = detail::compare_encoded(
370 23 encoded_user(),
371 23 other.encoded_user());
372
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 16 times.
23 if ( comp != 0 )
373 7 return comp;
374
375 16 comp = static_cast<int>(has_password()) -
376 16 static_cast<int>(other.has_password());
377
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 15 times.
16 if ( comp != 0 )
378 1 return comp;
379
380
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 if (has_password())
381 {
382 30 comp = detail::compare_encoded(
383 15 encoded_password(),
384 15 other.encoded_password());
385
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1 times.
15 if ( comp != 0 )
386 14 return comp;
387 }
388 }
389
390 318 comp = detail::ci_compare_encoded(
391 159 encoded_host(),
392 159 other.encoded_host());
393
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 142 times.
159 if ( comp != 0 )
394 17 return comp;
395
396 142 comp = static_cast<int>(has_port()) -
397 142 static_cast<int>(other.has_port());
398
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 135 times.
142 if ( comp != 0 )
399 7 return comp;
400
401
2/2
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 89 times.
135 if (has_port())
402 {
403 46 comp = detail::compare(
404 port(),
405 other.port());
406
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 4 times.
46 if ( comp != 0 )
407 42 return comp;
408 }
409
410 93 return 0;
411 }
412
413 } // urls
414 } // boost
415
416