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