ipv4_address.hpp 8.7 KB

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