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