segments_ref.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  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_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. */
  120. /** @{ */
  121. BOOST_URL_DECL
  122. segments_ref&
  123. operator=(segments_ref const& other);
  124. BOOST_URL_DECL
  125. segments_ref&
  126. operator=(segments_view const& other);
  127. /** @} */
  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. */
  157. BOOST_URL_DECL
  158. segments_ref&
  159. operator=(std::initializer_list<
  160. core::string_view> init);
  161. /** Conversion
  162. @see
  163. @ref segments_view.
  164. */
  165. BOOST_URL_DECL
  166. operator
  167. segments_view() const noexcept;
  168. //--------------------------------------------
  169. //
  170. // Observers
  171. //
  172. //--------------------------------------------
  173. /** Return the referenced url
  174. This function returns the url referenced
  175. by the view.
  176. @par Example
  177. @code
  178. url u( "/path/to/file.txt" );
  179. assert( &u.segments().url() == &u );
  180. @endcode
  181. @par Exception Safety
  182. Throws nothing.
  183. */
  184. url_base&
  185. url() const noexcept
  186. {
  187. return *u_;
  188. }
  189. //--------------------------------------------
  190. //
  191. // Modifiers
  192. //
  193. //--------------------------------------------
  194. /** Clear the contents of the container
  195. <br>
  196. All iterators are invalidated.
  197. @par Effects
  198. @code
  199. this->url().set_encoded_path( "" );
  200. @endcode
  201. @par Postconditions
  202. @code
  203. this->empty() == true
  204. @endcode
  205. @par Complexity
  206. Linear in `this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
  207. @par Exception Safety
  208. Throws nothing.
  209. */
  210. void
  211. clear() noexcept;
  212. /** Assign segments
  213. The existing contents are replaced
  214. by a copy of the contents of the
  215. initializer list.
  216. Reserved characters in the list are
  217. automatically escaped.
  218. <br>
  219. All iterators are invalidated.
  220. @note
  221. None of the character buffers referenced
  222. by `init` may overlap the character buffer
  223. of the underlying url, or else the behavior
  224. is undefined.
  225. @par Example
  226. @code
  227. url u;
  228. u.segments().assign( { "path", "to", "file.txt" } );
  229. @endcode
  230. @par Complexity
  231. Linear in `init.size() + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
  232. @par Exception Safety
  233. Strong guarantee.
  234. Calls to allocate may throw.
  235. @param init The list of segments to assign.
  236. */
  237. BOOST_URL_DECL
  238. void
  239. assign(std::initializer_list<
  240. core::string_view> init);
  241. /** Assign segments
  242. The existing contents are replaced
  243. by a copy of the contents of the range.
  244. Reserved characters in the range are
  245. automatically escaped.
  246. <br>
  247. All iterators are invalidated.
  248. @note
  249. None of the character buffers referenced
  250. by the range may overlap the character
  251. buffer of the underlying url, or else
  252. the behavior is undefined.
  253. @par Mandates
  254. @code
  255. std::is_convertible< std::iterator_traits< FwdIt >::reference_type, core::string_view >::value == true
  256. @endcode
  257. @par Complexity
  258. Linear in `std::distance( first, last ) + this->url().encoded_query().size() + this->url().encoded_fragment().size()`.
  259. @par Exception Safety
  260. Strong guarantee.
  261. Calls to allocate may throw.
  262. @param first, last The range of segments
  263. to assign.
  264. */
  265. template<class FwdIt>
  266. void
  267. assign(FwdIt first, FwdIt last);
  268. //--------------------------------------------
  269. /** Insert segments
  270. This function inserts a segment
  271. before the specified position.
  272. Reserved characters in the segment are
  273. automatically escaped.
  274. <br>
  275. All iterators that are equal to
  276. `before` or come after are invalidated.
  277. @par Complexity
  278. Linear in `s.size() + this->url().encoded_resource().size()`.
  279. @par Exception Safety
  280. Strong guarantee.
  281. Calls to allocate may throw.
  282. @return An iterator to the inserted
  283. segment.
  284. @param before An iterator before which
  285. the segment is inserted. This may
  286. be equal to `end()`.
  287. @param s The segment to insert.
  288. */
  289. BOOST_URL_DECL
  290. iterator
  291. insert(
  292. iterator before,
  293. core::string_view s);
  294. /** Insert segments
  295. This function inserts the segments
  296. in an initializer list before the
  297. specified position.
  298. Reserved characters in the list are
  299. percent-escaped in the result.
  300. <br>
  301. All iterators that are equal to
  302. `before` or come after are invalidated.
  303. @note
  304. None of the character buffers referenced
  305. by the list may overlap the character
  306. buffer of the underlying url, or else
  307. the behavior is undefined.
  308. @par Example
  309. @code
  310. url u( "/file.txt" );
  311. u.segments().insert( u.segments().begin(), { "path", "to" } );
  312. @endcode
  313. @par Complexity
  314. Linear in `init.size() + this->url().encoded_resource().size()`.
  315. @par Exception Safety
  316. Strong guarantee.
  317. Calls to allocate may throw.
  318. @return An iterator to the first
  319. element inserted, or `before` if
  320. `init.size() == 0`.
  321. @param before An iterator before which
  322. the list is inserted. This may
  323. be equal to `end()`.
  324. @param init The list of segments to insert.
  325. */
  326. BOOST_URL_DECL
  327. iterator
  328. insert(
  329. iterator before,
  330. std::initializer_list<core::string_view> init);
  331. /** Insert segments
  332. This function inserts the segments in
  333. a range before the specified position.
  334. Reserved characters in the list are
  335. automatically escaped.
  336. <br>
  337. All iterators that are equal to
  338. `before` or come after are invalidated.
  339. @note
  340. None of the character buffers referenced
  341. by the range may overlap the character
  342. buffer of the underlying url, or else
  343. the behavior is undefined.
  344. @par Mandates
  345. @code
  346. std::is_convertible< std::iterator_traits< FwdIt >::reference_type, core::string_view >::value == true
  347. @endcode
  348. @par Complexity
  349. Linear in `std::distance( first, last ) + this->url().encoded_resource().size()`.
  350. @par Exception Safety
  351. Strong guarantee.
  352. Calls to allocate may throw.
  353. @return An iterator to the first
  354. segment inserted, or `before` if
  355. `init.empty()`.
  356. @param before An iterator before which
  357. the range is inserted. This may
  358. be equal to `end()`.
  359. @param first, last The range of segments
  360. to insert.
  361. */
  362. template<class FwdIt>
  363. iterator
  364. insert(
  365. iterator before,
  366. FwdIt first,
  367. FwdIt last);
  368. //--------------------------------------------
  369. /** Erase segments
  370. This function removes a segment.
  371. <br>
  372. All iterators that are equal to
  373. `pos` or come after are invalidated.
  374. @par Complexity
  375. Linear in `this->url().encoded_resource().size()`.
  376. @par Exception Safety
  377. Throws nothing.
  378. @return An iterator to one past
  379. the removed segment.
  380. @param pos An iterator to the segment.
  381. */
  382. iterator
  383. erase(
  384. iterator pos) noexcept;
  385. /** Erase segments
  386. This function removes a range of segments.
  387. <br>
  388. All iterators that are equal to
  389. `first` or come after are invalidated.
  390. @par Complexity
  391. Linear in `this->url().encoded_resource().size()`.
  392. @par Exception Safety
  393. Throws nothing.
  394. @return An iterator to one past
  395. the removed range.
  396. @param first, last The range of
  397. segments to erase.
  398. */
  399. BOOST_URL_DECL
  400. iterator
  401. erase(
  402. iterator first,
  403. iterator last) noexcept;
  404. //--------------------------------------------
  405. /** Replace segments
  406. This function replaces the segment at
  407. the specified position.
  408. Reserved characters in the string are
  409. automatically escaped.
  410. <br>
  411. All iterators that are equal to
  412. `pos` or come after are invalidated.
  413. @par Complexity
  414. Linear in `s.size() + this->url().encoded_resouce().size()`.
  415. @par Exception Safety
  416. Strong guarantee.
  417. Calls to allocate may throw.
  418. @return An iterator to the replaced segment.
  419. @param pos An iterator to the segment.
  420. @param s The string to assign.
  421. */
  422. BOOST_URL_DECL
  423. iterator
  424. replace(
  425. iterator pos,
  426. core::string_view s);
  427. /** Replace segments
  428. This function replaces a range of
  429. segments with one segment.
  430. Reserved characters in the string are
  431. automatically escaped.
  432. <br>
  433. All iterators that are equal to
  434. `from` or come after are invalidated.
  435. @par Complexity
  436. Linear in `s.size() + this->url().encoded_resouce().size()`.
  437. @par Exception Safety
  438. Strong guarantee.
  439. Calls to allocate may throw.
  440. @return An iterator to the new segment.
  441. @param from, to The range of segments to replace.
  442. @param s The string to assign.
  443. */
  444. BOOST_URL_DECL
  445. iterator
  446. replace(
  447. iterator from,
  448. iterator to,
  449. core::string_view s);
  450. /** Replace segments
  451. This function replaces a range of
  452. segments with a list of segments in
  453. an initializer list.
  454. Reserved characters in the list are
  455. automatically escaped.
  456. <br>
  457. All iterators that are equal to
  458. `from` or come after are invalidated.
  459. @par Preconditions
  460. None of the character buffers referenced
  461. by the list may overlap the character
  462. buffer of the underlying url, or else
  463. the behavior is undefined.
  464. @par Complexity
  465. Linear in `init.size() + this->url().encoded_resouce().size()`.
  466. @par Exception Safety
  467. Strong guarantee.
  468. Calls to allocate may throw.
  469. @return An iterator to the first
  470. segment inserted, or one past `to` if
  471. `init.size() == 0`.
  472. @param from, to The range of segments to replace.
  473. @param init The list of segments to assign.
  474. */
  475. BOOST_URL_DECL
  476. iterator
  477. replace(
  478. iterator from,
  479. iterator to,
  480. std::initializer_list<
  481. core::string_view> init);
  482. /** Replace segments
  483. This function replaces a range of
  484. segments with annother range of segments.
  485. Reserved characters in the new range are
  486. automatically escaped.
  487. <br>
  488. All iterators that are equal to
  489. `from` or come after are invalidated.
  490. @par Preconditions
  491. None of the character buffers referenced
  492. by the new range may overlap the character
  493. buffer of the underlying url, or else
  494. the behavior is undefined.
  495. @par Complexity
  496. Linear in `std::distance( first, last ) + this->url().encoded_resouce().size()`.
  497. @par Exception Safety
  498. Strong guarantee.
  499. Calls to allocate may throw.
  500. @return An iterator to the first
  501. segment inserted, or one past `to` if
  502. `init.size() == 0`.
  503. @param from, to The range of segments to replace.
  504. @param first, last The range of segments to assign.
  505. */
  506. template<class FwdIt>
  507. iterator
  508. replace(
  509. iterator from,
  510. iterator to,
  511. FwdIt first,
  512. FwdIt last);
  513. /** Append a segment
  514. This function appends a segment to
  515. the end of the path.
  516. Reserved characters in the string are
  517. automatically escaped.
  518. <br>
  519. All end iterators are invalidated.
  520. @par Postconditions
  521. @code
  522. this->back() == s
  523. @endcode
  524. @par Exception Safety
  525. Strong guarantee.
  526. Calls to allocate may throw.
  527. @param s The segment to append.
  528. */
  529. void
  530. push_back(
  531. core::string_view s);
  532. /** Remove the last segment
  533. This function removes the last segment
  534. from the container.
  535. <br>
  536. Iterators to the last segment as well
  537. as all end iterators are invalidated.
  538. @par Preconditions
  539. @code
  540. not this->empty()
  541. @endcode
  542. @par Exception Safety
  543. Throws nothing.
  544. */
  545. void
  546. pop_back() noexcept;
  547. private:
  548. template<class FwdIt>
  549. iterator
  550. insert(
  551. iterator before,
  552. FwdIt first,
  553. FwdIt last,
  554. std::input_iterator_tag) = delete;
  555. template<class FwdIt>
  556. iterator
  557. insert(
  558. iterator before,
  559. FwdIt first,
  560. FwdIt last,
  561. std::forward_iterator_tag);
  562. };
  563. } // urls
  564. } // boost
  565. // This include is at the bottom of
  566. // url_base.hpp because of a circular dependency
  567. //
  568. // #include <boost/url/impl/segments_ref.hpp>
  569. #endif