Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4 : //
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)
7 : //
8 : // Official repository: https://github.com/boostorg/url
9 : //
10 :
11 : #ifndef BOOST_URL_IPV4_ADDRESS_HPP
12 : #define BOOST_URL_IPV4_ADDRESS_HPP
13 :
14 : #include <boost/url/detail/config.hpp>
15 : #include <boost/url/error.hpp>
16 : #include <boost/url/error_types.hpp>
17 : #include <boost/core/detail/string_view.hpp>
18 : #include <boost/url/grammar/string_token.hpp>
19 : #include <string>
20 : #include <array>
21 : #include <cstdint>
22 : #include <iosfwd>
23 :
24 : namespace boost {
25 : namespace urls {
26 :
27 : /** An IP version 4 style address.
28 :
29 : Objects of this type are used to construct,
30 : parse, and manipulate IP version 6 addresses.
31 :
32 : @par BNF
33 : @code
34 : IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
35 :
36 : dec-octet = DIGIT ; 0-9
37 : / %x31-39 DIGIT ; 10-99
38 : / "1" 2DIGIT ; 100-199
39 : / "2" %x30-34 DIGIT ; 200-249
40 : / "25" %x30-35 ; 250-255
41 : @endcode
42 :
43 : @par Specification
44 : @li <a href="https://en.wikipedia.org/wiki/IPv4"
45 : >IPv4 (Wikipedia)</a>
46 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
47 : >3.2.2. Host (rfc3986)</a>
48 :
49 : @see
50 : @ref parse_ipv4_address,
51 : @ref ipv6_address.
52 : */
53 : class ipv4_address
54 : {
55 : public:
56 : /** The number of characters in the longest possible IPv4 string.
57 :
58 : The longest ipv4 address string is "255.255.255.255".
59 : */
60 : static
61 : constexpr
62 : std::size_t max_str_len = 15;
63 :
64 : /** The type used to represent an address as an unsigned integer
65 : */
66 : using uint_type =
67 : std::uint_least32_t;
68 :
69 : /** The type used to represent an address as an array of bytes
70 : */
71 : using bytes_type =
72 : std::array<unsigned char, 4>;
73 :
74 : /** Constructor.
75 : */
76 77 : ipv4_address() = default;
77 :
78 : /** Constructor.
79 : */
80 : ipv4_address(
81 : ipv4_address const&) = default;
82 :
83 : /** Copy Assignment.
84 : */
85 : ipv4_address&
86 : operator=(
87 : ipv4_address const&) = default;
88 :
89 : //
90 : //---
91 : //
92 :
93 : /** Construct from an unsigned integer.
94 :
95 : This function constructs an address from
96 : the unsigned integer `u`, where the most
97 : significant byte forms the first octet
98 : of the resulting address.
99 :
100 : @param u The integer to construct from.
101 : */
102 : BOOST_URL_DECL
103 : explicit
104 : ipv4_address(
105 : uint_type u) noexcept;
106 :
107 : /** Construct from an array of bytes.
108 :
109 : This function constructs an address
110 : from the array in `bytes`, which is
111 : interpreted in big-endian.
112 :
113 : @param bytes The value to construct from.
114 : */
115 : BOOST_URL_DECL
116 : explicit
117 : ipv4_address(
118 : bytes_type const& bytes) noexcept;
119 :
120 : /** Construct from a string.
121 :
122 : This function constructs an address from
123 : the string `s`, which must contain a valid
124 : IPv4 address string or else an exception
125 : is thrown.
126 :
127 : @note For a non-throwing parse function,
128 : use @ref parse_ipv4_address.
129 :
130 : @par Exception Safety
131 : Exceptions thrown on invalid input.
132 :
133 : @throw system_error
134 : The input failed to parse correctly.
135 :
136 : @param s The string to parse.
137 :
138 : @par Specification
139 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2"
140 : >3.2.2. Host (rfc3986)</a>
141 :
142 : @see
143 : @ref parse_ipv4_address.
144 : */
145 : BOOST_URL_DECL
146 : explicit
147 : ipv4_address(
148 : core::string_view s);
149 :
150 : /** Return the address as bytes, in network byte order.
151 : */
152 : BOOST_URL_DECL
153 : bytes_type
154 : to_bytes() const noexcept;
155 :
156 : /** Return the address as an unsigned integer.
157 : */
158 : BOOST_URL_DECL
159 : uint_type
160 : to_uint() const noexcept;
161 :
162 : /** Return the address as a string in dotted decimal format
163 :
164 : When called with no arguments, the
165 : return type is `std::string`.
166 : Otherwise, the return type and style
167 : of output is determined by which string
168 : token is passed.
169 :
170 : @par Example
171 : @code
172 : assert( ipv4_address(0x01020304).to_string() == "1.2.3.4" );
173 : @endcode
174 :
175 : @par Complexity
176 : Constant.
177 :
178 : @par Exception Safety
179 : Strong guarantee.
180 : Calls to allocate may throw.
181 : String tokens may throw exceptions.
182 :
183 : @return The return type of the string token.
184 : If the token parameter is omitted, then
185 : a new `std::string` is returned.
186 : Otherwise, the function return type
187 : is the result type of the token.
188 :
189 : @param token An optional string token.
190 :
191 : @par Specification
192 : @li <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.2">
193 : 2.2. Text Representation of Addresses (rfc4291)</a>
194 : */
195 : template<BOOST_URL_STRTOK_TPARAM>
196 : BOOST_URL_STRTOK_RETURN
197 2 : to_string(
198 : BOOST_URL_STRTOK_ARG(token)) const
199 : {
200 2 : to_string_impl(token);
201 2 : return token.result();
202 : }
203 :
204 : /** Write a dotted decimal string representing the address to a buffer
205 :
206 : The resulting buffer is not null-terminated.
207 :
208 : @throw std::length_error `dest_size < ipv4_address::max_str_len`
209 :
210 : @return The formatted string
211 :
212 : @param dest The buffer in which to write,
213 : which must have at least `dest_size` space.
214 :
215 : @param dest_size The size of the output buffer.
216 : */
217 : BOOST_URL_DECL
218 : core::string_view
219 : to_buffer(
220 : char* dest,
221 : std::size_t dest_size) const;
222 :
223 : /** Return true if the address is a loopback address
224 : */
225 : BOOST_URL_DECL
226 : bool
227 : is_loopback() const noexcept;
228 :
229 : /** Return true if the address is unspecified
230 : */
231 : BOOST_URL_DECL
232 : bool
233 : is_unspecified() const noexcept;
234 :
235 : /** Return true if the address is a multicast address
236 : */
237 : BOOST_URL_DECL
238 : bool
239 : is_multicast() const noexcept;
240 :
241 : /** Return true if two addresses are equal
242 : */
243 : friend
244 : bool
245 57 : operator==(
246 : ipv4_address const& a1,
247 : ipv4_address const& a2) noexcept
248 : {
249 57 : return a1.addr_ == a2.addr_;
250 : }
251 :
252 : /** Return true if two addresses are not equal
253 : */
254 : friend
255 : bool
256 3 : operator!=(
257 : ipv4_address const& a1,
258 : ipv4_address const& a2) noexcept
259 : {
260 3 : return a1.addr_ != a2.addr_;
261 : }
262 :
263 : /** Return an address object that represents any address
264 : */
265 : static
266 : ipv4_address
267 3 : any() noexcept
268 : {
269 3 : return ipv4_address();
270 : }
271 :
272 : /** Return an address object that represents the loopback address
273 : */
274 : static
275 : ipv4_address
276 3 : loopback() noexcept
277 : {
278 3 : return ipv4_address(0x7F000001);
279 : }
280 :
281 : /** Return an address object that represents the broadcast address
282 : */
283 : static
284 : ipv4_address
285 3 : broadcast() noexcept
286 : {
287 3 : return ipv4_address(0xFFFFFFFF);
288 : }
289 :
290 : // hidden friend
291 : friend
292 : std::ostream&
293 1 : operator<<(
294 : std::ostream& os,
295 : ipv4_address const& addr)
296 : {
297 : char buf[ipv4_address::max_str_len];
298 1 : os << addr.to_buffer(buf, sizeof(buf));
299 1 : return os;
300 : }
301 :
302 : private:
303 : friend class ipv6_address;
304 :
305 : BOOST_URL_DECL
306 : std::size_t
307 : print_impl(
308 : char* dest) const noexcept;
309 :
310 : BOOST_URL_DECL
311 : void
312 : to_string_impl(
313 : string_token::arg& t) const;
314 :
315 : uint_type addr_ = 0;
316 : };
317 :
318 : /** Format the address to an output stream.
319 :
320 : IPv4 addresses written to output streams
321 : are written in their dotted decimal format.
322 :
323 : @param os The output stream.
324 :
325 : @param addr The address to format.
326 : */
327 : std::ostream&
328 : operator<<(
329 : std::ostream& os,
330 : ipv4_address const& addr);
331 :
332 : //------------------------------------------------
333 :
334 : /** Return an IPv4 address from an IP address string in dotted decimal form
335 : */
336 : BOOST_URL_DECL
337 : system::result<ipv4_address>
338 : parse_ipv4_address(
339 : core::string_view s) noexcept;
340 :
341 : } // urls
342 : } // boost
343 :
344 : #endif
|