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