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