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