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