ipaddress 1.2.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 * @parblock
172 * @note Site-local addresses are equivalent to private addresses in IPv4 and are not routable on the global internet.
173 * @endparblock
174 * @parblock
175 * @note The site-local address space is no longer recommended (per [RFC 3879](https://datatracker.ietf.org/doc/html/rfc3879.html)).
176 * Instead, use is_private to verify if the address is a unique local address ([RFC 4193](https://datatracker.ietf.org/doc/html/rfc4193.html)).
177 * @endparblock
178 * @remark These attribute is true for the network as a whole if it is true for both the network address and the broadcast address.
179 */
181 return _version == ip_version::V4 ? false : _ipv.ipv6.is_site_local();
182 }
183
184 /**
185 * Checks if the IP address is an IPv4 address.
186 *
187 * @return `true` if the IP address is an IPv4 address, `false` otherwise.
188 */
190 return _version == ip_version::V4;
191 }
192
193 /**
194 * Checks if the IP address is an IPv6 address.
195 *
196 * @return `true` if the IP address is an IPv6 address, `false` otherwise.
197 */
199 return _version == ip_version::V6;
200 }
201
202 /**
203 * Retrieves the size of the IP address.
204 *
205 * Depending on the IP version, this function returns the size of the IPv4 or IPv6 address.
206 *
207 * @return The size of the IP address in bytes.
208 */
210 return _version == ip_version::V4 ? _ipv.ipv4.size() : _ipv.ipv6.size();
211 }
212
213 /**
214 * Computes a hash value for the IP address.
215 *
216 * This function generates a hash value that can be used to uniquely identify the IP address.
217 * It can be useful when IP addresses are used as keys in hash tables.
218 *
219 * @return A `size_t` hash value of the IP address.
220 */
222 return _version == ip_version::V4 ? _ipv.ipv4.hash() : _ipv.ipv6.hash();
223 }
224
225 /**
226 * Determines if the IPv6 address is an IPv4-mapped address.
227 *
228 * If the IP address is an IPv6 address, this function returns the IPv4-mapped IPv6 address if available.
229 *
230 * @return An `optional` containing the mapped IPv4 address if the IPv6 address is IPv4-mapped, or an empty `optional` otherwise.
231 * @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`).
232 */
234 return _version == ip_version::V4 ? optional<ipv4_address>() : _ipv.ipv6.ipv4_mapped();
235 }
236
237 /**
238 * Obtains the IPv6-mapped representation of the current IP address.
239 *
240 * When the IP address holds an IPv4 value, this method converts it into its IPv6-mapped representation,
241 * following the convention (e.g. ::FFFF:IPv4). If the IP address already represents an IPv6 value,
242 * it returns the address as is.
243 *
244 * @return An `ipv6_address` representing the IPv6-mapped version of the stored IP address.
245 * @remark Converting an IPv4 address to IPv6 through this method always produces a valid IPv6 address.
246 * In contrast, the reverse operation via `ipv4_mapped()` succeeds only if the IPv6 address is indeed an IPv4-mapped address.
247 * @see [RFC 4291](https://datatracker.ietf.org/doc/html/rfc4291.html).
248 */
250 return _version == ip_version::V4 ? _ipv.ipv4.ipv6_mapped() : _ipv.ipv6;
251 }
252
253 /**
254 * Determines if the IPv6 address is a 6to4 address.
255 *
256 * If the IP address is an IPv6 address, this function returns the 6to4 address if available.
257 *
258 * @return An optional containing the encapsulated IPv4 address if the IPv6 address is a 6to4 address, or an empty optional otherwise.
259 * @remark A 6to4 address uses a `2002::/16` prefix and embeds an IPv4 address in the next 32 bits.
260 * @see [RFC 3056](https://datatracker.ietf.org/doc/html/rfc3056.html).
261 */
263 return _version == ip_version::V4 ? optional<ipv4_address>() : _ipv.ipv6.sixtofour();
264 }
265
266 /**
267 * Determines if the IPv6 address is a Teredo address.
268 *
269 * If the IP address is an IPv6 address, this function returns the Teredo address, which includes
270 * both the Teredo server and client IPv4 addresses.
271 *
272 * @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.
273 * @retval std::pair::first The Teredo server IPv4 address
274 * @retval std::pair::second The Teredo client IPv4 address
275 * @remark A Teredo address begins with the `2001::/32` prefix and is used for NAT traversal for IPv6.
276 * @see [RFC 4380](https://datatracker.ietf.org/doc/html/rfc4380.html).
277 */
278 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE optional<std::pair<ipv4_address, ipv4_address>> teredo() const IPADDRESS_NOEXCEPT {
279 return _version == ip_version::V4 ? optional<std::pair<ipv4_address, ipv4_address>>() : _ipv.ipv6.teredo();
280 }
281
282 /**
283 * Retrieves the IPv4 address.
284 *
285 * If the IP address is an IPv4 address, this function returns the IPv4 address.
286 *
287 * @return An optional containing the IPv4 address, or an empty optional if the IP address is not IPv4.
288 */
289 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE optional<ipv4_address> v4() const IPADDRESS_NOEXCEPT {
290 if (_version == ip_version::V6) {
291 return optional<ipv4_address>();
292 }
293 return optional<ipv4_address>(_ipv.ipv4);
294 }
295
296 /**
297 * Retrieves the IPv6 address.
298 *
299 * If the IP address is an IPv6 address, this function returns the IPv6 address.
300 *
301 * @return An optional containing the IPv6 address, or an empty optional if the IP address is not IPv6.
302 */
303 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE optional<ipv6_address> v6() const IPADDRESS_NOEXCEPT {
304 if (_version == ip_version::V4) {
305 return optional<ipv6_address>();
306 }
307 return optional<ipv6_address>(_ipv.ipv6);
308 }
309
310 /**
311 * Retrieves the raw data of the IP address in **network byte order** (big-endian).
312 *
313 * This function returns a pointer to the raw data representing the IP address. The format of the data
314 * depends on whether the address is IPv4 or IPv6.
315 *
316 * @return A pointer to the raw data of the IP address.
317 */
318 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE const uint8_t* data() const IPADDRESS_NOEXCEPT {
319 return _version == ip_version::V4 ? _ipv.ipv4.data() : _ipv.ipv6.data();
320 }
321
322 /**
323 * Default constructor.
324 *
325 * Constructs an ip_address object with an unspecified ip address with version IPv4.
326 */
327 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address() IPADDRESS_NOEXCEPT { // NOLINT(modernize-use-equals-default): for C++11 support
328 }
329
330 /**
331 * Constructor from an ipv4_address.
332 *
333 * Constructs an ip_address object with the specified IPv4 address.
334 *
335 * @param[in] ipv4 An ipv4_address object to initialize the ip_address.
336 */
337 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address(const ipv4_address& ipv4) IPADDRESS_NOEXCEPT : _ipv(ipv4) {
338 }
339
340 /**
341 * Constructor from an ipv6_address.
342 *
343 * Constructs an ip_address object with the specified IPv6 address.
344 *
345 * @param[in] ipv6 An ipv6_address object to initialize the ip_address.
346 */
347 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address(const ipv6_address& ipv6) IPADDRESS_NOEXCEPT : _ipv(ipv6), _version(ip_version::V6) {
348 }
349
350 /**
351 * Constructor from byte array for IPv4.
352 *
353 * Constructs an ip_address object with the specified byte array for an IPv4 address.
354 *
355 * @param[in] bytes A base_type_ipv4 object representing the byte array of the IPv4 address.
356 */
357 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE explicit ip_address(const base_type_ipv4& bytes) IPADDRESS_NOEXCEPT : _ipv(bytes) {
358 }
359
360 /**
361 * Constructor from byte array for IPv6.
362 *
363 * Constructs an ip_address object with the specified byte array for an IPv6 address.
364 *
365 * @param[in] bytes A base_type_ipv6 object representing the byte array of the IPv6 address.
366 */
367 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE explicit ip_address(const base_type_ipv6& bytes) IPADDRESS_NOEXCEPT : _ipv(bytes), _version(ip_version::V6) {
368 }
369
370 /**
371 * Static factory method to create an ip_address from byte array for IPv4.
372 *
373 * @param[in] bytes A base_type_ipv4 object representing the byte array of the IPv4 address.
374 * @return An ip_address object initialized with the provided IPv4 bytes.
375 */
376 IPADDRESS_NODISCARD static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address from_bytes(const base_type_ipv4& bytes) IPADDRESS_NOEXCEPT {
377 return ip_address(bytes);
378 }
379
380 /**
381 * Static factory method to create an ip_address from byte array for IPv6.
382 *
383 * @param[in] bytes A base_type_ipv6 object representing the byte array of the IPv6 address.
384 * @return An ip_address object initialized with the provided IPv6 bytes.
385 */
386 IPADDRESS_NODISCARD static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address from_bytes(const base_type_ipv6& bytes) IPADDRESS_NOEXCEPT {
387 return ip_address(bytes);
388 }
389
390 /**
391 * Static factory method to create an ip_address from raw bytes.
392 *
393 * This method creates an ip_address object from raw bytes, with the specified IP version.
394 *
395 * @param[in] bytes A pointer to the raw bytes representing the IP address.
396 * @param[in] byte_count The number of bytes to use from the pointer.
397 * @param[in] version The version of the IP address to create (IPv4 or IPv6).
398 * @return An ip_address object initialized with the provided bytes and version.
399 * @parblock
400 * @remark If the number of bytes \a byte_count is less than the target number .
401 * of bytes to represent the IP address, the missing bytes will be
402 * filled with zeros.
403 * @endparblock
404 * @parblock
405 * @remark If the number of bytes \a byte_count is greater than the target .
406 * number of bytes represented by the IP address, then the extra
407 * bytes will be ignored
408 * @endparblock
409 */
410 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 {
411 return version == ip_version::V4 ? ip_address(ipv4_address::from_bytes(bytes, byte_count)) : ip_address(ipv6_address::from_bytes(bytes, byte_count));
412 }
413
414 /**
415 * Static factory method to create an ip_address from a uint_type_ipv4.
416 *
417 * @param[in] ip A uint_type_ipv4 (uint32_t) representing the IPv4 address.
418 * @return An ip_address object initialized with the provided IPv4 address.
419 * @remark Bytes in integer \a ip must be presented in **host byte order**.
420 */
422 return ip_address(ipv4_address::from_uint(ip));
423 }
424
425 /**
426 * Static factory method to create an ip_address from a uint_type_ipv6.
427 *
428 * @param[in] ip A uint_type_ipv6 (uint128_t) representing the IPv6 address.
429 * @return An ip_address object initialized with the provided IPv6 address.
430 * @remark Bytes in integer \a ip must be presented in **host byte order**.
431 */
432 IPADDRESS_NODISCARD static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address from_uint(const uint_type_ipv6& ip) IPADDRESS_NOEXCEPT {
433 return ip_address(ipv6_address::from_uint(ip));
434 }
435
436 /**
437 * Converts the IP address to a uint32_t.
438 *
439 * This function returns the numeric representation of the IP address as a uint32_t. For IPv6 addresses,
440 * it returns the least significant 32 bits of the address.
441 *
442 * @return A uint32_t representing the IPv4 address or the least significant 32 bits of the IPv6 address.
443 * @remark Bytes in integer are presented in **host byte order**.
444 */
446 return _version == ip_version::V4 ? _ipv.ipv4.to_uint() : uint32_t(_ipv.ipv6.to_uint());
447 }
448
449 /**
450 * Converts the IP address to a uint128_t.
451 *
452 * This function returns the numeric representation of the IP address as a uint128_t. For IPv4 addresses,
453 * the function converts the address to a uint128_t format.
454 *
455 * @return A uint128_t representing the numeric value of the IP address.
456 * @remark Bytes in integer are presented in **host byte order**.
457 */
459 return _version == ip_version::V4 ? uint128_t(_ipv.ipv4.to_uint()) : _ipv.ipv6.to_uint();
460 }
461
462 /**
463 * Converts the IP address to a string.
464 *
465 * This function returns a string representation of the IP address. The format can be specified by the \a fmt parameter.
466 *
467 * @param[in] fmt The format to use for the string representation, defaults to compressed format.
468 * @return A `std::string` representing the IP address in the specified format.
469 */
471 return _version == ip_version::V4 ? _ipv.ipv4.to_string(fmt) : _ipv.ipv6.to_string(fmt);
472 }
473
474 /**
475 * Converts the IP address to a string.
476 *
477 * This function returns a string representation of the IP address. The format can be specified by the \a fmt parameter.
478 *
479 * @param[in] fmt The format to use for the string representation, defaults to compressed format.
480 * @return A `std::wstring` representing the IP address in the specified format.
481 */
483 return _version == ip_version::V4 ? _ipv.ipv4.to_wstring(fmt) : _ipv.ipv6.to_wstring(fmt);
484 }
485
486 /**
487 * Converts the IP address to a string.
488 *
489 * This function returns a string representation of the IP address. The format can be specified by the \a fmt parameter.
490 *
491 * @param[in] fmt The format to use for the string representation, defaults to compressed format.
492 * @return A `std::u16string` representing the IP address in the specified format.
493 */
495 return _version == ip_version::V4 ? _ipv.ipv4.to_u16string(fmt) : _ipv.ipv6.to_u16string(fmt);
496 }
497
498 /**
499 * Converts the IP address to a string.
500 *
501 * This function returns a string representation of the IP address. The format can be specified by the \a fmt parameter.
502 *
503 * @param[in] fmt The format to use for the string representation, defaults to compressed format.
504 * @return A `std::u32string` representing the IP address in the specified format.
505 */
507 return _version == ip_version::V4 ? _ipv.ipv4.to_u32string(fmt) : _ipv.ipv6.to_u32string(fmt);
508 }
509
510#if __cpp_char8_t >= 201811L
511
512 /**
513 * Converts the IP address to a string.
514 *
515 * This function returns a string representation of the IP address. The format can be specified by the \a fmt parameter.
516 *
517 * @param[in] fmt The format to use for the string representation, defaults to compressed format.
518 * @return A `std::u8string` representing the IP address in the specified format.
519 */
523
524#endif // __cpp_char8_t
525
526 /**
527 * Generates a reverse DNS lookup pointer for the IP address.
528 *
529 * This function creates a string that is the reverse DNS lookup pointer of the IP address.
530 * It is commonly used in reverse DNS lookups, where the IP address is reversed and appended with `.in-addr.arpa` for IPv4,
531 * or `.ip6.arpa` for IPv6, to form a domain name that can be looked up in the DNS system.
532 *
533 * The name of the reverse DNS PTR record for the IP address, e.g.:
534 * @code{.cpp}
535 * std::cout << ip_address::parse("127.0.0.1").reverse_pointer() << std::endl;
536 * std::cout << ip_address::parse("2001:db8::1").reverse_pointer() << std::endl;
537 *
538 * // out:
539 * // 1.0.0.127.in-addr.arpa
540 * // 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
541 * @endcode
542 * @return A `std::string` that is the reverse DNS lookup pointer of the IP address.
543 */
545 return _version == ip_version::V4 ? _ipv.ipv4.reverse_pointer() : _ipv.ipv6.reverse_pointer();
546 }
547
548 /**
549 * Swaps the contents of this ip_address with another ip_address.
550 *
551 * This function exchanges the contents of the ip_address with those of the ip parameter.
552 *
553 * @param[in] ip The other ip_address object to swap with.
554 */
556 const auto tmp = *this;
557 *this = ip;
558 ip = tmp;
559 }
560
561#ifdef IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
562
563 /**
564 * Static method template to parse an IP address from a fixed string at compile time.
565 *
566 * @tparam FixedString A non-type template parameter that holds the string representation of the IP address.
567 * @return An instance of ip address parsed from the fixed string.
568 * @note This method is only available when non-type template parameters for strings are supported.
569 * @remark If parsing fails, an error will be raised at compile time.
570 */
571 template <fixed_string FixedString>
573 constexpr auto str = FixedString;
574 auto code = error_code::no_error;
575
576 char ip[str.size() + 1]{};
577 for (size_t i = 0; i < str.size(); ++i) {
578 ip[i] = str[i];
579 }
580
581 const auto ipv4 = ipv4_address::parse(ip, code);
582 if (code == error_code::no_error) {
583 return ip_address(ipv4);
584 }
585
587 }
588
589#endif // IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
590
591#if IPADDRESS_CPP_VERSION >= 17
592
593 /**
594 * Parses an IP address from a string view.
595 *
596 * This method provides a way to parse an IP address from a string view,
597 * which is a non-owning reference to a sequence of characters.
598 *
599 * @param[in] address The string view containing the IP address to parse.
600 * @return An instance of ip address parsed from the string view.
601 * @throw parse_error Exception caused by invalid input string.
602 * @note This method is available for C++17 and later versions.
603 * @remark For C++ versions prior to C++17, member functions with `std::string` and C-strings will be used instead.
604 */
608
609 /**
610 * Parses an IP address from a wide string view.
611 *
612 * This method allows for parsing an IP address from a wide string view,
613 * which is typically used for wide character strings.
614 *
615 * @param[in] address The wide string view containing the IP address to parse.
616 * @return An instance of ip address parsed from the string view.
617 * @throw parse_error Exception caused by invalid input string.
618 * @note This method is available for C++17 and later versions.
619 * @remark For C++ versions prior to C++17, member functions with `std::wstring` and C-strings will be used instead.
620 */
624
625#if __cpp_char8_t >= 201811L
626
627 /**
628 * Parses an IP address from a UTF-8 string view.
629 *
630 * This method parses an IP address from a given UTF-8 string view. It leverages the `char8_t`
631 * type introduced in C++20 to handle UTF-8 strings natively.
632 *
633 * @param[in] address A UTF-8 string view containing the IP address to parse.
634 * @return An instance of ip address parsed from the string view.
635 * @throw parse_error Exception caused by invalid input string.
636 * @note This method is available for C++20 and later versions where `char8_t` is supported.
637 */
641
642#endif // __cpp_char8_t
643
644 /**
645 * Parses an IP address from a UTF-16 string view.
646 *
647 * This method is designed to parse an IP address from a UTF-16 string view,
648 * which is a sequence of 16-bit characters.
649 *
650 * @param[in] address The UTF-16 string view containing the IP address to parse.
651 * @return An instance of ip address parsed from the string view.
652 * @throw parse_error Exception caused by invalid input string.
653 * @note This method is available for C++17 and later versions.
654 * @remark For C++ versions prior to C++17, member functions with `std::u16string` and C-strings will be used instead.
655 */
659
660 /**
661 * Parses an IP address from a UTF-32 string view.
662 *
663 * This method allows for parsing an IP address from a UTF-32 string view,
664 * which is a sequence of 32-bit characters.
665 *
666 * @param[in] address The UTF-32 string view containing the IP address to parse.
667 * @return An instance of ip address parsed from the string view.
668 * @throw parse_error Exception caused by invalid input string.
669 * @note This method is available for C++17 and later versions.
670 * @remark For C++ versions prior to C++17, member functions with `std::u32string` and C-strings will be used instead.
671 */
675
676 /**
677 * Parses an IP address from a string view and reports errors through an error code.
678 *
679 * This method parses an IP address from a string view and provides an error code if the parsing fails.
680 *
681 * @param[in] address The string view containing the IP address to parse.
682 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
683 * @return An instance of ip address parsed from the string view. If parsing fails, the returned object will be in an unspecified state.
684 * @note This method is available for C++17 and later versions.
685 * @remark For C++ versions prior to C++17, member functions with `std::string` and C-strings will be used instead.
686 */
690
691 /**
692 * Parses an IP address from a wide string view and reports errors through an error code.
693 *
694 * This method parses an IP address from a wide string view and provides an error code if the parsing fails.
695 *
696 * @param[in] address The wide string view containing the IP address to parse.
697 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
698 * @return An instance of ip address parsed from the wide string view. If parsing fails, the returned object will be in an unspecified state.
699 * @note This method is available for C++17 and later versions.
700 * @remark For C++ versions prior to C++17, member functions with `std::wstring` and C-strings will be used instead.
701 */
705
706#if __cpp_char8_t >= 201811L
707
708 /**
709 * Parses an IP address from a UTF-8 string view and reports errors through an error code.
710 *
711 * This method parses an IP address from a UTF-8 string view and provides an error code if the parsing fails.
712 *
713 * @param[in] address The UTF-8 string view containing the IP address to parse.
714 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
715 * @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.
716 * @note This method is available for C++20 and later versions where `char8_t` is supported.
717 */
721
722#endif // __cpp_char8_t
723
724 /**
725 * Parses an IP address from a UTF-16 string view and reports errors through an error code.
726 *
727 * This method parses an IP address from a UTF-16 string view and provides an error code if the parsing fails.
728 *
729 * @param[in] address The UTF-16 string view containing the IP address to parse.
730 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
731 * @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.
732 * @note This method is available for C++17 and later versions.
733 * @remark For C++ versions prior to C++17, member functions with `std::u16string` and C-strings will be used instead.
734 */
738
739 /**
740 * Parses an IP address from a UTF-32 string view and reports errors through an error code.
741 *
742 * This method parses an IP address from a UTF-32 string view and provides an error code if the parsing fails.
743 *
744 * @param[in] address The UTF-32 string view containing the IP address to parse.
745 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
746 * @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.
747 * @note This method is available for C++17 and later versions.
748 * @remark For C++ versions prior to C++17, member functions with `std::u32string` and C-strings will be used instead.
749 */
753
754 /**
755 * Sets the scope identifier of the IPv6 address using a string view.
756 *
757 * This function sets the scope identifier using a string view, which allows for a more efficient
758 * way to handle strings without copying them.
759 *
760 * @param[in] scope_id The string view representing the scope identifier.
761 * @throw parse_error Exception caused by invalid input string.
762 * @parblock
763 * @note This method is available for C++17 and later versions.
764 * @endparblock
765 * @parblock
766 * @note According to [RFC 4007](https://datatracker.ietf.org/doc/html/rfc4007.html), the string identifies the specific scope zone of the address.
767 * @endparblock
768 * @parblock
769 * @remark For C++ versions prior to C++17, member functions with `std::string` and C-strings will be used instead.
770 * @endparblock
771 * @parblock
772 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
773 * @endparblock
774 */
780
781 /**
782 * Sets the scope identifier of the IPv6 address using a wide string view.
783 *
784 * This function sets the scope identifier using a wide string view, which allows for a more efficient
785 * way to handle strings without copying them.
786 *
787 * @param[in] scope_id The wide string view representing the scope identifier.
788 * @throw parse_error Exception caused by invalid input string.
789 * @parblock
790 * @note This method is available for C++17 and later versions.
791 * @endparblock
792 * @parblock
793 * @note According to [RFC 4007](https://datatracker.ietf.org/doc/html/rfc4007.html), the string identifies the specific scope zone of the address.
794 * @endparblock
795 * @parblock
796 * @remark For C++ versions prior to C++17, member functions with `std::wstring` and C-strings will be used instead.
797 * @endparblock
798 * @parblock
799 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
800 * @endparblock
801 */
807
808#if __cpp_char8_t >= 201811L
809
810 /**
811 * Sets the scope identifier of the IPv6 address using UTF-8 string view.
812 *
813 * This function sets the scope identifier using UTF-8 string view, which allows for a more efficient
814 * way to handle strings without copying them.
815 *
816 * @param[in] scope_id The UTF-8 string view representing the scope identifier.
817 * @throw parse_error Exception caused by invalid input string.
818 * @parblock
819 * @note This method is available for C++20 and later versions where `char8_t` is supported.
820 * @endparblock
821 * @parblock
822 * @note According to [RFC 4007](https://datatracker.ietf.org/doc/html/rfc4007.html), the string identifies the specific scope zone of the address.
823 * @endparblock
824 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
825 */
831
832#endif // __cpp_char8_t
833
834 /**
835 * Sets the scope identifier of the IPv6 address using UTF-16 string view.
836 *
837 * This function sets the scope identifier using UTF-16 string view, which allows for a more efficient
838 * way to handle strings without copying them.
839 *
840 * @param[in] scope_id The UTF-16 string view representing the scope identifier.
841 * @throw parse_error Exception caused by invalid input string.
842 * @parblock
843 * @note This method is available for C++17 and later versions.
844 * @endparblock
845 * @parblock
846 * @note According to [RFC 4007](https://datatracker.ietf.org/doc/html/rfc4007.html), the string identifies the specific scope zone of the address.
847 * @endparblock
848 * @parblock
849 * @remark For C++ versions prior to C++17, member functions with `std::u16string` and C-strings will be used instead.
850 * @endparblock
851 * @parblock
852 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
853 * @endparblock
854 */
860
861 /**
862 * Sets the scope identifier of the IPv6 address using UTF-32 string view.
863 *
864 * This function sets the scope identifier using UTF-32 string view, which allows for a more efficient
865 * way to handle strings without copying them.
866 *
867 * @param[in] scope_id The UTF-32 string view representing the scope identifier.
868 * @throw parse_error Exception caused by invalid input string.
869 * @parblock
870 * @note This method is available for C++17 and later versions.
871 * @endparblock
872 * @parblock
873 * @note According to [RFC 4007](https://datatracker.ietf.org/doc/html/rfc4007.html), the string identifies the specific scope zone of the address.
874 * @endparblock
875 * @parblock
876 * @remark For C++ versions prior to C++17, member functions with `std::u32string` and C-strings will be used instead.
877 * @endparblock
878 * @parblock
879 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
880 * @endparblock
881 */
887
888 /**
889 * Sets the scope identifier of the IPv6 address using a string view and reports any errors encountered.
890 *
891 * 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.
892 *
893 * @param[in] scope_id The string view representing the scope identifier.
894 * @param[out] code An error_code object that will be set to the error that occurred, if any.
895 * @parblock
896 * @note This method is available for C++17 and later versions.
897 * @endparblock
898 * @parblock
899 * @note According to [RFC 4007](https://datatracker.ietf.org/doc/html/rfc4007.html), the string identifies the specific scope zone of the address.
900 * @endparblock
901 * @parblock
902 * @remark For C++ versions prior to C++17, member functions with `std::string` and C-strings will be used instead.
903 * @endparblock
904 * @parblock
905 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
906 * @endparblock
907 */
913
914 /**
915 * Sets the scope identifier of the IPv6 address using a wide string view and reports any errors encountered.
916 *
917 * 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.
918 *
919 * @param[in] scope_id The wide string view representing the scope identifier.
920 * @param[out] code An error_code object that will be set to the error that occurred, if any.
921 * @parblock
922 * @note This method is available for C++17 and later versions.
923 * @endparblock
924 * @parblock
925 * @note According to [RFC 4007](https://datatracker.ietf.org/doc/html/rfc4007.html), the string identifies the specific scope zone of the address.
926 * @endparblock
927 * @parblock
928 * @remark For C++ versions prior to C++17, member functions with `std::wstring` and C-strings will be used instead.
929 * @endparblock
930 * @parblock
931 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
932 * @endparblock
933 */
939
940#if __cpp_char8_t >= 201811L
941
942 /**
943 * Sets the scope identifier of the IPv6 address using a UTF-8 string view and reports any errors encountered.
944 *
945 * 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.
946 *
947 * @param[in] scope_id The UTF-8 string view representing the scope identifier.
948 * @param[out] code An error_code object that will be set to the error that occurred, if any.
949 * @parblock
950 * @note This method is available for C++20 and later versions.
951 * @endparblock
952 * @parblock
953 * @note According to [RFC 4007](https://datatracker.ietf.org/doc/html/rfc4007.html), the string identifies the specific scope zone of the address.
954 * @endparblock
955 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
956 */
962
963#endif // __cpp_char8_t
964
965 /**
966 * Sets the scope identifier of the IPv6 address using a UTF-16 string view and reports any errors encountered.
967 *
968 * 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.
969 *
970 * @param[in] scope_id The UTF-16 string view representing the scope identifier.
971 * @param[out] code An error_code object that will be set to the error that occurred, if any.
972 * @parblock
973 * @note This method is available for C++17 and later versions.
974 * @endparblock
975 * @parblock
976 * @note According to [RFC 4007](https://datatracker.ietf.org/doc/html/rfc4007.html), the string identifies the specific scope zone of the address.
977 * @endparblock
978 * @parblock
979 * @remark For C++ versions prior to C++17, member functions with `std::u16string` and C-strings will be used instead.
980 * @endparblock
981 * @parblock
982 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
983 * @endparblock
984 */
990
991 /**
992 * Sets the scope identifier of the IPv6 address using a UTF-32 string view and reports any errors encountered.
993 *
994 * 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.
995 *
996 * @param[in] scope_id The UTF-32 string view representing the scope identifier.
997 * @param[out] code An error_code object that will be set to the error that occurred, if any.
998 * @parblock
999 * @note This method is available for C++17 and later versions.
1000 * @endparblock
1001 * @parblock
1002 * @note According to [RFC 4007](https://datatracker.ietf.org/doc/html/rfc4007.html), the string identifies the specific scope zone of the address.
1003 * @endparblock
1004 * @parblock
1005 * @remark For C++ versions prior to C++17, member functions with `std::u32string` and C-strings will be used instead.
1006 * @endparblock
1007 * @parblock
1008 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
1009 * @endparblock
1010 */
1016
1017#else // IPADDRESS_CPP_VERSION < 17
1018
1019 /**
1020 * Parses an IP address from a `std::string`.
1021 *
1022 * @param[in] address The `std::string` containing the IP address to parse.
1023 * @return An instance of ip address parsed from the string.
1024 * @throw parse_error Exception caused by invalid input string.
1025 */
1027 return internal::ip_any_parser<ip_address>::parse(address);
1028 }
1029
1030 /**
1031 * Parses an IP address from a wide `std::wstring`.
1032 *
1033 * @param[in] address The wide `std::wstring` containing the IP address to parse.
1034 * @return An instance of ip address parsed from the string.
1035 * @throw parse_error Exception caused by invalid input string.
1036 */
1038 return internal::ip_any_parser<ip_address>::parse(address);
1039 }
1040
1041 /**
1042 * Parses an IP address from a UTF-16 `std::u16string`.
1043 *
1044 * @param[in] address The UTF-16 `std::u16string` containing the IP address to parse.
1045 * @return An instance of ip address parsed from the string.
1046 * @throw parse_error Exception caused by invalid input string.
1047 */
1049 return internal::ip_any_parser<ip_address>::parse(address);
1050 }
1051
1052 /**
1053 * Parses an IP address from a UTF-32 `std::u32string`.
1054 *
1055 * @param[in] address The UTF-32 `std::u32string` containing the IP address to parse.
1056 * @return An instance of ip address parsed from the string.
1057 * @throw parse_error Exception caused by invalid input string.
1058 */
1060 return internal::ip_any_parser<ip_address>::parse(address);
1061 }
1062
1063 /**
1064 * Parses an IP address from a `std::string` and reports errors through an error code.
1065 *
1066 * @param[in] address The `std::string` containing the IP address to parse.
1067 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
1068 * @return An instance of ip address parsed from the string. If parsing fails, the returned object will be in an unspecified state.
1069 */
1070 static IPADDRESS_FORCE_INLINE ip_address parse(const std::string& address, error_code& code) IPADDRESS_NOEXCEPT {
1071 return internal::ip_any_parser<ip_address>::parse(address, code);
1072 }
1073
1074 /**
1075 * Parses an IP address from a wide `std::wstring` and reports errors through an error code.
1076 *
1077 * @param[in] address The wide `std::wstring` containing the IP address to parse.
1078 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
1079 * @return An instance of ip address parsed from the wide string. If parsing fails, the returned object will be in an unspecified state.
1080 */
1081 static IPADDRESS_FORCE_INLINE ip_address parse(const std::wstring& address, error_code& code) IPADDRESS_NOEXCEPT {
1082 return internal::ip_any_parser<ip_address>::parse(address, code);
1083 }
1084
1085 /**
1086 * Parses an IP address from a UTF-16 `std::u16string` and reports errors through an error code.
1087 *
1088 * @param[in] address The UTF-16 `std::u16string` containing the IP address to parse.
1089 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
1090 * @return An instance of ip address parsed from the UTF-16 string. If parsing fails, the returned object will be in an unspecified state.
1091 */
1092 static IPADDRESS_FORCE_INLINE ip_address parse(const std::u16string& address, error_code& code) IPADDRESS_NOEXCEPT {
1093 return internal::ip_any_parser<ip_address>::parse(address, code);
1094 }
1095
1096 /**
1097 * Parses an IP address from a UTF-32 `std::u32string` and reports errors through an error code.
1098 *
1099 * @param[in] address The UTF-32 `std::u32string` containing the IP address to parse.
1100 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
1101 * @return An instance of ip address parsed from the UTF-32 string. If parsing fails, the returned object will be in an unspecified state.
1102 */
1103 static IPADDRESS_FORCE_INLINE ip_address parse(const std::u32string& address, error_code& code) IPADDRESS_NOEXCEPT {
1104 return internal::ip_any_parser<ip_address>::parse(address, code);
1105 }
1106
1107 /**
1108 * Sets the scope identifier of the IPv6 address using a `std::string`.
1109 *
1110 * @param[in] scope_id The string representing the scope identifier.
1111 * @throw parse_error Exception caused by invalid input string.
1112 */
1113 IPADDRESS_FORCE_INLINE void set_scope_id(const std::string& scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1114 if (_version == ip_version::V6) {
1115 _ipv.ipv6.set_scope_id(scope_id);
1116 }
1117 }
1118
1119 /**
1120 * Sets the scope identifier of the IPv6 address using a `std::wstring`.
1121 *
1122 * @param[in] scope_id The wide string representing the scope identifier.
1123 * @throw parse_error Exception caused by invalid input wide string.
1124 */
1125 IPADDRESS_FORCE_INLINE void set_scope_id(const std::wstring& scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1126 if (_version == ip_version::V6) {
1127 _ipv.ipv6.set_scope_id(scope_id);
1128 }
1129 }
1130
1131 /**
1132 * Sets the scope identifier of the IPv6 address using a `std::u16string`.
1133 *
1134 * @param[in] scope_id The UTF-16 string representing the scope identifier.
1135 * @throw parse_error Exception caused by invalid input UTF-16 string.
1136 */
1137 IPADDRESS_FORCE_INLINE void set_scope_id(const std::u16string& scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1138 if (_version == ip_version::V6) {
1139 _ipv.ipv6.set_scope_id(scope_id);
1140 }
1141 }
1142
1143 /**
1144 * Sets the scope identifier of the IPv6 address using a `std::u32string`.
1145 *
1146 * @param[in] scope_id The UTF-32 string representing the scope identifier.
1147 * @throw parse_error Exception caused by invalid input UTF-32 string.
1148 */
1149 IPADDRESS_FORCE_INLINE void set_scope_id(const std::u32string& scope_id) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1150 if (_version == ip_version::V6) {
1151 _ipv.ipv6.set_scope_id(scope_id);
1152 }
1153 }
1154
1155 /**
1156 * Sets the scope identifier of the IPv6 address using a `std::string` and reports any errors.
1157 *
1158 * @param[in] scope_id The string representing the scope identifier.
1159 * @param[out] code An error_code object that will store the result of the operation.
1160 */
1161 IPADDRESS_FORCE_INLINE void set_scope_id(const std::string& scope_id, error_code& code) IPADDRESS_NOEXCEPT {
1162 if (_version == ip_version::V6) {
1163 _ipv.ipv6.set_scope_id(scope_id, code);
1164 }
1165 }
1166
1167 /**
1168 * Sets the scope identifier of the IPv6 address using a `std::wstring` and reports any errors.
1169 *
1170 * @param[in] scope_id The wide string representing the scope identifier.
1171 * @param[out] code An error_code object that will store the result of the operation.
1172 */
1173 IPADDRESS_FORCE_INLINE void set_scope_id(const std::wstring& scope_id, error_code& code) IPADDRESS_NOEXCEPT {
1174 if (_version == ip_version::V6) {
1175 _ipv.ipv6.set_scope_id(scope_id, code);
1176 }
1177 }
1178
1179 /**
1180 * Sets the scope identifier of the IPv6 address using a `std::u16string` and reports any errors.
1181 *
1182 * @param[in] scope_id The UTF-16 string representing the scope identifier.
1183 * @param[out] code An error_code object that will store the result of the operation.
1184 */
1185 IPADDRESS_FORCE_INLINE void set_scope_id(const std::u16string& scope_id, error_code& code) IPADDRESS_NOEXCEPT {
1186 if (_version == ip_version::V6) {
1187 _ipv.ipv6.set_scope_id(scope_id, code);
1188 }
1189 }
1190
1191 /**
1192 * Sets the scope identifier of the IPv6 address using a `std::u32string` and reports any errors.
1193 *
1194 * @param[in] scope_id The UTF-32 string representing the scope identifier.
1195 * @param[out] code An error_code object that will store the result of the operation.
1196 */
1197 IPADDRESS_FORCE_INLINE void set_scope_id(const std::u32string& scope_id, error_code& code) IPADDRESS_NOEXCEPT {
1198 if (_version == ip_version::V6) {
1199 _ipv.ipv6.set_scope_id(scope_id, code);
1200 }
1201 }
1202
1203#endif // IPADDRESS_CPP_VERSION < 17
1204
1205 /**
1206 * Parses an IP address from a character array.
1207 *
1208 * This method template parses an IP address from a character array of a
1209 * specified size. Can check and get the result at compile time.
1210 *
1211 * @tparam T The character type of the array.
1212 * @tparam N The size of the character array.
1213 * @param[in] address The character array containing the IP address to parse.
1214 * @return An instance of ip address parsed from the character array.
1215 */
1216 template <typename T, size_t N>
1218 return internal::ip_any_parser<ip_address>::parse(address);
1219 }
1220
1221 /**
1222 * Parses an IP address from a character array and reports errors through an error code.
1223 *
1224 * This method template parses an IP address from a character array of a specified size
1225 * and provides an error code if the parsing fails.
1226 *
1227 * @tparam T The character type of the array.
1228 * @tparam N The size of the character array.
1229 * @param[in] address The character array containing the IP address to parse.
1230 * @param[out] code A reference to an `error_code` object that will be set if an error occurs during parsing.
1231 * @return An instance of ip address parsed from the character array. If parsing fails, the returned object will be in an unspecified state.
1232 */
1233 template <typename T, size_t N>
1234 static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_address parse(const T(&address)[N], error_code& code) IPADDRESS_NOEXCEPT {
1235 return internal::ip_any_parser<ip_address>::parse(address, code);
1236 }
1237
1238 /**
1239 * Sets the scope identifier of the IPv6 address.
1240 *
1241 * This function sets the scope identifier using a character array. The length of the array
1242 * should not exceed `IPADDRESS_IPV6_SCOPE_MAX_LENGTH + 1`.
1243 *
1244 * @tparam T The character type of the scope identifier.
1245 * @tparam N The size of the scope identifier array.
1246 * @param[in] scope_id The character array representing the scope identifier.
1247 * @note According to [RFC 4007](https://datatracker.ietf.org/doc/html/rfc4007.html), the string identifies the specific scope zone of the address.
1248 * @remark If scope is disabled in settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`) then this call will have no effect.
1249 */
1250 template <typename T, size_t N>
1251 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE void set_scope_id(const T(&scope_id)[N]) IPADDRESS_NOEXCEPT(noexcept(ipv6_address().set_scope_id(scope_id))) {
1252 if (_version == ip_version::V6) {
1253 _ipv.ipv6.set_scope_id(scope_id);
1254 }
1255 }
1256
1257 /**
1258 * Retrieves the scope identifier of the IPv6 address.
1259 *
1260 * The scope identifier is used to determine the context in which the address is valid.
1261 * It is particularly relevant for link-local and site-local addresses.
1262 *
1263 * @return A `scope` object representing the scope identifier of the IPv6 address.
1264 * @remark If the scope is disabled in the settings (`IPADDRESS_IPV6_SCOPE_MAX_LENGTH == 0`), then an empty scope will be returned.
1265 */
1267 if (_version == ip_version::V4) {
1268 return fixed_string<IPADDRESS_IPV6_SCOPE_MAX_LENGTH>();
1269 }
1270 return _ipv.ipv6.get_scope_id();
1271 }
1272
1273 /**
1274 * Converts the IP address to a uint32_t.
1275 *
1276 * This function casts the IP address to a uint32_t. For IPv4 addresses, it returns the direct numeric representation.
1277 * For IPv6 addresses, it returns the least significant 32 bits of the address.
1278 *
1279 * @return A uint32_t representing the IPv4 address or the least significant 32 bits of the IPv6 address.
1280 * @remark Bytes in integer are presented in **host byte order**.
1281 */
1282 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE explicit operator uint32_t() const IPADDRESS_NOEXCEPT {
1283 return to_uint32();
1284 }
1285
1286 /**
1287 * Converts the IP address to a uint128_t.
1288 *
1289 * This function casts the IP address to a uint128_t. It is used to obtain the full numeric representation of the IP address,
1290 * especially for IPv6 addresses.
1291 *
1292 * @return A uint128_t representing the numeric value of the IP address.
1293 * @remark Bytes in integer are presented in **host byte order**.
1294 */
1296 return to_uint128();
1297 }
1298
1299 /**
1300 * Converts the IP address to a string.
1301 *
1302 * This operator allows the IP address to be converted to a string.
1303 *
1304 * @tparam T The character type of the string.
1305 * @return A `std::string` representation of the IP address.
1306 */
1307 template <typename T>
1308 IPADDRESS_NODISCARD IPADDRESS_FORCE_INLINE explicit operator std::basic_string<T, std::char_traits<T>, std::allocator<T>>() const {
1309 return internal::string_converter<T>::convert(to_string());
1310 }
1311
1312 /**
1313 * Equality comparison operator.
1314 *
1315 * Compares this IP address with another IP address for equality.
1316 *
1317 * @param[in] rhs The right-hand side ip_address object for comparison.
1318 * @return True if both IP addresses are equal, false otherwise.
1319 */
1321 if (_version != rhs._version) {
1322 return false;
1323 }
1324 return _version == ip_version::V4 ? (_ipv.ipv4 == rhs._ipv.ipv4) : (_ipv.ipv6 == rhs._ipv.ipv6);
1325 }
1326
1327 /**
1328 * Inequality comparison operator.
1329 *
1330 * Compares this IP address with another IP address for inequality.
1331 *
1332 * @param[in] rhs The right-hand side ip_address object for comparison.
1333 * @return True if both IP addresses are not equal, false otherwise.
1334 */
1336 return !(*this == rhs);
1337 }
1338
1339#ifdef IPADDRESS_HAS_SPACESHIP_OPERATOR
1340
1341 /**
1342 * Three-way comparison operator (spaceship operator).
1343 *
1344 * Compares this IP address with another IP address to determine the ordering.
1345 *
1346 * @param[in] rhs The right-hand side ip_address object for comparison.
1347 * @return `std::strong_ordering` indicating less than, equivalent to, or greater than.
1348 */
1350 if (const auto result = _version <=> rhs._version; result == std::strong_ordering::equivalent) {
1351 return _version == ip_version::V4 ? (_ipv.ipv4 <=> rhs._ipv.ipv4) : (_ipv.ipv6 <=> rhs._ipv.ipv6);
1352 } else {
1353 return result;
1354 }
1355 }
1356
1357#else // !IPADDRESS_HAS_SPACESHIP_OPERATOR
1358
1359 /**
1360 * Less than comparison operator.
1361 *
1362 * Compares this IP address with another IP address to determine if it is less than the other.
1363 *
1364 * @param[in] rhs The right-hand side ip_address object for comparison.
1365 * @return True if this IP address is less than the other, false otherwise.
1366 */
1368 if (_version < rhs._version) {
1369 return true;
1370 }
1371 if (_version > rhs._version) {
1372 return false;
1373 }
1374 return _version == ip_version::V4 ? (_ipv.ipv4 < rhs._ipv.ipv4) : (_ipv.ipv6 < rhs._ipv.ipv6);
1375 }
1376
1377 /**
1378 * Greater than comparison operator.
1379 *
1380 * Compares this IP address with another IP address to determine if it is greater than the other.
1381 *
1382 * @param[in] rhs The right-hand side ip_address object for comparison.
1383 * @return True if this IP address is greater than the other, false otherwise.
1384 */
1386 return rhs < *this;
1387 }
1388
1389 /**
1390 * Less than or equal to comparison operator.
1391 *
1392 * Compares this IP address with another IP address to determine if it is less than or equal to the other.
1393 *
1394 * @param[in] rhs The right-hand side ip_address object for comparison.
1395 * @return True if this IP address is less than or equal to the other, false otherwise.
1396 */
1398 return !(rhs < *this);
1399 }
1400
1401 /**
1402 * Greater than or equal to comparison operator.
1403 *
1404 * Compares this IP address with another IP address to determine if it is greater than or equal to the other.
1405 *
1406 * @param[in] rhs The right-hand side ip_address object for comparison.
1407 * @return True if this IP address is greater than or equal to the other, false otherwise.
1408 */
1410 return !(*this < rhs);
1411 }
1412
1413#endif // !IPADDRESS_HAS_SPACESHIP_OPERATOR
1414
1415private:
1416 union ip_any_address {
1417 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_any_address() IPADDRESS_NOEXCEPT : ipv4() {
1418 }
1419
1420 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_any_address(const ipv4_address& ip) IPADDRESS_NOEXCEPT : ipv4(ip) {
1421 }
1422
1423 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_any_address(const ipv6_address& ip) IPADDRESS_NOEXCEPT : ipv6(ip) {
1424 }
1425
1426 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE explicit ip_any_address(const base_type_ipv4& bytes) IPADDRESS_NOEXCEPT : ipv4(bytes) {
1427 }
1428
1429 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE explicit ip_any_address(const base_type_ipv6& bytes) IPADDRESS_NOEXCEPT : ipv6(bytes) {
1430 }
1431
1432 ipv4_address ipv4;
1433 ipv6_address ipv6;
1434 } _ipv {};
1435 ip_version _version = ip_version::V4;
1436};
1437
1438#ifdef IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
1439
1440 /**
1441 * User-defined literal for creating an ip_address from a fixed string at compile time.
1442 *
1443 * @tparam FixedString A compile-time fixed string representing the IPv6 address.
1444 * @return An ip_address object parsed from the fixed string.
1445 */
1446 IPADDRESS_EXPORT template <fixed_string FixedString>
1447 IPADDRESS_NODISCARD IPADDRESS_CONSTEVAL IPADDRESS_FORCE_INLINE ip_address operator""_ip() IPADDRESS_NOEXCEPT {
1448 return ip_address::parse<FixedString>();
1449 }
1450
1451#else // IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
1452
1453 /**
1454 * User-defined literal for creating an ip_address from a string literal.
1455 *
1456 * @param[in] address A pointer to a character array representing the IPv6 address.
1457 * @param[in] size The size of the character array.
1458 * @return An ip_address object parsed from the string literal.
1459 */
1461 if (size > ipv6_address::base_max_string_len) {
1462 raise_error(error_code::string_is_too_long, 0, address, size);
1463 }
1464 char str[ipv6_address::base_max_string_len + 1] = {};
1465 for (size_t i = 0; i < size && i < ipv6_address::base_max_string_len; ++i) {
1466 str[i] = address[i];
1467 }
1468 return ip_address::parse(str);
1469 }
1470
1471 /**
1472 * User-defined literal for creating an ip_address from a wide string literal.
1473 *
1474 * @param[in] address A pointer to a character array representing the IPv6 address.
1475 * @param[in] size The size of the character array.
1476 * @return An ip_address object parsed from the string literal.
1477 */
1478 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 {
1479 if (size > ipv6_address::base_max_string_len) {
1480 raise_error(error_code::string_is_too_long, 0, address, size);
1481 }
1482 wchar_t str[ipv6_address::base_max_string_len + 1] = {};
1483 for (size_t i = 0; i < size && i < ipv6_address::base_max_string_len; ++i) {
1484 str[i] = address[i];
1485 }
1486 return ip_address::parse(str);
1487 }
1488
1489 /**
1490 * User-defined literal for creating an ip_address from a UTF-16 string literal.
1491 *
1492 * @param[in] address A pointer to a character array representing the IPv6 address.
1493 * @param[in] size The size of the character array.
1494 * @return An ip_address object parsed from the string literal.
1495 */
1496 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 {
1497 if (size > ipv6_address::base_max_string_len) {
1498 raise_error(error_code::string_is_too_long, 0, address, size);
1499 }
1500 char16_t str[ipv6_address::base_max_string_len + 1] = {};
1501 for (size_t i = 0; i < size && i < ipv6_address::base_max_string_len; ++i) {
1502 str[i] = address[i];
1503 }
1504 return ip_address::parse(str);
1505 }
1506
1507 /**
1508 * User-defined literal for creating an ip_address from a UTF-32 string literal.
1509 *
1510 * @param[in] address A pointer to a character array representing the IPv6 address.
1511 * @param[in] size The size of the character array.
1512 * @return An ip_address object parsed from the string literal.
1513 */
1514 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 {
1515 if (size > ipv6_address::base_max_string_len) {
1516 raise_error(error_code::string_is_too_long, 0, address, size);
1517 }
1518 char32_t str[ipv6_address::base_max_string_len + 1] = {};
1519 for (size_t i = 0; i < size && i < ipv6_address::base_max_string_len; ++i) {
1520 str[i] = address[i];
1521 }
1522 return ip_address::parse(str);
1523 }
1524
1525#endif // IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
1526
1527} // namespace IPADDRESS_NAMESPACE
1528
1529#ifndef IPADDRESS_NO_OVERLOAD_STD
1530
1531namespace std {
1532
1533IPADDRESS_EXPORT template <>
1534struct hash<IPADDRESS_NAMESPACE::ip_address> {
1535 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE size_t operator()(const IPADDRESS_NAMESPACE::ip_address& ip) const IPADDRESS_NOEXCEPT {
1536 return ip.hash();
1537 }
1538};
1539
1541 ip1.swap(ip2);
1542}
1543
1545 return ip.to_string();
1546}
1547
1549 return ip.to_wstring();
1550}
1551
1552IPADDRESS_EXPORT template <typename T>
1553IPADDRESS_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) {
1554 auto& iword = stream.iword(IPADDRESS_NAMESPACE::stream_index());
1555 auto fmt = iword
1556 ? (IPADDRESS_NAMESPACE::format) (iword - 1)
1558 iword = 0;
1559 auto str = ip.to_string(fmt);
1560 if (stream.flags() & ios_base::uppercase) {
1561 auto end = std::find(str.cbegin(), str.cend(), '%');
1562 std::transform(str.cbegin(), end, str.begin(), [](char c){
1563 return std::toupper(c);
1564 });
1565 }
1566 return stream << IPADDRESS_NAMESPACE::internal::string_converter<T>::convert(str);
1567}
1568
1569IPADDRESS_EXPORT template <typename T>
1570IPADDRESS_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) {
1571 std::basic_string<T, std::char_traits<T>, std::allocator<T>> str;
1572 stream >> str;
1574 ip = IPADDRESS_NAMESPACE::ip_address::parse(str, err);
1576 stream.setstate(std::ios_base::failbit);
1577 }
1578 return stream;
1579}
1580
1581} // namespace std
1582
1583#endif // IPADDRESS_NO_OVERLOAD_STD
1584
1585#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:1409
constexpr inline bool is_v4() const noexcept
Checks if the IP address is an IPv4 address.
Definition ip-any-address.hpp:189
constexpr inline bool operator<(const ip_address &rhs) const noexcept
Less than comparison operator.
Definition ip-any-address.hpp:1367
inline std::u16string to_u16string(format fmt=format::compressed) const
Converts the IP address to a string.
Definition ip-any-address.hpp:494
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:318
constexpr inline bool is_site_local() const noexcept
Checks if the IPv6 address is a site-local address.
Definition ip-any-address.hpp:180
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:421
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:376
constexpr inline bool operator==(const ip_address &rhs) const noexcept
Equality comparison operator.
Definition ip-any-address.hpp:1320
inline std::string reverse_pointer() const
Generates a reverse DNS lookup pointer for the IP address.
Definition ip-any-address.hpp:544
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:1385
static constexpr inline ip_address parse(const T(&address)[N])
Parses an IP address from a character array.
Definition ip-any-address.hpp:1217
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:1251
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:1282
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:432
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:410
constexpr inline scope get_scope_id() const noexcept
Retrieves the scope identifier of the IPv6 address.
Definition ip-any-address.hpp:1266
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:555
constexpr inline uint32_t to_uint32() const noexcept
Converts the IP address to a uint32_t.
Definition ip-any-address.hpp:445
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:1308
constexpr inline ip_address(const base_type_ipv4 &bytes) noexcept
Constructor from byte array for IPv4.
Definition ip-any-address.hpp:357
constexpr inline uint128_t to_uint128() const noexcept
Converts the IP address to a uint128_t.
Definition ip-any-address.hpp:458
constexpr inline ip_address(const ipv4_address &ipv4) noexcept
Constructor from an ipv4_address.
Definition ip-any-address.hpp:337
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:289
constexpr inline ipv6_address ipv6_mapped() const noexcept
Obtains the IPv6-mapped representation of the current IP address.
Definition ip-any-address.hpp:249
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:1295
constexpr inline ip_address() noexcept
Default constructor.
Definition ip-any-address.hpp:327
constexpr inline optional< ipv6_address > v6() const noexcept
Retrieves the IPv6 address.
Definition ip-any-address.hpp:303
constexpr inline bool operator<=(const ip_address &rhs) const noexcept
Less than or equal to comparison operator.
Definition ip-any-address.hpp:1397
constexpr inline size_t hash() const noexcept
Computes a hash value for the IP address.
Definition ip-any-address.hpp:221
constexpr inline ip_address(const ipv6_address &ipv6) noexcept
Constructor from an ipv6_address.
Definition ip-any-address.hpp:347
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:278
constexpr inline optional< ipv4_address > ipv4_mapped() const noexcept
Determines if the IPv6 address is an IPv4-mapped address.
Definition ip-any-address.hpp:233
constexpr inline bool operator!=(const ip_address &rhs) const noexcept
Inequality comparison operator.
Definition ip-any-address.hpp:1335
inline std::wstring to_wstring(format fmt=format::compressed) const
Converts the IP address to a string.
Definition ip-any-address.hpp:482
constexpr inline optional< ipv4_address > sixtofour() const noexcept
Determines if the IPv6 address is a 6to4 address.
Definition ip-any-address.hpp:262
constexpr inline size_t size() const noexcept
Retrieves the size of the IP address.
Definition ip-any-address.hpp:209
inline std::u32string to_u32string(format fmt=format::compressed) const
Converts the IP address to a string.
Definition ip-any-address.hpp:506
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:1234
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:470
constexpr inline bool is_v6() const noexcept
Checks if the IP address is an IPv6 address.
Definition ip-any-address.hpp:198
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:403
#define IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS
Definition config.hpp:96
#define IPADDRESS_EXPORT
Definition config.hpp:45
#define IPADDRESS_NODISCARD
Definition config.hpp:101
#define IPADDRESS_FORCE_INLINE
Definition config.hpp:115
#define IPADDRESS_NAMESPACE
Definition config.hpp:41
#define IPADDRESS_NOEXCEPT
Definition config.hpp:92
#define IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS
Definition config.hpp:105
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.