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