GCC Code Coverage Report


Directory: libs/url/
File: include/boost/url/ipv6_address.hpp
Date: 2025-04-22 15:26:26
Exec Total Coverage
Lines: 14 14 100.0%
Functions: 6 6 100.0%
Branches: 2 4 50.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2022 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_IPV6_ADDRESS_HPP
12 #define BOOST_URL_IPV6_ADDRESS_HPP
13
14 #include <boost/url/detail/config.hpp>
15 #include <boost/url/error.hpp>
16 #include <boost/url/error_types.hpp>
17 #include <boost/core/detail/string_view.hpp>
18 #include <boost/url/grammar/string_token.hpp>
19 #include <array>
20 #include <cstdint>
21 #include <iosfwd>
22
23 namespace boost {
24 namespace urls {
25
26 #ifndef BOOST_URL_DOCS
27 class ipv4_address;
28 #endif
29
30 /** An IP version 6 style address.
31
32 Objects of this type are used to construct,
33 parse, and manipulate IP version 6 addresses.
34
35 @par BNF
36 @code
37 IPv6address = 6( h16 ":" ) ls32
38 / "::" 5( h16 ":" ) ls32
39 / [ h16 ] "::" 4( h16 ":" ) ls32
40 / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
41 / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
42 / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
43 / [ *4( h16 ":" ) h16 ] "::" ls32
44 / [ *5( h16 ":" ) h16 ] "::" h16
45 / [ *6( h16 ":" ) h16 ] "::"
46
47 ls32 = ( h16 ":" h16 ) / IPv4address
48 ; least-significant 32 bits of address
49
50 h16 = 1*4HEXDIG
51 ; 16 bits of address represented in hexadecimal
52 @endcode
53
54 @par Specification
55 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
56 >IP Version 6 Addressing Architecture (rfc4291)</a>
57 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
58 >3.2.2. Host (rfc3986)</a>
59
60 @see
61 @ref ipv4_address,
62 @ref parse_ipv6_address.
63 */
64 class ipv6_address
65 {
66 public:
67 /** The number of characters in the longest possible IPv6 string.
68
69 The longest IPv6 address is:
70 @code
71 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
72 @endcode
73
74 @see
75 @ref to_buffer.
76 */
77 // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
78 // ::ffff:255.255.255.255
79 // 12345678901234567890123456789012345678901234567890
80 // 1 2 3 4
81 static
82 constexpr
83 std::size_t max_str_len = 49;
84
85 /** The type used to represent an address as an array of bytes.
86
87 Octets are stored in network byte order.
88 */
89 using bytes_type = std::array<
90 unsigned char, 16>;
91
92 /** Constructor.
93
94 Default constructed objects represent
95 the unspecified address.
96
97 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2"
98 >2.5.2. The Unspecified Address</a>
99
100 @see
101 @ref is_unspecified
102 */
103 96 ipv6_address() = default;
104
105 /** Constructor.
106 */
107 ipv6_address(
108 ipv6_address const&) = default;
109
110 /** Copy Assignment
111
112 @return `*this`
113 */
114 ipv6_address&
115 operator=(
116 ipv6_address const&) = default;
117
118 /** Construct from an array of bytes.
119
120 This function constructs an address
121 from the array in `bytes`, which is
122 interpreted in big-endian.
123
124 @param bytes The value to construct from.
125 */
126 BOOST_URL_DECL
127 ipv6_address(
128 bytes_type const& bytes) noexcept;
129
130 /** Construct from an IPv4 address.
131
132 This function constructs an IPv6 address
133 from the IPv4 address `addr`. The resulting
134 address is an IPv4-Mapped IPv6 Address.
135
136 @param addr The address to construct from.
137
138 @par Specification
139 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2"
140 >2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
141 */
142 BOOST_URL_DECL
143 ipv6_address(
144 ipv4_address const& addr) noexcept;
145
146 /** Construct from a string.
147
148 This function constructs an address from
149 the string `s`, which must contain a valid
150 IPv6 address string or else an exception
151 is thrown.
152
153 @note For a non-throwing parse function,
154 use @ref parse_ipv6_address.
155
156 @par Exception Safety
157 Exceptions thrown on invalid input.
158
159 @throw system_error
160 The input failed to parse correctly.
161
162 @param s The string to parse.
163
164 @par Specification
165 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
166 >3.2.2. Host (rfc3986)</a>
167
168 @see
169 @ref parse_ipv6_address.
170 */
171 BOOST_URL_DECL
172 ipv6_address(
173 core::string_view s);
174
175 /** Return the address as bytes, in network byte order
176
177 @return The address as an array of bytes.
178 */
179 bytes_type
180 120 to_bytes() const noexcept
181 {
182 120 return addr_;
183 }
184
185 /** Return the address as a string.
186
187 The returned string does not
188 contain surrounding square brackets.
189
190 When called with no arguments, the
191 return type is `std::string`.
192 Otherwise, the return type and style
193 of output is determined by which string
194 token is passed.
195
196 @par Example
197 @code
198 ipv6_address::bytes_type b = {{
199 0, 1, 0, 2, 0, 3, 0, 4,
200 0, 5, 0, 6, 0, 7, 0, 8 }};
201 ipv6_address a(b);
202 assert(a.to_string() == "1:2:3:4:5:6:7:8");
203 assert( ipv4_address(0x01020304).to_string() == "1.2.3.4" );
204 @endcode
205
206 @par Complexity
207 Constant.
208
209 @par Exception Safety
210 Strong guarantee.
211 Calls to allocate may throw.
212 String tokens may throw exceptions.
213
214 @return The return type of the string token.
215 If the token parameter is omitted, then
216 a new `std::string` is returned.
217 Otherwise, the function return type
218 is the result type of the token.
219
220 @param token An optional string token.
221
222 @par Specification
223 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.2">
224 2.2. Text Representation of Addresses (rfc4291)</a>
225 */
226 template<BOOST_URL_STRTOK_TPARAM>
227 BOOST_URL_STRTOK_RETURN
228 38 to_string(
229 BOOST_URL_STRTOK_ARG(token)) const
230 {
231 38 to_string_impl(token);
232 38 return token.result();
233 }
234
235 /** Write a dotted decimal string representing the address to a buffer
236
237 The resulting buffer is not null-terminated.
238
239 @throw std::length_error `dest_size < ipv6_address::max_str_len`
240
241 @return The formatted string
242
243 @param dest The buffer in which to write,
244 which must have at least `dest_size` space.
245
246 @param dest_size The size of the output buffer.
247 */
248 BOOST_URL_DECL
249 core::string_view
250 to_buffer(
251 char* dest,
252 std::size_t dest_size) const;
253
254 /** Return true if the address is unspecified
255
256 The address 0:0:0:0:0:0:0:0 is called the
257 unspecified address. It indicates the
258 absence of an address.
259
260 @return `true` if the address is unspecified
261
262 @par Specification
263 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2">
264 2.5.2. The Unspecified Address (rfc4291)</a>
265 */
266 BOOST_URL_DECL
267 bool
268 is_unspecified() const noexcept;
269
270 /** Return true if the address is a loopback address
271
272 The unicast address 0:0:0:0:0:0:0:1 is called
273 the loopback address. It may be used by a node
274 to send an IPv6 packet to itself.
275
276 @return `true` if the address is a loopback address
277
278 @par Specification
279 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
280 2.5.3. The Loopback Address (rfc4291)</a>
281 */
282 BOOST_URL_DECL
283 bool
284 is_loopback() const noexcept;
285
286 /** Return true if the address is a mapped IPv4 address
287
288 This address type is used to represent the
289 addresses of IPv4 nodes as IPv6 addresses.
290
291 @return `true` if the address is a mapped IPv4 address
292
293 @par Specification
294 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2">
295 2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
296 */
297 BOOST_URL_DECL
298 bool
299 is_v4_mapped() const noexcept;
300
301 /** Return true if two addresses are equal
302
303 @param a1 The first address to compare.
304 @param a2 The second address to compare.
305 @return `true` if the addresses are equal
306 */
307 friend
308 bool
309 81 operator==(
310 ipv6_address const& a1,
311 ipv6_address const& a2) noexcept
312 {
313 81 return a1.addr_ == a2.addr_;
314 }
315
316 /** Return true if two addresses are not equal
317
318 @param a1 The first address to compare.
319 @param a2 The second address to compare.
320 @return `true` if the addresses are not equal
321 */
322 friend
323 bool
324 4 operator!=(
325 ipv6_address const& a1,
326 ipv6_address const& a2) noexcept
327 {
328 4 return !( a1 == a2 );
329 }
330
331 /** Return an address object that represents the loopback address
332
333 The unicast address 0:0:0:0:0:0:0:1 is called
334 the loopback address. It may be used by a node
335 to send an IPv6 packet to itself.
336
337 @par Specification
338 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
339 2.5.3. The Loopback Address (rfc4291)</a>
340
341 @return The loopback address.
342 */
343 BOOST_URL_DECL
344 static
345 ipv6_address
346 loopback() noexcept;
347
348 /** Format the address to an output stream
349
350 This hidden friend function writes the
351 address to an output stream using
352 standard notation.
353
354 @return The output stream, for chaining.
355
356 @param os The output stream to write to.
357
358 @param addr The address to write.
359 */
360 friend
361 std::ostream&
362 1 operator<<(
363 std::ostream& os,
364 ipv6_address const& addr)
365 {
366 char buf[ipv6_address::max_str_len];
367
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 auto const s = addr.to_buffer(
368 buf, sizeof(buf));
369
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 os << s;
370 1 return os;
371 }
372
373
374 private:
375 BOOST_URL_DECL
376 std::size_t
377 print_impl(
378 char* dest) const noexcept;
379
380 BOOST_URL_DECL
381 void
382 to_string_impl(
383 string_token::arg& t) const;
384
385 bytes_type addr_{{}};
386 };
387
388 /** Format the address to an output stream
389
390 This function writes the address to an
391 output stream using standard notation.
392
393 @return The output stream, for chaining.
394
395 @param os The output stream to write to.
396
397 @param addr The address to write.
398 */
399 std::ostream&
400 operator<<(
401 std::ostream& os,
402 ipv6_address const& addr);
403
404 //------------------------------------------------
405
406 /** Parse a string containing an IPv6 address.
407
408 This function attempts to parse the string
409 as an IPv6 address and returns a result
410 containing the address upon success, or
411 an error code if the string does not contain
412 a valid IPv6 address.
413
414 @par Exception Safety
415 Throws nothing.
416
417 @return A result containing the address.
418
419 @param s The string to parse.
420 */
421 BOOST_URL_DECL
422 system::result<ipv6_address>
423 parse_ipv6_address(
424 core::string_view s) noexcept;
425
426 } // urls
427 } // boost
428
429 #endif
430