GCC Code Coverage Report


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