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
45namespace std _GLIBCXX_VISIBILITY(default)
46{
47namespace experimental
48{
49inline 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
652namespace 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
694