url_view.hpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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. @ref 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 @ref result containing either a valid
  40. @ref url_view upon succcess, otherwise they
  41. contain an error. The error can be converted to
  42. an exception by the caller if desired:
  43. @code
  44. 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_SYMBOL_VISIBLE 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. BOOST_URL_DECL
  121. url_view() noexcept;
  122. /** Constructor
  123. This function constructs a URL from
  124. the string `s`, which must contain a
  125. valid <em>URI</em> or <em>relative-ref</em>
  126. or else an exception is thrown. Upon
  127. successful construction, the view
  128. refers to the characters in the
  129. buffer pointed to by `s`.
  130. Ownership is not transferred; The caller
  131. is responsible for ensuring that the
  132. lifetime of the buffer extends until
  133. it is no longer referenced.
  134. @par Example
  135. @code
  136. url_view u( "http://www.example.com/index.htm" );
  137. @endcode
  138. @par Effects
  139. @code
  140. return parse_uri_reference( s ).value();
  141. @endcode
  142. @par Complexity
  143. Linear in `s.size()`.
  144. @par Exception Safety
  145. Exceptions thrown on invalid input.
  146. @throw system_error
  147. The input failed to parse correctly.
  148. @param s The string to parse.
  149. @par BNF
  150. @code
  151. URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
  152. relative-ref = relative-part [ "?" query ] [ "#" fragment ]
  153. @endcode
  154. @par Specification
  155. @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-4.1"
  156. >4.1. URI Reference</a>
  157. @see
  158. @ref parse_uri_reference.
  159. */
  160. BOOST_URL_DECL
  161. url_view(string_view s);
  162. /// @copydoc url_view(string_view)
  163. template<
  164. class String
  165. #ifndef BOOST_URL_DOCS
  166. , class = typename std::enable_if<
  167. std::is_convertible<
  168. String,
  169. string_view
  170. >::value>::type
  171. #endif
  172. >
  173. url_view(
  174. String const& s)
  175. : url_view(
  176. detail::to_sv(s))
  177. {
  178. }
  179. /** Constructor
  180. After construction, both views
  181. reference the same underlying character
  182. buffer. Ownership is not transferred.
  183. @par Postconditions
  184. @code
  185. this->buffer().data() == other.buffer().data()
  186. @endcode
  187. @par Complexity
  188. Constant.
  189. @par Exception Safety
  190. Throws nothing.
  191. */
  192. url_view(
  193. url_view const& other) noexcept
  194. : url_view(static_cast<
  195. url_view_base const&>(other))
  196. {
  197. }
  198. /** Constructor
  199. After construction, both views
  200. reference the same underlying character
  201. buffer. Ownership is not transferred.
  202. @par Postconditions
  203. @code
  204. this->buffer().data() == other.buffer().data()
  205. @endcode
  206. @par Complexity
  207. Constant.
  208. @par Exception Safety
  209. Throws nothing.
  210. */
  211. BOOST_URL_DECL
  212. url_view(
  213. url_view_base const& other) noexcept;
  214. /** Assignment
  215. After assignment, both views
  216. reference the same underlying character
  217. buffer. Ownership is not transferred.
  218. @par Postconditions
  219. @code
  220. this->buffer().data() == other.buffer().data()
  221. @endcode
  222. @par Complexity
  223. Constant.
  224. @par Exception Safety
  225. Throws nothing.
  226. */
  227. url_view&
  228. operator=(
  229. url_view const& other) noexcept
  230. {
  231. if (this != &other)
  232. *this = static_cast<
  233. url_view_base const&>(other);
  234. return *this;
  235. }
  236. /** Assignment
  237. After assignment, both views
  238. reference the same underlying character
  239. buffer. Ownership is not transferred.
  240. @par Postconditions
  241. @code
  242. this->buffer().data() == other.buffer().data()
  243. @endcode
  244. @par Complexity
  245. Constant.
  246. @par Exception Safety
  247. Throws nothing.
  248. */
  249. BOOST_URL_DECL
  250. url_view& operator=(
  251. url_view_base const& other) noexcept;
  252. //--------------------------------------------
  253. //
  254. // Observers
  255. //
  256. //--------------------------------------------
  257. /** Return the maximum number of characters possible
  258. This represents the largest number of
  259. characters that are possible in a url,
  260. not including any null terminator.
  261. @par Complexity
  262. Constant.
  263. @par Exception Safety
  264. Throws nothing.
  265. */
  266. static
  267. constexpr
  268. std::size_t
  269. max_size() noexcept
  270. {
  271. return BOOST_URL_MAX_SIZE;
  272. }
  273. };
  274. } // urls
  275. } // boost
  276. //------------------------------------------------
  277. // std::hash specialization
  278. #ifndef BOOST_URL_DOCS
  279. namespace std {
  280. template<>
  281. struct hash< ::boost::urls::url_view >
  282. {
  283. hash() = default;
  284. hash(hash const&) = default;
  285. hash& operator=(hash const&) = default;
  286. explicit
  287. hash(std::size_t salt) noexcept
  288. : salt_(salt)
  289. {
  290. }
  291. std::size_t
  292. operator()(::boost::urls::url_view const& u) const noexcept
  293. {
  294. return u.digest(salt_);
  295. }
  296. private:
  297. std::size_t salt_ = 0;
  298. };
  299. } // std
  300. #endif
  301. #endif