segments_ref.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  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_REF_HPP
  11. #define BOOST_URL_SEGMENTS_REF_HPP
  12. #include <boost/url/detail/config.hpp>
  13. #include <boost/url/segments_base.hpp>
  14. #include <initializer_list>
  15. #include <iterator>
  16. namespace boost {
  17. namespace urls {
  18. #ifndef BOOST_URL_DOCS
  19. class url_base;
  20. class segments_view;
  21. #endif
  22. /** A view representing path segments in a URL
  23. Objects of this type are used to interpret
  24. the path as a bidirectional view of segments,
  25. where each segment is a string with percent
  26. escapes automatically decoded.
  27. The view does not retain ownership of the
  28. elements and instead references the original
  29. character buffer. The caller is responsible
  30. for ensuring that the lifetime of the buffer
  31. extends until it is no longer referenced.
  32. The view is modifiable; calling non-const
  33. members causes changes to the referenced
  34. url.
  35. @par Example
  36. @code
  37. url u( "/path/to/file.txt" );
  38. segments_ref ps = u.segments();
  39. @endcode
  40. Percent escapes in strings returned when
  41. dereferencing iterators are automatically
  42. decoded.
  43. Reserved characters in strings supplied
  44. to modifier functions are automatically
  45. percent-escaped.
  46. @par Iterator Invalidation
  47. Changes to the underlying character buffer
  48. can invalidate iterators which reference it.
  49. Modifications made through the container
  50. invalidate some or all iterators:
  51. <br>
  52. @li @ref push_back : Only `end()`.
  53. @li @ref assign, @ref clear,
  54. @ref operator= : All elements.
  55. @li @ref erase : Erased elements and all
  56. elements after (including `end()`).
  57. @li @ref insert : All elements at or after
  58. the insertion point (including `end()`).
  59. @li @ref replace : Modified
  60. elements and all elements
  61. after (including `end()`).
  62. @see
  63. @ref segments_encoded_ref,
  64. @ref segments_encoded_view,
  65. @ref segments_view.
  66. */
  67. class segments_ref
  68. : public segments_base
  69. {
  70. url_base* u_ = nullptr;
  71. friend class url_base;
  72. friend class segments_encoded_ref;
  73. segments_ref(url_base& u) noexcept;
  74. public:
  75. //--------------------------------------------
  76. //
  77. // Special Members
  78. //
  79. //--------------------------------------------
  80. /** Constructor
  81. After construction, both views
  82. reference the same url. Ownership is not
  83. transferred; the caller is responsible
  84. for ensuring the lifetime of the url
  85. extends until it is no longer
  86. referenced.
  87. @par Postconditions
  88. @code
  89. &this->url() == &other.url();
  90. @endcode
  91. @par Complexity
  92. Constant.
  93. @par Exception Safety
  94. Throws nothing.
  95. @param other The other view.
  96. */
  97. segments_ref(
  98. segments_ref const& other) = default;
  99. /** Assignment
  100. The existing contents are replaced
  101. by a copy of the other segments.
  102. <br>
  103. All iterators are invalidated.
  104. @note
  105. None of the character buffers referenced
  106. by `other` may overlap the buffer of the
  107. underlying url, or else the behavior
  108. is undefined.
  109. @par Effects
  110. @code
  111. this->assign( other.begin(), other.end() );
  112. @endcode
  113. @par Complexity
  114. Linear in `other.buffer().size()`.
  115. @par Exception Safety
  116. Strong guarantee.
  117. Calls to allocate may throw.
  118. @param other The segments to assign.
  119. @return A reference to this object.
  120. */
  121. BOOST_URL_DECL
  122. segments_ref&
  123. operator=(segments_ref const& other);
  124. /// @copydoc segments_ref::operator=(segments_ref const&)
  125. BOOST_URL_DECL
  126. segments_ref&
  127. operator=(segments_view const& other);
  128. /** Assignment
  129. The existing contents are replaced
  130. by a copy of the contents of the
  131. initializer list.
  132. Reserved characters in the list are
  133. automatically escaped.
  134. <br>
  135. All iterators are invalidated.
  136. @par Example
  137. @code
  138. url u;
  139. u.segments() = { "path", "to", "file.txt" };
  140. @endcode
  141. @par Preconditions
  142. None of the character buffers referenced
  143. by the list may overlap the character
  144. buffer of the underlying url, or else
  145. the behavior is undefined.
  146. @par Effects
  147. @code
  148. this->assign( init.begin(), init.end() );
  149. @endcode
  150. @par Complexity
  151. Linear in `init.size() + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
  152. @par Exception Safety
  153. Strong guarantee.
  154. Calls to allocate may throw.
  155. @param init The list of segments to assign.
  156. @return A reference to this object.
  157. */
  158. BOOST_URL_DECL
  159. segments_ref&
  160. operator=(std::initializer_list<
  161. core::string_view> init);
  162. /** Conversion
  163. @see
  164. @ref segments_view.
  165. @return A view of the segments.
  166. */
  167. BOOST_URL_DECL
  168. operator
  169. segments_view() const noexcept;
  170. //--------------------------------------------
  171. //
  172. // Observers
  173. //
  174. //--------------------------------------------
  175. /** Return the referenced url
  176. This function returns the url referenced
  177. by the view.
  178. @par Example
  179. @code
  180. url u( "/path/to/file.txt" );
  181. assert( &u.segments().url() == &u );
  182. @endcode
  183. @par Exception Safety
  184. Throws nothing.
  185. @return A reference to the url.
  186. */
  187. url_base&
  188. url() const noexcept
  189. {
  190. return *u_;
  191. }
  192. //--------------------------------------------
  193. //
  194. // Modifiers
  195. //
  196. //--------------------------------------------
  197. /** Clear the contents of the container
  198. <br>
  199. All iterators are invalidated.
  200. @par Effects
  201. @code
  202. this->url().set_encoded_path( "" );
  203. @endcode
  204. @par Postconditions
  205. @code
  206. this->empty() == true
  207. @endcode
  208. @par Complexity
  209. Linear in `this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
  210. @par Exception Safety
  211. Throws nothing.
  212. */
  213. void
  214. clear() noexcept;
  215. /** Assign segments
  216. The existing contents are replaced
  217. by a copy of the contents of the
  218. initializer list.
  219. Reserved characters in the list are
  220. automatically escaped.
  221. <br>
  222. All iterators are invalidated.
  223. @note
  224. None of the character buffers referenced
  225. by `init` may overlap the character buffer
  226. of the underlying url, or else the behavior
  227. is undefined.
  228. @par Example
  229. @code
  230. url u;
  231. u.segments().assign( { "path", "to", "file.txt" } );
  232. @endcode
  233. @par Complexity
  234. Linear in `init.size() + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
  235. @par Exception Safety
  236. Strong guarantee.
  237. Calls to allocate may throw.
  238. @param init The list of segments to assign.
  239. */
  240. BOOST_URL_DECL
  241. void
  242. assign(std::initializer_list<
  243. core::string_view> init);
  244. /** Assign segments
  245. The existing contents are replaced
  246. by a copy of the contents of the range.
  247. Reserved characters in the range are
  248. automatically escaped.
  249. <br>
  250. All iterators are invalidated.
  251. @note
  252. None of the character buffers referenced
  253. by the range may overlap the character
  254. buffer of the underlying url, or else
  255. the behavior is undefined.
  256. @par Mandates
  257. @code
  258. std::is_convertible< std::iterator_traits< FwdIt >::reference_type, core::string_view >::value == true
  259. @endcode
  260. @par Complexity
  261. Linear in `std::distance( first, last ) + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
  262. @par Exception Safety
  263. Strong guarantee.
  264. Calls to allocate may throw.
  265. @param first The beginning of the range of segments to assign.
  266. @param last The end of the range of segments to assign.
  267. */
  268. template<class FwdIt>
  269. void
  270. assign(FwdIt first, FwdIt last);
  271. //--------------------------------------------
  272. /** Insert segments
  273. This function inserts a segment
  274. before the specified position.
  275. Reserved characters in the segment are
  276. automatically escaped.
  277. <br>
  278. All iterators that are equal to
  279. `before` or come after are invalidated.
  280. @par Complexity
  281. Linear in `s.size() + this->url().encoded_resource().size()`.
  282. @par Exception Safety
  283. Strong guarantee.
  284. Calls to allocate may throw.
  285. @return An iterator to the inserted
  286. segment.
  287. @param before An iterator before which
  288. the segment is inserted. This may
  289. be equal to `end()`.
  290. @param s The segment to insert.
  291. */
  292. BOOST_URL_DECL
  293. iterator
  294. insert(
  295. iterator before,
  296. core::string_view s);
  297. /** Insert segments
  298. This function inserts the segments
  299. in an initializer list before the
  300. specified position.
  301. Reserved characters in the list are
  302. percent-escaped in the result.
  303. <br>
  304. All iterators that are equal to
  305. `before` or come after are invalidated.
  306. @note
  307. None of the character buffers referenced
  308. by the list may overlap the character
  309. buffer of the underlying url, or else
  310. the behavior is undefined.
  311. @par Example
  312. @code
  313. url u( "/file.txt" );
  314. u.segments().insert( u.segments().begin(), { "path", "to" } );
  315. @endcode
  316. @par Complexity
  317. Linear in `init.size() + this->url().encoded_resource().size()`.
  318. @par Exception Safety
  319. Strong guarantee.
  320. Calls to allocate may throw.
  321. @return An iterator to the first
  322. element inserted, or `before` if
  323. `init.size() == 0`.
  324. @param before An iterator before which
  325. the list is inserted. This may
  326. be equal to `end()`.
  327. @param init The list of segments to insert.
  328. */
  329. BOOST_URL_DECL
  330. iterator
  331. insert(
  332. iterator before,
  333. std::initializer_list<core::string_view> init);
  334. /** Insert segments
  335. This function inserts the segments in
  336. a range before the specified position.
  337. Reserved characters in the list are
  338. automatically escaped.
  339. <br>
  340. All iterators that are equal to
  341. `before` or come after are invalidated.
  342. @note
  343. None of the character buffers referenced
  344. by the range may overlap the character
  345. buffer of the underlying url, or else
  346. the behavior is undefined.
  347. @par Mandates
  348. @code
  349. std::is_convertible< std::iterator_traits< FwdIt >::reference_type, core::string_view >::value == true
  350. @endcode
  351. @par Complexity
  352. Linear in `std::distance( first, last ) + this->url().encoded_resource().size()`.
  353. @par Exception Safety
  354. Strong guarantee.
  355. Calls to allocate may throw.
  356. @return An iterator to the first
  357. segment inserted, or `before` if
  358. `init.empty()`.
  359. @param before An iterator before which
  360. the range is inserted. This may
  361. be equal to `end()`.
  362. @param first The beginning of the range of segments to insert.
  363. @param last The end of the range of segments to insert.
  364. */
  365. template<class FwdIt>
  366. iterator
  367. insert(
  368. iterator before,
  369. FwdIt first,
  370. FwdIt last);
  371. //--------------------------------------------
  372. /** Erase segments
  373. This function removes a segment.
  374. <br>
  375. All iterators that are equal to
  376. `pos` or come after are invalidated.
  377. @par Complexity
  378. Linear in `this->url().encoded_resource().size()`.
  379. @par Exception Safety
  380. Throws nothing.
  381. @return An iterator to one past
  382. the removed segment.
  383. @param pos An iterator to the segment.
  384. */
  385. iterator
  386. erase(
  387. iterator pos) noexcept;
  388. /** Erase segments
  389. This function removes a range of segments.
  390. <br>
  391. All iterators that are equal to
  392. `first` or come after are invalidated.
  393. @par Complexity
  394. Linear in `this->url().encoded_resource().size()`.
  395. @par Exception Safety
  396. Throws nothing.
  397. @return An iterator to one past
  398. the removed range.
  399. @param first The beginning of the range to remove.
  400. @param last The end of the range to remove.
  401. */
  402. BOOST_URL_DECL
  403. iterator
  404. erase(
  405. iterator first,
  406. iterator last) noexcept;
  407. //--------------------------------------------
  408. /** Replace segments
  409. This function replaces the segment at
  410. the specified position.
  411. Reserved characters in the string are
  412. automatically escaped.
  413. <br>
  414. All iterators that are equal to
  415. `pos` or come after are invalidated.
  416. @par Complexity
  417. Linear in `s.size() + this->url().encoded_resouce().size()`.
  418. @par Exception Safety
  419. Strong guarantee.
  420. Calls to allocate may throw.
  421. @return An iterator to the replaced segment.
  422. @param pos An iterator to the segment.
  423. @param s The string to assign.
  424. */
  425. BOOST_URL_DECL
  426. iterator
  427. replace(
  428. iterator pos,
  429. core::string_view s);
  430. /** Replace segments
  431. This function replaces a range of
  432. segments with one segment.
  433. Reserved characters in the string are
  434. automatically escaped.
  435. <br>
  436. All iterators that are equal to
  437. `from` or come after are invalidated.
  438. @par Complexity
  439. Linear in `s.size() + this->url().encoded_resouce().size()`.
  440. @par Exception Safety
  441. Strong guarantee.
  442. Calls to allocate may throw.
  443. @return An iterator to the new segment.
  444. @param from The beginning of the range of segments to replace.
  445. @param to The end of the range of segments to replace.
  446. @param s The string to assign.
  447. */
  448. BOOST_URL_DECL
  449. iterator
  450. replace(
  451. iterator from,
  452. iterator to,
  453. core::string_view s);
  454. /** Replace segments
  455. This function replaces a range of
  456. segments with a list of segments in
  457. an initializer list.
  458. Reserved characters in the list are
  459. automatically escaped.
  460. <br>
  461. All iterators that are equal to
  462. `from` or come after are invalidated.
  463. @par Preconditions
  464. None of the character buffers referenced
  465. by the list may overlap the character
  466. buffer of the underlying url, or else
  467. the behavior is undefined.
  468. @par Complexity
  469. Linear in `init.size() + this->url().encoded_resouce().size()`.
  470. @par Exception Safety
  471. Strong guarantee.
  472. Calls to allocate may throw.
  473. @return An iterator to the first
  474. segment inserted, or one past `to` if
  475. `init.size() == 0`.
  476. @param from The beginning of the range of segments to replace.
  477. @param to The end of the range of segments to replace.
  478. @param init The list of segments to assign.
  479. */
  480. BOOST_URL_DECL
  481. iterator
  482. replace(
  483. iterator from,
  484. iterator to,
  485. std::initializer_list<
  486. core::string_view> init);
  487. /** Replace segments
  488. This function replaces a range of
  489. segments with annother range of segments.
  490. Reserved characters in the new range are
  491. automatically escaped.
  492. <br>
  493. All iterators that are equal to
  494. `from` or come after are invalidated.
  495. @par Preconditions
  496. None of the character buffers referenced
  497. by the new range may overlap the character
  498. buffer of the underlying url, or else
  499. the behavior is undefined.
  500. @par Complexity
  501. Linear in `std::distance( first, last ) + this->url().encoded_resouce().size()`.
  502. @par Exception Safety
  503. Strong guarantee.
  504. Calls to allocate may throw.
  505. @return An iterator to the first
  506. segment inserted, or one past `to` if
  507. `init.size() == 0`.
  508. @param from The beginning of the range of segments to replace.
  509. @param to The end of the range of segments to replace.
  510. @param first The beginning of the range of segments to assign.
  511. @param last The end of the range of segments to assign.
  512. */
  513. template<class FwdIt>
  514. iterator
  515. replace(
  516. iterator from,
  517. iterator to,
  518. FwdIt first,
  519. FwdIt last);
  520. /** Append a segment
  521. This function appends a segment to
  522. the end of the path.
  523. Reserved characters in the string are
  524. automatically escaped.
  525. <br>
  526. All end iterators are invalidated.
  527. @par Postconditions
  528. @code
  529. this->back() == s
  530. @endcode
  531. @par Exception Safety
  532. Strong guarantee.
  533. Calls to allocate may throw.
  534. @param s The segment to append.
  535. */
  536. void
  537. push_back(
  538. core::string_view s);
  539. /** Remove the last segment
  540. This function removes the last segment
  541. from the container.
  542. <br>
  543. Iterators to the last segment as well
  544. as all end iterators are invalidated.
  545. @par Preconditions
  546. @code
  547. not this->empty()
  548. @endcode
  549. @par Exception Safety
  550. Throws nothing.
  551. */
  552. void
  553. pop_back() noexcept;
  554. private:
  555. template<class FwdIt>
  556. iterator
  557. insert(
  558. iterator before,
  559. FwdIt first,
  560. FwdIt last,
  561. std::input_iterator_tag) = delete;
  562. template<class FwdIt>
  563. iterator
  564. insert(
  565. iterator before,
  566. FwdIt first,
  567. FwdIt last,
  568. std::forward_iterator_tag);
  569. };
  570. } // urls
  571. } // boost
  572. // This include is at the bottom of
  573. // url_base.hpp because of a circular dependency
  574. //
  575. // #include <boost/url/impl/segments_ref.hpp>
  576. #endif