ipaddress 1.1.0
Loading...
Searching...
No Matches
ip-any-network.hpp
Go to the documentation of this file.
1/**
2 * @file ip-any-network.hpp
3 * @brief Defines the ip_network class for representing both IPv4 and IPv6 networks
4 * @author Vladimir Shaleev
5 * @copyright MIT License
6 *
7 * This file includes the definition of the ip_network class, which is a versatile
8 * representation of an IP network that can handle both IPv4 and IPv6 addresses.
9 * It provides methods to retrieve network properties such as the network and broadcast
10 * addresses, netmask, and hostmask, as well as to check for various types of networks
11 * like multicast, private, global, reserved, loopback, link-local, unspecified,
12 * site-local and etc.
13 *
14 * It integrates the ipv4_network and
15 * ipv6_network classes through a union, ensuring optimal space usage while maintaining
16 * the ability to represent both IP networks versions. This file is part of a larger library
17 * that aims to provide comprehensive support for network operations.
18 */
19
20#ifndef IPADDRESS_IP_ANY_NETWORK_HPP
21#define IPADDRESS_IP_ANY_NETWORK_HPP
22
23#include "ipv4-network.hpp"
24#include "ipv6-network.hpp"
27
28namespace IPADDRESS_NAMESPACE {
29
30namespace internal {
31
32template <typename T>
33struct net_any_parser {
34 template <typename Str>
35 IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE T parse(const Str& address, bool strict) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
36 auto code = error_code::no_error;
37 const auto net4 = ipv4_network::parse(address, code, strict);
38 if (code == error_code::no_error) {
39 return T(net4);
40 }
41 return T(ipv6_network::parse(address, strict));
42 }
43
44 template <typename Str>
45 static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE T parse(const Str& address, error_code& code, bool strict) IPADDRESS_NOEXCEPT {
47 const auto net4 = ipv4_network::parse(address, code, strict);
48 if (code == error_code::no_error) {
49 return T(net4);
50 }
51 const auto net6 = ipv6_network::parse(address, code, strict);
52 if (code == error_code::no_error) {
53 return T(net6);
54 }
55 return T();
56 }
57};
58
59} // namespace IPADDRESS_NAMESPACE::internal
60
61/**
62 * A class that encapsulates both IPv4 and IPv6 network functionalities.
63 *
64 * The ip_network class serves as a versatile tool for network address manipulation,
65 * capable of handling both IPv4 and IPv6 networks. It abstracts the complexities associated
66 * with the different IP versions and provides a consistent API for network operations.
67 * This class is essential for applications that require flexibility in dealing with
68 * various IP network types without concern for the underlying IP version.
69 */
71public:
72 using ip_address_type = ip_address; /**< Type alias for ip_address, representing the IP address within the network. */
73 using uint_type = uint128_t; /**< Type alias for a 128-bit unsigned integer type. */
74
75 /**
76 * Retrieves the IP version of the network.
77 *
78 * @return The IP version as an enumeration (either V4 or V6).
79 */
81 return _version;
82 }
83
84 /**
85 * Retrieves the prefix length of this network.
86 *
87 * This method returns the prefix length of the network. The prefix length is the number
88 * of bits in the network address portion of the IP address and is used to calculate the netmask.
89 *
90 * @return The prefix length of the network as a size_t value.
91 */
93 return is_v4() ? _ipv_net.ipv4.prefixlen() : _ipv_net.ipv6.prefixlen();
94 }
95
96 /**
97 * Retrieves the network address of this network.
98 *
99 * This method returns the network address component of the ip network object.
100 *
101 * @return A reference to the network address.
102 */
104 return is_v4() ? ip_address(_ipv_net.ipv4.network_address()) : ip_address(_ipv_net.ipv6.network_address());
105 }
106
107 /**
108 * Retrieves the broadcast address of this network.
109 *
110 * The broadcast address is the last address in the network and is used to communicate
111 * with all hosts on this network.
112 *
113 * @return The broadcast address of the network as an ip_address object.
114 */
116 return is_v4() ? ip_address(_ipv_net.ipv4.broadcast_address()) : ip_address(_ipv_net.ipv6.broadcast_address());
117 }
118
119 /**
120 * Retrieves the netmask of this network.
121 *
122 * This method returns the netmask of the network. The netmask is used to determine
123 * which portion of an IP address is the network portion and which is the host portion.
124 *
125 * @return A reference to the netmask as an ip_address object.
126 */
128 return is_v4() ? ip_address(_ipv_net.ipv4.netmask()) : ip_address(_ipv_net.ipv6.netmask());
129 }
130
131 /**
132 * Retrieves the hostmask of this network.
133 *
134 * The hostmask identifies the portion of the IP address that is allocated for host identifiers.
135 *
136 * @return The hostmask of the network as an ip_address object.
137 */
139 return is_v4() ? ip_address(_ipv_net.ipv4.hostmask()) : ip_address(_ipv_net.ipv6.hostmask());
140 }
141
142 /**
143 * Checks if the network is a multicast network.
144 *
145 * This method determines whether the network is a multicast network by checking if both the network
146 * address and the broadcast address are multicast addresses.
147 *
148 * @return `true` if the network is multicast, `false` otherwise.
149 * @see [RFC 3171](https://datatracker.ietf.org/doc/html/rfc3171.html) for IPv4.
150 * @see [RFC 2373](https://datatracker.ietf.org/doc/html/rfc2373.html) for IPv6.
151 */
153 return is_v4() ? _ipv_net.ipv4.is_multicast() : _ipv_net.ipv6.is_multicast();
154 }
155
156 /**
157 * Checks if the network is a private network.
158 *
159 * This method determines whether the network is a private network. Private networks are not routed
160 * on the global internet.
161 *
162 * @return `true` if the network is private, `false` otherwise.
163 * @see [iana-ipv4-special-registry](https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml).
164 * @see [iana-ipv6-special-registry](https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml).
165 */
167 return is_v4() ? _ipv_net.ipv4.is_private() : _ipv_net.ipv6.is_private();
168 }
169
170 /**
171 * Checks if the network is a global network.
172 *
173 * This method determines whether the network is a global network. Global networks are routable on the
174 * internet and are not private.
175 *
176 * @return `true` if the network is global, `false` otherwise.
177 * @see [iana-ipv4-special-registry](https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml).
178 * @see [iana-ipv6-special-registry](https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml).
179 */
181 return is_v4() ? _ipv_net.ipv4.is_global() : _ipv_net.ipv6.is_global();
182 }
183
184 /**
185 * Checks if the network is a reserved network.
186 *
187 * This method determines whether the network is reserved by checking if both the network address and
188 * the broadcast address are reserved addresses.
189 *
190 * @return `true` if the network is reserved, `false` otherwise.
191 */
193 return is_v4() ? _ipv_net.ipv4.is_reserved() : _ipv_net.ipv6.is_reserved();
194 }
195
196 /**
197 * Checks if the network is a loopback network.
198 *
199 * This method determines whether the network is a loopback network by checking if both the network
200 * address and the broadcast address are loopback addresses.
201 *
202 * @return `true` if the network is loopback, `false` otherwise.
203 * @see [RFC 3330](https://datatracker.ietf.org/doc/html/rfc3330.html) for IPv4.
204 * @see [RFC 2373](https://datatracker.ietf.org/doc/html/rfc2373.html) for IPv6.
205 */
207 return is_v4() ? _ipv_net.ipv4.is_loopback() : _ipv_net.ipv6.is_loopback();
208 }
209
210 /**
211 * Checks if the network is a link-local network.
212 *
213 * This method determines whether the network is a link-local network by checking if both the network
214 * address and the broadcast address are link-local addresses.
215 *
216 * @return `true` if the network is link-local, `false` otherwise.
217 * @see [RFC 3927](https://datatracker.ietf.org/doc/html/rfc3927.html).
218 */
220 return is_v4() ? _ipv_net.ipv4.is_link_local() : _ipv_net.ipv6.is_link_local();
221 }
222
223 /**
224 * Checks if the network is an unspecified network.
225 *
226 * This method determines whether the network is unspecified by checking if both the network address and
227 * the broadcast address are unspecified addresses.
228 *
229 * @return `true` if the network is unspecified, `false` otherwise.
230 * @see [RFC 5735](https://datatracker.ietf.org/doc/html/rfc5735.html) for IPv4.
231 * @see [RFC 2373](https://datatracker.ietf.org/doc/html/rfc2373.html) for IPv6.
232 */
234 return is_v4() ? _ipv_net.ipv4.is_unspecified() : _ipv_net.ipv6.is_unspecified();
235 }
236
237 /**
238 * Checks if the IPv6 network is site-local.
239 *
240 * This method determines if both the network address and the broadcast address
241 * of the IPv6 network are site-local, which are addresses used within a particular
242 * organization's intranet and are not routable on the global internet.
243 *
244 * @return A boolean value indicating whether the network is site-local.
245 */
247 return is_v4() ? false : _ipv_net.ipv6.is_site_local();
248 }
249
250 /**
251 * Checks if the IP network is an IPv4 network.
252 *
253 * @return `true` if the IP network is an IPv4 network, `false` otherwise.
254 */
256 return _version == ip_version::V4;
257 }
258
259 /**
260 * Checks if the IP network is an IPv6 network.
261 *
262 * @return `true` if the IP network is an IPv6 network, `false` otherwise.
263 */
265 return _version == ip_version::V6;
266 }
267
268 /**
269 * Retrieves the size of the IP address.
270 *
271 * Depending on the IP version, this function returns the size of the IPv4 or IPv6 address.
272 *
273 * @return The size of the IP address in bytes.
274 * @remark This is the number of bytes of the IP address that represents the current network.
275 */
277 return is_v4() ? _ipv_net.ipv4.size() : _ipv_net.ipv6.size();
278 }
279
280 /**
281 * Computes a hash value for the IP address.
282 *
283 * This function generates a hash value that can be used to uniquely identify the IP address.
284 * It can be useful when IP addresses are used as keys in hash tables.
285 *
286 * @return A `size_t` hash value of the IP address.
287 */
289 return is_v4() ? _ipv_net.ipv4.hash() : _ipv_net.ipv6.hash();
290 }
291
292 /**
293 * Calculates the total number of addresses in the network.
294 *
295 * @return The total number of addresses in the network as a `uint128_t` value.
296 */
298 return is_v4() ? uint128_t(_ipv_net.ipv4.addresses_count()) : _ipv_net.ipv6.addresses_count();
299 }
300
301 /**
302 * Checks if the given IP address is contained within this network.
303 *
304 * This method determines whether the provided IP address is part of the network
305 * represented by this ip network object, based on the network address and netmask.
306 *
307 * @code{.cpp}
308 * constexpr auto result1 = ip_network::parse("192.0.2.0/28").contains(ip_address::parse("192.0.2.6"));
309 * constexpr auto result2 = ip_network::parse("192.0.2.0/28").contains(ip_address::parse("192.0.3.6"));
310 *
311 * std::cout << std::boolalpha << result1 << std::endl;
312 * std::cout << std::boolalpha << result2 << std::endl;
313 *
314 * // out:
315 * // true
316 * // false
317 * @endcode
318 * @param[in] address The IP address to check.
319 * @return `true` if the address is part of the network, `false` otherwise.
320 */
321 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE bool contains(const ip_address& address) const IPADDRESS_NOEXCEPT {
322 if (_version == address.version()) {
323 return is_v4() ? _ipv_net.ipv4.contains(address.v4().value()) : _ipv_net.ipv6.contains(address.v6().value());
324 } else {
325 return false;
326 }
327 }
328
329 /**
330 * Determines if this network overlaps with another network.
331 *
332 * This method checks if there is any overlap between the network represented by this
333 * ip network object and another network, meaning if any part of one network lies within the other.
334 *
335 * @code{.cpp}
336 * constexpr auto a = ip_network::parse("1.2.3.0/24");
337 * constexpr auto b = ip_network::parse("1.2.3.0/30");
338 * constexpr auto overlaps = a.overlaps(b);
339 *
340 * std::cout << std::boolalpha << overlaps << std::endl;
341 *
342 * // out:
343 * // true
344 * @endcode
345 * @param[in] other The other ip network object to compare with.
346 * @return `true` if there is an overlap, `false` otherwise.
347 */
349 if (_version == other.version()) {
350 return is_v4() ? _ipv_net.ipv4.overlaps(other.v4().value()) : _ipv_net.ipv6.overlaps(other.v6().value());
351 } else {
352 return false;
353 }
354 }
355
356 /**
357 * Checks if this network is a subnet of another network.
358 *
359 * This method verifies if the network represented by this ip network object is a subnet
360 * of the provided network, meaning if this network is entirely contained within the other network.
361 *
362 * @code{.cpp}
363 * constexpr auto a = ip_network::parse("192.168.1.0/24");
364 * constexpr auto b = ip_network::parse("192.168.1.128/30");
365 * constexpr auto subnet_of = a.subnet_of(b);
366 *
367 * std::cout << std::boolalpha << subnet_of << std::endl;
368 *
369 * // out:
370 * // false
371 * @endcode
372 * @param[in] other The other ip network object to compare with.
373 * @return `true` if this network is a subnet of the other network, `false` otherwise.
374 */
376 if (_version == other.version()) {
377 return is_v4() ? _ipv_net.ipv4.subnet_of(other.v4().value()) : _ipv_net.ipv6.subnet_of(other.v6().value());
378 } else {
379 return false;
380 }
381 }
382
383 /**
384 * Checks if this network is a supernet of another network.
385 *
386 * This method determines if the network represented by this ip network object is a supernet
387 * of the provided network, meaning if the other network is entirely contained within this network.
388 *
389 * @code{.cpp}
390 * constexpr auto a = ip_network::parse("192.168.1.0/24");
391 * constexpr auto b = ip_network::parse("192.168.1.128/30");
392 * constexpr auto supernet_of = a.supernet_of(b);
393 *
394 * std::cout << std::boolalpha << supernet_of << std::endl;
395 *
396 * // out:
397 * // true
398 * @endcode
399 * @param[in] other The other ip network object to compare with.
400 * @return True if this network is a supernet of the other network, false otherwise.
401 */
403 if (_version == other.version()) {
404 return is_v4() ? _ipv_net.ipv4.supernet_of(other.v4().value()) : _ipv_net.ipv6.supernet_of(other.v6().value());
405 } else {
406 return false;
407 }
408 }
409
410 /**
411 * Generates a supernet from this network.
412 *
413 * The supernet containing this network definition, depending on the argument values. \a prefixlen_diff
414 * is the amount our prefix length should be decreased by. new_prefix is the desired new prefix of the
415 * supernet; it must be smaller than our prefix. One and only one of \a prefixlen_diff and new_prefix must
416 * be set.
417 *
418 * @code{.cpp}
419 * constexpr auto supernet = ip_network::parse("192.0.2.0/24").supernet(2);
420 *
421 * std::cout << supernet << std::endl;
422 *
423 * // out:
424 * // 192.0.0.0/22
425 * @endcode
426 * @param[in] prefixlen_diff The amount by which the prefix length should be decreased. *Defaults to 1*.
427 * @param[in] new_prefixlen An optional new prefix length for the supernet. If not specified, the prefix length is determined by subtracting \a prefixlen_diff from the current prefix length.
428 * @return An ip network object representing the supernet, or the current network if an error occurs.
429 * @throw logic_error Raised if the operation cannot be performed due to invalid parameters or prefix length.
430 */
431 IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_network supernet(size_t prefixlen_diff = 1, const optional<size_t>& new_prefixlen = nullptr) const IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
432 return is_v4() ? ip_network(_ipv_net.ipv4.supernet(prefixlen_diff, new_prefixlen)) : ip_network(_ipv_net.ipv6.supernet(prefixlen_diff, new_prefixlen));
433 }
434
435 /**
436 * Generates a supernet from this network with error handling.
437 *
438 * The supernet containing this network definition, depending on the argument values. \a prefixlen_diff
439 * is the amount our prefix length should be decreased by. new_prefix is the desired new prefix of the
440 * supernet; it must be smaller than our prefix. One and only one of \a prefixlen_diff and new_prefix must
441 * be set.
442 *
443 * @code{.cpp}
444 * auto err = error_code::no_error;
445 * auto supernet = ip_network::parse("192.0.2.0/24").supernet(err, 2);
446 *
447 * if (err == error_code::no_error) {
448 * std::cout << supernet << std::endl;
449 * }
450 *
451 * // out:
452 * // 192.0.0.0/22
453 * @endcode
454 * @param[out] code An error_code object that will be set if an error occurs during the operation.
455 * @param[in] prefixlen_diff The amount by which the prefix length should be decreased. *Defaults to 1*.
456 * @param[in] new_prefixlen An optional new prefix length for the supernet. If not specified, the prefix length is determined by subtracting \a prefixlen_diff from the current prefix length.
457 * @return An ip network object representing the supernet, or the current network if an error occurs.
458 */
459 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_network supernet(error_code& code, size_t prefixlen_diff = 1, const optional<size_t>& new_prefixlen = nullptr) const IPADDRESS_NOEXCEPT {
460 return is_v4() ? ip_network(_ipv_net.ipv4.supernet(code, prefixlen_diff, new_prefixlen)) : ip_network(_ipv_net.ipv6.supernet(code, prefixlen_diff, new_prefixlen));
461 }
462
463 /**
464 * Retrieves a sequence of host addresses in the network.
465 *
466 * This method returns a sequence of host addresses within the network, excluding the network and
467 * broadcast addresses.
468 *
469 * @code{.cpp}
470 * constexpr auto hosts_sequence = ip_network::parse("192.0.2.0/29").hosts();
471 *
472 * for (const auto& addr : hosts_sequence) {
473 * std::cout << addr << std::endl;
474 * }
475 *
476 * // out:
477 * // 192.0.2.1
478 * // 192.0.2.2
479 * // 192.0.2.3
480 * // 192.0.2.4
481 * // 192.0.2.5
482 * // 192.0.2.6
483 * @endcode
484 * @return A `hosts_sequence` object representing the sequence of host addresses.
485 * @retval Ipv4 For ipv4 all the IP addresses that belong to the network, except the network
486 * address itself and the network broadcast address. For networks with a mask length of 31,
487 * the network address and network broadcast address are also included in the result.
488 * Networks with a mask of 32 will return a list containing the single host address.
489 * @retval Ipv6 For ipv6 all the IP addresses that belong to the network, except the
490 * Subnet-Router anycast address. For networks with a mask length of 127, the Subnet-Router
491 * anycast address is also included in the result. Networks with a mask of 128 will return a
492 * list containing the single host address.
493 * @warning Please note that with IPv6, the number of addresses can be so large that iterating through
494 * them all may be practically impossible. Therefore, use the hosts() method cautiously to
495 * avoid endlessly retrieving addresses.
496 * @remark `hosts_sequence` uses lazy evaluation to iterate addresses.
497 */
499 if (is_v4()) {
500 const auto sequence = _ipv_net.ipv4.hosts();
501 return hosts_any_sequence(sequence.begin(), sequence.end());
502 } else {
503 const auto sequence = _ipv_net.ipv6.hosts();
504 return hosts_any_sequence(sequence.begin(), sequence.end());
505 }
506 }
507
508 /**
509 * Generates a sequence of subnets from this network.
510 *
511 * The subnets that join to make the current network definition, depending on the argument values.
512 * \a prefixlen_diff is the amount our prefix length should be increased by. new_prefix is the desired
513 * new prefix of the subnets; it must be larger than our prefix. One and only one of \a prefixlen_diff
514 * and new_prefix must be set.
515 *
516 * @code{.cpp}
517 * constexpr auto subnets_sequence = ip_network::parse("192.0.2.0/24").subnets(2);
518 *
519 * for (const auto& net : subnets_sequence) {
520 * std::cout << net << std::endl;
521 * }
522 *
523 * // out:
524 * // 192.0.2.0/26
525 * // 192.0.2.64/26
526 * // 192.0.2.128/26
527 * // 192.0.2.192/26
528 * @endcode
529 * @param[in] prefixlen_diff The difference in prefix length for the subnets. *Defaults to 1*.
530 * @param[in] new_prefixlen An optional new prefix length for the subnets. If not specified, the prefix length is determined by adding \a prefixlen_diff to the current prefix length.
531 * @return A `subnets_any_sequence` object representing the sequence of subnets.
532 * @throw logic_error Raised if the operation cannot be performed due to invalid parameters or prefix length.
533 * @remark `subnets_any_sequence` uses lazy evaluation to iterate over the subnets.
534 */
535 IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE subnets_any_sequence<ip_network> subnets(size_t prefixlen_diff = 1, const optional<size_t>& new_prefixlen = nullptr) const IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
536 if (is_v4()) {
537 const auto sequence = _ipv_net.ipv4.subnets(prefixlen_diff, new_prefixlen);
538 return subnets_any_sequence<ip_network>(sequence.begin(), sequence.end());
539 } else {
540 const auto sequence = _ipv_net.ipv6.subnets(prefixlen_diff, new_prefixlen);
541 return subnets_any_sequence<ip_network>(sequence.begin(), sequence.end());
542 }
543 }
544
545 /**
546 * Generates a sequence of subnets from this network with error handling.
547 *
548 * The subnets that join to make the current network definition, depending on the argument values.
549 * \a prefixlen_diff is the amount our prefix length should be increased by. new_prefix is the desired
550 * new prefix of the subnets; it must be larger than our prefix. One and only one of \a prefixlen_diff
551 * and new_prefix must be set.
552 *
553 * @code{.cpp}
554 * auto err = error_code::no_error;
555 * auto subnets_sequence = ip_network::parse("192.0.2.0/24").subnets(err, 2);
556 *
557 * if (err == error_code::no_error) {
558 * for (const auto& net : subnets_sequence) {
559 * std::cout << net << std::endl;
560 * }
561 * }
562 *
563 * // out:
564 * // 192.0.2.0/26
565 * // 192.0.2.64/26
566 * // 192.0.2.128/26
567 * // 192.0.2.192/26
568 * @endcode
569 * @param[out] code An error_code object that will be set if an error occurs during the operation.
570 * @param[in] prefixlen_diff The difference in prefix length for the subnets. *Defaults to 1*.
571 * @param[in] new_prefixlen An optional new prefix length for the subnets. If not specified, the prefix length is determined by adding \a prefixlen_diff to the current prefix length.
572 * @return A `subnets_any_sequence` object representing the sequence of subnets, or an empty sequence if an error occurs.
573 * @remark `subnets_any_sequence` uses lazy evaluation to iterate over the subnets.
574 */
575 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE subnets_any_sequence<ip_network> subnets(error_code& code, size_t prefixlen_diff = 1, const optional<size_t>& new_prefixlen = nullptr) const IPADDRESS_NOEXCEPT {
576 if (is_v4()) {
577 const auto sequence = _ipv_net.ipv4.subnets(code, prefixlen_diff, new_prefixlen);
578 return subnets_any_sequence<ip_network>(sequence.begin(), sequence.end());
579 } else {
580 const auto sequence = _ipv_net.ipv6.subnets(code, prefixlen_diff, new_prefixlen);
581 return subnets_any_sequence<ip_network>(sequence.begin(), sequence.end());
582 }
583 }
584
585 /**
586 * Computes the network definitions resulting from removing the given network from this one.
587 *
588 * @code{.cpp}
589 * constexpr auto a = ip_network::parse("192.0.2.0/28");
590 * constexpr auto b = ip_network::parse("192.0.2.1/32");
591 * constexpr auto exclude_sequence = a.address_exclude(b);
592 *
593 * for (const auto& net : exclude_sequence) {
594 * std::cout << net << std::endl;
595 * }
596 *
597 * // out:
598 * // 192.0.2.8/29
599 * // 192.0.2.4/30
600 * // 192.0.2.2/31
601 * // 192.0.2.0/32
602 * @endcode
603 * @param[in] other The other network to exclude from this network.
604 * @return An `exclude_network_sequence` object representing the remaining address ranges.
605 * @throw logic_error Raise if network is not completely contained in this network.
606 * @remark `exclude_network_sequence` uses lazy evaluation to iterate networks.
607 */
610 const auto result = address_exclude(other, code);
611 if (code != error_code::no_error) {
612 raise_error(code, 0, "", 0);
613 }
614 return result;
615 }
616
617 /**
618 * Computes the network definitions resulting from removing the given network from this one, with error handling.
619 *
620 * @code{.cpp}
621 * constexpr auto a = ip_network::parse("192.0.2.0/28");
622 * constexpr auto b = ip_network::parse("192.0.2.1/32");
623 *
624 * auto err = error_code::no_error;
625 * auto exclude_sequence = a.address_exclude(b, err);
626 *
627 * if (err == error_code::no_error) {
628 * for (const auto& net : exclude_sequence) {
629 * std::cout << net << std::endl;
630 * }
631 * }
632 *
633 * // out:
634 * // 192.0.2.8/29
635 * // 192.0.2.4/30
636 * // 192.0.2.2/31
637 * // 192.0.2.0/32
638 * @endcode
639 * @param[in] other The other network to exclude from this network.
640 * @param[out] code An error_code object that will be set if an error occurs during the operation.
641 * @return An `exclude_network_sequence` object representing the remaining address ranges, or an empty sequence if an error occurs.
642 * @remark `exclude_network_sequence` uses lazy evaluation to iterate networks.
643 */
646 if (_version != other._version) {
648 return exclude_network_sequence<ip_network>();
649 }
650
651 auto addr1 = network_address(); addr1.set_scope_id("");
652 auto addr2 = other.network_address(); addr2.set_scope_id("");
653 auto lhs = ip_network::from_address(addr1, prefixlen());
654 auto rhs = ip_network::from_address(addr2, other.prefixlen());
655
656 if (!rhs.subnet_of(lhs)) {
658 return exclude_network_sequence<ip_network>();
659 }
660
661 if (lhs == rhs) {
662 return exclude_network_sequence<ip_network>();
663 }
664
665 return exclude_network_sequence<ip_network>(lhs, rhs);
666 }
667
668 /**
669 * Retrieves the IPv4 network.
670 *
671 * If the IP network is an IPv4 network, this function returns the IPv4 network.
672 *
673 * @return An optional containing the IPv4 network, or an empty optional if the IP network is not IPv4.
674 */
675 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE optional<ipv4_network> v4() const IPADDRESS_NOEXCEPT {
676 if (_version == ip_version::V4) {
677 return optional<ipv4_network>(_ipv_net.ipv4);
678 }
679 return optional<ipv4_network>();
680 }
681
682 /**
683 * Retrieves the IPv6 network.
684 *
685 * If the IP network is an IPv6 network, this function returns the IPv6 network.
686 *
687 * @return An optional containing the IPv6 network, or an empty optional if the IP network is not IPv6.
688 */
689 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE optional<ipv6_network> v6() const IPADDRESS_NOEXCEPT {
690 if (_version == ip_version::V6) {
691 return optional<ipv6_network>(_ipv_net.ipv6);
692 }
693 return optional<ipv6_network>();
694 }
695
696 /**
697 * Constructs a new IP network object.
698 *
699 * Initializes a new instance of the ip_network class with the maximum prefix length
700 * for the IPv4 address, effectively setting the network address to the default address
701 * and the netmask to the maximum value.
702 */
703 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_network() IPADDRESS_NOEXCEPT { // NOLINT(modernize-use-equals-default): for C++11 support
704 }
705
706 /**
707 * Constructor from an ipv4_network.
708 *
709 * Constructs an ip_network object with the specified IPv4 network.
710 *
711 * @param[in] net4 An ipv4_network object to initialize the ip_network.
712 */
713 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_network(const ipv4_network& net4) IPADDRESS_NOEXCEPT : _ipv_net(net4) {
714 }
715
716 /**
717 * Constructor from an ipv6_network.
718 *
719 * Constructs an ip_network object with the specified IPv6 network.
720 *
721 * @param[in] net6 An ipv6_network object to initialize the ip_network.
722 */
723 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_network(const ipv6_network& net6) IPADDRESS_NOEXCEPT : _ipv_net(net6), _version(ip_version::V6) {
724 }
725
726 /**
727 * Creates an ip network object from a given IP address and prefix length.
728 *
729 * This static method constructs an ip network object representing the network
730 * that includes the given IP address, with the specified prefix length. If 'strict' is true,
731 * the address is validated against the netmask.
732 *
733 * @param[in] address The IP address to use for creating the network.
734 * @param[in] prefixlen The prefix length for the network's netmask. *Defaults to the maximum prefix length*.
735 * @param[in] strict Whether to validate the address against the netmask.
736 * @return An ip_network object representing the network.
737 * @throw parse_error Exception caused by invalid input string.
738 * @remark May throw an exception if the address does not conform to the netmask when \a strict is `true`.
739 */
741 const ip_address& address,
742 size_t prefixlen,
743 bool strict = true
745 return address.is_v4()
746 ? ip_network(ipv4_network::from_address(address.v4().value(), prefixlen, strict))
747 : ip_network(ipv6_network::from_address(address.v6().value(), prefixlen, strict));
748 }
749
750 /**
751 * Creates an ip network object from a given IP address and prefix length, with error handling.
752 *
753 * Similar to the from_address method above, but this version allows for error handling without exceptions.
754 * It populates the provided error_code object instead of throwing.
755 *
756 * @param[in] address The IP address to use for creating the network.
757 * @param[out] code An error_code object that will be set if an error occurs.
758 * @param[in] prefixlen The prefix length for the network's netmask. Defaults to the maximum prefix length.
759 * @param[in] strict Whether to validate the address against the netmask.
760 * @return An ip_network object representing the network, or an object in an error state if an error occurs.
761 */
763 const ip_address& address,
764 error_code& code,
765 size_t prefixlen,
766 bool strict = true
768 return address.is_v4()
769 ? ip_network(ipv4_network::from_address(address.v4().value(), code, prefixlen, strict))
770 : ip_network(ipv6_network::from_address(address.v6().value(), code, prefixlen, strict));
771 }
772
773 /**
774 * Converts the network to a string representation.
775 *
776 * This method returns a string representation of the network, combining the network address
777 * and the prefix length, formatted according to the specified format.
778 *
779 * @param[in] fmt The format to use for the string representation. *Defaults to format::compressed*.
780 * @return A string representation of the network.
781 */
783 return is_v4() ? _ipv_net.ipv4.to_string(fmt) : _ipv_net.ipv6.to_string(fmt);
784 }
785
786 /**
787 * Converts the network to a string representation.
788 *
789 * This method returns a string representation of the network, combining the network address
790 * and the prefix length, formatted according to the specified format.
791 *
792 * @param[in] fmt The format to use for the string representation. *Defaults to format::compressed*.
793 * @return A string representation of the network.
794 */
796 return is_v4() ? _ipv_net.ipv4.to_wstring(fmt) : _ipv_net.ipv6.to_wstring(fmt);
797 }
798
799 /**
800 * Converts the network to a string representation.
801 *
802 * This method returns a string representation of the network, combining the network address
803 * and the prefix length, formatted according to the specified format.
804 *
805 * @param[in] fmt The format to use for the string representation. *Defaults to format::compressed*.
806 * @return A string representation of the network.
807 */
809 return is_v4() ? _ipv_net.ipv4.to_u16string(fmt) : _ipv_net.ipv6.to_u16string(fmt);
810 }
811
812 /**
813 * Converts the network to a string representation.
814 *
815 * This method returns a string representation of the network, combining the network address
816 * and the prefix length, formatted according to the specified format.
817 *
818 * @param[in] fmt The format to use for the string representation. *Defaults to format::compressed*.
819 * @return A string representation of the network.
820 */
822 return is_v4() ? _ipv_net.ipv4.to_u32string(fmt) : _ipv_net.ipv6.to_u32string(fmt);
823 }
824
825#if __cpp_char8_t >= 201811L
826
827 /**
828 * Converts the network to a string representation.
829 *
830 * This method returns a string representation of the network, combining the network address
831 * and the prefix length, formatted according to the specified format.
832 *
833 * @param[in] fmt The format to use for the string representation. *Defaults to format::compressed*.
834 * @return A string representation of the network.
835 */
838 }
839
840#endif // __cpp_char8_t
841
842 /**
843 * Swaps the contents of this network with another network.
844 *
845 * This method exchanges the network address, netmask, and prefix length with those of another
846 * ip network object.
847 *
848 * @param[in,out] net The other ip_network object to swap contents with.
849 */
851 const auto tmp = *this;
852 *this = net;
853 net = tmp;
854 }
855
856#ifdef IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
857
858 /**
859 * Parses a network address and prefix from a fixed string at compile time.
860 *
861 * This template function allows for the compile-time parsing of an IP network address
862 * and prefix length from a fixed string. It is enabled only when non-type template parameters
863 * are supported by the compiler.
864 *
865 * @tparam FixedString A string literal representing the IP network in "address/prefix" format.
866 * @tparam Strict A boolean flag indicating whether to perform strict validation of the address.
867 * @return A consteval ip network object representing the parsed network.
868 */
869 template <fixed_string FixedString, bool Strict = true>
871 constexpr auto str = FixedString;
872 auto code = error_code::no_error;
873
874 char net[str.size() + 1]{};
875 for (size_t i = 0; i < str.size(); ++i) {
876 net[i] = str[i];
877 }
878
879 const auto net4 = ipv4_network::parse(net, code, Strict);
880 if (code == error_code::no_error) {
881 return ip_network(net4);
882 }
883
885 }
886
887#endif // IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
888
889#if IPADDRESS_CPP_VERSION >= 17
890
891 /**
892 * Parses a network address and prefix from a string view.
893 *
894 * This function parses an IP network address and prefix length from a string view.
895 * It is available when the compiler supports C++17 or later.
896 *
897 * @param[in] address A string view representing the IP network in "address/prefix" format.
898 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
899 * @return An ip network object representing the parsed network.
900 * @throw parse_error Exception caused by invalid input string.
901 * @note This method is available for C++17 and later versions.
902 * @remark For C++ versions prior to C++17, member functions with `std::string` and C-strings will be used instead.
903 */
906 }
907
908 /**
909 * Parses a network address and prefix from a wide string view.
910 *
911 * This function parses an IP network address and prefix length from a wide string view.
912 * It is available when the compiler supports C++17 or later.
913 *
914 * @param[in] address The wide string view representing the IP network in "address/prefix" format.
915 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
916 * @return An ip network object representing the parsed network.
917 * @throw parse_error Exception caused by invalid input string.
918 * @note This method is available for C++17 and later versions.
919 * @remark For C++ versions prior to C++17, member functions with `std::wstring` and C-strings will be used instead.
920 */
923 }
924
925#if __cpp_char8_t >= 201811L
926
927 /**
928 * Parses a network address and prefix from UTF-8 string view.
929 *
930 * This function parses an IP network address and prefix length from UTF-8 string view.
931 * It leverages the `char8_t` type introduced in C++20 to handle UTF-8 strings natively.
932 *
933 * @param[in] address A UTF-8 string view representing the IP network in "address/prefix" format.
934 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
935 * @return An ip network object representing the parsed network.
936 * @throw parse_error Exception caused by invalid input string.
937 * @note This method is available for C++20 and later versions where `char8_t` is supported.
938 */
941 }
942
943#endif // __cpp_char8_t
944
945 /**
946 * Parses a network address and prefix from UTF-16 string view.
947 *
948 * This function parses an IP network address and prefix length from UTF-16 string view.
949 * It is available when the compiler supports C++17 or later.
950 *
951 * @param[in] address The UTF-16 string view representing the IP network in "address/prefix" format.
952 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
953 * @return An ip network object representing the parsed network.
954 * @throw parse_error Exception caused by invalid input string.
955 * @note This method is available for C++17 and later versions.
956 * @remark For C++ versions prior to C++17, member functions with `std::u16string` and C-strings will be used instead.
957 */
960 }
961
962 /**
963 * Parses a network address and prefix from UTF-32 string view.
964 *
965 * This function parses an IP network address and prefix length from UTF-32 string view.
966 * It is available when the compiler supports C++17 or later.
967 *
968 * @param[in] address The UTF-32 string view representing the IP network in "address/prefix" format.
969 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
970 * @return An ip network object representing the parsed network.
971 * @throw parse_error Exception caused by invalid input string.
972 * @note This method is available for C++17 and later versions.
973 * @remark For C++ versions prior to C++17, member functions with `std::u32string` and C-strings will be used instead.
974 */
977 }
978
979 /**
980 * Parses a network address and prefix from a string view with error handling.
981 *
982 * This function parses an IP network address and prefix length from a string view,
983 * providing an error code for exception-free error handling.
984 *
985 * @param[in] address The string view representing the IP network in "address/prefix" format.
986 * @param[out] code An error_code object that will be set if an error occurs during parsing.
987 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
988 * @return An ip network object representing the parsed network.
989 * @note This method is available for C++17 and later versions.
990 * @remark For C++ versions prior to C++17, member functions with `std::string` and C-strings will be used instead.
991 */
994 }
995
996 /**
997 * Parses a network address and prefix from a wide string view with error handling.
998 *
999 * This function parses an IP network address and prefix length from a wide string view,
1000 * providing an error code for exception-free error handling.
1001 *
1002 * @param[in] address The wide string view representing the IP network in "address/prefix" format.
1003 * @param[out] code An error_code object that will be set if an error occurs during parsing.
1004 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
1005 * @return An ip network object representing the parsed network.
1006 * @note This method is available for C++17 and later versions.
1007 * @remark For C++ versions prior to C++17, member functions with `std::wstring` and C-strings will be used instead.
1008 */
1011 }
1012
1013#if __cpp_char8_t >= 201811L
1014
1015 /**
1016 * Parses a network address and prefix from UTF-8 string view with error handling.
1017 *
1018 * This function parses an IP network address and prefix length from UTF-8 string view,
1019 * providing an error code for exception-free error handling.
1020 *
1021 * @param[in] address The UTF-8 string view representing the IP network in "address/prefix" format.
1022 * @param[out] code An error_code object that will be set if an error occurs during parsing.
1023 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
1024 * @return An ip network object representing the parsed network.
1025 * @note This method is available for C++20 and later versions where `char8_t` is supported.
1026 */
1029 }
1030
1031#endif // __cpp_char8_t
1032
1033 /**
1034 * Parses a network address and prefix from UTF-16 string view with error handling.
1035 *
1036 * This function parses an IP network address and prefix length from UTF-16 string view,
1037 * providing an error code for exception-free error handling.
1038 *
1039 * @param[in] address The UTF-16 string view representing the IP network in "address/prefix" format.
1040 * @param[out] code An error_code object that will be set if an error occurs during parsing.
1041 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
1042 * @return An ip network object representing the parsed network.
1043 * @note This method is available for C++17 and later versions.
1044 * @remark For C++ versions prior to C++17, member functions with `std::u16string` and C-strings will be used instead.
1045 */
1048 }
1049
1050 /**
1051 * Parses a network address and prefix from UTF-32 string view with error handling.
1052 *
1053 * This function parses an IP network address and prefix length from UTF-32 string view,
1054 * providing an error code for exception-free error handling.
1055 *
1056 * @param[in] address The UTF-32 string view representing the IP network in "address/prefix" format.
1057 * @param[out] code An error_code object that will be set if an error occurs during parsing.
1058 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
1059 * @return An ip network object representing the parsed network.
1060 * @note This method is available for C++17 and later versions.
1061 * @remark For C++ versions prior to C++17, member functions with `std::u32string` and C-strings will be used instead.
1062 */
1065 }
1066
1067#else // IPADDRESS_CPP_VERSION < 17
1068
1069 /**
1070 * Parses a network address and prefix from a `std::string`.
1071 *
1072 * @param[in] address The `std::string` representing the IP network in "address/prefix" format.
1073 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
1074 * @return An ip network object representing the parsed network.
1075 * @throw parse_error Exception caused by invalid input string.
1076 */
1077 IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS static IPADDRESS_FORCE_INLINE ip_network parse(const std::string& address, bool strict = true) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1078 return internal::net_any_parser<ip_network>::parse(address, strict);
1079 }
1080
1081 /**
1082 * Parses a network address and prefix from a `std::wstring`.
1083 *
1084 * @param[in] address The `std::wstring` representing the IP network in "address/prefix" format.
1085 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
1086 * @return An ip network object representing the parsed network.
1087 * @throw parse_error Exception caused by invalid input string.
1088 */
1089 IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS static IPADDRESS_FORCE_INLINE ip_network parse(const std::wstring& address, bool strict = true) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1090 return internal::net_any_parser<ip_network>::parse(address, strict);
1091 }
1092
1093 /**
1094 * Parses a network address and prefix from a `std::u16string`.
1095 *
1096 * @param[in] address The `std::u16string` representing the IP network in "address/prefix" format.
1097 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
1098 * @return An ip network object representing the parsed network.
1099 * @throw parse_error Exception caused by invalid input string.
1100 */
1101 IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS static IPADDRESS_FORCE_INLINE ip_network parse(const std::u16string& address, bool strict = true) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1102 return internal::net_any_parser<ip_network>::parse(address, strict);
1103 }
1104
1105 /**
1106 * Parses a network address and prefix from a `std::u32string`.
1107 *
1108 * @param[in] address The `std::u32string` representing the IP network in "address/prefix" format.
1109 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
1110 * @return An ip network object representing the parsed network.
1111 * @throw parse_error Exception caused by invalid input string.
1112 */
1113 IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS static IPADDRESS_FORCE_INLINE ip_network parse(const std::u32string& address, bool strict = true) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1114 return internal::net_any_parser<ip_network>::parse(address, strict);
1115 }
1116
1117 /**
1118 * Parses a network address and prefix from a `std::string` and reports errors through an error code.
1119 *
1120 * @param[in] address The `std::string` representing the IP network in "address/prefix" format.
1121 * @param[out] code An error_code object that will be set if an error occurs during parsing.
1122 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
1123 * @return An ip network object representing the parsed network.
1124 */
1125 static IPADDRESS_FORCE_INLINE ip_network parse(const std::string& address, error_code& code, bool strict = true) IPADDRESS_NOEXCEPT {
1126 return internal::net_any_parser<ip_network>::parse(address, code, strict);
1127 }
1128
1129 /**
1130 * Parses a network address and prefix from a `std::wstring` and reports errors through an error code.
1131 *
1132 * @param[in] address The `std::wstring` representing the IP network in "address/prefix" format.
1133 * @param[out] code An error_code object that will be set if an error occurs during parsing.
1134 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
1135 * @return An ip network object representing the parsed network.
1136 */
1137 static IPADDRESS_FORCE_INLINE ip_network parse(const std::wstring& address, error_code& code, bool strict = true) IPADDRESS_NOEXCEPT {
1138 return internal::net_any_parser<ip_network>::parse(address, code, strict);
1139 }
1140
1141 /**
1142 * Parses a network address and prefix from a `std::u16string` and reports errors through an error code.
1143 *
1144 * @param[in] address The `std::u16string` representing the IP network in "address/prefix" format.
1145 * @param[out] code An error_code object that will be set if an error occurs during parsing.
1146 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
1147 * @return An ip network object representing the parsed network.
1148 */
1149 static IPADDRESS_FORCE_INLINE ip_network parse(const std::u16string& address, error_code& code, bool strict = true) IPADDRESS_NOEXCEPT {
1150 return internal::net_any_parser<ip_network>::parse(address, code, strict);
1151 }
1152
1153 /**
1154 * Parses a network address and prefix from a `std::u32string` and reports errors through an error code.
1155 *
1156 * @param[in] address The `std::u32string` representing the IP network in "address/prefix" format.
1157 * @param[out] code An error_code object that will be set if an error occurs during parsing.
1158 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
1159 * @return An ip network object representing the parsed network.
1160 */
1161 static IPADDRESS_FORCE_INLINE ip_network parse(const std::u32string& address, error_code& code, bool strict = true) IPADDRESS_NOEXCEPT {
1162 return internal::net_any_parser<ip_network>::parse(address, code, strict);
1163 }
1164
1165#endif // IPADDRESS_CPP_VERSION < 17
1166
1167 /**
1168 * Parses a network address and prefix from a character array.
1169 *
1170 * This function parses an IP network address and prefix length from a character array of a
1171 * specified size. Can check and get the result at compile time.
1172 *
1173 * @tparam T The character type of the array.
1174 * @tparam N The size of the character array.
1175 * @param[in] address The character array representing the IP network in "address/prefix" format.
1176 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
1177 * @return An ip network object representing the parsed network.
1178 */
1179 template <typename T, size_t N>
1181 return internal::net_any_parser<ip_network>::parse(address, strict);
1182 }
1183
1184 /**
1185 * Parses a network address and prefix from a character array and reports errors through an error code.
1186 *
1187 * This function parses an IP network address and prefix length from a character array of a specified size
1188 * and provides an error code if the parsing fails.
1189 *
1190 * @tparam T The character type of the array.
1191 * @tparam N The size of the character array.
1192 * @param[in] address The character array representing the IP network in "address/prefix" format.
1193 * @param[out] code An error_code object that will be set if an error occurs during parsing.
1194 * @param[in] strict A boolean flag indicating whether to perform strict validation of the address.
1195 * @return An ip network object representing the parsed network.
1196 */
1197 template <typename T, size_t N>
1198 static IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_network parse(const T(&address)[N], error_code& code, bool strict = true) IPADDRESS_NOEXCEPT {
1199 return internal::net_any_parser<ip_network>::parse(address, code, strict);
1200 }
1201
1202 /**
1203 * Converts the ip network object to a std::string.
1204 *
1205 * @tparam T The character type of the string.
1206 * @return A `std::string` representation of the ip network object.
1207 */
1208 template <typename T>
1209 IPADDRESS_NODISCARD IPADDRESS_FORCE_INLINE explicit operator std::basic_string<T, std::char_traits<T>, std::allocator<T>>() const {
1210 return internal::string_converter<T>::convert(to_string());
1211 }
1212
1213 /**
1214 * Equality comparison operator.
1215 *
1216 * Compares this ip network object to another for equality based on the network address and netmask.
1217 *
1218 * @param[in] rhs The other ip network object to compare with.
1219 * @return `true` if both objects are equal, `false` otherwise.
1220 */
1222 if (_version != rhs._version) {
1223 return false;
1224 }
1225 return _version == ip_version::V4 ? (_ipv_net.ipv4 == rhs._ipv_net.ipv4) : (_ipv_net.ipv6 == rhs._ipv_net.ipv6);
1226 }
1227
1228 /**
1229 * Inequality comparison operator.
1230 *
1231 * Compares this ip network object to another for inequality.
1232 *
1233 * @param[in] rhs The other ip network object to compare with.
1234 * @return `true` if both objects are not equal, `false` otherwise.
1235 */
1237 return !(*this == rhs);
1238 }
1239
1240#ifdef IPADDRESS_HAS_SPACESHIP_OPERATOR
1241
1242 /**
1243 * Three-way comparison operator (spaceship operator).
1244 *
1245 * Compares this ip network object to another using three-way comparison.
1246 *
1247 * @param[in] rhs The other ip network object to compare with.
1248 * @return `std::strong_ordering` result of the comparison.
1249 */
1251 if (const auto result = _version <=> rhs._version; result == std::strong_ordering::equivalent) {
1253 } else {
1254 return result;
1255 }
1256 }
1257
1258#else // !IPADDRESS_HAS_SPACESHIP_OPERATOR
1259
1260 /**
1261 * Less than comparison operator.
1262 *
1263 * Determines if this ip network object is less than another by comparing network addresses and netmasks.
1264 *
1265 * @param[in] rhs The other ip network object to compare with.
1266 * @return `true` if this object is less than the other, `false` otherwise.
1267 */
1269 if (_version < rhs._version) {
1270 return true;
1271 }
1272 if (_version > rhs._version) {
1273 return false;
1274 }
1275 return _version == ip_version::V4 ? (_ipv_net.ipv4 < rhs._ipv_net.ipv4) : (_ipv_net.ipv6 < rhs._ipv_net.ipv6);
1276 }
1277
1278 /**
1279 * Greater than comparison operator.
1280 *
1281 * Determines if this ip network object is greater than another.
1282 *
1283 * @param[in] rhs The other ip network object to compare with.
1284 * @return `true` if this object is greater than the other, `false` otherwise.
1285 */
1287 return rhs < *this;
1288 }
1289
1290 /**
1291 * Less than or equal to comparison operator.
1292 *
1293 * Determines if this ip network object is less than or equal to another.
1294 *
1295 * @param[in] rhs The other ip network object to compare with.
1296 * @return `true` if this object is less than or equal to the other, `false` otherwise.
1297 */
1299 return !(rhs < *this);
1300 }
1301
1302 /**
1303 * Greater than or equal to comparison operator.
1304 *
1305 * Determines if this ip network object is greater than or equal to another.
1306 *
1307 * @param[in] rhs The other ip network object to compare with.
1308 * @return `true` if this object is greater than or equal to the other, `false` otherwise.
1309 */
1311 return !(*this < rhs);
1312 }
1313
1314#endif // !IPADDRESS_HAS_SPACESHIP_OPERATOR
1315
1316private:
1317 union ip_any_network {
1318 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_any_network() IPADDRESS_NOEXCEPT : ipv4() {
1319 }
1320
1321 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_any_network(const ipv4_network& net) IPADDRESS_NOEXCEPT : ipv4(net) {
1322 }
1323
1324 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_any_network(const ipv6_network& net) IPADDRESS_NOEXCEPT : ipv6(net) {
1325 }
1326
1327 ipv4_network ipv4;
1328 ipv6_network ipv6;
1329 } _ipv_net {};
1330 ip_version _version = ip_version::V4;
1331};
1332
1333#ifdef IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
1334
1335 /**
1336 * User-defined literal operator for creating an ip_network object from a string literal.
1337 *
1338 * This operator allows the creation of ip_network objects using a string literal with the
1339 * `_net` suffix.
1340 *
1341 * @tparam FixedString A string literal representing the IP network.
1342 * @return An ip_network object representing the network specified by the string literal.
1343 */
1344 IPADDRESS_EXPORT template <fixed_string FixedString>
1345 IPADDRESS_NODISCARD IPADDRESS_CONSTEVAL IPADDRESS_FORCE_INLINE ip_network operator""_net() IPADDRESS_NOEXCEPT {
1346 return ip_network::parse<FixedString>();
1347 }
1348
1349#else // !IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
1350
1351 /**
1352 * User-defined literal operator for creating an ip_network object from a string literal.
1353 *
1354 * This operator allows the creation of ip_network objects using a string literal with the
1355 * `_net` suffix.
1356 *
1357 * @param[in] address The string literal representing the IP network.
1358 * @param[in] size The size of the string literal.
1359 * @return An ip_network object representing the network specified by the string literal.
1360 */
1362 const auto max_len = ipv6_address::base_max_string_len * 2 + 1;
1363 if (size > max_len) {
1364 raise_error(error_code::string_is_too_long, 0, address, size);
1365 }
1366 char str[max_len + 1] = {};
1367 for (size_t i = 0; i < size && i < max_len; ++i) {
1368 str[i] = address[i];
1369 }
1370 return ip_network::parse(str);
1371 }
1372
1373 /**
1374 * User-defined literal operator for creating an ip_network object from a wide string literal.
1375 *
1376 * This operator allows the creation of ip_network objects using a string literal with the
1377 * `_net` suffix.
1378 *
1379 * @param[in] address The string literal representing the IP network.
1380 * @param[in] size The size of the string literal.
1381 * @return An ip_network object representing the network specified by the string literal.
1382 */
1383 IPADDRESS_EXPORT IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_network operator""_net(const wchar_t* address, size_t size) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1384 const auto max_len = ipv6_address::base_max_string_len * 2 + 1;
1385 if (size > max_len) {
1386 raise_error(error_code::string_is_too_long, 0, address, size);
1387 }
1388 wchar_t str[max_len + 1] = {};
1389 for (size_t i = 0; i < size && i < max_len; ++i) {
1390 str[i] = address[i];
1391 }
1392 return ip_network::parse(str);
1393 }
1394
1395 /**
1396 * User-defined literal operator for creating an ip_network object from UTF-16 string literal.
1397 *
1398 * This operator allows the creation of ip_network objects using a string literal with the
1399 * `_net` suffix.
1400 *
1401 * @param[in] address The string literal representing the IP network.
1402 * @param[in] size The size of the string literal.
1403 * @return An ip_network object representing the network specified by the string literal.
1404 */
1405 IPADDRESS_EXPORT IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_network operator""_net(const char16_t* address, size_t size) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1406 const auto max_len = ipv6_address::base_max_string_len * 2 + 1;
1407 if (size > max_len) {
1408 raise_error(error_code::string_is_too_long, 0, address, size);
1409 }
1410 char16_t str[max_len + 1] = {};
1411 for (size_t i = 0; i < size && i < max_len; ++i) {
1412 str[i] = address[i];
1413 }
1414 return ip_network::parse(str);
1415 }
1416
1417 /**
1418 * User-defined literal operator for creating an ip_network object from UTF-32 string literal.
1419 *
1420 * This operator allows the creation of ip_network objects using a string literal with the
1421 * `_net` suffix.
1422 *
1423 * @param[in] address The string literal representing the IP network.
1424 * @param[in] size The size of the string literal.
1425 * @return An ip_network object representing the network specified by the string literal.
1426 */
1427 IPADDRESS_EXPORT IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE ip_network operator""_net(const char32_t* address, size_t size) IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS {
1428 const auto max_len = ipv6_address::base_max_string_len * 2 + 1;
1429 if (size > max_len) {
1430 raise_error(error_code::string_is_too_long, 0, address, size);
1431 }
1432 char32_t str[max_len + 1] = {};
1433 for (size_t i = 0; i < size && i < max_len; ++i) {
1434 str[i] = address[i];
1435 }
1436 return ip_network::parse(str);
1437 }
1438
1439#endif // !IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
1440
1441} // namespace IPADDRESS_NAMESPACE
1442
1443#ifndef IPADDRESS_NO_OVERLOAD_STD
1444
1445namespace std {
1446
1447IPADDRESS_EXPORT template <>
1448struct hash<IPADDRESS_NAMESPACE::ip_network> {
1449 IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE size_t operator()(const IPADDRESS_NAMESPACE::ip_network& network) const IPADDRESS_NOEXCEPT {
1450 return network.hash();
1451 }
1452};
1453
1455 return net1.swap(net2);
1456}
1457
1458IPADDRESS_EXPORT IPADDRESS_FORCE_INLINE std::string to_string(const IPADDRESS_NAMESPACE::ip_network& network) {
1459 return network.to_string();
1460}
1461
1462IPADDRESS_EXPORT IPADDRESS_FORCE_INLINE std::wstring to_wstring(const IPADDRESS_NAMESPACE::ip_network& network) {
1463 return network.to_wstring();
1464}
1465
1466IPADDRESS_EXPORT template <typename T>
1467IPADDRESS_FORCE_INLINE std::basic_ostream<T, std::char_traits<T>>& operator<<(std::basic_ostream<T, std::char_traits<T>>& stream, const IPADDRESS_NAMESPACE::ip_network& network) {
1468 auto& iword = stream.iword(IPADDRESS_NAMESPACE::stream_index());
1469 auto fmt = iword
1470 ? (IPADDRESS_NAMESPACE::format) (iword - 1)
1472 iword = 0;
1473 auto str = network.to_string(fmt);
1474 if (stream.flags() & ios_base::uppercase) {
1475 auto end = std::find(str.cbegin(), str.cend(), '%');
1476 std::transform(str.cbegin(), end, str.begin(), [](char c){
1477 return std::toupper(c);
1478 });
1479 }
1480 return stream << IPADDRESS_NAMESPACE::internal::string_converter<T>::convert(str);
1481}
1482
1483IPADDRESS_EXPORT template <typename T>
1484IPADDRESS_FORCE_INLINE std::basic_istream<T, std::char_traits<T>>& operator>>(std::basic_istream<T, std::char_traits<T>>& stream, IPADDRESS_NAMESPACE::ip_network& network) {
1485 auto& iword = stream.iword(IPADDRESS_NAMESPACE::network_strict_index());
1486 auto strict = iword == 0;
1487 iword = 0;
1488
1489 std::basic_string<T, std::char_traits<T>, std::allocator<T>> str;
1490 stream >> str;
1492 network = IPADDRESS_NAMESPACE::ip_network::parse(str, err, strict);
1494 stream.setstate(std::ios_base::failbit);
1495 }
1496 return stream;
1497}
1498
1499} // namespace std
1500
1501#endif // IPADDRESS_NO_OVERLOAD_STD
1502
1503#endif // IPADDRESS_IP_ANY_NETWORK_HPP
A sequence container for networks excluding specified subnets.
Definition ip-network-iterator.hpp:890
A sequence of host IP addresses.
Definition ip-any-iterator.hpp:479
A class that represents an IP address, supporting both IPv4 and IPv6 formats.
Definition ip-any-address.hpp:73
constexpr inline ip_version version() const noexcept
Retrieves the version of the IP address.
Definition ip-any-address.hpp:86
A class that encapsulates both IPv4 and IPv6 network functionalities.
Definition ip-any-network.hpp:70
constexpr inline void swap(ip_network &net) noexcept
Swaps the contents of this network with another network.
Definition ip-any-network.hpp:850
constexpr inline bool operator>=(const ip_network &rhs) const noexcept
Greater than or equal to comparison operator.
Definition ip-any-network.hpp:1310
constexpr inline bool is_v4() const noexcept
Checks if the IP network is an IPv4 network.
Definition ip-any-network.hpp:255
constexpr inline ip_address hostmask() const noexcept
Retrieves the hostmask of this network.
Definition ip-any-network.hpp:138
inline std::u16string to_u16string(format fmt=format::compressed) const
Converts the network to a string representation.
Definition ip-any-network.hpp:808
constexpr inline bool is_site_local() const noexcept
Checks if the IPv6 network is site-local.
Definition ip-any-network.hpp:246
constexpr inline ip_network(const ipv4_network &net4) noexcept
Constructor from an ipv4_network.
Definition ip-any-network.hpp:713
constexpr inline bool is_multicast() const noexcept
Checks if the network is a multicast network.
Definition ip-any-network.hpp:152
static constexpr inline ip_network from_address(const ip_address &address, error_code &code, size_t prefixlen, bool strict=true) noexcept
Creates an ip network object from a given IP address and prefix length, with error handling.
Definition ip-any-network.hpp:762
constexpr inline bool is_private() const noexcept
Checks if the network is a private network.
Definition ip-any-network.hpp:166
constexpr inline bool operator<=(const ip_network &rhs) const noexcept
Less than or equal to comparison operator.
Definition ip-any-network.hpp:1298
constexpr inline bool subnet_of(const ip_network &other) const noexcept
Checks if this network is a subnet of another network.
Definition ip-any-network.hpp:375
constexpr inline ip_address netmask() const noexcept
Retrieves the netmask of this network.
Definition ip-any-network.hpp:127
constexpr inline bool is_reserved() const noexcept
Checks if the network is a reserved network.
Definition ip-any-network.hpp:192
constexpr inline uint128_t addresses_count() const noexcept
Calculates the total number of addresses in the network.
Definition ip-any-network.hpp:297
constexpr inline bool is_link_local() const noexcept
Checks if the network is a link-local network.
Definition ip-any-network.hpp:219
constexpr inline bool operator==(const ip_network &rhs) const noexcept
Equality comparison operator.
Definition ip-any-network.hpp:1221
constexpr inline bool operator>(const ip_network &rhs) const noexcept
Greater than comparison operator.
Definition ip-any-network.hpp:1286
constexpr inline ip_address network_address() const noexcept
Retrieves the network address of this network.
Definition ip-any-network.hpp:103
inline operator std::basic_string< T, std::char_traits< T >, std::allocator< T > >() const
Converts the ip network object to a std::string.
Definition ip-any-network.hpp:1209
constexpr inline subnets_any_sequence< ip_network > subnets(error_code &code, size_t prefixlen_diff=1, const optional< size_t > &new_prefixlen=nullptr) const noexcept
Generates a sequence of subnets from this network with error handling.
Definition ip-any-network.hpp:575
constexpr inline ip_network() noexcept
Constructs a new IP network object.
Definition ip-any-network.hpp:703
static constexpr inline ip_network from_address(const ip_address &address, size_t prefixlen, bool strict=true)
Creates an ip network object from a given IP address and prefix length.
Definition ip-any-network.hpp:740
constexpr inline ip_version version() const noexcept
Retrieves the IP version of the network.
Definition ip-any-network.hpp:80
constexpr inline ip_network supernet(error_code &code, size_t prefixlen_diff=1, const optional< size_t > &new_prefixlen=nullptr) const noexcept
Generates a supernet from this network with error handling.
Definition ip-any-network.hpp:459
constexpr inline bool is_unspecified() const noexcept
Checks if the network is an unspecified network.
Definition ip-any-network.hpp:233
static constexpr inline ip_network parse(const T(&address)[N], error_code &code, bool strict=true) noexcept
Parses a network address and prefix from a character array and reports errors through an error code.
Definition ip-any-network.hpp:1198
constexpr inline bool contains(const ip_address &address) const noexcept
Checks if the given IP address is contained within this network.
Definition ip-any-network.hpp:321
constexpr inline bool supernet_of(const ip_network &other) const noexcept
Checks if this network is a supernet of another network.
Definition ip-any-network.hpp:402
constexpr inline bool is_global() const noexcept
Checks if the network is a global network.
Definition ip-any-network.hpp:180
static constexpr inline ip_network parse(const T(&address)[N], bool strict=true)
Parses a network address and prefix from a character array.
Definition ip-any-network.hpp:1180
constexpr inline ip_address broadcast_address() const noexcept
Retrieves the broadcast address of this network.
Definition ip-any-network.hpp:115
constexpr inline bool operator!=(const ip_network &rhs) const noexcept
Inequality comparison operator.
Definition ip-any-network.hpp:1236
constexpr inline hosts_any_sequence hosts() const noexcept
Retrieves a sequence of host addresses in the network.
Definition ip-any-network.hpp:498
constexpr inline bool overlaps(const ip_network &other) const noexcept
Determines if this network overlaps with another network.
Definition ip-any-network.hpp:348
constexpr inline size_t hash() const noexcept
Computes a hash value for the IP address.
Definition ip-any-network.hpp:288
constexpr inline bool operator<(const ip_network &rhs) const noexcept
Less than comparison operator.
Definition ip-any-network.hpp:1268
constexpr inline ip_network supernet(size_t prefixlen_diff=1, const optional< size_t > &new_prefixlen=nullptr) const
Generates a supernet from this network.
Definition ip-any-network.hpp:431
constexpr inline optional< ipv6_network > v6() const noexcept
Retrieves the IPv6 network.
Definition ip-any-network.hpp:689
inline std::wstring to_wstring(format fmt=format::compressed) const
Converts the network to a string representation.
Definition ip-any-network.hpp:795
constexpr inline subnets_any_sequence< ip_network > subnets(size_t prefixlen_diff=1, const optional< size_t > &new_prefixlen=nullptr) const
Generates a sequence of subnets from this network.
Definition ip-any-network.hpp:535
constexpr inline exclude_network_sequence< ip_network > address_exclude(const ip_network &other, error_code &code) const noexcept
Computes the network definitions resulting from removing the given network from this one,...
Definition ip-any-network.hpp:644
constexpr inline size_t prefixlen() const noexcept
Retrieves the prefix length of this network.
Definition ip-any-network.hpp:92
constexpr inline size_t size() const noexcept
Retrieves the size of the IP address.
Definition ip-any-network.hpp:276
inline std::u32string to_u32string(format fmt=format::compressed) const
Converts the network to a string representation.
Definition ip-any-network.hpp:821
constexpr inline exclude_network_sequence< ip_network > address_exclude(const ip_network &other) const
Computes the network definitions resulting from removing the given network from this one.
Definition ip-any-network.hpp:608
constexpr inline optional< ipv4_network > v4() const noexcept
Retrieves the IPv4 network.
Definition ip-any-network.hpp:675
constexpr inline bool is_loopback() const noexcept
Checks if the network is a loopback network.
Definition ip-any-network.hpp:206
inline std::string to_string(format fmt=format::compressed) const
Converts the network to a string representation.
Definition ip-any-network.hpp:782
constexpr inline bool is_v6() const noexcept
Checks if the IP network is an IPv6 network.
Definition ip-any-network.hpp:264
constexpr inline ip_network(const ipv6_network &net6) noexcept
Constructor from an ipv6_network.
Definition ip-any-network.hpp:723
A template class to manage an optional contained value.
Definition optional.hpp:35
A sequence container for subnet ranges within a network.
Definition ip-any-iterator.hpp:658
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
@ invalid_version
The IP address version does not match the expected version.
@ not_contained_network
The network is not a subnet of the other network as expected.
@ no_error
Indicates the absence of any errors.