d: Merge upstream dmd, druntime 66b93fc24a, phobos 0c28620c3
[official-gcc.git] / libstdc++-v3 / include / experimental / string_view
blobb273f806eb935e06c7f4bc4fa99c715b8367dc9b
1 // Components for manipulating non-owning sequences of characters -*- C++ -*-
3 // Copyright (C) 2013-2025 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 experimental/string_view
26  *  This is a TS C++ Library header.
27  *  @ingroup libfund-ts
28  */
31 // N3762 basic_string_view library
34 #ifndef _GLIBCXX_EXPERIMENTAL_STRING_VIEW
35 #define _GLIBCXX_EXPERIMENTAL_STRING_VIEW 1
37 #ifdef _GLIBCXX_SYSHDR
38 #pragma GCC system_header
39 #endif
41 #include <bits/requires_hosted.h> // experimental is currently omitted
43 #if __cplusplus >= 201402L
45 #include <string>
46 #include <limits>
47 #include <bits/ranges_base.h> // enable_borrowed_range, enable_view
48 #include <experimental/bits/lfts_config.h>
50 namespace std _GLIBCXX_VISIBILITY(default)
52 _GLIBCXX_BEGIN_NAMESPACE_VERSION
54 namespace experimental
56 inline namespace fundamentals_v1
58 #define __cpp_lib_experimental_string_view 201411
60   /**
61    *  @class basic_string_view <experimental/string_view>
62    *  @brief  A non-owning reference to a string.
63    *
64    *  @ingroup strings
65    *  @ingroup sequences
66    *  @ingroup libfund-ts
67    *
68    *  @tparam _CharT  Type of character
69    *  @tparam _Traits  Traits for character type, defaults to
70    *                   char_traits<_CharT>.
71    *
72    *  A basic_string_view looks like this:
73    *
74    *  @code
75    *    _CharT*    _M_str
76    *    size_t     _M_len
77    *  @endcode
78    */
79   template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
80     class basic_string_view
81     {
82     public:
84       // types
85       using traits_type = _Traits;
86       using value_type = _CharT;
87       using pointer = _CharT*;
88       using const_pointer = const _CharT*;
89       using reference = _CharT&;
90       using const_reference = const _CharT&;
91       using const_iterator = const _CharT*;
92       using iterator = const_iterator;
93       using const_reverse_iterator = std::reverse_iterator<const_iterator>;
94       using reverse_iterator = const_reverse_iterator;
95       using size_type = size_t;
96       using difference_type = ptrdiff_t;
97       static constexpr size_type npos = size_type(-1);
99       // [string.view.cons], construct/copy
101       constexpr
102       basic_string_view() noexcept
103       : _M_len{0}, _M_str{nullptr}
104       { }
106       constexpr basic_string_view(const basic_string_view&) noexcept = default;
108       template<typename _Allocator>
109         basic_string_view(const basic_string<_CharT, _Traits,
110                           _Allocator>& __str) noexcept
111         : _M_len{__str.length()}, _M_str{__str.data()}
112         { }
114       constexpr basic_string_view(const _CharT* __str)
115       : _M_len{__str == nullptr ? 0 : traits_type::length(__str)},
116         _M_str{__str}
117       { }
119       constexpr basic_string_view(const _CharT* __str, size_type __len)
120       : _M_len{__len},
121         _M_str{__str}
122       { }
124       basic_string_view&
125       operator=(const basic_string_view&) noexcept = default;
127       // [string.view.iterators], iterators
129       constexpr const_iterator
130       begin() const noexcept
131       { return this->_M_str; }
133       constexpr const_iterator
134       end() const noexcept
135       { return this->_M_str + this->_M_len; }
137       constexpr const_iterator
138       cbegin() const noexcept
139       { return this->_M_str; }
141       constexpr const_iterator
142       cend() const noexcept
143       { return this->_M_str + this->_M_len; }
145       const_reverse_iterator
146       rbegin() const noexcept
147       { return const_reverse_iterator(this->end()); }
149       const_reverse_iterator
150       rend() const noexcept
151       { return const_reverse_iterator(this->begin()); }
153       const_reverse_iterator
154       crbegin() const noexcept
155       { return const_reverse_iterator(this->end()); }
157       const_reverse_iterator
158       crend() const noexcept
159       { return const_reverse_iterator(this->begin()); }
161       // [string.view.capacity], capacity
163       constexpr size_type
164       size() const noexcept
165       { return this->_M_len; }
167       constexpr size_type
168       length() const noexcept
169       { return _M_len; }
171       constexpr size_type
172       max_size() const noexcept
173       {
174         return (npos - sizeof(size_type) - sizeof(void*))
175                 / sizeof(value_type) / 4;
176       }
178       _GLIBCXX_NODISCARD constexpr bool
179       empty() const noexcept
180       { return this->_M_len == 0; }
182       // [string.view.access], element access
184       constexpr const _CharT&
185       operator[](size_type __pos) const
186       {
187         __glibcxx_assert(__pos < this->_M_len);
188         return *(this->_M_str + __pos);
189       }
191       constexpr const _CharT&
192       at(size_type __pos) const
193       {
194         return __pos < this->_M_len
195              ? *(this->_M_str + __pos)
196              : (__throw_out_of_range_fmt(__N("basic_string_view::at: __pos "
197                                              "(which is %zu) >= this->size() "
198                                              "(which is %zu)"),
199                                          __pos, this->size()),
200                 *this->_M_str);
201       }
203       constexpr const _CharT&
204       front() const
205       {
206         __glibcxx_assert(this->_M_len > 0);
207         return *this->_M_str;
208       }
210       constexpr const _CharT&
211       back() const
212       {
213         __glibcxx_assert(this->_M_len > 0);
214         return *(this->_M_str + this->_M_len - 1);
215       }
217       constexpr const _CharT*
218       data() const noexcept
219       { return this->_M_str; }
221       // [string.view.modifiers], modifiers:
223       constexpr void
224       remove_prefix(size_type __n)
225       {
226         __glibcxx_assert(this->_M_len >= __n);
227         this->_M_str += __n;
228         this->_M_len -= __n;
229       }
231       constexpr void
232       remove_suffix(size_type __n)
233       { this->_M_len -= __n; }
235       constexpr void
236       swap(basic_string_view& __sv) noexcept
237       {
238         auto __tmp = *this;
239         *this = __sv;
240         __sv = __tmp;
241       }
244       // [string.view.ops], string operations:
246       template<typename _Allocator>
247         explicit operator basic_string<_CharT, _Traits, _Allocator>() const
248         {
249           return { this->_M_str, this->_M_len };
250         }
252       template<typename _Allocator = std::allocator<_CharT>>
253         basic_string<_CharT, _Traits, _Allocator>
254         to_string(const _Allocator& __alloc = _Allocator()) const
255         {
256           return { this->_M_str, this->_M_len, __alloc };
257         }
259       size_type
260       copy(_CharT* __str, size_type __n, size_type __pos = 0) const
261       {
262         __glibcxx_requires_string_len(__str, __n);
263         if (__pos > this->_M_len)
264           __throw_out_of_range_fmt(__N("basic_string_view::copy: __pos "
265                                        "(which is %zu) > this->size() "
266                                        "(which is %zu)"),
267                                    __pos, this->size());
268         size_type __rlen{std::min(__n, size_type{this->_M_len  - __pos})};
269         for (auto __begin = this->_M_str + __pos,
270              __end = __begin + __rlen; __begin != __end;)
271           *__str++ = *__begin++;
272         return __rlen;
273       }
276       // [string.view.ops], string operations:
278       constexpr basic_string_view
279       substr(size_type __pos = 0, size_type __n = npos) const
280       {
281         return __pos <= this->_M_len
282              ? basic_string_view{this->_M_str + __pos,
283                                 std::min(__n, size_type{this->_M_len  - __pos})}
284              : (__throw_out_of_range_fmt(__N("basic_string_view::substr: __pos "
285                                              "(which is %zu) > this->size() "
286                                              "(which is %zu)"),
287                                      __pos, this->size()), basic_string_view{});
288       }
290       constexpr int
291       compare(basic_string_view __str) const noexcept
292       {
293         int __ret = traits_type::compare(this->_M_str, __str._M_str,
294                                          std::min(this->_M_len, __str._M_len));
295         if (__ret == 0)
296           __ret = _S_compare(this->_M_len, __str._M_len);
297         return __ret;
298       }
300       constexpr int
301       compare(size_type __pos1, size_type __n1, basic_string_view __str) const
302       { return this->substr(__pos1, __n1).compare(__str); }
304       constexpr int
305       compare(size_type __pos1, size_type __n1,
306               basic_string_view __str, size_type __pos2, size_type __n2) const
307       { return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); }
309       constexpr int
310       compare(const _CharT* __str) const noexcept
311       { return this->compare(basic_string_view{__str}); }
313       constexpr int
314       compare(size_type __pos1, size_type __n1, const _CharT* __str) const
315       { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); }
317       constexpr int
318       compare(size_type __pos1, size_type __n1,
319               const _CharT* __str, size_type __n2) const
320       {
321         return this->substr(__pos1, __n1)
322                    .compare(basic_string_view(__str, __n2));
323       }
325       constexpr size_type
326       find(basic_string_view __str, size_type __pos = 0) const noexcept
327       { return this->find(__str._M_str, __pos, __str._M_len); }
329       constexpr size_type
330       find(_CharT __c, size_type __pos=0) const noexcept;
332       constexpr size_type
333       find(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
335       constexpr size_type
336       find(const _CharT* __str, size_type __pos=0) const noexcept
337       { return this->find(__str, __pos, traits_type::length(__str)); }
339       constexpr size_type
340       rfind(basic_string_view __str, size_type __pos = npos) const noexcept
341       { return this->rfind(__str._M_str, __pos, __str._M_len); }
343       constexpr size_type
344       rfind(_CharT __c, size_type __pos = npos) const noexcept;
346       constexpr size_type
347       rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
349       constexpr size_type
350       rfind(const _CharT* __str, size_type __pos = npos) const noexcept
351       { return this->rfind(__str, __pos, traits_type::length(__str)); }
353       constexpr size_type
354       find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept
355       { return this->find_first_of(__str._M_str, __pos, __str._M_len); }
357       constexpr size_type
358       find_first_of(_CharT __c, size_type __pos = 0) const noexcept
359       { return this->find(__c, __pos); }
361       constexpr size_type
362       find_first_of(const _CharT* __str, size_type __pos, size_type __n) const;
364       constexpr size_type
365       find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept
366       { return this->find_first_of(__str, __pos, traits_type::length(__str)); }
368       constexpr size_type
369       find_last_of(basic_string_view __str,
370                    size_type __pos = npos) const noexcept
371       { return this->find_last_of(__str._M_str, __pos, __str._M_len); }
373       constexpr size_type
374       find_last_of(_CharT __c, size_type __pos=npos) const noexcept
375       { return this->rfind(__c, __pos); }
377       constexpr size_type
378       find_last_of(const _CharT* __str, size_type __pos, size_type __n) const;
380       constexpr size_type
381       find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept
382       { return this->find_last_of(__str, __pos, traits_type::length(__str)); }
384       constexpr size_type
385       find_first_not_of(basic_string_view __str,
386                         size_type __pos = 0) const noexcept
387       { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); }
389       constexpr size_type
390       find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept;
392       constexpr size_type
393       find_first_not_of(const _CharT* __str,
394                         size_type __pos, size_type __n) const;
396       constexpr size_type
397       find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept
398       {
399         return this->find_first_not_of(__str, __pos,
400                                        traits_type::length(__str));
401       }
403       constexpr size_type
404       find_last_not_of(basic_string_view __str,
405                        size_type __pos = npos) const noexcept
406       { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); }
408       constexpr size_type
409       find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept;
411       constexpr size_type
412       find_last_not_of(const _CharT* __str,
413                        size_type __pos, size_type __n) const;
415       constexpr size_type
416       find_last_not_of(const _CharT* __str,
417                        size_type __pos = npos) const noexcept
418       {
419         return this->find_last_not_of(__str, __pos,
420                                       traits_type::length(__str));
421       }
423     private:
425       static constexpr int
426       _S_compare(size_type __n1, size_type __n2) noexcept
427       {
428         return difference_type(__n1 - __n2) > std::numeric_limits<int>::max()
429              ? std::numeric_limits<int>::max()
430              : difference_type(__n1 - __n2) < std::numeric_limits<int>::min()
431              ? std::numeric_limits<int>::min()
432              : static_cast<int>(difference_type(__n1 - __n2));
433       }
435       size_t        _M_len;
436       const _CharT* _M_str;
437     };
439   // [string.view.comparison], non-member basic_string_view comparison functions
441   // Several of these functions use type_identity_t to create a non-deduced
442   // context, so that only one argument participates in template argument
443   // deduction and the other argument gets implicitly converted to the deduced
444   // type (see N3766).
446   template<typename _CharT, typename _Traits>
447     constexpr bool
448     operator==(basic_string_view<_CharT, _Traits> __x,
449                basic_string_view<_CharT, _Traits> __y) noexcept
450     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
452   template<typename _CharT, typename _Traits>
453     constexpr bool
454     operator==(basic_string_view<_CharT, _Traits> __x,
455                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
456     noexcept
457     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
459   template<typename _CharT, typename _Traits>
460     constexpr bool
461     operator==(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
462                basic_string_view<_CharT, _Traits> __y) noexcept
463     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
465   template<typename _CharT, typename _Traits>
466     constexpr bool
467     operator!=(basic_string_view<_CharT, _Traits> __x,
468                basic_string_view<_CharT, _Traits> __y) noexcept
469     { return !(__x == __y); }
471   template<typename _CharT, typename _Traits>
472     constexpr bool
473     operator!=(basic_string_view<_CharT, _Traits> __x,
474                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
475     noexcept
476     { return !(__x == __y); }
478   template<typename _CharT, typename _Traits>
479     constexpr bool
480     operator!=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
481                basic_string_view<_CharT, _Traits> __y) noexcept
482     { return !(__x == __y); }
484   template<typename _CharT, typename _Traits>
485     constexpr bool
486     operator< (basic_string_view<_CharT, _Traits> __x,
487                basic_string_view<_CharT, _Traits> __y) noexcept
488     { return __x.compare(__y) < 0; }
490   template<typename _CharT, typename _Traits>
491     constexpr bool
492     operator< (basic_string_view<_CharT, _Traits> __x,
493                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
494     noexcept
495     { return __x.compare(__y) < 0; }
497   template<typename _CharT, typename _Traits>
498     constexpr bool
499     operator< (__type_identity_t<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                basic_string_view<_CharT, _Traits> __y) noexcept
507     { return __x.compare(__y) > 0; }
509   template<typename _CharT, typename _Traits>
510     constexpr bool
511     operator> (basic_string_view<_CharT, _Traits> __x,
512                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
513     noexcept
514     { return __x.compare(__y) > 0; }
516   template<typename _CharT, typename _Traits>
517     constexpr bool
518     operator> (__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
519                basic_string_view<_CharT, _Traits> __y) noexcept
520     { return __x.compare(__y) > 0; }
522   template<typename _CharT, typename _Traits>
523     constexpr bool
524     operator<=(basic_string_view<_CharT, _Traits> __x,
525                basic_string_view<_CharT, _Traits> __y) noexcept
526     { return __x.compare(__y) <= 0; }
528   template<typename _CharT, typename _Traits>
529     constexpr bool
530     operator<=(basic_string_view<_CharT, _Traits> __x,
531                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
532     noexcept
533     { return __x.compare(__y) <= 0; }
535   template<typename _CharT, typename _Traits>
536     constexpr bool
537     operator<=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
538                basic_string_view<_CharT, _Traits> __y) noexcept
539     { return __x.compare(__y) <= 0; }
541   template<typename _CharT, typename _Traits>
542     constexpr bool
543     operator>=(basic_string_view<_CharT, _Traits> __x,
544                basic_string_view<_CharT, _Traits> __y) noexcept
545     { return __x.compare(__y) >= 0; }
547   template<typename _CharT, typename _Traits>
548     constexpr bool
549     operator>=(basic_string_view<_CharT, _Traits> __x,
550                __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
551     noexcept
552     { return __x.compare(__y) >= 0; }
554   template<typename _CharT, typename _Traits>
555     constexpr bool
556     operator>=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
557                basic_string_view<_CharT, _Traits> __y) noexcept
558     { return __x.compare(__y) >= 0; }
560   // [string.view.io], Inserters and extractors
561   template<typename _CharT, typename _Traits>
562     inline basic_ostream<_CharT, _Traits>&
563     operator<<(basic_ostream<_CharT, _Traits>& __os,
564                basic_string_view<_CharT,_Traits> __str)
565     { return __ostream_insert(__os, __str.data(), __str.size()); }
568   // basic_string_view typedef names
570   using string_view = basic_string_view<char>;
571   using wstring_view = basic_string_view<wchar_t>;
572 #ifdef _GLIBCXX_USE_CHAR8_T
573   using u8string_view = basic_string_view<char8_t>;
574 #endif
575   using u16string_view = basic_string_view<char16_t>;
576   using u32string_view = basic_string_view<char32_t>;
577 } // namespace fundamentals_v1
578 } // namespace experimental
581   // [string.view.hash], hash support:
582   template<typename _Tp>
583     struct hash;
585   template<>
586     struct hash<experimental::string_view>
587     : public __hash_base<size_t, experimental::string_view>
588     {
589       size_t
590       operator()(const experimental::string_view& __str) const noexcept
591       { return std::_Hash_impl::hash(__str.data(), __str.length()); }
592     };
594   template<>
595     struct __is_fast_hash<hash<experimental::string_view>> : std::false_type
596     { };
598   template<>
599     struct hash<experimental::wstring_view>
600     : public __hash_base<size_t, wstring>
601     {
602       size_t
603       operator()(const experimental::wstring_view& __s) const noexcept
604       { return std::_Hash_impl::hash(__s.data(),
605                                      __s.length() * sizeof(wchar_t)); }
606     };
608   template<>
609     struct __is_fast_hash<hash<experimental::wstring_view>> : std::false_type
610     { };
612 #ifdef _GLIBCXX_USE_CHAR8_T
613   template<>
614     struct hash<experimental::u8string_view>
615     : public __hash_base<size_t, experimental::u8string_view>
616     {
617       size_t
618       operator()(const experimental::u8string_view& __s) const noexcept
619       { return std::_Hash_impl::hash(__s.data(), __s.length()); }
620     };
622   template<>
623     struct __is_fast_hash<hash<experimental::u8string_view>> : std::false_type
624     { };
625 #endif
627   template<>
628     struct hash<experimental::u16string_view>
629     : public __hash_base<size_t, experimental::u16string_view>
630     {
631       size_t
632       operator()(const experimental::u16string_view& __s) const noexcept
633       { return std::_Hash_impl::hash(__s.data(),
634                                      __s.length() * sizeof(char16_t)); }
635     };
637   template<>
638     struct __is_fast_hash<hash<experimental::u16string_view>> : std::false_type
639     { };
641   template<>
642     struct hash<experimental::u32string_view>
643     : public __hash_base<size_t, experimental::u32string_view>
644     {
645       size_t
646       operator()(const experimental::u32string_view& __s) const noexcept
647       { return std::_Hash_impl::hash(__s.data(),
648                                      __s.length() * sizeof(char32_t)); }
649     };
651   template<>
652     struct __is_fast_hash<hash<experimental::u32string_view>> : std::false_type
653     { };
655 namespace experimental
657   // I added these EMSR.
658   inline namespace literals
659   {
660   inline namespace string_view_literals
661   {
662 #pragma GCC diagnostic push
663 #pragma GCC diagnostic ignored "-Wliteral-suffix"
664     inline constexpr basic_string_view<char>
665     operator""sv(const char* __str, size_t __len) noexcept
666     { return basic_string_view<char>{__str, __len}; }
668     inline constexpr basic_string_view<wchar_t>
669     operator""sv(const wchar_t* __str, size_t __len) noexcept
670     { return basic_string_view<wchar_t>{__str, __len}; }
672 #ifdef _GLIBCXX_USE_CHAR8_T
673     inline constexpr basic_string_view<char8_t>
674     operator""sv(const char8_t* __str, size_t __len) noexcept
675     { return basic_string_view<char8_t>{__str, __len}; }
676 #endif
678     inline constexpr basic_string_view<char16_t>
679     operator""sv(const char16_t* __str, size_t __len) noexcept
680     { return basic_string_view<char16_t>{__str, __len}; }
682     inline constexpr basic_string_view<char32_t>
683     operator""sv(const char32_t* __str, size_t __len) noexcept
684     { return basic_string_view<char32_t>{__str, __len}; }
685 #pragma GCC diagnostic pop
686   } // namespace string_literals
687   } // namespace literals
688 } // namespace experimental
690 #if __cpp_lib_concepts
691   namespace ranges
692   {
693     // Opt-in to borrowed_range concept
694     template<typename _CharT, typename _Traits>
695       inline constexpr bool
696         enable_borrowed_range<experimental::basic_string_view<_CharT, _Traits>>
697           = true;
699     // Opt-in to view concept
700     template<typename _CharT, typename _Traits>
701       inline constexpr bool
702         enable_view<experimental::basic_string_view<_CharT, _Traits>> = true;
703   }
704 #endif
706 _GLIBCXX_END_NAMESPACE_VERSION
707 } // namespace std
709 #include <experimental/bits/string_view.tcc>
711 #endif // __cplusplus <= 201103L
713 #endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW