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   /** Stores and parses an IP version 4 address. 29   /** Stores and parses an IP version 4 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   145482 ipv4_address() = default; 77   145890 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   5294 static ipv4_address loopback() noexcept 230   5307 static ipv4_address loopback() noexcept
231   { 231   {
HITCBC 232   5294 return ipv4_address(0x7F000001); 232   5307 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   This operator writes the address in dotted decimal format. 246   This operator writes the address in dotted decimal format.
247   247  
248   @param os The output stream. 248   @param os The output stream.
249   @param addr The address to format. 249   @param addr The address to format.
250   @return The output stream. 250   @return The output stream.
251   */ 251   */
252   friend BOOST_COROSIO_DECL std::ostream& 252   friend BOOST_COROSIO_DECL std::ostream&
253   operator<<(std::ostream& os, ipv4_address const& addr); 253   operator<<(std::ostream& os, ipv4_address const& addr);
254   254  
255   private: 255   private:
256   friend class ipv6_address; 256   friend class ipv6_address;
257   257  
258   std::size_t print_impl(char* dest) const noexcept; 258   std::size_t print_impl(char* dest) const noexcept;
259   }; 259   };
260   260  
261   /** Create an IPv4 address from an IP address string in dotted decimal form. 261   /** Create an IPv4 address from an IP address string in dotted decimal form.
262   262  
263   @param s The string to parse. 263   @param s The string to parse.
264   @return The error code, empty on success, and the parsed 264   @return The error code, empty on success, and the parsed
265   address — default-constructed on failure. 265   address — default-constructed on failure.
266   */ 266   */
267   [[nodiscard]] BOOST_COROSIO_DECL capy::io_result<ipv4_address> 267   [[nodiscard]] BOOST_COROSIO_DECL capy::io_result<ipv4_address>
268   make_ipv4_address(std::string_view s) noexcept; 268   make_ipv4_address(std::string_view s) noexcept;
269   269  
270   } // namespace boost::corosio 270   } // namespace boost::corosio
271   271  
272   namespace std { 272   namespace std {
273   273  
274   /// Hash support for `boost::corosio::ipv4_address`. 274   /// Hash support for `boost::corosio::ipv4_address`.
275   template<> 275   template<>
276   struct hash<boost::corosio::ipv4_address> 276   struct hash<boost::corosio::ipv4_address>
277   { 277   {
278   /// Return the hash of `addr`. 278   /// Return the hash of `addr`.
279   std::size_t 279   std::size_t
HITCBC 280   20 operator()(boost::corosio::ipv4_address const& addr) const noexcept 280   20 operator()(boost::corosio::ipv4_address const& addr) const noexcept
281   { 281   {
HITCBC 282   20 return hash<std::uint32_t>()(addr.to_uint()); 282   20 return hash<std::uint32_t>()(addr.to_uint());
283   } 283   }
284   }; 284   };
285   285  
286   } // namespace std 286   } // namespace std
287   287  
288   #endif 288   #endif