Home | History | Annotate | Download | only in include
      1 // -*- C++ -*-
      2 //===------------------------ string_view ---------------------------------===//
      3 //
      4 //                     The LLVM Compiler Infrastructure
      5 //
      6 // This file is distributed under the University of Illinois Open Source
      7 // License. See LICENSE.TXT for details.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 
     11 #ifndef _LIBCPP_STRING_VIEW
     12 #define _LIBCPP_STRING_VIEW
     13 
     14 /*
     15 string_view synopsis
     16 
     17 namespace std {
     18 
     19     // 7.2, Class template basic_string_view
     20     template<class charT, class traits = char_traits<charT>>
     21         class basic_string_view;
     22 
     23     // 7.9, basic_string_view non-member comparison functions
     24     template<class charT, class traits>
     25     constexpr bool operator==(basic_string_view<charT, traits> x,
     26                               basic_string_view<charT, traits> y) noexcept;
     27     template<class charT, class traits>
     28     constexpr bool operator!=(basic_string_view<charT, traits> x,
     29                               basic_string_view<charT, traits> y) noexcept;
     30     template<class charT, class traits>
     31     constexpr bool operator< (basic_string_view<charT, traits> x,
     32                                  basic_string_view<charT, traits> y) noexcept;
     33     template<class charT, class traits>
     34     constexpr bool operator> (basic_string_view<charT, traits> x,
     35                               basic_string_view<charT, traits> y) noexcept;
     36     template<class charT, class traits>
     37     constexpr bool operator<=(basic_string_view<charT, traits> x,
     38                                  basic_string_view<charT, traits> y) noexcept;
     39     template<class charT, class traits>
     40     constexpr bool operator>=(basic_string_view<charT, traits> x,
     41                               basic_string_view<charT, traits> y) noexcept;
     42     // see below, sufficient additional overloads of comparison functions
     43 
     44     // 7.10, Inserters and extractors
     45     template<class charT, class traits>
     46       basic_ostream<charT, traits>&
     47         operator<<(basic_ostream<charT, traits>& os,
     48                    basic_string_view<charT, traits> str);
     49 
     50     // basic_string_view typedef names
     51     typedef basic_string_view<char> string_view;
     52     typedef basic_string_view<char16_t> u16string_view;
     53     typedef basic_string_view<char32_t> u32string_view;
     54     typedef basic_string_view<wchar_t> wstring_view;
     55 
     56     template<class charT, class traits = char_traits<charT>>
     57     class basic_string_view {
     58       public:
     59       // types
     60       typedef traits traits_type;
     61       typedef charT value_type;
     62       typedef charT* pointer;
     63       typedef const charT* const_pointer;
     64       typedef charT& reference;
     65       typedef const charT& const_reference;
     66       typedef implementation-defined const_iterator;
     67       typedef const_iterator iterator;
     68       typedef reverse_iterator<const_iterator> const_reverse_iterator;
     69       typedef const_reverse_iterator reverse_iterator;
     70       typedef size_t size_type;
     71       typedef ptrdiff_t difference_type;
     72       static constexpr size_type npos = size_type(-1);
     73 
     74       // 7.3, basic_string_view constructors and assignment operators
     75       constexpr basic_string_view() noexcept;
     76       constexpr basic_string_view(const basic_string_view&) noexcept = default;
     77       basic_string_view& operator=(const basic_string_view&) noexcept = default;
     78       template<class Allocator>
     79       constexpr basic_string_view(const charT* str);
     80       constexpr basic_string_view(const charT* str, size_type len);
     81 
     82       // 7.4, basic_string_view iterator support
     83       constexpr const_iterator begin() const noexcept;
     84       constexpr const_iterator end() const noexcept;
     85       constexpr const_iterator cbegin() const noexcept;
     86       constexpr const_iterator cend() const noexcept;
     87       const_reverse_iterator rbegin() const noexcept;
     88       const_reverse_iterator rend() const noexcept;
     89       const_reverse_iterator crbegin() const noexcept;
     90       const_reverse_iterator crend() const noexcept;
     91 
     92       // 7.5, basic_string_view capacity
     93       constexpr size_type size() const noexcept;
     94       constexpr size_type length() const noexcept;
     95       constexpr size_type max_size() const noexcept;
     96       constexpr bool empty() const noexcept;
     97 
     98       // 7.6, basic_string_view element access
     99       constexpr const_reference operator[](size_type pos) const;
    100       constexpr const_reference at(size_type pos) const;
    101       constexpr const_reference front() const;
    102       constexpr const_reference back() const;
    103       constexpr const_pointer data() const noexcept;
    104 
    105       // 7.7, basic_string_view modifiers
    106       constexpr void remove_prefix(size_type n);
    107       constexpr void remove_suffix(size_type n);
    108       constexpr void swap(basic_string_view& s) noexcept;
    109 
    110       size_type copy(charT* s, size_type n, size_type pos = 0) const;
    111 
    112       constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
    113       constexpr int compare(basic_string_view s) const noexcept;
    114       constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const;
    115       constexpr int compare(size_type pos1, size_type n1,
    116                             basic_string_view s, size_type pos2, size_type n2) const;
    117       constexpr int compare(const charT* s) const;
    118       constexpr int compare(size_type pos1, size_type n1, const charT* s) const;
    119       constexpr int compare(size_type pos1, size_type n1,
    120                             const charT* s, size_type n2) const;
    121       constexpr size_type find(basic_string_view s, size_type pos = 0) const noexcept;
    122       constexpr size_type find(charT c, size_type pos = 0) const noexcept;
    123       constexpr size_type find(const charT* s, size_type pos, size_type n) const;
    124       constexpr size_type find(const charT* s, size_type pos = 0) const;
    125       constexpr size_type rfind(basic_string_view s, size_type pos = npos) const noexcept;
    126       constexpr size_type rfind(charT c, size_type pos = npos) const noexcept;
    127       constexpr size_type rfind(const charT* s, size_type pos, size_type n) const;
    128       constexpr size_type rfind(const charT* s, size_type pos = npos) const;
    129       constexpr size_type find_first_of(basic_string_view s, size_type pos = 0) const noexcept;
    130       constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept;
    131       constexpr size_type find_first_of(const charT* s, size_type pos, size_type n) const;
    132       constexpr size_type find_first_of(const charT* s, size_type pos = 0) const;
    133       constexpr size_type find_last_of(basic_string_view s, size_type pos = npos) const noexcept;
    134       constexpr size_type find_last_of(charT c, size_type pos = npos) const noexcept;
    135       constexpr size_type find_last_of(const charT* s, size_type pos, size_type n) const;
    136       constexpr size_type find_last_of(const charT* s, size_type pos = npos) const;
    137       constexpr size_type find_first_not_of(basic_string_view s, size_type pos = 0) const noexcept;
    138       constexpr size_type find_first_not_of(charT c, size_type pos = 0) const noexcept;
    139       constexpr size_type find_first_not_of(const charT* s, size_type pos, size_type n) const;
    140       constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const;
    141       constexpr size_type find_last_not_of(basic_string_view s, size_type pos = npos) const noexcept;
    142       constexpr size_type find_last_not_of(charT c, size_type pos = npos) const noexcept;
    143       constexpr size_type find_last_not_of(const charT* s, size_type pos, size_type n) const;
    144       constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const;
    145 
    146       constexpr bool starts_with(basic_string_view s) const noexcept; // C++2a
    147       constexpr bool starts_with(charT c) const noexcept;             // C++2a
    148       constexpr bool starts_with(const charT* s) const;               // C++2a
    149       constexpr bool ends_with(basic_string_view s) const noexcept;   // C++2a
    150       constexpr bool ends_with(charT c) const noexcept;               // C++2a
    151       constexpr bool ends_with(const charT* s) const;                 // C++2a
    152 
    153      private:
    154       const_pointer data_;  // exposition only
    155       size_type     size_;  // exposition only
    156     };
    157 
    158   // 7.11, Hash support
    159   template <class T> struct hash;
    160   template <> struct hash<string_view>;
    161   template <> struct hash<u16string_view>;
    162   template <> struct hash<u32string_view>;
    163   template <> struct hash<wstring_view>;
    164 
    165   constexpr basic_string_view<char>     operator "" sv( const char *str,     size_t len ) noexcept;
    166   constexpr basic_string_view<wchar_t>  operator "" sv( const wchar_t *str,  size_t len ) noexcept;
    167   constexpr basic_string_view<char16_t> operator "" sv( const char16_t *str, size_t len ) noexcept;
    168   constexpr basic_string_view<char32_t> operator "" sv( const char32_t *str, size_t len ) noexcept;
    169 
    170 }  // namespace std
    171 
    172 
    173 */
    174 
    175 #include <__config>
    176 #include <__string>
    177 #include <algorithm>
    178 #include <iterator>
    179 #include <limits>
    180 #include <stdexcept>
    181 #include <__debug>
    182 
    183 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    184 #pragma GCC system_header
    185 #endif
    186 
    187 _LIBCPP_PUSH_MACROS
    188 #include <__undef_macros>
    189 
    190 
    191 _LIBCPP_BEGIN_NAMESPACE_STD
    192 
    193 template<class _CharT, class _Traits = char_traits<_CharT> >
    194 class _LIBCPP_TEMPLATE_VIS basic_string_view {
    195 public:
    196     // types
    197     typedef _Traits                                    traits_type;
    198     typedef _CharT                                     value_type;
    199     typedef _CharT*                                    pointer;
    200     typedef const _CharT*                              const_pointer;
    201     typedef _CharT&                                    reference;
    202     typedef const _CharT&                              const_reference;
    203     typedef const_pointer                              const_iterator; // See [string.view.iterators]
    204     typedef const_iterator                             iterator;
    205     typedef _VSTD::reverse_iterator<const_iterator>    const_reverse_iterator;
    206     typedef const_reverse_iterator                     reverse_iterator;
    207     typedef size_t                                     size_type;
    208     typedef ptrdiff_t                                  difference_type;
    209     static _LIBCPP_CONSTEXPR const size_type npos = -1; // size_type(-1);
    210 
    211     static_assert(is_trivial<value_type>::value, "Character type of basic_string_view must be trivial");
    212     static_assert((is_same<_CharT, typename traits_type::char_type>::value),
    213                   "traits_type::char_type must be the same type as CharT");
    214 
    215     // [string.view.cons], construct/copy
    216     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    217     basic_string_view() _NOEXCEPT : __data (nullptr), __size(0) {}
    218 
    219     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    220     basic_string_view(const basic_string_view&) _NOEXCEPT = default;
    221 
    222     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    223     basic_string_view& operator=(const basic_string_view&) _NOEXCEPT = default;
    224 
    225     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    226     basic_string_view(const _CharT* __s, size_type __len) _NOEXCEPT
    227         : __data(__s), __size(__len)
    228     {
    229 // #if _LIBCPP_STD_VER > 11
    230 //         _LIBCPP_ASSERT(__len == 0 || __s != nullptr, "string_view::string_view(_CharT *, size_t): received nullptr");
    231 // #endif
    232     }
    233 
    234     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    235     basic_string_view(const _CharT* __s)
    236         : __data(__s), __size(_Traits::length(__s)) {}
    237 
    238     // [string.view.iterators], iterators
    239     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    240     const_iterator begin()  const _NOEXCEPT { return cbegin(); }
    241 
    242     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    243     const_iterator end()    const _NOEXCEPT { return cend(); }
    244 
    245     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    246     const_iterator cbegin() const _NOEXCEPT { return __data; }
    247 
    248     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    249     const_iterator cend()   const _NOEXCEPT { return __data + __size; }
    250 
    251     _LIBCPP_CONSTEXPR_AFTER_CXX14 _LIBCPP_INLINE_VISIBILITY
    252     const_reverse_iterator rbegin()   const _NOEXCEPT { return const_reverse_iterator(cend()); }
    253 
    254     _LIBCPP_CONSTEXPR_AFTER_CXX14 _LIBCPP_INLINE_VISIBILITY
    255     const_reverse_iterator rend()     const _NOEXCEPT { return const_reverse_iterator(cbegin()); }
    256 
    257     _LIBCPP_CONSTEXPR_AFTER_CXX14 _LIBCPP_INLINE_VISIBILITY
    258     const_reverse_iterator crbegin()  const _NOEXCEPT { return const_reverse_iterator(cend()); }
    259 
    260     _LIBCPP_CONSTEXPR_AFTER_CXX14 _LIBCPP_INLINE_VISIBILITY
    261     const_reverse_iterator crend()    const _NOEXCEPT { return const_reverse_iterator(cbegin()); }
    262 
    263     // [string.view.capacity], capacity
    264     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    265     size_type size()     const _NOEXCEPT { return __size; }
    266 
    267     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    268     size_type length()   const _NOEXCEPT { return __size; }
    269 
    270     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    271     size_type max_size() const _NOEXCEPT { return numeric_limits<size_type>::max(); }
    272 
    273     _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
    274     bool empty()         const _NOEXCEPT { return __size == 0; }
    275 
    276     // [string.view.access], element access
    277     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    278     const_reference operator[](size_type __pos) const _NOEXCEPT { return __data[__pos]; }
    279 
    280     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    281     const_reference at(size_type __pos) const
    282     {
    283         return __pos >= size()
    284             ? (__throw_out_of_range("string_view::at"), __data[0])
    285             : __data[__pos];
    286     }
    287 
    288     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    289     const_reference front() const
    290     {
    291         return _LIBCPP_ASSERT(!empty(), "string_view::front(): string is empty"), __data[0];
    292     }
    293 
    294     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    295     const_reference back() const
    296     {
    297         return _LIBCPP_ASSERT(!empty(), "string_view::back(): string is empty"), __data[__size-1];
    298     }
    299 
    300     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    301     const_pointer data() const _NOEXCEPT { return __data; }
    302 
    303     // [string.view.modifiers], modifiers:
    304     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    305     void remove_prefix(size_type __n) _NOEXCEPT
    306     {
    307         _LIBCPP_ASSERT(__n <= size(), "remove_prefix() can't remove more than size()");
    308         __data += __n;
    309         __size -= __n;
    310     }
    311 
    312     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    313     void remove_suffix(size_type __n) _NOEXCEPT
    314     {
    315         _LIBCPP_ASSERT(__n <= size(), "remove_suffix() can't remove more than size()");
    316         __size -= __n;
    317     }
    318 
    319     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    320     void swap(basic_string_view& __other) _NOEXCEPT
    321     {
    322         const value_type *__p = __data;
    323         __data = __other.__data;
    324         __other.__data = __p;
    325 
    326         size_type __sz = __size;
    327         __size = __other.__size;
    328         __other.__size = __sz;
    329     }
    330 
    331     _LIBCPP_INLINE_VISIBILITY
    332     size_type copy(_CharT* __s, size_type __n, size_type __pos = 0) const
    333     {
    334         if (__pos > size())
    335             __throw_out_of_range("string_view::copy");
    336         size_type __rlen = _VSTD::min(__n, size() - __pos);
    337         _Traits::copy(__s, data() + __pos, __rlen);
    338         return __rlen;
    339     }
    340 
    341     _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
    342     basic_string_view substr(size_type __pos = 0, size_type __n = npos) const
    343     {
    344         return __pos > size()
    345             ? (__throw_out_of_range("string_view::substr"), basic_string_view())
    346             : basic_string_view(data() + __pos, _VSTD::min(__n, size() - __pos));
    347     }
    348 
    349     _LIBCPP_CONSTEXPR_AFTER_CXX11 int compare(basic_string_view __sv) const _NOEXCEPT
    350     {
    351         size_type __rlen = _VSTD::min( size(), __sv.size());
    352         int __retval = _Traits::compare(data(), __sv.data(), __rlen);
    353         if ( __retval == 0 ) // first __rlen chars matched
    354             __retval = size() == __sv.size() ? 0 : ( size() < __sv.size() ? -1 : 1 );
    355         return __retval;
    356     }
    357 
    358     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    359     int compare(size_type __pos1, size_type __n1, basic_string_view __sv) const
    360     {
    361         return substr(__pos1, __n1).compare(__sv);
    362     }
    363 
    364     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    365     int compare(                       size_type __pos1, size_type __n1, 
    366                 basic_string_view __sv, size_type __pos2, size_type __n2) const
    367     {
    368         return substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2));
    369     }
    370 
    371     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    372     int compare(const _CharT* __s) const _NOEXCEPT
    373     {
    374         return compare(basic_string_view(__s));
    375     }
    376 
    377     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    378     int compare(size_type __pos1, size_type __n1, const _CharT* __s) const
    379     {
    380         return substr(__pos1, __n1).compare(basic_string_view(__s));
    381     }
    382 
    383     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    384     int compare(size_type __pos1, size_type __n1, const _CharT* __s, size_type __n2) const
    385     {
    386         return substr(__pos1, __n1).compare(basic_string_view(__s, __n2));
    387     }
    388 
    389     // find
    390     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    391     size_type find(basic_string_view __s, size_type __pos = 0) const _NOEXCEPT
    392     {
    393         _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find(): received nullptr");
    394         return __str_find<value_type, size_type, traits_type, npos>
    395             (data(), size(), __s.data(), __pos, __s.size());
    396     }
    397 
    398     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    399     size_type find(_CharT __c, size_type __pos = 0) const _NOEXCEPT
    400     {
    401         return __str_find<value_type, size_type, traits_type, npos>
    402             (data(), size(), __c, __pos);
    403     }
    404 
    405     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    406     size_type find(const _CharT* __s, size_type __pos, size_type __n) const
    407     {
    408         _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find(): received nullptr");
    409         return __str_find<value_type, size_type, traits_type, npos>
    410             (data(), size(), __s, __pos, __n);
    411     }
    412 
    413     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    414     size_type find(const _CharT* __s, size_type __pos = 0) const
    415     {
    416         _LIBCPP_ASSERT(__s != nullptr, "string_view::find(): received nullptr");
    417         return __str_find<value_type, size_type, traits_type, npos>
    418             (data(), size(), __s, __pos, traits_type::length(__s));
    419     }
    420 
    421     // rfind
    422     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    423     size_type rfind(basic_string_view __s, size_type __pos = npos) const _NOEXCEPT
    424     {
    425         _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find(): received nullptr");
    426         return __str_rfind<value_type, size_type, traits_type, npos>
    427             (data(), size(), __s.data(), __pos, __s.size());
    428     }
    429 
    430     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    431     size_type rfind(_CharT __c, size_type __pos = npos) const _NOEXCEPT
    432     {
    433         return __str_rfind<value_type, size_type, traits_type, npos>
    434             (data(), size(), __c, __pos);
    435     }
    436 
    437     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    438     size_type rfind(const _CharT* __s, size_type __pos, size_type __n) const
    439     {
    440         _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::rfind(): received nullptr");
    441         return __str_rfind<value_type, size_type, traits_type, npos>
    442             (data(), size(), __s, __pos, __n);
    443     }
    444 
    445     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    446     size_type rfind(const _CharT* __s, size_type __pos=npos) const
    447     {
    448         _LIBCPP_ASSERT(__s != nullptr, "string_view::rfind(): received nullptr");
    449         return __str_rfind<value_type, size_type, traits_type, npos>
    450             (data(), size(), __s, __pos, traits_type::length(__s));
    451     }
    452 
    453     // find_first_of
    454     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    455     size_type find_first_of(basic_string_view __s, size_type __pos = 0) const _NOEXCEPT
    456     {
    457         _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find_first_of(): received nullptr");
    458         return __str_find_first_of<value_type, size_type, traits_type, npos>
    459             (data(), size(), __s.data(), __pos, __s.size());
    460     }
    461 
    462     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    463     size_type find_first_of(_CharT __c, size_type __pos = 0) const _NOEXCEPT
    464     { return find(__c, __pos); }
    465 
    466     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    467     size_type find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
    468     {
    469         _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_first_of(): received nullptr");
    470         return __str_find_first_of<value_type, size_type, traits_type, npos>
    471             (data(), size(), __s, __pos, __n);
    472     }
    473 
    474     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    475     size_type find_first_of(const _CharT* __s, size_type __pos=0) const
    476     {
    477         _LIBCPP_ASSERT(__s != nullptr, "string_view::find_first_of(): received nullptr");
    478         return __str_find_first_of<value_type, size_type, traits_type, npos>
    479             (data(), size(), __s, __pos, traits_type::length(__s));
    480     }
    481 
    482     // find_last_of
    483     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    484     size_type find_last_of(basic_string_view __s, size_type __pos=npos) const _NOEXCEPT
    485     {
    486         _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find_last_of(): received nullptr");
    487         return __str_find_last_of<value_type, size_type, traits_type, npos>
    488             (data(), size(), __s.data(), __pos, __s.size());
    489     }
    490 
    491     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    492     size_type find_last_of(_CharT __c, size_type __pos = npos) const _NOEXCEPT
    493     { return rfind(__c, __pos); }
    494 
    495     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    496     size_type find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
    497     {
    498         _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_last_of(): received nullptr");
    499         return __str_find_last_of<value_type, size_type, traits_type, npos>
    500             (data(), size(), __s, __pos, __n);
    501     }
    502 
    503     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    504     size_type find_last_of(const _CharT* __s, size_type __pos=npos) const
    505     {
    506         _LIBCPP_ASSERT(__s != nullptr, "string_view::find_last_of(): received nullptr");
    507         return __str_find_last_of<value_type, size_type, traits_type, npos>
    508             (data(), size(), __s, __pos, traits_type::length(__s));
    509     }
    510 
    511     // find_first_not_of
    512     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    513     size_type find_first_not_of(basic_string_view __s, size_type __pos=0) const _NOEXCEPT
    514     {
    515         _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find_first_not_of(): received nullptr");
    516         return __str_find_first_not_of<value_type, size_type, traits_type, npos>
    517             (data(), size(), __s.data(), __pos, __s.size());
    518     }
    519 
    520     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    521     size_type find_first_not_of(_CharT __c, size_type __pos=0) const _NOEXCEPT
    522     {
    523         return __str_find_first_not_of<value_type, size_type, traits_type, npos>
    524             (data(), size(), __c, __pos);
    525     }
    526 
    527     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    528     size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
    529     {
    530         _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_first_not_of(): received nullptr");
    531         return __str_find_first_not_of<value_type, size_type, traits_type, npos>
    532             (data(), size(), __s, __pos, __n);
    533     }
    534 
    535     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    536     size_type find_first_not_of(const _CharT* __s, size_type __pos=0) const
    537     {
    538         _LIBCPP_ASSERT(__s != nullptr, "string_view::find_first_not_of(): received nullptr");
    539         return __str_find_first_not_of<value_type, size_type, traits_type, npos>
    540             (data(), size(), __s, __pos, traits_type::length(__s));
    541     }
    542 
    543     // find_last_not_of
    544     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    545     size_type find_last_not_of(basic_string_view __s, size_type __pos=npos) const _NOEXCEPT
    546     {
    547         _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find_last_not_of(): received nullptr");
    548         return __str_find_last_not_of<value_type, size_type, traits_type, npos>
    549             (data(), size(), __s.data(), __pos, __s.size());
    550     }
    551 
    552     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    553     size_type find_last_not_of(_CharT __c, size_type __pos=npos) const _NOEXCEPT
    554     {
    555         return __str_find_last_not_of<value_type, size_type, traits_type, npos>
    556             (data(), size(), __c, __pos);
    557     }
    558 
    559     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    560     size_type find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
    561     {
    562         _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_last_not_of(): received nullptr");
    563         return __str_find_last_not_of<value_type, size_type, traits_type, npos>
    564             (data(), size(), __s, __pos, __n);
    565     }
    566 
    567     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    568     size_type find_last_not_of(const _CharT* __s, size_type __pos=npos) const
    569     {
    570         _LIBCPP_ASSERT(__s != nullptr, "string_view::find_last_not_of(): received nullptr");
    571         return __str_find_last_not_of<value_type, size_type, traits_type, npos>
    572             (data(), size(), __s, __pos, traits_type::length(__s));
    573     }
    574 
    575 #if _LIBCPP_STD_VER > 17
    576     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    577     bool starts_with(basic_string_view __s) const _NOEXCEPT
    578     { return size() >= __s.size() && compare(0, __s.size(), __s) == 0; }
    579 
    580     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    581     bool starts_with(value_type __c) const _NOEXCEPT
    582     { return !empty() && _Traits::eq(front(), __c); }
    583 
    584     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    585     bool starts_with(const value_type* __s) const _NOEXCEPT
    586     { return starts_with(basic_string_view(__s)); }
    587 
    588     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    589     bool ends_with(basic_string_view __s) const _NOEXCEPT
    590     { return size() >= __s.size() && compare(size() - __s.size(), npos, __s) == 0; }
    591 
    592     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    593     bool ends_with(value_type __c) const _NOEXCEPT
    594     { return !empty() && _Traits::eq(back(), __c); }
    595 
    596     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    597     bool ends_with(const value_type* __s) const _NOEXCEPT
    598     { return ends_with(basic_string_view(__s)); }
    599 #endif
    600 
    601 private:
    602     const   value_type* __data;
    603     size_type           __size;
    604 };
    605 
    606 
    607 // [string.view.comparison]
    608 // operator ==
    609 template<class _CharT, class _Traits>
    610 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    611 bool operator==(basic_string_view<_CharT, _Traits> __lhs,
    612                 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
    613 {
    614     if ( __lhs.size() != __rhs.size()) return false;
    615     return __lhs.compare(__rhs) == 0;
    616 }
    617 
    618 template<class _CharT, class _Traits>
    619 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    620 bool operator==(basic_string_view<_CharT, _Traits> __lhs,
    621                 typename common_type<basic_string_view<_CharT, _Traits> >::type __rhs) _NOEXCEPT
    622 {
    623     if ( __lhs.size() != __rhs.size()) return false;
    624     return __lhs.compare(__rhs) == 0;
    625 }
    626 
    627 template<class _CharT, class _Traits>
    628 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    629 bool operator==(typename common_type<basic_string_view<_CharT, _Traits> >::type __lhs, 
    630                 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
    631 {
    632     if ( __lhs.size() != __rhs.size()) return false;
    633     return __lhs.compare(__rhs) == 0;
    634 }
    635 
    636 
    637 // operator !=
    638 template<class _CharT, class _Traits>
    639 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    640 bool operator!=(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
    641 {
    642     if ( __lhs.size() != __rhs.size())
    643         return true;
    644     return __lhs.compare(__rhs) != 0;
    645 }
    646 
    647 template<class _CharT, class _Traits>
    648 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    649 bool operator!=(basic_string_view<_CharT, _Traits> __lhs,
    650                 typename common_type<basic_string_view<_CharT, _Traits> >::type __rhs) _NOEXCEPT
    651 {
    652     if ( __lhs.size() != __rhs.size())
    653         return true;
    654     return __lhs.compare(__rhs) != 0;
    655 }
    656 
    657 template<class _CharT, class _Traits>
    658 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    659 bool operator!=(typename common_type<basic_string_view<_CharT, _Traits> >::type __lhs, 
    660                 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
    661 {
    662     if ( __lhs.size() != __rhs.size())
    663         return true;
    664     return __lhs.compare(__rhs) != 0;
    665 }
    666 
    667 
    668 // operator <
    669 template<class _CharT, class _Traits>
    670 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    671 bool operator<(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
    672 {
    673     return __lhs.compare(__rhs) < 0;
    674 }
    675 
    676 template<class _CharT, class _Traits>
    677 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    678 bool operator<(basic_string_view<_CharT, _Traits> __lhs,
    679                 typename common_type<basic_string_view<_CharT, _Traits> >::type __rhs) _NOEXCEPT
    680 {
    681     return __lhs.compare(__rhs) < 0;
    682 }
    683 
    684 template<class _CharT, class _Traits>
    685 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    686 bool operator<(typename common_type<basic_string_view<_CharT, _Traits> >::type __lhs, 
    687                 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
    688 {
    689     return __lhs.compare(__rhs) < 0;
    690 }
    691 
    692 
    693 // operator >
    694 template<class _CharT, class _Traits>
    695 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    696 bool operator> (basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
    697 {
    698     return __lhs.compare(__rhs) > 0;
    699 }
    700 
    701 template<class _CharT, class _Traits>
    702 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    703 bool operator>(basic_string_view<_CharT, _Traits> __lhs,
    704                 typename common_type<basic_string_view<_CharT, _Traits> >::type __rhs) _NOEXCEPT
    705 {
    706     return __lhs.compare(__rhs) > 0;
    707 }
    708 
    709 template<class _CharT, class _Traits>
    710 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    711 bool operator>(typename common_type<basic_string_view<_CharT, _Traits> >::type __lhs, 
    712                 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
    713 {
    714     return __lhs.compare(__rhs) > 0;
    715 }
    716 
    717 
    718 // operator <=
    719 template<class _CharT, class _Traits>
    720 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    721 bool operator<=(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
    722 {
    723     return __lhs.compare(__rhs) <= 0;
    724 }
    725 
    726 template<class _CharT, class _Traits>
    727 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    728 bool operator<=(basic_string_view<_CharT, _Traits> __lhs,
    729                 typename common_type<basic_string_view<_CharT, _Traits> >::type __rhs) _NOEXCEPT
    730 {
    731     return __lhs.compare(__rhs) <= 0;
    732 }
    733 
    734 template<class _CharT, class _Traits>
    735 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    736 bool operator<=(typename common_type<basic_string_view<_CharT, _Traits> >::type __lhs, 
    737                 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
    738 {
    739     return __lhs.compare(__rhs) <= 0;
    740 }
    741 
    742 
    743 // operator >=
    744 template<class _CharT, class _Traits>
    745 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    746 bool operator>=(basic_string_view<_CharT, _Traits> __lhs, basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
    747 {
    748     return __lhs.compare(__rhs) >= 0;
    749 }
    750 
    751 
    752 template<class _CharT, class _Traits>
    753 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    754 bool operator>=(basic_string_view<_CharT, _Traits> __lhs,
    755                 typename common_type<basic_string_view<_CharT, _Traits> >::type __rhs) _NOEXCEPT
    756 {
    757     return __lhs.compare(__rhs) >= 0;
    758 }
    759 
    760 template<class _CharT, class _Traits>
    761 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    762 bool operator>=(typename common_type<basic_string_view<_CharT, _Traits> >::type __lhs, 
    763                 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
    764 {
    765     return __lhs.compare(__rhs) >= 0;
    766 }
    767 
    768 typedef basic_string_view<char>     string_view;
    769 typedef basic_string_view<char16_t> u16string_view;
    770 typedef basic_string_view<char32_t> u32string_view;
    771 typedef basic_string_view<wchar_t>  wstring_view;
    772 
    773 // [string.view.hash]
    774 template<class _CharT, class _Traits>
    775 struct _LIBCPP_TEMPLATE_VIS hash<basic_string_view<_CharT, _Traits> >
    776     : public unary_function<basic_string_view<_CharT, _Traits>, size_t>
    777 {
    778     size_t operator()(const basic_string_view<_CharT, _Traits> __val) const _NOEXCEPT;
    779 };
    780 
    781 template<class _CharT, class _Traits>
    782 size_t
    783 hash<basic_string_view<_CharT, _Traits> >::operator()(
    784         const basic_string_view<_CharT, _Traits> __val) const _NOEXCEPT
    785 {
    786     return __do_string_hash(__val.data(), __val.data() + __val.size());
    787 }
    788 
    789 
    790 #if _LIBCPP_STD_VER > 11 
    791 inline namespace literals
    792 {
    793   inline namespace string_view_literals
    794   {
    795     inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
    796     basic_string_view<char> operator "" sv(const char *__str, size_t __len) _NOEXCEPT
    797     {
    798         return basic_string_view<char> (__str, __len);
    799     }
    800 
    801     inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
    802     basic_string_view<wchar_t> operator "" sv(const wchar_t *__str, size_t __len) _NOEXCEPT
    803     {
    804         return basic_string_view<wchar_t> (__str, __len);
    805     }
    806 
    807     inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
    808     basic_string_view<char16_t> operator "" sv(const char16_t *__str, size_t __len) _NOEXCEPT
    809     {
    810         return basic_string_view<char16_t> (__str, __len);
    811     }
    812 
    813     inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
    814     basic_string_view<char32_t> operator "" sv(const char32_t *__str, size_t __len) _NOEXCEPT
    815     {
    816         return basic_string_view<char32_t> (__str, __len);
    817     }
    818   }
    819 }
    820 #endif
    821 _LIBCPP_END_NAMESPACE_STD
    822 
    823 _LIBCPP_POP_MACROS
    824 
    825 #endif // _LIBCPP_STRING_VIEW
    826