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/results.hpp> 16   #include <boost/capy/results.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   265125 ipv4_address() = default; 77   269848 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   /** Return the address as bytes, in network byte order. 110   /** Return the address as bytes, in network byte order.
111   111  
112   @return The address as an array of bytes. 112   @return The address as an array of bytes.
113   */ 113   */
114   bytes_type to_bytes() const noexcept; 114   bytes_type to_bytes() const noexcept;
115   115  
116   /** Return the address as an unsigned integer. 116   /** Return the address as an unsigned integer.
117   117  
118   @return The address as an unsigned integer. 118   @return The address as an unsigned integer.
119   */ 119   */
120   uint_type to_uint() const noexcept; 120   uint_type to_uint() const noexcept;
121   121  
122   /** Return the address as a string in dotted decimal format. 122   /** Return the address as a string in dotted decimal format.
123   123  
124   @par Example 124   @par Example
125   @par !example to_string 125   @par !example to_string
126   126  
127   @return The address as a string. 127   @return The address as a string.
128   */ 128   */
129   std::string to_string() const; 129   std::string to_string() const;
130   130  
131   /** Write a dotted decimal string representing the address to a buffer. 131   /** Write a dotted decimal string representing the address to a buffer.
132   132  
133   The resulting buffer is not null-terminated. 133   The resulting buffer is not null-terminated.
134   134  
135   @throws std::length_error `dest_size < ipv4_address::max_str_len` 135   @throws std::length_error `dest_size < ipv4_address::max_str_len`
136   136  
137   @param dest The buffer in which to write, 137   @param dest The buffer in which to write,
138   which must have at least `dest_size` space. 138   which must have at least `dest_size` space.
139   139  
140   @param dest_size The size of the output buffer. 140   @param dest_size The size of the output buffer.
141   141  
142   @return The formatted string view. 142   @return The formatted string view.
143   */ 143   */
144   std::string_view to_buffer(char* dest, std::size_t dest_size) const; 144   std::string_view to_buffer(char* dest, std::size_t dest_size) const;
145   145  
146   /** Return true if the address is a loopback address. 146   /** Return true if the address is a loopback address.
147   147  
148   @return `true` if the address is a loopback address. 148   @return `true` if the address is a loopback address.
149   */ 149   */
150   bool is_loopback() const noexcept; 150   bool is_loopback() const noexcept;
151   151  
152   /** Return true if the address is unspecified. 152   /** Return true if the address is unspecified.
153   153  
154   @return `true` if the address is unspecified. 154   @return `true` if the address is unspecified.
155   */ 155   */
156   bool is_unspecified() const noexcept; 156   bool is_unspecified() const noexcept;
157   157  
158   /** Return true if the address is a multicast address. 158   /** Return true if the address is a multicast address.
159   159  
160   @return `true` if the address is a multicast address. 160   @return `true` if the address is a multicast address.
161   */ 161   */
162   bool is_multicast() const noexcept; 162   bool is_multicast() const noexcept;
163   163  
164   /** Return true if two addresses are equal. 164   /** Return true if two addresses are equal.
165   165  
166   @return `true` if the addresses are equal, otherwise `false`. 166   @return `true` if the addresses are equal, otherwise `false`.
167   */ 167   */
168   friend bool 168   friend bool
HITCBC 169   193 operator==(ipv4_address const& a1, ipv4_address const& a2) noexcept 169   193 operator==(ipv4_address const& a1, ipv4_address const& a2) noexcept
170   { 170   {
HITCBC 171   193 return a1.addr_ == a2.addr_; 171   193 return a1.addr_ == a2.addr_;
172   } 172   }
173   173  
174   /** Order two addresses. 174   /** Order two addresses.
175   175  
176   Establishes a strict total ordering consistent with 176   Establishes a strict total ordering consistent with
177   `operator==`: addresses are ordered by their integer 177   `operator==`: addresses are ordered by their integer
178   value, most significant octet first. This makes 178   value, most significant octet first. This makes
179   `ipv4_address` usable as a key in ordered containers 179   `ipv4_address` usable as a key in ordered containers
180   such as `std::map` and `std::set`. 180   such as `std::map` and `std::set`.
181   181  
182   @return The relative order of `a1` and `a2`. 182   @return The relative order of `a1` and `a2`.
183   */ 183   */
184   friend std::strong_ordering 184   friend std::strong_ordering
HITCBC 185   23 operator<=>(ipv4_address const& a1, ipv4_address const& a2) noexcept 185   23 operator<=>(ipv4_address const& a1, ipv4_address const& a2) noexcept
186   { 186   {
HITCBC 187   23 return a1.addr_ <=> a2.addr_; 187   23 return a1.addr_ <=> a2.addr_;
188   } 188   }
189   189  
190   /** Return an address object that represents any address. 190   /** Return an address object that represents any address.
191   191  
192   @return The any address (0.0.0.0). 192   @return The any address (0.0.0.0).
193   */ 193   */
HITCBC 194   28 static ipv4_address any() noexcept 194   28 static ipv4_address any() noexcept
195   { 195   {
HITCBC 196   28 return ipv4_address(); 196   28 return ipv4_address();
197   } 197   }
198   198  
199   /** Return an address object that represents the loopback address. 199   /** Return an address object that represents the loopback address.
200   200  
201   @return The loopback address (127.0.0.1). 201   @return The loopback address (127.0.0.1).
202   */ 202   */
HITCBC 203   8077 static ipv4_address loopback() noexcept 203   8050 static ipv4_address loopback() noexcept
204   { 204   {
HITCBC 205   8077 return ipv4_address(0x7F000001); 205   8050 return ipv4_address(0x7F000001);
206   } 206   }
207   207  
208   /** Return an address object that represents the broadcast address. 208   /** Return an address object that represents the broadcast address.
209   209  
210   @return The broadcast address (255.255.255.255). 210   @return The broadcast address (255.255.255.255).
211   */ 211   */
HITCBC 212   6 static ipv4_address broadcast() noexcept 212   6 static ipv4_address broadcast() noexcept
213   { 213   {
HITCBC 214   6 return ipv4_address(0xFFFFFFFF); 214   6 return ipv4_address(0xFFFFFFFF);
215   } 215   }
216   216  
217   /** Format the address to an output stream. 217   /** Format the address to an output stream.
218   218  
219   This operator writes the address in dotted decimal format. 219   This operator writes the address in dotted decimal format.
220   220  
221   @param os The output stream. 221   @param os The output stream.
222   @param addr The address to format. 222   @param addr The address to format.
223   @return The output stream. 223   @return The output stream.
224   */ 224   */
225   friend BOOST_COROSIO_DECL std::ostream& 225   friend BOOST_COROSIO_DECL std::ostream&
226   operator<<(std::ostream& os, ipv4_address const& addr); 226   operator<<(std::ostream& os, ipv4_address const& addr);
227   227  
228   private: 228   private:
229   friend class ipv6_address; 229   friend class ipv6_address;
230   230  
231   std::size_t print_impl(char* dest) const noexcept; 231   std::size_t print_impl(char* dest) const noexcept;
232   }; 232   };
233   233  
234   /** Create an IPv4 address from an IP address string in dotted decimal form. 234   /** Create an IPv4 address from an IP address string in dotted decimal form.
235   235  
236   @par Specification 236   @par Specification
237   @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2" 237   @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
238   >3.2.2. Host (rfc3986)</a> 238   >3.2.2. Host (rfc3986)</a>
239   239  
240   @param s The string to parse. 240   @param s The string to parse.
241   @return The error code, empty on success, and the parsed 241   @return The error code, empty on success, and the parsed
242   address — default-constructed on failure. 242   address — default-constructed on failure.
243   */ 243   */
244   [[nodiscard]] BOOST_COROSIO_DECL capy::results<ipv4_address> 244   [[nodiscard]] BOOST_COROSIO_DECL capy::results<ipv4_address>
245   make_ipv4_address(std::string_view s) noexcept; 245   make_ipv4_address(std::string_view s) noexcept;
246   246  
247   } // namespace boost::corosio 247   } // namespace boost::corosio
248   248  
249   namespace std { 249   namespace std {
250   250  
251   /// Hash support for `boost::corosio::ipv4_address`. 251   /// Hash support for `boost::corosio::ipv4_address`.
252   template<> 252   template<>
253   struct hash<boost::corosio::ipv4_address> 253   struct hash<boost::corosio::ipv4_address>
254   { 254   {
255   /// Return the hash of `addr`. 255   /// Return the hash of `addr`.
256   std::size_t 256   std::size_t
HITCBC 257   20 operator()(boost::corosio::ipv4_address const& addr) const noexcept 257   20 operator()(boost::corosio::ipv4_address const& addr) const noexcept
258   { 258   {
HITCBC 259   20 return hash<std::uint32_t>()(addr.to_uint()); 259   20 return hash<std::uint32_t>()(addr.to_uint());
260   } 260   }
261   }; 261   };
262   262  
263   } // namespace std 263   } // namespace std
264   264  
265   #endif 265   #endif