mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-22 03:47:02 -05:00
The use of #pragma GCC system_header in libstdc++ has led to bugs going undetected for a while due to the silencing of compiler warnings that would have revealed them promptly, and also interferes with warnings about problematic template instantiations induced by user code. But removing it, or even compiling with -Wsystem-header, is also problematic due to warnings about deliberate uses of extensions. So this patch adds #pragma GCC diagnostic as needed to suppress these warnings. The change to acinclude.m4 changes -Wabi to warn only in comparison to ABI 19, to avoid lots of warnings that we now mangle concept requirements, which are in any case still experimental. I checked for any other changes against ABI v15, and found only the <format> lambda mangling, which we can ignore. This also enables -Wsystem-headers while building the library, so we see any warnings not silenced by these #pragmas. libstdc++-v3/ChangeLog: * include/bits/algorithmfwd.h: * include/bits/allocator.h: * include/bits/codecvt.h: * include/bits/concept_check.h: * include/bits/cpp_type_traits.h: * include/bits/hashtable.h: * include/bits/iterator_concepts.h: * include/bits/ostream_insert.h: * include/bits/ranges_base.h: * include/bits/regex_automaton.h: * include/bits/std_abs.h: * include/bits/stl_algo.h: * include/c_compatibility/fenv.h: * include/c_compatibility/inttypes.h: * include/c_compatibility/stdint.h: * include/ext/concurrence.h: * include/ext/type_traits.h: * testsuite/ext/type_traits/add_unsigned_floating_neg.cc: * testsuite/ext/type_traits/add_unsigned_integer_neg.cc: * testsuite/ext/type_traits/remove_unsigned_floating_neg.cc: * testsuite/ext/type_traits/remove_unsigned_integer_neg.cc: * include/bits/basic_ios.tcc: * include/bits/basic_string.tcc: * include/bits/fstream.tcc: * include/bits/istream.tcc: * include/bits/locale_classes.tcc: * include/bits/locale_facets.tcc: * include/bits/ostream.tcc: * include/bits/regex_compiler.tcc: * include/bits/sstream.tcc: * include/bits/streambuf.tcc: * configure: Regenerate. * include/bits/c++config: * include/c/cassert: * include/c/cctype: * include/c/cerrno: * include/c/cfloat: * include/c/climits: * include/c/clocale: * include/c/cmath: * include/c/csetjmp: * include/c/csignal: * include/c/cstdarg: * include/c/cstddef: * include/c/cstdio: * include/c/cstdlib: * include/c/cstring: * include/c/ctime: * include/c/cwchar: * include/c/cwctype: * include/c_global/climits: * include/c_global/cmath: * include/c_global/cstddef: * include/c_global/cstdlib: * include/decimal/decimal: * include/ext/rope: * include/std/any: * include/std/charconv: * include/std/complex: * include/std/coroutine: * include/std/format: * include/std/iomanip: * include/std/limits: * include/std/numbers: * include/tr1/functional: * include/tr1/tuple: * include/tr1/type_traits: * libsupc++/compare: * libsupc++/new: Add #pragma GCC diagnostic to suppress undesired warnings. * acinclude.m4: Change -Wabi version from 2 to 19. gcc/ChangeLog: * ginclude/stdint-wrap.h: Add #pragma GCC diagnostic to suppress undesired warnings. * gsyslimits.h: Likewise.
1039 lines
31 KiB
C++
1039 lines
31 KiB
C++
// Components for manipulating sequences of characters -*- C++ -*-
|
|
|
|
// Copyright (C) 1997-2024 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.tcc
|
|
* 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
|
|
//
|
|
|
|
// Written by Jason Merrill based upon the specification by Takanori Adachi
|
|
// in ANSI X3J16/94-0013R2. Rewritten by Nathan Myers to ISO-14882.
|
|
// Non-reference-counted implementation written by Paolo Carlini and
|
|
// updated by Jonathan Wakely for ISO-14882-2011.
|
|
|
|
#ifndef _BASIC_STRING_TCC
|
|
#define _BASIC_STRING_TCC 1
|
|
|
|
#pragma GCC system_header
|
|
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wc++11-extensions"
|
|
|
|
#include <bits/cxxabi_forced.h>
|
|
|
|
namespace std _GLIBCXX_VISIBILITY(default)
|
|
{
|
|
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|
|
|
#if _GLIBCXX_USE_CXX11_ABI
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
const typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
|
basic_string<_CharT, _Traits, _Alloc>::npos;
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
swap(basic_string& __s) _GLIBCXX_NOEXCEPT
|
|
{
|
|
if (this == std::__addressof(__s))
|
|
return;
|
|
|
|
_Alloc_traits::_S_on_swap(_M_get_allocator(), __s._M_get_allocator());
|
|
|
|
if (_M_is_local())
|
|
if (__s._M_is_local())
|
|
{
|
|
if (length() && __s.length())
|
|
{
|
|
_CharT __tmp_data[_S_local_capacity + 1];
|
|
traits_type::copy(__tmp_data, __s._M_local_buf,
|
|
__s.length() + 1);
|
|
traits_type::copy(__s._M_local_buf, _M_local_buf,
|
|
length() + 1);
|
|
traits_type::copy(_M_local_buf, __tmp_data,
|
|
__s.length() + 1);
|
|
}
|
|
else if (__s.length())
|
|
{
|
|
_M_init_local_buf();
|
|
traits_type::copy(_M_local_buf, __s._M_local_buf,
|
|
__s.length() + 1);
|
|
_M_length(__s.length());
|
|
__s._M_set_length(0);
|
|
return;
|
|
}
|
|
else if (length())
|
|
{
|
|
__s._M_init_local_buf();
|
|
traits_type::copy(__s._M_local_buf, _M_local_buf,
|
|
length() + 1);
|
|
__s._M_length(length());
|
|
_M_set_length(0);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const size_type __tmp_capacity = __s._M_allocated_capacity;
|
|
__s._M_init_local_buf();
|
|
traits_type::copy(__s._M_local_buf, _M_local_buf,
|
|
length() + 1);
|
|
_M_data(__s._M_data());
|
|
__s._M_data(__s._M_local_buf);
|
|
_M_capacity(__tmp_capacity);
|
|
}
|
|
else
|
|
{
|
|
const size_type __tmp_capacity = _M_allocated_capacity;
|
|
if (__s._M_is_local())
|
|
{
|
|
_M_init_local_buf();
|
|
traits_type::copy(_M_local_buf, __s._M_local_buf,
|
|
__s.length() + 1);
|
|
__s._M_data(_M_data());
|
|
_M_data(_M_local_buf);
|
|
}
|
|
else
|
|
{
|
|
pointer __tmp_ptr = _M_data();
|
|
_M_data(__s._M_data());
|
|
__s._M_data(__tmp_ptr);
|
|
_M_capacity(__s._M_allocated_capacity);
|
|
}
|
|
__s._M_capacity(__tmp_capacity);
|
|
}
|
|
|
|
const size_type __tmp_length = length();
|
|
_M_length(__s.length());
|
|
__s._M_length(__tmp_length);
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
typename basic_string<_CharT, _Traits, _Alloc>::pointer
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
_M_create(size_type& __capacity, size_type __old_capacity)
|
|
{
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 83. String::npos vs. string::max_size()
|
|
if (__capacity > max_size())
|
|
std::__throw_length_error(__N("basic_string::_M_create"));
|
|
|
|
// The below implements an exponential growth policy, necessary to
|
|
// meet amortized linear time requirements of the library: see
|
|
// http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
|
|
if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
|
|
{
|
|
__capacity = 2 * __old_capacity;
|
|
// Never allocate a string bigger than max_size.
|
|
if (__capacity > max_size())
|
|
__capacity = max_size();
|
|
}
|
|
|
|
// NB: Need an array of char_type[__capacity], plus a terminating
|
|
// null char_type() element.
|
|
return _S_allocate(_M_get_allocator(), __capacity + 1);
|
|
}
|
|
|
|
// NB: This is the special case for Input Iterators, used in
|
|
// istreambuf_iterators, etc.
|
|
// Input Iterators have a cost structure very different from
|
|
// pointers, calling for a different coding style.
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
template<typename _InIterator>
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
_M_construct(_InIterator __beg, _InIterator __end,
|
|
std::input_iterator_tag)
|
|
{
|
|
size_type __len = 0;
|
|
size_type __capacity = size_type(_S_local_capacity);
|
|
|
|
_M_init_local_buf();
|
|
|
|
while (__beg != __end && __len < __capacity)
|
|
{
|
|
_M_local_buf[__len++] = *__beg;
|
|
++__beg;
|
|
}
|
|
|
|
struct _Guard
|
|
{
|
|
_GLIBCXX20_CONSTEXPR
|
|
explicit _Guard(basic_string* __s) : _M_guarded(__s) { }
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
~_Guard() { if (_M_guarded) _M_guarded->_M_dispose(); }
|
|
|
|
basic_string* _M_guarded;
|
|
} __guard(this);
|
|
|
|
while (__beg != __end)
|
|
{
|
|
if (__len == __capacity)
|
|
{
|
|
// Allocate more space.
|
|
__capacity = __len + 1;
|
|
pointer __another = _M_create(__capacity, __len);
|
|
this->_S_copy(__another, _M_data(), __len);
|
|
_M_dispose();
|
|
_M_data(__another);
|
|
_M_capacity(__capacity);
|
|
}
|
|
traits_type::assign(_M_data()[__len++], *__beg);
|
|
++__beg;
|
|
}
|
|
|
|
__guard._M_guarded = 0;
|
|
|
|
_M_set_length(__len);
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
template<typename _InIterator>
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
_M_construct(_InIterator __beg, _InIterator __end,
|
|
std::forward_iterator_tag)
|
|
{
|
|
size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));
|
|
|
|
if (__dnew > size_type(_S_local_capacity))
|
|
{
|
|
_M_data(_M_create(__dnew, size_type(0)));
|
|
_M_capacity(__dnew);
|
|
}
|
|
else
|
|
_M_init_local_buf();
|
|
|
|
// Check for out_of_range and length_error exceptions.
|
|
struct _Guard
|
|
{
|
|
_GLIBCXX20_CONSTEXPR
|
|
explicit _Guard(basic_string* __s) : _M_guarded(__s) { }
|
|
|
|
_GLIBCXX20_CONSTEXPR
|
|
~_Guard() { if (_M_guarded) _M_guarded->_M_dispose(); }
|
|
|
|
basic_string* _M_guarded;
|
|
} __guard(this);
|
|
|
|
this->_S_copy_chars(_M_data(), __beg, __end);
|
|
|
|
__guard._M_guarded = 0;
|
|
|
|
_M_set_length(__dnew);
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
_M_construct(size_type __n, _CharT __c)
|
|
{
|
|
if (__n > size_type(_S_local_capacity))
|
|
{
|
|
_M_data(_M_create(__n, size_type(0)));
|
|
_M_capacity(__n);
|
|
}
|
|
else
|
|
_M_init_local_buf();
|
|
|
|
if (__n)
|
|
this->_S_assign(_M_data(), __n, __c);
|
|
|
|
_M_set_length(__n);
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
_M_assign(const basic_string& __str)
|
|
{
|
|
if (this != std::__addressof(__str))
|
|
{
|
|
const size_type __rsize = __str.length();
|
|
const size_type __capacity = capacity();
|
|
|
|
if (__rsize > __capacity)
|
|
{
|
|
size_type __new_capacity = __rsize;
|
|
pointer __tmp = _M_create(__new_capacity, __capacity);
|
|
_M_dispose();
|
|
_M_data(__tmp);
|
|
_M_capacity(__new_capacity);
|
|
}
|
|
|
|
if (__rsize)
|
|
this->_S_copy(_M_data(), __str._M_data(), __rsize);
|
|
|
|
_M_set_length(__rsize);
|
|
}
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
reserve(size_type __res)
|
|
{
|
|
const size_type __capacity = capacity();
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 2968. Inconsistencies between basic_string reserve and
|
|
// vector/unordered_map/unordered_set reserve functions
|
|
// P0966 reserve should not shrink
|
|
if (__res <= __capacity)
|
|
return;
|
|
|
|
pointer __tmp = _M_create(__res, __capacity);
|
|
this->_S_copy(__tmp, _M_data(), length() + 1);
|
|
_M_dispose();
|
|
_M_data(__tmp);
|
|
_M_capacity(__res);
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
_M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
|
|
size_type __len2)
|
|
{
|
|
const size_type __how_much = length() - __pos - __len1;
|
|
|
|
size_type __new_capacity = length() + __len2 - __len1;
|
|
pointer __r = _M_create(__new_capacity, capacity());
|
|
|
|
if (__pos)
|
|
this->_S_copy(__r, _M_data(), __pos);
|
|
if (__s && __len2)
|
|
this->_S_copy(__r + __pos, __s, __len2);
|
|
if (__how_much)
|
|
this->_S_copy(__r + __pos + __len2,
|
|
_M_data() + __pos + __len1, __how_much);
|
|
|
|
_M_dispose();
|
|
_M_data(__r);
|
|
_M_capacity(__new_capacity);
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
_M_erase(size_type __pos, size_type __n)
|
|
{
|
|
const size_type __how_much = length() - __pos - __n;
|
|
|
|
if (__how_much && __n)
|
|
this->_S_move(_M_data() + __pos, _M_data() + __pos + __n, __how_much);
|
|
|
|
_M_set_length(length() - __n);
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
reserve()
|
|
{
|
|
if (_M_is_local())
|
|
return;
|
|
|
|
const size_type __length = length();
|
|
const size_type __capacity = _M_allocated_capacity;
|
|
|
|
if (__length <= size_type(_S_local_capacity))
|
|
{
|
|
_M_init_local_buf();
|
|
this->_S_copy(_M_local_buf, _M_data(), __length + 1);
|
|
_M_destroy(__capacity);
|
|
_M_data(_M_local_data());
|
|
}
|
|
#if __cpp_exceptions
|
|
else if (__length < __capacity)
|
|
try
|
|
{
|
|
pointer __tmp = _S_allocate(_M_get_allocator(), __length + 1);
|
|
this->_S_copy(__tmp, _M_data(), __length + 1);
|
|
_M_dispose();
|
|
_M_data(__tmp);
|
|
_M_capacity(__length);
|
|
}
|
|
catch (const __cxxabiv1::__forced_unwind&)
|
|
{ throw; }
|
|
catch (...)
|
|
{ /* swallow the exception */ }
|
|
#endif
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
void
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
resize(size_type __n, _CharT __c)
|
|
{
|
|
const size_type __size = this->size();
|
|
if (__size < __n)
|
|
this->append(__n - __size, __c);
|
|
else if (__n < __size)
|
|
this->_M_set_length(__n);
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string<_CharT, _Traits, _Alloc>&
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
_M_append(const _CharT* __s, size_type __n)
|
|
{
|
|
const size_type __len = __n + this->size();
|
|
|
|
if (__len <= this->capacity())
|
|
{
|
|
if (__n)
|
|
this->_S_copy(this->_M_data() + this->size(), __s, __n);
|
|
}
|
|
else
|
|
this->_M_mutate(this->size(), size_type(0), __s, __n);
|
|
|
|
this->_M_set_length(__len);
|
|
return *this;
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
template<typename _InputIterator>
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string<_CharT, _Traits, _Alloc>&
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
_M_replace_dispatch(const_iterator __i1, const_iterator __i2,
|
|
_InputIterator __k1, _InputIterator __k2,
|
|
std::__false_type)
|
|
{
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 2788. unintentionally require a default constructible allocator
|
|
const basic_string __s(__k1, __k2, this->get_allocator());
|
|
const size_type __n1 = __i2 - __i1;
|
|
return _M_replace(__i1 - begin(), __n1, __s._M_data(),
|
|
__s.size());
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string<_CharT, _Traits, _Alloc>&
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
_M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
|
|
_CharT __c)
|
|
{
|
|
_M_check_length(__n1, __n2, "basic_string::_M_replace_aux");
|
|
|
|
const size_type __old_size = this->size();
|
|
const size_type __new_size = __old_size + __n2 - __n1;
|
|
|
|
if (__new_size <= this->capacity())
|
|
{
|
|
pointer __p = this->_M_data() + __pos1;
|
|
|
|
const size_type __how_much = __old_size - __pos1 - __n1;
|
|
if (__how_much && __n1 != __n2)
|
|
this->_S_move(__p + __n2, __p + __n1, __how_much);
|
|
}
|
|
else
|
|
this->_M_mutate(__pos1, __n1, 0, __n2);
|
|
|
|
if (__n2)
|
|
this->_S_assign(this->_M_data() + __pos1, __n2, __c);
|
|
|
|
this->_M_set_length(__new_size);
|
|
return *this;
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
__attribute__((__noinline__, __noclone__, __cold__)) void
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
_M_replace_cold(pointer __p, size_type __len1, const _CharT* __s,
|
|
const size_type __len2, const size_type __how_much)
|
|
{
|
|
// Work in-place.
|
|
if (__len2 && __len2 <= __len1)
|
|
this->_S_move(__p, __s, __len2);
|
|
if (__how_much && __len1 != __len2)
|
|
this->_S_move(__p + __len2, __p + __len1, __how_much);
|
|
if (__len2 > __len1)
|
|
{
|
|
if (__s + __len2 <= __p + __len1)
|
|
this->_S_move(__p, __s, __len2);
|
|
else if (__s >= __p + __len1)
|
|
{
|
|
// Hint to middle end that __p and __s overlap
|
|
// (PR 98465).
|
|
const size_type __poff = (__s - __p) + (__len2 - __len1);
|
|
this->_S_copy(__p, __p + __poff, __len2);
|
|
}
|
|
else
|
|
{
|
|
const size_type __nleft = (__p + __len1) - __s;
|
|
this->_S_move(__p, __s, __nleft);
|
|
this->_S_copy(__p + __nleft, __p + __len2, __len2 - __nleft);
|
|
}
|
|
}
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
basic_string<_CharT, _Traits, _Alloc>&
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
_M_replace(size_type __pos, size_type __len1, const _CharT* __s,
|
|
const size_type __len2)
|
|
{
|
|
_M_check_length(__len1, __len2, "basic_string::_M_replace");
|
|
|
|
const size_type __old_size = this->size();
|
|
const size_type __new_size = __old_size + __len2 - __len1;
|
|
|
|
if (__new_size <= this->capacity())
|
|
{
|
|
pointer __p = this->_M_data() + __pos;
|
|
|
|
const size_type __how_much = __old_size - __pos - __len1;
|
|
#if __cpp_lib_is_constant_evaluated
|
|
if (std::is_constant_evaluated())
|
|
{
|
|
auto __newp = _S_allocate(_M_get_allocator(), __new_size);
|
|
_S_copy(__newp, this->_M_data(), __pos);
|
|
_S_copy(__newp + __pos, __s, __len2);
|
|
_S_copy(__newp + __pos + __len2, __p + __len1, __how_much);
|
|
_S_copy(this->_M_data(), __newp, __new_size);
|
|
this->_M_get_allocator().deallocate(__newp, __new_size);
|
|
}
|
|
else
|
|
#endif
|
|
if (__builtin_expect(_M_disjunct(__s), true))
|
|
{
|
|
if (__how_much && __len1 != __len2)
|
|
this->_S_move(__p + __len2, __p + __len1, __how_much);
|
|
if (__len2)
|
|
this->_S_copy(__p, __s, __len2);
|
|
}
|
|
else
|
|
_M_replace_cold(__p, __len1, __s, __len2, __how_much);
|
|
}
|
|
else
|
|
this->_M_mutate(__pos, __len1, __s, __len2);
|
|
|
|
this->_M_set_length(__new_size);
|
|
return *this;
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX20_CONSTEXPR
|
|
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
copy(_CharT* __s, size_type __n, size_type __pos) const
|
|
{
|
|
_M_check(__pos, "basic_string::copy");
|
|
__n = _M_limit(__pos, __n);
|
|
__glibcxx_requires_string_len(__s, __n);
|
|
if (__n)
|
|
_S_copy(__s, _M_data() + __pos, __n);
|
|
// 21.3.5.7 par 3: do not append null. (good.)
|
|
return __n;
|
|
}
|
|
|
|
#ifdef __glibcxx_string_resize_and_overwrite // C++ >= 23
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
template<typename _Operation>
|
|
[[__gnu__::__always_inline__]]
|
|
constexpr void
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
__resize_and_overwrite(const size_type __n, _Operation __op)
|
|
{ resize_and_overwrite<_Operation&>(__n, __op); }
|
|
#endif
|
|
|
|
#if __cplusplus >= 201103L
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
template<typename _Operation>
|
|
_GLIBCXX20_CONSTEXPR void
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
#ifdef __glibcxx_string_resize_and_overwrite // C++ >= 23
|
|
resize_and_overwrite(const size_type __n, _Operation __op)
|
|
#else
|
|
__resize_and_overwrite(const size_type __n, _Operation __op)
|
|
#endif
|
|
{
|
|
reserve(__n);
|
|
_CharT* const __p = _M_data();
|
|
#if __cpp_lib_is_constant_evaluated
|
|
if (std::__is_constant_evaluated() && __n > size())
|
|
traits_type::assign(__p + size(), __n - size(), _CharT());
|
|
#endif
|
|
struct _Terminator {
|
|
_GLIBCXX20_CONSTEXPR ~_Terminator() { _M_this->_M_set_length(_M_r); }
|
|
basic_string* _M_this;
|
|
size_type _M_r;
|
|
};
|
|
_Terminator __term{this, 0};
|
|
auto __r = std::move(__op)(__p + 0, __n + 0);
|
|
#ifdef __cpp_lib_concepts
|
|
static_assert(ranges::__detail::__is_integer_like<decltype(__r)>);
|
|
#else
|
|
static_assert(__gnu_cxx::__is_integer_nonstrict<decltype(__r)>::__value,
|
|
"resize_and_overwrite operation must return an integer");
|
|
#endif
|
|
_GLIBCXX_DEBUG_ASSERT(__r >= 0 && __r <= __n);
|
|
__term._M_r = size_type(__r);
|
|
if (__term._M_r > __n)
|
|
__builtin_unreachable();
|
|
}
|
|
#endif // C++11
|
|
|
|
#endif // _GLIBCXX_USE_CXX11_ABI
|
|
|
|
#if __glibcxx_constexpr_string >= 201907L
|
|
# define _GLIBCXX_STRING_CONSTEXPR constexpr
|
|
#else
|
|
# define _GLIBCXX_STRING_CONSTEXPR
|
|
#endif
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_STRING_CONSTEXPR
|
|
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
find(const _CharT* __s, size_type __pos, size_type __n) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{
|
|
__glibcxx_requires_string_len(__s, __n);
|
|
const size_type __size = this->size();
|
|
|
|
if (__n == 0)
|
|
return __pos <= __size ? __pos : npos;
|
|
if (__pos >= __size)
|
|
return npos;
|
|
|
|
const _CharT __elem0 = __s[0];
|
|
const _CharT* const __data = data();
|
|
const _CharT* __first = __data + __pos;
|
|
const _CharT* const __last = __data + __size;
|
|
size_type __len = __size - __pos;
|
|
|
|
while (__len >= __n)
|
|
{
|
|
// Find the first occurrence of __elem0:
|
|
__first = traits_type::find(__first, __len - __n + 1, __elem0);
|
|
if (!__first)
|
|
return npos;
|
|
// Compare the full strings from the first occurrence of __elem0.
|
|
// We already know that __first[0] == __s[0] but compare them again
|
|
// anyway because __s is probably aligned, which helps memcmp.
|
|
if (traits_type::compare(__first, __s, __n) == 0)
|
|
return __first - __data;
|
|
__len = __last - ++__first;
|
|
}
|
|
return npos;
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_STRING_CONSTEXPR
|
|
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
find(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
|
|
{
|
|
size_type __ret = npos;
|
|
const size_type __size = this->size();
|
|
if (__pos < __size)
|
|
{
|
|
const _CharT* __data = _M_data();
|
|
const size_type __n = __size - __pos;
|
|
const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
|
|
if (__p)
|
|
__ret = __p - __data;
|
|
}
|
|
return __ret;
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_STRING_CONSTEXPR
|
|
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
rfind(const _CharT* __s, size_type __pos, size_type __n) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{
|
|
__glibcxx_requires_string_len(__s, __n);
|
|
const size_type __size = this->size();
|
|
if (__n <= __size)
|
|
{
|
|
__pos = std::min(size_type(__size - __n), __pos);
|
|
const _CharT* __data = _M_data();
|
|
do
|
|
{
|
|
if (traits_type::compare(__data + __pos, __s, __n) == 0)
|
|
return __pos;
|
|
}
|
|
while (__pos-- > 0);
|
|
}
|
|
return npos;
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_STRING_CONSTEXPR
|
|
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
rfind(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
|
|
{
|
|
size_type __size = this->size();
|
|
if (__size)
|
|
{
|
|
if (--__size > __pos)
|
|
__size = __pos;
|
|
for (++__size; __size-- > 0; )
|
|
if (traits_type::eq(_M_data()[__size], __c))
|
|
return __size;
|
|
}
|
|
return npos;
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_STRING_CONSTEXPR
|
|
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{
|
|
__glibcxx_requires_string_len(__s, __n);
|
|
for (; __n && __pos < this->size(); ++__pos)
|
|
{
|
|
const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
|
|
if (__p)
|
|
return __pos;
|
|
}
|
|
return npos;
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_STRING_CONSTEXPR
|
|
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{
|
|
__glibcxx_requires_string_len(__s, __n);
|
|
size_type __size = this->size();
|
|
if (__size && __n)
|
|
{
|
|
if (--__size > __pos)
|
|
__size = __pos;
|
|
do
|
|
{
|
|
if (traits_type::find(__s, __n, _M_data()[__size]))
|
|
return __size;
|
|
}
|
|
while (__size-- != 0);
|
|
}
|
|
return npos;
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_STRING_CONSTEXPR
|
|
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{
|
|
__glibcxx_requires_string_len(__s, __n);
|
|
for (; __pos < this->size(); ++__pos)
|
|
if (!traits_type::find(__s, __n, _M_data()[__pos]))
|
|
return __pos;
|
|
return npos;
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_STRING_CONSTEXPR
|
|
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
find_first_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
|
|
{
|
|
for (; __pos < this->size(); ++__pos)
|
|
if (!traits_type::eq(_M_data()[__pos], __c))
|
|
return __pos;
|
|
return npos;
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_STRING_CONSTEXPR
|
|
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
|
|
_GLIBCXX_NOEXCEPT
|
|
{
|
|
__glibcxx_requires_string_len(__s, __n);
|
|
size_type __size = this->size();
|
|
if (__size)
|
|
{
|
|
if (--__size > __pos)
|
|
__size = __pos;
|
|
do
|
|
{
|
|
if (!traits_type::find(__s, __n, _M_data()[__size]))
|
|
return __size;
|
|
}
|
|
while (__size--);
|
|
}
|
|
return npos;
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
_GLIBCXX_STRING_CONSTEXPR
|
|
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
|
basic_string<_CharT, _Traits, _Alloc>::
|
|
find_last_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
|
|
{
|
|
size_type __size = this->size();
|
|
if (__size)
|
|
{
|
|
if (--__size > __pos)
|
|
__size = __pos;
|
|
do
|
|
{
|
|
if (!traits_type::eq(_M_data()[__size], __c))
|
|
return __size;
|
|
}
|
|
while (__size--);
|
|
}
|
|
return npos;
|
|
}
|
|
|
|
#undef _GLIBCXX_STRING_CONSTEXPR
|
|
|
|
// 21.3.7.9 basic_string::getline and operators
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
basic_istream<_CharT, _Traits>&
|
|
operator>>(basic_istream<_CharT, _Traits>& __in,
|
|
basic_string<_CharT, _Traits, _Alloc>& __str)
|
|
{
|
|
typedef basic_istream<_CharT, _Traits> __istream_type;
|
|
typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
|
|
typedef typename __istream_type::ios_base __ios_base;
|
|
typedef typename __istream_type::int_type __int_type;
|
|
typedef typename __string_type::size_type __size_type;
|
|
typedef ctype<_CharT> __ctype_type;
|
|
typedef typename __ctype_type::ctype_base __ctype_base;
|
|
|
|
__size_type __extracted = 0;
|
|
typename __ios_base::iostate __err = __ios_base::goodbit;
|
|
typename __istream_type::sentry __cerb(__in, false);
|
|
if (__cerb)
|
|
{
|
|
__try
|
|
{
|
|
// Avoid reallocation for common case.
|
|
__str.erase();
|
|
_CharT __buf[128];
|
|
__size_type __len = 0;
|
|
const streamsize __w = __in.width();
|
|
const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
|
|
: __str.max_size();
|
|
const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
|
|
const __int_type __eof = _Traits::eof();
|
|
__int_type __c = __in.rdbuf()->sgetc();
|
|
|
|
while (__extracted < __n
|
|
&& !_Traits::eq_int_type(__c, __eof)
|
|
&& !__ct.is(__ctype_base::space,
|
|
_Traits::to_char_type(__c)))
|
|
{
|
|
if (__len == sizeof(__buf) / sizeof(_CharT))
|
|
{
|
|
__str.append(__buf, sizeof(__buf) / sizeof(_CharT));
|
|
__len = 0;
|
|
}
|
|
__buf[__len++] = _Traits::to_char_type(__c);
|
|
++__extracted;
|
|
__c = __in.rdbuf()->snextc();
|
|
}
|
|
__str.append(__buf, __len);
|
|
|
|
if (__extracted < __n && _Traits::eq_int_type(__c, __eof))
|
|
__err |= __ios_base::eofbit;
|
|
__in.width(0);
|
|
}
|
|
__catch(__cxxabiv1::__forced_unwind&)
|
|
{
|
|
__in._M_setstate(__ios_base::badbit);
|
|
__throw_exception_again;
|
|
}
|
|
__catch(...)
|
|
{
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 91. Description of operator>> and getline() for string<>
|
|
// might cause endless loop
|
|
__in._M_setstate(__ios_base::badbit);
|
|
}
|
|
}
|
|
// 211. operator>>(istream&, string&) doesn't set failbit
|
|
if (!__extracted)
|
|
__err |= __ios_base::failbit;
|
|
if (__err)
|
|
__in.setstate(__err);
|
|
return __in;
|
|
}
|
|
|
|
template<typename _CharT, typename _Traits, typename _Alloc>
|
|
basic_istream<_CharT, _Traits>&
|
|
getline(basic_istream<_CharT, _Traits>& __in,
|
|
basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim)
|
|
{
|
|
typedef basic_istream<_CharT, _Traits> __istream_type;
|
|
typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
|
|
typedef typename __istream_type::ios_base __ios_base;
|
|
typedef typename __istream_type::int_type __int_type;
|
|
typedef typename __string_type::size_type __size_type;
|
|
|
|
__size_type __extracted = 0;
|
|
const __size_type __n = __str.max_size();
|
|
typename __ios_base::iostate __err = __ios_base::goodbit;
|
|
typename __istream_type::sentry __cerb(__in, true);
|
|
if (__cerb)
|
|
{
|
|
__try
|
|
{
|
|
__str.erase();
|
|
const __int_type __idelim = _Traits::to_int_type(__delim);
|
|
const __int_type __eof = _Traits::eof();
|
|
__int_type __c = __in.rdbuf()->sgetc();
|
|
|
|
while (__extracted < __n
|
|
&& !_Traits::eq_int_type(__c, __eof)
|
|
&& !_Traits::eq_int_type(__c, __idelim))
|
|
{
|
|
__str += _Traits::to_char_type(__c);
|
|
++__extracted;
|
|
__c = __in.rdbuf()->snextc();
|
|
}
|
|
|
|
if (_Traits::eq_int_type(__c, __eof))
|
|
__err |= __ios_base::eofbit;
|
|
else if (_Traits::eq_int_type(__c, __idelim))
|
|
{
|
|
++__extracted;
|
|
__in.rdbuf()->sbumpc();
|
|
}
|
|
else
|
|
__err |= __ios_base::failbit;
|
|
}
|
|
__catch(__cxxabiv1::__forced_unwind&)
|
|
{
|
|
__in._M_setstate(__ios_base::badbit);
|
|
__throw_exception_again;
|
|
}
|
|
__catch(...)
|
|
{
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 91. Description of operator>> and getline() for string<>
|
|
// might cause endless loop
|
|
__in._M_setstate(__ios_base::badbit);
|
|
}
|
|
}
|
|
if (!__extracted)
|
|
__err |= __ios_base::failbit;
|
|
if (__err)
|
|
__in.setstate(__err);
|
|
return __in;
|
|
}
|
|
|
|
// Inhibit implicit instantiations for required instantiations,
|
|
// which are defined via explicit instantiations elsewhere.
|
|
#if _GLIBCXX_EXTERN_TEMPLATE
|
|
// The explicit instantiation definitions in src/c++11/string-inst.cc and
|
|
// src/c++17/string-inst.cc only instantiate the members required for C++17
|
|
// and earlier standards (so not C++20's starts_with and ends_with).
|
|
// Suppress the explicit instantiation declarations for C++20, so C++20
|
|
// code will implicitly instantiate std::string and std::wstring as needed.
|
|
# if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0
|
|
extern template class basic_string<char>;
|
|
# elif ! _GLIBCXX_USE_CXX11_ABI
|
|
// Still need to prevent implicit instantiation of the COW empty rep,
|
|
// to ensure the definition in libstdc++.so is unique (PR 86138).
|
|
extern template basic_string<char>::size_type
|
|
basic_string<char>::_Rep::_S_empty_rep_storage[];
|
|
# elif _GLIBCXX_EXTERN_TEMPLATE > 0
|
|
// Export _M_replace_cold even for C++20.
|
|
extern template void
|
|
basic_string<char>::_M_replace_cold(char *, size_type, const char*,
|
|
const size_type, const size_type);
|
|
# endif
|
|
|
|
extern template
|
|
basic_istream<char>&
|
|
operator>>(basic_istream<char>&, string&);
|
|
extern template
|
|
basic_ostream<char>&
|
|
operator<<(basic_ostream<char>&, const string&);
|
|
extern template
|
|
basic_istream<char>&
|
|
getline(basic_istream<char>&, string&, char);
|
|
extern template
|
|
basic_istream<char>&
|
|
getline(basic_istream<char>&, string&);
|
|
|
|
#ifdef _GLIBCXX_USE_WCHAR_T
|
|
# if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0
|
|
extern template class basic_string<wchar_t>;
|
|
# elif ! _GLIBCXX_USE_CXX11_ABI
|
|
extern template basic_string<wchar_t>::size_type
|
|
basic_string<wchar_t>::_Rep::_S_empty_rep_storage[];
|
|
# elif _GLIBCXX_EXTERN_TEMPLATE > 0
|
|
// Export _M_replace_cold even for C++20.
|
|
extern template void
|
|
basic_string<wchar_t>::_M_replace_cold(wchar_t*, size_type, const wchar_t*,
|
|
const size_type, const size_type);
|
|
# endif
|
|
|
|
extern template
|
|
basic_istream<wchar_t>&
|
|
operator>>(basic_istream<wchar_t>&, wstring&);
|
|
extern template
|
|
basic_ostream<wchar_t>&
|
|
operator<<(basic_ostream<wchar_t>&, const wstring&);
|
|
extern template
|
|
basic_istream<wchar_t>&
|
|
getline(basic_istream<wchar_t>&, wstring&, wchar_t);
|
|
extern template
|
|
basic_istream<wchar_t>&
|
|
getline(basic_istream<wchar_t>&, wstring&);
|
|
#endif // _GLIBCXX_USE_WCHAR_T
|
|
#endif // _GLIBCXX_EXTERN_TEMPLATE
|
|
|
|
_GLIBCXX_END_NAMESPACE_VERSION
|
|
} // namespace std
|
|
|
|
#pragma GCC diagnostic pop
|
|
#endif
|