Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:28

0001 //
0002 // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/url
0008 //
0009 
0010 #ifndef BOOST_URL_GRAMMAR_STRING_VIEW_BASE_HPP
0011 #define BOOST_URL_GRAMMAR_STRING_VIEW_BASE_HPP
0012 
0013 #include <boost/url/detail/config.hpp>
0014 #include <boost/url/detail/string_view.hpp>
0015 #include <boost/core/detail/string_view.hpp>
0016 #include <cstddef>
0017 #include <iterator>
0018 #include <string>
0019 #include <type_traits>
0020 #include <utility>
0021 
0022 namespace boost {
0023 namespace urls {
0024 namespace grammar {
0025 
0026 /** Common functionality for string views
0027 
0028     This base class is used to provide common
0029     member functions for reference types that
0030     behave like string views. This cannot be
0031     instantiated directly; Instead, derive
0032     from the type and provide constructors
0033     which offer any desired preconditions
0034     and invariants.
0035 */
0036 class string_view_base
0037 {
0038 protected:
0039     /** The referenced character buffer
0040     */
0041     core::string_view s_;
0042 
0043     /** Constructor
0044     */
0045     constexpr
0046     string_view_base(
0047         core::string_view s) noexcept
0048         : s_(s)
0049     {
0050     }
0051 
0052     /** Constructor
0053     */
0054     constexpr
0055     string_view_base(
0056         char const* data,
0057         std::size_t size) noexcept
0058         : s_(data, size)
0059     {
0060     }
0061 
0062     /** Swap
0063     */
0064     // VFALCO No idea why this fails in msvc
0065     /*BOOST_CXX14_CONSTEXPR*/ void swap(
0066         string_view_base& s ) noexcept
0067     {
0068         std::swap(s_, s.s_);
0069     }
0070 
0071     /** Constructor
0072     */
0073     string_view_base() = default;
0074 
0075     /** Constructor
0076     */
0077     string_view_base(
0078         string_view_base const&) = default;
0079 
0080     /** Assignment
0081     */
0082     string_view_base& operator=(
0083         string_view_base const&) = default;
0084 
0085 public:
0086     /// The character traits
0087     typedef std::char_traits<char> traits_type;
0088     /// The value type
0089     typedef char value_type;
0090     /// The pointer type
0091     typedef char* pointer;
0092     /// The const pointer type
0093     typedef char const* const_pointer;
0094     /// The reference type
0095     typedef char& reference;
0096     /// The const reference type
0097     typedef char const& const_reference;
0098     /// The const iterator type
0099     typedef char const* const_iterator;
0100     /// The iterator type
0101     typedef const_iterator iterator;
0102     /// The const reverse iterator type
0103     typedef std::reverse_iterator<
0104         const_iterator> const_reverse_iterator;
0105     /// The reverse iterator type
0106     typedef const_reverse_iterator reverse_iterator;
0107     /// The size type
0108     typedef std::size_t size_type;
0109     /// The difference type
0110     typedef std::ptrdiff_t difference_type;
0111 
0112     /// A constant used to represent "no position"
0113     static constexpr std::size_t npos = core::string_view::npos;
0114 
0115     //--------------------------------------------
0116 
0117     /** Conversion
0118     */
0119     operator
0120     core::string_view() const noexcept
0121     {
0122         return s_;
0123     }
0124 
0125     /** Conversion
0126     */
0127 #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
0128     operator
0129     std::string_view() const noexcept
0130     {
0131         return std::string_view(s_);
0132     }
0133 #endif
0134 
0135     /** Conversion
0136 
0137         Conversion to std::string is explicit
0138         because assigning to string using an
0139         implicit constructor does not preserve
0140         capacity.
0141     */
0142     explicit
0143     operator
0144     std::string() const noexcept
0145     {
0146         return std::string(s_);
0147     }
0148 
0149     //--------------------------------------------
0150 
0151     // iterator support
0152 
0153     /** Return an iterator to the beginning
0154 
0155         See `core::string_view::begin`
0156     */
0157     BOOST_CONSTEXPR const_iterator begin() const noexcept
0158     {
0159         return s_.begin();
0160     }
0161 
0162     /** Return an iterator to the end
0163 
0164         See `core::string_view::end`
0165     */
0166     BOOST_CONSTEXPR const_iterator end() const noexcept
0167     {
0168         return s_.end();
0169     }
0170 
0171     /** Return an iterator to the beginning
0172 
0173         See `core::string_view::cbegin`
0174     */
0175     BOOST_CONSTEXPR const_iterator cbegin() const noexcept
0176     {
0177         return s_.cbegin();
0178     }
0179 
0180     /** Return an iterator to the end
0181 
0182         See `core::string_view::cend`
0183     */
0184     BOOST_CONSTEXPR const_iterator cend() const noexcept
0185     {
0186         return s_.cend();
0187     }
0188 
0189     /** Return a reverse iterator to the end
0190 
0191         See `core::string_view::rbegin`
0192     */
0193 #ifdef __cpp_lib_array_constexpr
0194     constexpr
0195 #endif
0196     const_reverse_iterator rbegin() const noexcept
0197     {
0198         return s_.rbegin();
0199     }
0200 
0201     /** Return a reverse iterator to the beginning
0202 
0203         See `core::string_view::rend`
0204     */
0205 #ifdef __cpp_lib_array_constexpr
0206     constexpr
0207 #endif
0208     const_reverse_iterator rend() const noexcept
0209     {
0210         return s_.rend();
0211     }
0212 
0213     /** Return a reverse iterator to the end
0214 
0215         See `core::string_view::crbegin`
0216     */
0217 #ifdef __cpp_lib_array_constexpr
0218     constexpr
0219 #endif
0220     const_reverse_iterator crbegin() const noexcept
0221     {
0222         return s_.crbegin();
0223     }
0224 
0225     /** Return a reverse iterator to the beginning
0226 
0227         See `core::string_view::crend`
0228     */
0229 #ifdef __cpp_lib_array_constexpr
0230     constexpr
0231 #endif
0232     const_reverse_iterator crend() const noexcept
0233     {
0234         return s_.crend();
0235     }
0236 
0237     // capacity
0238 
0239     /** Return the size
0240 
0241         See `core::string_view::size`
0242     */
0243     BOOST_CONSTEXPR size_type size() const noexcept
0244     {
0245         return s_.size();
0246     }
0247 
0248     /** Return the size
0249 
0250         See `core::string_view::length`
0251     */
0252     BOOST_CONSTEXPR size_type length() const noexcept
0253     {
0254         return s_.length();
0255     }
0256 
0257     /** Return the maximum allowed size
0258 
0259         See `core::string_view::max_size`
0260     */
0261     BOOST_CONSTEXPR size_type max_size() const noexcept
0262     {
0263         return s_.max_size();
0264     }
0265 
0266     /** Return true if the string is empty
0267 
0268         See `core::string_view::size`
0269     */
0270     BOOST_CONSTEXPR bool empty() const noexcept
0271     {
0272         return s_.empty();
0273     }
0274    
0275     // element access
0276 
0277     /** Access a character
0278 
0279         See `core::string_view::operator[]`
0280     */
0281     BOOST_CXX14_CONSTEXPR const_reference
0282         operator[]( size_type pos ) const noexcept
0283     {
0284         return s_[pos];
0285     }
0286 
0287     /** Access a character
0288 
0289         See `core::string_view::at`
0290     */
0291     BOOST_CXX14_CONSTEXPR const_reference
0292         at( size_type pos ) const
0293     {
0294         return s_.at(pos);
0295     }
0296 
0297     /** Return the first character
0298 
0299         See `core::string_view::front`
0300     */
0301     BOOST_CXX14_CONSTEXPR const_reference
0302         front() const noexcept
0303     {
0304         return s_.front();
0305     }
0306 
0307     /** Return the last character
0308 
0309         See `core::string_view::back`
0310     */
0311     BOOST_CXX14_CONSTEXPR const_reference
0312         back() const noexcept
0313     {
0314         return s_.back();
0315     }
0316 
0317     /** Return a pointer to the character buffer
0318 
0319         See `core::string_view::data`
0320     */
0321     BOOST_CONSTEXPR const_pointer
0322         data() const noexcept
0323     {
0324         return s_.data();
0325     }
0326 
0327     // string operations
0328 
0329     /** Copy the characters to another buffer
0330 
0331         See `core::string_view::copy`
0332     */
0333     BOOST_CXX14_CONSTEXPR size_type copy(
0334         char* s, size_type n, size_type pos = 0 ) const
0335     {
0336         return s_.copy(s, n, pos);
0337     }
0338 
0339     /** Return a view to part of the string
0340 
0341         See `core::string_view::substr`
0342     */
0343     BOOST_CXX14_CONSTEXPR core::string_view substr(
0344         size_type pos = 0, size_type n = core::string_view::npos ) const
0345     {
0346         return s_.substr(pos, n);
0347     }
0348 
0349     // comparison
0350 
0351     /** Return the result of comparing to another string
0352 
0353         See `core::string_view::compare`
0354     */
0355     BOOST_CXX14_CONSTEXPR int
0356         compare( core::string_view str ) const noexcept
0357     {
0358         return s_.compare(str);
0359     }
0360 
0361     /** Return the result of comparing to another string
0362 
0363         See `core::string_view::compare`
0364     */
0365     BOOST_CONSTEXPR int compare(
0366         size_type pos1, size_type n1, core::string_view str ) const
0367     {
0368         return s_.compare(pos1, n1, str);
0369     }
0370 
0371     /** Return the result of comparing to another string
0372 
0373         See `core::string_view::compare`
0374     */
0375     BOOST_CONSTEXPR int compare(
0376         size_type pos1, size_type n1, core::string_view str,
0377         size_type pos2, size_type n2 ) const
0378     {
0379         return s_.compare(pos1, n1, str, pos2, n2);
0380     }
0381 
0382     /** Return the result of comparing to another string
0383 
0384         See `core::string_view::compare`
0385     */
0386     BOOST_CONSTEXPR int compare(
0387         char const* s ) const noexcept
0388     {
0389         return s_.compare(s);
0390     }
0391 
0392     /** Return the result of comparing to another string
0393 
0394         See `core::string_view::compare`
0395     */
0396     BOOST_CONSTEXPR int compare(
0397         size_type pos1, size_type n1, char const* s ) const
0398     {
0399         return s_.compare(pos1, n1, s);
0400     }
0401 
0402     /** Return the result of comparing to another string
0403 
0404         See `core::string_view::compare`
0405     */
0406     BOOST_CONSTEXPR int compare(
0407         size_type pos1, size_type n1,
0408         char const* s, size_type n2 ) const
0409     {
0410         return s_.compare(pos1, n1, s, n2);
0411     }
0412 
0413     // starts_with
0414 
0415     /** Return true if a matching prefix exists
0416 
0417         See `core::string_view::starts_with`
0418     */
0419     BOOST_CONSTEXPR bool starts_with(
0420         core::string_view x ) const noexcept
0421     {
0422         return s_.starts_with(x);
0423     }
0424 
0425     /** Return true if a matching prefix exists
0426 
0427         See `core::string_view::starts_with`
0428     */
0429     BOOST_CONSTEXPR bool starts_with(
0430         char x ) const noexcept
0431     {
0432         return s_.starts_with(x);
0433     }
0434 
0435     /** Return true if a matching prefix exists
0436 
0437         See `core::string_view::starts_with`
0438     */
0439     BOOST_CONSTEXPR bool starts_with(
0440         char const* x ) const noexcept
0441     {
0442         return s_.starts_with(x);
0443     }
0444 
0445     // ends_with
0446 
0447     /** Return true if a matching suffix exists
0448 
0449         See `core::string_view::ends_with`
0450     */
0451     BOOST_CONSTEXPR bool ends_with(
0452         core::string_view x ) const noexcept
0453     {
0454         return s_.ends_with(x);
0455     }
0456 
0457     /** Return true if a matching suffix exists
0458 
0459         See `core::string_view::ends_with`
0460     */
0461     BOOST_CONSTEXPR bool ends_with(
0462         char x ) const noexcept
0463     {
0464         return s_.ends_with(x);
0465     }
0466 
0467     /** Return true if a matching suffix exists
0468 
0469         See `core::string_view::ends_with`
0470     */
0471     BOOST_CONSTEXPR bool ends_with(
0472         char const* x ) const noexcept
0473     {
0474         return s_.ends_with(x);
0475     }
0476 
0477     // find
0478 
0479     /** Return the position of matching characters
0480 
0481         See `core::string_view::find`
0482     */
0483     BOOST_CONSTEXPR size_type find(
0484         core::string_view str, size_type pos = 0 ) const noexcept
0485     {
0486         return s_.find(str, pos);
0487     }
0488 
0489     /** Return the position of matching characters
0490 
0491         See `core::string_view::find`
0492     */
0493     BOOST_CXX14_CONSTEXPR size_type find(
0494         char c, size_type pos = 0 ) const noexcept
0495     {
0496         return s_.find(c, pos);
0497     }
0498 
0499     /** Return the position of matching characters
0500 
0501         See `core::string_view::find`
0502     */
0503     BOOST_CXX14_CONSTEXPR size_type find(
0504         char const* s, size_type pos, size_type n ) const noexcept
0505     {
0506         return s_.find(s, pos, n);
0507     }
0508 
0509     /** Return the position of matching characters
0510 
0511         See `core::string_view::find`
0512     */
0513     BOOST_CONSTEXPR size_type find(
0514         char const* s, size_type pos = 0 ) const noexcept
0515     {
0516         return s_.find(s, pos);
0517     }
0518 
0519     // rfind
0520 
0521     /** Return the position of matching characters
0522 
0523         See `core::string_view::rfind`
0524     */
0525     BOOST_CONSTEXPR size_type rfind(
0526         core::string_view str, size_type pos = core::string_view::npos ) const noexcept
0527     {
0528         return s_.rfind(str, pos);
0529     }
0530 
0531     /** Return the position of matching characters
0532 
0533         See `core::string_view::rfind`
0534     */
0535     BOOST_CXX14_CONSTEXPR size_type rfind(
0536         char c, size_type pos = core::string_view::npos ) const noexcept
0537     {
0538         return s_.rfind(c, pos);
0539     }
0540 
0541     /** Return the position of matching characters
0542 
0543         See `core::string_view::rfind`
0544     */
0545     BOOST_CXX14_CONSTEXPR size_type rfind(
0546         char const* s, size_type pos, size_type n ) const noexcept
0547     {
0548         return s_.rfind(s, pos, n);
0549     }
0550 
0551     /** Return the position of matching characters
0552 
0553         See `core::string_view::rfind`
0554     */
0555     BOOST_CONSTEXPR size_type rfind(
0556         char const* s, size_type pos = core::string_view::npos ) const noexcept
0557     {
0558         return s_.rfind(s, pos);
0559     }
0560 
0561     // find_first_of
0562 
0563     /** Return the position of the first match
0564 
0565         See `core::string_view::find_first_of`
0566     */
0567     BOOST_CXX14_CONSTEXPR size_type find_first_of(
0568         core::string_view str, size_type pos = 0 ) const noexcept
0569     {
0570         return s_.find_first_of(str, pos);
0571     }
0572 
0573     /** Return the position of the first match
0574 
0575         See `core::string_view::find_first_of`
0576     */
0577     BOOST_CONSTEXPR size_type find_first_of(
0578         char c, size_type pos = 0 ) const noexcept
0579     {
0580         return s_.find_first_of(c, pos);
0581     }
0582 
0583     /** Return the position of the first match
0584 
0585         See `core::string_view::find_first_of`
0586     */
0587     BOOST_CXX14_CONSTEXPR size_type find_first_of(
0588         char const* s, size_type pos, size_type n ) const noexcept
0589     {
0590         return s_.find_first_of(s, pos, n);
0591     }
0592 
0593     /** Return the position of the first match
0594 
0595         See `core::string_view::find_first_of`
0596     */
0597     BOOST_CXX14_CONSTEXPR size_type find_first_of(
0598         char const* s, size_type pos = 0 ) const noexcept
0599     {
0600         return s_.find_first_of(s, pos);
0601     }
0602 
0603     // find_last_of
0604 
0605     /** Return the position of the last match
0606 
0607         See `core::string_view::find_last_of`
0608     */
0609     BOOST_CXX14_CONSTEXPR size_type find_last_of(
0610         core::string_view str, size_type pos = core::string_view::npos ) const noexcept
0611     {
0612         return s_.find_last_of(str, pos);
0613     }
0614 
0615     /** Return the position of the last match
0616 
0617         See `core::string_view::find_last_of`
0618     */
0619     BOOST_CONSTEXPR size_type find_last_of(
0620         char c, size_type pos = core::string_view::npos ) const noexcept
0621     {
0622         return s_.find_last_of(c, pos);
0623     }
0624 
0625     /** Return the position of the last match
0626 
0627         See `core::string_view::find_last_of`
0628     */
0629     BOOST_CXX14_CONSTEXPR size_type find_last_of(
0630         char const* s, size_type pos, size_type n ) const noexcept
0631     {
0632         return s_.find_last_of(s, pos, n);
0633     }
0634 
0635     /** Return the position of the last match
0636 
0637         See `core::string_view::find_last_of`
0638     */
0639     BOOST_CXX14_CONSTEXPR size_type find_last_of(
0640         char const* s, size_type pos = core::string_view::npos ) const noexcept
0641     {
0642         return s_.find_last_of(s, pos);
0643     }
0644 
0645     // find_first_not_of
0646 
0647     /** Return the position of the first non-match
0648 
0649         See `core::string_view::find_first_not_of`
0650     */
0651     BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
0652         core::string_view str, size_type pos = 0 ) const noexcept
0653     {
0654         return s_.find_first_not_of(str, pos);
0655     }
0656 
0657     /** Return the position of the first non-match
0658 
0659         See `core::string_view::find_first_not_of`
0660     */
0661     BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
0662         char c, size_type pos = 0 ) const noexcept
0663     {
0664         return s_.find_first_not_of(c, pos);
0665     }
0666 
0667     /** Return the position of the first non-match
0668 
0669         See `core::string_view::find_first_not_of`
0670     */
0671     BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
0672         char const* s, size_type pos, size_type n ) const noexcept
0673     {
0674         return s_.find_first_not_of(s, pos, n);
0675     }
0676 
0677     /** Return the position of the first non-match
0678 
0679         See `core::string_view::find_first_not_of`
0680     */
0681     BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
0682         char const* s, size_type pos = 0 ) const noexcept
0683     {
0684         return s_.find_first_not_of(s, pos);
0685     }
0686 
0687     // find_last_not_of
0688 
0689     /** Return the position of the last non-match
0690 
0691         See `core::string_view::find_last_not_of`
0692     */
0693     BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
0694         core::string_view str, size_type pos = core::string_view::npos ) const noexcept
0695     {
0696         return s_.find_last_not_of(str, pos);
0697     }
0698 
0699     /** Return the position of the last non-match
0700 
0701         See `core::string_view::find_last_not_of`
0702     */
0703     BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
0704         char c, size_type pos = core::string_view::npos ) const noexcept
0705     {
0706         return s_.find_last_not_of(c, pos);
0707     }
0708 
0709     /** Return the position of the last non-match
0710 
0711         See `core::string_view::find_last_not_of`
0712     */
0713     BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
0714         char const* s, size_type pos, size_type n ) const noexcept
0715     {
0716         return s_.find_last_not_of(s, pos, n);
0717     }
0718 
0719     /** Return the position of the last non-match
0720 
0721         See `core::string_view::find_last_not_of`
0722     */
0723     BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
0724         char const* s, size_type pos = core::string_view::npos ) const noexcept
0725     {
0726         return s_.find_last_not_of(s, pos);
0727     }
0728 
0729     // contains
0730 
0731     /** Return true if matching characters are found
0732 
0733         See `core::string_view::contains`
0734     */
0735     BOOST_CONSTEXPR bool contains( core::string_view sv ) const noexcept
0736     {
0737         return s_.contains(sv);
0738     }
0739 
0740     /** Return true if matching characters are found
0741 
0742         See `core::string_view::contains`
0743     */
0744     BOOST_CXX14_CONSTEXPR bool contains( char c ) const noexcept
0745     {
0746         return s_.contains(c);
0747     }
0748 
0749     /** Return true if matching characters are found
0750 
0751         See `core::string_view::contains`
0752     */
0753     BOOST_CONSTEXPR bool contains( char const* s ) const noexcept
0754     {
0755         return s_.contains(s);
0756     }
0757 
0758     // relational operators
0759 #ifndef BOOST_URL_DOCS
0760 private:
0761     template<class S0, class S1>
0762     using is_match = std::integral_constant<bool,
0763         std::is_convertible<S0, core::string_view>::value &&
0764         std::is_convertible<S1, core::string_view>::value && (
0765             (std::is_base_of<string_view_base,
0766                 typename std::decay<S0>::type>::value &&
0767             std::is_convertible<S0 const volatile*,
0768                 string_view_base const volatile*>::value) ||
0769             (std::is_base_of<string_view_base,
0770                 typename std::decay<S1>::type>::value &&
0771             std::is_convertible<S1 const volatile*,
0772                 string_view_base const volatile*>::value))>;
0773 public:
0774 
0775     template<class S0, class S1>
0776     BOOST_CXX14_CONSTEXPR friend auto operator==(
0777         S0 const& s0, S1 const& s1) noexcept ->
0778         typename std::enable_if<
0779             is_match<S0, S1>::value, bool>::type
0780     {
0781         return urls::detail::to_sv(s0) == urls::detail::to_sv(s1);
0782     }
0783 
0784     template<class S0, class S1>
0785     BOOST_CXX14_CONSTEXPR friend auto operator!=(
0786         S0 const& s0, S1 const& s1) noexcept ->
0787         typename std::enable_if<
0788             is_match<S0, S1>::value, bool>::type
0789     {
0790         return urls::detail::to_sv(s0) != urls::detail::to_sv(s1);
0791     }
0792 
0793     template<class S0, class S1>
0794     BOOST_CXX14_CONSTEXPR friend auto operator<(
0795         S0 const& s0, S1 const& s1) noexcept ->
0796         typename std::enable_if<
0797             is_match<S0, S1>::value, bool>::type
0798     {
0799         return urls::detail::to_sv(s0) < urls::detail::to_sv(s1);
0800     }
0801 
0802     template<class S0, class S1>
0803     BOOST_CXX14_CONSTEXPR friend auto operator<=(
0804         S0 const& s0, S1 const& s1) noexcept ->
0805         typename std::enable_if<
0806             is_match<S0, S1>::value, bool>::type
0807     {
0808         return urls::detail::to_sv(s0) <= urls::detail::to_sv(s1);
0809     }
0810 
0811     template<class S0, class S1>
0812     BOOST_CXX14_CONSTEXPR friend auto operator>(
0813         S0 const& s0, S1 const& s1) noexcept ->
0814         typename std::enable_if<
0815             is_match<S0, S1>::value, bool>::type
0816     {
0817         return urls::detail::to_sv(s0) > urls::detail::to_sv(s1);
0818     }
0819 
0820     template<class S0, class S1>
0821     BOOST_CXX14_CONSTEXPR friend auto operator>=(
0822         S0 const& s0, S1 const& s1) noexcept ->
0823         typename std::enable_if<
0824             is_match<S0, S1>::value, bool>::type
0825     {
0826         return urls::detail::to_sv(s0) >= urls::detail::to_sv(s1);
0827     }
0828 #endif
0829 
0830     //--------------------------------------------
0831 
0832     /** Return the hash of this value
0833     */
0834     friend
0835     std::size_t
0836     hash_value(
0837         string_view_base const& s) noexcept
0838     {
0839         return hash_value(s.s_);
0840     }
0841 
0842     BOOST_URL_DECL
0843     friend
0844     std::ostream&
0845     operator<<(
0846         std::ostream& os,
0847         string_view_base const& s);
0848 };
0849 
0850 //------------------------------------------------
0851 
0852 /** Format a string to an output stream
0853 */
0854 BOOST_URL_DECL
0855 std::ostream&
0856 operator<<(
0857     std::ostream& os,
0858     string_view_base const& s);
0859 
0860 } // grammar
0861 
0862 #ifndef BOOST_URL_DOCS
0863 namespace detail {
0864 template <>
0865 inline
0866 core::string_view
0867 to_sv(grammar::string_view_base const& s) noexcept
0868 {
0869     return s.operator core::string_view();
0870 }
0871 } // detail
0872 #endif
0873 
0874 } // urls
0875 } // boost
0876 
0877 #endif