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