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