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