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