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