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