1// Components for manipulating non-owning sequences of characters -*- C++ -*-
2
3// Copyright (C) 2013-2019 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
44namespace std _GLIBCXX_VISIBILITY(default)
45{
46_GLIBCXX_BEGIN_NAMESPACE_VERSION
47
48namespace experimental
49{
50inline 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 = _CharT*;
82      using const_pointer = const _CharT*;
83      using reference = _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      _GLIBCXX_NODISCARD 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_CHAR8_T
567  using u8string_view = basic_string_view<char8_t>;
568#endif
569  using u16string_view = basic_string_view<char16_t>;
570  using u32string_view = basic_string_view<char32_t>;
571} // namespace fundamentals_v1
572} // namespace experimental
573
574
575  // [string.view.hash], hash support:
576  template<typename _Tp>
577    struct hash;
578
579  template<>
580    struct hash<experimental::string_view>
581    : public __hash_base<size_t, experimental::string_view>
582    {
583      size_t
584      operator()(const experimental::string_view& __str) const noexcept
585      { return std::_Hash_impl::hash(__str.data(), __str.length()); }
586    };
587
588  template<>
589    struct __is_fast_hash<hash<experimental::string_view>> : std::false_type
590    { };
591
592#ifdef _GLIBCXX_USE_WCHAR_T
593  template<>
594    struct hash<experimental::wstring_view>
595    : public __hash_base<size_t, wstring>
596    {
597      size_t
598      operator()(const experimental::wstring_view& __s) const noexcept
599      { return std::_Hash_impl::hash(__s.data(),
600                                     __s.length() * sizeof(wchar_t)); }
601    };
602
603  template<>
604    struct __is_fast_hash<hash<experimental::wstring_view>> : std::false_type
605    { };
606#endif
607
608#ifdef _GLIBCXX_USE_CHAR8_T
609  template<>
610    struct hash<experimental::u8string_view>
611    : public __hash_base<size_t, experimental::u8string_view>
612    {
613      size_t
614      operator()(const experimental::u8string_view& __s) const noexcept
615      { return std::_Hash_impl::hash(__s.data(), __s.length()); }
616    };
617
618  template<>
619    struct __is_fast_hash<hash<experimental::u8string_view>> : std::false_type
620    { };
621#endif
622
623  template<>
624    struct hash<experimental::u16string_view>
625    : public __hash_base<size_t, experimental::u16string_view>
626    {
627      size_t
628      operator()(const experimental::u16string_view& __s) const noexcept
629      { return std::_Hash_impl::hash(__s.data(),
630                                     __s.length() * sizeof(char16_t)); }
631    };
632
633  template<>
634    struct __is_fast_hash<hash<experimental::u16string_view>> : std::false_type
635    { };
636
637  template<>
638    struct hash<experimental::u32string_view>
639    : public __hash_base<size_t, experimental::u32string_view>
640    {
641      size_t
642      operator()(const experimental::u32string_view& __s) const noexcept
643      { return std::_Hash_impl::hash(__s.data(),
644                                     __s.length() * sizeof(char32_t)); }
645    };
646
647  template<>
648    struct __is_fast_hash<hash<experimental::u32string_view>> : std::false_type
649    { };
650
651namespace experimental
652{
653  // I added these EMSR.
654  inline namespace literals
655  {
656  inline namespace string_view_literals
657  {
658#pragma GCC diagnostic push
659#pragma GCC diagnostic ignored "-Wliteral-suffix"
660    inline constexpr basic_string_view<char>
661    operator""sv(const char* __str, size_t __len) noexcept
662    { return basic_string_view<char>{__str, __len}; }
663
664#ifdef _GLIBCXX_USE_WCHAR_T
665    inline constexpr basic_string_view<wchar_t>
666    operator""sv(const wchar_t* __str, size_t __len) noexcept
667    { return basic_string_view<wchar_t>{__str, __len}; }
668#endif
669
670#ifdef _GLIBCXX_USE_CHAR8_T
671    inline constexpr basic_string_view<char8_t>
672    operator""sv(const char8_t* __str, size_t __len) noexcept
673    { return basic_string_view<char8_t>{__str, __len}; }
674#endif
675
676    inline constexpr basic_string_view<char16_t>
677    operator""sv(const char16_t* __str, size_t __len) noexcept
678    { return basic_string_view<char16_t>{__str, __len}; }
679
680    inline constexpr basic_string_view<char32_t>
681    operator""sv(const char32_t* __str, size_t __len) noexcept
682    { return basic_string_view<char32_t>{__str, __len}; }
683#pragma GCC diagnostic pop
684  } // namespace string_literals
685  } // namespace literals
686} // namespace experimental
687
688_GLIBCXX_END_NAMESPACE_VERSION
689} // namespace std
690
691#include <experimental/bits/string_view.tcc>
692
693#endif // __cplusplus <= 201103L
694
695#endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW
696