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 <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 HIT 251340 : 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 ipv4_address(uint_type u) noexcept;
94 :
95 : /** Construct from an array of bytes.
96 :
97 : This function constructs an address
98 : from the array in `bytes`, which is
99 : interpreted in big-endian.
100 :
101 : @param bytes The value to construct from.
102 : */
103 : explicit ipv4_address(bytes_type const& bytes) noexcept;
104 :
105 : /** Construct from a string.
106 :
107 : This function constructs an address from
108 : the string `s`, which must contain a valid
109 : IPv4 address string or else an exception
110 : is thrown.
111 :
112 : @note For a non-throwing parse function,
113 : use @ref parse_ipv4_address.
114 :
115 : @par Exception Safety
116 : Exceptions thrown on invalid input.
117 :
118 : @throw std::invalid_argument The input failed to parse correctly.
119 :
120 : @param s The string to parse.
121 :
122 : @par Specification
123 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
124 : >3.2.2. Host (rfc3986)</a>
125 :
126 : @see
127 : @ref parse_ipv4_address.
128 : */
129 : explicit ipv4_address(std::string_view s);
130 :
131 : /** Return the address as bytes, in network byte order.
132 :
133 : @return The address as an array of bytes.
134 : */
135 : bytes_type to_bytes() const noexcept;
136 :
137 : /** Return the address as an unsigned integer.
138 :
139 : @return The address as an unsigned integer.
140 : */
141 : uint_type to_uint() const noexcept;
142 :
143 : /** Return the address as a string in dotted decimal format.
144 :
145 : @par Example
146 : @code
147 : assert( ipv4_address(0x01020304).to_string() == "1.2.3.4" );
148 : @endcode
149 :
150 : @return The address as a string.
151 : */
152 : std::string to_string() const;
153 :
154 : /** Write a dotted decimal string representing the address to a buffer.
155 :
156 : The resulting buffer is not null-terminated.
157 :
158 : @throw std::length_error `dest_size < ipv4_address::max_str_len`
159 :
160 : @return The formatted string view.
161 :
162 : @param dest The buffer in which to write,
163 : which must have at least `dest_size` space.
164 :
165 : @param dest_size The size of the output buffer.
166 : */
167 : std::string_view to_buffer(char* dest, std::size_t dest_size) const;
168 :
169 : /** Return true if the address is a loopback address.
170 :
171 : @return `true` if the address is a loopback address.
172 : */
173 : bool is_loopback() const noexcept;
174 :
175 : /** Return true if the address is unspecified.
176 :
177 : @return `true` if the address is unspecified.
178 : */
179 : bool is_unspecified() const noexcept;
180 :
181 : /** Return true if the address is a multicast address.
182 :
183 : @return `true` if the address is a multicast address.
184 : */
185 : bool is_multicast() const noexcept;
186 :
187 : /** Return true if two addresses are equal.
188 :
189 : @return `true` if the addresses are equal, otherwise `false`.
190 : */
191 : friend bool
192 59 : operator==(ipv4_address const& a1, ipv4_address const& a2) noexcept
193 : {
194 59 : return a1.addr_ == a2.addr_;
195 : }
196 :
197 : /** Return true if two addresses are not equal.
198 :
199 : @return `true` if the addresses are not equal, otherwise `false`.
200 : */
201 : friend bool
202 2 : operator!=(ipv4_address const& a1, ipv4_address const& a2) noexcept
203 : {
204 2 : return a1.addr_ != a2.addr_;
205 : }
206 :
207 : /** Return an address object that represents any address.
208 :
209 : @return The any address (0.0.0.0).
210 : */
211 251316 : static ipv4_address any() noexcept
212 : {
213 251316 : return ipv4_address();
214 : }
215 :
216 : /** Return an address object that represents the loopback address.
217 :
218 : @return The loopback address (127.0.0.1).
219 : */
220 8476 : static ipv4_address loopback() noexcept
221 : {
222 8476 : return ipv4_address(0x7F000001);
223 : }
224 :
225 : /** Return an address object that represents the broadcast address.
226 :
227 : @return The broadcast address (255.255.255.255).
228 : */
229 1 : static ipv4_address broadcast() noexcept
230 : {
231 1 : return ipv4_address(0xFFFFFFFF);
232 : }
233 :
234 : /** Format the address to an output stream.
235 :
236 : IPv4 addresses written to output streams
237 : are written in their dotted decimal format.
238 :
239 : @param os The output stream.
240 : @param addr The address to format.
241 : @return The output stream.
242 : */
243 : friend BOOST_COROSIO_DECL std::ostream&
244 : operator<<(std::ostream& os, ipv4_address const& addr);
245 :
246 : private:
247 : friend class ipv6_address;
248 :
249 : std::size_t print_impl(char* dest) const noexcept;
250 : };
251 :
252 :
253 : /** Return an IPv4 address from an IP address string in dotted decimal form.
254 :
255 : @param s The string to parse.
256 : @param addr The address to store the result.
257 : @return An error code (empty on success).
258 : */
259 : [[nodiscard]] BOOST_COROSIO_DECL std::error_code
260 : parse_ipv4_address(std::string_view s, ipv4_address& addr) noexcept;
261 :
262 : } // namespace boost::corosio
263 :
264 : #endif
|