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