segments_encoded_ref.hpp 20 KB

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