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/io_result.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 /** An IP version 4 style 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 145522x 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 /** Construct from a string.
111
112 This function constructs an address from
113 the string `s`, which must contain a valid
114 IPv4 address string or else an exception
115 is thrown.
116
117 @par Exception Safety
118 Strong guarantee.
119
120 @throws std::system_error `errc::invalid_argument` if the input
121 failed to parse correctly.
122
123 @note For a non-throwing parse function,
124 use @ref make_ipv4_address.
125
126 @param s The string to parse.
127
128 @par Specification
129 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
130 >3.2.2. Host (rfc3986)</a>
131
132 @see
133 @ref make_ipv4_address.
134 */
135 explicit ipv4_address(std::string_view s);
136
137 /** Return the address as bytes, in network byte order.
138
139 @return The address as an array of bytes.
140 */
141 bytes_type to_bytes() const noexcept;
142
143 /** Return the address as an unsigned integer.
144
145 @return The address as an unsigned integer.
146 */
147 uint_type to_uint() const noexcept;
148
149 /** Return the address as a string in dotted decimal format.
150
151 @par Example
152 @par !example to_string
153
154 @return The address as a string.
155 */
156 std::string to_string() const;
157
158 /** Write a dotted decimal string representing the address to a buffer.
159
160 The resulting buffer is not null-terminated.
161
162 @throws std::length_error `dest_size < ipv4_address::max_str_len`
163
164 @param dest The buffer in which to write,
165 which must have at least `dest_size` space.
166
167 @param dest_size The size of the output buffer.
168
169 @return The formatted string view.
170 */
171 std::string_view to_buffer(char* dest, std::size_t dest_size) const;
172
173 /** Return true if the address is a loopback address.
174
175 @return `true` if the address is a loopback address.
176 */
177 bool is_loopback() const noexcept;
178
179 /** Return true if the address is unspecified.
180
181 @return `true` if the address is unspecified.
182 */
183 bool is_unspecified() const noexcept;
184
185 /** Return true if the address is a multicast address.
186
187 @return `true` if the address is a multicast address.
188 */
189 bool is_multicast() const noexcept;
190
191 /** Return true if two addresses are equal.
192
193 @return `true` if the addresses are equal, otherwise `false`.
194 */
195 friend bool
196 157x operator==(ipv4_address const& a1, ipv4_address const& a2) noexcept
197 {
198 157x return a1.addr_ == a2.addr_;
199 }
200
201 /** Order two addresses.
202
203 Establishes a strict total ordering consistent with
204 `operator==`: addresses are ordered by their integer
205 value, most significant octet first. This makes
206 `ipv4_address` usable as a key in ordered containers
207 such as `std::map` and `std::set`.
208
209 @return The relative order of `a1` and `a2`.
210 */
211 friend std::strong_ordering
212 23x operator<=>(ipv4_address const& a1, ipv4_address const& a2) noexcept
213 {
214 23x return a1.addr_ <=> a2.addr_;
215 }
216
217 /** Return an address object that represents any address.
218
219 @return The any address (0.0.0.0).
220 */
221 28x static ipv4_address any() noexcept
222 {
223 28x return ipv4_address();
224 }
225
226 /** Return an address object that represents the loopback address.
227
228 @return The loopback address (127.0.0.1).
229 */
230 5302x static ipv4_address loopback() noexcept
231 {
232 5302x return ipv4_address(0x7F000001);
233 }
234
235 /** Return an address object that represents the broadcast address.
236
237 @return The broadcast address (255.255.255.255).
238 */
239 6x static ipv4_address broadcast() noexcept
240 {
241 6x return ipv4_address(0xFFFFFFFF);
242 }
243
244 /** Format the address to an output stream.
245
246 IPv4 addresses written to output streams
247 are written in their dotted decimal format.
248
249 @param os The output stream.
250 @param addr The address to format.
251 @return The output stream.
252 */
253 friend BOOST_COROSIO_DECL std::ostream&
254 operator<<(std::ostream& os, ipv4_address const& addr);
255
256 private:
257 friend class ipv6_address;
258
259 std::size_t print_impl(char* dest) const noexcept;
260 };
261
262 /** Create an IPv4 address from an IP address string in dotted decimal form.
263
264 @param s The string to parse.
265 @return The error code, empty on success, and the parsed
266 address — default-constructed on failure.
267 */
268 [[nodiscard]] BOOST_COROSIO_DECL capy::io_result<ipv4_address>
269 make_ipv4_address(std::string_view s) noexcept;
270
271 } // namespace boost::corosio
272
273 namespace std {
274
275 /// Hash support for `boost::corosio::ipv4_address`.
276 template<>
277 struct hash<boost::corosio::ipv4_address>
278 {
279 /// Return the hash of `addr`.
280 std::size_t
281 20x operator()(boost::corosio::ipv4_address const& addr) const noexcept
282 {
283 20x return hash<std::uint32_t>()(addr.to_uint());
284 }
285 };
286
287 } // namespace std
288
289 #endif
290