string_view_base.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. //
  2. // Copyright (c) 2022 Vinnie Falco ([email protected])
  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_GRAMMAR_STRING_VIEW_BASE_HPP
  10. #define BOOST_URL_GRAMMAR_STRING_VIEW_BASE_HPP
  11. #include <boost/url/detail/config.hpp>
  12. #include <boost/url/detail/string_view.hpp>
  13. #include <boost/core/detail/string_view.hpp>
  14. #include <cstddef>
  15. #include <iterator>
  16. #include <string>
  17. #include <type_traits>
  18. #include <utility>
  19. namespace boost {
  20. namespace urls {
  21. namespace grammar {
  22. /** Common functionality for string views
  23. This base class is used to provide common
  24. member functions for reference types that
  25. behave like string views. This cannot be
  26. instantiated directly; Instead, derive
  27. from the type and provide constructors
  28. which offer any desired preconditions
  29. and invariants.
  30. */
  31. class string_view_base
  32. {
  33. protected:
  34. /** The referenced character buffer
  35. */
  36. core::string_view s_;
  37. /** Constructor
  38. */
  39. constexpr
  40. string_view_base(
  41. core::string_view s) noexcept
  42. : s_(s)
  43. {
  44. }
  45. /** Constructor
  46. */
  47. constexpr
  48. string_view_base(
  49. char const* data,
  50. std::size_t size) noexcept
  51. : s_(data, size)
  52. {
  53. }
  54. /** Swap
  55. */
  56. // VFALCO No idea why this fails in msvc
  57. /*BOOST_CXX14_CONSTEXPR*/ void swap(
  58. string_view_base& s ) noexcept
  59. {
  60. std::swap(s_, s.s_);
  61. }
  62. /** Constructor
  63. */
  64. string_view_base() = default;
  65. /** Constructor
  66. */
  67. string_view_base(
  68. string_view_base const&) = default;
  69. /** Assignment
  70. */
  71. string_view_base& operator=(
  72. string_view_base const&) = default;
  73. public:
  74. /// The character traits
  75. typedef std::char_traits<char> traits_type;
  76. /// The value type
  77. typedef char value_type;
  78. /// The pointer type
  79. typedef char* pointer;
  80. /// The const pointer type
  81. typedef char const* const_pointer;
  82. /// The reference type
  83. typedef char& reference;
  84. /// The const reference type
  85. typedef char const& const_reference;
  86. /// The const iterator type
  87. typedef char const* const_iterator;
  88. /// The iterator type
  89. typedef const_iterator iterator;
  90. /// The const reverse iterator type
  91. typedef std::reverse_iterator<
  92. const_iterator> const_reverse_iterator;
  93. /// The reverse iterator type
  94. typedef const_reverse_iterator reverse_iterator;
  95. /// The size type
  96. typedef std::size_t size_type;
  97. /// The difference type
  98. typedef std::ptrdiff_t difference_type;
  99. /// A constant used to represent "no position"
  100. static constexpr std::size_t npos = core::string_view::npos;
  101. //--------------------------------------------
  102. /** Conversion
  103. */
  104. operator
  105. core::string_view() const noexcept
  106. {
  107. return s_;
  108. }
  109. /** Conversion
  110. */
  111. #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
  112. operator
  113. std::string_view() const noexcept
  114. {
  115. return std::string_view(s_);
  116. }
  117. #endif
  118. /** Conversion
  119. Conversion to std::string is explicit
  120. because assigning to string using an
  121. implicit constructor does not preserve
  122. capacity.
  123. */
  124. explicit
  125. operator
  126. std::string() const noexcept
  127. {
  128. return std::string(s_);
  129. }
  130. //--------------------------------------------
  131. // iterator support
  132. /** Return an iterator to the beginning
  133. See `core::string_view::begin`
  134. */
  135. BOOST_CONSTEXPR const_iterator begin() const noexcept
  136. {
  137. return s_.begin();
  138. }
  139. /** Return an iterator to the end
  140. See `core::string_view::end`
  141. */
  142. BOOST_CONSTEXPR const_iterator end() const noexcept
  143. {
  144. return s_.end();
  145. }
  146. /** Return an iterator to the beginning
  147. See `core::string_view::cbegin`
  148. */
  149. BOOST_CONSTEXPR const_iterator cbegin() const noexcept
  150. {
  151. return s_.cbegin();
  152. }
  153. /** Return an iterator to the end
  154. See `core::string_view::cend`
  155. */
  156. BOOST_CONSTEXPR const_iterator cend() const noexcept
  157. {
  158. return s_.cend();
  159. }
  160. /** Return a reverse iterator to the end
  161. See `core::string_view::rbegin`
  162. */
  163. #ifdef __cpp_lib_array_constexpr
  164. constexpr
  165. #endif
  166. const_reverse_iterator rbegin() const noexcept
  167. {
  168. return s_.rbegin();
  169. }
  170. /** Return a reverse iterator to the beginning
  171. See `core::string_view::rend`
  172. */
  173. #ifdef __cpp_lib_array_constexpr
  174. constexpr
  175. #endif
  176. const_reverse_iterator rend() const noexcept
  177. {
  178. return s_.rend();
  179. }
  180. /** Return a reverse iterator to the end
  181. See `core::string_view::crbegin`
  182. */
  183. #ifdef __cpp_lib_array_constexpr
  184. constexpr
  185. #endif
  186. const_reverse_iterator crbegin() const noexcept
  187. {
  188. return s_.crbegin();
  189. }
  190. /** Return a reverse iterator to the beginning
  191. See `core::string_view::crend`
  192. */
  193. #ifdef __cpp_lib_array_constexpr
  194. constexpr
  195. #endif
  196. const_reverse_iterator crend() const noexcept
  197. {
  198. return s_.crend();
  199. }
  200. // capacity
  201. /** Return the size
  202. See `core::string_view::size`
  203. */
  204. BOOST_CONSTEXPR size_type size() const noexcept
  205. {
  206. return s_.size();
  207. }
  208. /** Return the size
  209. See `core::string_view::length`
  210. */
  211. BOOST_CONSTEXPR size_type length() const noexcept
  212. {
  213. return s_.length();
  214. }
  215. /** Return the maximum allowed size
  216. See `core::string_view::max_size`
  217. */
  218. BOOST_CONSTEXPR size_type max_size() const noexcept
  219. {
  220. return s_.max_size();
  221. }
  222. /** Return true if the string is empty
  223. See `core::string_view::size`
  224. */
  225. BOOST_CONSTEXPR bool empty() const noexcept
  226. {
  227. return s_.empty();
  228. }
  229. // element access
  230. /** Access a character
  231. See `core::string_view::operator[]`
  232. */
  233. BOOST_CXX14_CONSTEXPR const_reference
  234. operator[]( size_type pos ) const noexcept
  235. {
  236. return s_[pos];
  237. }
  238. /** Access a character
  239. See `core::string_view::at`
  240. */
  241. BOOST_CXX14_CONSTEXPR const_reference
  242. at( size_type pos ) const
  243. {
  244. return s_.at(pos);
  245. }
  246. /** Return the first character
  247. See `core::string_view::front`
  248. */
  249. BOOST_CXX14_CONSTEXPR const_reference
  250. front() const noexcept
  251. {
  252. return s_.front();
  253. }
  254. /** Return the last character
  255. See `core::string_view::back`
  256. */
  257. BOOST_CXX14_CONSTEXPR const_reference
  258. back() const noexcept
  259. {
  260. return s_.back();
  261. }
  262. /** Return a pointer to the character buffer
  263. See `core::string_view::data`
  264. */
  265. BOOST_CONSTEXPR const_pointer
  266. data() const noexcept
  267. {
  268. return s_.data();
  269. }
  270. // string operations
  271. /** Copy the characters to another buffer
  272. See `core::string_view::copy`
  273. */
  274. BOOST_CXX14_CONSTEXPR size_type copy(
  275. char* s, size_type n, size_type pos = 0 ) const
  276. {
  277. return s_.copy(s, n, pos);
  278. }
  279. /** Return a view to part of the string
  280. See `core::string_view::substr`
  281. */
  282. BOOST_CXX14_CONSTEXPR core::string_view substr(
  283. size_type pos = 0, size_type n = core::string_view::npos ) const
  284. {
  285. return s_.substr(pos, n);
  286. }
  287. // comparison
  288. /** Return the result of comparing to another string
  289. See `core::string_view::compare`
  290. */
  291. BOOST_CXX14_CONSTEXPR int
  292. compare( core::string_view str ) const noexcept
  293. {
  294. return s_.compare(str);
  295. }
  296. /** Return the result of comparing to another string
  297. See `core::string_view::compare`
  298. */
  299. BOOST_CONSTEXPR int compare(
  300. size_type pos1, size_type n1, core::string_view str ) const
  301. {
  302. return s_.compare(pos1, n1, str);
  303. }
  304. /** Return the result of comparing to another string
  305. See `core::string_view::compare`
  306. */
  307. BOOST_CONSTEXPR int compare(
  308. size_type pos1, size_type n1, core::string_view str,
  309. size_type pos2, size_type n2 ) const
  310. {
  311. return s_.compare(pos1, n1, str, pos2, n2);
  312. }
  313. /** Return the result of comparing to another string
  314. See `core::string_view::compare`
  315. */
  316. BOOST_CONSTEXPR int compare(
  317. char const* s ) const noexcept
  318. {
  319. return s_.compare(s);
  320. }
  321. /** Return the result of comparing to another string
  322. See `core::string_view::compare`
  323. */
  324. BOOST_CONSTEXPR int compare(
  325. size_type pos1, size_type n1, char const* s ) const
  326. {
  327. return s_.compare(pos1, n1, s);
  328. }
  329. /** Return the result of comparing to another string
  330. See `core::string_view::compare`
  331. */
  332. BOOST_CONSTEXPR int compare(
  333. size_type pos1, size_type n1,
  334. char const* s, size_type n2 ) const
  335. {
  336. return s_.compare(pos1, n1, s, n2);
  337. }
  338. // starts_with
  339. /** Return true if a matching prefix exists
  340. See `core::string_view::starts_with`
  341. */
  342. BOOST_CONSTEXPR bool starts_with(
  343. core::string_view x ) const noexcept
  344. {
  345. return s_.starts_with(x);
  346. }
  347. /** Return true if a matching prefix exists
  348. See `core::string_view::starts_with`
  349. */
  350. BOOST_CONSTEXPR bool starts_with(
  351. char x ) const noexcept
  352. {
  353. return s_.starts_with(x);
  354. }
  355. /** Return true if a matching prefix exists
  356. See `core::string_view::starts_with`
  357. */
  358. BOOST_CONSTEXPR bool starts_with(
  359. char const* x ) const noexcept
  360. {
  361. return s_.starts_with(x);
  362. }
  363. // ends_with
  364. /** Return true if a matching suffix exists
  365. See `core::string_view::ends_with`
  366. */
  367. BOOST_CONSTEXPR bool ends_with(
  368. core::string_view x ) const noexcept
  369. {
  370. return s_.ends_with(x);
  371. }
  372. /** Return true if a matching suffix exists
  373. See `core::string_view::ends_with`
  374. */
  375. BOOST_CONSTEXPR bool ends_with(
  376. char x ) const noexcept
  377. {
  378. return s_.ends_with(x);
  379. }
  380. /** Return true if a matching suffix exists
  381. See `core::string_view::ends_with`
  382. */
  383. BOOST_CONSTEXPR bool ends_with(
  384. char const* x ) const noexcept
  385. {
  386. return s_.ends_with(x);
  387. }
  388. // find
  389. /** Return the position of matching characters
  390. See `core::string_view::find`
  391. */
  392. BOOST_CONSTEXPR size_type find(
  393. core::string_view str, size_type pos = 0 ) const noexcept
  394. {
  395. return s_.find(str, pos);
  396. }
  397. /** Return the position of matching characters
  398. See `core::string_view::find`
  399. */
  400. BOOST_CXX14_CONSTEXPR size_type find(
  401. char c, size_type pos = 0 ) const noexcept
  402. {
  403. return s_.find(c, pos);
  404. }
  405. /** Return the position of matching characters
  406. See `core::string_view::find`
  407. */
  408. BOOST_CXX14_CONSTEXPR size_type find(
  409. char const* s, size_type pos, size_type n ) const noexcept
  410. {
  411. return s_.find(s, pos, n);
  412. }
  413. /** Return the position of matching characters
  414. See `core::string_view::find`
  415. */
  416. BOOST_CONSTEXPR size_type find(
  417. char const* s, size_type pos = 0 ) const noexcept
  418. {
  419. return s_.find(s, pos);
  420. }
  421. // rfind
  422. /** Return the position of matching characters
  423. See `core::string_view::rfind`
  424. */
  425. BOOST_CONSTEXPR size_type rfind(
  426. core::string_view str, size_type pos = core::string_view::npos ) const noexcept
  427. {
  428. return s_.rfind(str, pos);
  429. }
  430. /** Return the position of matching characters
  431. See `core::string_view::rfind`
  432. */
  433. BOOST_CXX14_CONSTEXPR size_type rfind(
  434. char c, size_type pos = core::string_view::npos ) const noexcept
  435. {
  436. return s_.rfind(c, pos);
  437. }
  438. /** Return the position of matching characters
  439. See `core::string_view::rfind`
  440. */
  441. BOOST_CXX14_CONSTEXPR size_type rfind(
  442. char const* s, size_type pos, size_type n ) const noexcept
  443. {
  444. return s_.rfind(s, pos, n);
  445. }
  446. /** Return the position of matching characters
  447. See `core::string_view::rfind`
  448. */
  449. BOOST_CONSTEXPR size_type rfind(
  450. char const* s, size_type pos = core::string_view::npos ) const noexcept
  451. {
  452. return s_.rfind(s, pos);
  453. }
  454. // find_first_of
  455. /** Return the position of the first match
  456. See `core::string_view::find_first_of`
  457. */
  458. BOOST_CXX14_CONSTEXPR size_type find_first_of(
  459. core::string_view str, size_type pos = 0 ) const noexcept
  460. {
  461. return s_.find_first_of(str, pos);
  462. }
  463. /** Return the position of the first match
  464. See `core::string_view::find_first_of`
  465. */
  466. BOOST_CONSTEXPR size_type find_first_of(
  467. char c, size_type pos = 0 ) const noexcept
  468. {
  469. return s_.find_first_of(c, pos);
  470. }
  471. /** Return the position of the first match
  472. See `core::string_view::find_first_of`
  473. */
  474. BOOST_CXX14_CONSTEXPR size_type find_first_of(
  475. char const* s, size_type pos, size_type n ) const noexcept
  476. {
  477. return s_.find_first_of(s, pos, n);
  478. }
  479. /** Return the position of the first match
  480. See `core::string_view::find_first_of`
  481. */
  482. BOOST_CXX14_CONSTEXPR size_type find_first_of(
  483. char const* s, size_type pos = 0 ) const noexcept
  484. {
  485. return s_.find_first_of(s, pos);
  486. }
  487. // find_last_of
  488. /** Return the position of the last match
  489. See `core::string_view::find_last_of`
  490. */
  491. BOOST_CXX14_CONSTEXPR size_type find_last_of(
  492. core::string_view str, size_type pos = core::string_view::npos ) const noexcept
  493. {
  494. return s_.find_last_of(str, pos);
  495. }
  496. /** Return the position of the last match
  497. See `core::string_view::find_last_of`
  498. */
  499. BOOST_CONSTEXPR size_type find_last_of(
  500. char c, size_type pos = core::string_view::npos ) const noexcept
  501. {
  502. return s_.find_last_of(c, pos);
  503. }
  504. /** Return the position of the last match
  505. See `core::string_view::find_last_of`
  506. */
  507. BOOST_CXX14_CONSTEXPR size_type find_last_of(
  508. char const* s, size_type pos, size_type n ) const noexcept
  509. {
  510. return s_.find_last_of(s, pos, n);
  511. }
  512. /** Return the position of the last match
  513. See `core::string_view::find_last_of`
  514. */
  515. BOOST_CXX14_CONSTEXPR size_type find_last_of(
  516. char const* s, size_type pos = core::string_view::npos ) const noexcept
  517. {
  518. return s_.find_last_of(s, pos);
  519. }
  520. // find_first_not_of
  521. /** Return the position of the first non-match
  522. See `core::string_view::find_first_not_of`
  523. */
  524. BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
  525. core::string_view str, size_type pos = 0 ) const noexcept
  526. {
  527. return s_.find_first_not_of(str, pos);
  528. }
  529. /** Return the position of the first non-match
  530. See `core::string_view::find_first_not_of`
  531. */
  532. BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
  533. char c, size_type pos = 0 ) const noexcept
  534. {
  535. return s_.find_first_not_of(c, pos);
  536. }
  537. /** Return the position of the first non-match
  538. See `core::string_view::find_first_not_of`
  539. */
  540. BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
  541. char const* s, size_type pos, size_type n ) const noexcept
  542. {
  543. return s_.find_first_not_of(s, pos, n);
  544. }
  545. /** Return the position of the first non-match
  546. See `core::string_view::find_first_not_of`
  547. */
  548. BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
  549. char const* s, size_type pos = 0 ) const noexcept
  550. {
  551. return s_.find_first_not_of(s, pos);
  552. }
  553. // find_last_not_of
  554. /** Return the position of the last non-match
  555. See `core::string_view::find_last_not_of`
  556. */
  557. BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
  558. core::string_view str, size_type pos = core::string_view::npos ) const noexcept
  559. {
  560. return s_.find_last_not_of(str, pos);
  561. }
  562. /** Return the position of the last non-match
  563. See `core::string_view::find_last_not_of`
  564. */
  565. BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
  566. char c, size_type pos = core::string_view::npos ) const noexcept
  567. {
  568. return s_.find_last_not_of(c, pos);
  569. }
  570. /** Return the position of the last non-match
  571. See `core::string_view::find_last_not_of`
  572. */
  573. BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
  574. char const* s, size_type pos, size_type n ) const noexcept
  575. {
  576. return s_.find_last_not_of(s, pos, n);
  577. }
  578. /** Return the position of the last non-match
  579. See `core::string_view::find_last_not_of`
  580. */
  581. BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
  582. char const* s, size_type pos = core::string_view::npos ) const noexcept
  583. {
  584. return s_.find_last_not_of(s, pos);
  585. }
  586. // contains
  587. /** Return true if matching characters are found
  588. See `core::string_view::contains`
  589. */
  590. BOOST_CONSTEXPR bool contains( core::string_view sv ) const noexcept
  591. {
  592. return s_.contains(sv);
  593. }
  594. /** Return true if matching characters are found
  595. See `core::string_view::contains`
  596. */
  597. BOOST_CXX14_CONSTEXPR bool contains( char c ) const noexcept
  598. {
  599. return s_.contains(c);
  600. }
  601. /** Return true if matching characters are found
  602. See `core::string_view::contains`
  603. */
  604. BOOST_CONSTEXPR bool contains( char const* s ) const noexcept
  605. {
  606. return s_.contains(s);
  607. }
  608. // relational operators
  609. #ifndef BOOST_URL_DOCS
  610. private:
  611. template<class S0, class S1>
  612. using is_match = std::integral_constant<bool,
  613. std::is_convertible<S0, core::string_view>::value &&
  614. std::is_convertible<S1, core::string_view>::value && (
  615. (std::is_base_of<string_view_base,
  616. typename std::decay<S0>::type>::value &&
  617. std::is_convertible<S0 const volatile*,
  618. string_view_base const volatile*>::value) ||
  619. (std::is_base_of<string_view_base,
  620. typename std::decay<S1>::type>::value &&
  621. std::is_convertible<S1 const volatile*,
  622. string_view_base const volatile*>::value))>;
  623. public:
  624. template<class S0, class S1>
  625. BOOST_CXX14_CONSTEXPR friend auto operator==(
  626. S0 const& s0, S1 const& s1) noexcept ->
  627. typename std::enable_if<
  628. is_match<S0, S1>::value, bool>::type
  629. {
  630. return urls::detail::to_sv(s0) == urls::detail::to_sv(s1);
  631. }
  632. template<class S0, class S1>
  633. BOOST_CXX14_CONSTEXPR friend auto operator!=(
  634. S0 const& s0, S1 const& s1) noexcept ->
  635. typename std::enable_if<
  636. is_match<S0, S1>::value, bool>::type
  637. {
  638. return urls::detail::to_sv(s0) != urls::detail::to_sv(s1);
  639. }
  640. template<class S0, class S1>
  641. BOOST_CXX14_CONSTEXPR friend auto operator<(
  642. S0 const& s0, S1 const& s1) noexcept ->
  643. typename std::enable_if<
  644. is_match<S0, S1>::value, bool>::type
  645. {
  646. return urls::detail::to_sv(s0) < urls::detail::to_sv(s1);
  647. }
  648. template<class S0, class S1>
  649. BOOST_CXX14_CONSTEXPR friend auto operator<=(
  650. S0 const& s0, S1 const& s1) noexcept ->
  651. typename std::enable_if<
  652. is_match<S0, S1>::value, bool>::type
  653. {
  654. return urls::detail::to_sv(s0) <= urls::detail::to_sv(s1);
  655. }
  656. template<class S0, class S1>
  657. BOOST_CXX14_CONSTEXPR friend auto operator>(
  658. S0 const& s0, S1 const& s1) noexcept ->
  659. typename std::enable_if<
  660. is_match<S0, S1>::value, bool>::type
  661. {
  662. return urls::detail::to_sv(s0) > urls::detail::to_sv(s1);
  663. }
  664. template<class S0, class S1>
  665. BOOST_CXX14_CONSTEXPR friend auto operator>=(
  666. S0 const& s0, S1 const& s1) noexcept ->
  667. typename std::enable_if<
  668. is_match<S0, S1>::value, bool>::type
  669. {
  670. return urls::detail::to_sv(s0) >= urls::detail::to_sv(s1);
  671. }
  672. #endif
  673. //--------------------------------------------
  674. /** Return the hash of this value
  675. */
  676. friend
  677. std::size_t
  678. hash_value(
  679. string_view_base const& s) noexcept
  680. {
  681. return hash_value(s.s_);
  682. }
  683. BOOST_URL_DECL
  684. friend
  685. std::ostream&
  686. operator<<(
  687. std::ostream& os,
  688. string_view_base const& s);
  689. };
  690. //------------------------------------------------
  691. /** Format a string to an output stream
  692. */
  693. BOOST_URL_DECL
  694. std::ostream&
  695. operator<<(
  696. std::ostream& os,
  697. string_view_base const& s);
  698. } // grammar
  699. #ifndef BOOST_URL_DOCS
  700. namespace detail {
  701. template <>
  702. inline
  703. core::string_view
  704. to_sv(grammar::string_view_base const& s) noexcept
  705. {
  706. return s.operator core::string_view();
  707. }
  708. } // detail
  709. #endif
  710. } // urls
  711. } // boost
  712. #endif