[gcc/testsuite]
[official-gcc.git] / libstdc++-v3 / include / std / string_view
blob97316ef49ab92f754150ef3ce5a3de69ff1a6e8e
1 // Components for manipulating non-owning sequences of characters -*- C++ -*-
3 // Copyright (C) 2013-2017 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file string_view
26  *  This is a Standard C++ Library header.
27  */
30 // N3762 basic_string_view library
33 #ifndef _GLIBCXX_STRING_VIEW
34 #define _GLIBCXX_STRING_VIEW 1
36 #pragma GCC system_header
38 #if __cplusplus >= 201703L
40 #include <limits>
41 #include <iosfwd>
42 #include <bits/char_traits.h>
43 #include <bits/functional_hash.h>
44 #include <bits/range_access.h>
46 namespace std _GLIBCXX_VISIBILITY(default)
48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
50 #define __cpp_lib_string_view 201603
52   /**
53    *  @class basic_string_view <string_view>
54    *  @brief  A non-owning reference to a string.
55    *
56    *  @ingroup strings
57    *  @ingroup sequences
58    *
59    *  @tparam _CharT  Type of character
60    *  @tparam _Traits  Traits for character type, defaults to
61    *                   char_traits<_CharT>.
62    *
63    *  A basic_string_view looks like this:
64    *
65    *  @code
66    *    _CharT*    _M_str
67    *    size_t     _M_len
68    *  @endcode
69    */
70   template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
71     class basic_string_view
72     {
73     public:
75       // types
76       using traits_type = _Traits;
77       using value_type = _CharT;
78       using pointer = const _CharT*;
79       using const_pointer = const _CharT*;
80       using reference = const _CharT&;
81       using const_reference = const _CharT&;
82       using const_iterator = const _CharT*;
83       using iterator = const_iterator;
84       using const_reverse_iterator = std::reverse_iterator<const_iterator>;
85       using reverse_iterator = const_reverse_iterator;
86       using size_type = size_t;
87       using difference_type = ptrdiff_t;
88       static constexpr size_type npos = size_type(-1);
90       // [string.view.cons], construct/copy
92       constexpr
93       basic_string_view() noexcept
94       : _M_len{0}, _M_str{nullptr}
95       { }
97       constexpr basic_string_view(const basic_string_view&) noexcept = default;
99       constexpr basic_string_view(const _CharT* __str)
100       : _M_len{__str == nullptr ? 0 : traits_type::length(__str)},
101         _M_str{__str}
102       { }
104       constexpr basic_string_view(const _CharT* __str, size_type __len)
105       : _M_len{__len},
106         _M_str{__str}
107       { }
109       constexpr basic_string_view&
110       operator=(const basic_string_view&) noexcept = default;
112       // [string.view.iterators], iterators
114       constexpr const_iterator
115       begin() const noexcept
116       { return this->_M_str; }
118       constexpr const_iterator
119       end() const noexcept
120       { return this->_M_str + this->_M_len; }
122       constexpr const_iterator
123       cbegin() const noexcept
124       { return this->_M_str; }
126       constexpr const_iterator
127       cend() const noexcept
128       { return this->_M_str + this->_M_len; }
130       constexpr const_reverse_iterator
131       rbegin() const noexcept
132       { return const_reverse_iterator(this->end()); }
134       constexpr const_reverse_iterator
135       rend() const noexcept
136       { return const_reverse_iterator(this->begin()); }
138       constexpr const_reverse_iterator
139       crbegin() const noexcept
140       { return const_reverse_iterator(this->end()); }
142       constexpr const_reverse_iterator
143       crend() const noexcept
144       { return const_reverse_iterator(this->begin()); }
146       // [string.view.capacity], capacity
148       constexpr size_type
149       size() const noexcept
150       { return this->_M_len; }
152       constexpr size_type
153       length() const noexcept
154       { return _M_len; }
156       constexpr size_type
157       max_size() const noexcept
158       {
159         return (npos - sizeof(size_type) - sizeof(void*))
160                 / sizeof(value_type) / 4;
161       }
163       constexpr bool
164       empty() const noexcept
165       { return this->_M_len == 0; }
167       // [string.view.access], element access
169       constexpr const _CharT&
170       operator[](size_type __pos) const noexcept
171       {
172         // TODO: Assert to restore in a way compatible with the constexpr.
173         // __glibcxx_assert(__pos < this->_M_len);
174         return *(this->_M_str + __pos);
175       }
177       constexpr const _CharT&
178       at(size_type __pos) const
179       {
180         return __pos < this->_M_len
181              ? *(this->_M_str + __pos)
182              : (__throw_out_of_range_fmt(__N("basic_string_view::at: __pos "
183                                              "(which is %zu) >= this->size() "
184                                              "(which is %zu)"),
185                                          __pos, this->size()),
186                 *this->_M_str);
187       }
189       constexpr const _CharT&
190       front() const
191       {
192         // TODO: Assert to restore in a way compatible with the constexpr.
193         // __glibcxx_assert(this->_M_len > 0);
194         return *this->_M_str;
195       }
197       constexpr const _CharT&
198       back() const
199       {
200         // TODO: Assert to restore in a way compatible with the constexpr.
201         // __glibcxx_assert(this->_M_len > 0);
202         return *(this->_M_str + this->_M_len - 1);
203       }
205       constexpr const _CharT*
206       data() const noexcept
207       { return this->_M_str; }
209       // [string.view.modifiers], modifiers:
211       constexpr void
212       remove_prefix(size_type __n)
213       {
214         __glibcxx_assert(this->_M_len >= __n);
215         this->_M_str += __n;
216         this->_M_len -= __n;
217       }
219       constexpr void
220       remove_suffix(size_type __n)
221       { this->_M_len -= __n; }
223       constexpr void
224       swap(basic_string_view& __sv) noexcept
225       {
226         auto __tmp = *this;
227         *this = __sv;
228         __sv = __tmp;
229       }
232       // [string.view.ops], string operations:
234       size_type
235       copy(_CharT* __str, size_type __n, size_type __pos = 0) const
236       {
237         __glibcxx_requires_string_len(__str, __n);
238         if (__pos > this->_M_len)
239           __throw_out_of_range_fmt(__N("basic_string_view::copy: __pos "
240                                        "(which is %zu) > this->size() "
241                                        "(which is %zu)"),
242                                    __pos, this->size());
243         size_type __rlen{std::min(__n, size_type{this->_M_len  - __pos})};
244         for (auto __begin = this->_M_str + __pos,
245              __end = __begin + __rlen; __begin != __end;)
246           *__str++ = *__begin++;
247         return __rlen;
248       }
251       // [string.view.ops], string operations:
253       constexpr basic_string_view
254       substr(size_type __pos, size_type __n=npos) const
255       {
256         return __pos <= this->_M_len
257              ? basic_string_view{this->_M_str + __pos,
258                                 std::min(__n, size_type{this->_M_len  - __pos})}
259              : (__throw_out_of_range_fmt(__N("basic_string_view::substr: __pos "
260                                              "(which is %zu) > this->size() "
261                                              "(which is %zu)"),
262                                      __pos, this->size()), basic_string_view{});
263       }
265       constexpr int
266       compare(basic_string_view __str) const noexcept
267       {
268         int __ret = traits_type::compare(this->_M_str, __str._M_str,
269                                          std::min(this->_M_len, __str._M_len));
270         if (__ret == 0)
271           __ret = _S_compare(this->_M_len, __str._M_len);
272         return __ret;
273       }
275       constexpr int
276       compare(size_type __pos1, size_type __n1, basic_string_view __str) const
277       { return this->substr(__pos1, __n1).compare(__str); }
279       constexpr int
280       compare(size_type __pos1, size_type __n1,
281               basic_string_view __str, size_type __pos2, size_type __n2) const
282       { return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); }
284       constexpr int
285       compare(const _CharT* __str) const noexcept
286       { return this->compare(basic_string_view{__str}); }
288       constexpr int
289       compare(size_type __pos1, size_type __n1, const _CharT* __str) const
290       { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); }
292       constexpr int
293       compare(size_type __pos1, size_type __n1,
294               const _CharT* __str, size_type __n2) const
295       {
296         return this->substr(__pos1, __n1)
297                    .compare(basic_string_view(__str, __n2));
298       }
300       constexpr size_type
301       find(basic_string_view __str, size_type __pos = 0) const noexcept
302       { return this->find(__str._M_str, __pos, __str._M_len); }
304       constexpr size_type
305       find(_CharT __c, size_type __pos=0) const noexcept;
307       constexpr size_type
308       find(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
310       constexpr size_type
311       find(const _CharT* __str, size_type __pos=0) const noexcept
312       { return this->find(__str, __pos, traits_type::length(__str)); }
314       constexpr size_type
315       rfind(basic_string_view __str, size_type __pos = npos) const noexcept
316       { return this->rfind(__str._M_str, __pos, __str._M_len); }
318       constexpr size_type
319       rfind(_CharT __c, size_type __pos = npos) const noexcept;
321       constexpr size_type
322       rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
324       constexpr size_type
325       rfind(const _CharT* __str, size_type __pos = npos) const noexcept
326       { return this->rfind(__str, __pos, traits_type::length(__str)); }
328       constexpr size_type
329       find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept
330       { return this->find_first_of(__str._M_str, __pos, __str._M_len); }
332       constexpr size_type
333       find_first_of(_CharT __c, size_type __pos = 0) const noexcept
334       { return this->find(__c, __pos); }
336       constexpr size_type
337       find_first_of(const _CharT* __str, size_type __pos, size_type __n) const;
339       constexpr size_type
340       find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept
341       { return this->find_first_of(__str, __pos, traits_type::length(__str)); }
343       constexpr size_type
344       find_last_of(basic_string_view __str,
345                    size_type __pos = npos) const noexcept
346       { return this->find_last_of(__str._M_str, __pos, __str._M_len); }
348       constexpr size_type
349       find_last_of(_CharT __c, size_type __pos=npos) const noexcept
350       { return this->rfind(__c, __pos); }
352       constexpr size_type
353       find_last_of(const _CharT* __str, size_type __pos, size_type __n) const;
355       constexpr size_type
356       find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept
357       { return this->find_last_of(__str, __pos, traits_type::length(__str)); }
359       constexpr size_type
360       find_first_not_of(basic_string_view __str,
361                         size_type __pos = 0) const noexcept
362       { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); }
364       constexpr size_type
365       find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept;
367       constexpr size_type
368       find_first_not_of(const _CharT* __str,
369                         size_type __pos, size_type __n) const;
371       constexpr size_type
372       find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept
373       {
374         return this->find_first_not_of(__str, __pos,
375                                        traits_type::length(__str));
376       }
378       constexpr size_type
379       find_last_not_of(basic_string_view __str,
380                        size_type __pos = npos) const noexcept
381       { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); }
383       constexpr size_type
384       find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept;
386       constexpr size_type
387       find_last_not_of(const _CharT* __str,
388                        size_type __pos, size_type __n) const;
390       constexpr size_type
391       find_last_not_of(const _CharT* __str,
392                        size_type __pos = npos) const noexcept
393       {
394         return this->find_last_not_of(__str, __pos,
395                                       traits_type::length(__str));
396       }
398       constexpr size_type
399       _M_check(size_type __pos, const char* __s) const
400       {
401         if (__pos > this->size())
402           __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > "
403                                        "this->size() (which is %zu)"),
404                                    __s, __pos, this->size());
405         return __pos;
406       }
408       // NB: _M_limit doesn't check for a bad __pos value.
409       constexpr size_type
410       _M_limit(size_type __pos, size_type __off) const _GLIBCXX_NOEXCEPT
411       {
412         const bool __testoff =  __off < this->size() - __pos;
413         return __testoff ? __off : this->size() - __pos;
414       }
415       
416     private:
418       static constexpr int
419       _S_compare(size_type __n1, size_type __n2) noexcept
420       {
421         return difference_type{__n1 - __n2} > std::numeric_limits<int>::max()
422              ? std::numeric_limits<int>::max()
423              : difference_type{__n1 - __n2} < std::numeric_limits<int>::min()
424              ? std::numeric_limits<int>::min()
425              : static_cast<int>(difference_type{__n1 - __n2});
426       }
428       size_t        _M_len;
429       const _CharT* _M_str;
430     };
432   // [string.view.comparison], non-member basic_string_view comparison function
434   namespace __detail
435   {
436     // Identity transform to create a non-deduced context, so that only one
437     // argument participates in template argument deduction and the other
438     // argument gets implicitly converted to the deduced type. See n3766.html.
439     template<typename _Tp>
440       using __idt = common_type_t<_Tp>;
441   }
443   template<typename _CharT, typename _Traits>
444     constexpr bool
445     operator==(basic_string_view<_CharT, _Traits> __x,
446                basic_string_view<_CharT, _Traits> __y) noexcept
447     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
449   template<typename _CharT, typename _Traits>
450     constexpr bool
451     operator==(basic_string_view<_CharT, _Traits> __x,
452                __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
453     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
455   template<typename _CharT, typename _Traits>
456     constexpr bool
457     operator==(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
458                basic_string_view<_CharT, _Traits> __y) noexcept
459     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
461   template<typename _CharT, typename _Traits>
462     constexpr bool
463     operator!=(basic_string_view<_CharT, _Traits> __x,
464                basic_string_view<_CharT, _Traits> __y) noexcept
465     { return !(__x == __y); }
467   template<typename _CharT, typename _Traits>
468     constexpr bool
469     operator!=(basic_string_view<_CharT, _Traits> __x,
470                __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
471     { return !(__x == __y); }
473   template<typename _CharT, typename _Traits>
474     constexpr bool
475     operator!=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
476                basic_string_view<_CharT, _Traits> __y) noexcept
477     { return !(__x == __y); }
479   template<typename _CharT, typename _Traits>
480     constexpr bool
481     operator< (basic_string_view<_CharT, _Traits> __x,
482                basic_string_view<_CharT, _Traits> __y) noexcept
483     { return __x.compare(__y) < 0; }
485   template<typename _CharT, typename _Traits>
486     constexpr bool
487     operator< (basic_string_view<_CharT, _Traits> __x,
488                __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
489     { return __x.compare(__y) < 0; }
491   template<typename _CharT, typename _Traits>
492     constexpr bool
493     operator< (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
494                basic_string_view<_CharT, _Traits> __y) noexcept
495     { return __x.compare(__y) < 0; }
497   template<typename _CharT, typename _Traits>
498     constexpr bool
499     operator> (basic_string_view<_CharT, _Traits> __x,
500                basic_string_view<_CharT, _Traits> __y) noexcept
501     { return __x.compare(__y) > 0; }
503   template<typename _CharT, typename _Traits>
504     constexpr bool
505     operator> (basic_string_view<_CharT, _Traits> __x,
506                __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
507     { return __x.compare(__y) > 0; }
509   template<typename _CharT, typename _Traits>
510     constexpr bool
511     operator> (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
512                basic_string_view<_CharT, _Traits> __y) noexcept
513     { return __x.compare(__y) > 0; }
515   template<typename _CharT, typename _Traits>
516     constexpr bool
517     operator<=(basic_string_view<_CharT, _Traits> __x,
518                basic_string_view<_CharT, _Traits> __y) noexcept
519     { return __x.compare(__y) <= 0; }
521   template<typename _CharT, typename _Traits>
522     constexpr bool
523     operator<=(basic_string_view<_CharT, _Traits> __x,
524                __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
525     { return __x.compare(__y) <= 0; }
527   template<typename _CharT, typename _Traits>
528     constexpr bool
529     operator<=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
530                basic_string_view<_CharT, _Traits> __y) noexcept
531     { return __x.compare(__y) <= 0; }
533   template<typename _CharT, typename _Traits>
534     constexpr bool
535     operator>=(basic_string_view<_CharT, _Traits> __x,
536                basic_string_view<_CharT, _Traits> __y) noexcept
537     { return __x.compare(__y) >= 0; }
539   template<typename _CharT, typename _Traits>
540     constexpr bool
541     operator>=(basic_string_view<_CharT, _Traits> __x,
542                __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
543     { return __x.compare(__y) >= 0; }
545   template<typename _CharT, typename _Traits>
546     constexpr bool
547     operator>=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
548                basic_string_view<_CharT, _Traits> __y) noexcept
549     { return __x.compare(__y) >= 0; }
551   // [string.view.io], Inserters and extractors
552   template<typename _CharT, typename _Traits>
553     inline basic_ostream<_CharT, _Traits>&
554     operator<<(basic_ostream<_CharT, _Traits>& __os,
555                basic_string_view<_CharT,_Traits> __str)
556     { return __ostream_insert(__os, __str.data(), __str.size()); }
559   // basic_string_view typedef names
561   using string_view = basic_string_view<char>;
562 #ifdef _GLIBCXX_USE_WCHAR_T
563   using wstring_view = basic_string_view<wchar_t>;
564 #endif
565 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
566   using u16string_view = basic_string_view<char16_t>;
567   using u32string_view = basic_string_view<char32_t>;
568 #endif
570   // [string.view.hash], hash support:
572   template<typename _Tp>
573     struct hash;
575   template<>
576     struct hash<string_view>
577     : public __hash_base<size_t, string_view>
578     {
579       size_t
580       operator()(const string_view& __str) const noexcept
581       { return std::_Hash_impl::hash(__str.data(), __str.length()); }
582     };
584   template<>
585     struct __is_fast_hash<hash<string_view>> : std::false_type
586     { };
588 #ifdef _GLIBCXX_USE_WCHAR_T
589   template<>
590     struct hash<wstring_view>
591     : public __hash_base<size_t, wstring>
592     {
593       size_t
594       operator()(const wstring_view& __s) const noexcept
595       { return std::_Hash_impl::hash(__s.data(),
596                                      __s.length() * sizeof(wchar_t)); }
597     };
599   template<>
600     struct __is_fast_hash<hash<wstring_view>> : std::false_type
601     { };
602 #endif
604 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
605   template<>
606     struct hash<u16string_view>
607     : public __hash_base<size_t, u16string_view>
608     {
609       size_t
610       operator()(const u16string_view& __s) const noexcept
611       { return std::_Hash_impl::hash(__s.data(),
612                                      __s.length() * sizeof(char16_t)); }
613     };
615   template<>
616     struct __is_fast_hash<hash<u16string_view>> : std::false_type
617     { };
619   template<>
620     struct hash<u32string_view>
621     : public __hash_base<size_t, u32string_view>
622     {
623       size_t
624       operator()(const u32string_view& __s) const noexcept
625       { return std::_Hash_impl::hash(__s.data(),
626                                      __s.length() * sizeof(char32_t)); }
627     };
629   template<>
630     struct __is_fast_hash<hash<u32string_view>> : std::false_type
631     { };
632 #endif
634   inline namespace literals
635   {
636   inline namespace string_view_literals
637   {
638     inline constexpr basic_string_view<char>
639     operator""sv(const char* __str, size_t __len)
640     { return basic_string_view<char>{__str, __len}; }
642 #ifdef _GLIBCXX_USE_WCHAR_T
643     inline constexpr basic_string_view<wchar_t>
644     operator""sv(const wchar_t* __str, size_t __len)
645     { return basic_string_view<wchar_t>{__str, __len}; }
646 #endif
648 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
649     inline constexpr basic_string_view<char16_t>
650     operator""sv(const char16_t* __str, size_t __len)
651     { return basic_string_view<char16_t>{__str, __len}; }
653     inline constexpr basic_string_view<char32_t>
654     operator""sv(const char32_t* __str, size_t __len)
655     { return basic_string_view<char32_t>{__str, __len}; }
656 #endif
657   } // namespace string_literals
658   } // namespace literals
660 _GLIBCXX_END_NAMESPACE_VERSION
661 } // namespace std
663 #include <bits/string_view.tcc>
665 #endif // __cplusplus <= 201402L
667 #endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW