decode_view.hpp 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078
  1. //
  2. // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/url
  8. //
  9. #ifndef BOOST_URL_DECODE_VIEW_HPP
  10. #define BOOST_URL_DECODE_VIEW_HPP
  11. #include <boost/url/detail/config.hpp>
  12. #include <boost/core/detail/string_view.hpp>
  13. #include <boost/url/encoding_opts.hpp>
  14. #include <boost/url/pct_string_view.hpp>
  15. #include <type_traits>
  16. #include <iterator>
  17. #include <iosfwd>
  18. namespace boost {
  19. namespace urls {
  20. //------------------------------------------------
  21. class decode_view;
  22. namespace detail {
  23. // unchecked
  24. template<class... Args>
  25. decode_view
  26. make_decode_view(
  27. Args&&... args) noexcept;
  28. } // detail
  29. //------------------------------------------------
  30. /** A reference to a valid, percent-encoded string
  31. These views reference strings in parts of URLs
  32. or other components that are percent-encoded.
  33. The special characters (those not in the
  34. allowed character set) are stored as three
  35. character escapes that consist of a percent
  36. sign ('%%') followed by a two-digit hexadecimal
  37. number of the corresponding unescaped character
  38. code, which may be part of a UTF-8 code point
  39. depending on the context.
  40. The view refers to the original character
  41. buffer and only decodes escaped sequences when
  42. needed. In particular these operations perform
  43. percent-decoding automatically without the
  44. need to allocate memory:
  45. @li Iteration of the string
  46. @li Accessing the encoded character buffer
  47. @li Comparison to encoded or plain strings
  48. These objects can only be constructed from
  49. strings that have a valid percent-encoding,
  50. otherwise construction fails. The caller is
  51. responsible for ensuring that the lifetime
  52. of the character buffer from which the view
  53. is constructed extends unmodified until the
  54. view is no longer accessed.
  55. */
  56. class decode_view
  57. {
  58. char const* p_ = nullptr;
  59. std::size_t n_ = 0;
  60. std::size_t dn_ = 0;
  61. bool space_as_plus_ = true;
  62. template<class... Args>
  63. friend
  64. decode_view
  65. detail::make_decode_view(
  66. Args&&... args) noexcept;
  67. // unchecked
  68. BOOST_CXX14_CONSTEXPR
  69. explicit
  70. decode_view(
  71. core::string_view s,
  72. std::size_t n,
  73. encoding_opts opt) noexcept
  74. : p_(s.data())
  75. , n_(s.size())
  76. , dn_(n)
  77. , space_as_plus_(
  78. opt.space_as_plus)
  79. {}
  80. public:
  81. /** The value type
  82. */
  83. using value_type = char;
  84. /** The reference type
  85. */
  86. using reference = char;
  87. /// @copydoc reference
  88. using const_reference = char;
  89. /** The unsigned integer type
  90. */
  91. using size_type = std::size_t;
  92. /** The signed integer type
  93. */
  94. using difference_type = std::ptrdiff_t;
  95. /** An iterator of constant, decoded characters.
  96. This iterator is used to access the encoded
  97. string as a *bidirectional* range of characters
  98. with percent-decoding applied. Escape sequences
  99. are not decoded until the iterator is
  100. dereferenced.
  101. */
  102. class iterator;
  103. /// @copydoc iterator
  104. using const_iterator = iterator;
  105. //--------------------------------------------
  106. //
  107. // Special Members
  108. //
  109. //--------------------------------------------
  110. /** Constructor
  111. Default-constructed views represent
  112. empty strings.
  113. @par Example
  114. @code
  115. decode_view ds;
  116. @endcode
  117. @par Postconditions
  118. @code
  119. this->empty() == true
  120. @endcode
  121. @par Complexity
  122. Constant.
  123. @par Exception Safety
  124. Throws nothing.
  125. */
  126. BOOST_CXX14_CONSTEXPR
  127. decode_view() noexcept = default;
  128. /** Constructor
  129. This constructs a view from the character
  130. buffer `s`, which must remain valid and
  131. unmodified until the view is no longer
  132. accessed.
  133. @par Example
  134. @code
  135. decode_view ds( "Program%20Files" );
  136. @endcode
  137. @par Postconditions
  138. @code
  139. this->encoded() == s
  140. @endcode
  141. @par Complexity
  142. Linear in `s.size()`.
  143. @par Exception Safety
  144. Although this function does not throw exceptions,
  145. implicitly constructing a @ref pct_string_view
  146. for the first argument can throw exceptions
  147. on invalid input.
  148. @param s A percent-encoded string that has
  149. already been validated. Implicit conversion
  150. from other string types is supported but
  151. may throw exceptions.
  152. @param opt The options for decoding. If
  153. this parameter is omitted, the default
  154. options are used.
  155. */
  156. BOOST_CXX14_CONSTEXPR
  157. explicit
  158. decode_view(
  159. pct_string_view s,
  160. encoding_opts opt = {}) noexcept
  161. : decode_view(
  162. detail::to_sv(s),
  163. s.decoded_size(),
  164. opt)
  165. {
  166. }
  167. //--------------------------------------------
  168. //
  169. // Observers
  170. //
  171. //--------------------------------------------
  172. /** Return true if the string is empty
  173. @par Example
  174. @code
  175. assert( decode_view( "" ).empty() );
  176. @endcode
  177. @par Complexity
  178. Constant.
  179. @par Exception Safety
  180. Throws nothing.
  181. @return `true` if the string is empty
  182. */
  183. bool
  184. empty() const noexcept
  185. {
  186. return n_ == 0;
  187. }
  188. /** Return the number of decoded characters
  189. @par Example
  190. @code
  191. assert( decode_view( "Program%20Files" ).size() == 13 );
  192. @endcode
  193. @par Effects
  194. @code
  195. return std::distance( this->begin(), this->end() );
  196. @endcode
  197. @par Complexity
  198. Constant.
  199. @par Exception Safety
  200. Throws nothing.
  201. @return The number of decoded characters
  202. */
  203. size_type
  204. size() const noexcept
  205. {
  206. return dn_;
  207. }
  208. /** Return an iterator to the beginning
  209. @par Example
  210. @code
  211. auto it = this->begin();
  212. @endcode
  213. @par Complexity
  214. Constant.
  215. @par Exception Safety
  216. Throws nothing.
  217. @return An iterator to the first decoded character
  218. */
  219. iterator
  220. begin() const noexcept;
  221. /** Return an iterator to the end
  222. @par Example
  223. @code
  224. auto it = this->end();
  225. @endcode
  226. @par Complexity
  227. Constant.
  228. @par Exception Safety
  229. Throws nothing.
  230. @return An iterator to one past the last decoded character
  231. */
  232. iterator
  233. end() const noexcept;
  234. /** Return the first character
  235. @par Example
  236. @code
  237. assert( decode_view( "Program%20Files" ).front() == 'P' );
  238. @endcode
  239. @par Preconditions
  240. @code
  241. not this->empty()
  242. @endcode
  243. @par Complexity
  244. Constant.
  245. @par Exception Safety
  246. Throws nothing.
  247. @return The first decoded character
  248. */
  249. reference
  250. front() const noexcept;
  251. /** Return the last character
  252. @par Example
  253. @code
  254. assert( decode_view( "Program%20Files" ).back() == 's' );
  255. @endcode
  256. @par Preconditions
  257. @code
  258. not this->empty()
  259. @endcode
  260. @par Complexity
  261. Constant.
  262. @par Exception Safety
  263. Throws nothing.
  264. @return The last decoded character
  265. */
  266. reference
  267. back() const noexcept;
  268. /** Checks if the string begins with the given prefix
  269. @par Example
  270. @code
  271. assert( decode_view( "Program%20Files" ).starts_with("Program") );
  272. @endcode
  273. @par Complexity
  274. Linear.
  275. @par Exception Safety
  276. Throws nothing.
  277. @param s The string to search for
  278. @return `true` if the decoded string starts with `s`
  279. */
  280. BOOST_URL_DECL
  281. bool
  282. starts_with( core::string_view s ) const noexcept;
  283. /** Checks if the string ends with the given prefix
  284. @par Example
  285. @code
  286. assert( decode_view( "Program%20Files" ).ends_with("Files") );
  287. @endcode
  288. @par Complexity
  289. Linear.
  290. @par Exception Safety
  291. Throws nothing.
  292. @param s The string to search for
  293. @return `true` if the decoded string ends with `s`
  294. */
  295. BOOST_URL_DECL
  296. bool
  297. ends_with( core::string_view s ) const noexcept;
  298. /** Checks if the string begins with the given prefix
  299. @par Example
  300. @code
  301. assert( decode_view( "Program%20Files" ).starts_with('P') );
  302. @endcode
  303. @par Complexity
  304. Constant.
  305. @par Exception Safety
  306. Throws nothing.
  307. @param ch The character to search for
  308. @return `true` if the decoded string starts with `ch`
  309. */
  310. BOOST_URL_DECL
  311. bool
  312. starts_with( char ch ) const noexcept;
  313. /** Checks if the string ends with the given prefix
  314. @par Example
  315. @code
  316. assert( decode_view( "Program%20Files" ).ends_with('s') );
  317. @endcode
  318. @par Complexity
  319. Constant.
  320. @par Exception Safety
  321. Throws nothing.
  322. @param ch The character to search for
  323. @return `true` if the decoded string ends with `ch`
  324. */
  325. BOOST_URL_DECL
  326. bool
  327. ends_with( char ch ) const noexcept;
  328. /** Finds the first occurrence of character in this view
  329. @par Complexity
  330. Linear.
  331. @par Exception Safety
  332. Throws nothing.
  333. @param ch The character to search for
  334. @return An iterator to the first decoded occurrence of `ch` or `end()`
  335. */
  336. BOOST_URL_DECL
  337. const_iterator
  338. find( char ch ) const noexcept;
  339. /** Finds the first occurrence of character in this view
  340. @par Complexity
  341. Linear.
  342. @par Exception Safety
  343. Throws nothing.
  344. @param ch The character to search for
  345. @return An iterator to the last occurrence of `ch` or `end()`
  346. */
  347. BOOST_URL_DECL
  348. const_iterator
  349. rfind( char ch ) const noexcept;
  350. /** Remove the first characters
  351. @par Example
  352. @code
  353. decode_view d( "Program%20Files" );
  354. d.remove_prefix( 8 );
  355. assert( d == "Files" );
  356. @endcode
  357. @par Preconditions
  358. @code
  359. not this->empty()
  360. @endcode
  361. @par Complexity
  362. Linear.
  363. @param n The number of characters to remove
  364. */
  365. BOOST_URL_DECL
  366. void
  367. remove_prefix( size_type n );
  368. /** Remove the last characters
  369. @par Example
  370. @code
  371. decode_view d( "Program%20Files" );
  372. d.remove_prefix( 6 );
  373. assert( d == "Program" );
  374. @endcode
  375. @par Preconditions
  376. @code
  377. not this->empty()
  378. @endcode
  379. @par Complexity
  380. Linear.
  381. @param n The number of characters to remove
  382. */
  383. BOOST_URL_DECL
  384. void
  385. remove_suffix( size_type n );
  386. /** Return the decoding options
  387. @return The decoding options used by this view
  388. */
  389. encoding_opts
  390. options() const noexcept
  391. {
  392. encoding_opts opt;
  393. opt.space_as_plus = space_as_plus_;
  394. return opt;
  395. }
  396. //--------------------------------------------
  397. //
  398. // Comparison
  399. //
  400. //--------------------------------------------
  401. /** Return the result of comparing to another string
  402. The length of the sequences to compare is the smaller of
  403. `size()` and `other.size()`.
  404. The function compares the two strings as if by calling
  405. `char_traits<char>::compare(to_string().data(), v.data(), rlen)`.
  406. This means the comparison is performed with
  407. percent-decoding applied to the current string.
  408. @param other string to compare
  409. @return Negative value if this string is less than the other
  410. character sequence, zero if the both character sequences are
  411. equal, positive value if this string is greater than the other
  412. character sequence
  413. */
  414. BOOST_CXX14_CONSTEXPR
  415. int
  416. compare(core::string_view other) const noexcept;
  417. /** Return the result of comparing to another string
  418. The length of the sequences to compare is the smaller of
  419. `size()` and `other.size()`.
  420. The function compares the two strings as if by calling
  421. `char_traits<char>::compare(to_string().data(), v.to_string().data(), rlen)`.
  422. This means the comparison is performed with
  423. percent-decoding applied to the current string.
  424. @param other string to compare
  425. @return Negative value if this string is less than the other
  426. character sequence, zero if the both character sequences are
  427. equal, positive value if this string is greater than the other
  428. character sequence
  429. */
  430. BOOST_CXX14_CONSTEXPR
  431. int
  432. compare(decode_view other) const noexcept;
  433. //--------------------------------------------
  434. // relational operators
  435. private:
  436. template<class S0, class S1>
  437. using is_match = std::integral_constant<bool,
  438. // both decode_view or convertible to core::string_view
  439. (
  440. std::is_same<typename std::decay<S0>::type, decode_view>::value ||
  441. std::is_convertible<S0, core::string_view>::value) &&
  442. (
  443. std::is_same<typename std::decay<S1>::type, decode_view>::value ||
  444. std::is_convertible<S1, core::string_view>::value) &&
  445. // not both are convertible to string view
  446. (
  447. !std::is_convertible<S0, core::string_view>::value ||
  448. !std::is_convertible<S1, core::string_view>::value)>;
  449. BOOST_CXX14_CONSTEXPR
  450. static
  451. int
  452. decode_compare(decode_view s0, decode_view s1) noexcept
  453. {
  454. return s0.compare(s1);
  455. }
  456. template <class S>
  457. BOOST_CXX14_CONSTEXPR
  458. static
  459. int
  460. decode_compare(decode_view s0, S const& s1) noexcept
  461. {
  462. return s0.compare(s1);
  463. }
  464. template <class S>
  465. BOOST_CXX14_CONSTEXPR
  466. static
  467. int
  468. decode_compare(S const& s0, decode_view s1) noexcept
  469. {
  470. return -s1.compare(s0);
  471. }
  472. public:
  473. #ifndef BOOST_URL_HAS_CONCEPTS
  474. /** Compare two decode views for equality
  475. @param lhs The left-hand-side decode view to compare
  476. @param rhs The right-hand-side decode view to compare
  477. @return `true` if decoded `lhs` is equal to the decoded `rhs`
  478. */
  479. template<class S0, class S1>
  480. BOOST_CXX14_CONSTEXPR friend auto operator==(
  481. S0 const& lhs, S1 const& rhs) noexcept ->
  482. typename std::enable_if<
  483. is_match<S0, S1>::value, bool>::type
  484. {
  485. return decode_compare(lhs, rhs) == 0;
  486. }
  487. #else
  488. /** Compare two decode views for equality
  489. @param lhs The left-hand-side decode view to compare
  490. @param rhs The right-hand-side decode view to compare
  491. @return `true` if decoded `lhs` is equal to the decoded `rhs`
  492. */
  493. BOOST_CXX14_CONSTEXPR
  494. friend
  495. bool
  496. operator==(
  497. decode_view const& lhs,
  498. decode_view const& rhs) noexcept
  499. {
  500. return decode_compare(lhs, rhs) == 0;
  501. }
  502. /** Compare two decode views for equality
  503. @param lhs The left-hand-side decode view to compare
  504. @param rhs The right-hand-side decode view to compare
  505. @return `true` if decoded `lhs` is equal to the decoded `rhs`
  506. */
  507. template <std::convertible_to<core::string_view> S>
  508. BOOST_CXX14_CONSTEXPR
  509. friend
  510. bool
  511. operator==(
  512. decode_view const& lhs,
  513. S const& rhs) noexcept
  514. {
  515. return decode_compare(lhs, rhs) == 0;
  516. }
  517. /** Compare two decode views for equality
  518. @param lhs The left-hand-side decode view to compare
  519. @param rhs The right-hand-side decode view to compare
  520. @return `true` if decoded `lhs` is equal to the decoded `rhs`
  521. */
  522. template <std::convertible_to<core::string_view> S>
  523. BOOST_CXX14_CONSTEXPR
  524. friend
  525. bool
  526. operator==(
  527. S const& lhs,
  528. decode_view const& rhs) noexcept
  529. {
  530. return decode_compare(lhs, rhs) == 0;
  531. }
  532. #endif
  533. #ifndef BOOST_URL_HAS_CONCEPTS
  534. /** Compare two decode views for inequality
  535. @param lhs The left-hand-side decode view to compare
  536. @param rhs The right-hand-side decode view to compare
  537. @return `true` if decoded `lhs` is not equal to the decoded `rhs`
  538. */
  539. template<class S0, class S1>
  540. BOOST_CXX14_CONSTEXPR friend auto operator!=(
  541. S0 const& lhs, S1 const& rhs) noexcept ->
  542. typename std::enable_if<
  543. is_match<S0, S1>::value, bool>::type
  544. {
  545. return decode_compare(lhs, rhs) != 0;
  546. }
  547. #else
  548. /** Compare two decode views for inequality
  549. @param lhs The left-hand-side decode view to compare
  550. @param rhs The right-hand-side decode view to compare
  551. @return `true` if decoded `lhs` is not equal to the decoded `rhs`
  552. */
  553. BOOST_CXX14_CONSTEXPR
  554. friend
  555. bool
  556. operator!=(
  557. decode_view const& lhs,
  558. decode_view const& rhs) noexcept
  559. {
  560. return decode_compare(lhs, rhs) != 0;
  561. }
  562. /** Compare two decode views for inequality
  563. @param lhs The left-hand-side decode view to compare
  564. @param rhs The right-hand-side decode view to compare
  565. @return `true` if decoded `lhs` is not equal to the decoded `rhs`
  566. */
  567. template <std::convertible_to<core::string_view> S>
  568. BOOST_CXX14_CONSTEXPR
  569. friend
  570. bool
  571. operator!=(
  572. decode_view const& lhs,
  573. S const& rhs) noexcept
  574. {
  575. return decode_compare(lhs, rhs) != 0;
  576. }
  577. /** Compare two decode views for inequality
  578. @param lhs The left-hand-side decode view to compare
  579. @param rhs The right-hand-side decode view to compare
  580. @return `true` if decoded `lhs` is not equal to the decoded `rhs`
  581. */
  582. template <std::convertible_to<core::string_view> S>
  583. BOOST_CXX14_CONSTEXPR
  584. friend
  585. bool
  586. operator!=(
  587. S const& lhs,
  588. decode_view const& rhs) noexcept
  589. {
  590. return decode_compare(lhs, rhs) != 0;
  591. }
  592. #endif
  593. #ifndef BOOST_URL_HAS_CONCEPTS
  594. /** Compare two decode views for less than
  595. @param lhs The left-hand-side decode view to compare
  596. @param rhs The right-hand-side decode view to compare
  597. @return `true` if decoded `lhs` is less than to the decoded `rhs`
  598. */
  599. template<class S0, class S1>
  600. BOOST_CXX14_CONSTEXPR friend auto operator<(
  601. S0 const& lhs, S1 const& rhs) noexcept ->
  602. typename std::enable_if<
  603. is_match<S0, S1>::value, bool>::type
  604. {
  605. return decode_compare(lhs, rhs) < 0;
  606. }
  607. #else
  608. /** Compare two decode views for less than
  609. @param lhs The left-hand-side decode view to compare
  610. @param rhs The right-hand-side decode view to compare
  611. @return `true` if decoded `lhs` is less than to the decoded `rhs`
  612. */
  613. BOOST_CXX14_CONSTEXPR
  614. friend
  615. bool
  616. operator<(
  617. decode_view const& lhs,
  618. decode_view const& rhs) noexcept
  619. {
  620. return decode_compare(lhs, rhs) < 0;
  621. }
  622. /** Compare two decode views for less than
  623. @param lhs The left-hand-side decode view to compare
  624. @param rhs The right-hand-side decode view to compare
  625. @return `true` if decoded `lhs` is less than to the decoded `rhs`
  626. */
  627. template <std::convertible_to<core::string_view> S>
  628. BOOST_CXX14_CONSTEXPR
  629. friend
  630. bool
  631. operator<(
  632. decode_view const& lhs,
  633. S const& rhs) noexcept
  634. {
  635. return decode_compare(lhs, rhs) < 0;
  636. }
  637. /** Compare two decode views for less than
  638. @param lhs The left-hand-side decode view to compare
  639. @param rhs The right-hand-side decode view to compare
  640. @return `true` if decoded `lhs` is less than to the decoded `rhs`
  641. */
  642. template <std::convertible_to<core::string_view> S>
  643. BOOST_CXX14_CONSTEXPR
  644. friend
  645. bool
  646. operator<(
  647. S const& lhs,
  648. decode_view const& rhs) noexcept
  649. {
  650. return decode_compare(lhs, rhs) < 0;
  651. }
  652. #endif
  653. #ifndef BOOST_URL_HAS_CONCEPTS
  654. /** Compare two decode views for less than or equal
  655. @param lhs The left-hand-side decode view to compare
  656. @param rhs The right-hand-side decode view to compare
  657. @return `true` if decoded `lhs` is less than or equal to the decoded `rhs`
  658. */
  659. template<class S0, class S1>
  660. BOOST_CXX14_CONSTEXPR friend auto operator<=(
  661. S0 const& lhs, S1 const& rhs) noexcept ->
  662. typename std::enable_if<
  663. is_match<S0, S1>::value, bool>::type
  664. {
  665. return decode_compare(lhs, rhs) <= 0;
  666. }
  667. #else
  668. /** Compare two decode views for less than or equal
  669. @param lhs The left-hand-side decode view to compare
  670. @param rhs The right-hand-side decode view to compare
  671. @return `true` if decoded `lhs` is less than or equal to the decoded `rhs`
  672. */
  673. BOOST_CXX14_CONSTEXPR
  674. friend
  675. bool
  676. operator<=(
  677. decode_view const& lhs,
  678. decode_view const& rhs) noexcept
  679. {
  680. return decode_compare(lhs, rhs) <= 0;
  681. }
  682. /** Compare two decode views for less than or equal
  683. @param lhs The left-hand-side decode view to compare
  684. @param rhs The right-hand-side decode view to compare
  685. @return `true` if decoded `lhs` is less than or equal to the decoded `rhs`
  686. */
  687. template <std::convertible_to<core::string_view> S>
  688. BOOST_CXX14_CONSTEXPR
  689. friend
  690. bool
  691. operator<=(
  692. decode_view const& lhs,
  693. S const& rhs) noexcept
  694. {
  695. return decode_compare(lhs, rhs) <= 0;
  696. }
  697. /** Compare two decode views for less than or equal
  698. @param lhs The left-hand-side decode view to compare
  699. @param rhs The right-hand-side decode view to compare
  700. @return `true` if decoded `lhs` is less than or equal to the decoded `rhs`
  701. */
  702. template <std::convertible_to<core::string_view> S>
  703. BOOST_CXX14_CONSTEXPR
  704. friend
  705. bool
  706. operator<=(
  707. S const& lhs,
  708. decode_view const& rhs) noexcept
  709. {
  710. return decode_compare(lhs, rhs) <= 0;
  711. }
  712. #endif
  713. #ifndef BOOST_URL_HAS_CONCEPTS
  714. /** Compare two decode views for greater than
  715. @param lhs The left-hand-side decode view to compare
  716. @param rhs The right-hand-side decode view to compare
  717. @return `true` if decoded `lhs` is greater than to the decoded `rhs`
  718. */
  719. template<class S0, class S1>
  720. BOOST_CXX14_CONSTEXPR friend auto operator>(
  721. S0 const& lhs, S1 const& rhs) noexcept ->
  722. typename std::enable_if<
  723. is_match<S0, S1>::value, bool>::type
  724. {
  725. return decode_compare(lhs, rhs) > 0;
  726. }
  727. #else
  728. /** Compare two decode views for greater than
  729. @param lhs The left-hand-side decode view to compare
  730. @param rhs The right-hand-side decode view to compare
  731. @return `true` if decoded `lhs` is greater than to the decoded `rhs`
  732. */
  733. BOOST_CXX14_CONSTEXPR
  734. friend
  735. bool
  736. operator>(
  737. decode_view const& lhs,
  738. decode_view const& rhs) noexcept
  739. {
  740. return decode_compare(lhs, rhs) > 0;
  741. }
  742. /** Compare two decode views for greater than
  743. @param lhs The left-hand-side decode view to compare
  744. @param rhs The right-hand-side decode view to compare
  745. @return `true` if decoded `lhs` is greater than to the decoded `rhs`
  746. */
  747. template <std::convertible_to<core::string_view> S>
  748. BOOST_CXX14_CONSTEXPR
  749. friend
  750. bool
  751. operator>(
  752. decode_view const& lhs,
  753. S const& rhs) noexcept
  754. {
  755. return decode_compare(lhs, rhs) > 0;
  756. }
  757. /** Compare two decode views for greater than
  758. @param lhs The left-hand-side decode view to compare
  759. @param rhs The right-hand-side decode view to compare
  760. @return `true` if decoded `lhs` is greater than to the decoded `rhs`
  761. */
  762. template <std::convertible_to<core::string_view> S>
  763. BOOST_CXX14_CONSTEXPR
  764. friend
  765. bool
  766. operator>(
  767. S const& lhs,
  768. decode_view const& rhs) noexcept
  769. {
  770. return decode_compare(lhs, rhs) > 0;
  771. }
  772. #endif
  773. #ifndef BOOST_URL_HAS_CONCEPTS
  774. /** Compare two decode views for greater than or equal
  775. @param lhs The left-hand-side decode view to compare
  776. @param rhs The right-hand-side decode view to compare
  777. @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs`
  778. */
  779. template<class S0, class S1>
  780. BOOST_CXX14_CONSTEXPR friend auto operator>=(
  781. S0 const& lhs, S1 const& rhs) noexcept ->
  782. typename std::enable_if<
  783. is_match<S0, S1>::value, bool>::type
  784. {
  785. return decode_compare(lhs, rhs) >= 0;
  786. }
  787. #else
  788. /** Compare two decode views for greater than or equal
  789. @param lhs The left-hand-side decode view to compare
  790. @param rhs The right-hand-side decode view to compare
  791. @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs`
  792. */
  793. BOOST_CXX14_CONSTEXPR
  794. friend
  795. bool
  796. operator>=(
  797. decode_view const& lhs,
  798. decode_view const& rhs) noexcept
  799. {
  800. return decode_compare(lhs, rhs) >= 0;
  801. }
  802. /** Compare two decode views for greater than or equal
  803. @param lhs The left-hand-side decode view to compare
  804. @param rhs The right-hand-side decode view to compare
  805. @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs`
  806. */
  807. template <std::convertible_to<core::string_view> S>
  808. BOOST_CXX14_CONSTEXPR
  809. friend
  810. bool
  811. operator>=(
  812. decode_view const& lhs,
  813. S const& rhs) noexcept
  814. {
  815. return decode_compare(lhs, rhs) >= 0;
  816. }
  817. /** Compare two decode views for greater than or equal
  818. @param lhs The left-hand-side decode view to compare
  819. @param rhs The right-hand-side decode view to compare
  820. @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs`
  821. */
  822. template <std::convertible_to<core::string_view> S>
  823. BOOST_CXX14_CONSTEXPR
  824. friend
  825. bool
  826. operator>=(
  827. S const& lhs,
  828. decode_view const& rhs) noexcept
  829. {
  830. return decode_compare(lhs, rhs) >= 0;
  831. }
  832. #endif
  833. /** Format the string with percent-decoding applied to the output stream
  834. This hidden friend function serializes the decoded view
  835. to the output stream.
  836. @return A reference to the output stream, for chaining
  837. @param os The output stream to write to
  838. @param s The decoded view to write
  839. */
  840. friend
  841. std::ostream&
  842. operator<<(
  843. std::ostream& os,
  844. decode_view const& s)
  845. {
  846. // hidden friend
  847. s.write(os);
  848. return os;
  849. }
  850. private:
  851. BOOST_URL_DECL
  852. void
  853. write(std::ostream& os) const;
  854. };
  855. /** Format the string with percent-decoding applied to the output stream
  856. This function serializes the decoded view
  857. to the output stream.
  858. @return A reference to the output stream, for chaining
  859. @param os The output stream to write to
  860. @param s The decoded view to write
  861. */
  862. inline
  863. std::ostream&
  864. operator<<(
  865. std::ostream& os,
  866. decode_view const& s);
  867. //------------------------------------------------
  868. inline
  869. decode_view
  870. pct_string_view::operator*() const noexcept
  871. {
  872. return decode_view(*this);
  873. }
  874. namespace detail {
  875. template<class... Args>
  876. decode_view
  877. make_decode_view(
  878. Args&&... args) noexcept
  879. {
  880. return decode_view(
  881. std::forward<Args>(args)...);
  882. }
  883. } // detail
  884. //------------------------------------------------
  885. } // urls
  886. } // boost
  887. #include <boost/url/impl/decode_view.hpp>
  888. #endif