2
3
4
5
6
7
8
9
10
12#ifndef IPADDRESS_BASE_V4_HPP
13#define IPADDRESS_BASE_V4_HPP
21
22
23
24
25
26
27
28
33 using uint_type = uint32_t;
36 static constexpr size_t base_size = 4;
37 static constexpr size_t base_max_string_len = 15;
38 static constexpr size_t base_max_prefixlen =
base_size * 8;
39 static constexpr uint_type base_all_ones = (uint_type) (-1);
42
43
44
45
51
52
53
54
60 template <
typename Iter>
67 base_type octets = {};
68 char first_symbol =
'\0';
75 uint32_t error_symbol = 0;
78 auto c = internal::next_char_or_error(it, end, code, error_symbol);
87 if (c >=
'0' && c <=
'9') {
88 if (digits > 0 && first_symbol ==
'0') {
91 }
else if (digits == 0) {
95 octet = octet * 10 + d;
101 }
else if (c ==
'.' && digits > 0) {
106 octets[index++] = uint8_t(octet & 0xFF);
109 }
else if (c ==
'.') {
129 octets[index] = uint8_t(octet & 0xFF);
130 return ip_address_base<Ext>(octets);
137 uint8_t((ip >> 8) & 0xFF),
138 uint8_t((ip >> 16) & 0xFF),
139 uint8_t((ip >> 24) & 0xFF) });
143 return prefixlen != 0
144 ? ip_address_base<Ext>::ip_from_uint32(base_all_ones ^ (base_all_ones >> (prefixlen - 1) >> 1))
145 : ip_address_base<Ext>::ip_from_uint32(0);
150 (uint32_t(bytes[3]) << 24) |
151 (uint32_t(bytes[2]) << 16) |
152 (uint32_t(bytes[1]) << 8) |
153 (uint32_t(bytes[0]));
154 return is_little_endian() ? swap_bytes(ip) : ip;
160 for (size_t b = 0; b < 4; ++b) {
161 const size_t length = byte_to_string(bytes[b], buffer);
162 for (size_t i = 0; i < length; ++i) {
163 result[offset++] = buffer[i];
166 result[offset++] =
'.';
169 result[offset] =
'\0';
174 return ip_from_uint32(swap_bytes(ip_to_uint32(bytes))).to_string() +
".in-addr.arpa";
177 template <
typename Iter>
183 size_t prefixlen = 0;
184 auto is_value =
true;
185 auto has_prefixlen =
false;
188 has_prefixlen =
true;
189 const auto c = internal::next_char_or_error(it, end, code, code_value);
193 if (c >=
'0' && c <=
'9') {
194 prefixlen = prefixlen * 10 + (c -
'0');
201 if (prefixlen > base_max_prefixlen) {
206 auto ip = ip_to_uint32(ip_from_string(begin, end, code, code_value).bytes());
212 prefixlen = prefix_from_ip_uint32(ip, code);
214 ip = ip ^ base_all_ones;
216 prefixlen = prefix_from_ip_uint32(ip, code);
222 prefixlen = has_prefixlen ? prefixlen : base_max_prefixlen;
223 auto netmask = ip_from_prefix(prefixlen);
224 return std::make_tuple(netmask, prefixlen);
228 auto pack_address = address.to_uint();
229 auto pack_netmask = netmask.to_uint();
230 if ((pack_address & pack_netmask) != pack_address) {
235 return ip_from_uint32(pack_address & pack_netmask);
243 auto trailing_zeroes = count_righthand_zero_bits(ip, base_max_prefixlen);
244 auto prefixlen = base_max_prefixlen - trailing_zeroes;
245 auto leading_ones = trailing_zeroes != 32 ? (ip >> trailing_zeroes) : 0;
246 auto all_ones = (uint_type(1) << (prefixlen - 1) << 1) - uint_type(1);
247 if (leading_ones != all_ones) {
258 number = (~number & (number - 1));
260 while (number != 0) {
261 count += number & 0x1;
276 *p++ =
char((byte % 10) +
'0');
283 for (size_t i = 0, midle = length / 2; i < midle; ++i) {
293template <
typename Ext>
296template <
typename Ext>
297constexpr size_t
base_v4<Ext>::base_size;
299template <
typename Ext>
300constexpr size_t
base_v4<Ext>::base_max_string_len;
302template <
typename Ext>
303constexpr size_t
base_v4<Ext>::base_max_prefixlen;
305template <
typename Ext>
306constexpr typename base_v4<Ext>::uint_type
base_v4<Ext>::base_all_ones;
A template class providing the base functionality for IPv4 addresses.
Definition base-v4.hpp:30
constexpr inline ip_version version() const noexcept
Retrieves the IP version of the address.
Definition base-v4.hpp:46
constexpr inline size_t size() const noexcept
Retrieves the size of the IPv4 address.
Definition base-v4.hpp:55
A template base class for IP address representations.
Definition ip-address-base.hpp:56
#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
ip_version
Enumerates the IP address versions.
Definition ip-address-base.hpp:29
@ V4
IPv4 version identifier.
constexpr inline bool is_little_endian() noexcept
Checks if the system is little-endian.
Definition endian.hpp:110
error_code
Enumeration of error codes for IP address parsing and validation.
Definition errors.hpp:52
@ octet_has_invalid_symbol
An octet contains characters other than digits, which are invalid.
@ empty_address
The IP address string is empty when it should contain a valid address.
@ octet_exceeded_255
An octet's value exceeds the maximum allowed value of 255.
@ leading_0_are_not_permitted
Leading zeroes are not permitted in any octet of the IPv4 address.
@ empty_octet
An octet in the IPv4 address is empty when it should contain a numeric value.
@ no_error
Indicates the absence of any errors.
@ has_host_bits_set
The address has host bits set when they are expected to be clear.
@ octet_more_3_characters
An octet contains more than three characters, exceeding the maximum allowed.
@ expected_4_octets
The IPv4 address does not contain the expected four octets.
@ netmask_pattern_mixes_zeroes_and_ones
The netmask contains an invalid pattern of zeroes and ones.
@ invalid_netmask
The provided netmask is not valid according to standard netmask formatting rules.
constexpr inline uint32_t swap_bytes(uint32_t value) noexcept
Swaps the bytes of a 32-bit unsigned integer.
Definition endian.hpp:126
A template class for creating and managing a fixed-size array of bytes.
Definition byte-array.hpp:33