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
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 = 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	// TODO: Assert to restore in a way compatible with the constexpr.
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	// TODO: Assert to restore in a way compatible with the constexpr.
202	// __glibcxx_assert(this->_M_len > 0);
203	return *this->_M_str;
204      }
205
206      constexpr const _CharT&
207      back() const
208      {
209	// TODO: Assert to restore in a way compatible with the constexpr.
210	// __glibcxx_assert(this->_M_len > 0);
211	return *(this->_M_str + this->_M_len - 1);
212      }
213
214      constexpr const _CharT*
215      data() const noexcept
216      { return this->_M_str; }
217
218      // [string.view.modifiers], modifiers:
219
220      constexpr void
221      remove_prefix(size_type __n)
222      {
223	__glibcxx_assert(this->_M_len >= __n);
224	this->_M_str += __n;
225	this->_M_len -= __n;
226      }
227
228      constexpr void
229      remove_suffix(size_type __n)
230      { this->_M_len -= __n; }
231
232      constexpr void
233      swap(basic_string_view& __sv) noexcept
234      {
235	auto __tmp = *this;
236	*this = __sv;
237	__sv = __tmp;
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 = 0, 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      constexpr 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      constexpr int
298      compare(size_type __pos1, size_type __n1, basic_string_view __str) const
299      { return this->substr(__pos1, __n1).compare(__str); }
300
301      constexpr 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      constexpr int
307      compare(const _CharT* __str) const noexcept
308      { return this->compare(basic_string_view{__str}); }
309
310      constexpr 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      constexpr 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      constexpr 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      constexpr size_type
327      find(_CharT __c, size_type __pos=0) const noexcept;
328
329      constexpr size_type
330      find(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
331
332      constexpr 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      constexpr 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      constexpr size_type
341      rfind(_CharT __c, size_type __pos = npos) const noexcept;
342
343      constexpr size_type
344      rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
345
346      constexpr 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      constexpr 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      constexpr size_type
355      find_first_of(_CharT __c, size_type __pos = 0) const noexcept
356      { return this->find(__c, __pos); }
357
358      constexpr size_type
359      find_first_of(const _CharT* __str, size_type __pos, size_type __n) const;
360
361      constexpr 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      constexpr 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      constexpr size_type
371      find_last_of(_CharT __c, size_type __pos=npos) const noexcept
372      { return this->rfind(__c, __pos); }
373
374      constexpr size_type
375      find_last_of(const _CharT* __str, size_type __pos, size_type __n) const;
376
377      constexpr 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      constexpr 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      constexpr size_type
387      find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept;
388
389      constexpr size_type
390      find_first_not_of(const _CharT* __str,
391			size_type __pos, size_type __n) const;
392
393      constexpr 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      constexpr 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      constexpr size_type
406      find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept;
407
408      constexpr size_type
409      find_last_not_of(const _CharT* __str,
410		       size_type __pos, size_type __n) const;
411
412      constexpr 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 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  // [string.view.comparison], non-member basic_string_view comparison functions
437
438  namespace __detail
439  {
440    // Identity transform to create a non-deduced context, so that only one
441    // argument participates in template argument deduction and the other
442    // argument gets implicitly converted to the deduced type. See n3766.html.
443    template<typename _Tp>
444      using __idt = common_type_t<_Tp>;
445  }
446
447  template<typename _CharT, typename _Traits>
448    constexpr bool
449    operator==(basic_string_view<_CharT, _Traits> __x,
450               basic_string_view<_CharT, _Traits> __y) noexcept
451    { return __x.size() == __y.size() && __x.compare(__y) == 0; }
452
453  template<typename _CharT, typename _Traits>
454    constexpr bool
455    operator==(basic_string_view<_CharT, _Traits> __x,
456               __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
457    { return __x.size() == __y.size() && __x.compare(__y) == 0; }
458
459  template<typename _CharT, typename _Traits>
460    constexpr bool
461    operator==(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
462               basic_string_view<_CharT, _Traits> __y) noexcept
463    { return __x.size() == __y.size() && __x.compare(__y) == 0; }
464
465  template<typename _CharT, typename _Traits>
466    constexpr bool
467    operator!=(basic_string_view<_CharT, _Traits> __x,
468               basic_string_view<_CharT, _Traits> __y) noexcept
469    { return !(__x == __y); }
470
471  template<typename _CharT, typename _Traits>
472    constexpr bool
473    operator!=(basic_string_view<_CharT, _Traits> __x,
474               __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
475    { return !(__x == __y); }
476
477  template<typename _CharT, typename _Traits>
478    constexpr bool
479    operator!=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
480               basic_string_view<_CharT, _Traits> __y) noexcept
481    { return !(__x == __y); }
482
483  template<typename _CharT, typename _Traits>
484    constexpr bool
485    operator< (basic_string_view<_CharT, _Traits> __x,
486               basic_string_view<_CharT, _Traits> __y) noexcept
487    { return __x.compare(__y) < 0; }
488
489  template<typename _CharT, typename _Traits>
490    constexpr bool
491    operator< (basic_string_view<_CharT, _Traits> __x,
492               __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
493    { return __x.compare(__y) < 0; }
494
495  template<typename _CharT, typename _Traits>
496    constexpr bool
497    operator< (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
498               basic_string_view<_CharT, _Traits> __y) noexcept
499    { return __x.compare(__y) < 0; }
500
501  template<typename _CharT, typename _Traits>
502    constexpr bool
503    operator> (basic_string_view<_CharT, _Traits> __x,
504               basic_string_view<_CharT, _Traits> __y) noexcept
505    { return __x.compare(__y) > 0; }
506
507  template<typename _CharT, typename _Traits>
508    constexpr bool
509    operator> (basic_string_view<_CharT, _Traits> __x,
510               __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
511    { return __x.compare(__y) > 0; }
512
513  template<typename _CharT, typename _Traits>
514    constexpr bool
515    operator> (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
516               basic_string_view<_CharT, _Traits> __y) noexcept
517    { return __x.compare(__y) > 0; }
518
519  template<typename _CharT, typename _Traits>
520    constexpr bool
521    operator<=(basic_string_view<_CharT, _Traits> __x,
522               basic_string_view<_CharT, _Traits> __y) noexcept
523    { return __x.compare(__y) <= 0; }
524
525  template<typename _CharT, typename _Traits>
526    constexpr bool
527    operator<=(basic_string_view<_CharT, _Traits> __x,
528               __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
529    { return __x.compare(__y) <= 0; }
530
531  template<typename _CharT, typename _Traits>
532    constexpr bool
533    operator<=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
534               basic_string_view<_CharT, _Traits> __y) noexcept
535    { return __x.compare(__y) <= 0; }
536
537  template<typename _CharT, typename _Traits>
538    constexpr bool
539    operator>=(basic_string_view<_CharT, _Traits> __x,
540               basic_string_view<_CharT, _Traits> __y) noexcept
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               __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
547    { return __x.compare(__y) >= 0; }
548
549  template<typename _CharT, typename _Traits>
550    constexpr bool
551    operator>=(__detail::__idt<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_C99_STDINT_TR1
570  using u16string_view = basic_string_view<char16_t>;
571  using u32string_view = basic_string_view<char32_t>;
572#endif
573} // namespace fundamentals_v1
574} // namespace experimental
575
576
577  // [string.view.hash], hash support:
578  template<typename _Tp>
579    struct hash;
580
581  template<>
582    struct hash<experimental::string_view>
583    : public __hash_base<size_t, experimental::string_view>
584    {
585      size_t
586      operator()(const experimental::string_view& __str) const noexcept
587      { return std::_Hash_impl::hash(__str.data(), __str.length()); }
588    };
589
590  template<>
591    struct __is_fast_hash<hash<experimental::string_view>> : std::false_type
592    { };
593
594#ifdef _GLIBCXX_USE_WCHAR_T
595  template<>
596    struct hash<experimental::wstring_view>
597    : public __hash_base<size_t, wstring>
598    {
599      size_t
600      operator()(const experimental::wstring_view& __s) const noexcept
601      { return std::_Hash_impl::hash(__s.data(),
602                                     __s.length() * sizeof(wchar_t)); }
603    };
604
605  template<>
606    struct __is_fast_hash<hash<experimental::wstring_view>> : std::false_type
607    { };
608#endif
609
610#ifdef _GLIBCXX_USE_C99_STDINT_TR1
611  template<>
612    struct hash<experimental::u16string_view>
613    : public __hash_base<size_t, experimental::u16string_view>
614    {
615      size_t
616      operator()(const experimental::u16string_view& __s) const noexcept
617      { return std::_Hash_impl::hash(__s.data(),
618                                     __s.length() * sizeof(char16_t)); }
619    };
620
621  template<>
622    struct __is_fast_hash<hash<experimental::u16string_view>> : std::false_type
623    { };
624
625  template<>
626    struct hash<experimental::u32string_view>
627    : public __hash_base<size_t, experimental::u32string_view>
628    {
629      size_t
630      operator()(const experimental::u32string_view& __s) const noexcept
631      { return std::_Hash_impl::hash(__s.data(),
632                                     __s.length() * sizeof(char32_t)); }
633    };
634
635  template<>
636    struct __is_fast_hash<hash<experimental::u32string_view>> : std::false_type
637    { };
638#endif
639
640namespace experimental
641{
642  // I added these EMSR.
643  inline namespace literals
644  {
645  inline namespace string_view_literals
646  {
647#pragma GCC diagnostic push
648#pragma GCC diagnostic ignored "-Wliteral-suffix"
649    inline constexpr basic_string_view<char>
650    operator""sv(const char* __str, size_t __len) noexcept
651    { return basic_string_view<char>{__str, __len}; }
652
653#ifdef _GLIBCXX_USE_WCHAR_T
654    inline constexpr basic_string_view<wchar_t>
655    operator""sv(const wchar_t* __str, size_t __len) noexcept
656    { return basic_string_view<wchar_t>{__str, __len}; }
657#endif
658
659#ifdef _GLIBCXX_USE_C99_STDINT_TR1
660    inline constexpr basic_string_view<char16_t>
661    operator""sv(const char16_t* __str, size_t __len) noexcept
662    { return basic_string_view<char16_t>{__str, __len}; }
663
664    inline constexpr basic_string_view<char32_t>
665    operator""sv(const char32_t* __str, size_t __len) noexcept
666    { return basic_string_view<char32_t>{__str, __len}; }
667#endif
668#pragma GCC diagnostic pop
669  } // namespace string_literals
670  } // namespace literals
671} // namespace experimental
672
673_GLIBCXX_END_NAMESPACE_VERSION
674} // namespace std
675
676#include <experimental/bits/string_view.tcc>
677
678#endif // __cplusplus <= 201103L
679
680#endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW
681