mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 20:01:22 -05:00
This paper implement the changes from P2438R2 basic_string::substr() && paper into C++26. The additional substr and constructor overload are implemented only for SSO string, as they require mutating the content (if reused), and thus would require copy of the string anyway for COW strings. (In consequence allocators implicitly constructible from int remain ambiguous for C++11 ABI strings, see r16-7497-gfa1149534d8580). In addition to cases when the allocators are not compatible (equal), this patch does not reuse (transfer) allocator storage, if the selected substring fits inside the SSO buffer, so we do not risk keeping large chunk of memory for few characters. (This also covers cases when the source stored the content in the local buffer). As this additional overloads are meant to be optimization, in contrast to move constructor, the source is left unmodified if the allocation is not transferred. This avoid introducing a write (of null terminator) to previously untouched, heap allocated, memory. Separate overloads for substr(size_type __pos, size_type __n) and substr(size_type __pos == 0), that delegate to corresponding constructor, are provided to avoid the check of __n against the length() in the later case. Finally, the signatures of existing substr() overload are not modified (no longer required since C++20), which avoid any impact on the ABI. PR libstdc++/119745 libstdc++-v3/ChangeLog: * include/bits/basic_string.h (basic_string::_M_construct) [__cplusplus >= 202302L]: Declare. (basic_string::basic_string(basic_string&&, size_type, const _Alloc&)) (basic_string(basic_string&&, size_type, size_type, const _Alloc&)) (basic_string::substr(size_type, size_type) &&) (basic_string::substr(size_type) &&) [__cplusplus >= 202302L]: Define. * include/bits/basic_string.tcc (basic_string::_M_construct) [__cplusplus >= 202302L]: Define. * testsuite/21_strings/basic_string/operations/substr/rvalue.cc: New test. Reviewed-by: Jonathan Wakely <jwakely@redhat.com> Reviewed-by: Patrick Palka <ppalka@redhat.com> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
5098 lines
173 KiB
C++
5098 lines
173 KiB
C++
// Components for manipulating sequences of characters -*- C++ -*-
|
|
|
|
// Copyright (C) 1997-2026 Free Software Foundation, Inc.
|
|
//
|
|
// This file is part of the GNU ISO C++ Library. This library is free
|
|
// software; you can redistribute it and/or modify it under the
|
|
// terms of the GNU General Public License as published by the
|
|
// Free Software Foundation; either version 3, or (at your option)
|
|
// any later version.
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// Under Section 7 of GPL version 3, you are granted additional
|
|
// permissions described in the GCC Runtime Library Exception, version
|
|
// 3.1, as published by the Free Software Foundation.
|
|
|
|
// You should have received a copy of the GNU General Public License and
|
|
// a copy of the GCC Runtime Library Exception along with this program;
|
|
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
// <http://www.gnu.org/licenses/>.
|
|
|
|
/** @file bits/basic_string.h
|
|
* This is an internal header file, included by other library headers.
|
|
* Do not attempt to use it directly. @headername{string}
|
|
*/
|
|
|
|
//
|
|
// ISO C++ 14882: 21 Strings library
|
|
//
|
|
|
|
#ifndef _BASIC_STRING_H
|
|
#define _BASIC_STRING_H 1
|
|
|
|
#ifdef _GLIBCXX_SYSHDR
|
|
#pragma GCC system_header
|
|
#endif
|
|
|
|
#include <ext/alloc_traits.h>
|
|
#include <debug/debug.h>
|
|
|
|
#if __cplusplus >= 201103L
|
|
#include <initializer_list>
|
|
#endif
|
|
|
|
#include <bits/version.h>
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
# include <string_view>
|
|
#endif
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
# include <bits/ranges_algobase.h> // ranges::copy
|
|
# include <bits/ranges_util.h> // ranges::subrange
|
|
#endif
|
|
|
|
#if __cplusplus > 202302L
|
|
# include <charconv>
|
|
#endif
|
|
|
|
|
|
#if ! _GLIBCXX_USE_CXX11_ABI
|
|
# include "cow_string.h"
|
|
#else
|
|
|
|
namespace std _GLIBCXX_VISIBILITY(default)
|
|
{
|
|
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|
_GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|
|
|
/**
|
|
* @class basic_string basic_string.h <string>
|
|
* @brief Managing sequences of characters and character-like objects.
|
|
*
|
|
* @ingroup strings
|
|
* @ingroup sequences
|
|
* @headerfile string
|
|
* @since C++98
|
|
*
|
|
* @tparam _CharT Type of character
|
|
* @tparam _Traits Traits for character type, defaults to
|
|
* char_traits<_CharT>.
|
|
* @tparam _Alloc Allocator type, defaults to allocator<_CharT>.
|
|
*
|
|
* Meets the requirements of a <a href="tables.html#65">container</a>, a
|
|
* <a href="tables.html#66">reversible container</a>, and a
|
|
* <a href="tables.html#67">sequence</a>. Of the
|
|
* <a href="tables.html#68">optional sequence requirements</a>, only
|
|
* @c push_back, @c at, and @c %array access are supported.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
class basic_string
|
|
{
|
|
#if __cplusplus >= 202002L
|
|
static_assert(is_trivially_copyable_v<_CharT>
|
|
&& is_trivially_default_constructible_v<_CharT>
|
|
&& is_standard_layout_v<_CharT>);
|
|
static_assert(is_same_v<_CharT, typename _Traits::char_type>);
|
|
static_assert(is_same_v<_CharT, typename _Alloc::value_type>);
|
|
using _Char_alloc_type = _Alloc;
|
|
#else
|
|
typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
|
|
rebind<_CharT>::other _Char_alloc_type;
|
|
#endif
|
|
|
|
typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits;
|
|
|
|
// Types:
|
|
public:
|
|
typedef _Traits traits_type;
|
|
typedef typename _Traits::char_type value_type;
|
|
typedef _Char_alloc_type allocator_type;
|
|
typedef typename _Alloc_traits::size_type size_type;
|
|
typedef typename _Alloc_traits::difference_type difference_type;
|
|
typedef typename _Alloc_traits::reference reference;
|
|
typedef typename _Alloc_traits::const_reference const_reference;
|
|
typedef typename _Alloc_traits::pointer pointer;
|
|
typedef typename _Alloc_traits::const_pointer const_pointer;
|
|
typedef __gnu_cxx::__normal_iterator<pointer, basic_string> iterator;
|
|
typedef __gnu_cxx::__normal_iterator<const_pointer, basic_string>
|
|
const_iterator;
|
|
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
|
typedef std::reverse_iterator<iterator> reverse_iterator;
|
|
|
|
/// Value returned by various member functions when they fail.
|
|
static const size_type npos = static_cast<size_type>(-1);
|
|
|
|
protected:
|
|
// type used for positions in insert, erase etc.
|
|
#if __cplusplus < 201103L
|
|
typedef iterator __const_iterator;
|
|
#else
|
|
typedef const_iterator __const_iterator;
|
|
#endif
|
|
|
|
private:
|
|
static _GLIBCXX20_CONSTEXPR pointer
|
|
_S_allocate(_Char_alloc_type& __a, size_type __n)
|
|
{
|
|
pointer __p = _Alloc_traits::allocate(__a, __n);
|
|
#if __glibcxx_constexpr_string >= 201907L
|
|
// std::char_traits begins the lifetime of characters,
|
|
// but custom traits might not, so do it here.
|
|
if constexpr (!is_same_v<_Traits, char_traits<_CharT>>)
|
|
if (std::__is_constant_evaluated())
|
|
// Begin the lifetime of characters in allocated storage.
|
|
for (size_type __i = 0; __i < __n; ++__i)
|
|
std::construct_at(__builtin_addressof(__p[__i]));
|
|
#endif
|
|
return __p;
|
|
}
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
// A helper type for avoiding boiler-plate.
|
|
typedef basic_string_view<_CharT, _Traits> __sv_type;
|
|
|
|
template<typename _Tp, typename _Res>
|
|
using _If_sv = enable_if_t<
|
|
__and_<is_convertible<const _Tp&, __sv_type>,
|
|
__not_<is_convertible<const _Tp*, const basic_string*>>,
|
|
__not_<is_convertible<const _Tp&, const _CharT*>>>::value,
|
|
_Res>;
|
|
|
|
// Allows an implicit conversion to __sv_type.
|
|
_GLIBCXX20_CONSTEXPR
|
|
static __sv_type
|
|
_S_to_string_view(__sv_type __svt) noexcept
|
|
{ return __svt; }
|
|
|
|
// Wraps a string_view by explicit conversion and thus
|
|
// allows to add an internal constructor that does not
|
|
// participate in overload resolution when a string_view
|
|
// is provided.
|
|
struct __sv_wrapper
|
|
{
|
|
_GLIBCXX20_CONSTEXPR explicit
|
|
__sv_wrapper(__sv_type __sv) noexcept : _M_sv(__sv) { }
|
|
|
|
__sv_type _M_sv;
|
|
};
|
|
|
|
/**
|
|
* @brief Only internally used: Construct string from a string view
|
|
* wrapper.
|
|
* @param __svw string view wrapper.
|
|
* @param __a Allocator to use.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
explicit
|
|
basic_string(__sv_wrapper __svw, const _Alloc& __a)
|
|
: basic_string(__svw._M_sv.data(), __svw._M_sv.size(), __a) { }
|
|
#endif
|
|
|
|
// Use empty-base optimization: http://www.cantrip.org/emptyopt.html
|
|
struct _Alloc_hider : allocator_type // TODO check __is_final
|
|
{
|
|
#if __cplusplus < 201103L
|
|
_Alloc_hider(pointer __dat, const _Alloc& __a = _Alloc())
|
|
: allocator_type(__a), _M_p(__dat) { }
|
|
#else
|
|
_GLIBCXX20_CONSTEXPR
|
|
_Alloc_hider(pointer __dat, const _Alloc& __a)
|
|
: allocator_type(__a), _M_p(__dat) { }
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
_Alloc_hider(pointer __dat, _Alloc&& __a = _Alloc())
|
|
: allocator_type(std::move(__a)), _M_p(__dat) { }
|
|
#endif
|
|
|
|
pointer _M_p; // The actual data.
|
|
};
|
|
|
|
_Alloc_hider _M_dataplus;
|
|
size_type _M_string_length;
|
|
|
|
enum { _S_local_capacity = 15 / sizeof(_CharT) };
|
|
|
|
union
|
|
{
|
|
_CharT _M_local_buf[_S_local_capacity + 1];
|
|
size_type _M_allocated_capacity;
|
|
};
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
_M_data(pointer __p)
|
|
{ _M_dataplus._M_p = __p; }
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
_M_length(size_type __length)
|
|
{ _M_string_length = __length; }
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
pointer
|
|
_M_data() const
|
|
{ return _M_dataplus._M_p; }
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
pointer
|
|
_M_local_data()
|
|
{
|
|
#if __cplusplus >= 201103L
|
|
return std::pointer_traits<pointer>::pointer_to(*_M_local_buf);
|
|
#else
|
|
return pointer(_M_local_buf);
|
|
#endif
|
|
}
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
const_pointer
|
|
_M_local_data() const
|
|
{
|
|
#if __cplusplus >= 201103L
|
|
return std::pointer_traits<const_pointer>::pointer_to(*_M_local_buf);
|
|
#else
|
|
return const_pointer(_M_local_buf);
|
|
#endif
|
|
}
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
_M_capacity(size_type __capacity)
|
|
{ _M_allocated_capacity = __capacity; }
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
_M_set_length(size_type __n)
|
|
{
|
|
traits_type::assign(_M_data()[__n], _CharT());
|
|
_M_length(__n);
|
|
}
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
bool
|
|
_M_is_local() const
|
|
{
|
|
if (_M_data() == _M_local_data())
|
|
{
|
|
if (_M_string_length > _S_local_capacity)
|
|
__builtin_unreachable();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Create & Destroy
|
|
_GLIBCXX20_CONSTEXPR
|
|
pointer
|
|
_M_create(size_type&, size_type);
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
_M_dispose()
|
|
{
|
|
if (!_M_is_local())
|
|
_M_destroy(_M_allocated_capacity);
|
|
}
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
_M_destroy(size_type __size) throw()
|
|
{ _Alloc_traits::deallocate(_M_get_allocator(), _M_data(), __size + 1); }
|
|
|
|
#if __cplusplus < 201103L || defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
|
|
// _M_construct_aux is used to implement the 21.3.1 para 15 which
|
|
// requires special behaviour if _InIterator is an integral type
|
|
template<typename _InIterator>
|
|
void
|
|
_M_construct_aux(_InIterator __beg, _InIterator __end,
|
|
std::__false_type)
|
|
{
|
|
typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
|
|
_M_construct(__beg, __end, _Tag());
|
|
}
|
|
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 438. Ambiguity in the "do the right thing" clause
|
|
template<typename _Integer>
|
|
void
|
|
_M_construct_aux(_Integer __beg, _Integer __end, std::__true_type)
|
|
{ _M_construct_aux_2(static_cast<size_type>(__beg), __end); }
|
|
|
|
void
|
|
_M_construct_aux_2(size_type __req, _CharT __c)
|
|
{ _M_construct(__req, __c); }
|
|
#endif
|
|
|
|
// For Input Iterators, used in istreambuf_iterators, etc.
|
|
template<typename _InIterator>
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
_M_construct(_InIterator __beg, _InIterator __end,
|
|
std::input_iterator_tag);
|
|
|
|
// For forward_iterators up to random_access_iterators, used for
|
|
// string::iterator, _CharT*, etc.
|
|
template<typename _FwdIterator>
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
_M_construct(_FwdIterator __beg, _FwdIterator __end,
|
|
std::forward_iterator_tag);
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
_M_construct(size_type __req, _CharT __c);
|
|
|
|
// Construct using block of memory of known size.
|
|
// If _Terminated is true assume that source is already 0 terminated.
|
|
template<bool _Terminated>
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
_M_construct(const _CharT *__c, size_type __n);
|
|
|
|
#if __cplusplus >= 202302L
|
|
constexpr void
|
|
_M_construct(basic_string&& __str, size_type __pos, size_type __n);
|
|
#endif
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
allocator_type&
|
|
_M_get_allocator()
|
|
{ return _M_dataplus; }
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
const allocator_type&
|
|
_M_get_allocator() const
|
|
{ return _M_dataplus; }
|
|
|
|
// Ensure that _M_local_buf is the active member of the union.
|
|
__attribute__((__always_inline__))
|
|
_GLIBCXX14_CONSTEXPR
|
|
void
|
|
_M_init_local_buf() _GLIBCXX_NOEXCEPT
|
|
{
|
|
#if __glibcxx_is_constant_evaluated
|
|
if (std::is_constant_evaluated())
|
|
for (size_type __i = 0; __i <= _S_local_capacity; ++__i)
|
|
_M_local_buf[__i] = _CharT();
|
|
#endif
|
|
}
|
|
|
|
__attribute__((__always_inline__))
|
|
_GLIBCXX14_CONSTEXPR
|
|
pointer
|
|
_M_use_local_data() _GLIBCXX_NOEXCEPT
|
|
{
|
|
#if __cpp_lib_is_constant_evaluated
|
|
_M_init_local_buf();
|
|
#endif
|
|
return _M_local_data();
|
|
}
|
|
|
|
private:
|
|
|
|
#ifdef _GLIBCXX_DISAMBIGUATE_REPLACE_INST
|
|
// The explicit instantiations in misc-inst.cc require this due to
|
|
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64063
|
|
template<typename _Tp, bool _Requires =
|
|
!__are_same<_Tp, _CharT*>::__value
|
|
&& !__are_same<_Tp, const _CharT*>::__value
|
|
&& !__are_same<_Tp, iterator>::__value
|
|
&& !__are_same<_Tp, const_iterator>::__value>
|
|
struct __enable_if_not_native_iterator
|
|
{ typedef basic_string& __type; };
|
|
template<typename _Tp>
|
|
struct __enable_if_not_native_iterator<_Tp, false> { };
|
|
#endif
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
_M_check(size_type __pos, const char* __s) const
|
|
{
|
|
if (__pos > this->size())
|
|
__throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > "
|
|
"this->size() (which is %zu)"),
|
|
__s, (size_t)__pos, (size_t)this->size());
|
|
return __pos;
|
|
}
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
_M_check_length(size_type __n1, size_type __n2, const char* __s) const
|
|
{
|
|
if (this->max_size() - (this->size() - __n1) < __n2)
|
|
__throw_length_error(__N(__s));
|
|
}
|
|
|
|
|
|
// NB: _M_limit doesn't check for a bad __pos value.
|
|
_GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
_M_limit(size_type __pos, size_type __off) const _GLIBCXX_NOEXCEPT
|
|
{
|
|
const bool __testoff = __off < this->size() - __pos;
|
|
return __testoff ? __off : this->size() - __pos;
|
|
}
|
|
|
|
// True if _Rep and source do not overlap.
|
|
bool
|
|
_M_disjunct(const _CharT* __s) const _GLIBCXX_NOEXCEPT
|
|
{
|
|
return (less<const _CharT*>()(__s, _M_data())
|
|
|| less<const _CharT*>()(_M_data() + this->size(), __s));
|
|
}
|
|
|
|
// When __n = 1 way faster than the general multichar
|
|
// traits_type::copy/move/assign.
|
|
_GLIBCXX20_CONSTEXPR
|
|
static void
|
|
_S_copy(_CharT* __d, const _CharT* __s, size_type __n)
|
|
{
|
|
if (__n == 1)
|
|
traits_type::assign(*__d, *__s);
|
|
else
|
|
traits_type::copy(__d, __s, __n);
|
|
}
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
static void
|
|
_S_move(_CharT* __d, const _CharT* __s, size_type __n)
|
|
{
|
|
if (__n == 1)
|
|
traits_type::assign(*__d, *__s);
|
|
else
|
|
traits_type::move(__d, __s, __n);
|
|
}
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
static void
|
|
_S_assign(_CharT* __d, size_type __n, _CharT __c)
|
|
{
|
|
if (__n == 1)
|
|
traits_type::assign(*__d, __c);
|
|
else
|
|
traits_type::assign(__d, __n, __c);
|
|
}
|
|
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wc++17-extensions"
|
|
// _S_copy_chars is a separate template to permit specialization
|
|
// to optimize for the common case of pointers as iterators.
|
|
template<class _Iterator>
|
|
_GLIBCXX20_CONSTEXPR
|
|
static void
|
|
_S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2)
|
|
{
|
|
#if __cplusplus >= 201103L
|
|
using _IterBase = decltype(std::__niter_base(__k1));
|
|
if constexpr (__or_<is_same<_IterBase, _CharT*>,
|
|
is_same<_IterBase, const _CharT*>>::value)
|
|
_S_copy(__p, std::__niter_base(__k1), __k2 - __k1);
|
|
#if __cpp_lib_concepts
|
|
else if constexpr (requires {
|
|
requires contiguous_iterator<_Iterator>;
|
|
{ std::to_address(__k1) }
|
|
-> convertible_to<const _CharT*>;
|
|
})
|
|
{
|
|
const auto __d = __k2 - __k1;
|
|
(void) (__k1 + __d); // See P3349R1
|
|
_S_copy(__p, std::to_address(__k1), static_cast<size_type>(__d));
|
|
}
|
|
#endif
|
|
else
|
|
#endif
|
|
for (; __k1 != __k2; ++__k1, (void)++__p)
|
|
traits_type::assign(*__p, static_cast<_CharT>(*__k1));
|
|
}
|
|
#pragma GCC diagnostic pop
|
|
|
|
#if __cplusplus < 201103L || defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
|
|
static void
|
|
_S_copy_chars(_CharT* __p, iterator __k1, iterator __k2)
|
|
{ _S_copy_chars(__p, __k1.base(), __k2.base()); }
|
|
|
|
static void
|
|
_S_copy_chars(_CharT* __p, const_iterator __k1, const_iterator __k2)
|
|
{ _S_copy_chars(__p, __k1.base(), __k2.base()); }
|
|
|
|
static void
|
|
_S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2)
|
|
{ _S_copy(__p, __k1, __k2 - __k1); }
|
|
|
|
static void
|
|
_S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2)
|
|
{ _S_copy(__p, __k1, __k2 - __k1); }
|
|
#endif
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
// pre: __n == ranges::distance(__rg). __p+[0,__n) is a valid range.
|
|
template<typename _Rg>
|
|
static constexpr void
|
|
_S_copy_range(pointer __p, _Rg&& __rg, size_type __n)
|
|
{
|
|
if constexpr (requires {
|
|
requires ranges::contiguous_range<_Rg>;
|
|
{ ranges::data(std::forward<_Rg>(__rg)) }
|
|
-> convertible_to<const _CharT*>;
|
|
})
|
|
_S_copy(__p, ranges::data(std::forward<_Rg>(__rg)), __n);
|
|
else
|
|
{
|
|
auto __first = ranges::begin(__rg);
|
|
const auto __last = ranges::end(__rg);
|
|
for (; __first != __last; ++__first)
|
|
traits_type::assign(*__p++, static_cast<_CharT>(*__first));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
static int
|
|
_S_compare(size_type __n1, size_type __n2) _GLIBCXX_NOEXCEPT
|
|
{
|
|
const difference_type __d = difference_type(__n1 - __n2);
|
|
|
|
if (__d > __gnu_cxx::__numeric_traits<int>::__max)
|
|
return __gnu_cxx::__numeric_traits<int>::__max;
|
|
else if (__d < __gnu_cxx::__numeric_traits<int>::__min)
|
|
return __gnu_cxx::__numeric_traits<int>::__min;
|
|
else
|
|
return int(__d);
|
|
}
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
_M_assign(const basic_string&);
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
_M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
|
|
size_type __len2);
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
_M_erase(size_type __pos, size_type __n);
|
|
|
|
public:
|
|
// Construct/copy/destroy:
|
|
// NB: We overload ctors in some cases instead of using default
|
|
// arguments, per 17.4.4.4 para. 2 item 2.
|
|
|
|
/**
|
|
* @brief Default constructor creates an empty string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string()
|
|
_GLIBCXX_NOEXCEPT_IF(is_nothrow_default_constructible<_Alloc>::value)
|
|
#if __cpp_concepts && __glibcxx_type_trait_variable_templates
|
|
requires is_default_constructible_v<_Alloc>
|
|
#endif
|
|
: _M_dataplus(_M_local_data())
|
|
{
|
|
_M_init_local_buf();
|
|
_M_set_length(0);
|
|
}
|
|
|
|
/**
|
|
* @brief Construct an empty string using allocator @a a.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
explicit
|
|
basic_string(const _Alloc& __a) _GLIBCXX_NOEXCEPT
|
|
: _M_dataplus(_M_local_data(), __a)
|
|
{
|
|
_M_init_local_buf();
|
|
_M_set_length(0);
|
|
}
|
|
|
|
/**
|
|
* @brief Construct string with copy of value of @a __str.
|
|
* @param __str Source string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(const basic_string& __str)
|
|
: _M_dataplus(_M_local_data(),
|
|
_Alloc_traits::_S_select_on_copy(__str._M_get_allocator()))
|
|
{
|
|
_M_construct<true>(__str._M_data(), __str.length());
|
|
}
|
|
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 2583. no way to supply an allocator for basic_string(str, pos)
|
|
/**
|
|
* @brief Construct string as copy of a substring.
|
|
* @param __str Source string.
|
|
* @param __pos Index of first character to copy from.
|
|
* @param __a Allocator to use.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(const basic_string& __str, size_type __pos,
|
|
const _Alloc& __a = _Alloc())
|
|
: _M_dataplus(_M_local_data(), __a)
|
|
{
|
|
const _CharT* __start = __str._M_data()
|
|
+ __str._M_check(__pos, "basic_string::basic_string");
|
|
_M_construct(__start, __start + __str._M_limit(__pos, npos),
|
|
std::forward_iterator_tag());
|
|
}
|
|
|
|
/**
|
|
* @brief Construct string as copy of a substring.
|
|
* @param __str Source string.
|
|
* @param __pos Index of first character to copy from.
|
|
* @param __n Number of characters to copy.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(const basic_string& __str, size_type __pos,
|
|
size_type __n)
|
|
: _M_dataplus(_M_local_data())
|
|
{
|
|
const _CharT* __start = __str._M_data()
|
|
+ __str._M_check(__pos, "basic_string::basic_string");
|
|
_M_construct(__start, __start + __str._M_limit(__pos, __n),
|
|
std::forward_iterator_tag());
|
|
}
|
|
|
|
/**
|
|
* @brief Construct string as copy of a substring.
|
|
* @param __str Source string.
|
|
* @param __pos Index of first character to copy from.
|
|
* @param __n Number of characters to copy.
|
|
* @param __a Allocator to use.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(const basic_string& __str, size_type __pos,
|
|
size_type __n, const _Alloc& __a)
|
|
: _M_dataplus(_M_local_data(), __a)
|
|
{
|
|
const _CharT* __start
|
|
= __str._M_data() + __str._M_check(__pos, "string::string");
|
|
_M_construct(__start, __start + __str._M_limit(__pos, __n),
|
|
std::forward_iterator_tag());
|
|
}
|
|
|
|
#if __cplusplus >= 202302L
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(basic_string&& __str, size_type __pos,
|
|
const _Alloc& __a = _Alloc())
|
|
: _M_dataplus(_M_local_data(), __a)
|
|
{
|
|
__pos = __str._M_check(__pos, "string::string");
|
|
_M_construct(std::move(__str), __pos, __str.length() - __pos);
|
|
}
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(basic_string&& __str, size_type __pos, size_type __n,
|
|
const _Alloc& __a = _Alloc())
|
|
: _M_dataplus(_M_local_data(), __a)
|
|
{
|
|
__pos = __str._M_check(__pos, "string::string");
|
|
_M_construct(std::move(__str), __pos, __str._M_limit(__pos, __n));
|
|
}
|
|
#endif // C++23
|
|
|
|
/**
|
|
* @brief Construct string initialized by a character %array.
|
|
* @param __s Source character %array.
|
|
* @param __n Number of characters to copy.
|
|
* @param __a Allocator to use (default is default allocator).
|
|
*
|
|
* NB: @a __s must have at least @a __n characters, '\\0'
|
|
* has no special meaning.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(const _CharT* __s, size_type __n,
|
|
const _Alloc& __a = _Alloc())
|
|
: _M_dataplus(_M_local_data(), __a)
|
|
{
|
|
// NB: Not required, but considered best practice.
|
|
if (__s == 0 && __n > 0)
|
|
std::__throw_logic_error(__N("basic_string: "
|
|
"construction from null is not valid"));
|
|
_M_construct(__s, __s + __n, std::forward_iterator_tag());
|
|
}
|
|
|
|
/**
|
|
* @brief Construct string as copy of a C string.
|
|
* @param __s Source C string.
|
|
* @param __a Allocator to use (default is default allocator).
|
|
*/
|
|
#if __cpp_deduction_guides && ! defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 3076. basic_string CTAD ambiguity
|
|
template<typename = _RequireAllocator<_Alloc>>
|
|
#endif
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
|
|
: _M_dataplus(_M_local_data(), __a)
|
|
{
|
|
// NB: Not required, but considered best practice.
|
|
if (__s == 0)
|
|
std::__throw_logic_error(__N("basic_string: "
|
|
"construction from null is not valid"));
|
|
const _CharT* __end = __s + traits_type::length(__s);
|
|
_M_construct(__s, __end, forward_iterator_tag());
|
|
}
|
|
|
|
/**
|
|
* @brief Construct string as multiple characters.
|
|
* @param __n Number of characters.
|
|
* @param __c Character to use.
|
|
* @param __a Allocator to use (default is default allocator).
|
|
*/
|
|
#if __cpp_deduction_guides && ! defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 3076. basic_string CTAD ambiguity
|
|
template<typename = _RequireAllocator<_Alloc>>
|
|
#endif
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc())
|
|
: _M_dataplus(_M_local_data(), __a)
|
|
{ _M_construct(__n, __c); }
|
|
|
|
#if __cplusplus >= 201103L
|
|
/**
|
|
* @brief Move construct string.
|
|
* @param __str Source string.
|
|
*
|
|
* The newly-created string contains the exact contents of @a __str.
|
|
* @a __str is a valid, but unspecified string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(basic_string&& __str) noexcept
|
|
: _M_dataplus(_M_local_data(), std::move(__str._M_get_allocator()))
|
|
{
|
|
if (__str._M_is_local())
|
|
{
|
|
_M_init_local_buf();
|
|
traits_type::copy(_M_local_buf, __str._M_local_buf,
|
|
__str.length() + 1);
|
|
}
|
|
else
|
|
{
|
|
_M_data(__str._M_data());
|
|
_M_capacity(__str._M_allocated_capacity);
|
|
}
|
|
|
|
// Must use _M_length() here not _M_set_length() because
|
|
// basic_stringbuf relies on writing into unallocated capacity so
|
|
// we mess up the contents if we put a '\0' in the string.
|
|
_M_length(__str.length());
|
|
__str._M_data(__str._M_use_local_data());
|
|
__str._M_set_length(0);
|
|
}
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
/**
|
|
* @brief Construct a string from a range.
|
|
* @since C++23
|
|
*/
|
|
template<__detail::__container_compatible_range<_CharT> _Rg>
|
|
constexpr
|
|
basic_string(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())
|
|
: basic_string(__a)
|
|
{
|
|
if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
|
|
{
|
|
const auto __n = static_cast<size_type>(ranges::distance(__rg));
|
|
reserve(__n);
|
|
_S_copy_range(_M_data(), std::forward<_Rg>(__rg), __n);
|
|
_M_set_length(__n);
|
|
}
|
|
else
|
|
{
|
|
auto __first = ranges::begin(__rg);
|
|
const auto __last = ranges::end(__rg);
|
|
for (; __first != __last; ++__first)
|
|
push_back(*__first);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @brief Construct string from an initializer %list.
|
|
* @param __l std::initializer_list of characters.
|
|
* @param __a Allocator to use (default is default allocator).
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc())
|
|
: _M_dataplus(_M_local_data(), __a)
|
|
{ _M_construct(__l.begin(), __l.end(), std::forward_iterator_tag()); }
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(const basic_string& __str, const _Alloc& __a)
|
|
: _M_dataplus(_M_local_data(), __a)
|
|
{ _M_construct(__str.begin(), __str.end(), std::forward_iterator_tag()); }
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(basic_string&& __str, const _Alloc& __a)
|
|
noexcept(_Alloc_traits::_S_always_equal())
|
|
: _M_dataplus(_M_local_data(), __a)
|
|
{
|
|
if (__str._M_is_local())
|
|
{
|
|
_M_init_local_buf();
|
|
traits_type::copy(_M_local_buf, __str._M_local_buf,
|
|
__str.length() + 1);
|
|
_M_length(__str.length());
|
|
__str._M_set_length(0);
|
|
}
|
|
else if (_Alloc_traits::_S_always_equal()
|
|
|| __str.get_allocator() == __a)
|
|
{
|
|
_M_data(__str._M_data());
|
|
_M_length(__str.length());
|
|
_M_capacity(__str._M_allocated_capacity);
|
|
__str._M_data(__str._M_use_local_data());
|
|
__str._M_set_length(0);
|
|
}
|
|
else
|
|
_M_construct(__str.begin(), __str.end(), std::forward_iterator_tag());
|
|
}
|
|
#endif // C++11
|
|
|
|
#if __cplusplus >= 202100L
|
|
basic_string(nullptr_t) = delete;
|
|
basic_string& operator=(nullptr_t) = delete;
|
|
#endif // C++23
|
|
|
|
/**
|
|
* @brief Construct string as copy of a range.
|
|
* @param __beg Start of range.
|
|
* @param __end End of range.
|
|
* @param __a Allocator to use (default is default allocator).
|
|
*/
|
|
#if __cplusplus >= 201103L
|
|
template<typename _InputIterator,
|
|
typename = std::_RequireInputIter<_InputIterator>>
|
|
#else
|
|
template<typename _InputIterator>
|
|
#endif
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(_InputIterator __beg, _InputIterator __end,
|
|
const _Alloc& __a = _Alloc())
|
|
: _M_dataplus(_M_local_data(), __a), _M_string_length(0)
|
|
{
|
|
#if __cplusplus >= 201103L
|
|
_M_construct(__beg, __end, std::__iterator_category(__beg));
|
|
#else
|
|
typedef typename std::__is_integer<_InputIterator>::__type _Integral;
|
|
_M_construct_aux(__beg, __end, _Integral());
|
|
#endif
|
|
}
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
/**
|
|
* @brief Construct string from a substring of a string_view.
|
|
* @param __t Source object convertible to string view.
|
|
* @param __pos The index of the first character to copy from __t.
|
|
* @param __n The number of characters to copy from __t.
|
|
* @param __a Allocator to use.
|
|
*/
|
|
template<typename _Tp,
|
|
typename = enable_if_t<is_convertible_v<const _Tp&, __sv_type>>>
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string(const _Tp& __t, size_type __pos, size_type __n,
|
|
const _Alloc& __a = _Alloc())
|
|
: basic_string(_S_to_string_view(__t).substr(__pos, __n), __a) { }
|
|
|
|
/**
|
|
* @brief Construct string from a string_view.
|
|
* @param __t Source object convertible to string view.
|
|
* @param __a Allocator to use (default is default allocator).
|
|
*/
|
|
template<typename _Tp, typename = _If_sv<_Tp, void>>
|
|
_GLIBCXX20_CONSTEXPR
|
|
explicit
|
|
basic_string(const _Tp& __t, const _Alloc& __a = _Alloc())
|
|
: basic_string(__sv_wrapper(_S_to_string_view(__t)), __a) { }
|
|
#endif // C++17
|
|
|
|
/**
|
|
* @brief Destroy the string instance.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
~basic_string()
|
|
{ _M_dispose(); }
|
|
|
|
/**
|
|
* @brief Assign the value of @a str to this string.
|
|
* @param __str Source string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
operator=(const basic_string& __str)
|
|
{
|
|
return this->assign(__str);
|
|
}
|
|
|
|
/**
|
|
* @brief Copy contents of @a s into this string.
|
|
* @param __s Source null-terminated string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
operator=(const _CharT* __s)
|
|
{ return this->assign(__s); }
|
|
|
|
/**
|
|
* @brief Set value to string of length 1.
|
|
* @param __c Source character.
|
|
*
|
|
* Assigning to a character makes this string length 1 and
|
|
* (*this)[0] == @a c.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
operator=(_CharT __c)
|
|
{
|
|
this->assign(1, __c);
|
|
return *this;
|
|
}
|
|
|
|
#if __cplusplus >= 201103L
|
|
/**
|
|
* @brief Move assign the value of @a str to this string.
|
|
* @param __str Source string.
|
|
*
|
|
* The contents of @a str are moved into this string (without copying).
|
|
* @a str is a valid, but unspecified string.
|
|
*/
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 2063. Contradictory requirements for string move assignment
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
operator=(basic_string&& __str)
|
|
noexcept(_Alloc_traits::_S_nothrow_move())
|
|
{
|
|
const bool __equal_allocs = _Alloc_traits::_S_always_equal()
|
|
|| _M_get_allocator() == __str._M_get_allocator();
|
|
if (!_M_is_local() && _Alloc_traits::_S_propagate_on_move_assign()
|
|
&& !__equal_allocs)
|
|
{
|
|
// Destroy existing storage before replacing allocator.
|
|
_M_destroy(_M_allocated_capacity);
|
|
_M_data(_M_local_data());
|
|
_M_set_length(0);
|
|
}
|
|
// Replace allocator if POCMA is true.
|
|
std::__alloc_on_move(_M_get_allocator(), __str._M_get_allocator());
|
|
|
|
if (__str._M_is_local())
|
|
{
|
|
// We've always got room for a short string, just copy it
|
|
// (unless this is a self-move, because that would violate the
|
|
// char_traits::copy precondition that the ranges don't overlap).
|
|
if (__builtin_expect(std::__addressof(__str) != this, true))
|
|
{
|
|
if (__str.size())
|
|
this->_S_copy(_M_data(), __str._M_data(), __str.size());
|
|
_M_set_length(__str.size());
|
|
}
|
|
}
|
|
else if (_Alloc_traits::_S_propagate_on_move_assign() || __equal_allocs)
|
|
{
|
|
// Just move the allocated pointer, our allocator can free it.
|
|
pointer __data = nullptr;
|
|
size_type __capacity;
|
|
if (!_M_is_local())
|
|
{
|
|
if (__equal_allocs)
|
|
{
|
|
// __str can reuse our existing storage.
|
|
__data = _M_data();
|
|
__capacity = _M_allocated_capacity;
|
|
}
|
|
else // __str can't use it, so free it.
|
|
_M_destroy(_M_allocated_capacity);
|
|
}
|
|
|
|
_M_data(__str._M_data());
|
|
_M_length(__str.length());
|
|
_M_capacity(__str._M_allocated_capacity);
|
|
if (__data)
|
|
{
|
|
__str._M_data(__data);
|
|
__str._M_capacity(__capacity);
|
|
}
|
|
else
|
|
__str._M_data(__str._M_use_local_data());
|
|
}
|
|
else // Need to do a deep copy
|
|
_M_assign(__str);
|
|
__str.clear();
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief Set value to string constructed from initializer %list.
|
|
* @param __l std::initializer_list.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
operator=(initializer_list<_CharT> __l)
|
|
{
|
|
this->assign(__l.begin(), __l.size());
|
|
return *this;
|
|
}
|
|
#endif // C++11
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
/**
|
|
* @brief Set value to string constructed from a string_view.
|
|
* @param __svt An object convertible to string_view.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, basic_string&>
|
|
operator=(const _Tp& __svt)
|
|
{ return this->assign(__svt); }
|
|
|
|
/**
|
|
* @brief Convert to a string_view.
|
|
* @return A string_view.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
operator __sv_type() const noexcept
|
|
{ return __sv_type(data(), size()); }
|
|
#endif // C++17
|
|
|
|
// Iterators:
|
|
/**
|
|
* Returns a read/write iterator that points to the first character in
|
|
* the %string.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
iterator
|
|
begin() _GLIBCXX_NOEXCEPT
|
|
{ return iterator(_M_data()); }
|
|
|
|
/**
|
|
* Returns a read-only (constant) iterator that points to the first
|
|
* character in the %string.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
const_iterator
|
|
begin() const _GLIBCXX_NOEXCEPT
|
|
{ return const_iterator(_M_data()); }
|
|
|
|
/**
|
|
* Returns a read/write iterator that points one past the last
|
|
* character in the %string.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
iterator
|
|
end() _GLIBCXX_NOEXCEPT
|
|
{ return iterator(_M_data() + this->size()); }
|
|
|
|
/**
|
|
* Returns a read-only (constant) iterator that points one past the
|
|
* last character in the %string.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
const_iterator
|
|
end() const _GLIBCXX_NOEXCEPT
|
|
{ return const_iterator(_M_data() + this->size()); }
|
|
|
|
/**
|
|
* Returns a read/write reverse iterator that points to the last
|
|
* character in the %string. Iteration is done in reverse element
|
|
* order.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
reverse_iterator
|
|
rbegin() _GLIBCXX_NOEXCEPT
|
|
{ return reverse_iterator(this->end()); }
|
|
|
|
/**
|
|
* Returns a read-only (constant) reverse iterator that points
|
|
* to the last character in the %string. Iteration is done in
|
|
* reverse element order.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
const_reverse_iterator
|
|
rbegin() const _GLIBCXX_NOEXCEPT
|
|
{ return const_reverse_iterator(this->end()); }
|
|
|
|
/**
|
|
* Returns a read/write reverse iterator that points to one before the
|
|
* first character in the %string. Iteration is done in reverse
|
|
* element order.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
reverse_iterator
|
|
rend() _GLIBCXX_NOEXCEPT
|
|
{ return reverse_iterator(this->begin()); }
|
|
|
|
/**
|
|
* Returns a read-only (constant) reverse iterator that points
|
|
* to one before the first character in the %string. Iteration
|
|
* is done in reverse element order.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
const_reverse_iterator
|
|
rend() const _GLIBCXX_NOEXCEPT
|
|
{ return const_reverse_iterator(this->begin()); }
|
|
|
|
#if __cplusplus >= 201103L
|
|
/**
|
|
* Returns a read-only (constant) iterator that points to the first
|
|
* character in the %string.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
const_iterator
|
|
cbegin() const noexcept
|
|
{ return const_iterator(this->_M_data()); }
|
|
|
|
/**
|
|
* Returns a read-only (constant) iterator that points one past the
|
|
* last character in the %string.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
const_iterator
|
|
cend() const noexcept
|
|
{ return const_iterator(this->_M_data() + this->size()); }
|
|
|
|
/**
|
|
* Returns a read-only (constant) reverse iterator that points
|
|
* to the last character in the %string. Iteration is done in
|
|
* reverse element order.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
const_reverse_iterator
|
|
crbegin() const noexcept
|
|
{ return const_reverse_iterator(this->end()); }
|
|
|
|
/**
|
|
* Returns a read-only (constant) reverse iterator that points
|
|
* to one before the first character in the %string. Iteration
|
|
* is done in reverse element order.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
const_reverse_iterator
|
|
crend() const noexcept
|
|
{ return const_reverse_iterator(this->begin()); }
|
|
#endif
|
|
|
|
public:
|
|
// Capacity:
|
|
/// Returns the number of characters in the string, not including any
|
|
/// null-termination.
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
size() const _GLIBCXX_NOEXCEPT
|
|
{
|
|
size_type __sz = _M_string_length;
|
|
if (__sz > max_size ())
|
|
__builtin_unreachable();
|
|
return __sz;
|
|
}
|
|
|
|
/// Returns the number of characters in the string, not including any
|
|
/// null-termination.
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
length() const _GLIBCXX_NOEXCEPT
|
|
{ return size(); }
|
|
|
|
/// Returns the size() of the largest possible %string.
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
max_size() const _GLIBCXX_NOEXCEPT
|
|
{
|
|
const size_t __diffmax
|
|
= __gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(_CharT);
|
|
const size_t __allocmax = _Alloc_traits::max_size(_M_get_allocator());
|
|
return (std::min)(__diffmax, __allocmax) - 1;
|
|
}
|
|
|
|
/**
|
|
* @brief Resizes the %string to the specified number of characters.
|
|
* @param __n Number of characters the %string should contain.
|
|
* @param __c Character to fill any new elements.
|
|
*
|
|
* This function will %resize the %string to the specified
|
|
* number of characters. If the number is smaller than the
|
|
* %string's current size the %string is truncated, otherwise
|
|
* the %string is extended and new elements are %set to @a __c.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
resize(size_type __n, _CharT __c);
|
|
|
|
/**
|
|
* @brief Resizes the %string to the specified number of characters.
|
|
* @param __n Number of characters the %string should contain.
|
|
*
|
|
* This function will resize the %string to the specified length. If
|
|
* the new size is smaller than the %string's current size the %string
|
|
* is truncated, otherwise the %string is extended and new characters
|
|
* are default-constructed. For basic types such as char, this means
|
|
* setting them to 0.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
resize(size_type __n)
|
|
{ this->resize(__n, _CharT()); }
|
|
|
|
#if __cplusplus >= 201103L
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
/// A non-binding request to reduce capacity() to size().
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
shrink_to_fit() noexcept
|
|
{ reserve(); }
|
|
#pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
#ifdef __glibcxx_string_resize_and_overwrite // C++ >= 23
|
|
/** Resize the string and call a function to fill it.
|
|
*
|
|
* @param __n The maximum size requested.
|
|
* @param __op A callable object that writes characters to the string.
|
|
*
|
|
* This is a low-level function that is easy to misuse, be careful.
|
|
*
|
|
* Calling `str.resize_and_overwrite(n, op)` will reserve at least `n`
|
|
* characters in `str`, evaluate `n2 = std::move(op)(str.data(), n)`,
|
|
* and finally set the string length to `n2` (adding a null terminator
|
|
* at the end). The function object `op` is allowed to write to the
|
|
* extra capacity added by the initial reserve operation, which is not
|
|
* allowed if you just call `str.reserve(n)` yourself.
|
|
*
|
|
* This can be used to efficiently fill a `string` buffer without the
|
|
* overhead of zero-initializing characters that will be overwritten
|
|
* anyway.
|
|
*
|
|
* The callable `op` must not access the string directly (only through
|
|
* the pointer passed as its first argument), must not write more than
|
|
* `n` characters to the string, must return a value no greater than `n`,
|
|
* and must ensure that all characters up to the returned length are
|
|
* valid after it returns (i.e. there must be no uninitialized values
|
|
* left in the string after the call, because accessing them would
|
|
* have undefined behaviour). If `op` exits by throwing an exception
|
|
* the behaviour is undefined.
|
|
*
|
|
* @since C++23
|
|
*/
|
|
template<typename _Operation>
|
|
constexpr void
|
|
resize_and_overwrite(size_type __n, _Operation __op);
|
|
#endif
|
|
|
|
#if __cplusplus >= 201103L
|
|
/// Non-standard version of resize_and_overwrite for C++11 and above.
|
|
template<typename _Operation>
|
|
_GLIBCXX20_CONSTEXPR void
|
|
__resize_and_overwrite(size_type __n, _Operation __op);
|
|
#endif
|
|
|
|
/**
|
|
* Returns the total number of characters that the %string can hold
|
|
* before needing to allocate more memory.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
capacity() const _GLIBCXX_NOEXCEPT
|
|
{
|
|
size_t __sz = _M_is_local() ? size_type(_S_local_capacity)
|
|
: _M_allocated_capacity;
|
|
if (__sz < _S_local_capacity || __sz > max_size ())
|
|
__builtin_unreachable();
|
|
return __sz;
|
|
}
|
|
|
|
/**
|
|
* @brief Attempt to preallocate enough memory for specified number of
|
|
* characters.
|
|
* @param __res_arg Number of characters required.
|
|
* @throw std::length_error If @a __res_arg exceeds @c max_size().
|
|
*
|
|
* This function attempts to reserve enough memory for the
|
|
* %string to hold the specified number of characters. If the
|
|
* number requested is more than max_size(), length_error is
|
|
* thrown.
|
|
*
|
|
* The advantage of this function is that if optimal code is a
|
|
* necessity and the user can determine the string length that will be
|
|
* required, the user can reserve the memory in %advance, and thus
|
|
* prevent a possible reallocation of memory and copying of %string
|
|
* data.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
reserve(size_type __res_arg);
|
|
|
|
/**
|
|
* Equivalent to shrink_to_fit().
|
|
*/
|
|
#if __cplusplus > 201703L
|
|
[[deprecated("use shrink_to_fit() instead")]]
|
|
#endif
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
reserve();
|
|
|
|
/**
|
|
* Erases the string, making it empty.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
clear() _GLIBCXX_NOEXCEPT
|
|
{ _M_set_length(0); }
|
|
|
|
/**
|
|
* Returns true if the %string is empty. Equivalent to
|
|
* <code>*this == ""</code>.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
bool
|
|
empty() const _GLIBCXX_NOEXCEPT
|
|
{ return _M_string_length == 0; }
|
|
|
|
// Element access:
|
|
/**
|
|
* @brief Subscript access to the data contained in the %string.
|
|
* @param __pos The index of the character to access.
|
|
* @return Read-only (constant) reference to the character.
|
|
*
|
|
* This operator allows for easy, array-style, data access.
|
|
* Note that data access with this operator is unchecked and
|
|
* out_of_range lookups are not defined. (For checked lookups
|
|
* see at().)
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
const_reference
|
|
operator[] (size_type __pos) const _GLIBCXX_NOEXCEPT
|
|
{
|
|
__glibcxx_assert(__pos <= size());
|
|
return _M_data()[__pos];
|
|
}
|
|
|
|
/**
|
|
* @brief Subscript access to the data contained in the %string.
|
|
* @param __pos The index of the character to access.
|
|
* @return Read/write reference to the character.
|
|
*
|
|
* This operator allows for easy, array-style, data access.
|
|
* Note that data access with this operator is unchecked and
|
|
* out_of_range lookups are not defined. (For checked lookups
|
|
* see at().)
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
reference
|
|
operator[](size_type __pos)
|
|
{
|
|
// Allow pos == size() both in C++98 mode, as v3 extension,
|
|
// and in C++11 mode.
|
|
__glibcxx_assert(__pos <= size());
|
|
// In pedantic mode be strict in C++98 mode.
|
|
_GLIBCXX_DEBUG_PEDASSERT(__cplusplus >= 201103L || __pos < size());
|
|
return _M_data()[__pos];
|
|
}
|
|
|
|
/**
|
|
* @brief Provides access to the data contained in the %string.
|
|
* @param __n The index of the character to access.
|
|
* @return Read-only (const) reference to the character.
|
|
* @throw std::out_of_range If @a n is an invalid index.
|
|
*
|
|
* This function provides for safer data access. The parameter is
|
|
* first checked that it is in the range of the string. The function
|
|
* throws out_of_range if the check fails.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
const_reference
|
|
at(size_type __n) const
|
|
{
|
|
if (__n >= this->size())
|
|
__throw_out_of_range_fmt(__N("basic_string::at: __n "
|
|
"(which is %zu) >= this->size() "
|
|
"(which is %zu)"),
|
|
__n, this->size());
|
|
return _M_data()[__n];
|
|
}
|
|
|
|
/**
|
|
* @brief Provides access to the data contained in the %string.
|
|
* @param __n The index of the character to access.
|
|
* @return Read/write reference to the character.
|
|
* @throw std::out_of_range If @a n is an invalid index.
|
|
*
|
|
* This function provides for safer data access. The parameter is
|
|
* first checked that it is in the range of the string. The function
|
|
* throws out_of_range if the check fails.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
reference
|
|
at(size_type __n)
|
|
{
|
|
if (__n >= size())
|
|
__throw_out_of_range_fmt(__N("basic_string::at: __n "
|
|
"(which is %zu) >= this->size() "
|
|
"(which is %zu)"),
|
|
__n, this->size());
|
|
return _M_data()[__n];
|
|
}
|
|
|
|
#if __cplusplus >= 201103L
|
|
/**
|
|
* Returns a read/write reference to the data at the first
|
|
* element of the %string.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
reference
|
|
front() noexcept
|
|
{
|
|
__glibcxx_assert(!empty());
|
|
return operator[](0);
|
|
}
|
|
|
|
/**
|
|
* Returns a read-only (constant) reference to the data at the first
|
|
* element of the %string.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
const_reference
|
|
front() const noexcept
|
|
{
|
|
__glibcxx_assert(!empty());
|
|
return operator[](0);
|
|
}
|
|
|
|
/**
|
|
* Returns a read/write reference to the data at the last
|
|
* element of the %string.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
reference
|
|
back() noexcept
|
|
{
|
|
__glibcxx_assert(!empty());
|
|
return operator[](this->size() - 1);
|
|
}
|
|
|
|
/**
|
|
* Returns a read-only (constant) reference to the data at the
|
|
* last element of the %string.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
const_reference
|
|
back() const noexcept
|
|
{
|
|
__glibcxx_assert(!empty());
|
|
return operator[](this->size() - 1);
|
|
}
|
|
#endif
|
|
|
|
// Modifiers:
|
|
/**
|
|
* @brief Append a string to this string.
|
|
* @param __str The string to append.
|
|
* @return Reference to this string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
operator+=(const basic_string& __str)
|
|
{ return this->append(__str); }
|
|
|
|
/**
|
|
* @brief Append a C string.
|
|
* @param __s The C string to append.
|
|
* @return Reference to this string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
operator+=(const _CharT* __s)
|
|
{ return this->append(__s); }
|
|
|
|
/**
|
|
* @brief Append a character.
|
|
* @param __c The character to append.
|
|
* @return Reference to this string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
operator+=(_CharT __c)
|
|
{
|
|
this->push_back(__c);
|
|
return *this;
|
|
}
|
|
|
|
#if __cplusplus >= 201103L
|
|
/**
|
|
* @brief Append an initializer_list of characters.
|
|
* @param __l The initializer_list of characters to be appended.
|
|
* @return Reference to this string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
operator+=(initializer_list<_CharT> __l)
|
|
{ return this->append(__l.begin(), __l.size()); }
|
|
#endif // C++11
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
/**
|
|
* @brief Append a string_view.
|
|
* @param __svt An object convertible to string_view to be appended.
|
|
* @return Reference to this string.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, basic_string&>
|
|
operator+=(const _Tp& __svt)
|
|
{ return this->append(__svt); }
|
|
#endif // C++17
|
|
|
|
/**
|
|
* @brief Append a string to this string.
|
|
* @param __str The string to append.
|
|
* @return Reference to this string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
append(const basic_string& __str)
|
|
{ return this->append(__str._M_data(), __str.size()); }
|
|
|
|
/**
|
|
* @brief Append a substring.
|
|
* @param __str The string to append.
|
|
* @param __pos Index of the first character of str to append.
|
|
* @param __n The number of characters to append.
|
|
* @return Reference to this string.
|
|
* @throw std::out_of_range if @a __pos is not a valid index.
|
|
*
|
|
* This function appends @a __n characters from @a __str
|
|
* starting at @a __pos to this string. If @a __n is is larger
|
|
* than the number of available characters in @a __str, the
|
|
* remainder of @a __str is appended.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
append(const basic_string& __str, size_type __pos, size_type __n = npos)
|
|
{ return this->append(__str._M_data()
|
|
+ __str._M_check(__pos, "basic_string::append"),
|
|
__str._M_limit(__pos, __n)); }
|
|
|
|
/**
|
|
* @brief Append a C substring.
|
|
* @param __s The C string to append.
|
|
* @param __n The number of characters to append.
|
|
* @return Reference to this string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
append(const _CharT* __s, size_type __n)
|
|
{
|
|
__glibcxx_requires_string_len(__s, __n);
|
|
_M_check_length(size_type(0), __n, "basic_string::append");
|
|
return _M_append(__s, __n);
|
|
}
|
|
|
|
/**
|
|
* @brief Append a C string.
|
|
* @param __s The C string to append.
|
|
* @return Reference to this string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
append(const _CharT* __s)
|
|
{
|
|
__glibcxx_requires_string(__s);
|
|
const size_type __n = traits_type::length(__s);
|
|
_M_check_length(size_type(0), __n, "basic_string::append");
|
|
return _M_append(__s, __n);
|
|
}
|
|
|
|
/**
|
|
* @brief Append multiple characters.
|
|
* @param __n The number of characters to append.
|
|
* @param __c The character to use.
|
|
* @return Reference to this string.
|
|
*
|
|
* Appends __n copies of __c to this string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
append(size_type __n, _CharT __c)
|
|
{ return _M_replace_aux(this->size(), size_type(0), __n, __c); }
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
/**
|
|
* @brief Append a range to the string.
|
|
* @param __rg A range of values that are convertible to `value_type`.
|
|
* @since C++23
|
|
*
|
|
* The range `__rg` is allowed to overlap with `*this`.
|
|
*/
|
|
template<__detail::__container_compatible_range<_CharT> _Rg>
|
|
constexpr basic_string&
|
|
append_range(_Rg&& __rg)
|
|
{
|
|
// N.B. __rg may overlap with *this, so we must copy from __rg before
|
|
// existing elements or iterators referring to *this are invalidated.
|
|
// e.g. in s.append_range(views::concat(s, str)), rg overlaps s.
|
|
if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
|
|
{
|
|
const auto __len = size_type(ranges::distance(__rg));
|
|
|
|
// Don't care if this addition wraps around, we check it below:
|
|
const size_type __newlen = size() + __len;
|
|
|
|
if ((capacity() - size()) >= __len)
|
|
_S_copy_range(_M_data() + size(), std::forward<_Rg>(__rg),
|
|
__len);
|
|
else
|
|
{
|
|
_M_check_length(0, __len, "basic_string::append_range");
|
|
basic_string __s(_M_get_allocator());
|
|
__s.reserve(__newlen);
|
|
_S_copy_range(__s._M_data() + size(), std::forward<_Rg>(__rg),
|
|
__len);
|
|
_S_copy(__s._M_data(), _M_data(), size());
|
|
if (!_M_is_local())
|
|
_M_destroy(_M_allocated_capacity);
|
|
_M_data(__s._M_data());
|
|
_M_capacity(__s._M_allocated_capacity);
|
|
__s._M_data(__s._M_local_data());
|
|
__s._M_length(0);
|
|
}
|
|
_M_set_length(__newlen); // adds null-terminator
|
|
}
|
|
else
|
|
{
|
|
basic_string __s(from_range, std::forward<_Rg>(__rg),
|
|
_M_get_allocator());
|
|
append(__s);
|
|
}
|
|
return *this;
|
|
}
|
|
#endif
|
|
|
|
#if __cplusplus >= 201103L
|
|
/**
|
|
* @brief Append an initializer_list of characters.
|
|
* @param __l The initializer_list of characters to append.
|
|
* @return Reference to this string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
append(initializer_list<_CharT> __l)
|
|
{ return this->append(__l.begin(), __l.size()); }
|
|
#endif // C++11
|
|
|
|
/**
|
|
* @brief Append a range of characters.
|
|
* @param __first Iterator referencing the first character to append.
|
|
* @param __last Iterator marking the end of the range.
|
|
* @return Reference to this string.
|
|
*
|
|
* Appends characters in the range [__first,__last) to this string.
|
|
*/
|
|
#if __cplusplus >= 201103L
|
|
template<class _InputIterator,
|
|
typename = std::_RequireInputIter<_InputIterator>>
|
|
_GLIBCXX20_CONSTEXPR
|
|
#else
|
|
template<class _InputIterator>
|
|
#endif
|
|
basic_string&
|
|
append(_InputIterator __first, _InputIterator __last)
|
|
{ return this->replace(end(), end(), __first, __last); }
|
|
|
|
#ifdef __glibcxx_string_view
|
|
/**
|
|
* @brief Append a string_view.
|
|
* @param __svt An object convertible to string_view to be appended.
|
|
* @return Reference to this string.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, basic_string&>
|
|
append(const _Tp& __svt)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return this->append(__sv.data(), __sv.size());
|
|
}
|
|
|
|
/**
|
|
* @brief Append a range of characters from a string_view.
|
|
* @param __svt An object convertible to string_view to be appended from.
|
|
* @param __pos The position in the string_view to append from.
|
|
* @param __n The number of characters to append from the string_view.
|
|
* @return Reference to this string.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, basic_string&>
|
|
append(const _Tp& __svt, size_type __pos, size_type __n = npos)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return _M_append(__sv.data()
|
|
+ std::__sv_check(__sv.size(), __pos, "basic_string::append"),
|
|
std::__sv_limit(__sv.size(), __pos, __n));
|
|
}
|
|
#endif // C++17
|
|
|
|
/**
|
|
* @brief Append a single character.
|
|
* @param __c Character to append.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
push_back(_CharT __c)
|
|
{
|
|
const size_type __size = this->size();
|
|
if (__size + 1 > this->capacity())
|
|
this->_M_mutate(__size, size_type(0), 0, size_type(1));
|
|
traits_type::assign(this->_M_data()[__size], __c);
|
|
this->_M_set_length(__size + 1);
|
|
}
|
|
|
|
/**
|
|
* @brief Set value to contents of another string.
|
|
* @param __str Source string to use.
|
|
* @return Reference to this string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
assign(const basic_string& __str)
|
|
{
|
|
#if __cplusplus >= 201103L
|
|
if (_Alloc_traits::_S_propagate_on_copy_assign())
|
|
{
|
|
if (!_Alloc_traits::_S_always_equal() && !_M_is_local()
|
|
&& _M_get_allocator() != __str._M_get_allocator())
|
|
{
|
|
// Propagating allocator cannot free existing storage so must
|
|
// deallocate it before replacing current allocator.
|
|
if (__str.size() <= _S_local_capacity)
|
|
{
|
|
_M_destroy(_M_allocated_capacity);
|
|
_M_data(_M_use_local_data());
|
|
_M_set_length(0);
|
|
}
|
|
else
|
|
{
|
|
const auto __len = __str.size();
|
|
auto __alloc = __str._M_get_allocator();
|
|
// If this allocation throws there are no effects:
|
|
auto __ptr = _S_allocate(__alloc, __len + 1);
|
|
_M_destroy(_M_allocated_capacity);
|
|
_M_data(__ptr);
|
|
_M_capacity(__len);
|
|
_M_set_length(__len);
|
|
}
|
|
}
|
|
std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator());
|
|
}
|
|
#endif
|
|
this->_M_assign(__str);
|
|
return *this;
|
|
}
|
|
|
|
#if __cplusplus >= 201103L
|
|
/**
|
|
* @brief Set value to contents of another string.
|
|
* @param __str Source string to use.
|
|
* @return Reference to this string.
|
|
*
|
|
* This function sets this string to the exact contents of @a __str.
|
|
* @a __str is a valid, but unspecified string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
assign(basic_string&& __str)
|
|
noexcept(_Alloc_traits::_S_nothrow_move())
|
|
{
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 2063. Contradictory requirements for string move assignment
|
|
return *this = std::move(__str);
|
|
}
|
|
#endif // C++11
|
|
|
|
/**
|
|
* @brief Set value to a substring of a string.
|
|
* @param __str The string to use.
|
|
* @param __pos Index of the first character of str.
|
|
* @param __n Number of characters to use.
|
|
* @return Reference to this string.
|
|
* @throw std::out_of_range if @a pos is not a valid index.
|
|
*
|
|
* This function sets this string to the substring of @a __str
|
|
* consisting of @a __n characters at @a __pos. If @a __n is
|
|
* is larger than the number of available characters in @a
|
|
* __str, the remainder of @a __str is used.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
assign(const basic_string& __str, size_type __pos, size_type __n = npos)
|
|
{ return _M_replace(size_type(0), this->size(), __str._M_data()
|
|
+ __str._M_check(__pos, "basic_string::assign"),
|
|
__str._M_limit(__pos, __n)); }
|
|
|
|
/**
|
|
* @brief Set value to a C substring.
|
|
* @param __s The C string to use.
|
|
* @param __n Number of characters to use.
|
|
* @return Reference to this string.
|
|
*
|
|
* This function sets the value of this string to the first @a __n
|
|
* characters of @a __s. If @a __n is is larger than the number of
|
|
* available characters in @a __s, the remainder of @a __s is used.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
assign(const _CharT* __s, size_type __n)
|
|
{
|
|
__glibcxx_requires_string_len(__s, __n);
|
|
return _M_replace(size_type(0), this->size(), __s, __n);
|
|
}
|
|
|
|
/**
|
|
* @brief Set value to contents of a C string.
|
|
* @param __s The C string to use.
|
|
* @return Reference to this string.
|
|
*
|
|
* This function sets the value of this string to the value of @a __s.
|
|
* The data is copied, so there is no dependence on @a __s once the
|
|
* function returns.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
assign(const _CharT* __s)
|
|
{
|
|
__glibcxx_requires_string(__s);
|
|
return _M_replace(size_type(0), this->size(), __s,
|
|
traits_type::length(__s));
|
|
}
|
|
|
|
/**
|
|
* @brief Set value to multiple characters.
|
|
* @param __n Length of the resulting string.
|
|
* @param __c The character to use.
|
|
* @return Reference to this string.
|
|
*
|
|
* This function sets the value of this string to @a __n copies of
|
|
* character @a __c.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
assign(size_type __n, _CharT __c)
|
|
{ return _M_replace_aux(size_type(0), this->size(), __n, __c); }
|
|
|
|
/**
|
|
* @brief Set value to a range of characters.
|
|
* @param __first Iterator referencing the first character to append.
|
|
* @param __last Iterator marking the end of the range.
|
|
* @return Reference to this string.
|
|
*
|
|
* Sets value of string to characters in the range [__first,__last).
|
|
*/
|
|
#if __cplusplus >= 201103L
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wc++17-extensions"
|
|
template<class _InputIterator,
|
|
typename = std::_RequireInputIter<_InputIterator>>
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
assign(_InputIterator __first, _InputIterator __last)
|
|
{
|
|
using _IterTraits = iterator_traits<_InputIterator>;
|
|
if constexpr (is_pointer<decltype(std::__niter_base(__first))>::value
|
|
&& is_same<typename _IterTraits::value_type,
|
|
_CharT>::value)
|
|
{
|
|
__glibcxx_requires_valid_range(__first, __last);
|
|
return _M_replace(size_type(0), size(),
|
|
std::__niter_base(__first), __last - __first);
|
|
}
|
|
#if __cplusplus >= 202002L
|
|
else if constexpr (contiguous_iterator<_InputIterator>
|
|
&& is_same_v<iter_value_t<_InputIterator>,
|
|
_CharT>)
|
|
{
|
|
__glibcxx_requires_valid_range(__first, __last);
|
|
return _M_replace(size_type(0), size(),
|
|
std::to_address(__first), __last - __first);
|
|
}
|
|
#endif
|
|
else
|
|
return *this = basic_string(__first, __last, get_allocator());
|
|
}
|
|
#pragma GCC diagnostic pop
|
|
#else
|
|
template<class _InputIterator>
|
|
basic_string&
|
|
assign(_InputIterator __first, _InputIterator __last)
|
|
{ return this->replace(begin(), end(), __first, __last); }
|
|
#endif
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
/**
|
|
* @brief Assign a range to the string.
|
|
* @param __rg A range of values that are convertible to `value_type`.
|
|
* @since C++23
|
|
*
|
|
* The range `__rg` is allowed to overlap with `*this`.
|
|
*/
|
|
template<__detail::__container_compatible_range<_CharT> _Rg>
|
|
constexpr basic_string&
|
|
assign_range(_Rg&& __rg)
|
|
{
|
|
basic_string __s(from_range, std::forward<_Rg>(__rg),
|
|
_M_get_allocator());
|
|
assign(std::move(__s));
|
|
return *this;
|
|
}
|
|
#endif
|
|
|
|
#if __cplusplus >= 201103L
|
|
/**
|
|
* @brief Set value to an initializer_list of characters.
|
|
* @param __l The initializer_list of characters to assign.
|
|
* @return Reference to this string.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
assign(initializer_list<_CharT> __l)
|
|
{
|
|
// The initializer_list array cannot alias the characters in *this
|
|
// so we don't need to use replace to that case.
|
|
const size_type __n = __l.size();
|
|
if (__n > capacity())
|
|
*this = basic_string(__l.begin(), __l.end(), get_allocator());
|
|
else
|
|
{
|
|
if (__n)
|
|
_S_copy(_M_data(), __l.begin(), __n);
|
|
_M_set_length(__n);
|
|
}
|
|
return *this;
|
|
}
|
|
#endif // C++11
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
/**
|
|
* @brief Set value from a string_view.
|
|
* @param __svt The source object convertible to string_view.
|
|
* @return Reference to this string.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, basic_string&>
|
|
assign(const _Tp& __svt)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return this->assign(__sv.data(), __sv.size());
|
|
}
|
|
|
|
/**
|
|
* @brief Set value from a range of characters in a string_view.
|
|
* @param __svt The source object convertible to string_view.
|
|
* @param __pos The position in the string_view to assign from.
|
|
* @param __n The number of characters to assign.
|
|
* @return Reference to this string.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, basic_string&>
|
|
assign(const _Tp& __svt, size_type __pos, size_type __n = npos)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return _M_replace(size_type(0), this->size(),
|
|
__sv.data()
|
|
+ std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
|
|
std::__sv_limit(__sv.size(), __pos, __n));
|
|
}
|
|
#endif // C++17
|
|
|
|
#if __cplusplus >= 201103L
|
|
/**
|
|
* @brief Insert multiple characters.
|
|
* @param __p Const_iterator referencing location in string to
|
|
* insert at.
|
|
* @param __n Number of characters to insert
|
|
* @param __c The character to insert.
|
|
* @return Iterator referencing the first inserted char.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Inserts @a __n copies of character @a __c starting at the
|
|
* position referenced by iterator @a __p. If adding
|
|
* characters causes the length to exceed max_size(),
|
|
* length_error is thrown. The value of the string doesn't
|
|
* change if an error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
iterator
|
|
insert(const_iterator __p, size_type __n, _CharT __c)
|
|
{
|
|
_GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
|
|
const size_type __pos = __p - begin();
|
|
this->replace(__p, __p, __n, __c);
|
|
return iterator(this->_M_data() + __pos);
|
|
}
|
|
#else
|
|
/**
|
|
* @brief Insert multiple characters.
|
|
* @param __p Iterator referencing location in string to insert at.
|
|
* @param __n Number of characters to insert
|
|
* @param __c The character to insert.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Inserts @a __n copies of character @a __c starting at the
|
|
* position referenced by iterator @a __p. If adding
|
|
* characters causes the length to exceed max_size(),
|
|
* length_error is thrown. The value of the string doesn't
|
|
* change if an error is thrown.
|
|
*/
|
|
void
|
|
insert(iterator __p, size_type __n, _CharT __c)
|
|
{ this->replace(__p, __p, __n, __c); }
|
|
#endif
|
|
|
|
#if __cplusplus >= 201103L
|
|
/**
|
|
* @brief Insert a range of characters.
|
|
* @param __p Const_iterator referencing location in string to
|
|
* insert at.
|
|
* @param __beg Start of range.
|
|
* @param __end End of range.
|
|
* @return Iterator referencing the first inserted char.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Inserts characters in range [beg,end). If adding characters
|
|
* causes the length to exceed max_size(), length_error is
|
|
* thrown. The value of the string doesn't change if an error
|
|
* is thrown.
|
|
*/
|
|
template<class _InputIterator,
|
|
typename = std::_RequireInputIter<_InputIterator>>
|
|
_GLIBCXX20_CONSTEXPR
|
|
iterator
|
|
insert(const_iterator __p, _InputIterator __beg, _InputIterator __end)
|
|
{
|
|
_GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
|
|
const size_type __pos = __p - begin();
|
|
this->replace(__p, __p, __beg, __end);
|
|
return iterator(this->_M_data() + __pos);
|
|
}
|
|
#else
|
|
/**
|
|
* @brief Insert a range of characters.
|
|
* @param __p Iterator referencing location in string to insert at.
|
|
* @param __beg Start of range.
|
|
* @param __end End of range.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Inserts characters in range [__beg,__end). If adding
|
|
* characters causes the length to exceed max_size(),
|
|
* length_error is thrown. The value of the string doesn't
|
|
* change if an error is thrown.
|
|
*/
|
|
template<class _InputIterator>
|
|
void
|
|
insert(iterator __p, _InputIterator __beg, _InputIterator __end)
|
|
{ this->replace(__p, __p, __beg, __end); }
|
|
#endif
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
/**
|
|
* @brief Insert a range into the string.
|
|
* @param __rg A range of values that are convertible to `value_type`.
|
|
* @since C++23
|
|
*
|
|
* The range `__rg` is allowed to overlap with `*this`.
|
|
*/
|
|
template<__detail::__container_compatible_range<_CharT> _Rg>
|
|
constexpr iterator
|
|
insert_range(const_iterator __p, _Rg&& __rg)
|
|
{
|
|
auto __pos = __p - cbegin();
|
|
|
|
if constexpr (ranges::forward_range<_Rg>)
|
|
if (ranges::empty(__rg))
|
|
return begin() + __pos;
|
|
|
|
|
|
if (__p == cend())
|
|
append_range(std::forward<_Rg>(__rg));
|
|
else
|
|
{
|
|
basic_string __s(from_range, std::forward<_Rg>(__rg),
|
|
_M_get_allocator());
|
|
insert(__pos, __s);
|
|
}
|
|
return begin() + __pos;
|
|
}
|
|
#endif
|
|
|
|
#if __cplusplus >= 201103L
|
|
/**
|
|
* @brief Insert an initializer_list of characters.
|
|
* @param __p Iterator referencing location in string to insert at.
|
|
* @param __l The initializer_list of characters to insert.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
iterator
|
|
insert(const_iterator __p, initializer_list<_CharT> __l)
|
|
{ return this->insert(__p, __l.begin(), __l.end()); }
|
|
|
|
#ifdef _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
|
|
// See PR libstdc++/83328
|
|
void
|
|
insert(iterator __p, initializer_list<_CharT> __l)
|
|
{
|
|
_GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
|
|
this->insert(__p - begin(), __l.begin(), __l.size());
|
|
}
|
|
#endif
|
|
#endif // C++11
|
|
|
|
/**
|
|
* @brief Insert value of a string.
|
|
* @param __pos1 Position in string to insert at.
|
|
* @param __str The string to insert.
|
|
* @return Reference to this string.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Inserts value of @a __str starting at @a __pos1. If adding
|
|
* characters causes the length to exceed max_size(),
|
|
* length_error is thrown. The value of the string doesn't
|
|
* change if an error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
insert(size_type __pos1, const basic_string& __str)
|
|
{ return this->replace(__pos1, size_type(0),
|
|
__str._M_data(), __str.size()); }
|
|
|
|
/**
|
|
* @brief Insert a substring.
|
|
* @param __pos1 Position in string to insert at.
|
|
* @param __str The string to insert.
|
|
* @param __pos2 Start of characters in str to insert.
|
|
* @param __n Number of characters to insert.
|
|
* @return Reference to this string.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
* @throw std::out_of_range If @a pos1 > size() or
|
|
* @a __pos2 > @a str.size().
|
|
*
|
|
* Starting at @a pos1, insert @a __n character of @a __str
|
|
* beginning with @a __pos2. If adding characters causes the
|
|
* length to exceed max_size(), length_error is thrown. If @a
|
|
* __pos1 is beyond the end of this string or @a __pos2 is
|
|
* beyond the end of @a __str, out_of_range is thrown. The
|
|
* value of the string doesn't change if an error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
insert(size_type __pos1, const basic_string& __str,
|
|
size_type __pos2, size_type __n = npos)
|
|
{ return this->replace(__pos1, size_type(0), __str._M_data()
|
|
+ __str._M_check(__pos2, "basic_string::insert"),
|
|
__str._M_limit(__pos2, __n)); }
|
|
|
|
/**
|
|
* @brief Insert a C substring.
|
|
* @param __pos Position in string to insert at.
|
|
* @param __s The C string to insert.
|
|
* @param __n The number of characters to insert.
|
|
* @return Reference to this string.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
* @throw std::out_of_range If @a __pos is beyond the end of this
|
|
* string.
|
|
*
|
|
* Inserts the first @a __n characters of @a __s starting at @a
|
|
* __pos. If adding characters causes the length to exceed
|
|
* max_size(), length_error is thrown. If @a __pos is beyond
|
|
* end(), out_of_range is thrown. The value of the string
|
|
* doesn't change if an error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
insert(size_type __pos, const _CharT* __s, size_type __n)
|
|
{ return this->replace(__pos, size_type(0), __s, __n); }
|
|
|
|
/**
|
|
* @brief Insert a C string.
|
|
* @param __pos Position in string to insert at.
|
|
* @param __s The C string to insert.
|
|
* @return Reference to this string.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
* @throw std::out_of_range If @a pos is beyond the end of this
|
|
* string.
|
|
*
|
|
* Inserts the first @a n characters of @a __s starting at @a __pos. If
|
|
* adding characters causes the length to exceed max_size(),
|
|
* length_error is thrown. If @a __pos is beyond end(), out_of_range is
|
|
* thrown. The value of the string doesn't change if an error is
|
|
* thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
insert(size_type __pos, const _CharT* __s)
|
|
{
|
|
__glibcxx_requires_string(__s);
|
|
return this->replace(__pos, size_type(0), __s,
|
|
traits_type::length(__s));
|
|
}
|
|
|
|
/**
|
|
* @brief Insert multiple characters.
|
|
* @param __pos Index in string to insert at.
|
|
* @param __n Number of characters to insert
|
|
* @param __c The character to insert.
|
|
* @return Reference to this string.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
* @throw std::out_of_range If @a __pos is beyond the end of this
|
|
* string.
|
|
*
|
|
* Inserts @a __n copies of character @a __c starting at index
|
|
* @a __pos. If adding characters causes the length to exceed
|
|
* max_size(), length_error is thrown. If @a __pos > length(),
|
|
* out_of_range is thrown. The value of the string doesn't
|
|
* change if an error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
insert(size_type __pos, size_type __n, _CharT __c)
|
|
{ return _M_replace_aux(_M_check(__pos, "basic_string::insert"),
|
|
size_type(0), __n, __c); }
|
|
|
|
/**
|
|
* @brief Insert one character.
|
|
* @param __p Iterator referencing position in string to insert at.
|
|
* @param __c The character to insert.
|
|
* @return Iterator referencing newly inserted char.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Inserts character @a __c at position referenced by @a __p.
|
|
* If adding character causes the length to exceed max_size(),
|
|
* length_error is thrown. If @a __p is beyond end of string,
|
|
* out_of_range is thrown. The value of the string doesn't
|
|
* change if an error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
iterator
|
|
insert(__const_iterator __p, _CharT __c)
|
|
{
|
|
_GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
|
|
const size_type __pos = __p - begin();
|
|
_M_replace_aux(__pos, size_type(0), size_type(1), __c);
|
|
return iterator(_M_data() + __pos);
|
|
}
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
/**
|
|
* @brief Insert a string_view.
|
|
* @param __pos Position in string to insert at.
|
|
* @param __svt The object convertible to string_view to insert.
|
|
* @return Reference to this string.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, basic_string&>
|
|
insert(size_type __pos, const _Tp& __svt)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return this->insert(__pos, __sv.data(), __sv.size());
|
|
}
|
|
|
|
/**
|
|
* @brief Insert a string_view.
|
|
* @param __pos1 Position in string to insert at.
|
|
* @param __svt The object convertible to string_view to insert from.
|
|
* @param __pos2 Start of characters in str to insert.
|
|
* @param __n The number of characters to insert.
|
|
* @return Reference to this string.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, basic_string&>
|
|
insert(size_type __pos1, const _Tp& __svt,
|
|
size_type __pos2, size_type __n = npos)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return this->replace(__pos1, size_type(0),
|
|
__sv.data()
|
|
+ std::__sv_check(__sv.size(), __pos2, "basic_string::insert"),
|
|
std::__sv_limit(__sv.size(), __pos2, __n));
|
|
}
|
|
#endif // C++17
|
|
|
|
/**
|
|
* @brief Remove characters.
|
|
* @param __pos Index of first character to remove (default 0).
|
|
* @param __n Number of characters to remove (default remainder).
|
|
* @return Reference to this string.
|
|
* @throw std::out_of_range If @a pos is beyond the end of this
|
|
* string.
|
|
*
|
|
* Removes @a __n characters from this string starting at @a
|
|
* __pos. The length of the string is reduced by @a __n. If
|
|
* there are < @a __n characters to remove, the remainder of
|
|
* the string is truncated. If @a __p is beyond end of string,
|
|
* out_of_range is thrown. The value of the string doesn't
|
|
* change if an error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
erase(size_type __pos = 0, size_type __n = npos)
|
|
{
|
|
_M_check(__pos, "basic_string::erase");
|
|
if (__n == npos)
|
|
this->_M_set_length(__pos);
|
|
else if (__n != 0)
|
|
this->_M_erase(__pos, _M_limit(__pos, __n));
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief Remove one character.
|
|
* @param __position Iterator referencing the character to remove.
|
|
* @return iterator referencing same location after removal.
|
|
*
|
|
* Removes the character at @a __position from this string. The value
|
|
* of the string doesn't change if an error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
iterator
|
|
erase(__const_iterator __position)
|
|
{
|
|
_GLIBCXX_DEBUG_PEDASSERT(__position >= begin()
|
|
&& __position < end());
|
|
const size_type __pos = __position - begin();
|
|
this->_M_erase(__pos, size_type(1));
|
|
return iterator(_M_data() + __pos);
|
|
}
|
|
|
|
/**
|
|
* @brief Remove a range of characters.
|
|
* @param __first Iterator referencing the first character to remove.
|
|
* @param __last Iterator referencing the end of the range.
|
|
* @return Iterator referencing location of first after removal.
|
|
*
|
|
* Removes the characters in the range [first,last) from this string.
|
|
* The value of the string doesn't change if an error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
iterator
|
|
erase(__const_iterator __first, __const_iterator __last)
|
|
{
|
|
_GLIBCXX_DEBUG_PEDASSERT(__first >= begin() && __first <= __last
|
|
&& __last <= end());
|
|
const size_type __pos = __first - begin();
|
|
if (__last == end())
|
|
this->_M_set_length(__pos);
|
|
else
|
|
this->_M_erase(__pos, __last - __first);
|
|
return iterator(this->_M_data() + __pos);
|
|
}
|
|
|
|
#if __cplusplus >= 201103L
|
|
/**
|
|
* @brief Remove the last character.
|
|
*
|
|
* The string must be non-empty.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
pop_back() noexcept
|
|
{
|
|
__glibcxx_assert(!empty());
|
|
_M_erase(size() - 1, 1);
|
|
}
|
|
#endif // C++11
|
|
|
|
/**
|
|
* @brief Replace characters with value from another string.
|
|
* @param __pos Index of first character to replace.
|
|
* @param __n Number of characters to be replaced.
|
|
* @param __str String to insert.
|
|
* @return Reference to this string.
|
|
* @throw std::out_of_range If @a pos is beyond the end of this
|
|
* string.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Removes the characters in the range [__pos,__pos+__n) from
|
|
* this string. In place, the value of @a __str is inserted.
|
|
* If @a __pos is beyond end of string, out_of_range is thrown.
|
|
* If the length of the result exceeds max_size(), length_error
|
|
* is thrown. The value of the string doesn't change if an
|
|
* error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
replace(size_type __pos, size_type __n, const basic_string& __str)
|
|
{ return this->replace(__pos, __n, __str._M_data(), __str.size()); }
|
|
|
|
/**
|
|
* @brief Replace characters with value from another string.
|
|
* @param __pos1 Index of first character to replace.
|
|
* @param __n1 Number of characters to be replaced.
|
|
* @param __str String to insert.
|
|
* @param __pos2 Index of first character of str to use.
|
|
* @param __n2 Number of characters from str to use.
|
|
* @return Reference to this string.
|
|
* @throw std::out_of_range If @a __pos1 > size() or @a __pos2 >
|
|
* __str.size().
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Removes the characters in the range [__pos1,__pos1 + n) from this
|
|
* string. In place, the value of @a __str is inserted. If @a __pos is
|
|
* beyond end of string, out_of_range is thrown. If the length of the
|
|
* result exceeds max_size(), length_error is thrown. The value of the
|
|
* string doesn't change if an error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
replace(size_type __pos1, size_type __n1, const basic_string& __str,
|
|
size_type __pos2, size_type __n2 = npos)
|
|
{ return this->replace(__pos1, __n1, __str._M_data()
|
|
+ __str._M_check(__pos2, "basic_string::replace"),
|
|
__str._M_limit(__pos2, __n2)); }
|
|
|
|
/**
|
|
* @brief Replace characters with value of a C substring.
|
|
* @param __pos Index of first character to replace.
|
|
* @param __n1 Number of characters to be replaced.
|
|
* @param __s C string to insert.
|
|
* @param __n2 Number of characters from @a s to use.
|
|
* @return Reference to this string.
|
|
* @throw std::out_of_range If @a pos1 > size().
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Removes the characters in the range [__pos,__pos + __n1)
|
|
* from this string. In place, the first @a __n2 characters of
|
|
* @a __s are inserted, or all of @a __s if @a __n2 is too large. If
|
|
* @a __pos is beyond end of string, out_of_range is thrown. If
|
|
* the length of result exceeds max_size(), length_error is
|
|
* thrown. The value of the string doesn't change if an error
|
|
* is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
replace(size_type __pos, size_type __n1, const _CharT* __s,
|
|
size_type __n2)
|
|
{
|
|
__glibcxx_requires_string_len(__s, __n2);
|
|
return _M_replace(_M_check(__pos, "basic_string::replace"),
|
|
_M_limit(__pos, __n1), __s, __n2);
|
|
}
|
|
|
|
/**
|
|
* @brief Replace characters with value of a C string.
|
|
* @param __pos Index of first character to replace.
|
|
* @param __n1 Number of characters to be replaced.
|
|
* @param __s C string to insert.
|
|
* @return Reference to this string.
|
|
* @throw std::out_of_range If @a pos > size().
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Removes the characters in the range [__pos,__pos + __n1)
|
|
* from this string. In place, the characters of @a __s are
|
|
* inserted. If @a __pos is beyond end of string, out_of_range
|
|
* is thrown. If the length of result exceeds max_size(),
|
|
* length_error is thrown. The value of the string doesn't
|
|
* change if an error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
replace(size_type __pos, size_type __n1, const _CharT* __s)
|
|
{
|
|
__glibcxx_requires_string(__s);
|
|
return this->replace(__pos, __n1, __s, traits_type::length(__s));
|
|
}
|
|
|
|
/**
|
|
* @brief Replace characters with multiple characters.
|
|
* @param __pos Index of first character to replace.
|
|
* @param __n1 Number of characters to be replaced.
|
|
* @param __n2 Number of characters to insert.
|
|
* @param __c Character to insert.
|
|
* @return Reference to this string.
|
|
* @throw std::out_of_range If @a __pos > size().
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Removes the characters in the range [pos,pos + n1) from this
|
|
* string. In place, @a __n2 copies of @a __c are inserted.
|
|
* If @a __pos is beyond end of string, out_of_range is thrown.
|
|
* If the length of result exceeds max_size(), length_error is
|
|
* thrown. The value of the string doesn't change if an error
|
|
* is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c)
|
|
{ return _M_replace_aux(_M_check(__pos, "basic_string::replace"),
|
|
_M_limit(__pos, __n1), __n2, __c); }
|
|
|
|
/**
|
|
* @brief Replace range of characters with string.
|
|
* @param __i1 Iterator referencing start of range to replace.
|
|
* @param __i2 Iterator referencing end of range to replace.
|
|
* @param __str String value to insert.
|
|
* @return Reference to this string.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Removes the characters in the range [__i1,__i2). In place,
|
|
* the value of @a __str is inserted. If the length of result
|
|
* exceeds max_size(), length_error is thrown. The value of
|
|
* the string doesn't change if an error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
replace(__const_iterator __i1, __const_iterator __i2,
|
|
const basic_string& __str)
|
|
{ return this->replace(__i1, __i2, __str._M_data(), __str.size()); }
|
|
|
|
/**
|
|
* @brief Replace range of characters with C substring.
|
|
* @param __i1 Iterator referencing start of range to replace.
|
|
* @param __i2 Iterator referencing end of range to replace.
|
|
* @param __s C string value to insert.
|
|
* @param __n Number of characters from s to insert.
|
|
* @return Reference to this string.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Removes the characters in the range [__i1,__i2). In place,
|
|
* the first @a __n characters of @a __s are inserted. If the
|
|
* length of result exceeds max_size(), length_error is thrown.
|
|
* The value of the string doesn't change if an error is
|
|
* thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
replace(__const_iterator __i1, __const_iterator __i2,
|
|
const _CharT* __s, size_type __n)
|
|
{
|
|
_GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
|
|
&& __i2 <= end());
|
|
return this->replace(__i1 - begin(), __i2 - __i1, __s, __n);
|
|
}
|
|
|
|
/**
|
|
* @brief Replace range of characters with C string.
|
|
* @param __i1 Iterator referencing start of range to replace.
|
|
* @param __i2 Iterator referencing end of range to replace.
|
|
* @param __s C string value to insert.
|
|
* @return Reference to this string.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Removes the characters in the range [__i1,__i2). In place,
|
|
* the characters of @a __s are inserted. If the length of
|
|
* result exceeds max_size(), length_error is thrown. The
|
|
* value of the string doesn't change if an error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
replace(__const_iterator __i1, __const_iterator __i2, const _CharT* __s)
|
|
{
|
|
__glibcxx_requires_string(__s);
|
|
return this->replace(__i1, __i2, __s, traits_type::length(__s));
|
|
}
|
|
|
|
/**
|
|
* @brief Replace range of characters with multiple characters
|
|
* @param __i1 Iterator referencing start of range to replace.
|
|
* @param __i2 Iterator referencing end of range to replace.
|
|
* @param __n Number of characters to insert.
|
|
* @param __c Character to insert.
|
|
* @return Reference to this string.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Removes the characters in the range [__i1,__i2). In place,
|
|
* @a __n copies of @a __c are inserted. If the length of
|
|
* result exceeds max_size(), length_error is thrown. The
|
|
* value of the string doesn't change if an error is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
replace(__const_iterator __i1, __const_iterator __i2, size_type __n,
|
|
_CharT __c)
|
|
{
|
|
_GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
|
|
&& __i2 <= end());
|
|
return _M_replace_aux(__i1 - begin(), __i2 - __i1, __n, __c);
|
|
}
|
|
|
|
/**
|
|
* @brief Replace range of characters with range.
|
|
* @param __i1 Iterator referencing start of range to replace.
|
|
* @param __i2 Iterator referencing end of range to replace.
|
|
* @param __k1 Iterator referencing start of range to insert.
|
|
* @param __k2 Iterator referencing end of range to insert.
|
|
* @return Reference to this string.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Removes the characters in the range [__i1,__i2). In place,
|
|
* characters in the range [__k1,__k2) are inserted. If the
|
|
* length of result exceeds max_size(), length_error is thrown.
|
|
* The value of the string doesn't change if an error is
|
|
* thrown.
|
|
*/
|
|
#if __cplusplus >= 201103L
|
|
template<class _InputIterator,
|
|
typename = std::_RequireInputIter<_InputIterator>>
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
replace(const_iterator __i1, const_iterator __i2,
|
|
_InputIterator __k1, _InputIterator __k2)
|
|
{
|
|
_GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
|
|
&& __i2 <= end());
|
|
__glibcxx_requires_valid_range(__k1, __k2);
|
|
return this->_M_replace_dispatch(__i1, __i2, __k1, __k2,
|
|
std::__false_type());
|
|
}
|
|
#else
|
|
template<class _InputIterator>
|
|
#ifdef _GLIBCXX_DISAMBIGUATE_REPLACE_INST
|
|
typename __enable_if_not_native_iterator<_InputIterator>::__type
|
|
#else
|
|
basic_string&
|
|
#endif
|
|
replace(iterator __i1, iterator __i2,
|
|
_InputIterator __k1, _InputIterator __k2)
|
|
{
|
|
_GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
|
|
&& __i2 <= end());
|
|
__glibcxx_requires_valid_range(__k1, __k2);
|
|
typedef typename std::__is_integer<_InputIterator>::__type _Integral;
|
|
return _M_replace_dispatch(__i1, __i2, __k1, __k2, _Integral());
|
|
}
|
|
#endif
|
|
|
|
// Specializations for the common case of pointer and iterator:
|
|
// useful to avoid the overhead of temporary buffering in _M_replace.
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
replace(__const_iterator __i1, __const_iterator __i2,
|
|
_CharT* __k1, _CharT* __k2)
|
|
{
|
|
_GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
|
|
&& __i2 <= end());
|
|
__glibcxx_requires_valid_range(__k1, __k2);
|
|
return this->replace(__i1 - begin(), __i2 - __i1,
|
|
__k1, __k2 - __k1);
|
|
}
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
replace(__const_iterator __i1, __const_iterator __i2,
|
|
const _CharT* __k1, const _CharT* __k2)
|
|
{
|
|
_GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
|
|
&& __i2 <= end());
|
|
__glibcxx_requires_valid_range(__k1, __k2);
|
|
return this->replace(__i1 - begin(), __i2 - __i1,
|
|
__k1, __k2 - __k1);
|
|
}
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
replace(__const_iterator __i1, __const_iterator __i2,
|
|
iterator __k1, iterator __k2)
|
|
{
|
|
_GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
|
|
&& __i2 <= end());
|
|
__glibcxx_requires_valid_range(__k1, __k2);
|
|
return this->replace(__i1 - begin(), __i2 - __i1,
|
|
__k1.base(), __k2 - __k1);
|
|
}
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
replace(__const_iterator __i1, __const_iterator __i2,
|
|
const_iterator __k1, const_iterator __k2)
|
|
{
|
|
_GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
|
|
&& __i2 <= end());
|
|
__glibcxx_requires_valid_range(__k1, __k2);
|
|
return this->replace(__i1 - begin(), __i2 - __i1,
|
|
__k1.base(), __k2 - __k1);
|
|
}
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
/**
|
|
* @brief Replace part of the string with a range.
|
|
* @param __rg A range of values that are convertible to `value_type`.
|
|
* @since C++23
|
|
*
|
|
* The range `__rg` is allowed to overlap with `*this`.
|
|
*/
|
|
template<__detail::__container_compatible_range<_CharT> _Rg>
|
|
constexpr basic_string&
|
|
replace_with_range(const_iterator __i1, const_iterator __i2, _Rg&& __rg)
|
|
{
|
|
if (__i1 == cend())
|
|
append_range(std::forward<_Rg>(__rg));
|
|
else
|
|
{
|
|
basic_string __s(from_range, std::forward<_Rg>(__rg),
|
|
_M_get_allocator());
|
|
replace(__i1, __i2, __s);
|
|
}
|
|
return *this;
|
|
}
|
|
#endif
|
|
|
|
#if __cplusplus >= 201103L
|
|
/**
|
|
* @brief Replace range of characters with initializer_list.
|
|
* @param __i1 Iterator referencing start of range to replace.
|
|
* @param __i2 Iterator referencing end of range to replace.
|
|
* @param __l The initializer_list of characters to insert.
|
|
* @return Reference to this string.
|
|
* @throw std::length_error If new length exceeds @c max_size().
|
|
*
|
|
* Removes the characters in the range [__i1,__i2). In place,
|
|
* characters in the range [__k1,__k2) are inserted. If the
|
|
* length of result exceeds max_size(), length_error is thrown.
|
|
* The value of the string doesn't change if an error is
|
|
* thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string& replace(const_iterator __i1, const_iterator __i2,
|
|
initializer_list<_CharT> __l)
|
|
{ return this->replace(__i1, __i2, __l.begin(), __l.size()); }
|
|
#endif // C++11
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
/**
|
|
* @brief Replace range of characters with string_view.
|
|
* @param __pos The position to replace at.
|
|
* @param __n The number of characters to replace.
|
|
* @param __svt The object convertible to string_view to insert.
|
|
* @return Reference to this string.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, basic_string&>
|
|
replace(size_type __pos, size_type __n, const _Tp& __svt)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return this->replace(__pos, __n, __sv.data(), __sv.size());
|
|
}
|
|
|
|
/**
|
|
* @brief Replace range of characters with string_view.
|
|
* @param __pos1 The position to replace at.
|
|
* @param __n1 The number of characters to replace.
|
|
* @param __svt The object convertible to string_view to insert from.
|
|
* @param __pos2 The position in the string_view to insert from.
|
|
* @param __n2 The number of characters to insert.
|
|
* @return Reference to this string.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, basic_string&>
|
|
replace(size_type __pos1, size_type __n1, const _Tp& __svt,
|
|
size_type __pos2, size_type __n2 = npos)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return this->replace(__pos1, __n1,
|
|
__sv.data()
|
|
+ std::__sv_check(__sv.size(), __pos2, "basic_string::replace"),
|
|
std::__sv_limit(__sv.size(), __pos2, __n2));
|
|
}
|
|
|
|
/**
|
|
* @brief Replace range of characters with string_view.
|
|
* @param __i1 An iterator referencing the start position
|
|
to replace at.
|
|
* @param __i2 An iterator referencing the end position
|
|
for the replace.
|
|
* @param __svt The object convertible to string_view to insert from.
|
|
* @return Reference to this string.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, basic_string&>
|
|
replace(const_iterator __i1, const_iterator __i2, const _Tp& __svt)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return this->replace(__i1 - begin(), __i2 - __i1, __sv);
|
|
}
|
|
#endif // C++17
|
|
|
|
private:
|
|
template<class _Integer>
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
_M_replace_dispatch(const_iterator __i1, const_iterator __i2,
|
|
_Integer __n, _Integer __val, __true_type)
|
|
{ return _M_replace_aux(__i1 - begin(), __i2 - __i1, __n, __val); }
|
|
|
|
template<class _InputIterator>
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
_M_replace_dispatch(const_iterator __i1, const_iterator __i2,
|
|
_InputIterator __k1, _InputIterator __k2,
|
|
__false_type);
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
_M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
|
|
_CharT __c);
|
|
|
|
__attribute__((__noinline__, __noclone__, __cold__)) void
|
|
_M_replace_cold(pointer __p, size_type __len1, const _CharT* __s,
|
|
const size_type __len2, const size_type __how_much);
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
_M_replace(size_type __pos, size_type __len1, const _CharT* __s,
|
|
const size_type __len2);
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string&
|
|
_M_append(const _CharT* __s, size_type __n);
|
|
|
|
public:
|
|
|
|
/**
|
|
* @brief Copy substring into C string.
|
|
* @param __s C string to copy value into.
|
|
* @param __n Number of characters to copy.
|
|
* @param __pos Index of first character to copy.
|
|
* @return Number of characters actually copied
|
|
* @throw std::out_of_range If __pos > size().
|
|
*
|
|
* Copies up to @a __n characters starting at @a __pos into the
|
|
* C string @a __s. If @a __pos is %greater than size(),
|
|
* out_of_range is thrown.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
copy(_CharT* __s, size_type __n, size_type __pos = 0) const;
|
|
|
|
/**
|
|
* @brief Swap contents with another string.
|
|
* @param __s String to swap with.
|
|
*
|
|
* Exchanges the contents of this string with that of @a __s in constant
|
|
* time.
|
|
*/
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
swap(basic_string& __s) _GLIBCXX_NOEXCEPT;
|
|
|
|
// String operations:
|
|
/**
|
|
* @brief Return const pointer to null-terminated contents.
|
|
*
|
|
* This is a handle to internal data. Do not modify or dire things may
|
|
* happen.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
const _CharT*
|
|
c_str() const _GLIBCXX_NOEXCEPT
|
|
{ return _M_data(); }
|
|
|
|
/**
|
|
* @brief Return const pointer to contents.
|
|
*
|
|
* This is a pointer to internal data. It is undefined to modify
|
|
* the contents through the returned pointer. To get a pointer that
|
|
* allows modifying the contents use @c &str[0] instead,
|
|
* (or in C++17 the non-const @c str.data() overload).
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
const _CharT*
|
|
data() const _GLIBCXX_NOEXCEPT
|
|
{ return _M_data(); }
|
|
|
|
#if __cplusplus >= 201703L
|
|
/**
|
|
* @brief Return non-const pointer to contents.
|
|
*
|
|
* This is a pointer to the character sequence held by the string.
|
|
* Modifying the characters in the sequence is allowed.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
_CharT*
|
|
data() noexcept
|
|
{ return _M_data(); }
|
|
#endif
|
|
|
|
/**
|
|
* @brief Return copy of allocator used to construct this string.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
allocator_type
|
|
get_allocator() const _GLIBCXX_NOEXCEPT
|
|
{ return _M_get_allocator(); }
|
|
|
|
/**
|
|
* @brief Find position of a C substring.
|
|
* @param __s C string to locate.
|
|
* @param __pos Index of character to search from.
|
|
* @param __n Number of characters from @a s to search for.
|
|
* @return Index of start of first occurrence.
|
|
*
|
|
* Starting from @a __pos, searches forward for the first @a
|
|
* __n characters in @a __s within this string. If found,
|
|
* returns the index where it begins. If not found, returns
|
|
* npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find(const _CharT* __s, size_type __pos, size_type __n) const
|
|
_GLIBCXX_NOEXCEPT;
|
|
|
|
/**
|
|
* @brief Find position of a string.
|
|
* @param __str String to locate.
|
|
* @param __pos Index of character to search from (default 0).
|
|
* @return Index of start of first occurrence.
|
|
*
|
|
* Starting from @a __pos, searches forward for value of @a __str within
|
|
* this string. If found, returns the index where it begins. If not
|
|
* found, returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find(const basic_string& __str, size_type __pos = 0) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{ return this->find(__str.data(), __pos, __str.size()); }
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
/**
|
|
* @brief Find position of a string_view.
|
|
* @param __svt The object convertible to string_view to locate.
|
|
* @param __pos Index of character to search from (default 0).
|
|
* @return Index of start of first occurrence.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, size_type>
|
|
find(const _Tp& __svt, size_type __pos = 0) const
|
|
noexcept(is_same<_Tp, __sv_type>::value)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return this->find(__sv.data(), __pos, __sv.size());
|
|
}
|
|
#endif // C++17
|
|
|
|
/**
|
|
* @brief Find position of a C string.
|
|
* @param __s C string to locate.
|
|
* @param __pos Index of character to search from (default 0).
|
|
* @return Index of start of first occurrence.
|
|
*
|
|
* Starting from @a __pos, searches forward for the value of @a
|
|
* __s within this string. If found, returns the index where
|
|
* it begins. If not found, returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPT
|
|
{
|
|
__glibcxx_requires_string(__s);
|
|
return this->find(__s, __pos, traits_type::length(__s));
|
|
}
|
|
|
|
/**
|
|
* @brief Find position of a character.
|
|
* @param __c Character to locate.
|
|
* @param __pos Index of character to search from (default 0).
|
|
* @return Index of first occurrence.
|
|
*
|
|
* Starting from @a __pos, searches forward for @a __c within
|
|
* this string. If found, returns the index where it was
|
|
* found. If not found, returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT;
|
|
|
|
/**
|
|
* @brief Find last position of a string.
|
|
* @param __str String to locate.
|
|
* @param __pos Index of character to search back from (default end).
|
|
* @return Index of start of last occurrence.
|
|
*
|
|
* Starting from @a __pos, searches backward for value of @a
|
|
* __str within this string. If found, returns the index where
|
|
* it begins. If not found, returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
rfind(const basic_string& __str, size_type __pos = npos) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{ return this->rfind(__str.data(), __pos, __str.size()); }
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
/**
|
|
* @brief Find last position of a string_view.
|
|
* @param __svt The object convertible to string_view to locate.
|
|
* @param __pos Index of character to search back from (default end).
|
|
* @return Index of start of last occurrence.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, size_type>
|
|
rfind(const _Tp& __svt, size_type __pos = npos) const
|
|
noexcept(is_same<_Tp, __sv_type>::value)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return this->rfind(__sv.data(), __pos, __sv.size());
|
|
}
|
|
#endif // C++17
|
|
|
|
/**
|
|
* @brief Find last position of a C substring.
|
|
* @param __s C string to locate.
|
|
* @param __pos Index of character to search back from.
|
|
* @param __n Number of characters from s to search for.
|
|
* @return Index of start of last occurrence.
|
|
*
|
|
* Starting from @a __pos, searches backward for the first @a
|
|
* __n characters in @a __s within this string. If found,
|
|
* returns the index where it begins. If not found, returns
|
|
* npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
rfind(const _CharT* __s, size_type __pos, size_type __n) const
|
|
_GLIBCXX_NOEXCEPT;
|
|
|
|
/**
|
|
* @brief Find last position of a C string.
|
|
* @param __s C string to locate.
|
|
* @param __pos Index of character to start search at (default end).
|
|
* @return Index of start of last occurrence.
|
|
*
|
|
* Starting from @a __pos, searches backward for the value of
|
|
* @a __s within this string. If found, returns the index
|
|
* where it begins. If not found, returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
rfind(const _CharT* __s, size_type __pos = npos) const
|
|
{
|
|
__glibcxx_requires_string(__s);
|
|
return this->rfind(__s, __pos, traits_type::length(__s));
|
|
}
|
|
|
|
/**
|
|
* @brief Find last position of a character.
|
|
* @param __c Character to locate.
|
|
* @param __pos Index of character to search back from (default end).
|
|
* @return Index of last occurrence.
|
|
*
|
|
* Starting from @a __pos, searches backward for @a __c within
|
|
* this string. If found, returns the index where it was
|
|
* found. If not found, returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
rfind(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT;
|
|
|
|
/**
|
|
* @brief Find position of a character of string.
|
|
* @param __str String containing characters to locate.
|
|
* @param __pos Index of character to search from (default 0).
|
|
* @return Index of first occurrence.
|
|
*
|
|
* Starting from @a __pos, searches forward for one of the
|
|
* characters of @a __str within this string. If found,
|
|
* returns the index where it was found. If not found, returns
|
|
* npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_first_of(const basic_string& __str, size_type __pos = 0) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{ return this->find_first_of(__str.data(), __pos, __str.size()); }
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
/**
|
|
* @brief Find position of a character of a string_view.
|
|
* @param __svt An object convertible to string_view containing
|
|
* characters to locate.
|
|
* @param __pos Index of character to search from (default 0).
|
|
* @return Index of first occurrence.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, size_type>
|
|
find_first_of(const _Tp& __svt, size_type __pos = 0) const
|
|
noexcept(is_same<_Tp, __sv_type>::value)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return this->find_first_of(__sv.data(), __pos, __sv.size());
|
|
}
|
|
#endif // C++17
|
|
|
|
/**
|
|
* @brief Find position of a character of C substring.
|
|
* @param __s String containing characters to locate.
|
|
* @param __pos Index of character to search from.
|
|
* @param __n Number of characters from s to search for.
|
|
* @return Index of first occurrence.
|
|
*
|
|
* Starting from @a __pos, searches forward for one of the
|
|
* first @a __n characters of @a __s within this string. If
|
|
* found, returns the index where it was found. If not found,
|
|
* returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
|
|
_GLIBCXX_NOEXCEPT;
|
|
|
|
/**
|
|
* @brief Find position of a character of C string.
|
|
* @param __s String containing characters to locate.
|
|
* @param __pos Index of character to search from (default 0).
|
|
* @return Index of first occurrence.
|
|
*
|
|
* Starting from @a __pos, searches forward for one of the
|
|
* characters of @a __s within this string. If found, returns
|
|
* the index where it was found. If not found, returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_first_of(const _CharT* __s, size_type __pos = 0) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{
|
|
__glibcxx_requires_string(__s);
|
|
return this->find_first_of(__s, __pos, traits_type::length(__s));
|
|
}
|
|
|
|
/**
|
|
* @brief Find position of a character.
|
|
* @param __c Character to locate.
|
|
* @param __pos Index of character to search from (default 0).
|
|
* @return Index of first occurrence.
|
|
*
|
|
* Starting from @a __pos, searches forward for the character
|
|
* @a __c within this string. If found, returns the index
|
|
* where it was found. If not found, returns npos.
|
|
*
|
|
* Note: equivalent to find(__c, __pos).
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_first_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT
|
|
{ return this->find(__c, __pos); }
|
|
|
|
/**
|
|
* @brief Find last position of a character of string.
|
|
* @param __str String containing characters to locate.
|
|
* @param __pos Index of character to search back from (default end).
|
|
* @return Index of last occurrence.
|
|
*
|
|
* Starting from @a __pos, searches backward for one of the
|
|
* characters of @a __str within this string. If found,
|
|
* returns the index where it was found. If not found, returns
|
|
* npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_last_of(const basic_string& __str, size_type __pos = npos) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{ return this->find_last_of(__str.data(), __pos, __str.size()); }
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
/**
|
|
* @brief Find last position of a character of string.
|
|
* @param __svt An object convertible to string_view containing
|
|
* characters to locate.
|
|
* @param __pos Index of character to search back from (default end).
|
|
* @return Index of last occurrence.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, size_type>
|
|
find_last_of(const _Tp& __svt, size_type __pos = npos) const
|
|
noexcept(is_same<_Tp, __sv_type>::value)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return this->find_last_of(__sv.data(), __pos, __sv.size());
|
|
}
|
|
#endif // C++17
|
|
|
|
/**
|
|
* @brief Find last position of a character of C substring.
|
|
* @param __s C string containing characters to locate.
|
|
* @param __pos Index of character to search back from.
|
|
* @param __n Number of characters from s to search for.
|
|
* @return Index of last occurrence.
|
|
*
|
|
* Starting from @a __pos, searches backward for one of the
|
|
* first @a __n characters of @a __s within this string. If
|
|
* found, returns the index where it was found. If not found,
|
|
* returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
|
|
_GLIBCXX_NOEXCEPT;
|
|
|
|
/**
|
|
* @brief Find last position of a character of C string.
|
|
* @param __s C string containing characters to locate.
|
|
* @param __pos Index of character to search back from (default end).
|
|
* @return Index of last occurrence.
|
|
*
|
|
* Starting from @a __pos, searches backward for one of the
|
|
* characters of @a __s within this string. If found, returns
|
|
* the index where it was found. If not found, returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_last_of(const _CharT* __s, size_type __pos = npos) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{
|
|
__glibcxx_requires_string(__s);
|
|
return this->find_last_of(__s, __pos, traits_type::length(__s));
|
|
}
|
|
|
|
/**
|
|
* @brief Find last position of a character.
|
|
* @param __c Character to locate.
|
|
* @param __pos Index of character to search back from (default end).
|
|
* @return Index of last occurrence.
|
|
*
|
|
* Starting from @a __pos, searches backward for @a __c within
|
|
* this string. If found, returns the index where it was
|
|
* found. If not found, returns npos.
|
|
*
|
|
* Note: equivalent to rfind(__c, __pos).
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_last_of(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT
|
|
{ return this->rfind(__c, __pos); }
|
|
|
|
/**
|
|
* @brief Find position of a character not in string.
|
|
* @param __str String containing characters to avoid.
|
|
* @param __pos Index of character to search from (default 0).
|
|
* @return Index of first occurrence.
|
|
*
|
|
* Starting from @a __pos, searches forward for a character not contained
|
|
* in @a __str within this string. If found, returns the index where it
|
|
* was found. If not found, returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_first_not_of(const basic_string& __str, size_type __pos = 0) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{ return this->find_first_not_of(__str.data(), __pos, __str.size()); }
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
/**
|
|
* @brief Find position of a character not in a string_view.
|
|
* @param __svt A object convertible to string_view containing
|
|
* characters to avoid.
|
|
* @param __pos Index of character to search from (default 0).
|
|
* @return Index of first occurrence.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, size_type>
|
|
find_first_not_of(const _Tp& __svt, size_type __pos = 0) const
|
|
noexcept(is_same<_Tp, __sv_type>::value)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return this->find_first_not_of(__sv.data(), __pos, __sv.size());
|
|
}
|
|
#endif // C++17
|
|
|
|
/**
|
|
* @brief Find position of a character not in C substring.
|
|
* @param __s C string containing characters to avoid.
|
|
* @param __pos Index of character to search from.
|
|
* @param __n Number of characters from __s to consider.
|
|
* @return Index of first occurrence.
|
|
*
|
|
* Starting from @a __pos, searches forward for a character not
|
|
* contained in the first @a __n characters of @a __s within
|
|
* this string. If found, returns the index where it was
|
|
* found. If not found, returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_first_not_of(const _CharT* __s, size_type __pos,
|
|
size_type __n) const _GLIBCXX_NOEXCEPT;
|
|
|
|
/**
|
|
* @brief Find position of a character not in C string.
|
|
* @param __s C string containing characters to avoid.
|
|
* @param __pos Index of character to search from (default 0).
|
|
* @return Index of first occurrence.
|
|
*
|
|
* Starting from @a __pos, searches forward for a character not
|
|
* contained in @a __s within this string. If found, returns
|
|
* the index where it was found. If not found, returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_first_not_of(const _CharT* __s, size_type __pos = 0) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{
|
|
__glibcxx_requires_string(__s);
|
|
return this->find_first_not_of(__s, __pos, traits_type::length(__s));
|
|
}
|
|
|
|
/**
|
|
* @brief Find position of a different character.
|
|
* @param __c Character to avoid.
|
|
* @param __pos Index of character to search from (default 0).
|
|
* @return Index of first occurrence.
|
|
*
|
|
* Starting from @a __pos, searches forward for a character
|
|
* other than @a __c within this string. If found, returns the
|
|
* index where it was found. If not found, returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_first_not_of(_CharT __c, size_type __pos = 0) const
|
|
_GLIBCXX_NOEXCEPT;
|
|
|
|
/**
|
|
* @brief Find last position of a character not in string.
|
|
* @param __str String containing characters to avoid.
|
|
* @param __pos Index of character to search back from (default end).
|
|
* @return Index of last occurrence.
|
|
*
|
|
* Starting from @a __pos, searches backward for a character
|
|
* not contained in @a __str within this string. If found,
|
|
* returns the index where it was found. If not found, returns
|
|
* npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_last_not_of(const basic_string& __str, size_type __pos = npos) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{ return this->find_last_not_of(__str.data(), __pos, __str.size()); }
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
/**
|
|
* @brief Find last position of a character not in a string_view.
|
|
* @param __svt An object convertible to string_view containing
|
|
* characters to avoid.
|
|
* @param __pos Index of character to search back from (default end).
|
|
* @return Index of last occurrence.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, size_type>
|
|
find_last_not_of(const _Tp& __svt, size_type __pos = npos) const
|
|
noexcept(is_same<_Tp, __sv_type>::value)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return this->find_last_not_of(__sv.data(), __pos, __sv.size());
|
|
}
|
|
#endif // C++17
|
|
|
|
/**
|
|
* @brief Find last position of a character not in C substring.
|
|
* @param __s C string containing characters to avoid.
|
|
* @param __pos Index of character to search back from.
|
|
* @param __n Number of characters from s to consider.
|
|
* @return Index of last occurrence.
|
|
*
|
|
* Starting from @a __pos, searches backward for a character not
|
|
* contained in the first @a __n characters of @a __s within this string.
|
|
* If found, returns the index where it was found. If not found,
|
|
* returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_last_not_of(const _CharT* __s, size_type __pos,
|
|
size_type __n) const _GLIBCXX_NOEXCEPT;
|
|
/**
|
|
* @brief Find last position of a character not in C string.
|
|
* @param __s C string containing characters to avoid.
|
|
* @param __pos Index of character to search back from (default end).
|
|
* @return Index of last occurrence.
|
|
*
|
|
* Starting from @a __pos, searches backward for a character
|
|
* not contained in @a __s within this string. If found,
|
|
* returns the index where it was found. If not found, returns
|
|
* npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_last_not_of(const _CharT* __s, size_type __pos = npos) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{
|
|
__glibcxx_requires_string(__s);
|
|
return this->find_last_not_of(__s, __pos, traits_type::length(__s));
|
|
}
|
|
|
|
/**
|
|
* @brief Find last position of a different character.
|
|
* @param __c Character to avoid.
|
|
* @param __pos Index of character to search back from (default end).
|
|
* @return Index of last occurrence.
|
|
*
|
|
* Starting from @a __pos, searches backward for a character other than
|
|
* @a __c within this string. If found, returns the index where it was
|
|
* found. If not found, returns npos.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
size_type
|
|
find_last_not_of(_CharT __c, size_type __pos = npos) const
|
|
_GLIBCXX_NOEXCEPT;
|
|
|
|
/**
|
|
* @brief Get a substring.
|
|
* @param __pos Index of first character (default 0).
|
|
* @param __n Number of characters in substring (default remainder).
|
|
* @return The new string.
|
|
* @throw std::out_of_range If __pos > size().
|
|
*
|
|
* Construct and return a new string using the @a __n
|
|
* characters starting at @a __pos. If the string is too
|
|
* short, use the remainder of the characters. If @a __pos is
|
|
* beyond the end of the string, out_of_range is thrown.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
basic_string
|
|
substr(size_type __pos = 0, size_type __n = npos) const
|
|
{ return basic_string(*this,
|
|
_M_check(__pos, "basic_string::substr"), __n); }
|
|
|
|
#if __cplusplus >= 202302L
|
|
_GLIBCXX_NODISCARD
|
|
constexpr basic_string
|
|
substr(size_type __pos = 0) &&
|
|
{ return basic_string(std::move(*this), __pos); }
|
|
|
|
_GLIBCXX_NODISCARD
|
|
constexpr basic_string
|
|
substr(size_type __pos, size_type __n) &&
|
|
{ return basic_string(std::move(*this), __pos, __n); }
|
|
#endif // C++23
|
|
|
|
#ifdef __glibcxx_string_subview // >= C++26
|
|
/**
|
|
* @brief Get a subview.
|
|
* @param __pos Index of first character (default 0).
|
|
* @param __n Number of characters in subview (default remainder).
|
|
* @return The subview.
|
|
* @throw std::out_of_range If __pos > size().
|
|
*
|
|
* Construct and return a subview using the `__n` characters starting at
|
|
* `__pos`. If the string is too short, use the remainder of the
|
|
* characters. If `__pos` is beyond the end of the string, out_of_range
|
|
* is thrown.
|
|
*/
|
|
[[nodiscard]]
|
|
constexpr basic_string_view<_CharT, _Traits>
|
|
subview(size_type __pos = 0, size_type __n = npos) const
|
|
{ return __sv_type(*this).subview(__pos, __n); }
|
|
#endif
|
|
|
|
/**
|
|
* @brief Compare to a string.
|
|
* @param __str String to compare against.
|
|
* @return Integer < 0, 0, or > 0.
|
|
*
|
|
* Returns an integer < 0 if this string is ordered before @a
|
|
* __str, 0 if their values are equivalent, or > 0 if this
|
|
* string is ordered after @a __str. Determines the effective
|
|
* length rlen of the strings to compare as the smallest of
|
|
* size() and str.size(). The function then compares the two
|
|
* strings by calling traits::compare(data(), str.data(),rlen).
|
|
* If the result of the comparison is nonzero returns it,
|
|
* otherwise the shorter one is ordered first.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
int
|
|
compare(const basic_string& __str) const
|
|
{
|
|
const size_type __size = this->size();
|
|
const size_type __osize = __str.size();
|
|
const size_type __len = std::min(__size, __osize);
|
|
|
|
int __r = traits_type::compare(_M_data(), __str.data(), __len);
|
|
if (!__r)
|
|
__r = _S_compare(__size, __osize);
|
|
return __r;
|
|
}
|
|
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
/**
|
|
* @brief Compare to a string_view.
|
|
* @param __svt An object convertible to string_view to compare against.
|
|
* @return Integer < 0, 0, or > 0.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, int>
|
|
compare(const _Tp& __svt) const
|
|
noexcept(is_same<_Tp, __sv_type>::value)
|
|
{
|
|
__sv_type __sv = __svt;
|
|
const size_type __size = this->size();
|
|
const size_type __osize = __sv.size();
|
|
const size_type __len = std::min(__size, __osize);
|
|
|
|
int __r = traits_type::compare(_M_data(), __sv.data(), __len);
|
|
if (!__r)
|
|
__r = _S_compare(__size, __osize);
|
|
return __r;
|
|
}
|
|
|
|
/**
|
|
* @brief Compare to a string_view.
|
|
* @param __pos A position in the string to start comparing from.
|
|
* @param __n The number of characters to compare.
|
|
* @param __svt An object convertible to string_view to compare
|
|
* against.
|
|
* @return Integer < 0, 0, or > 0.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, int>
|
|
compare(size_type __pos, size_type __n, const _Tp& __svt) const
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return __sv_type(*this).substr(__pos, __n).compare(__sv);
|
|
}
|
|
|
|
/**
|
|
* @brief Compare to a string_view.
|
|
* @param __pos1 A position in the string to start comparing from.
|
|
* @param __n1 The number of characters to compare.
|
|
* @param __svt An object convertible to string_view to compare
|
|
* against.
|
|
* @param __pos2 A position in the string_view to start comparing from.
|
|
* @param __n2 The number of characters to compare.
|
|
* @return Integer < 0, 0, or > 0.
|
|
*/
|
|
template<typename _Tp>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
_If_sv<_Tp, int>
|
|
compare(size_type __pos1, size_type __n1, const _Tp& __svt,
|
|
size_type __pos2, size_type __n2 = npos) const
|
|
{
|
|
__sv_type __sv = __svt;
|
|
return __sv_type(*this)
|
|
.substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2));
|
|
}
|
|
#endif // C++17
|
|
|
|
/**
|
|
* @brief Compare substring to a string.
|
|
* @param __pos Index of first character of substring.
|
|
* @param __n Number of characters in substring.
|
|
* @param __str String to compare against.
|
|
* @return Integer < 0, 0, or > 0.
|
|
*
|
|
* Form the substring of this string from the @a __n characters
|
|
* starting at @a __pos. Returns an integer < 0 if the
|
|
* substring is ordered before @a __str, 0 if their values are
|
|
* equivalent, or > 0 if the substring is ordered after @a
|
|
* __str. Determines the effective length rlen of the strings
|
|
* to compare as the smallest of the length of the substring
|
|
* and @a __str.size(). The function then compares the two
|
|
* strings by calling
|
|
* traits::compare(substring.data(),str.data(),rlen). If the
|
|
* result of the comparison is nonzero returns it, otherwise
|
|
* the shorter one is ordered first.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
int
|
|
compare(size_type __pos, size_type __n, const basic_string& __str) const
|
|
{
|
|
_M_check(__pos, "basic_string::compare");
|
|
__n = _M_limit(__pos, __n);
|
|
const size_type __osize = __str.size();
|
|
const size_type __len = std::min(__n, __osize);
|
|
int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
|
|
if (!__r)
|
|
__r = _S_compare(__n, __osize);
|
|
return __r;
|
|
}
|
|
|
|
/**
|
|
* @brief Compare substring to a substring.
|
|
* @param __pos1 Index of first character of substring.
|
|
* @param __n1 Number of characters in substring.
|
|
* @param __str String to compare against.
|
|
* @param __pos2 Index of first character of substring of str.
|
|
* @param __n2 Number of characters in substring of str.
|
|
* @return Integer < 0, 0, or > 0.
|
|
*
|
|
* Form the substring of this string from the @a __n1
|
|
* characters starting at @a __pos1. Form the substring of @a
|
|
* __str from the @a __n2 characters starting at @a __pos2.
|
|
* Returns an integer < 0 if this substring is ordered before
|
|
* the substring of @a __str, 0 if their values are equivalent,
|
|
* or > 0 if this substring is ordered after the substring of
|
|
* @a __str. Determines the effective length rlen of the
|
|
* strings to compare as the smallest of the lengths of the
|
|
* substrings. The function then compares the two strings by
|
|
* calling
|
|
* traits::compare(substring.data(),str.substr(pos2,n2).data(),rlen).
|
|
* If the result of the comparison is nonzero returns it,
|
|
* otherwise the shorter one is ordered first.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
int
|
|
compare(size_type __pos1, size_type __n1, const basic_string& __str,
|
|
size_type __pos2, size_type __n2 = npos) const
|
|
{
|
|
_M_check(__pos1, "basic_string::compare");
|
|
__str._M_check(__pos2, "basic_string::compare");
|
|
__n1 = _M_limit(__pos1, __n1);
|
|
__n2 = __str._M_limit(__pos2, __n2);
|
|
const size_type __len = std::min(__n1, __n2);
|
|
int __r = traits_type::compare(_M_data() + __pos1,
|
|
__str.data() + __pos2, __len);
|
|
if (!__r)
|
|
__r = _S_compare(__n1, __n2);
|
|
return __r;
|
|
}
|
|
|
|
/**
|
|
* @brief Compare to a C string.
|
|
* @param __s C string to compare against.
|
|
* @return Integer < 0, 0, or > 0.
|
|
*
|
|
* Returns an integer < 0 if this string is ordered before @a __s, 0 if
|
|
* their values are equivalent, or > 0 if this string is ordered after
|
|
* @a __s. Determines the effective length rlen of the strings to
|
|
* compare as the smallest of size() and the length of a string
|
|
* constructed from @a __s. The function then compares the two strings
|
|
* by calling traits::compare(data(),s,rlen). If the result of the
|
|
* comparison is nonzero returns it, otherwise the shorter one is
|
|
* ordered first.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
int
|
|
compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT
|
|
{
|
|
__glibcxx_requires_string(__s);
|
|
const size_type __size = this->size();
|
|
const size_type __osize = traits_type::length(__s);
|
|
const size_type __len = std::min(__size, __osize);
|
|
int __r = traits_type::compare(_M_data(), __s, __len);
|
|
if (!__r)
|
|
__r = _S_compare(__size, __osize);
|
|
return __r;
|
|
}
|
|
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 5 String::compare specification questionable
|
|
/**
|
|
* @brief Compare substring to a C string.
|
|
* @param __pos Index of first character of substring.
|
|
* @param __n1 Number of characters in substring.
|
|
* @param __s C string to compare against.
|
|
* @return Integer < 0, 0, or > 0.
|
|
*
|
|
* Form the substring of this string from the @a __n1
|
|
* characters starting at @a pos. Returns an integer < 0 if
|
|
* the substring is ordered before @a __s, 0 if their values
|
|
* are equivalent, or > 0 if the substring is ordered after @a
|
|
* __s. Determines the effective length rlen of the strings to
|
|
* compare as the smallest of the length of the substring and
|
|
* the length of a string constructed from @a __s. The
|
|
* function then compares the two string by calling
|
|
* traits::compare(substring.data(),__s,rlen). If the result of
|
|
* the comparison is nonzero returns it, otherwise the shorter
|
|
* one is ordered first.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
int
|
|
compare(size_type __pos, size_type __n1, const _CharT* __s) const
|
|
{
|
|
__glibcxx_requires_string(__s);
|
|
_M_check(__pos, "basic_string::compare");
|
|
__n1 = _M_limit(__pos, __n1);
|
|
const size_type __osize = traits_type::length(__s);
|
|
const size_type __len = std::min(__n1, __osize);
|
|
int __r = traits_type::compare(_M_data() + __pos, __s, __len);
|
|
if (!__r)
|
|
__r = _S_compare(__n1, __osize);
|
|
return __r;
|
|
}
|
|
|
|
/**
|
|
* @brief Compare substring against a character %array.
|
|
* @param __pos Index of first character of substring.
|
|
* @param __n1 Number of characters in substring.
|
|
* @param __s character %array to compare against.
|
|
* @param __n2 Number of characters of s.
|
|
* @return Integer < 0, 0, or > 0.
|
|
*
|
|
* Form the substring of this string from the @a __n1
|
|
* characters starting at @a __pos. Form a string from the
|
|
* first @a __n2 characters of @a __s. Returns an integer < 0
|
|
* if this substring is ordered before the string from @a __s,
|
|
* 0 if their values are equivalent, or > 0 if this substring
|
|
* is ordered after the string from @a __s. Determines the
|
|
* effective length rlen of the strings to compare as the
|
|
* smallest of the length of the substring and @a __n2. The
|
|
* function then compares the two strings by calling
|
|
* traits::compare(substring.data(),s,rlen). If the result of
|
|
* the comparison is nonzero returns it, otherwise the shorter
|
|
* one is ordered first.
|
|
*
|
|
* NB: s must have at least n2 characters, '\\0' has
|
|
* no special meaning.
|
|
*/
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
int
|
|
compare(size_type __pos, size_type __n1, const _CharT* __s,
|
|
size_type __n2) const
|
|
{
|
|
__glibcxx_requires_string_len(__s, __n2);
|
|
_M_check(__pos, "basic_string::compare");
|
|
__n1 = _M_limit(__pos, __n1);
|
|
const size_type __len = std::min(__n1, __n2);
|
|
int __r = traits_type::compare(_M_data() + __pos, __s, __len);
|
|
if (!__r)
|
|
__r = _S_compare(__n1, __n2);
|
|
return __r;
|
|
}
|
|
|
|
#if __cplusplus >= 202002L
|
|
[[nodiscard]]
|
|
constexpr bool
|
|
starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept
|
|
{ return __sv_type(this->data(), this->size()).starts_with(__x); }
|
|
|
|
[[nodiscard]]
|
|
constexpr bool
|
|
starts_with(_CharT __x) const noexcept
|
|
{ return __sv_type(this->data(), this->size()).starts_with(__x); }
|
|
|
|
[[nodiscard, __gnu__::__nonnull__]]
|
|
constexpr bool
|
|
starts_with(const _CharT* __x) const noexcept
|
|
{ return __sv_type(this->data(), this->size()).starts_with(__x); }
|
|
|
|
[[nodiscard]]
|
|
constexpr bool
|
|
ends_with(basic_string_view<_CharT, _Traits> __x) const noexcept
|
|
{ return __sv_type(this->data(), this->size()).ends_with(__x); }
|
|
|
|
[[nodiscard]]
|
|
constexpr bool
|
|
ends_with(_CharT __x) const noexcept
|
|
{ return __sv_type(this->data(), this->size()).ends_with(__x); }
|
|
|
|
[[nodiscard, __gnu__::__nonnull__]]
|
|
constexpr bool
|
|
ends_with(const _CharT* __x) const noexcept
|
|
{ return __sv_type(this->data(), this->size()).ends_with(__x); }
|
|
#endif // C++20
|
|
|
|
#if __cplusplus > 202002L
|
|
[[nodiscard]]
|
|
constexpr bool
|
|
contains(basic_string_view<_CharT, _Traits> __x) const noexcept
|
|
{ return __sv_type(this->data(), this->size()).contains(__x); }
|
|
|
|
[[nodiscard]]
|
|
constexpr bool
|
|
contains(_CharT __x) const noexcept
|
|
{ return __sv_type(this->data(), this->size()).contains(__x); }
|
|
|
|
[[nodiscard, __gnu__::__nonnull__]]
|
|
constexpr bool
|
|
contains(const _CharT* __x) const noexcept
|
|
{ return __sv_type(this->data(), this->size()).contains(__x); }
|
|
#endif // C++23
|
|
|
|
// Allow basic_stringbuf::__xfer_bufptrs to call _M_length:
|
|
template<typename, typename, typename> friend class basic_stringbuf;
|
|
};
|
|
_GLIBCXX_END_NAMESPACE_CXX11
|
|
_GLIBCXX_END_NAMESPACE_VERSION
|
|
} // namespace std
|
|
#endif // _GLIBCXX_USE_CXX11_ABI
|
|
|
|
namespace std _GLIBCXX_VISIBILITY(default)
|
|
{
|
|
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|
|
|
#if __cpp_deduction_guides >= 201606
|
|
_GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|
template<typename _InputIterator, typename _CharT
|
|
= typename iterator_traits<_InputIterator>::value_type,
|
|
typename _Allocator = allocator<_CharT>,
|
|
typename = _RequireInputIter<_InputIterator>,
|
|
typename = _RequireAllocator<_Allocator>>
|
|
basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator())
|
|
-> basic_string<_CharT, char_traits<_CharT>, _Allocator>;
|
|
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 3075. basic_string needs deduction guides from basic_string_view
|
|
template<typename _CharT, typename _Traits,
|
|
typename _Allocator = allocator<_CharT>,
|
|
typename = _RequireAllocator<_Allocator>>
|
|
basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator())
|
|
-> basic_string<_CharT, _Traits, _Allocator>;
|
|
|
|
template<typename _CharT, typename _Traits,
|
|
typename _Allocator = allocator<_CharT>,
|
|
typename = _RequireAllocator<_Allocator>>
|
|
basic_string(basic_string_view<_CharT, _Traits>,
|
|
typename basic_string<_CharT, _Traits, _Allocator>::size_type,
|
|
typename basic_string<_CharT, _Traits, _Allocator>::size_type,
|
|
const _Allocator& = _Allocator())
|
|
-> basic_string<_CharT, _Traits, _Allocator>;
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
template<ranges::input_range _Rg,
|
|
typename _Allocator = allocator<ranges::range_value_t<_Rg>>>
|
|
basic_string(from_range_t, _Rg&&, _Allocator = _Allocator())
|
|
-> basic_string<ranges::range_value_t<_Rg>,
|
|
char_traits<ranges::range_value_t<_Rg>>,
|
|
_Allocator>;
|
|
#endif
|
|
_GLIBCXX_END_NAMESPACE_CXX11
|
|
#endif
|
|
|
|
template<typename _Str>
|
|
_GLIBCXX20_CONSTEXPR
|
|
inline _Str
|
|
__str_concat(typename _Str::value_type const* __lhs,
|
|
typename _Str::size_type __lhs_len,
|
|
typename _Str::value_type const* __rhs,
|
|
typename _Str::size_type __rhs_len,
|
|
typename _Str::allocator_type const& __a)
|
|
{
|
|
typedef typename _Str::allocator_type allocator_type;
|
|
typedef __gnu_cxx::__alloc_traits<allocator_type> _Alloc_traits;
|
|
_Str __str(_Alloc_traits::_S_select_on_copy(__a));
|
|
__str.reserve(__lhs_len + __rhs_len);
|
|
__str.append(__lhs, __lhs_len);
|
|
__str.append(__rhs, __rhs_len);
|
|
return __str;
|
|
}
|
|
|
|
// operator+
|
|
/**
|
|
* @brief Concatenate two strings.
|
|
* @param __lhs First string.
|
|
* @param __rhs Last string.
|
|
* @return New string with value of @a __lhs followed by @a __rhs.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
inline basic_string<_CharT, _Traits, _Alloc>
|
|
operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
{
|
|
typedef basic_string<_CharT, _Traits, _Alloc> _Str;
|
|
return std::__str_concat<_Str>(__lhs.c_str(), __lhs.size(),
|
|
__rhs.c_str(), __rhs.size(),
|
|
__lhs.get_allocator());
|
|
}
|
|
|
|
/**
|
|
* @brief Concatenate C string and string.
|
|
* @param __lhs First string.
|
|
* @param __rhs Last string.
|
|
* @return New string with value of @a __lhs followed by @a __rhs.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
inline basic_string<_CharT,_Traits,_Alloc>
|
|
operator+(const _CharT* __lhs,
|
|
const basic_string<_CharT,_Traits,_Alloc>& __rhs)
|
|
{
|
|
__glibcxx_requires_string(__lhs);
|
|
typedef basic_string<_CharT, _Traits, _Alloc> _Str;
|
|
return std::__str_concat<_Str>(__lhs, _Traits::length(__lhs),
|
|
__rhs.c_str(), __rhs.size(),
|
|
__rhs.get_allocator());
|
|
}
|
|
|
|
/**
|
|
* @brief Concatenate character and string.
|
|
* @param __lhs First string.
|
|
* @param __rhs Last string.
|
|
* @return New string with @a __lhs followed by @a __rhs.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
inline basic_string<_CharT,_Traits,_Alloc>
|
|
operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs)
|
|
{
|
|
typedef basic_string<_CharT, _Traits, _Alloc> _Str;
|
|
return std::__str_concat<_Str>(__builtin_addressof(__lhs), 1,
|
|
__rhs.c_str(), __rhs.size(),
|
|
__rhs.get_allocator());
|
|
}
|
|
|
|
/**
|
|
* @brief Concatenate string and C string.
|
|
* @param __lhs First string.
|
|
* @param __rhs Last string.
|
|
* @return New string with @a __lhs followed by @a __rhs.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
inline basic_string<_CharT, _Traits, _Alloc>
|
|
operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const _CharT* __rhs)
|
|
{
|
|
__glibcxx_requires_string(__rhs);
|
|
typedef basic_string<_CharT, _Traits, _Alloc> _Str;
|
|
return std::__str_concat<_Str>(__lhs.c_str(), __lhs.size(),
|
|
__rhs, _Traits::length(__rhs),
|
|
__lhs.get_allocator());
|
|
}
|
|
/**
|
|
* @brief Concatenate string and character.
|
|
* @param __lhs First string.
|
|
* @param __rhs Last string.
|
|
* @return New string with @a __lhs followed by @a __rhs.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
inline basic_string<_CharT, _Traits, _Alloc>
|
|
operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs)
|
|
{
|
|
typedef basic_string<_CharT, _Traits, _Alloc> _Str;
|
|
return std::__str_concat<_Str>(__lhs.c_str(), __lhs.size(),
|
|
__builtin_addressof(__rhs), 1,
|
|
__lhs.get_allocator());
|
|
}
|
|
|
|
#if __cplusplus >= 201103L
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
inline basic_string<_CharT, _Traits, _Alloc>
|
|
operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
{ return std::move(__lhs.append(__rhs)); }
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
inline basic_string<_CharT, _Traits, _Alloc>
|
|
operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
basic_string<_CharT, _Traits, _Alloc>&& __rhs)
|
|
{ return std::move(__rhs.insert(0, __lhs)); }
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
inline basic_string<_CharT, _Traits, _Alloc>
|
|
operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
|
|
basic_string<_CharT, _Traits, _Alloc>&& __rhs)
|
|
{
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
|
|
// Return value must use __lhs.get_allocator(), but if __rhs has equal
|
|
// allocator then we can choose which parameter to modify in-place.
|
|
bool __use_rhs = false;
|
|
if constexpr (allocator_traits<_Alloc>::is_always_equal::value)
|
|
__use_rhs = true;
|
|
else if (__lhs.get_allocator() == __rhs.get_allocator())
|
|
__use_rhs = true;
|
|
if (__use_rhs)
|
|
{
|
|
const auto __size = __lhs.size() + __rhs.size();
|
|
if (__size > __lhs.capacity() && __size <= __rhs.capacity())
|
|
return std::move(__rhs.insert(0, __lhs));
|
|
}
|
|
return std::move(__lhs.append(__rhs));
|
|
#pragma GCC diagnostic pop
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
inline basic_string<_CharT, _Traits, _Alloc>
|
|
operator+(const _CharT* __lhs,
|
|
basic_string<_CharT, _Traits, _Alloc>&& __rhs)
|
|
{ return std::move(__rhs.insert(0, __lhs)); }
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
inline basic_string<_CharT, _Traits, _Alloc>
|
|
operator+(_CharT __lhs,
|
|
basic_string<_CharT, _Traits, _Alloc>&& __rhs)
|
|
{ return std::move(__rhs.insert(0, 1, __lhs)); }
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
inline basic_string<_CharT, _Traits, _Alloc>
|
|
operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
|
|
const _CharT* __rhs)
|
|
{ return std::move(__lhs.append(__rhs)); }
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
inline basic_string<_CharT, _Traits, _Alloc>
|
|
operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
|
|
_CharT __rhs)
|
|
{ return std::move(__lhs.append(1, __rhs)); }
|
|
#endif
|
|
|
|
#if __glibcxx_string_view >= 202403L
|
|
// const string & + string_view
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
[[nodiscard]]
|
|
constexpr basic_string<_CharT, _Traits, _Alloc>
|
|
operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
type_identity_t<basic_string_view<_CharT, _Traits>> __rhs)
|
|
{
|
|
using _Str = basic_string<_CharT, _Traits, _Alloc>;
|
|
return std::__str_concat<_Str>(__lhs.data(), __lhs.size(),
|
|
__rhs.data(), __rhs.size(),
|
|
__lhs.get_allocator());
|
|
}
|
|
|
|
// string && + string_view
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
[[nodiscard]]
|
|
constexpr basic_string<_CharT, _Traits, _Alloc>
|
|
operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
|
|
type_identity_t<basic_string_view<_CharT, _Traits>> __rhs)
|
|
{
|
|
return std::move(__lhs.append(__rhs));
|
|
}
|
|
|
|
// string_view + const string &
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
[[nodiscard]]
|
|
constexpr basic_string<_CharT, _Traits, _Alloc>
|
|
operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
{
|
|
using _Str = basic_string<_CharT, _Traits, _Alloc>;
|
|
return std::__str_concat<_Str>(__lhs.data(), __lhs.size(),
|
|
__rhs.data(), __rhs.size(),
|
|
__rhs.get_allocator());
|
|
}
|
|
|
|
// string_view + string &&
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
[[nodiscard]]
|
|
constexpr basic_string<_CharT, _Traits, _Alloc>
|
|
operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
|
|
basic_string<_CharT, _Traits, _Alloc>&& __rhs)
|
|
{
|
|
return std::move(__rhs.insert(0, __lhs));
|
|
}
|
|
#endif
|
|
|
|
// operator ==
|
|
/**
|
|
* @brief Test equivalence of two strings.
|
|
* @param __lhs First string.
|
|
* @param __rhs Second string.
|
|
* @return True if @a __lhs.compare(@a __rhs) == 0. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
inline bool
|
|
operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
_GLIBCXX_NOEXCEPT
|
|
{
|
|
return __lhs.size() == __rhs.size()
|
|
&& !_Traits::compare(__lhs.data(), __rhs.data(), __lhs.size());
|
|
}
|
|
|
|
/**
|
|
* @brief Test equivalence of string and C string.
|
|
* @param __lhs String.
|
|
* @param __rhs C string.
|
|
* @return True if @a __lhs.compare(@a __rhs) == 0. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
|
|
inline bool
|
|
operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const _CharT* __rhs)
|
|
{
|
|
return __lhs.size() == _Traits::length(__rhs)
|
|
&& !_Traits::compare(__lhs.data(), __rhs, __lhs.size());
|
|
}
|
|
|
|
#if __cpp_lib_three_way_comparison
|
|
/**
|
|
* @brief Three-way comparison of a string and a C string.
|
|
* @param __lhs A string.
|
|
* @param __rhs A null-terminated string.
|
|
* @return A value indicating whether `__lhs` is less than, equal to,
|
|
* greater than, or incomparable with `__rhs`.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
[[nodiscard]]
|
|
constexpr auto
|
|
operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs) noexcept
|
|
-> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
|
|
{ return __detail::__char_traits_cmp_cat<_Traits>(__lhs.compare(__rhs)); }
|
|
|
|
/**
|
|
* @brief Three-way comparison of a string and a C string.
|
|
* @param __lhs A string.
|
|
* @param __rhs A null-terminated string.
|
|
* @return A value indicating whether `__lhs` is less than, equal to,
|
|
* greater than, or incomparable with `__rhs`.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
[[nodiscard]]
|
|
constexpr auto
|
|
operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const _CharT* __rhs) noexcept
|
|
-> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
|
|
{ return __detail::__char_traits_cmp_cat<_Traits>(__lhs.compare(__rhs)); }
|
|
#else
|
|
/**
|
|
* @brief Test equivalence of C string and string.
|
|
* @param __lhs C string.
|
|
* @param __rhs String.
|
|
* @return True if @a __rhs.compare(@a __lhs) == 0. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator==(const _CharT* __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
{ return __rhs == __lhs; }
|
|
|
|
// operator !=
|
|
/**
|
|
* @brief Test difference of two strings.
|
|
* @param __lhs First string.
|
|
* @param __rhs Second string.
|
|
* @return True if @a __lhs.compare(@a __rhs) != 0. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
_GLIBCXX_NOEXCEPT
|
|
{ return !(__lhs == __rhs); }
|
|
|
|
/**
|
|
* @brief Test difference of C string and string.
|
|
* @param __lhs C string.
|
|
* @param __rhs String.
|
|
* @return True if @a __rhs.compare(@a __lhs) != 0. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator!=(const _CharT* __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
{ return !(__rhs == __lhs); }
|
|
|
|
/**
|
|
* @brief Test difference of string and C string.
|
|
* @param __lhs String.
|
|
* @param __rhs C string.
|
|
* @return True if @a __lhs.compare(@a __rhs) != 0. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const _CharT* __rhs)
|
|
{ return !(__lhs == __rhs); }
|
|
|
|
// operator <
|
|
/**
|
|
* @brief Test if string precedes string.
|
|
* @param __lhs First string.
|
|
* @param __rhs Second string.
|
|
* @return True if @a __lhs precedes @a __rhs. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
_GLIBCXX_NOEXCEPT
|
|
{ return __lhs.compare(__rhs) < 0; }
|
|
|
|
/**
|
|
* @brief Test if string precedes C string.
|
|
* @param __lhs String.
|
|
* @param __rhs C string.
|
|
* @return True if @a __lhs precedes @a __rhs. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const _CharT* __rhs)
|
|
{ return __lhs.compare(__rhs) < 0; }
|
|
|
|
/**
|
|
* @brief Test if C string precedes string.
|
|
* @param __lhs C string.
|
|
* @param __rhs String.
|
|
* @return True if @a __lhs precedes @a __rhs. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator<(const _CharT* __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
{ return __rhs.compare(__lhs) > 0; }
|
|
|
|
// operator >
|
|
/**
|
|
* @brief Test if string follows string.
|
|
* @param __lhs First string.
|
|
* @param __rhs Second string.
|
|
* @return True if @a __lhs follows @a __rhs. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
_GLIBCXX_NOEXCEPT
|
|
{ return __lhs.compare(__rhs) > 0; }
|
|
|
|
/**
|
|
* @brief Test if string follows C string.
|
|
* @param __lhs String.
|
|
* @param __rhs C string.
|
|
* @return True if @a __lhs follows @a __rhs. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const _CharT* __rhs)
|
|
{ return __lhs.compare(__rhs) > 0; }
|
|
|
|
/**
|
|
* @brief Test if C string follows string.
|
|
* @param __lhs C string.
|
|
* @param __rhs String.
|
|
* @return True if @a __lhs follows @a __rhs. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator>(const _CharT* __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
{ return __rhs.compare(__lhs) < 0; }
|
|
|
|
// operator <=
|
|
/**
|
|
* @brief Test if string doesn't follow string.
|
|
* @param __lhs First string.
|
|
* @param __rhs Second string.
|
|
* @return True if @a __lhs doesn't follow @a __rhs. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
_GLIBCXX_NOEXCEPT
|
|
{ return __lhs.compare(__rhs) <= 0; }
|
|
|
|
/**
|
|
* @brief Test if string doesn't follow C string.
|
|
* @param __lhs String.
|
|
* @param __rhs C string.
|
|
* @return True if @a __lhs doesn't follow @a __rhs. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const _CharT* __rhs)
|
|
{ return __lhs.compare(__rhs) <= 0; }
|
|
|
|
/**
|
|
* @brief Test if C string doesn't follow string.
|
|
* @param __lhs C string.
|
|
* @param __rhs String.
|
|
* @return True if @a __lhs doesn't follow @a __rhs. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator<=(const _CharT* __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
{ return __rhs.compare(__lhs) >= 0; }
|
|
|
|
// operator >=
|
|
/**
|
|
* @brief Test if string doesn't precede string.
|
|
* @param __lhs First string.
|
|
* @param __rhs Second string.
|
|
* @return True if @a __lhs doesn't precede @a __rhs. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
_GLIBCXX_NOEXCEPT
|
|
{ return __lhs.compare(__rhs) >= 0; }
|
|
|
|
/**
|
|
* @brief Test if string doesn't precede C string.
|
|
* @param __lhs String.
|
|
* @param __rhs C string.
|
|
* @return True if @a __lhs doesn't precede @a __rhs. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
const _CharT* __rhs)
|
|
{ return __lhs.compare(__rhs) >= 0; }
|
|
|
|
/**
|
|
* @brief Test if C string doesn't precede string.
|
|
* @param __lhs C string.
|
|
* @param __rhs String.
|
|
* @return True if @a __lhs doesn't precede @a __rhs. False otherwise.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator>=(const _CharT* __lhs,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
{ return __rhs.compare(__lhs) <= 0; }
|
|
#endif // three-way comparison
|
|
|
|
/**
|
|
* @brief Swap contents of two strings.
|
|
* @param __lhs First string.
|
|
* @param __rhs Second string.
|
|
*
|
|
* Exchanges the contents of @a __lhs and @a __rhs in constant time.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
inline void
|
|
swap(basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
|
basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
|
_GLIBCXX_NOEXCEPT_IF(noexcept(__lhs.swap(__rhs)))
|
|
{ __lhs.swap(__rhs); }
|
|
|
|
|
|
/**
|
|
* @brief Read stream into a string.
|
|
* @param __is Input stream.
|
|
* @param __str Buffer to store into.
|
|
* @return Reference to the input stream.
|
|
*
|
|
* Stores characters from @a __is into @a __str until whitespace is
|
|
* found, the end of the stream is encountered, or str.max_size()
|
|
* is reached. If is.width() is non-zero, that is the limit on the
|
|
* number of characters stored into @a __str. Any previous
|
|
* contents of @a __str are erased.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
basic_istream<_CharT, _Traits>&
|
|
operator>>(basic_istream<_CharT, _Traits>& __is,
|
|
basic_string<_CharT, _Traits, _Alloc>& __str);
|
|
|
|
template<>
|
|
basic_istream<char>&
|
|
operator>>(basic_istream<char>& __is, basic_string<char>& __str);
|
|
|
|
/**
|
|
* @brief Write string to a stream.
|
|
* @param __os Output stream.
|
|
* @param __str String to write out.
|
|
* @return Reference to the output stream.
|
|
*
|
|
* Output characters of @a __str into os following the same rules as for
|
|
* writing a C string.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
inline basic_ostream<_CharT, _Traits>&
|
|
operator<<(basic_ostream<_CharT, _Traits>& __os,
|
|
const basic_string<_CharT, _Traits, _Alloc>& __str)
|
|
{
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 586. string inserter not a formatted function
|
|
return __ostream_insert(__os, __str.data(), __str.size());
|
|
}
|
|
|
|
/**
|
|
* @brief Read a line from stream into a string.
|
|
* @param __is Input stream.
|
|
* @param __str Buffer to store into.
|
|
* @param __delim Character marking end of line.
|
|
* @return Reference to the input stream.
|
|
*
|
|
* Stores characters from @a __is into @a __str until @a __delim is
|
|
* found, the end of the stream is encountered, or str.max_size()
|
|
* is reached. Any previous contents of @a __str are erased. If
|
|
* @a __delim is encountered, it is extracted but not stored into
|
|
* @a __str.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
basic_istream<_CharT, _Traits>&
|
|
getline(basic_istream<_CharT, _Traits>& __is,
|
|
basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim);
|
|
|
|
/**
|
|
* @brief Read a line from stream into a string.
|
|
* @param __is Input stream.
|
|
* @param __str Buffer to store into.
|
|
* @return Reference to the input stream.
|
|
*
|
|
* Stores characters from is into @a __str until '\n' is
|
|
* found, the end of the stream is encountered, or str.max_size()
|
|
* is reached. Any previous contents of @a __str are erased. If
|
|
* end of line is encountered, it is extracted but not stored into
|
|
* @a __str.
|
|
*/
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
inline basic_istream<_CharT, _Traits>&
|
|
getline(basic_istream<_CharT, _Traits>& __is,
|
|
basic_string<_CharT, _Traits, _Alloc>& __str)
|
|
{ return std::getline(__is, __str, __is.widen('\n')); }
|
|
|
|
#if __cplusplus >= 201103L
|
|
/// Read a line from an rvalue stream into a string.
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
inline basic_istream<_CharT, _Traits>&
|
|
getline(basic_istream<_CharT, _Traits>&& __is,
|
|
basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim)
|
|
{ return std::getline(__is, __str, __delim); }
|
|
|
|
/// Read a line from an rvalue stream into a string.
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
inline basic_istream<_CharT, _Traits>&
|
|
getline(basic_istream<_CharT, _Traits>&& __is,
|
|
basic_string<_CharT, _Traits, _Alloc>& __str)
|
|
{ return std::getline(__is, __str); }
|
|
#endif
|
|
|
|
template<>
|
|
basic_istream<char>&
|
|
getline(basic_istream<char>& __in, basic_string<char>& __str,
|
|
char __delim);
|
|
|
|
#ifdef _GLIBCXX_USE_WCHAR_T
|
|
template<>
|
|
basic_istream<wchar_t>&
|
|
getline(basic_istream<wchar_t>& __in, basic_string<wchar_t>& __str,
|
|
wchar_t __delim);
|
|
#endif
|
|
|
|
_GLIBCXX_END_NAMESPACE_VERSION
|
|
} // namespace
|
|
|
|
#if __cplusplus >= 201103L
|
|
|
|
#include <ext/string_conversions.h>
|
|
#include <bits/charconv.h>
|
|
|
|
namespace std _GLIBCXX_VISIBILITY(default)
|
|
{
|
|
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|
_GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|
|
|
// 21.4 Numeric Conversions [string.conversions].
|
|
inline int
|
|
stoi(const string& __str, size_t* __idx = 0, int __base = 10)
|
|
{ return __gnu_cxx::__stoa<long, int>(&std::strtol, "stoi", __str.c_str(),
|
|
__idx, __base); }
|
|
|
|
inline long
|
|
stol(const string& __str, size_t* __idx = 0, int __base = 10)
|
|
{ return __gnu_cxx::__stoa(&std::strtol, "stol", __str.c_str(),
|
|
__idx, __base); }
|
|
|
|
inline unsigned long
|
|
stoul(const string& __str, size_t* __idx = 0, int __base = 10)
|
|
{ return __gnu_cxx::__stoa(&std::strtoul, "stoul", __str.c_str(),
|
|
__idx, __base); }
|
|
|
|
#if _GLIBCXX_USE_C99_STDLIB
|
|
inline long long
|
|
stoll(const string& __str, size_t* __idx = 0, int __base = 10)
|
|
{ return __gnu_cxx::__stoa(&std::strtoll, "stoll", __str.c_str(),
|
|
__idx, __base); }
|
|
|
|
inline unsigned long long
|
|
stoull(const string& __str, size_t* __idx = 0, int __base = 10)
|
|
{ return __gnu_cxx::__stoa(&std::strtoull, "stoull", __str.c_str(),
|
|
__idx, __base); }
|
|
#elif __LONG_WIDTH__ == __LONG_LONG_WIDTH__
|
|
inline long long
|
|
stoll(const string& __str, size_t* __idx = 0, int __base = 10)
|
|
{ return std::stol(__str, __idx, __base); }
|
|
|
|
inline unsigned long long
|
|
stoull(const string& __str, size_t* __idx = 0, int __base = 10)
|
|
{ return std::stoul(__str, __idx, __base); }
|
|
#endif
|
|
|
|
inline double
|
|
stod(const string& __str, size_t* __idx = 0)
|
|
{ return __gnu_cxx::__stoa(&std::strtod, "stod", __str.c_str(), __idx); }
|
|
|
|
#if _GLIBCXX_HAVE_STRTOF
|
|
// NB: strtof vs strtod.
|
|
inline float
|
|
stof(const string& __str, size_t* __idx = 0)
|
|
{ return __gnu_cxx::__stoa(&std::strtof, "stof", __str.c_str(), __idx); }
|
|
#else
|
|
inline float
|
|
stof(const string& __str, size_t* __idx = 0)
|
|
{
|
|
double __d = std::stod(__str, __idx);
|
|
if (__builtin_isfinite(__d) && __d != 0.0)
|
|
{
|
|
double __abs_d = __builtin_fabs(__d);
|
|
if (__abs_d < __FLT_MIN__ || __abs_d > __FLT_MAX__)
|
|
{
|
|
errno = ERANGE;
|
|
std::__throw_out_of_range("stof");
|
|
}
|
|
}
|
|
return __d;
|
|
}
|
|
#endif
|
|
|
|
#if _GLIBCXX_HAVE_STRTOLD && ! _GLIBCXX_HAVE_BROKEN_STRTOLD
|
|
inline long double
|
|
stold(const string& __str, size_t* __idx = 0)
|
|
{ return __gnu_cxx::__stoa(&std::strtold, "stold", __str.c_str(), __idx); }
|
|
#elif __DBL_MANT_DIG__ == __LDBL_MANT_DIG__
|
|
inline long double
|
|
stold(const string& __str, size_t* __idx = 0)
|
|
{ return std::stod(__str, __idx); }
|
|
#endif
|
|
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// DR 1261. Insufficent overloads for to_string / to_wstring
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline string
|
|
to_string(int __val)
|
|
#if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_INT__) <= 32
|
|
noexcept // any 32-bit value fits in the SSO buffer
|
|
#endif
|
|
{
|
|
const bool __neg = __val < 0;
|
|
const unsigned __uval = __neg ? (unsigned)~__val + 1u : __val;
|
|
const auto __len = __detail::__to_chars_len(__uval);
|
|
string __str;
|
|
__str.__resize_and_overwrite(__neg + __len, [=](char* __p, size_t __n) {
|
|
__p[0] = '-';
|
|
__detail::__to_chars_10_impl(__p + (int)__neg, __len, __uval);
|
|
return __n;
|
|
});
|
|
return __str;
|
|
}
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline string
|
|
to_string(unsigned __val)
|
|
#if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_INT__) <= 32
|
|
noexcept // any 32-bit value fits in the SSO buffer
|
|
#endif
|
|
{
|
|
const auto __len = __detail::__to_chars_len(__val);
|
|
string __str;
|
|
__str.__resize_and_overwrite(__len, [__val](char* __p, size_t __n) {
|
|
__detail::__to_chars_10_impl(__p, __n, __val);
|
|
return __n;
|
|
});
|
|
return __str;
|
|
}
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline string
|
|
to_string(long __val)
|
|
#if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_LONG__) <= 32
|
|
noexcept // any 32-bit value fits in the SSO buffer
|
|
#endif
|
|
{
|
|
const bool __neg = __val < 0;
|
|
const unsigned long __uval = __neg ? (unsigned long)~__val + 1ul : __val;
|
|
const auto __len = __detail::__to_chars_len(__uval);
|
|
string __str;
|
|
__str.__resize_and_overwrite(__neg + __len, [=](char* __p, size_t __n) {
|
|
__p[0] = '-';
|
|
__detail::__to_chars_10_impl(__p + (int)__neg, __len, __uval);
|
|
return __n;
|
|
});
|
|
return __str;
|
|
}
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline string
|
|
to_string(unsigned long __val)
|
|
#if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_LONG__) <= 32
|
|
noexcept // any 32-bit value fits in the SSO buffer
|
|
#endif
|
|
{
|
|
const auto __len = __detail::__to_chars_len(__val);
|
|
string __str;
|
|
__str.__resize_and_overwrite(__len, [__val](char* __p, size_t __n) {
|
|
__detail::__to_chars_10_impl(__p, __n, __val);
|
|
return __n;
|
|
});
|
|
return __str;
|
|
}
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline string
|
|
to_string(long long __val)
|
|
{
|
|
const bool __neg = __val < 0;
|
|
const unsigned long long __uval
|
|
= __neg ? (unsigned long long)~__val + 1ull : __val;
|
|
const auto __len = __detail::__to_chars_len(__uval);
|
|
string __str;
|
|
__str.__resize_and_overwrite(__neg + __len, [=](char* __p, size_t __n) {
|
|
__p[0] = '-';
|
|
__detail::__to_chars_10_impl(__p + (int)__neg, __len, __uval);
|
|
return __n;
|
|
});
|
|
return __str;
|
|
}
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline string
|
|
to_string(unsigned long long __val)
|
|
{
|
|
const auto __len = __detail::__to_chars_len(__val);
|
|
string __str;
|
|
__str.__resize_and_overwrite(__len, [__val](char* __p, size_t __n) {
|
|
__detail::__to_chars_10_impl(__p, __n, __val);
|
|
return __n;
|
|
});
|
|
return __str;
|
|
}
|
|
|
|
#if __glibcxx_to_string >= 202306L // C++ >= 26
|
|
|
|
[[nodiscard]]
|
|
inline string
|
|
to_string(float __val)
|
|
{
|
|
string __str;
|
|
size_t __len = 15;
|
|
do {
|
|
__str.resize_and_overwrite(__len,
|
|
[__val, &__len] (char* __p, size_t __n) {
|
|
auto [__end, __err] = std::to_chars(__p, __p + __n, __val);
|
|
if (__err == errc{}) [[likely]]
|
|
return __end - __p;
|
|
__len *= 2;
|
|
return __p - __p;;
|
|
});
|
|
} while (__str.empty());
|
|
return __str;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
inline string
|
|
to_string(double __val)
|
|
{
|
|
string __str;
|
|
size_t __len = 15;
|
|
do {
|
|
__str.resize_and_overwrite(__len,
|
|
[__val, &__len] (char* __p, size_t __n) {
|
|
auto [__end, __err] = std::to_chars(__p, __p + __n, __val);
|
|
if (__err == errc{}) [[likely]]
|
|
return __end - __p;
|
|
__len *= 2;
|
|
return __p - __p;;
|
|
});
|
|
} while (__str.empty());
|
|
return __str;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
inline string
|
|
to_string(long double __val)
|
|
{
|
|
string __str;
|
|
size_t __len = 15;
|
|
do {
|
|
__str.resize_and_overwrite(__len,
|
|
[__val, &__len] (char* __p, size_t __n) {
|
|
auto [__end, __err] = std::to_chars(__p, __p + __n, __val);
|
|
if (__err == errc{}) [[likely]]
|
|
return __end - __p;
|
|
__len *= 2;
|
|
return __p - __p;;
|
|
});
|
|
} while (__str.empty());
|
|
return __str;
|
|
}
|
|
#elif _GLIBCXX_USE_C99_STDIO
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
|
|
// NB: (v)snprintf vs sprintf.
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline string
|
|
to_string(float __val)
|
|
{
|
|
const int __n =
|
|
__gnu_cxx::__numeric_traits<float>::__max_exponent10 + 20;
|
|
return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
|
|
"%f", __val);
|
|
}
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline string
|
|
to_string(double __val)
|
|
{
|
|
const int __n =
|
|
__gnu_cxx::__numeric_traits<double>::__max_exponent10 + 20;
|
|
return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
|
|
"%f", __val);
|
|
}
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline string
|
|
to_string(long double __val)
|
|
{
|
|
const int __n =
|
|
__gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 20;
|
|
return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
|
|
"%Lf", __val);
|
|
}
|
|
#pragma GCC diagnostic pop
|
|
#endif // _GLIBCXX_USE_C99_STDIO
|
|
|
|
#if defined(_GLIBCXX_USE_WCHAR_T) && _GLIBCXX_USE_C99_WCHAR
|
|
inline int
|
|
stoi(const wstring& __str, size_t* __idx = 0, int __base = 10)
|
|
{ return __gnu_cxx::__stoa<long, int>(&std::wcstol, "stoi", __str.c_str(),
|
|
__idx, __base); }
|
|
|
|
inline long
|
|
stol(const wstring& __str, size_t* __idx = 0, int __base = 10)
|
|
{ return __gnu_cxx::__stoa(&std::wcstol, "stol", __str.c_str(),
|
|
__idx, __base); }
|
|
|
|
inline unsigned long
|
|
stoul(const wstring& __str, size_t* __idx = 0, int __base = 10)
|
|
{ return __gnu_cxx::__stoa(&std::wcstoul, "stoul", __str.c_str(),
|
|
__idx, __base); }
|
|
|
|
inline long long
|
|
stoll(const wstring& __str, size_t* __idx = 0, int __base = 10)
|
|
{ return __gnu_cxx::__stoa(&std::wcstoll, "stoll", __str.c_str(),
|
|
__idx, __base); }
|
|
|
|
inline unsigned long long
|
|
stoull(const wstring& __str, size_t* __idx = 0, int __base = 10)
|
|
{ return __gnu_cxx::__stoa(&std::wcstoull, "stoull", __str.c_str(),
|
|
__idx, __base); }
|
|
|
|
// NB: wcstof vs wcstod.
|
|
inline float
|
|
stof(const wstring& __str, size_t* __idx = 0)
|
|
{ return __gnu_cxx::__stoa(&std::wcstof, "stof", __str.c_str(), __idx); }
|
|
|
|
inline double
|
|
stod(const wstring& __str, size_t* __idx = 0)
|
|
{ return __gnu_cxx::__stoa(&std::wcstod, "stod", __str.c_str(), __idx); }
|
|
|
|
inline long double
|
|
stold(const wstring& __str, size_t* __idx = 0)
|
|
{ return __gnu_cxx::__stoa(&std::wcstold, "stold", __str.c_str(), __idx); }
|
|
#endif
|
|
|
|
#ifdef _GLIBCXX_USE_WCHAR_T
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wc++17-extensions"
|
|
_GLIBCXX20_CONSTEXPR
|
|
inline void
|
|
__to_wstring_numeric(const char* __s, int __len, wchar_t* __wout)
|
|
{
|
|
// This condition is true if exec-charset and wide-exec-charset share the
|
|
// same values for the ASCII subset or the EBCDIC invariant character set.
|
|
if constexpr (wchar_t('0') == L'0' && wchar_t('-') == L'-'
|
|
&& wchar_t('.') == L'.' && wchar_t('e') == L'e')
|
|
{
|
|
for (int __i = 0; __i < __len; ++__i)
|
|
__wout[__i] = (wchar_t) __s[__i];
|
|
}
|
|
else
|
|
{
|
|
wchar_t __wc[256];
|
|
for (int __i = '0'; __i <= '9'; ++__i)
|
|
__wc[__i] = L'0' + __i;
|
|
__wc['.'] = L'.';
|
|
__wc['+'] = L'+';
|
|
__wc['-'] = L'-';
|
|
__wc['a'] = L'a';
|
|
__wc['b'] = L'b';
|
|
__wc['c'] = L'c';
|
|
__wc['d'] = L'd';
|
|
__wc['e'] = L'e';
|
|
__wc['f'] = L'f';
|
|
__wc['i'] = L'i'; // for "inf"
|
|
__wc['n'] = L'n'; // for "nan" and "inf"
|
|
__wc['p'] = L'p'; // for hexfloats "0x1p1"
|
|
__wc['x'] = L'x';
|
|
__wc['A'] = L'A';
|
|
__wc['B'] = L'B';
|
|
__wc['C'] = L'C';
|
|
__wc['D'] = L'D';
|
|
__wc['E'] = L'E';
|
|
__wc['F'] = L'F';
|
|
__wc['I'] = L'I';
|
|
__wc['N'] = L'N';
|
|
__wc['P'] = L'P';
|
|
__wc['X'] = L'X';
|
|
|
|
for (int __i = 0; __i < __len; ++__i)
|
|
__wout[__i] = __wc[(int)__s[__i]];
|
|
}
|
|
}
|
|
|
|
#if __glibcxx_constexpr_string >= 201907L
|
|
constexpr
|
|
#endif
|
|
inline wstring
|
|
#ifdef __glibcxx_string_view // >= C++17
|
|
__to_wstring_numeric(string_view __s)
|
|
#else
|
|
__to_wstring_numeric(const string& __s)
|
|
#endif
|
|
{
|
|
if constexpr (wchar_t('0') == L'0' && wchar_t('-') == L'-'
|
|
&& wchar_t('.') == L'.' && wchar_t('e') == L'e')
|
|
return wstring(__s.data(), __s.data() + __s.size());
|
|
else
|
|
{
|
|
wstring __ws;
|
|
auto __f = __s.data();
|
|
__ws.__resize_and_overwrite(__s.size(),
|
|
[__f] (wchar_t* __to, int __n) {
|
|
std::__to_wstring_numeric(__f, __n, __to);
|
|
return __n;
|
|
});
|
|
return __ws;
|
|
}
|
|
}
|
|
#pragma GCC diagnostic pop
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline wstring
|
|
to_wstring(int __val)
|
|
{ return std::__to_wstring_numeric(std::to_string(__val)); }
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline wstring
|
|
to_wstring(unsigned __val)
|
|
{ return std::__to_wstring_numeric(std::to_string(__val)); }
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline wstring
|
|
to_wstring(long __val)
|
|
{ return std::__to_wstring_numeric(std::to_string(__val)); }
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline wstring
|
|
to_wstring(unsigned long __val)
|
|
{ return std::__to_wstring_numeric(std::to_string(__val)); }
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline wstring
|
|
to_wstring(long long __val)
|
|
{ return std::__to_wstring_numeric(std::to_string(__val)); }
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline wstring
|
|
to_wstring(unsigned long long __val)
|
|
{ return std::__to_wstring_numeric(std::to_string(__val)); }
|
|
|
|
#if __glibcxx_to_string || _GLIBCXX_USE_C99_STDIO
|
|
_GLIBCXX_NODISCARD
|
|
inline wstring
|
|
to_wstring(float __val)
|
|
{ return std::__to_wstring_numeric(std::to_string(__val)); }
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline wstring
|
|
to_wstring(double __val)
|
|
{ return std::__to_wstring_numeric(std::to_string(__val)); }
|
|
|
|
_GLIBCXX_NODISCARD
|
|
inline wstring
|
|
to_wstring(long double __val)
|
|
{ return std::__to_wstring_numeric(std::to_string(__val)); }
|
|
#endif
|
|
#endif // _GLIBCXX_USE_WCHAR_T
|
|
|
|
_GLIBCXX_END_NAMESPACE_CXX11
|
|
_GLIBCXX_END_NAMESPACE_VERSION
|
|
} // namespace
|
|
|
|
#endif /* C++11 */
|
|
|
|
#if __cplusplus >= 201103L
|
|
|
|
#include <bits/functional_hash.h>
|
|
|
|
namespace std _GLIBCXX_VISIBILITY(default)
|
|
{
|
|
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 3705. Hashability shouldn't depend on basic_string's allocator
|
|
|
|
template<typename _CharT, typename _Alloc,
|
|
typename _StrT = basic_string<_CharT, char_traits<_CharT>, _Alloc>>
|
|
struct __str_hash_base
|
|
: public __hash_base<size_t, _StrT>
|
|
{
|
|
[[__nodiscard__]]
|
|
size_t
|
|
operator()(const _StrT& __s) const noexcept
|
|
{ return _Hash_impl::hash(__s.data(), __s.length() * sizeof(_CharT)); }
|
|
};
|
|
|
|
#ifndef _GLIBCXX_COMPATIBILITY_CXX0X
|
|
/// std::hash specialization for string.
|
|
template<typename _Alloc>
|
|
struct hash<basic_string<char, char_traits<char>, _Alloc>>
|
|
: public __str_hash_base<char, _Alloc>
|
|
{ };
|
|
|
|
/// std::hash specialization for wstring.
|
|
template<typename _Alloc>
|
|
struct hash<basic_string<wchar_t, char_traits<wchar_t>, _Alloc>>
|
|
: public __str_hash_base<wchar_t, _Alloc>
|
|
{ };
|
|
|
|
template<typename _Alloc>
|
|
struct __is_fast_hash<hash<basic_string<wchar_t, char_traits<wchar_t>,
|
|
_Alloc>>>
|
|
: std::false_type
|
|
{ };
|
|
#endif /* _GLIBCXX_COMPATIBILITY_CXX0X */
|
|
|
|
#ifdef _GLIBCXX_USE_CHAR8_T
|
|
/// std::hash specialization for u8string.
|
|
template<typename _Alloc>
|
|
struct hash<basic_string<char8_t, char_traits<char8_t>, _Alloc>>
|
|
: public __str_hash_base<char8_t, _Alloc>
|
|
{ };
|
|
#endif
|
|
|
|
/// std::hash specialization for u16string.
|
|
template<typename _Alloc>
|
|
struct hash<basic_string<char16_t, char_traits<char16_t>, _Alloc>>
|
|
: public __str_hash_base<char16_t, _Alloc>
|
|
{ };
|
|
|
|
/// std::hash specialization for u32string.
|
|
template<typename _Alloc>
|
|
struct hash<basic_string<char32_t, char_traits<char32_t>, _Alloc>>
|
|
: public __str_hash_base<char32_t, _Alloc>
|
|
{ };
|
|
|
|
#if ! _GLIBCXX_INLINE_VERSION
|
|
// PR libstdc++/105907 - __is_fast_hash affects unordered container ABI.
|
|
template<> struct __is_fast_hash<hash<string>> : std::false_type { };
|
|
template<> struct __is_fast_hash<hash<wstring>> : std::false_type { };
|
|
template<> struct __is_fast_hash<hash<u16string>> : std::false_type { };
|
|
template<> struct __is_fast_hash<hash<u32string>> : std::false_type { };
|
|
#ifdef _GLIBCXX_USE_CHAR8_T
|
|
template<> struct __is_fast_hash<hash<u8string>> : std::false_type { };
|
|
#endif
|
|
#else
|
|
// For versioned namespace, assume every std::hash<basic_string<>> is slow.
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
struct __is_fast_hash<hash<basic_string<_CharT, _Traits, _Alloc>>>
|
|
: std::false_type
|
|
{ };
|
|
#endif
|
|
|
|
#ifdef __glibcxx_string_udls // C++ >= 14
|
|
inline namespace literals
|
|
{
|
|
inline namespace string_literals
|
|
{
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wliteral-suffix"
|
|
|
|
#if __glibcxx_constexpr_string >= 201907L
|
|
# define _GLIBCXX_STRING_CONSTEXPR constexpr
|
|
#else
|
|
# define _GLIBCXX_STRING_CONSTEXPR
|
|
#endif
|
|
|
|
_GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_STRING_CONSTEXPR
|
|
inline basic_string<char>
|
|
operator""s(const char* __str, size_t __len)
|
|
{ return basic_string<char>{__str, __len}; }
|
|
|
|
_GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_STRING_CONSTEXPR
|
|
inline basic_string<wchar_t>
|
|
operator""s(const wchar_t* __str, size_t __len)
|
|
{ return basic_string<wchar_t>{__str, __len}; }
|
|
|
|
#ifdef _GLIBCXX_USE_CHAR8_T
|
|
_GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_STRING_CONSTEXPR
|
|
inline basic_string<char8_t>
|
|
operator""s(const char8_t* __str, size_t __len)
|
|
{ return basic_string<char8_t>{__str, __len}; }
|
|
#endif
|
|
|
|
_GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_STRING_CONSTEXPR
|
|
inline basic_string<char16_t>
|
|
operator""s(const char16_t* __str, size_t __len)
|
|
{ return basic_string<char16_t>{__str, __len}; }
|
|
|
|
_GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_STRING_CONSTEXPR
|
|
inline basic_string<char32_t>
|
|
operator""s(const char32_t* __str, size_t __len)
|
|
{ return basic_string<char32_t>{__str, __len}; }
|
|
|
|
#undef _GLIBCXX_STRING_CONSTEXPR
|
|
#pragma GCC diagnostic pop
|
|
} // inline namespace string_literals
|
|
} // inline namespace literals
|
|
#endif // __glibcxx_string_udls
|
|
|
|
#ifdef __glibcxx_variant // >= C++17
|
|
namespace __detail::__variant
|
|
{
|
|
template<typename> struct _Never_valueless_alt; // see <variant>
|
|
|
|
// Provide the strong exception-safety guarantee when emplacing a
|
|
// basic_string into a variant, but only if moving the string cannot throw.
|
|
template<typename _Tp, typename _Traits, typename _Alloc>
|
|
struct _Never_valueless_alt<std::basic_string<_Tp, _Traits, _Alloc>>
|
|
: __and_<
|
|
is_nothrow_move_constructible<std::basic_string<_Tp, _Traits, _Alloc>>,
|
|
is_nothrow_move_assignable<std::basic_string<_Tp, _Traits, _Alloc>>
|
|
>::type
|
|
{ };
|
|
} // namespace __detail::__variant
|
|
#endif // C++17
|
|
|
|
_GLIBCXX_END_NAMESPACE_VERSION
|
|
} // namespace std
|
|
|
|
#endif // C++11
|
|
|
|
#endif /* _BASIC_STRING_H */
|