include/boost/corosio/ipv4_address.hpp

100.0% Lines (13 / 13) 100.0% Functions (7 / 7)
ipv4_address.hpp
f(x) Functions (7)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2026 Michael Vandeberg
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/cppalliance/corosio
9 //
10
11 #ifndef BOOST_COROSIO_IPV4_ADDRESS_HPP
12 #define BOOST_COROSIO_IPV4_ADDRESS_HPP
13
14 #include <boost/corosio/detail/config.hpp>
15
16 #include <boost/capy/results.hpp>
17
18 #include <array>
19 #include <compare>
20 #include <cstdint>
21 #include <functional>
22 #include <iosfwd>
23 #include <string>
24 #include <string_view>
25 #include <system_error>
26
27 namespace boost::corosio {
28
29 /** Stores and parses an IP version 4 address.
30
31 Objects of this type are used to construct,
32 parse, and manipulate IP version 4 addresses.
33
34 @par BNF
35 @code
36 IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
37
38 dec-octet = DIGIT ; 0-9
39 / %x31-39 DIGIT ; 10-99
40 / "1" 2DIGIT ; 100-199
41 / "2" %x30-34 DIGIT ; 200-249
42 / "25" %x30-35 ; 250-255
43 @endcode
44
45 @par Specification
46 @li <a href="https://en.wikipedia.org/wiki/IPv4">IPv4 (Wikipedia)</a>
47 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
48 >3.2.2. Host (rfc3986)</a>
49
50 @see
51 @ref make_ipv4_address,
52 @ref ipv6_address
53 */
54 class BOOST_COROSIO_DECL ipv4_address
55 {
56 std::uint32_t addr_ = 0;
57
58 public:
59 /** The number of characters in the longest possible IPv4 string.
60
61 The longest IPv4 address string is "255.255.255.255".
62 */
63 static constexpr std::size_t max_str_len = 15;
64
65 /** The type used to represent an address as an unsigned integer.
66 */
67 using uint_type = std::uint32_t;
68
69 /** The type used to represent an address as an array of bytes.
70 */
71 using bytes_type = std::array<unsigned char, 4>;
72
73 /** Default constructor.
74
75 Constructs the unspecified address (0.0.0.0).
76 */
77 269848x ipv4_address() = default;
78
79 /** Copy constructor.
80 */
81 ipv4_address(ipv4_address const&) = default;
82
83 /** Copy assignment.
84
85 @return A reference to this object.
86 */
87 ipv4_address& operator=(ipv4_address const&) = default;
88
89 /** Construct from an unsigned integer.
90
91 This function constructs an address from
92 the unsigned integer `u`, where the most
93 significant byte forms the first octet
94 of the resulting address.
95
96 @param u The integer to construct from.
97 */
98 explicit ipv4_address(uint_type u) noexcept;
99
100 /** Construct from an array of bytes.
101
102 This function constructs an address
103 from the array in `bytes`, which is
104 interpreted in big-endian.
105
106 @param bytes The value to construct from.
107 */
108 explicit ipv4_address(bytes_type const& bytes) noexcept;
109
110 /** Return the address as bytes, in network byte order.
111
112 @return The address as an array of bytes.
113 */
114 bytes_type to_bytes() const noexcept;
115
116 /** Return the address as an unsigned integer.
117
118 @return The address as an unsigned integer.
119 */
120 uint_type to_uint() const noexcept;
121
122 /** Return the address as a string in dotted decimal format.
123
124 @par Example
125 @par !example to_string
126
127 @return The address as a string.
128 */
129 std::string to_string() const;
130
131 /** Write a dotted decimal string representing the address to a buffer.
132
133 The resulting buffer is not null-terminated.
134
135 @throws std::length_error `dest_size < ipv4_address::max_str_len`
136
137 @param dest The buffer in which to write,
138 which must have at least `dest_size` space.
139
140 @param dest_size The size of the output buffer.
141
142 @return The formatted string view.
143 */
144 std::string_view to_buffer(char* dest, std::size_t dest_size) const;
145
146 /** Return true if the address is a loopback address.
147
148 @return `true` if the address is a loopback address.
149 */
150 bool is_loopback() const noexcept;
151
152 /** Return true if the address is unspecified.
153
154 @return `true` if the address is unspecified.
155 */
156 bool is_unspecified() const noexcept;
157
158 /** Return true if the address is a multicast address.
159
160 @return `true` if the address is a multicast address.
161 */
162 bool is_multicast() const noexcept;
163
164 /** Return true if two addresses are equal.
165
166 @return `true` if the addresses are equal, otherwise `false`.
167 */
168 friend bool
169 193x operator==(ipv4_address const& a1, ipv4_address const& a2) noexcept
170 {
171 193x return a1.addr_ == a2.addr_;
172 }
173
174 /** Order two addresses.
175
176 Establishes a strict total ordering consistent with
177 `operator==`: addresses are ordered by their integer
178 value, most significant octet first. This makes
179 `ipv4_address` usable as a key in ordered containers
180 such as `std::map` and `std::set`.
181
182 @return The relative order of `a1` and `a2`.
183 */
184 friend std::strong_ordering
185 23x operator<=>(ipv4_address const& a1, ipv4_address const& a2) noexcept
186 {
187 23x return a1.addr_ <=> a2.addr_;
188 }
189
190 /** Return an address object that represents any address.
191
192 @return The any address (0.0.0.0).
193 */
194 28x static ipv4_address any() noexcept
195 {
196 28x return ipv4_address();
197 }
198
199 /** Return an address object that represents the loopback address.
200
201 @return The loopback address (127.0.0.1).
202 */
203 8050x static ipv4_address loopback() noexcept
204 {
205 8050x return ipv4_address(0x7F000001);
206 }
207
208 /** Return an address object that represents the broadcast address.
209
210 @return The broadcast address (255.255.255.255).
211 */
212 6x static ipv4_address broadcast() noexcept
213 {
214 6x return ipv4_address(0xFFFFFFFF);
215 }
216
217 /** Format the address to an output stream.
218
219 This operator writes the address in dotted decimal format.
220
221 @param os The output stream.
222 @param addr The address to format.
223 @return The output stream.
224 */
225 friend BOOST_COROSIO_DECL std::ostream&
226 operator<<(std::ostream& os, ipv4_address const& addr);
227
228 private:
229 friend class ipv6_address;
230
231 std::size_t print_impl(char* dest) const noexcept;
232 };
233
234 /** Create an IPv4 address from an IP address string in dotted decimal form.
235
236 @par Specification
237 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
238 >3.2.2. Host (rfc3986)</a>
239
240 @param s The string to parse.
241 @return The error code, empty on success, and the parsed
242 address — default-constructed on failure.
243 */
244 [[nodiscard]] BOOST_COROSIO_DECL capy::results<ipv4_address>
245 make_ipv4_address(std::string_view s) noexcept;
246
247 } // namespace boost::corosio
248
249 namespace std {
250
251 /// Hash support for `boost::corosio::ipv4_address`.
252 template<>
253 struct hash<boost::corosio::ipv4_address>
254 {
255 /// Return the hash of `addr`.
256 std::size_t
257 20x operator()(boost::corosio::ipv4_address const& addr) const noexcept
258 {
259 20x return hash<std::uint32_t>()(addr.to_uint());
260 }
261 };
262
263 } // namespace std
264
265 #endif
266