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