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