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-2015 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 <= 201103L
39 # include <bits/c++14_warning.h>
40 #else
41 
42 #include <string>
43 #include <limits>
44 
45 namespace std _GLIBCXX_VISIBILITY(default)
46 {
47 namespace experimental
48 {
49 inline namespace fundamentals_v1
50 {
51 _GLIBCXX_BEGIN_NAMESPACE_VERSION
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 experimental
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 = const _CharT*;
83  using const_pointer = const _CharT*;
84  using reference = const _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  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  // TODO: Assert to restore in a way compatible with the constexpr.
183  // _GLIBCXX_DEBUG_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  // TODO: Assert to restore in a way compatible with the constexpr.
203  // _GLIBCXX_DEBUG_ASSERT(this->_M_len > 0);
204  return *this->_M_str;
205  }
206 
207  constexpr const _CharT&
208  back() const
209  {
210  // TODO: Assert to restore in a way compatible with the constexpr.
211  // _GLIBCXX_DEBUG_ASSERT(this->_M_len > 0);
212  return *(this->_M_str + this->_M_len - 1);
213  }
214 
215  constexpr const _CharT*
216  data() const noexcept
217  { return this->_M_str; }
218 
219  // [string.view.modifiers], modifiers:
220 
221  void
222  remove_prefix(size_type __n)
223  {
224  _GLIBCXX_DEBUG_ASSERT(this->_M_len >= __n);
225  this->_M_str += __n;
226  this->_M_len -= __n;
227  }
228 
229  void
230  remove_suffix(size_type __n)
231  { this->_M_len -= __n; }
232 
233  void
234  swap(basic_string_view& __sv) noexcept
235  {
236  std::swap(this->_M_len, __sv._M_len);
237  std::swap(this->_M_str, __sv._M_str);
238  }
239 
240 
241  // [string.view.ops], string operations:
242 
243  template<typename _Allocator>
244  explicit operator basic_string<_CharT, _Traits, _Allocator>() const
245  {
246  return { this->_M_str, this->_M_len };
247  }
248 
249  template<typename _Allocator = std::allocator<_CharT>>
250  basic_string<_CharT, _Traits, _Allocator>
251  to_string(const _Allocator& __alloc = _Allocator()) const
252  {
253  return { this->_M_str, this->_M_len, __alloc };
254  }
255 
256  size_type
257  copy(_CharT* __str, size_type __n, size_type __pos = 0) const
258  {
259  __glibcxx_requires_string_len(__str, __n);
260  if (__pos > this->_M_len)
261  __throw_out_of_range_fmt(__N("basic_string_view::copy: __pos "
262  "(which is %zu) > this->size() "
263  "(which is %zu)"),
264  __pos, this->size());
265  size_type __rlen{std::min(__n, size_type{this->_M_len - __pos})};
266  for (auto __begin = this->_M_str + __pos,
267  __end = __begin + __rlen; __begin != __end;)
268  *__str++ = *__begin++;
269  return __rlen;
270  }
271 
272 
273  // [string.view.ops], string operations:
274 
275  constexpr basic_string_view
276  substr(size_type __pos, size_type __n=npos) const
277  {
278  return __pos <= this->_M_len
279  ? basic_string_view{this->_M_str + __pos,
280  std::min(__n, size_type{this->_M_len - __pos})}
281  : (__throw_out_of_range_fmt(__N("basic_string_view::substr: __pos "
282  "(which is %zu) > this->size() "
283  "(which is %zu)"),
284  __pos, this->size()), basic_string_view{});
285  }
286 
287  int
288  compare(basic_string_view __str) const noexcept
289  {
290  int __ret = traits_type::compare(this->_M_str, __str._M_str,
291  std::min(this->_M_len, __str._M_len));
292  if (__ret == 0)
293  __ret = _S_compare(this->_M_len, __str._M_len);
294  return __ret;
295  }
296 
297  int
298  compare(size_type __pos1, size_type __n1, basic_string_view __str) const
299  { return this->substr(__pos1, __n1).compare(__str); }
300 
301  int
302  compare(size_type __pos1, size_type __n1,
303  basic_string_view __str, size_type __pos2, size_type __n2) const
304  { return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); }
305 
306  int
307  compare(const _CharT* __str) const noexcept
308  { return this->compare(basic_string_view{__str}); }
309 
310  int
311  compare(size_type __pos1, size_type __n1, const _CharT* __str) const
312  { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); }
313 
314  int
315  compare(size_type __pos1, size_type __n1,
316  const _CharT* __str, size_type __n2) const
317  {
318  return this->substr(__pos1, __n1)
319  .compare(basic_string_view(__str, __n2));
320  }
321 
322  size_type
323  find(basic_string_view __str, size_type __pos = 0) const noexcept
324  { return this->find(__str._M_str, __pos, __str._M_len); }
325 
326  size_type
327  find(_CharT __c, size_type __pos=0) const noexcept;
328 
329  size_type
330  find(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
331 
332  size_type
333  find(const _CharT* __str, size_type __pos=0) const noexcept
334  { return this->find(__str, __pos, traits_type::length(__str)); }
335 
336  size_type
337  rfind(basic_string_view __str, size_type __pos = npos) const noexcept
338  { return this->rfind(__str._M_str, __pos, __str._M_len); }
339 
340  size_type
341  rfind(_CharT __c, size_type __pos = npos) const noexcept;
342 
343  size_type
344  rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
345 
346  size_type
347  rfind(const _CharT* __str, size_type __pos = npos) const noexcept
348  { return this->rfind(__str, __pos, traits_type::length(__str)); }
349 
350  size_type
351  find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept
352  { return this->find_first_of(__str._M_str, __pos, __str._M_len); }
353 
354  size_type
355  find_first_of(_CharT __c, size_type __pos = 0) const noexcept
356  { return this->find(__c, __pos); }
357 
358  size_type
359  find_first_of(const _CharT* __str, size_type __pos, size_type __n) const;
360 
361  size_type
362  find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept
363  { return this->find_first_of(__str, __pos, traits_type::length(__str)); }
364 
365  size_type
366  find_last_of(basic_string_view __str,
367  size_type __pos = npos) const noexcept
368  { return this->find_last_of(__str._M_str, __pos, __str._M_len); }
369 
370  size_type
371  find_last_of(_CharT __c, size_type __pos=npos) const noexcept
372  { return this->rfind(__c, __pos); }
373 
374  size_type
375  find_last_of(const _CharT* __str, size_type __pos, size_type __n) const;
376 
377  size_type
378  find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept
379  { return this->find_last_of(__str, __pos, traits_type::length(__str)); }
380 
381  size_type
382  find_first_not_of(basic_string_view __str,
383  size_type __pos = 0) const noexcept
384  { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); }
385 
386  size_type
387  find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept;
388 
389  size_type
390  find_first_not_of(const _CharT* __str,
391  size_type __pos, size_type __n) const;
392 
393  size_type
394  find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept
395  {
396  return this->find_first_not_of(__str, __pos,
397  traits_type::length(__str));
398  }
399 
400  size_type
401  find_last_not_of(basic_string_view __str,
402  size_type __pos = npos) const noexcept
403  { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); }
404 
405  size_type
406  find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept;
407 
408  size_type
409  find_last_not_of(const _CharT* __str,
410  size_type __pos, size_type __n) const;
411 
412  size_type
413  find_last_not_of(const _CharT* __str,
414  size_type __pos = npos) const noexcept
415  {
416  return this->find_last_not_of(__str, __pos,
417  traits_type::length(__str));
418  }
419 
420  private:
421 
422  static constexpr const int
423  _S_compare(size_type __n1, size_type __n2) noexcept
424  {
425  return difference_type{__n1 - __n2} > std::numeric_limits<int>::max()
426  ? std::numeric_limits<int>::max()
427  : difference_type{__n1 - __n2} < std::numeric_limits<int>::min()
428  ? std::numeric_limits<int>::min()
429  : static_cast<int>(difference_type{__n1 - __n2});
430  }
431 
432  size_t _M_len;
433  const _CharT* _M_str;
434  };
435 
436 
437  // [string.view.comparison], non-member basic_string_view comparison functions
438 
439  namespace __detail
440  {
441  // Identity transform to make ADL work with just one argument.
442  // See n3766.html.
443  template<typename _Tp = void>
444  struct __identity
445  { typedef _Tp type; };
446 
447  template<>
448  struct __identity<void>;
449 
450  template<typename _Tp>
451  using __idt = typename __identity<_Tp>::type;
452  }
453 
454  template<typename _CharT, typename _Traits>
455  inline bool
456  operator==(basic_string_view<_CharT, _Traits> __x,
457  basic_string_view<_CharT, _Traits> __y) noexcept
458  { return __x.compare(__y) == 0; }
459 
460  template<typename _CharT, typename _Traits>
461  inline bool
462  operator==(basic_string_view<_CharT, _Traits> __x,
463  __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
464  { return __x.compare(__y) == 0; }
465 
466  template<typename _CharT, typename _Traits>
467  inline bool
468  operator==(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
469  basic_string_view<_CharT, _Traits> __y) noexcept
470  { return __x.compare(__y) == 0; }
471 
472  template<typename _CharT, typename _Traits>
473  inline bool
474  operator!=(basic_string_view<_CharT, _Traits> __x,
475  basic_string_view<_CharT, _Traits> __y) noexcept
476  { return !(__x == __y); }
477 
478  template<typename _CharT, typename _Traits>
479  inline bool
480  operator!=(basic_string_view<_CharT, _Traits> __x,
481  __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
482  { return !(__x == __y); }
483 
484  template<typename _CharT, typename _Traits>
485  inline bool
486  operator!=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
487  basic_string_view<_CharT, _Traits> __y) noexcept
488  { return !(__x == __y); }
489 
490  template<typename _CharT, typename _Traits>
491  inline bool
492  operator< (basic_string_view<_CharT, _Traits> __x,
493  basic_string_view<_CharT, _Traits> __y) noexcept
494  { return __x.compare(__y) < 0; }
495 
496  template<typename _CharT, typename _Traits>
497  inline bool
498  operator< (basic_string_view<_CharT, _Traits> __x,
499  __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
500  { return __x.compare(__y) < 0; }
501 
502  template<typename _CharT, typename _Traits>
503  inline bool
504  operator< (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
505  basic_string_view<_CharT, _Traits> __y) noexcept
506  { return __x.compare(__y) < 0; }
507 
508  template<typename _CharT, typename _Traits>
509  inline bool
510  operator> (basic_string_view<_CharT, _Traits> __x,
511  basic_string_view<_CharT, _Traits> __y) noexcept
512  { return __x.compare(__y) > 0; }
513 
514  template<typename _CharT, typename _Traits>
515  inline bool
516  operator> (basic_string_view<_CharT, _Traits> __x,
517  __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
518  { return __x.compare(__y) > 0; }
519 
520  template<typename _CharT, typename _Traits>
521  inline bool
522  operator> (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
523  basic_string_view<_CharT, _Traits> __y) noexcept
524  { return __x.compare(__y) > 0; }
525 
526  template<typename _CharT, typename _Traits>
527  inline bool
528  operator<=(basic_string_view<_CharT, _Traits> __x,
529  basic_string_view<_CharT, _Traits> __y) noexcept
530  { return __x.compare(__y) <= 0; }
531 
532  template<typename _CharT, typename _Traits>
533  inline bool
534  operator<=(basic_string_view<_CharT, _Traits> __x,
535  __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
536  { return __x.compare(__y) <= 0; }
537 
538  template<typename _CharT, typename _Traits>
539  inline bool
540  operator<=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
541  basic_string_view<_CharT, _Traits> __y) noexcept
542  { return __x.compare(__y) <= 0; }
543 
544  template<typename _CharT, typename _Traits>
545  inline bool
546  operator>=(basic_string_view<_CharT, _Traits> __x,
547  basic_string_view<_CharT, _Traits> __y) noexcept
548  { return __x.compare(__y) >= 0; }
549 
550  template<typename _CharT, typename _Traits>
551  inline bool
552  operator>=(basic_string_view<_CharT, _Traits> __x,
553  __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
554  { return __x.compare(__y) >= 0; }
555 
556  template<typename _CharT, typename _Traits>
557  inline bool
558  operator>=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
559  basic_string_view<_CharT, _Traits> __y) noexcept
560  { return __x.compare(__y) >= 0; }
561 
562  // [string.view.io], Inserters and extractors
563  template<typename _CharT, typename _Traits>
564  inline basic_ostream<_CharT, _Traits>&
565  operator<<(basic_ostream<_CharT, _Traits>& __os,
566  basic_string_view<_CharT,_Traits> __str)
567  { return __ostream_insert(__os, __str.data(), __str.size()); }
568 
569 
570  // basic_string_view typedef names
571 
572  using string_view = basic_string_view<char>;
573 #ifdef _GLIBCXX_USE_WCHAR_T
574  using wstring_view = basic_string_view<wchar_t>;
575 #endif
576 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
577  using u16string_view = basic_string_view<char16_t>;
578  using u32string_view = basic_string_view<char32_t>;
579 #endif
580 
581 _GLIBCXX_END_NAMESPACE_VERSION
582 } // namespace fundamentals_v1
583 } // namespace experimental
584 
585 
586  // [string.view.hash], hash support:
587 
588 _GLIBCXX_BEGIN_NAMESPACE_VERSION
589  template<typename _Tp>
590  struct hash;
591 
592  template<>
593  struct hash<experimental::string_view>
594  : public __hash_base<size_t, experimental::string_view>
595  {
596  size_t
597  operator()(const experimental::string_view& __str) const noexcept
598  { return std::_Hash_impl::hash(__str.data(), __str.length()); }
599  };
600 
601  template<>
602  struct __is_fast_hash<hash<experimental::string_view>> : std::false_type
603  { };
604 
605 #ifdef _GLIBCXX_USE_WCHAR_T
606  template<>
607  struct hash<experimental::wstring_view>
608  : public __hash_base<size_t, wstring>
609  {
610  size_t
611  operator()(const experimental::wstring_view& __s) const noexcept
612  { return std::_Hash_impl::hash(__s.data(),
613  __s.length() * sizeof(wchar_t)); }
614  };
615 
616  template<>
617  struct __is_fast_hash<hash<experimental::wstring_view>> : std::false_type
618  { };
619 #endif
620 
621 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
622  template<>
623  struct hash<experimental::u16string_view>
624  : public __hash_base<size_t, experimental::u16string_view>
625  {
626  size_t
627  operator()(const experimental::u16string_view& __s) const noexcept
628  { return std::_Hash_impl::hash(__s.data(),
629  __s.length() * sizeof(char16_t)); }
630  };
631 
632  template<>
633  struct __is_fast_hash<hash<experimental::u16string_view>> : std::false_type
634  { };
635 
636  template<>
637  struct hash<experimental::u32string_view>
638  : public __hash_base<size_t, experimental::u32string_view>
639  {
640  size_t
641  operator()(const experimental::u32string_view& __s) const noexcept
642  { return std::_Hash_impl::hash(__s.data(),
643  __s.length() * sizeof(char32_t)); }
644  };
645 
646  template<>
647  struct __is_fast_hash<hash<experimental::u32string_view>> : std::false_type
648  { };
649 #endif
650 _GLIBCXX_END_NAMESPACE_VERSION
651 
652 namespace experimental
653 {
654 _GLIBCXX_BEGIN_NAMESPACE_VERSION
655 
656  // I added these EMSR.
657  inline namespace literals
658  {
659  inline namespace string_view_literals
660  {
661 
662  inline constexpr basic_string_view<char>
663  operator""sv(const char* __str, size_t __len)
664  { return basic_string_view<char>{__str, __len}; }
665 
666 #ifdef _GLIBCXX_USE_WCHAR_T
667  inline constexpr basic_string_view<wchar_t>
668  operator""sv(const wchar_t* __str, size_t __len)
669  { return basic_string_view<wchar_t>{__str, __len}; }
670 #endif
671 
672 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
673  inline constexpr basic_string_view<char16_t>
674  operator""sv(const char16_t* __str, size_t __len)
675  { return basic_string_view<char16_t>{__str, __len}; }
676 
677  inline constexpr basic_string_view<char32_t>
678  operator""sv(const char32_t* __str, size_t __len)
679  { return basic_string_view<char32_t>{__str, __len}; }
680 #endif
681 
682  }
683  }
684 
685 _GLIBCXX_END_NAMESPACE_VERSION
686 } // namespace experimental
687 } // namespace std
688 
689 #include <experimental/string_view.tcc>
690 
691 #endif // __cplusplus <= 201103L
692 
693 #endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW