1// Components for manipulating non-owning sequences of characters -*- C++ -*-
 
    3// Copyright (C) 2013-2021 Free Software Foundation, Inc.
 
    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)
 
   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.
 
   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.
 
   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/>.
 
   25/** @file experimental/string_view
 
   26 *  This is a TS C++ Library header.
 
   31// N3762 basic_string_view library
 
   34#ifndef _GLIBCXX_EXPERIMENTAL_STRING_VIEW
 
   35#define _GLIBCXX_EXPERIMENTAL_STRING_VIEW 1
 
   37#pragma GCC system_header
 
   39#if __cplusplus >= 201402L
 
   43#include <bits/ranges_base.h> // enable_borrowed_range, enable_view
 
   44#include <experimental/bits/lfts_config.h>
 
   46namespace std _GLIBCXX_VISIBILITY(default)
 
   48_GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   52inline namespace fundamentals_v1
 
   54#define __cpp_lib_experimental_string_view 201411
 
   57   *  @class basic_string_view <experimental/string_view>
 
   58   *  @brief  A non-owning reference to a string.
 
   64   *  @tparam _CharT  Type of character
 
   65   *  @tparam _Traits  Traits for character type, defaults to
 
   66   *                   char_traits<_CharT>.
 
   68   *  A basic_string_view looks like this:
 
   75  template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
 
   76    class basic_string_view
 
   81      using traits_type = _Traits;
 
   82      using value_type = _CharT;
 
   83      using pointer = _CharT*;
 
   84      using const_pointer = const _CharT*;
 
   85      using reference = _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);
 
   95      // [string.view.cons], construct/copy
 
   98      basic_string_view() noexcept
 
   99      : _M_len{0}, _M_str{nullptr}
 
  102      constexpr basic_string_view(const basic_string_view&) noexcept = default;
 
  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()}
 
  110      constexpr basic_string_view(const _CharT* __str)
 
  111      : _M_len{__str == nullptr ? 0 : traits_type::length(__str)},
 
  115      constexpr basic_string_view(const _CharT* __str, size_type __len)
 
  121      operator=(const basic_string_view&) noexcept = default;
 
  123      // [string.view.iterators], iterators
 
  125      constexpr const_iterator
 
  126      begin() const noexcept
 
  127      { return this->_M_str; }
 
  129      constexpr const_iterator
 
  131      { return this->_M_str + this->_M_len; }
 
  133      constexpr const_iterator
 
  134      cbegin() const noexcept
 
  135      { return this->_M_str; }
 
  137      constexpr const_iterator
 
  138      cend() const noexcept
 
  139      { return this->_M_str + this->_M_len; }
 
  141      const_reverse_iterator
 
  142      rbegin() const noexcept
 
  143      { return const_reverse_iterator(this->end()); }
 
  145      const_reverse_iterator
 
  146      rend() const noexcept
 
  147      { return const_reverse_iterator(this->begin()); }
 
  149      const_reverse_iterator
 
  150      crbegin() const noexcept
 
  151      { return const_reverse_iterator(this->end()); }
 
  153      const_reverse_iterator
 
  154      crend() const noexcept
 
  155      { return const_reverse_iterator(this->begin()); }
 
  157      // [string.view.capacity], capacity
 
  160      size() const noexcept
 
  161      { return this->_M_len; }
 
  164      length() const noexcept
 
  168      max_size() const noexcept
 
  170        return (npos - sizeof(size_type) - sizeof(void*))
 
  171                / sizeof(value_type) / 4;
 
  174      _GLIBCXX_NODISCARD constexpr bool
 
  175      empty() const noexcept
 
  176      { return this->_M_len == 0; }
 
  178      // [string.view.access], element access
 
  180      constexpr const _CharT&
 
  181      operator[](size_type __pos) const
 
  183        __glibcxx_assert(__pos < this->_M_len);
 
  184        return *(this->_M_str + __pos);
 
  187      constexpr const _CharT&
 
  188      at(size_type __pos) const
 
  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() "
 
  195                                         __pos, this->size()),
 
  199      constexpr const _CharT&
 
  202        __glibcxx_assert(this->_M_len > 0);
 
  203        return *this->_M_str;
 
  206      constexpr const _CharT&
 
  209        __glibcxx_assert(this->_M_len > 0);
 
  210        return *(this->_M_str + this->_M_len - 1);
 
  213      constexpr const _CharT*
 
  214      data() const noexcept
 
  215      { return this->_M_str; }
 
  217      // [string.view.modifiers], modifiers:
 
  220      remove_prefix(size_type __n)
 
  222        __glibcxx_assert(this->_M_len >= __n);
 
  228      remove_suffix(size_type __n)
 
  229      { this->_M_len -= __n; }
 
  232      swap(basic_string_view& __sv) noexcept
 
  240      // [string.view.ops], string operations:
 
  242      template<typename _Allocator>
 
  243        explicit operator basic_string<_CharT, _Traits, _Allocator>() const
 
  245          return { this->_M_str, this->_M_len };
 
  248      template<typename _Allocator = std::allocator<_CharT>>
 
  249        basic_string<_CharT, _Traits, _Allocator>
 
  250        to_string(const _Allocator& __alloc = _Allocator()) const
 
  252          return { this->_M_str, this->_M_len, __alloc };
 
  256      copy(_CharT* __str, size_type __n, size_type __pos = 0) const
 
  258        __glibcxx_requires_string_len(__str, __n);
 
  259        if (__pos > this->_M_len)
 
  260          __throw_out_of_range_fmt(__N("basic_string_view::copy: __pos "
 
  261                                       "(which is %zu) > this->size() "
 
  263                                   __pos, this->size());
 
  264        size_type __rlen{std::min(__n, size_type{this->_M_len  - __pos})};
 
  265        for (auto __begin = this->_M_str + __pos,
 
  266             __end = __begin + __rlen; __begin != __end;)
 
  267          *__str++ = *__begin++;
 
  272      // [string.view.ops], string operations:
 
  274      constexpr basic_string_view
 
  275      substr(size_type __pos = 0, size_type __n = npos) const
 
  277        return __pos <= this->_M_len
 
  278             ? basic_string_view{this->_M_str + __pos,
 
  279                                std::min(__n, size_type{this->_M_len  - __pos})}
 
  280             : (__throw_out_of_range_fmt(__N("basic_string_view::substr: __pos "
 
  281                                             "(which is %zu) > this->size() "
 
  283                                     __pos, this->size()), basic_string_view{});
 
  287      compare(basic_string_view __str) const noexcept
 
  289        int __ret = traits_type::compare(this->_M_str, __str._M_str,
 
  290                                         std::min(this->_M_len, __str._M_len));
 
  292          __ret = _S_compare(this->_M_len, __str._M_len);
 
  297      compare(size_type __pos1, size_type __n1, basic_string_view __str) const
 
  298      { return this->substr(__pos1, __n1).compare(__str); }
 
  301      compare(size_type __pos1, size_type __n1,
 
  302              basic_string_view __str, size_type __pos2, size_type __n2) const
 
  303      { return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); }
 
  306      compare(const _CharT* __str) const noexcept
 
  307      { return this->compare(basic_string_view{__str}); }
 
  310      compare(size_type __pos1, size_type __n1, const _CharT* __str) const
 
  311      { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); }
 
  314      compare(size_type __pos1, size_type __n1,
 
  315              const _CharT* __str, size_type __n2) const
 
  317        return this->substr(__pos1, __n1)
 
  318                   .compare(basic_string_view(__str, __n2));
 
  322      find(basic_string_view __str, size_type __pos = 0) const noexcept
 
  323      { return this->find(__str._M_str, __pos, __str._M_len); }
 
  326      find(_CharT __c, size_type __pos=0) const noexcept;
 
  329      find(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
 
  332      find(const _CharT* __str, size_type __pos=0) const noexcept
 
  333      { return this->find(__str, __pos, traits_type::length(__str)); }
 
  336      rfind(basic_string_view __str, size_type __pos = npos) const noexcept
 
  337      { return this->rfind(__str._M_str, __pos, __str._M_len); }
 
  340      rfind(_CharT __c, size_type __pos = npos) const noexcept;
 
  343      rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
 
  346      rfind(const _CharT* __str, size_type __pos = npos) const noexcept
 
  347      { return this->rfind(__str, __pos, traits_type::length(__str)); }
 
  350      find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept
 
  351      { return this->find_first_of(__str._M_str, __pos, __str._M_len); }
 
  354      find_first_of(_CharT __c, size_type __pos = 0) const noexcept
 
  355      { return this->find(__c, __pos); }
 
  358      find_first_of(const _CharT* __str, size_type __pos, size_type __n) const;
 
  361      find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept
 
  362      { return this->find_first_of(__str, __pos, traits_type::length(__str)); }
 
  365      find_last_of(basic_string_view __str,
 
  366                   size_type __pos = npos) const noexcept
 
  367      { return this->find_last_of(__str._M_str, __pos, __str._M_len); }
 
  370      find_last_of(_CharT __c, size_type __pos=npos) const noexcept
 
  371      { return this->rfind(__c, __pos); }
 
  374      find_last_of(const _CharT* __str, size_type __pos, size_type __n) const;
 
  377      find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept
 
  378      { return this->find_last_of(__str, __pos, traits_type::length(__str)); }
 
  381      find_first_not_of(basic_string_view __str,
 
  382                        size_type __pos = 0) const noexcept
 
  383      { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); }
 
  386      find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept;
 
  389      find_first_not_of(const _CharT* __str,
 
  390                        size_type __pos, size_type __n) const;
 
  393      find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept
 
  395        return this->find_first_not_of(__str, __pos,
 
  396                                       traits_type::length(__str));
 
  400      find_last_not_of(basic_string_view __str,
 
  401                       size_type __pos = npos) const noexcept
 
  402      { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); }
 
  405      find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept;
 
  408      find_last_not_of(const _CharT* __str,
 
  409                       size_type __pos, size_type __n) const;
 
  412      find_last_not_of(const _CharT* __str,
 
  413                       size_type __pos = npos) const noexcept
 
  415        return this->find_last_not_of(__str, __pos,
 
  416                                      traits_type::length(__str));
 
  422      _S_compare(size_type __n1, size_type __n2) noexcept
 
  424        return difference_type(__n1 - __n2) > std::numeric_limits<int>::max()
 
  425             ? std::numeric_limits<int>::max()
 
  426             : difference_type(__n1 - __n2) < std::numeric_limits<int>::min()
 
  427             ? std::numeric_limits<int>::min()
 
  428             : static_cast<int>(difference_type(__n1 - __n2));
 
  432      const _CharT* _M_str;
 
  435  // [string.view.comparison], non-member basic_string_view comparison functions
 
  437  // Several of these functions use type_identity_t to create a non-deduced
 
  438  // context, so that only one argument participates in template argument
 
  439  // deduction and the other argument gets implicitly converted to the deduced
 
  442  template<typename _CharT, typename _Traits>
 
  444    operator==(basic_string_view<_CharT, _Traits> __x,
 
  445               basic_string_view<_CharT, _Traits> __y) noexcept
 
  446    { return __x.size() == __y.size() && __x.compare(__y) == 0; }
 
  448  template<typename _CharT, typename _Traits>
 
  450    operator==(basic_string_view<_CharT, _Traits> __x,
 
  451               __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
 
  453    { return __x.size() == __y.size() && __x.compare(__y) == 0; }
 
  455  template<typename _CharT, typename _Traits>
 
  457    operator==(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
 
  458               basic_string_view<_CharT, _Traits> __y) noexcept
 
  459    { return __x.size() == __y.size() && __x.compare(__y) == 0; }
 
  461  template<typename _CharT, typename _Traits>
 
  463    operator!=(basic_string_view<_CharT, _Traits> __x,
 
  464               basic_string_view<_CharT, _Traits> __y) noexcept
 
  465    { return !(__x == __y); }
 
  467  template<typename _CharT, typename _Traits>
 
  469    operator!=(basic_string_view<_CharT, _Traits> __x,
 
  470               __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
 
  472    { return !(__x == __y); }
 
  474  template<typename _CharT, typename _Traits>
 
  476    operator!=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
 
  477               basic_string_view<_CharT, _Traits> __y) noexcept
 
  478    { return !(__x == __y); }
 
  480  template<typename _CharT, typename _Traits>
 
  482    operator< (basic_string_view<_CharT, _Traits> __x,
 
  483               basic_string_view<_CharT, _Traits> __y) noexcept
 
  484    { return __x.compare(__y) < 0; }
 
  486  template<typename _CharT, typename _Traits>
 
  488    operator< (basic_string_view<_CharT, _Traits> __x,
 
  489               __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
 
  491    { return __x.compare(__y) < 0; }
 
  493  template<typename _CharT, typename _Traits>
 
  495    operator< (__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
 
  496               basic_string_view<_CharT, _Traits> __y) noexcept
 
  497    { return __x.compare(__y) < 0; }
 
  499  template<typename _CharT, typename _Traits>
 
  501    operator> (basic_string_view<_CharT, _Traits> __x,
 
  502               basic_string_view<_CharT, _Traits> __y) noexcept
 
  503    { return __x.compare(__y) > 0; }
 
  505  template<typename _CharT, typename _Traits>
 
  507    operator> (basic_string_view<_CharT, _Traits> __x,
 
  508               __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
 
  510    { return __x.compare(__y) > 0; }
 
  512  template<typename _CharT, typename _Traits>
 
  514    operator> (__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
 
  515               basic_string_view<_CharT, _Traits> __y) noexcept
 
  516    { return __x.compare(__y) > 0; }
 
  518  template<typename _CharT, typename _Traits>
 
  520    operator<=(basic_string_view<_CharT, _Traits> __x,
 
  521               basic_string_view<_CharT, _Traits> __y) noexcept
 
  522    { return __x.compare(__y) <= 0; }
 
  524  template<typename _CharT, typename _Traits>
 
  526    operator<=(basic_string_view<_CharT, _Traits> __x,
 
  527               __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
 
  529    { return __x.compare(__y) <= 0; }
 
  531  template<typename _CharT, typename _Traits>
 
  533    operator<=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
 
  534               basic_string_view<_CharT, _Traits> __y) noexcept
 
  535    { return __x.compare(__y) <= 0; }
 
  537  template<typename _CharT, typename _Traits>
 
  539    operator>=(basic_string_view<_CharT, _Traits> __x,
 
  540               basic_string_view<_CharT, _Traits> __y) noexcept
 
  541    { return __x.compare(__y) >= 0; }
 
  543  template<typename _CharT, typename _Traits>
 
  545    operator>=(basic_string_view<_CharT, _Traits> __x,
 
  546               __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
 
  548    { return __x.compare(__y) >= 0; }
 
  550  template<typename _CharT, typename _Traits>
 
  552    operator>=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x,
 
  553               basic_string_view<_CharT, _Traits> __y) noexcept
 
  554    { return __x.compare(__y) >= 0; }
 
  556  // [string.view.io], Inserters and extractors
 
  557  template<typename _CharT, typename _Traits>
 
  558    inline basic_ostream<_CharT, _Traits>&
 
  559    operator<<(basic_ostream<_CharT, _Traits>& __os,
 
  560               basic_string_view<_CharT,_Traits> __str)
 
  561    { return __ostream_insert(__os, __str.data(), __str.size()); }
 
  564  // basic_string_view typedef names
 
  566  using string_view = basic_string_view<char>;
 
  567#ifdef _GLIBCXX_USE_WCHAR_T
 
  568  using wstring_view = basic_string_view<wchar_t>;
 
  570#ifdef _GLIBCXX_USE_CHAR8_T
 
  571  using u8string_view = basic_string_view<char8_t>;
 
  573  using u16string_view = basic_string_view<char16_t>;
 
  574  using u32string_view = basic_string_view<char32_t>;
 
  575} // namespace fundamentals_v1
 
  576} // namespace experimental
 
  579  // [string.view.hash], hash support:
 
  580  template<typename _Tp>
 
  584    struct hash<experimental::string_view>
 
  585    : public __hash_base<size_t, experimental::string_view>
 
  588      operator()(const experimental::string_view& __str) const noexcept
 
  589      { return std::_Hash_impl::hash(__str.data(), __str.length()); }
 
  593    struct __is_fast_hash<hash<experimental::string_view>> : std::false_type
 
  596#ifdef _GLIBCXX_USE_WCHAR_T
 
  598    struct hash<experimental::wstring_view>
 
  599    : public __hash_base<size_t, wstring>
 
  602      operator()(const experimental::wstring_view& __s) const noexcept
 
  603      { return std::_Hash_impl::hash(__s.data(),
 
  604                                     __s.length() * sizeof(wchar_t)); }
 
  608    struct __is_fast_hash<hash<experimental::wstring_view>> : std::false_type
 
  612#ifdef _GLIBCXX_USE_CHAR8_T
 
  614    struct hash<experimental::u8string_view>
 
  615    : public __hash_base<size_t, experimental::u8string_view>
 
  618      operator()(const experimental::u8string_view& __s) const noexcept
 
  619      { return std::_Hash_impl::hash(__s.data(), __s.length()); }
 
  623    struct __is_fast_hash<hash<experimental::u8string_view>> : std::false_type
 
  628    struct hash<experimental::u16string_view>
 
  629    : public __hash_base<size_t, experimental::u16string_view>
 
  632      operator()(const experimental::u16string_view& __s) const noexcept
 
  633      { return std::_Hash_impl::hash(__s.data(),
 
  634                                     __s.length() * sizeof(char16_t)); }
 
  638    struct __is_fast_hash<hash<experimental::u16string_view>> : std::false_type
 
  642    struct hash<experimental::u32string_view>
 
  643    : public __hash_base<size_t, experimental::u32string_view>
 
  646      operator()(const experimental::u32string_view& __s) const noexcept
 
  647      { return std::_Hash_impl::hash(__s.data(),
 
  648                                     __s.length() * sizeof(char32_t)); }
 
  652    struct __is_fast_hash<hash<experimental::u32string_view>> : std::false_type
 
  655namespace experimental
 
  657  // I added these EMSR.
 
  658  inline namespace literals
 
  660  inline namespace string_view_literals
 
  662#pragma GCC diagnostic push
 
  663#pragma GCC diagnostic ignored "-Wliteral-suffix"
 
  664    inline constexpr basic_string_view<char>
 
  665    operator""sv(const char* __str, size_t __len) noexcept
 
  666    { return basic_string_view<char>{__str, __len}; }
 
  668#ifdef _GLIBCXX_USE_WCHAR_T
 
  669    inline constexpr basic_string_view<wchar_t>
 
  670    operator""sv(const wchar_t* __str, size_t __len) noexcept
 
  671    { return basic_string_view<wchar_t>{__str, __len}; }
 
  674#ifdef _GLIBCXX_USE_CHAR8_T
 
  675    inline constexpr basic_string_view<char8_t>
 
  676    operator""sv(const char8_t* __str, size_t __len) noexcept
 
  677    { return basic_string_view<char8_t>{__str, __len}; }
 
  680    inline constexpr basic_string_view<char16_t>
 
  681    operator""sv(const char16_t* __str, size_t __len) noexcept
 
  682    { return basic_string_view<char16_t>{__str, __len}; }
 
  684    inline constexpr basic_string_view<char32_t>
 
  685    operator""sv(const char32_t* __str, size_t __len) noexcept
 
  686    { return basic_string_view<char32_t>{__str, __len}; }
 
  687#pragma GCC diagnostic pop
 
  688  } // namespace string_literals
 
  689  } // namespace literals
 
  690} // namespace experimental
 
  692#if __cpp_lib_concepts
 
  695    // Opt-in to borrowed_range concept
 
  696    template<typename _CharT, typename _Traits>
 
  697      inline constexpr bool
 
  698        enable_borrowed_range<experimental::basic_string_view<_CharT, _Traits>>
 
  701    // Opt-in to view concept
 
  702    template<typename _CharT, typename _Traits>
 
  703      inline constexpr bool
 
  704        enable_view<experimental::basic_string_view<_CharT, _Traits>> = true;
 
  708_GLIBCXX_END_NAMESPACE_VERSION
 
  711#include <experimental/bits/string_view.tcc>
 
  713#endif // __cplusplus <= 201103L
 
  715#endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW