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