url_view.hpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. //
  2. // Copyright (c) 2019 Vinnie Falco ([email protected])
  3. // Copyright (c) 2022 Alan de Freitas ([email protected])
  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 @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. 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. */
  195. url_view(
  196. url_view const& other) noexcept
  197. : url_view(static_cast<
  198. url_view_base const&>(other))
  199. {
  200. }
  201. /** Constructor
  202. After construction, both views
  203. reference the same underlying character
  204. buffer. Ownership is not transferred.
  205. @par Postconditions
  206. @code
  207. this->buffer().data() == other.buffer().data()
  208. @endcode
  209. @par Complexity
  210. Constant.
  211. @par Exception Safety
  212. Throws nothing.
  213. */
  214. url_view(
  215. url_view_base const& other) noexcept;
  216. /** Assignment
  217. After assignment, both views
  218. reference the same underlying character
  219. buffer. Ownership is not transferred.
  220. @par Postconditions
  221. @code
  222. this->buffer().data() == other.buffer().data()
  223. @endcode
  224. @par Complexity
  225. Constant.
  226. @par Exception Safety
  227. Throws nothing.
  228. */
  229. url_view&
  230. operator=(
  231. url_view const& other) noexcept
  232. {
  233. if (this != &other)
  234. *this = static_cast<
  235. url_view_base const&>(other);
  236. return *this;
  237. }
  238. /** Assignment
  239. After assignment, both views
  240. reference the same underlying character
  241. buffer. Ownership is not transferred.
  242. @par Postconditions
  243. @code
  244. this->buffer().data() == other.buffer().data()
  245. @endcode
  246. @par Complexity
  247. Constant.
  248. @par Exception Safety
  249. Throws nothing.
  250. */
  251. url_view& operator=(
  252. url_view_base const& other) noexcept;
  253. //--------------------------------------------
  254. //
  255. // Observers
  256. //
  257. //--------------------------------------------
  258. /** Return the maximum number of characters possible
  259. This represents the largest number of
  260. characters that are possible in a url,
  261. not including any null terminator.
  262. @par Complexity
  263. Constant.
  264. @par Exception Safety
  265. Throws nothing.
  266. */
  267. static
  268. constexpr
  269. std::size_t
  270. max_size() noexcept
  271. {
  272. return BOOST_URL_MAX_SIZE;
  273. }
  274. };
  275. } // urls
  276. } // boost
  277. //------------------------------------------------
  278. // std::hash specialization
  279. #ifndef BOOST_URL_DOCS
  280. namespace std {
  281. template<>
  282. struct hash< ::boost::urls::url_view >
  283. {
  284. hash() = default;
  285. hash(hash const&) = default;
  286. hash& operator=(hash const&) = default;
  287. explicit
  288. hash(std::size_t salt) noexcept
  289. : salt_(salt)
  290. {
  291. }
  292. std::size_t
  293. operator()(::boost::urls::url_view const& u) const noexcept
  294. {
  295. return u.digest(salt_);
  296. }
  297. private:
  298. std::size_t salt_ = 0;
  299. };
  300. } // std
  301. #endif
  302. #endif