ipaddress 1.1.0
Loading...
Searching...
No Matches
ip-any-address.hpp
Go to the documentation of this file.
1/**
2 * @file ip-any-address.hpp
3 * @brief Unified interface for handling both IPv4 and IPv6 addresses
4 * @author Vladimir Shaleev
5 * @copyright MIT License
6 *
7 * This header defines the ip_address class, which provides a seamless and
8 * efficient way to handle IP addresses, supporting both IPv4 and IPv6 versions.
9 * It encapsulates the complexities of dealing with different IP versions and
10 * offers a simple and consistent API to work with. The class internally manages
11 * the storage and representation of the IP addresses, abstracting away the
12 * underlying details from the user.
13 *
14 * The ip_address class is designed to be a versatile and robust solution for IP address
15 * manipulation in network-related applications. It integrates the ipv4_address and
16 * ipv6_address classes through a union, ensuring optimal space usage while maintaining
17 * the ability to represent both IP address versions. This file is part of a larger library
18 * that aims to provide comprehensive support for network operations.
19 */
20
21#ifndef IPADDRESS_IP_ANY_ADDRESS_HPP
22#define IPADDRESS_IP_ANY_ADDRESS_HPP
23
24#include "ipv6-address.hpp"
25
26namespace IPADDRESS_NAMESPACE {
27
28namespace internal {
29
30template <typename T>
31struct ip_any_parser {
32 template <typename Str>
34 auto code = error_code::no_error;
35 const auto ipv4 = ipv4_address::parse(address, code);
36 if (code == error_code::no_error) {
37 return T(ipv4);
38 }
39 return T(ipv6_address::parse(address));
40 }
41
42 template <typename Str>
43 static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE T parse(const Str& address, error_code& code) IPADDRESS_NOEXCEPT {
45 const auto ipv4 = ipv4_address::parse(address, code);
46 if (code == error_code::no_error) {
47 return T(ipv4);
48 }
49 const auto ipv6 = ipv6_address::parse(address, code);
50 if (code == error_code::no_error) {
51 return T(ipv6);
52 }
53 return T();
54 }
55};
56
57} // namespace IPADDRESS_NAMESPACE::internal
58
59/**
60 * A class that represents an IP address, supporting both IPv4 and IPv6 formats.
61 *
62 * The ip_address class is a union-type structure that encapsulates both ipv4_address
63 * and ipv6_address, allowing for the representation and manipulation of both IPv4
64 * and IPv6 addresses. It provides a set of functions and type aliases that facilitate
65 * the handling of IP addresses in a network context, making it a versatile tool for
66 * developers working with IP-based communications.
67 *
68 * The class ensures that the size of its instances will always be large enough to
69 * store an IPv6 address, which is the larger of the two address types. This design
70 * guarantees that an ip_address object can store any valid IP address, regardless
71 * of its version, without the need for separate storage mechanisms.
72 */
74public:
75 using base_type_ipv4 = typename ipv4_address::base_type; /**< Base type for IPv4 address storage. */
76 using base_type_ipv6 = typename ipv6_address::base_type; /**< Base type for IPv6 address storage. */
77
78 using uint_type_ipv4 = typename ipv4_address::uint_type; /**< Unsigned integer type for IPv4 address representation. */
79 using uint_type_ipv6 = typename ipv6_address::uint_type; /**< Unsigned integer type for IPv6 address representation. */
80
81 /**
82 * Retrieves the version of the IP address.
83 *
84 * @return The version of the IP address, either IPv4 or IPv6.
85 */
87 return _version;
88 }
89
90 /**
91 * Checks if the IP address is a multicast address.
92 *
93 * @return `true` if the IP address is reserved for multicast use, `false` otherwise.
94 * @see [RFC 3171](https://datatracker.ietf.org/doc/html/rfc3171.html) for IPv4.
95 * @see [RFC 2373](https://datatracker.ietf.org/doc/html/rfc2373.html) for IPv6.
96 */
98 return _version == ip_version::V4 ? _ipv.ipv4.is_multicast() : _ipv.ipv6.is_multicast();
99 }
100
101 /**
102 * Checks if the IP address is a private address.
103 *
104 * @return `true` if the IP address is allocated for private networks, `false` otherwise.
105 * @see [iana-ipv4-special-registry](https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml).
106 * @see [iana-ipv6-special-registry](https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml).
107 */
109 return _version == ip_version::V4 ? _ipv.ipv4.is_private() : _ipv.ipv6.is_private();
110 }
111
112 /**
113 * Checks if the IP address is a global address.
114 *
115 * @return `true` if the IP address is allocated for public networks, `false` otherwise.
116 * @see [iana-ipv4-special-registry](https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml).
117 * @see [iana-ipv6-special-registry](https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml).
118 */
120 return _version == ip_version::V4 ? _ipv.ipv4.is_global() : _ipv.ipv6.is_global();
121 }
122
123 /**
124 * Checks if the IP address is a reserved address.
125 *
126 * @return `true` if the IP address is otherwise IETF reserved, `false` otherwise.
127 */
129 return _version == ip_version::V4 ? _ipv.ipv4.is_reserved() : _ipv.ipv6.is_reserved();
130 }
131
132 /**
133 * Checks if the IP address is a loopback address.
134 *
135 * @return `true` if the IP address is a loopback address, `false` otherwise.
136 * @see [RFC 3330](https://datatracker.ietf.org/doc/html/rfc3330.html) for IPv4.
137 * @see [RFC 2373](https://datatracker.ietf.org/doc/html/rfc2373.html) for IPv6.
138 */
140 return _version == ip_version::V4 ? _ipv.ipv4.is_loopback() : _ipv.ipv6.is_loopback();
141 }
142
143 /**
144 * Checks if the IP address is link-local.
145 *
146 * @return True if the IP address is link-local, false otherwise.
147 */
149 return _version == ip_version::V4 ? _ipv.ipv4.is_link_local() : _ipv.ipv6.is_link_local();
150 }
151
152 /**
153 * Checks if the IP address is unspecified.
154 *
155 * An unspecified IP address is an address with all bits set to zero.
156 * In IPv4, this is represented as 0.0.0.0, and in IPv6, as ::.
157 * This type of address is used to indicate the absence of an address.
158 *
159 * @return `true` if the IP address is unspecified (all bits are zero), `false` otherwise.
160 * @see [RFC 5735](https://datatracker.ietf.org/doc/html/rfc5735.html) for IPv4.
161 * @see [RFC 2373](https://datatracker.ietf.org/doc/html/rfc2373.html) for IPv6.
162 */
164 return _version == ip_version::V4 ? _ipv.ipv4.is_unspecified() : _ipv.ipv6.is_unspecified();
165 }
166
167 /**
168 * Checks if the IPv6 address is a site-local address.
169 *
170 * @return `true` if the address is site-local, `false` otherwise.
171 * @note Site-local addresses are equivalent to private addresses in IPv4 and are not routable on the global internet.
172 * @remark These attribute is true for the network as a whole if it is true for both the network address and the broadcast address.
173 */
175 return _version == ip_version::V4 ? false : _ipv.ipv6.is_site_local();
176 }
177
178 /**
179 * Checks if the IP address is an IPv4 address.
180 *
181 * @return `true` if the IP address is an IPv4 address, `false` otherwise.
182 */
184 return _version == ip_version::V4;
185 }
186
187 /**
188 * Checks if the IP address is an IPv6 address.
189 *
190 * @return `true` if the IP address is an IPv6 address, `false` otherwise.
191 */
193 return _version == ip_version::V6;
194 }
195
196 /**
197 * Retrieves the size of the IP address.
198 *
199 * Depending on the IP version, this function returns the size of the IPv4 or IPv6 address.
200 *
201 * @return The size of the IP address in bytes.
202 */
204 return _version == ip_version::V4 ? _ipv.ipv4.size() : _ipv.ipv6.size();
205 }
206
207 /**
208 * Computes a hash value for the IP address.
209 *
210 * This function generates a hash value that can be used to uniquely identify the IP address.
211 * It can be useful when IP addresses are used as keys in hash tables.
212 *
213 * @return A `size_t` hash value of the IP address.
214 */
216 return _version == ip_version::V4 ? _ipv.ipv4.hash() : _ipv.ipv6.hash();
217 }
218
219 /**
220 * Determines if the IPv6 address is an IPv4-mapped address.
221 *
222 * If the IP address is an IPv6 address, this function returns the IPv4-mapped IPv6 address if available.
223 *
224 * @return An `optional` containing the mapped IPv4 address if the IPv6 address is IPv4-mapped, or an empty `optional` otherwise.
225 * @remark An IPv4-mapped IPv6 address has its first 80 bits set to zero and the next 16 bits set to one (starting with `::FFFF/96`).
226 */
228 return _version == ip_version::V4 ? optional<ipv4_address>() : _ipv.ipv6.ipv4_mapped();
229 }
230
231 /**
232 * Determines if the IPv6 address is a 6to4 address.
233 *
234 * If the IP address is an IPv6 address, this function returns the 6to4 address if available.
235 *
236 * @return An optional containing the encapsulated IPv4 address if the IPv6 address is a 6to4 address, or an empty optional otherwise.
237 * @remark A 6to4 address uses a `2002::/16` prefix and embeds an IPv4 address in the next 32 bits.
238 * @see [RFC 3056](https://datatracker.ietf.org/doc/html/rfc3056.html).
239 */
241 return _version == ip_version::V4 ? optional<ipv4_address>() : _ipv.ipv6.sixtofour();
242 }
243
244 /**
245 * Determines if the IPv6 address is a Teredo address.
246 *
247 * If the IP address is an IPv6 address, this function returns the Teredo address, which includes
248 * both the Teredo server and client IPv4 addresses.
249 *
250 * @return An optional containing a pair of IPv4 addresses representing the Teredo server and client if the IPv6 address is a Teredo address, or an empty optional otherwise.
251 * @retval std::pair::first The Teredo server IPv4 address
252 * @retval std::pair::second The Teredo client IPv4 address
253 * @remark A Teredo address begins with the `2001::/32` prefix and is used for NAT traversal for IPv6.
254 * @see [RFC 4380](https://datatracker.ietf.org/doc/html/rfc4380.html).
255 */
256 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE optional<std::pair<ipv4_address, ipv4_address>> teredo() const IPADDRESS_NOEXCEPT {
257 return _version == ip_version::V4 ? optional<std::pair<ipv4_address, ipv4_address>>() : _ipv.ipv6.teredo();
258 }
259
260 /**
261 * Retrieves the IPv4 address.
262 *
263 * If the IP address is an IPv4 address, this function returns the IPv4 address.
264 *
265 * @return An optional containing the IPv4 address, or an empty optional if the IP address is not IPv4.
266 */
267 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE optional<ipv4_address> v4() const IPADDRESS_NOEXCEPT {
268 if (_version == ip_version::V6) {
269 return optional<ipv4_address>();
270 }
271 return optional<ipv4_address>(_ipv.ipv4);
272 }
273
274 /**
275 * Retrieves the IPv6 address.
276 *
277 * If the IP address is an IPv6 address, this function returns the IPv6 address.
278 *
279 * @return An optional containing the IPv6 address, or an empty optional if the IP address is not IPv6.
280 */
281 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE optional<ipv6_address> v6() const IPADDRESS_NOEXCEPT {
282 if (_version == ip_version::V4) {
283 return optional<ipv6_address>();
284 }
285 return optional<ipv6_address>(_ipv.ipv6);
286 }
287
288 /**
289 * Retrieves the raw data of the IP address in **network byte order** (big-endian).
290 *
291 * This function returns a pointer to the raw data representing the IP address. The format of the data
292 * depends on whether the address is IPv4 or IPv6.
293 *
294 * @return A pointer to the raw data of the IP address.
295 */
296 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE const uint8_t* data() const IPADDRESS_NOEXCEPT {
297 return _version == ip_version::V4 ? _ipv.ipv4.data() : _ipv.ipv6.data();
298 }
299
300 /**
301 * Default constructor.
302 *
303 * Constructs an ip_address object with an unspecified ip address with version IPv4.
304 */
305 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address() IPADDRESS_NOEXCEPT { // NOLINT(modernize-use-equals-default): for C++11 support
306 }
307
308 /**
309 * Constructor from an ipv4_address.
310 *
311 * Constructs an ip_address object with the specified IPv4 address.
312 *
313 * @param[in] ipv4 An ipv4_address object to initialize the ip_address.
314 */
315 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address(const ipv4_address& ipv4) IPADDRESS_NOEXCEPT : _ipv(ipv4) {
316 }
317
318 /**
319 * Constructor from an ipv6_address.
320 *
321 * Constructs an ip_address object with the specified IPv6 address.
322 *
323 * @param[in] ipv6 An ipv6_address object to initialize the ip_address.
324 */
325 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address(const ipv6_address& ipv6) IPADDRESS_NOEXCEPT : _ipv(ipv6), _version(ip_version::V6) {
326 }
327
328 /**
329 * Constructor from byte array for IPv4.
330 *
331 * Constructs an ip_address object with the specified byte array for an IPv4 address.
332 *
333 * @param[in] bytes A base_type_ipv4 object representing the byte array of the IPv4 address.
334 */
335 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE explicit ip_address(const base_type_ipv4& bytes) IPADDRESS_NOEXCEPT : _ipv(bytes) {
336 }
337
338 /**
339 * Constructor from byte array for IPv6.
340 *
341 * Constructs an ip_address object with the specified byte array for an IPv6 address.
342 *
343 * @param[in] bytes A base_type_ipv6 object representing the byte array of the IPv6 address.
344 */
345 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE explicit ip_address(const base_type_ipv6& bytes) IPADDRESS_NOEXCEPT : _ipv(bytes), _version(ip_version::V6) {
346 }
347
348 /**
349 * Static factory method to create an ip_address from byte array for IPv4.
350 *
351 * @param[in] bytes A base_type_ipv4 object representing the byte array of the IPv4 address.
352 * @return An ip_address object initialized with the provided IPv4 bytes.
353 */
354 IPADDRESS_NODISCARD static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address from_bytes(const base_type_ipv4& bytes) IPADDRESS_NOEXCEPT {
355 return ip_address(bytes);
356 }
357
358 /**
359 * Static factory method to create an ip_address from byte array for IPv6.
360 *
361 * @param[in] bytes A base_type_ipv6 object representing the byte array of the IPv6 address.
362 * @return An ip_address object initialized with the provided IPv6 bytes.
363 */
364 IPADDRESS_NODISCARD static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address from_bytes(const base_type_ipv6& bytes) IPADDRESS_NOEXCEPT {
365 return ip_address(bytes);
366 }
367
368 /**
369 * Static factory method to create an ip_address from raw bytes.
370 *
371 * This method creates an ip_address object from raw bytes, with the specified IP version.
372 *
373 * @param[in] bytes A pointer to the raw bytes representing the IP address.
374 * @param[in] byte_count The number of bytes to use from the pointer.
375 * @param[in] version The version of the IP address to create (IPv4 or IPv6).
376 * @return An ip_address object initialized with the provided bytes and version.
377 * @parblock
378 * @remark If the number of bytes \a byte_count is less than the target number .
379 * of bytes to represent the IP address, the missing bytes will be
380 * filled with zeros.
381 * @endparblock
382 * @parblock
383 * @remark If the number of bytes \a byte_count is greater than the target .
384 * number of bytes represented by the IP address, then the extra
385 * bytes will be ignored
386 * @endparblock
387 */
388 IPADDRESS_NODISCARD static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address from_bytes(const uint8_t* bytes, size_t byte_count, ip_version version) IPADDRESS_NOEXCEPT {
389 return version == ip_version::V4 ? ip_address(ipv4_address::from_bytes(bytes, byte_count)) : ip_address(ipv6_address::from_bytes(bytes, byte_count));
390 }
391
392 /**
393 * Static factory method to create an ip_address from a uint_type_ipv4.
394 *
395 * @param[in] ip A uint_type_ipv4 (uint32_t) representing the IPv4 address.
396 * @return An ip_address object initialized with the provided IPv4 address.
397 * @remark Bytes in integer \a ip must be presented in **host byte order**.
398 */
400 return ip_address(ipv4_address::from_uint(ip));
401 }
402
403 /**
404 * Static factory method to create an ip_address from a uint_type_ipv6.
405 *
406 * @param[in] ip A uint_type_ipv6 (uint128_t) representing the IPv6 address.
407 * @return An ip_address object initialized with the provided IPv6 address.
408 * @remark Bytes in integer \a ip must be presented in **host byte order**.
409 */
410 IPADDRESS_NODISCARD static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address from_uint(const uint_type_ipv6& ip) IPADDRESS_NOEXCEPT {
411 return ip_address(ipv6_address::from_uint(ip));
412 }
413
414 /**
415 * Converts the IP address to a uint32_t.
416 *
417 * This function returns the numeric representation of the IP address as a uint32_t. For IPv6 addresses,
418 * it returns the least significant 32 bits of the address.
419 *
420 * @return A uint32_t representing the IPv4 address or the least significant 32 bits of the IPv6 address.
421 * @remark Bytes in integer are presented in **host byte order**.
422 */
424 return _version == ip_version::V4 ? _ipv.ipv4.to_uint() : uint32_t(_ipv.ipv6.to_uint());
425 }
426
427 /**
428 * Converts the IP address to a uint128_t.
429 *
430 * This function returns the numeric representation of the IP address as a uint128_t. For IPv4 addresses,
431 * the function converts the address to a uint128_t format.
432 *
433 * @return A uint128_t representing the numeric value of the IP address.
434 * @remark Bytes in integer are presented in **host byte order**.
435 */
437 return _version == ip_version::V4 ? uint128_t(_ipv.ipv4.to_uint()) : _ipv.ipv6.to_uint();
438 }
439
440 /**
441 * Converts the IP address to a string.
442 *
443 * This function returns a string representation of the IP address. The format can be specified by the \a fmt parameter.
444 *
445 * @param[in] fmt The format to use for the string representation, defaults to compressed format.
446 * @return A `std::string` representing the IP address in the specified format.
447 */
449 return _version == ip_version::V4 ? _ipv.ipv4.to_string(fmt) : _ipv.ipv6.to_string(fmt);
450 }
451
452 /**
453 * Converts the IP address to a string.
454 *
455 * This function returns a string representation of the IP address. The format can be specified by the \a fmt parameter.
456 *
457 * @param[in] fmt The format to use for the string representation, defaults to compressed format.
458 * @return A `std::wstring` representing the IP address in the specified format.
459 */
461 return _version == ip_version::V4 ? _ipv.ipv4.to_wstring(fmt) : _ipv.ipv6.to_wstring(fmt);
462 }
463
464 /**
465 * Converts the IP address to a string.
466 *
467 * This function returns a string representation of the IP address. The format can be specified by the \a fmt parameter.
468 *
469 * @param[in] fmt The format to use for the string representation, defaults to compressed format.
470 * @return A `std::u16string` representing the IP address in the specified format.
471 */
473 return _version == ip_version::V4 ? _ipv.ipv4.to_u16string(fmt) : _ipv.ipv6.to_u16string(fmt);
474 }
475
476 /**
477 * Converts the IP address to a string.
478 *
479 * This function returns a string representation of the IP address. The format can be specified by the \a fmt parameter.
480 *
481 * @param[in] fmt The format to use for the string representation, defaults to compressed format.
482 * @return A `std::u32string` representing the IP address in the specified format.
483 */
485 return _version == ip_version::V4 ? _ipv.ipv4.to_u32string(fmt) : _ipv.ipv6.to_u32string(fmt);
486 }
487
488#if __cpp_char8_t >= 201811L
489
490 /**
491 * Converts the IP address to a string.
492 *
493 * This function returns a string representation of the IP address. The format can be specified by the \a fmt parameter.
494 *
495 * @param[in] fmt The format to use for the string representation, defaults to compressed format.
496 * @return A `std::u8string` representing the IP address in the specified format.
497 */
500 }
501
502#endif // __cpp_char8_t
503
504 /**
505 * Generates a reverse DNS lookup pointer for the IP address.
506 *
507 * This function creates a string that is the reverse DNS lookup pointer of the IP address.
508 * It is commonly used in reverse DNS lookups, where the IP address is reversed and appended with `.in-addr.arpa` for IPv4,
509 * or `.ip6.arpa` for IPv6, to form a domain name that can be looked up in the DNS system.
510 *
511 * The name of the reverse DNS PTR record for the IP address, e.g.:
512 * @code{.cpp}
513 * std::cout << ip_address::parse("127.0.0.1").reverse_pointer() << std::endl;
514 * std::cout << ip_address::parse("2001:db8::1").reverse_pointer() << std::endl;
515 *
516 * // out:
517 * // 1.0.0.127.in-addr.arpa
518 * // 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa
519 * @endcode
520 * @return A `std::string` that is the reverse DNS lookup pointer of the IP address.
521 */
523 return _version == ip_version::V4 ? _ipv.ipv4.reverse_pointer() : _ipv.ipv6.reverse_pointer();
524 }
525
526 /**
527 * Swaps the contents of this ip_address with another ip_address.
528 *
529 * This function exchanges the contents of the ip_address with those of the ip parameter.
530 *
531 * @param[in] ip The other ip_address object to swap with.
532 */
534 const auto tmp = *this;
535 *this = ip;
536 ip = tmp;
537 }
538
539#ifdef IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
540
541 /**
542 * Static method template to parse an IP address from a fixed string at compile time.
543 *
544 * @tparam FixedString A non-type template parameter that holds the string representation of the IP address.
545 * @return An instance of ip address parsed from the fixed string.
546 * @note This method is only available when non-type template parameters for strings are supported.
547 * @remark If parsing fails, an error will be raised at compile time.
548 */
549 template <fixed_string FixedString>
551 constexpr auto str = FixedString;
552 auto code = error_code::no_error;
553
554 char ip[str.size() + 1]{};
555 for (size_t i = 0; i < str.size(); ++i) {
556 ip[i] = str[i];
557 }
558
559 const auto ipv4 = ipv4_address::parse(ip, code);
560 if (code == error_code::no_error) {
561 return ip_address(ipv4);
562 }
563
565 }
566
567#endif // IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
568
569#if IPADDRESS_CPP_VERSION >= 17
570
571 /**
572 * Parses an IP address from a string view.
573 *
574 * This method provides a way to parse an IP address from a string view,
575 * which is a non-owning reference to a sequence of characters.
576 *
577 * @param[in] address The string view containing the IP address to parse.
578 * @return An instance of ip address parsed from the string view.
579 * @throw parse_error Exception caused by invalid input string.
580 * @note This method is available for C++17 and later versions.
581 * @remark For C++ versions prior to C++17, member functions with `std::string` and C-strings will be used instead.
582 */
585 }
586
587 /**
588 * Parses an IP address from a wide string view.
589 *
590 * This method allows for parsing an IP address from a wide string view,
591 * which is typically used for wide character strings.
592 *
593 * @param[in] address The wide string view containing the IP address to parse.
594 * @return An instance of ip address parsed from the string view.
595 * @throw parse_error Exception caused by invalid input string.
596 * @note This method is available for C++17 and later versions.
597 * @remark For C++ versions prior to C++17, member functions with `std::wstring` and C-strings will be used instead.
598 */
601 }
602
603#if __cpp_char8_t >= 201811L
604
605 /**
606 * Parses an IP address from a UTF-8 string view.
607 *
608 * This method parses an IP address from a given UTF-8 string view. It leverages the `char8_t`
609 * type introduced in C++20 to handle UTF-8 strings natively.
610 *
611 * @param[in] address A UTF-8 string view containing the IP address to parse.
612 * @return An instance of ip address parsed from the string view.
613 * @throw parse_error Exception caused by invalid input string.
614 * @note This method is available for C++20 and later versions where `char8_t` is supported.
615 */
618 }
619
620#endif // __cpp_char8_t
621
622 /**
623 * Parses an IP address from a UTF-16 string view.
624 *
625 * This method is designed to parse an IP address from a UTF-16 string view,
626 * which is a sequence of 16-bit characters.
627 *
628 * @param[in] address The UTF-16 string view containing the IP address to parse.
629 * @return An instance of ip address parsed from the string view.
630 * @throw parse_error Exception caused by invalid input string.
631 * @note This method is available for C++17 and later versions.
632 * @remark For C++ versions prior to C++17, member functions with `std::u16string` and C-strings will be used instead.
633 */
636 }
637
638 /**
639 * Parses an IP address from a UTF-32 string view.
640 *
641 * This method allows for parsing an IP address from a UTF-32 string view,
642 * which is a sequence of 32-bit characters.
643 *
644 * @param[in] address The UTF-32 string view containing the IP address to parse.
645 * @return An instance of ip address parsed from the string view.
646 * @throw parse_error Exception caused by invalid input string.
647 * @note This method is available for C++17 and later versions.
648 * @remark For C++ versions prior to C++17, member functions with `std::u32string` and C-strings will be used instead.
649 */
652 }
653
654 /**
655 * Parses an IP address from a string view and reports errors through an error code.
656 *
657 * This method parses an IP address from a string view and provides an error code if the parsing fails.
658 *
659 * @param[in] address The string view containing the IP address to parse.
660 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
661 * @return An instance of ip address parsed from the string view. If parsing fails, the returned object will be in an unspecified state.
662 * @note This method is available for C++17 and later versions.
663 * @remark For C++ versions prior to C++17, member functions with `std::string` and C-strings will be used instead.
664 */
667 }
668
669 /**
670 * Parses an IP address from a wide string view and reports errors through an error code.
671 *
672 * This method parses an IP address from a wide string view and provides an error code if the parsing fails.
673 *
674 * @param[in] address The wide string view containing the IP address to parse.
675 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
676 * @return An instance of ip address parsed from the wide string view. If parsing fails, the returned object will be in an unspecified state.
677 * @note This method is available for C++17 and later versions.
678 * @remark For C++ versions prior to C++17, member functions with `std::wstring` and C-strings will be used instead.
679 */
682 }
683
684#if __cpp_char8_t >= 201811L
685
686 /**
687 * Parses an IP address from a UTF-8 string view and reports errors through an error code.
688 *
689 * This method parses an IP address from a UTF-8 string view and provides an error code if the parsing fails.
690 *
691 * @param[in] address The UTF-8 string view containing the IP address to parse.
692 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
693 * @return An instance of ip address parsed from the UTF-8 string view. If parsing fails, the returned object will be in an unspecified state.
694 * @note This method is available for C++20 and later versions where `char8_t` is supported.
695 */
698 }
699
700#endif // __cpp_char8_t
701
702 /**
703 * Parses an IP address from a UTF-16 string view and reports errors through an error code.
704 *
705 * This method parses an IP address from a UTF-16 string view and provides an error code if the parsing fails.
706 *
707 * @param[in] address The UTF-16 string view containing the IP address to parse.
708 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
709 * @return An instance of ip address parsed from the UTF-16 string view. If parsing fails, the returned object will be in an unspecified state.
710 * @note This method is available for C++17 and later versions.
711 * @remark For C++ versions prior to C++17, member functions with `std::u16string` and C-strings will be used instead.
712 */
715 }
716
717 /**
718 * Parses an IP address from a UTF-32 string view and reports errors through an error code.
719 *
720 * This method parses an IP address from a UTF-32 string view and provides an error code if the parsing fails.
721 *
722 * @param[in] address The UTF-32 string view containing the IP address to parse.
723 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
724 * @return An instance of ip address parsed from the UTF-32 string view. If parsing fails, the returned object will be in an unspecified state.
725 * @note This method is available for C++17 and later versions.
726 * @remark For C++ versions prior to C++17, member functions with `std::u32string` and C-strings will be used instead.
727 */
730 }
731
732 /**
733 * Sets the scope identifier of the IPv6 address using a string view.
734 *
735 * This function sets the scope identifier using a string view, which allows for a more efficient
736 * way to handle strings without copying them.
737 *
738 * @param[in] scope_id The string view representing the scope identifier.
739 * @throw parse_error Exception caused by invalid input string.
740 * @note This method is available for C++17 and later versions.
741 * @parblock
742 * @remark For C++ versions prior to C++17, member functions with `std::string` and C-strings will be used instead.
743 * @endparblock
744 * @parblock
745 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
746 * @endparblock
747 */
749 if (_version == ip_version::V6) {
751 }
752 }
753
754 /**
755 * Sets the scope identifier of the IPv6 address using a wide string view.
756 *
757 * This function sets the scope identifier using a wide string view, which allows for a more efficient
758 * way to handle strings without copying them.
759 *
760 * @param[in] scope_id The wide string view representing the scope identifier.
761 * @throw parse_error Exception caused by invalid input string.
762 * @note This method is available for C++17 and later versions.
763 * @parblock
764 * @remark For C++ versions prior to C++17, member functions with `std::wstring` and C-strings will be used instead.
765 * @endparblock
766 * @parblock
767 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
768 * @endparblock
769 */
771 if (_version == ip_version::V6) {
773 }
774 }
775
776#if __cpp_char8_t >= 201811L
777
778 /**
779 * Sets the scope identifier of the IPv6 address using UTF-8 string view.
780 *
781 * This function sets the scope identifier using UTF-8 string view, which allows for a more efficient
782 * way to handle strings without copying them.
783 *
784 * @param[in] scope_id The UTF-8 string view representing the scope identifier.
785 * @throw parse_error Exception caused by invalid input string.
786 * @note This method is available for C++20 and later versions where `char8_t` is supported.
787 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
788 */
790 if (_version == ip_version::V6) {
792 }
793 }
794
795#endif // __cpp_char8_t
796
797 /**
798 * Sets the scope identifier of the IPv6 address using UTF-16 string view.
799 *
800 * This function sets the scope identifier using UTF-16 string view, which allows for a more efficient
801 * way to handle strings without copying them.
802 *
803 * @param[in] scope_id The UTF-16 string view representing the scope identifier.
804 * @throw parse_error Exception caused by invalid input string.
805 * @note This method is available for C++17 and later versions.
806 * @parblock
807 * @remark For C++ versions prior to C++17, member functions with `std::u16string` and C-strings will be used instead.
808 * @endparblock
809 * @parblock
810 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
811 * @endparblock
812 */
814 if (_version == ip_version::V6) {
816 }
817 }
818
819 /**
820 * Sets the scope identifier of the IPv6 address using UTF-32 string view.
821 *
822 * This function sets the scope identifier using UTF-32 string view, which allows for a more efficient
823 * way to handle strings without copying them.
824 *
825 * @param[in] scope_id The UTF-32 string view representing the scope identifier.
826 * @throw parse_error Exception caused by invalid input string.
827 * @note This method is available for C++17 and later versions.
828 * @parblock
829 * @remark For C++ versions prior to C++17, member functions with `std::u32string` and C-strings will be used instead.
830 * @endparblock
831 * @parblock
832 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
833 * @endparblock
834 */
836 if (_version == ip_version::V6) {
838 }
839 }
840
841 /**
842 * Sets the scope identifier of the IPv6 address using a string view and reports any errors encountered.
843 *
844 * This function sets the scope identifier using a string view and provides an error code parameter to report any issues that occur during the operation.
845 *
846 * @param[in] scope_id The string view representing the scope identifier.
847 * @param[out] code An error_code object that will be set to the error that occurred, if any.
848 * @note This method is available for C++17 and later versions.
849 * @parblock
850 * @remark For C++ versions prior to C++17, member functions with `std::string` and C-strings will be used instead.
851 * @endparblock
852 * @parblock
853 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
854 * @endparblock
855 */
857 if (_version == ip_version::V6) {
859 }
860 }
861
862 /**
863 * Sets the scope identifier of the IPv6 address using a wide string view and reports any errors encountered.
864 *
865 * This function sets the scope identifier using a wide string view and provides an error code parameter to report any issues that occur during the operation.
866 *
867 * @param[in] scope_id The wide string view representing the scope identifier.
868 * @param[out] code An error_code object that will be set to the error that occurred, if any.
869 * @note This method is available for C++17 and later versions.
870 * @parblock
871 * @remark For C++ versions prior to C++17, member functions with `std::wstring` and C-strings will be used instead.
872 * @endparblock
873 * @parblock
874 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
875 * @endparblock
876 */
878 if (_version == ip_version::V6) {
880 }
881 }
882
883#if __cpp_char8_t >= 201811L
884
885 /**
886 * Sets the scope identifier of the IPv6 address using a UTF-8 string view and reports any errors encountered.
887 *
888 * This function sets the scope identifier using a UTF-8 string view and provides an error code parameter to report any issues that occur during the operation.
889 *
890 * @param[in] scope_id The UTF-8 string view representing the scope identifier.
891 * @param[out] code An error_code object that will be set to the error that occurred, if any.
892 * @note This method is available for C++20 and later versions.
893 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
894 */
896 if (_version == ip_version::V6) {
898 }
899 }
900
901#endif // __cpp_char8_t
902
903 /**
904 * Sets the scope identifier of the IPv6 address using a UTF-16 string view and reports any errors encountered.
905 *
906 * This function sets the scope identifier using a UTF-16 string view and provides an error code parameter to report any issues that occur during the operation.
907 *
908 * @param[in] scope_id The UTF-16 string view representing the scope identifier.
909 * @param[out] code An error_code object that will be set to the error that occurred, if any.
910 * @note This method is available for C++17 and later versions.
911 * @parblock
912 * @remark For C++ versions prior to C++17, member functions with `std::u16string` and C-strings will be used instead.
913 * @endparblock
914 * @parblock
915 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
916 * @endparblock
917 */
919 if (_version == ip_version::V6) {
921 }
922 }
923
924 /**
925 * Sets the scope identifier of the IPv6 address using a UTF-32 string view and reports any errors encountered.
926 *
927 * This function sets the scope identifier using a UTF-32 string view and provides an error code parameter to report any issues that occur during the operation.
928 *
929 * @param[in] scope_id The UTF-32 string view representing the scope identifier.
930 * @param[out] code An error_code object that will be set to the error that occurred, if any.
931 * @note This method is available for C++17 and later versions.
932 * @parblock
933 * @remark For C++ versions prior to C++17, member functions with `std::u32string` and C-strings will be used instead.
934 * @endparblock
935 * @parblock
936 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
937 * @endparblock
938 */
940 if (_version == ip_version::V6) {
942 }
943 }
944
945#else // IPADDRESS_CPP_VERSION < 17
946
947 /**
948 * Parses an IP address from a `std::string`.
949 *
950 * @param[in] address The `std::string` containing the IP address to parse.
951 * @return An instance of ip address parsed from the string.
952 * @throw parse_error Exception caused by invalid input string.
953 */
955 return internal::ip_any_parser<ip_address>::parse(address);
956 }
957
958 /**
959 * Parses an IP address from a wide `std::wstring`.
960 *
961 * @param[in] address The wide `std::wstring` containing the IP address to parse.
962 * @return An instance of ip address parsed from the string.
963 * @throw parse_error Exception caused by invalid input string.
964 */
966 return internal::ip_any_parser<ip_address>::parse(address);
967 }
968
969 /**
970 * Parses an IP address from a UTF-16 `std::u16string`.
971 *
972 * @param[in] address The UTF-16 `std::u16string` containing the IP address to parse.
973 * @return An instance of ip address parsed from the string.
974 * @throw parse_error Exception caused by invalid input string.
975 */
977 return internal::ip_any_parser<ip_address>::parse(address);
978 }
979
980 /**
981 * Parses an IP address from a UTF-32 `std::u32string`.
982 *
983 * @param[in] address The UTF-32 `std::u32string` containing the IP address to parse.
984 * @return An instance of ip address parsed from the string.
985 * @throw parse_error Exception caused by invalid input string.
986 */
988 return internal::ip_any_parser<ip_address>::parse(address);
989 }
990
991 /**
992 * Parses an IP address from a `std::string` and reports errors through an error code.
993 *
994 * @param[in] address The `std::string` containing the IP address to parse.
995 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
996 * @return An instance of ip address parsed from the string. If parsing fails, the returned object will be in an unspecified state.
997 */
998 static IPADDRESS_FORCE_INLINE ip_address parse(const std::string& address, error_code& code) IPADDRESS_NOEXCEPT {
999 return internal::ip_any_parser<ip_address>::parse(address, code);
1000 }
1001
1002 /**
1003 * Parses an IP address from a wide `std::wstring` and reports errors through an error code.
1004 *
1005 * @param[in] address The wide `std::wstring` containing the IP address to parse.
1006 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
1007 * @return An instance of ip address parsed from the wide string. If parsing fails, the returned object will be in an unspecified state.
1008 */
1009 static IPADDRESS_FORCE_INLINE ip_address parse(const std::wstring& address, error_code& code) IPADDRESS_NOEXCEPT {
1010 return internal::ip_any_parser<ip_address>::parse(address, code);
1011 }
1012
1013 /**
1014 * Parses an IP address from a UTF-16 `std::u16string` and reports errors through an error code.
1015 *
1016 * @param[in] address The UTF-16 `std::u16string` containing the IP address to parse.
1017 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
1018 * @return An instance of ip address parsed from the UTF-16 string. If parsing fails, the returned object will be in an unspecified state.
1019 */
1020 static IPADDRESS_FORCE_INLINE ip_address parse(const std::u16string& address, error_code& code) IPADDRESS_NOEXCEPT {
1021 return internal::ip_any_parser<ip_address>::parse(address, code);
1022 }
1023
1024 /**
1025 * Parses an IP address from a UTF-32 `std::u32string` and reports errors through an error code.
1026 *
1027 * @param[in] address The UTF-32 `std::u32string` containing the IP address to parse.
1028 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
1029 * @return An instance of ip address parsed from the UTF-32 string. If parsing fails, the returned object will be in an unspecified state.
1030 */
1031 static IPADDRESS_FORCE_INLINE ip_address parse(const std::u32string& address, error_code& code) IPADDRESS_NOEXCEPT {
1032 return internal::ip_any_parser<ip_address>::parse(address, code);
1033 }
1034
1035 /**
1036 * Sets the scope identifier of the IPv6 address using a `std::string`.
1037 *
1038 * @param[in] scope_id The string representing the scope identifier.
1039 * @throw parse_error Exception caused by invalid input string.
1040 */
1041 IPADDRESS_FORCE_INLINE void set_scope_id(const std::string& scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1042 if (_version == ip_version::V6) {
1043 _ipv.ipv6.set_scope_id(scope_id);
1044 }
1045 }
1046
1047 /**
1048 * Sets the scope identifier of the IPv6 address using a `std::wstring`.
1049 *
1050 * @param[in] scope_id The wide string representing the scope identifier.
1051 * @throw parse_error Exception caused by invalid input wide string.
1052 */
1053 IPADDRESS_FORCE_INLINE void set_scope_id(const std::wstring& scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1054 if (_version == ip_version::V6) {
1055 _ipv.ipv6.set_scope_id(scope_id);
1056 }
1057 }
1058
1059 /**
1060 * Sets the scope identifier of the IPv6 address using a `std::u16string`.
1061 *
1062 * @param[in] scope_id The UTF-16 string representing the scope identifier.
1063 * @throw parse_error Exception caused by invalid input UTF-16 string.
1064 */
1065 IPADDRESS_FORCE_INLINE void set_scope_id(const std::u16string& scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1066 if (_version == ip_version::V6) {
1067 _ipv.ipv6.set_scope_id(scope_id);
1068 }
1069 }
1070
1071 /**
1072 * Sets the scope identifier of the IPv6 address using a `std::u32string`.
1073 *
1074 * @param[in] scope_id The UTF-32 string representing the scope identifier.
1075 * @throw parse_error Exception caused by invalid input UTF-32 string.
1076 */
1077 IPADDRESS_FORCE_INLINE void set_scope_id(const std::u32string& scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1078 if (_version == ip_version::V6) {
1079 _ipv.ipv6.set_scope_id(scope_id);
1080 }
1081 }
1082
1083 /**
1084 * Sets the scope identifier of the IPv6 address using a `std::string` and reports any errors.
1085 *
1086 * @param[in] scope_id The string representing the scope identifier.
1087 * @param[out] code An error_code object that will store the result of the operation.
1088 */
1089 IPADDRESS_FORCE_INLINE void set_scope_id(const std::string& scope_id, error_code& code) IPADDRESS_NOEXCEPT {
1090 if (_version == ip_version::V6) {
1091 _ipv.ipv6.set_scope_id(scope_id, code);
1092 }
1093 }
1094
1095 /**
1096 * Sets the scope identifier of the IPv6 address using a `std::wstring` and reports any errors.
1097 *
1098 * @param[in] scope_id The wide string representing the scope identifier.
1099 * @param[out] code An error_code object that will store the result of the operation.
1100 */
1101 IPADDRESS_FORCE_INLINE void set_scope_id(const std::wstring& scope_id, error_code& code) IPADDRESS_NOEXCEPT {
1102 if (_version == ip_version::V6) {
1103 _ipv.ipv6.set_scope_id(scope_id, code);
1104 }
1105 }
1106
1107 /**
1108 * Sets the scope identifier of the IPv6 address using a `std::u16string` and reports any errors.
1109 *
1110 * @param[in] scope_id The UTF-16 string representing the scope identifier.
1111 * @param[out] code An error_code object that will store the result of the operation.
1112 */
1113 IPADDRESS_FORCE_INLINE void set_scope_id(const std::u16string& scope_id, error_code& code) IPADDRESS_NOEXCEPT {
1114 if (_version == ip_version::V6) {
1115 _ipv.ipv6.set_scope_id(scope_id, code);
1116 }
1117 }
1118
1119 /**
1120 * Sets the scope identifier of the IPv6 address using a `std::u32string` and reports any errors.
1121 *
1122 * @param[in] scope_id The UTF-32 string representing the scope identifier.
1123 * @param[out] code An error_code object that will store the result of the operation.
1124 */
1125 IPADDRESS_FORCE_INLINE void set_scope_id(const std::u32string& scope_id, error_code& code) IPADDRESS_NOEXCEPT {
1126 if (_version == ip_version::V6) {
1127 _ipv.ipv6.set_scope_id(scope_id, code);
1128 }
1129 }
1130
1131#endif // IPADDRESS_CPP_VERSION < 17
1132
1133 /**
1134 * Parses an IP address from a character array.
1135 *
1136 * This method template parses an IP address from a character array of a
1137 * specified size. Can check and get the result at compile time.
1138 *
1139 * @tparam T The character type of the array.
1140 * @tparam N The size of the character array.
1141 * @param[in] address The character array containing the IP address to parse.
1142 * @return An instance of ip address parsed from the character array.
1143 */
1144 template <typename T, size_t N>
1146 return internal::ip_any_parser<ip_address>::parse(address);
1147 }
1148
1149 /**
1150 * Parses an IP address from a character array and reports errors through an error code.
1151 *
1152 * This method template parses an IP address from a character array of a specified size
1153 * and provides an error code if the parsing fails.
1154 *
1155 * @tparam T The character type of the array.
1156 * @tparam N The size of the character array.
1157 * @param[in] address The character array containing the IP address to parse.
1158 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
1159 * @return An instance of ip address parsed from the character array. If parsing fails, the returned object will be in an unspecified state.
1160 */
1161 template <typename T, size_t N>
1162 static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address parse(const T(&address)[N], error_code& code) IPADDRESS_NOEXCEPT {
1163 return internal::ip_any_parser<ip_address>::parse(address, code);
1164 }
1165
1166 /**
1167 * Sets the scope identifier of the IPv6 address.
1168 *
1169 * This function sets the scope identifier using a character array. The length of the array
1170 * should not exceed `IPADDRESS_IPV6_SCOPE_MAX_LENGTH + 1`.
1171 *
1172 * @tparam T The character type of the scope identifier.
1173 * @tparam N The size of the scope identifier array.
1174 * @param[in] scope_id The character array representing the scope identifier.
1175 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
1176 */
1177 template <typename T, size_t N>
1178 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void set_scope_id(const T(&scope_id)[N]) IPADDRESS_NOEXCEPT(noexcept(ipv6_address().set_scope_id(scope_id))) {
1179 if (_version == ip_version::V6) {
1180 _ipv.ipv6.set_scope_id(scope_id);
1181 }
1182 }
1183
1184 /**
1185 * Retrieves the scope identifier of the IPv6 address.
1186 *
1187 * The scope identifier is used to determine the context in which the address is valid.
1188 * It is particularly relevant for link-local and site-local addresses.
1189 *
1190 * @return A `scope` object representing the scope identifier of the IPv6 address.
1191 * @remark If the scope is disabled in the settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`), then an empty scope will be returned.
1192 */
1194 if (_version == ip_version::V4) {
1195 return fixed_string<IPADDRESS_IPV6_SCOPE_MAX_LENGTH>();
1196 }
1197 return _ipv.ipv6.get_scope_id();
1198 }
1199
1200 /**
1201 * Converts the IP address to a uint32_t.
1202 *
1203 * This function casts the IP address to a uint32_t. For IPv4 addresses, it returns the direct numeric representation.
1204 * For IPv6 addresses, it returns the least significant 32 bits of the address.
1205 *
1206 * @return A uint32_t representing the IPv4 address or the least significant 32 bits of the IPv6 address.
1207 * @remark Bytes in integer are presented in **host byte order**.
1208 */
1209 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE explicit operator uint32_t() const IPADDRESS_NOEXCEPT {
1210 return to_uint32();
1211 }
1212
1213 /**
1214 * Converts the IP address to a uint128_t.
1215 *
1216 * This function casts the IP address to a uint128_t. It is used to obtain the full numeric representation of the IP address,
1217 * especially for IPv6 addresses.
1218 *
1219 * @return A uint128_t representing the numeric value of the IP address.
1220 * @remark Bytes in integer are presented in **host byte order**.
1221 */
1223 return to_uint128();
1224 }
1225
1226 /**
1227 * Converts the IP address to a string.
1228 *
1229 * This operator allows the IP address to be converted to a string.
1230 *
1231 * @tparam T The character type of the string.
1232 * @return A `std::string` representation of the IP address.
1233 */
1234 template <typename T>
1235 IPADDRESS_NODISCARD IPADDRESS_FORCE_INLINE explicit operator std::basic_string<T, std::char_traits<T>, std::allocator<T>>() const {
1236 return internal::string_converter<T>::convert(to_string());
1237 }
1238
1239 /**
1240 * Equality comparison operator.
1241 *
1242 * Compares this IP address with another IP address for equality.
1243 *
1244 * @param[in] rhs The right-hand side ip_address object for comparison.
1245 * @return True if both IP addresses are equal, false otherwise.
1246 */
1248 if (_version != rhs._version) {
1249 return false;
1250 }
1251 return _version == ip_version::V4 ? (_ipv.ipv4 == rhs._ipv.ipv4) : (_ipv.ipv6 == rhs._ipv.ipv6);
1252 }
1253
1254 /**
1255 * Inequality comparison operator.
1256 *
1257 * Compares this IP address with another IP address for inequality.
1258 *
1259 * @param[in] rhs The right-hand side ip_address object for comparison.
1260 * @return True if both IP addresses are not equal, false otherwise.
1261 */
1263 return !(*this == rhs);
1264 }
1265
1266#ifdef IPADDRESS_HAS_SPACESHIP_OPERATOR
1267
1268 /**
1269 * Three-way comparison operator (spaceship operator).
1270 *
1271 * Compares this IP address with another IP address to determine the ordering.
1272 *
1273 * @param[in] rhs The right-hand side ip_address object for comparison.
1274 * @return `std::strong_ordering` indicating less than, equivalent to, or greater than.
1275 */
1277 if (const auto result = _version <=> rhs._version; result == std::strong_ordering::equivalent) {
1278 return _version == ip_version::V4 ? (_ipv.ipv4 <=> rhs._ipv.ipv4) : (_ipv.ipv6 <=> rhs._ipv.ipv6);
1279 } else {
1280 return result;
1281 }
1282 }
1283
1284#else // !IPADDRESS_HAS_SPACESHIP_OPERATOR
1285
1286 /**
1287 * Less than comparison operator.
1288 *
1289 * Compares this IP address with another IP address to determine if it is less than the other.
1290 *
1291 * @param[in] rhs The right-hand side ip_address object for comparison.
1292 * @return True if this IP address is less than the other, false otherwise.
1293 */
1295 if (_version < rhs._version) {
1296 return true;
1297 }
1298 if (_version > rhs._version) {
1299 return false;
1300 }
1301 return _version == ip_version::V4 ? (_ipv.ipv4 < rhs._ipv.ipv4) : (_ipv.ipv6 < rhs._ipv.ipv6);
1302 }
1303
1304 /**
1305 * Greater than comparison operator.
1306 *
1307 * Compares this IP address with another IP address to determine if it is greater than the other.
1308 *
1309 * @param[in] rhs The right-hand side ip_address object for comparison.
1310 * @return True if this IP address is greater than the other, false otherwise.
1311 */
1313 return rhs < *this;
1314 }
1315
1316 /**
1317 * Less than or equal to comparison operator.
1318 *
1319 * Compares this IP address with another IP address to determine if it is less than or equal to the other.
1320 *
1321 * @param[in] rhs The right-hand side ip_address object for comparison.
1322 * @return True if this IP address is less than or equal to the other, false otherwise.
1323 */
1325 return !(rhs < *this);
1326 }
1327
1328 /**
1329 * Greater than or equal to comparison operator.
1330 *
1331 * Compares this IP address with another IP address to determine if it is greater than or equal to the other.
1332 *
1333 * @param[in] rhs The right-hand side ip_address object for comparison.
1334 * @return True if this IP address is greater than or equal to the other, false otherwise.
1335 */
1337 return !(*this < rhs);
1338 }
1339
1340#endif // !IPADDRESS_HAS_SPACESHIP_OPERATOR
1341
1342private:
1343 union ip_any_address {
1344 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_any_address() IPADDRESS_NOEXCEPT : ipv4() {
1345 }
1346
1347 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_any_address(const ipv4_address& ip) IPADDRESS_NOEXCEPT : ipv4(ip) {
1348 }
1349
1350 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_any_address(const ipv6_address& ip) IPADDRESS_NOEXCEPT : ipv6(ip) {
1351 }
1352
1353 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE explicit ip_any_address(const base_type_ipv4& bytes) IPADDRESS_NOEXCEPT : ipv4(bytes) {
1354 }
1355
1356 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE explicit ip_any_address(const base_type_ipv6& bytes) IPADDRESS_NOEXCEPT : ipv6(bytes) {
1357 }
1358
1359 ipv4_address ipv4;
1360 ipv6_address ipv6;
1361 } _ipv {};
1362 ip_version _version = ip_version::V4;
1363};
1364
1365#ifdef IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
1366
1367 /**
1368 * User-defined literal for creating an ip_address from a fixed string at compile time.
1369 *
1370 * @tparam FixedString A compile-time fixed string representing the IPv6 address.
1371 * @return An ip_address object parsed from the fixed string.
1372 */
1373 IPADDRESS_EXPORT template <fixed_string FixedString>
1374 IPADDRESS_NODISCARD IPADDRESS_CONSTEVAL IPADDRESS_FORCE_INLINE ip_address operator""_ip() IPADDRESS_NOEXCEPT {
1375 return ip_address::parse<FixedString>();
1376 }
1377
1378#else // IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
1379
1380 /**
1381 * User-defined literal for creating an ip_address from a string literal.
1382 *
1383 * @param[in] address A pointer to a character array representing the IPv6 address.
1384 * @param[in] size The size of the character array.
1385 * @return An ip_address object parsed from the string literal.
1386 */
1388 if (size > ipv6_address::base_max_string_len) {
1389 raise_error(error_code::string_is_too_long, 0, address, size);
1390 }
1391 char str[ipv6_address::base_max_string_len + 1] = {};
1392 for (size_t i = 0; i < size && i < ipv6_address::base_max_string_len; ++i) {
1393 str[i] = address[i];
1394 }
1395 return ip_address::parse(str);
1396 }
1397
1398 /**
1399 * User-defined literal for creating an ip_address from a wide string literal.
1400 *
1401 * @param[in] address A pointer to a character array representing the IPv6 address.
1402 * @param[in] size The size of the character array.
1403 * @return An ip_address object parsed from the string literal.
1404 */
1405 IPADDRESS_EXPORT IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address operator""_ip(const wchar_t* address, size_t size) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1406 if (size > ipv6_address::base_max_string_len) {
1407 raise_error(error_code::string_is_too_long, 0, address, size);
1408 }
1409 wchar_t str[ipv6_address::base_max_string_len + 1] = {};
1410 for (size_t i = 0; i < size && i < ipv6_address::base_max_string_len; ++i) {
1411 str[i] = address[i];
1412 }
1413 return ip_address::parse(str);
1414 }
1415
1416 /**
1417 * User-defined literal for creating an ip_address from a UTF-16 string literal.
1418 *
1419 * @param[in] address A pointer to a character array representing the IPv6 address.
1420 * @param[in] size The size of the character array.
1421 * @return An ip_address object parsed from the string literal.
1422 */
1423 IPADDRESS_EXPORT IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address operator""_ip(const char16_t* address, size_t size) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1424 if (size > ipv6_address::base_max_string_len) {
1425 raise_error(error_code::string_is_too_long, 0, address, size);
1426 }
1427 char16_t str[ipv6_address::base_max_string_len + 1] = {};
1428 for (size_t i = 0; i < size && i < ipv6_address::base_max_string_len; ++i) {
1429 str[i] = address[i];
1430 }
1431 return ip_address::parse(str);
1432 }
1433
1434 /**
1435 * User-defined literal for creating an ip_address from a UTF-32 string literal.
1436 *
1437 * @param[in] address A pointer to a character array representing the IPv6 address.
1438 * @param[in] size The size of the character array.
1439 * @return An ip_address object parsed from the string literal.
1440 */
1441 IPADDRESS_EXPORT IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address operator""_ip(const char32_t* address, size_t size) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1442 if (size > ipv6_address::base_max_string_len) {
1443 raise_error(error_code::string_is_too_long, 0, address, size);
1444 }
1445 char32_t str[ipv6_address::base_max_string_len + 1] = {};
1446 for (size_t i = 0; i < size && i < ipv6_address::base_max_string_len; ++i) {
1447 str[i] = address[i];
1448 }
1449 return ip_address::parse(str);
1450 }
1451
1452#endif // IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
1453
1454} // namespace IPADDRESS_NAMESPACE
1455
1456#ifndef IPADDRESS_NO_OVERLOAD_STD
1457
1458namespace std {
1459
1460IPADDRESS_EXPORT template <>
1461struct hash<IPADDRESS_NAMESPACE::ip_address> {
1462 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE size_t operator()(const IPADDRESS_NAMESPACE::ip_address& ip) const IPADDRESS_NOEXCEPT {
1463 return ip.hash();
1464 }
1465};
1466
1468 ip1.swap(ip2);
1469}
1470
1472 return ip.to_string();
1473}
1474
1476 return ip.to_wstring();
1477}
1478
1479IPADDRESS_EXPORT template <typename T>
1480IPADDRESS_FORCE_INLINE std::basic_ostream<T, std::char_traits<T>>& operator<<(std::basic_ostream<T, std::char_traits<T>>& stream, const IPADDRESS_NAMESPACE::ip_address& ip) {
1481 auto& iword = stream.iword(IPADDRESS_NAMESPACE::stream_index());
1482 auto fmt = iword
1483 ? (IPADDRESS_NAMESPACE::format) (iword - 1)
1485 iword = 0;
1486 auto str = ip.to_string(fmt);
1487 if (stream.flags() & ios_base::uppercase) {
1488 auto end = std::find(str.cbegin(), str.cend(), '%');
1489 std::transform(str.cbegin(), end, str.begin(), [](char c){
1490 return std::toupper(c);
1491 });
1492 }
1493 return stream << IPADDRESS_NAMESPACE::internal::string_converter<T>::convert(str);
1494}
1495
1496IPADDRESS_EXPORT template <typename T>
1497IPADDRESS_FORCE_INLINE std::basic_istream<T, std::char_traits<T>>& operator>>(std::basic_istream<T, std::char_traits<T>>& stream, IPADDRESS_NAMESPACE::ip_address& ip) {
1498 std::basic_string<T, std::char_traits<T>, std::allocator<T>> str;
1499 stream >> str;
1501 ip = IPADDRESS_NAMESPACE::ip_address::parse(str, err);
1503 stream.setstate(std::ios_base::failbit);
1504 }
1505 return stream;
1506}
1507
1508} // namespace std
1509
1510#endif // IPADDRESS_NO_OVERLOAD_STD
1511
1512#endif // IPADDRESS_IP_ANY_ADDRESS_HPP
A class that represents an IP address, supporting both IPv4 and IPv6 formats.
Definition ip-any-address.hpp:73
constexpr inline bool operator>=(const ip_address &rhs) const noexcept
Greater than or equal to comparison operator.
Definition ip-any-address.hpp:1336
constexpr inline bool is_v4() const noexcept
Checks if the IP address is an IPv4 address.
Definition ip-any-address.hpp:183
constexpr inline bool operator<(const ip_address &rhs) const noexcept
Less than comparison operator.
Definition ip-any-address.hpp:1294
inline std::u16string to_u16string(format fmt=format::compressed) const
Converts the IP address to a string.
Definition ip-any-address.hpp:472
constexpr inline const uint8_t * data() const noexcept
Retrieves the raw data of the IP address in network byte order (big-endian).
Definition ip-any-address.hpp:296
constexpr inline bool is_site_local() const noexcept
Checks if the IPv6 address is a site-local address.
Definition ip-any-address.hpp:174
static constexpr inline ip_address from_uint(uint_type_ipv4 ip) noexcept
Static factory method to create an ip_address from a uint_type_ipv4.
Definition ip-any-address.hpp:399
static constexpr inline ip_address from_bytes(const base_type_ipv4 &bytes) noexcept
Static factory method to create an ip_address from byte array for IPv4.
Definition ip-any-address.hpp:354
constexpr inline bool operator==(const ip_address &rhs) const noexcept
Equality comparison operator.
Definition ip-any-address.hpp:1247
inline std::string reverse_pointer() const
Generates a reverse DNS lookup pointer for the IP address.
Definition ip-any-address.hpp:522
constexpr inline bool is_multicast() const noexcept
Checks if the IP address is a multicast address.
Definition ip-any-address.hpp:97
constexpr inline bool operator>(const ip_address &rhs) const noexcept
Greater than comparison operator.
Definition ip-any-address.hpp:1312
static constexpr inline ip_address parse(const T(&address)[N])
Parses an IP address from a character array.
Definition ip-any-address.hpp:1145
constexpr inline void set_scope_id(const T(&scope_id)[N]) noexcept(noexcept(ipv6_address().set_scope_id(scope_id)))
Sets the scope identifier of the IPv6 address.
Definition ip-any-address.hpp:1178
constexpr inline bool is_private() const noexcept
Checks if the IP address is a private address.
Definition ip-any-address.hpp:108
constexpr inline operator uint32_t() const noexcept
Converts the IP address to a uint32_t.
Definition ip-any-address.hpp:1209
constexpr inline bool is_reserved() const noexcept
Checks if the IP address is a reserved address.
Definition ip-any-address.hpp:128
static constexpr inline ip_address from_uint(const uint_type_ipv6 &ip) noexcept
Static factory method to create an ip_address from a uint_type_ipv6.
Definition ip-any-address.hpp:410
static constexpr inline ip_address from_bytes(const uint8_t *bytes, size_t byte_count, ip_version version) noexcept
Static factory method to create an ip_address from raw bytes.
Definition ip-any-address.hpp:388
constexpr inline scope get_scope_id() const noexcept
Retrieves the scope identifier of the IPv6 address.
Definition ip-any-address.hpp:1193
constexpr inline bool is_link_local() const noexcept
Checks if the IP address is link-local.
Definition ip-any-address.hpp:148
constexpr inline void swap(ip_address &ip) noexcept
Swaps the contents of this ip_address with another ip_address.
Definition ip-any-address.hpp:533
constexpr inline uint32_t to_uint32() const noexcept
Converts the IP address to a uint32_t.
Definition ip-any-address.hpp:423
inline operator std::basic_string< T, std::char_traits< T >, std::allocator< T > >() const
Converts the IP address to a string.
Definition ip-any-address.hpp:1235
constexpr inline ip_address(const base_type_ipv4 &bytes) noexcept
Constructor from byte array for IPv4.
Definition ip-any-address.hpp:335
constexpr inline uint128_t to_uint128() const noexcept
Converts the IP address to a uint128_t.
Definition ip-any-address.hpp:436
constexpr inline ip_address(const ipv4_address &ipv4) noexcept
Constructor from an ipv4_address.
Definition ip-any-address.hpp:315
constexpr inline ip_version version() const noexcept
Retrieves the version of the IP address.
Definition ip-any-address.hpp:86
constexpr inline bool is_unspecified() const noexcept
Checks if the IP address is unspecified.
Definition ip-any-address.hpp:163
constexpr inline optional< ipv4_address > v4() const noexcept
Retrieves the IPv4 address.
Definition ip-any-address.hpp:267
constexpr inline bool is_global() const noexcept
Checks if the IP address is a global address.
Definition ip-any-address.hpp:119
constexpr inline operator uint128_t() const noexcept
Converts the IP address to a uint128_t.
Definition ip-any-address.hpp:1222
constexpr inline ip_address() noexcept
Default constructor.
Definition ip-any-address.hpp:305
constexpr inline optional< ipv6_address > v6() const noexcept
Retrieves the IPv6 address.
Definition ip-any-address.hpp:281
constexpr inline bool operator<=(const ip_address &rhs) const noexcept
Less than or equal to comparison operator.
Definition ip-any-address.hpp:1324
constexpr inline size_t hash() const noexcept
Computes a hash value for the IP address.
Definition ip-any-address.hpp:215
constexpr inline ip_address(const ipv6_address &ipv6) noexcept
Constructor from an ipv6_address.
Definition ip-any-address.hpp:325
constexpr inline optional< std::pair< ipv4_address, ipv4_address > > teredo() const noexcept
Determines if the IPv6 address is a Teredo address.
Definition ip-any-address.hpp:256
constexpr inline optional< ipv4_address > ipv4_mapped() const noexcept
Determines if the IPv6 address is an IPv4-mapped address.
Definition ip-any-address.hpp:227
constexpr inline bool operator!=(const ip_address &rhs) const noexcept
Inequality comparison operator.
Definition ip-any-address.hpp:1262
inline std::wstring to_wstring(format fmt=format::compressed) const
Converts the IP address to a string.
Definition ip-any-address.hpp:460
constexpr inline optional< ipv4_address > sixtofour() const noexcept
Determines if the IPv6 address is a 6to4 address.
Definition ip-any-address.hpp:240
constexpr inline size_t size() const noexcept
Retrieves the size of the IP address.
Definition ip-any-address.hpp:203
inline std::u32string to_u32string(format fmt=format::compressed) const
Converts the IP address to a string.
Definition ip-any-address.hpp:484
static constexpr inline ip_address parse(const T(&address)[N], error_code &code) noexcept
Parses an IP address from a character array and reports errors through an error code.
Definition ip-any-address.hpp:1162
constexpr inline bool is_loopback() const noexcept
Checks if the IP address is a loopback address.
Definition ip-any-address.hpp:139
inline std::string to_string(format fmt=format::compressed) const
Converts the IP address to a string.
Definition ip-any-address.hpp:448
constexpr inline bool is_v6() const noexcept
Checks if the IP address is an IPv6 address.
Definition ip-any-address.hpp:192
A template class to manage an optional contained value.
Definition optional.hpp:35
inline std::u8string to_u8string(format fmt=format::decimal) const
Converts the uint128_t value to a string representation.
Definition uint128.hpp:402
#define IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS
Definition config.hpp:93
#define IPADDRESS_EXPORT
Definition config.hpp:42
#define IPADDRESS_NODISCARD
Definition config.hpp:98
#define IPADDRESS_FORCE_INLINE
Definition config.hpp:112
#define IPADDRESS_NAMESPACE
Definition config.hpp:38
#define IPADDRESS_NOEXCEPT
Definition config.hpp:89
#define IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS
Definition config.hpp:102
ip_version
Enumerates the IP address versions.
Definition ip-address-base.hpp:29
@ V4
IPv4 version identifier.
@ V6
IPv6 version identifier.
format
Enumerates the formatting options for IP address strings.
Definition ip-address-base.hpp:40
@ compressed
Compressed format with maximal omission of segments or octets.
error_code
Enumeration of error codes for IP address parsing and validation.
Definition errors.hpp:52
@ no_error
Indicates the absence of any errors.