GCC Code Coverage Report


Directory: libs/url/
File: boost/url/ipv6_address.hpp
Date: 2023-12-15 15:31:49
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 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 bytes_type
176 120 to_bytes() const noexcept
177 {
178 120 return addr_;
179 }
180
181 /** Return the address as a string.
182
183 The returned string does not
184 contain surrounding square brackets.
185
186 When called with no arguments, the
187 return type is `std::string`.
188 Otherwise, the return type and style
189 of output is determined by which string
190 token is passed.
191
192 @par Example
193 @code
194 ipv6_address::bytes_type b = {{
195 0, 1, 0, 2, 0, 3, 0, 4,
196 0, 5, 0, 6, 0, 7, 0, 8 }};
197 ipv6_address a(b);
198 assert(a.to_string() == "1:2:3:4:5:6:7:8");
199 assert( ipv4_address(0x01020304).to_string() == "1.2.3.4" );
200 @endcode
201
202 @par Complexity
203 Constant.
204
205 @par Exception Safety
206 Strong guarantee.
207 Calls to allocate may throw.
208 String tokens may throw exceptions.
209
210 @return The return type of the string token.
211 If the token parameter is omitted, then
212 a new `std::string` is returned.
213 Otherwise, the function return type
214 is the result type of the token.
215
216 @param token An optional string token.
217
218 @par Specification
219 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.2">
220 2.2. Text Representation of Addresses (rfc4291)</a>
221 */
222 template<BOOST_URL_STRTOK_TPARAM>
223 BOOST_URL_STRTOK_RETURN
224 38 to_string(
225 BOOST_URL_STRTOK_ARG(token)) const
226 {
227 38 to_string_impl(token);
228 38 return token.result();
229 }
230
231 /** Write a dotted decimal string representing the address to a buffer
232
233 The resulting buffer is not null-terminated.
234
235 @throw std::length_error `dest_size < ipv6_address::max_str_len`
236
237 @return The formatted string
238
239 @param dest The buffer in which to write,
240 which must have at least `dest_size` space.
241
242 @param dest_size The size of the output buffer.
243 */
244 BOOST_URL_DECL
245 core::string_view
246 to_buffer(
247 char* dest,
248 std::size_t dest_size) const;
249
250 /** Return true if the address is unspecified
251
252 The address 0:0:0:0:0:0:0:0 is called the
253 unspecified address. It indicates the
254 absence of an address.
255
256 @par Specification
257 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.2">
258 2.5.2. The Unspecified Address (rfc4291)</a>
259 */
260 BOOST_URL_DECL
261 bool
262 is_unspecified() const noexcept;
263
264 /** Return true if the address is a loopback address
265
266 The unicast address 0:0:0:0:0:0:0:1 is called
267 the loopback address. It may be used by a node
268 to send an IPv6 packet to itself.
269
270 @par Specification
271 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
272 2.5.3. The Loopback Address (rfc4291)</a>
273 */
274 BOOST_URL_DECL
275 bool
276 is_loopback() const noexcept;
277
278 /** Return true if the address is a mapped IPv4 address
279
280 This address type is used to represent the
281 addresses of IPv4 nodes as IPv6 addresses.
282
283 @par Specification
284 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2">
285 2.5.5.2. IPv4-Mapped IPv6 Address (rfc4291)</a>
286 */
287 BOOST_URL_DECL
288 bool
289 is_v4_mapped() const noexcept;
290
291 /** Return true if two addresses are equal
292 */
293 friend
294 bool
295 81 operator==(
296 ipv6_address const& a1,
297 ipv6_address const& a2) noexcept
298 {
299 81 return a1.addr_ == a2.addr_;
300 }
301
302 /** Return true if two addresses are not equal
303 */
304 friend
305 bool
306 4 operator!=(
307 ipv6_address const& a1,
308 ipv6_address const& a2) noexcept
309 {
310 4 return !( a1 == a2 );
311 }
312
313 /** Return an address object that represents the loopback address
314
315 The unicast address 0:0:0:0:0:0:0:1 is called
316 the loopback address. It may be used by a node
317 to send an IPv6 packet to itself.
318
319 @par Specification
320 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.3">
321 2.5.3. The Loopback Address (rfc4291)</a>
322 */
323 BOOST_URL_DECL
324 static
325 ipv6_address
326 loopback() noexcept;
327
328 // hidden friend
329 friend
330 std::ostream&
331 1 operator<<(
332 std::ostream& os,
333 ipv6_address const& addr)
334 {
335 char buf[ipv6_address::max_str_len];
336 auto const s = addr.to_buffer(
337
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 buf, sizeof(buf));
338
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 os << s;
339 1 return os;
340 }
341
342
343 private:
344 BOOST_URL_DECL
345 std::size_t
346 print_impl(
347 char* dest) const noexcept;
348
349 BOOST_URL_DECL
350 void
351 to_string_impl(
352 string_token::arg& t) const;
353
354 bytes_type addr_{{}};
355 };
356
357 /** Format the address to an output stream
358
359 This function writes the address to an
360 output stream using standard notation.
361
362 @return The output stream, for chaining.
363
364 @param os The output stream to write to.
365
366 @param addr The address to write.
367 */
368 std::ostream&
369 operator<<(
370 std::ostream& os,
371 ipv6_address const& addr);
372
373 //------------------------------------------------
374
375 /** Parse a string containing an IPv6 address.
376
377 This function attempts to parse the string
378 as an IPv6 address and returns a result
379 containing the address upon success, or
380 an error code if the string does not contain
381 a valid IPv6 address.
382
383 @par Exception Safety
384 Throws nothing.
385
386 @return A result containing the address.
387
388 @param s The string to parse.
389 */
390 BOOST_URL_DECL
391 system::result<ipv6_address>
392 parse_ipv6_address(
393 core::string_view s) noexcept;
394
395 } // urls
396 } // boost
397
398 #endif
399