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