segments_encoded_view.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  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_SEGMENTS_ENCODED_VIEW_HPP
  11. #define BOOST_URL_SEGMENTS_ENCODED_VIEW_HPP
  12. #include <boost/url/detail/config.hpp>
  13. #include <boost/url/error_types.hpp>
  14. #include <boost/url/segments_encoded_base.hpp>
  15. #include <boost/url/segments_view.hpp>
  16. #include <boost/core/detail/string_view.hpp>
  17. #include <iosfwd>
  18. #include <utility>
  19. namespace boost {
  20. namespace urls {
  21. /** A view representing path segments in a URL
  22. Objects of this type are used to interpret
  23. the path as a bidirectional view of segment
  24. strings.
  25. The view does not retain ownership of the
  26. elements and instead references the original
  27. character buffer. The caller is responsible
  28. for ensuring that the lifetime of the buffer
  29. extends until it is no longer referenced.
  30. @par Example
  31. @code
  32. url_view u( "/path/to/file.txt" );
  33. segments_encoded_view ps = u.encoded_segments();
  34. assert( ps.buffer().data() == u.buffer().data() );
  35. @endcode
  36. Strings produced when elements are returned
  37. have type @ref param_pct_view and represent
  38. encoded strings. Strings passed to member
  39. functions may contain percent escapes, and
  40. throw exceptions on invalid inputs.
  41. @par Iterator Invalidation
  42. Changes to the underlying character buffer
  43. can invalidate iterators which reference it.
  44. @see
  45. @ref segments_view,
  46. @ref segments_encoded_ref,
  47. @ref segments_ref.
  48. */
  49. class segments_encoded_view
  50. : public segments_encoded_base
  51. {
  52. friend class url_view_base;
  53. friend class segments_encoded_ref;
  54. segments_encoded_view(
  55. detail::path_ref const& ref) noexcept;
  56. public:
  57. /** Constructor
  58. Default-constructed segments have
  59. zero elements.
  60. @par Example
  61. @code
  62. segments_encoded_view ps;
  63. @endcode
  64. @par Effects
  65. @code
  66. return segments_encoded_view( "" );
  67. @endcode
  68. @par Complexity
  69. Constant.
  70. @par Exception Safety
  71. Throws nothing.
  72. */
  73. segments_encoded_view() = default;
  74. /** Constructor
  75. After construction, both views
  76. reference the same character buffer.
  77. Ownership is not transferred; the caller
  78. is responsible for ensuring the lifetime
  79. of the buffer extends until it is no
  80. longer referenced.
  81. @par Postconditions
  82. @code
  83. this->buffer().data() == other.buffer().data()
  84. @endcode
  85. @par Complexity
  86. Constant.
  87. @par Exception Safety
  88. Throws nothing
  89. */
  90. segments_encoded_view(
  91. segments_encoded_view const&) noexcept = default;
  92. /** Constructor
  93. This function constructs segments from
  94. a valid path string, which can contain
  95. percent escapes.
  96. Upon construction, the view references
  97. the character buffer pointed to by `s`.
  98. caller is responsible for ensuring
  99. that the lifetime of the buffer
  100. extends until the view is destroyed.
  101. @par Example
  102. @code
  103. segments_encoded_view ps( "/path/to/file.txt" );
  104. @endcode
  105. @par Effects
  106. @code
  107. return parse_path( s ).value();
  108. @endcode
  109. @par Postconditions
  110. @code
  111. this->buffer().data() == s.data()
  112. @endcode
  113. @par Complexity
  114. Linear in `s`.
  115. @par Exception Safety
  116. Exceptions thrown on invalid input.
  117. @throw system_error
  118. `s` contains an invalid path.
  119. @param s The string to parse.
  120. @par BNF
  121. @code
  122. path = [ "/" ] [ segment *( "/" segment ) ]
  123. segment = *pchar
  124. @endcode
  125. @par Specification
  126. @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.3"
  127. >3.3. Path</a>
  128. */
  129. BOOST_URL_DECL
  130. segments_encoded_view(
  131. core::string_view s);
  132. /** Constructor
  133. This function creates a new @ref segments_encoded_view
  134. from a pair of iterators referring to
  135. elements of another encoded segments
  136. view. The resulting view references
  137. the same underlying character buffer
  138. as the original.
  139. The constructed view preserves the
  140. original absolute flag when `first`
  141. selects the first segment and otherwise
  142. produces an absolute subview: if the
  143. source path is relative and `first ==
  144. ps.begin()` the new view is relative,
  145. and in every other case the subview is
  146. absolute with the separator immediately
  147. preceding `*first` retained at the front.
  148. This ensures the underlying text can be
  149. reconstructed by concatenating the buffers
  150. of adjacent subviews.
  151. The caller is responsible for ensuring
  152. that the lifetime of the original buffer
  153. extends until the constructed view
  154. is no longer referenced.
  155. @par Example
  156. @code
  157. segments_encoded_view ps( "/path/to/file.txt" );
  158. segments_encoded_view sub(
  159. std::next(ps.begin()),
  160. ps.end());
  161. segments_encoded_view first_half(
  162. ps.begin(),
  163. std::next(ps.begin()));
  164. // sub represents "/to/file.txt"
  165. std::string combined(
  166. first_half.buffer().data(),
  167. first_half.buffer().size());
  168. combined.append(
  169. sub.buffer().data(),
  170. sub.buffer().size());
  171. BOOST_ASSERT(combined == ps.buffer());
  172. @endcode
  173. @par Preconditions
  174. The iterators must be valid and belong to
  175. the same @ref segments_encoded_view.
  176. @par Postconditions
  177. `sub.buffer()` references characters in the
  178. original `ps.buffer()`.
  179. @par Complexity
  180. Constant
  181. @par Exception Safety
  182. Throws nothing.
  183. @param first The beginning iterator.
  184. @param last The ending iterator.
  185. */
  186. BOOST_URL_DECL
  187. segments_encoded_view(
  188. iterator first,
  189. iterator last) noexcept;
  190. /** Assignment
  191. After assignment, both views
  192. reference the same underlying character
  193. buffer.
  194. Ownership is not transferred; the caller
  195. is responsible for ensuring the lifetime
  196. of the buffer extends until it is no
  197. longer referenced.
  198. @par Postconditions
  199. @code
  200. this->buffer().data() == other.buffer().data()
  201. @endcode
  202. @par Complexity
  203. Constant
  204. @par Exception Safety
  205. Throws nothing
  206. @param other The segments to copy.
  207. @return Reference to this object
  208. */
  209. segments_encoded_view&
  210. operator=(
  211. segments_encoded_view const& other) = default;
  212. /** Conversion
  213. This conversion returns a new view which
  214. references the same underlying character
  215. buffer, and whose iterators and members
  216. return ordinary strings with decoding
  217. applied to any percent escapes.
  218. Ownership is not transferred; the caller
  219. is responsible for ensuring the lifetime
  220. of the buffer extends until it is no
  221. longer referenced.
  222. @par Example
  223. @code
  224. segments_view ps = parse_path( "/path/to/file.txt" ).value();
  225. @endcode
  226. @par Postconditions
  227. @code
  228. segments_view( *this ).buffer().data() == this->buffer().data()
  229. @endcode
  230. @par Complexity
  231. Constant
  232. @par Exception Safety
  233. Throws nothing
  234. @return A view of the segments.
  235. */
  236. BOOST_URL_DECL
  237. operator
  238. segments_view() const noexcept;
  239. //--------------------------------------------
  240. BOOST_URL_DECL
  241. friend
  242. system::result<segments_encoded_view>
  243. parse_path(core::string_view s) noexcept;
  244. };
  245. } // urls
  246. } // boost
  247. #endif