url_view.hpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  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_URL_VIEW_HPP
  11. #define BOOST_URL_URL_VIEW_HPP
  12. #include <boost/url/detail/config.hpp>
  13. #include <boost/url/url_view_base.hpp>
  14. #include <utility>
  15. namespace boost {
  16. namespace urls {
  17. /** A non-owning reference to a valid URL
  18. Objects of this type represent valid URL
  19. strings constructed from a parsed, external
  20. character buffer whose storage is managed
  21. by the caller. That is, it acts like a
  22. `core::string_view` in terms of ownership.
  23. The caller is responsible for ensuring
  24. that the lifetime of the underlying
  25. character buffer extends until it is no
  26. longer referenced.
  27. @par Example 1
  28. Construction from a string parses the input
  29. as a <em>URI-reference</em> and throws an
  30. exception on error. Upon success, the
  31. constructed object points to the passed
  32. character buffer; ownership is not
  33. transferred.
  34. @code
  35. url_view u( "https://www.example.com/index.htm?text=none#a1" );
  36. @endcode
  37. @par Example 2
  38. Parsing functions like @ref parse_uri_reference
  39. return a `boost::system::result` containing either a valid
  40. @ref url_view upon success, otherwise they
  41. contain an error. The error can be converted to
  42. an exception by the caller if desired:
  43. @code
  44. system::result< url_view > rv = parse_uri_reference( "https://www.example.com/index.htm?text=none#a1" );
  45. @endcode
  46. @par BNF
  47. @code
  48. URI-reference = URI / relative-ref
  49. URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
  50. relative-ref = relative-part [ "?" query ] [ "#" fragment ]
  51. @endcode
  52. @par Specification
  53. @li <a href="https://tools.ietf.org/html/rfc3986"
  54. >Uniform Resource Identifier (URI): Generic Syntax (rfc3986)</a>
  55. @see
  56. @ref parse_absolute_uri,
  57. @ref parse_origin_form,
  58. @ref parse_relative_ref,
  59. @ref parse_uri,
  60. @ref parse_uri_reference.
  61. */
  62. class BOOST_URL_DECL url_view
  63. : public url_view_base
  64. {
  65. friend std::hash<url_view>;
  66. friend class url_view_base;
  67. friend class params_base;
  68. friend class params_encoded_base;
  69. #ifndef BOOST_URL_DOCS
  70. // VFALCO docca emits this erroneously
  71. friend struct detail::url_impl;
  72. #endif
  73. using url_view_base::digest;
  74. explicit
  75. url_view(
  76. detail::url_impl const& impl) noexcept
  77. : url_view_base(impl)
  78. {
  79. }
  80. public:
  81. //--------------------------------------------
  82. //
  83. // Special Members
  84. //
  85. //--------------------------------------------
  86. /** Destructor
  87. Any params, segments, iterators, or
  88. other views which reference the same
  89. underlying character buffer remain
  90. valid.
  91. */
  92. ~url_view() = default;
  93. /** Constructor
  94. Default constructed views refer to
  95. a string with zero length, which
  96. always remains valid. This matches
  97. the grammar for a relative-ref with
  98. an empty path and no query or
  99. fragment.
  100. @par Example
  101. @code
  102. url_view u;
  103. @endcode
  104. @par Postconditions
  105. @code
  106. this->empty() == true
  107. @endcode
  108. @par Complexity
  109. Constant.
  110. @par Exception Safety
  111. Throws nothing.
  112. @par BNF
  113. @code
  114. relative-ref = relative-part [ "?" query ] [ "#" fragment ]
  115. @endcode
  116. @par Specification
  117. <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.2"
  118. >4.2. Relative Reference (rfc3986)</a>
  119. */
  120. url_view() noexcept;
  121. /** Constructor
  122. This function constructs a URL from
  123. the string `s`, which must contain a
  124. valid <em>URI</em> or <em>relative-ref</em>
  125. or else an exception is thrown. Upon
  126. successful construction, the view
  127. refers to the characters in the
  128. buffer pointed to by `s`.
  129. Ownership is not transferred; The caller
  130. is responsible for ensuring that the
  131. lifetime of the buffer extends until
  132. it is no longer referenced.
  133. @par Example
  134. @code
  135. url_view u( "http://www.example.com/index.htm" );
  136. @endcode
  137. @par Effects
  138. @code
  139. return parse_uri_reference( s ).value();
  140. @endcode
  141. @par Complexity
  142. Linear in `s.size()`.
  143. @par Exception Safety
  144. Exceptions thrown on invalid input.
  145. @throw system_error
  146. The input failed to parse correctly.
  147. @param s The string to parse.
  148. @par BNF
  149. @code
  150. URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
  151. relative-ref = relative-part [ "?" query ] [ "#" fragment ]
  152. @endcode
  153. @par Specification
  154. @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.1"
  155. >4.1. URI Reference</a>
  156. @see
  157. @ref parse_uri_reference.
  158. */
  159. url_view(core::string_view s);
  160. /// @copydoc url_view(core::string_view)
  161. template<
  162. class String
  163. #ifndef BOOST_URL_DOCS
  164. , class = typename std::enable_if<
  165. std::is_convertible<
  166. String,
  167. core::string_view
  168. >::value &&
  169. !std::is_convertible<
  170. String*,
  171. url_view_base*
  172. >::value
  173. >::type
  174. #endif
  175. >
  176. url_view(
  177. String const& s)
  178. : url_view(
  179. detail::to_sv(s))
  180. {
  181. }
  182. /** Constructor
  183. After construction, both views
  184. reference the same underlying character
  185. buffer. Ownership is not transferred.
  186. @par Postconditions
  187. @code
  188. this->buffer().data() == other.buffer().data()
  189. @endcode
  190. @par Complexity
  191. Constant.
  192. @par Exception Safety
  193. Throws nothing.
  194. @param other The other view.
  195. */
  196. url_view(
  197. url_view const& other) noexcept
  198. : url_view(static_cast<
  199. url_view_base const&>(other))
  200. {
  201. }
  202. /** Constructor
  203. After construction, both views
  204. reference the same underlying character
  205. buffer. Ownership is not transferred.
  206. @par Postconditions
  207. @code
  208. this->buffer().data() == other.buffer().data()
  209. @endcode
  210. @par Complexity
  211. Constant.
  212. @par Exception Safety
  213. Throws nothing.
  214. @param other The other view.
  215. */
  216. url_view(
  217. url_view_base const& other) noexcept;
  218. /** Assignment
  219. After assignment, both views
  220. reference the same underlying character
  221. buffer. Ownership is not transferred.
  222. @par Postconditions
  223. @code
  224. this->buffer().data() == other.buffer().data()
  225. @endcode
  226. @par Complexity
  227. Constant.
  228. @par Exception Safety
  229. Throws nothing.
  230. @param other The other view.
  231. @return A reference to this object.
  232. */
  233. url_view&
  234. operator=(
  235. url_view const& other) noexcept
  236. {
  237. if (this != &other)
  238. *this = static_cast<
  239. url_view_base const&>(other);
  240. return *this;
  241. }
  242. /** Assignment
  243. After assignment, both views
  244. reference the same underlying character
  245. buffer. Ownership is not transferred.
  246. @par Postconditions
  247. @code
  248. this->buffer().data() == other.buffer().data()
  249. @endcode
  250. @par Complexity
  251. Constant.
  252. @par Exception Safety
  253. Throws nothing.
  254. @param other The other view.
  255. @return A reference to this object.
  256. */
  257. url_view& operator=(
  258. url_view_base const& other) noexcept;
  259. //--------------------------------------------
  260. //
  261. // Observers
  262. //
  263. //--------------------------------------------
  264. /** Return the maximum number of characters possible
  265. This represents the largest number of
  266. characters that are possible in a url,
  267. not including any null terminator.
  268. @par Complexity
  269. Constant.
  270. @par Exception Safety
  271. Throws nothing.
  272. @return The maximum number of characters possible.
  273. */
  274. static
  275. constexpr
  276. std::size_t
  277. max_size() noexcept
  278. {
  279. return BOOST_URL_MAX_SIZE;
  280. }
  281. };
  282. } // urls
  283. } // boost
  284. //------------------------------------------------
  285. // std::hash specialization
  286. #ifndef BOOST_URL_DOCS
  287. namespace std {
  288. template<>
  289. struct hash< ::boost::urls::url_view >
  290. {
  291. hash() = default;
  292. hash(hash const&) = default;
  293. hash& operator=(hash const&) = default;
  294. explicit
  295. hash(std::size_t salt) noexcept
  296. : salt_(salt)
  297. {
  298. }
  299. std::size_t
  300. operator()(::boost::urls::url_view const& u) const noexcept
  301. {
  302. return u.digest(salt_);
  303. }
  304. private:
  305. std::size_t salt_ = 0;
  306. };
  307. } // std
  308. #endif
  309. #endif