segments_view.hpp 6.5 KB

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