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