1  
//
1  
//
2  
// Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/cppalliance/corosio
7  
// Official repository: https://github.com/cppalliance/corosio
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_COROSIO_IPV4_ADDRESS_HPP
10  
#ifndef BOOST_COROSIO_IPV4_ADDRESS_HPP
11  
#define BOOST_COROSIO_IPV4_ADDRESS_HPP
11  
#define BOOST_COROSIO_IPV4_ADDRESS_HPP
12  

12  

13  
#include <boost/corosio/detail/config.hpp>
13  
#include <boost/corosio/detail/config.hpp>
14  

14  

15  
#include <array>
15  
#include <array>
16  
#include <cstdint>
16  
#include <cstdint>
17  
#include <iosfwd>
17  
#include <iosfwd>
18  
#include <string>
18  
#include <string>
19  
#include <string_view>
19  
#include <string_view>
20  
#include <system_error>
20  
#include <system_error>
21  

21  

22  
namespace boost::corosio {
22  
namespace boost::corosio {
23  

23  

24  
/** An IP version 4 style address.
24  
/** An IP version 4 style address.
25  

25  

26  
    Objects of this type are used to construct,
26  
    Objects of this type are used to construct,
27  
    parse, and manipulate IP version 4 addresses.
27  
    parse, and manipulate IP version 4 addresses.
28  

28  

29  
    @par BNF
29  
    @par BNF
30  
    @code
30  
    @code
31  
    IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
31  
    IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
32  

32  

33  
    dec-octet   = DIGIT                 ; 0-9
33  
    dec-octet   = DIGIT                 ; 0-9
34  
                / %x31-39 DIGIT         ; 10-99
34  
                / %x31-39 DIGIT         ; 10-99
35  
                / "1" 2DIGIT            ; 100-199
35  
                / "1" 2DIGIT            ; 100-199
36  
                / "2" %x30-34 DIGIT     ; 200-249
36  
                / "2" %x30-34 DIGIT     ; 200-249
37  
                / "25" %x30-35          ; 250-255
37  
                / "25" %x30-35          ; 250-255
38  
    @endcode
38  
    @endcode
39  

39  

40  
    @par Specification
40  
    @par Specification
41  
    @li <a href="https://en.wikipedia.org/wiki/IPv4">IPv4 (Wikipedia)</a>
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"
42  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
43  
        >3.2.2. Host (rfc3986)</a>
43  
        >3.2.2. Host (rfc3986)</a>
44  

44  

45  
    @see
45  
    @see
46  
        @ref parse_ipv4_address,
46  
        @ref parse_ipv4_address,
47  
        @ref ipv6_address.
47  
        @ref ipv6_address.
48  
*/
48  
*/
49  
class BOOST_COROSIO_DECL ipv4_address
49  
class BOOST_COROSIO_DECL ipv4_address
50  
{
50  
{
51  
    std::uint32_t addr_ = 0;
51  
    std::uint32_t addr_ = 0;
52  

52  

53  
public:
53  
public:
54  
    /** The number of characters in the longest possible IPv4 string.
54  
    /** The number of characters in the longest possible IPv4 string.
55  

55  

56  
        The longest IPv4 address string is "255.255.255.255".
56  
        The longest IPv4 address string is "255.255.255.255".
57  
    */
57  
    */
58  
    static constexpr std::size_t max_str_len = 15;
58  
    static constexpr std::size_t max_str_len = 15;
59  

59  

60  
    /** The type used to represent an address as an unsigned integer.
60  
    /** The type used to represent an address as an unsigned integer.
61  
    */
61  
    */
62  
    using uint_type = std::uint32_t;
62  
    using uint_type = std::uint32_t;
63  

63  

64  
    /** The type used to represent an address as an array of bytes.
64  
    /** The type used to represent an address as an array of bytes.
65  
    */
65  
    */
66  
    using bytes_type = std::array<unsigned char, 4>;
66  
    using bytes_type = std::array<unsigned char, 4>;
67  

67  

68  
    /** Default constructor.
68  
    /** Default constructor.
69  

69  

70  
        Constructs the unspecified address (0.0.0.0).
70  
        Constructs the unspecified address (0.0.0.0).
71  
    */
71  
    */
72  
    ipv4_address() = default;
72  
    ipv4_address() = default;
73  

73  

74  
    /** Copy constructor.
74  
    /** Copy constructor.
75  
    */
75  
    */
76  
    ipv4_address(ipv4_address const&) = default;
76  
    ipv4_address(ipv4_address const&) = default;
77  

77  

78  
    /** Copy assignment.
78  
    /** Copy assignment.
79  

79  

80  
        @return A reference to this object.
80  
        @return A reference to this object.
81  
    */
81  
    */
82  
    ipv4_address& operator=(ipv4_address const&) = default;
82  
    ipv4_address& operator=(ipv4_address const&) = default;
83  

83  

84  
    /** Construct from an unsigned integer.
84  
    /** Construct from an unsigned integer.
85  

85  

86  
        This function constructs an address from
86  
        This function constructs an address from
87  
        the unsigned integer `u`, where the most
87  
        the unsigned integer `u`, where the most
88  
        significant byte forms the first octet
88  
        significant byte forms the first octet
89  
        of the resulting address.
89  
        of the resulting address.
90  

90  

91  
        @param u The integer to construct from.
91  
        @param u The integer to construct from.
92  
    */
92  
    */
93 -
    explicit
93 +
    explicit ipv4_address(uint_type u) noexcept;
94 -
    ipv4_address(uint_type u) noexcept;
 
95  

94  

96  
    /** Construct from an array of bytes.
95  
    /** Construct from an array of bytes.
97  

96  

98  
        This function constructs an address
97  
        This function constructs an address
99  
        from the array in `bytes`, which is
98  
        from the array in `bytes`, which is
100  
        interpreted in big-endian.
99  
        interpreted in big-endian.
101  

100  

102  
        @param bytes The value to construct from.
101  
        @param bytes The value to construct from.
103  
    */
102  
    */
104 -
    explicit
103 +
    explicit ipv4_address(bytes_type const& bytes) noexcept;
105 -
    ipv4_address(bytes_type const& bytes) noexcept;
 
106  

104  

107  
    /** Construct from a string.
105  
    /** Construct from a string.
108  

106  

109  
        This function constructs an address from
107  
        This function constructs an address from
110  
        the string `s`, which must contain a valid
108  
        the string `s`, which must contain a valid
111  
        IPv4 address string or else an exception
109  
        IPv4 address string or else an exception
112  
        is thrown.
110  
        is thrown.
113  

111  

114  
        @note For a non-throwing parse function,
112  
        @note For a non-throwing parse function,
115  
        use @ref parse_ipv4_address.
113  
        use @ref parse_ipv4_address.
116  

114  

117  
        @par Exception Safety
115  
        @par Exception Safety
118  
        Exceptions thrown on invalid input.
116  
        Exceptions thrown on invalid input.
119  

117  

120  
        @throw std::invalid_argument The input failed to parse correctly.
118  
        @throw std::invalid_argument The input failed to parse correctly.
121  

119  

122  
        @param s The string to parse.
120  
        @param s The string to parse.
123  

121  

124  
        @par Specification
122  
        @par Specification
125  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
123  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
126  
            >3.2.2. Host (rfc3986)</a>
124  
            >3.2.2. Host (rfc3986)</a>
127  

125  

128  
        @see
126  
        @see
129  
            @ref parse_ipv4_address.
127  
            @ref parse_ipv4_address.
130  
    */
128  
    */
131 -
    explicit
129 +
    explicit ipv4_address(std::string_view s);
132 -
    ipv4_address(std::string_view s);
 
133  

130  

134  
    /** Return the address as bytes, in network byte order.
131  
    /** Return the address as bytes, in network byte order.
135  

132  

136  
        @return The address as an array of bytes.
133  
        @return The address as an array of bytes.
137  
    */
134  
    */
138 -
    bytes_type
135 +
    bytes_type to_bytes() const noexcept;
139 -
    to_bytes() const noexcept;
 
140  

136  

141  
    /** Return the address as an unsigned integer.
137  
    /** Return the address as an unsigned integer.
142  

138  

143  
        @return The address as an unsigned integer.
139  
        @return The address as an unsigned integer.
144  
    */
140  
    */
145 -
    uint_type
141 +
    uint_type to_uint() const noexcept;
146 -
    to_uint() const noexcept;
 
147  

142  

148  
    /** Return the address as a string in dotted decimal format.
143  
    /** Return the address as a string in dotted decimal format.
149  

144  

150  
        @par Example
145  
        @par Example
151  
        @code
146  
        @code
152  
        assert( ipv4_address(0x01020304).to_string() == "1.2.3.4" );
147  
        assert( ipv4_address(0x01020304).to_string() == "1.2.3.4" );
153  
        @endcode
148  
        @endcode
154  

149  

155  
        @return The address as a string.
150  
        @return The address as a string.
156  
    */
151  
    */
157 -
    std::string
152 +
    std::string to_string() const;
158 -
    to_string() const;
 
159  

153  

160  
    /** Write a dotted decimal string representing the address to a buffer.
154  
    /** Write a dotted decimal string representing the address to a buffer.
161  

155  

162  
        The resulting buffer is not null-terminated.
156  
        The resulting buffer is not null-terminated.
163  

157  

164  
        @throw std::length_error `dest_size < ipv4_address::max_str_len`
158  
        @throw std::length_error `dest_size < ipv4_address::max_str_len`
165  

159  

166  
        @return The formatted string view.
160  
        @return The formatted string view.
167  

161  

168  
        @param dest The buffer in which to write,
162  
        @param dest The buffer in which to write,
169  
        which must have at least `dest_size` space.
163  
        which must have at least `dest_size` space.
170  

164  

171  
        @param dest_size The size of the output buffer.
165  
        @param dest_size The size of the output buffer.
172  
    */
166  
    */
173 -
    std::string_view
167 +
    std::string_view to_buffer(char* dest, std::size_t dest_size) const;
174 -
    to_buffer(char* dest, std::size_t dest_size) const;
 
175  

168  

176  
    /** Return true if the address is a loopback address.
169  
    /** Return true if the address is a loopback address.
177  

170  

178  
        @return `true` if the address is a loopback address.
171  
        @return `true` if the address is a loopback address.
179  
    */
172  
    */
180 -
    bool
173 +
    bool is_loopback() const noexcept;
181 -
    is_loopback() const noexcept;
 
182  

174  

183  
    /** Return true if the address is unspecified.
175  
    /** Return true if the address is unspecified.
184  

176  

185  
        @return `true` if the address is unspecified.
177  
        @return `true` if the address is unspecified.
186  
    */
178  
    */
187 -
    bool
179 +
    bool is_unspecified() const noexcept;
188 -
    is_unspecified() const noexcept;
 
189  

180  

190  
    /** Return true if the address is a multicast address.
181  
    /** Return true if the address is a multicast address.
191  

182  

192  
        @return `true` if the address is a multicast address.
183  
        @return `true` if the address is a multicast address.
193  
    */
184  
    */
194 -
    bool
185 +
    bool is_multicast() const noexcept;
195 -
    is_multicast() const noexcept;
 
196  

186  

197  
    /** Return true if two addresses are equal.
187  
    /** Return true if two addresses are equal.
198  

188  

199  
        @return `true` if the addresses are equal, otherwise `false`.
189  
        @return `true` if the addresses are equal, otherwise `false`.
200  
    */
190  
    */
201 -
    friend
191 +
    friend bool
202 -
    bool
 
203  
    operator==(ipv4_address const& a1, ipv4_address const& a2) noexcept
192  
    operator==(ipv4_address const& a1, ipv4_address const& a2) noexcept
204  
    {
193  
    {
205  
        return a1.addr_ == a2.addr_;
194  
        return a1.addr_ == a2.addr_;
206  
    }
195  
    }
207  

196  

208  
    /** Return true if two addresses are not equal.
197  
    /** Return true if two addresses are not equal.
209  

198  

210  
        @return `true` if the addresses are not equal, otherwise `false`.
199  
        @return `true` if the addresses are not equal, otherwise `false`.
211  
    */
200  
    */
212 -
    friend
201 +
    friend bool
213 -
    bool
 
214  
    operator!=(ipv4_address const& a1, ipv4_address const& a2) noexcept
202  
    operator!=(ipv4_address const& a1, ipv4_address const& a2) noexcept
215  
    {
203  
    {
216  
        return a1.addr_ != a2.addr_;
204  
        return a1.addr_ != a2.addr_;
217  
    }
205  
    }
218  

206  

219  
    /** Return an address object that represents any address.
207  
    /** Return an address object that represents any address.
220  

208  

221  
        @return The any address (0.0.0.0).
209  
        @return The any address (0.0.0.0).
222  
    */
210  
    */
223 -
    static
211 +
    static ipv4_address any() noexcept
224 -
    ipv4_address
 
225 -
    any() noexcept
 
226  
    {
212  
    {
227  
        return ipv4_address();
213  
        return ipv4_address();
228  
    }
214  
    }
229  

215  

230  
    /** Return an address object that represents the loopback address.
216  
    /** Return an address object that represents the loopback address.
231  

217  

232  
        @return The loopback address (127.0.0.1).
218  
        @return The loopback address (127.0.0.1).
233  
    */
219  
    */
234 -
    static
220 +
    static ipv4_address loopback() noexcept
235 -
    ipv4_address
 
236 -
    loopback() noexcept
 
237  
    {
221  
    {
238  
        return ipv4_address(0x7F000001);
222  
        return ipv4_address(0x7F000001);
239  
    }
223  
    }
240  

224  

241  
    /** Return an address object that represents the broadcast address.
225  
    /** Return an address object that represents the broadcast address.
242  

226  

243  
        @return The broadcast address (255.255.255.255).
227  
        @return The broadcast address (255.255.255.255).
244  
    */
228  
    */
245 -
    static
229 +
    static ipv4_address broadcast() noexcept
246 -
    ipv4_address
 
247 -
    broadcast() noexcept
 
248  
    {
230  
    {
249  
        return ipv4_address(0xFFFFFFFF);
231  
        return ipv4_address(0xFFFFFFFF);
250  
    }
232  
    }
251  

233  

252  
    /** Format the address to an output stream.
234  
    /** Format the address to an output stream.
253  

235  

254  
        IPv4 addresses written to output streams
236  
        IPv4 addresses written to output streams
255  
        are written in their dotted decimal format.
237  
        are written in their dotted decimal format.
256  

238  

257  
        @param os The output stream.
239  
        @param os The output stream.
258  
        @param addr The address to format.
240  
        @param addr The address to format.
259  
        @return The output stream.
241  
        @return The output stream.
260  
    */
242  
    */
261 -
    friend
243 +
    friend BOOST_COROSIO_DECL std::ostream&
262 -
    BOOST_COROSIO_DECL
 
263 -
    std::ostream&
 
264  
    operator<<(std::ostream& os, ipv4_address const& addr);
244  
    operator<<(std::ostream& os, ipv4_address const& addr);
265  

245  

266  
private:
246  
private:
267  
    friend class ipv6_address;
247  
    friend class ipv6_address;
268  

248  

269 -
    std::size_t
249 +
    std::size_t print_impl(char* dest) const noexcept;
270 -
    print_impl(char* dest) const noexcept;
 
271  
};
250  
};
272 -
//------------------------------------------------
 
273  

251  

274  

252  

275  
/** Return an IPv4 address from an IP address string in dotted decimal form.
253  
/** Return an IPv4 address from an IP address string in dotted decimal form.
276  

254  

277  
    @param s The string to parse.
255  
    @param s The string to parse.
278  
    @param addr The address to store the result.
256  
    @param addr The address to store the result.
279  
    @return An error code (empty on success).
257  
    @return An error code (empty on success).
280  
*/
258  
*/
281 -
[[nodiscard]] BOOST_COROSIO_DECL
259 +
[[nodiscard]] BOOST_COROSIO_DECL std::error_code
282 -
std::error_code
260 +
parse_ipv4_address(std::string_view s, ipv4_address& addr) noexcept;
283 -
parse_ipv4_address(
 
284 -
    std::string_view s,
 
285 -
    ipv4_address& addr) noexcept;
 
286  

261  

287  
} // namespace boost::corosio
262  
} // namespace boost::corosio
288  

263  

289  
#endif
264  
#endif