You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
890 lines
31 KiB
890 lines
31 KiB
5 years ago
|
/***************************************************************************
|
||
|
*
|
||
|
* string.cc - Definitions for the Standard Library string classes
|
||
|
*
|
||
|
* $Id: string.cc 172106 2011-11-02 17:04:12Z statham $
|
||
|
*
|
||
|
***************************************************************************
|
||
|
*
|
||
|
* Copyright (c) 1994-2001 Rogue Wave Software, Inc. All Rights Reserved.
|
||
|
*
|
||
|
* This computer software is owned by Rogue Wave Software, Inc. and is
|
||
|
* protected by U.S. copyright laws and other laws and by international
|
||
|
* treaties. This computer software is furnished by Rogue Wave Software,
|
||
|
* Inc. pursuant to a written license agreement and may be used, copied,
|
||
|
* transmitted, and stored only in accordance with the terms of such
|
||
|
* license and with the inclusion of the above copyright notice. This
|
||
|
* computer software or any other copies thereof may not be provided or
|
||
|
* otherwise made available to any other person.
|
||
|
*
|
||
|
* U.S. Government Restricted Rights. This computer software is provided
|
||
|
* with Restricted Rights. Use, duplication, or disclosure by the
|
||
|
* Government is subject to restrictions as set forth in subparagraph (c)
|
||
|
* (1) (ii) of The Rights in Technical Data and Computer Software clause
|
||
|
* at DFARS 252.227-7013 or subparagraphs (c) (1) and (2) of the
|
||
|
* Commercial Computer Software--Restricted Rights at 48 CFR 52.227-19,
|
||
|
* as applicable. Manufacturer is Rogue Wave Software, Inc., 5500
|
||
|
* Flatiron Parkway, Boulder, Colorado 80301 USA.
|
||
|
*
|
||
|
**************************************************************************/
|
||
|
|
||
|
_RWSTD_NAMESPACE_BEGIN (std)
|
||
|
|
||
|
|
||
|
#if defined (_RWSTD_LLP64_ARCHITECTURE) \
|
||
|
&& defined (_RWSTD_NO_STATIC_CONST_MEMBER_INIT) \
|
||
|
&& defined (_RWBUILD_std)
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
const _TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type
|
||
|
basic_string<_CharT, _Traits, _Allocator>::npos = size_t(-1);
|
||
|
|
||
|
#elif !defined(_RWSTD_NO_STATIC_CONST_MEMBER_INIT)
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
const _TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type
|
||
|
basic_string<_CharT, _Traits, _Allocator>::npos;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#ifndef _RWSTD_NO_COLLAPSE_TEMPLATE_STATICS
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
_RW::__null_ref<_CharT, _Traits, _Allocator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>::__nullref;
|
||
|
|
||
|
#endif // _RWSTD_NO_STRING_REF_COUNT
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
_TYPENAME basic_string<_CharT, _Traits, _Allocator>::_C_string_ref_type *
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
_C_getRep (size_type __cap, size_type __len)
|
||
|
{
|
||
|
_RWSTD_REQUIRES (__cap <= max_size (),
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::_C_getRep(size_type, "
|
||
|
"size_type)"), __cap, max_size ()));
|
||
|
|
||
|
_RWSTD_REQUIRES (__len <= __cap,
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::_C_getRep(size_type, "
|
||
|
"size_type)"), __len, __cap));
|
||
|
|
||
|
if (!__cap) {
|
||
|
_RWSTD_ASSERT (!__len);
|
||
|
|
||
|
#ifndef _RWSTD_NO_COLLAPSE_TEMPLATE_STATICS
|
||
|
|
||
|
return &__nullref;
|
||
|
|
||
|
#else // if defined (_RWSTD_NO_COLLAPSE_TEMPLATE_STATICS)
|
||
|
|
||
|
return _RWSTD_REINTERPRET_CAST (_C_string_ref_type*, &_RW::__nullref);
|
||
|
|
||
|
#endif // _RWSTD_NO_COLLAPSE_TEMPLATE_STATICS
|
||
|
|
||
|
}
|
||
|
|
||
|
// allocate, initialize the __string_ref, and initialize each character
|
||
|
_C_string_ref_type * __ret =
|
||
|
_RWSTD_REINTERPRET_CAST (_C_string_ref_type*,
|
||
|
_RWSTD_VALUE_ALLOC (_C_value_alloc_type,
|
||
|
allocate (__cap + sizeof (_C_string_ref_type) /
|
||
|
sizeof (value_type) + 2)));
|
||
|
|
||
|
// avoid copy construction (mutex isn't copy-constructible)
|
||
|
// _C_ref_alloc_type (*this).construct (__ret, _C_string_ref_type ());
|
||
|
new (__ret) _C_string_ref_type ();
|
||
|
|
||
|
#ifndef _RWSTD_NO_STRING_REF_COUNT
|
||
|
|
||
|
// set initial reference count to 1
|
||
|
__ret->_C_init (1, __cap, __len);
|
||
|
|
||
|
#else // if defined (_RWSTD_NO_STRING_REF_COUNT)
|
||
|
|
||
|
// initial reference count is 0 (ref counting disabled)
|
||
|
__ret->_C_init (0, __cap, __len);
|
||
|
|
||
|
#endif // _RWSTD_NO_STRING_REF_COUNT
|
||
|
|
||
|
|
||
|
_RWSTD_VALUE_ALLOC (_C_value_alloc_type, construct (__ret->data () + __len,
|
||
|
value_type ()));
|
||
|
|
||
|
return __ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
basic_string (const basic_string &__s,
|
||
|
size_type __pos, size_type __n, const allocator_type& __alloc)
|
||
|
: allocator_type (__alloc)
|
||
|
{
|
||
|
_RWSTD_REQUIRES (__pos <= __s.size (),
|
||
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
||
|
_RWSTD_FUNC ("basic_string::basic_string(const "
|
||
|
"basic_string&, size_type, size_type)"),
|
||
|
__pos, __s.size ()));
|
||
|
|
||
|
size_type __slen = __s.size() - __pos;
|
||
|
size_type __rlen = __n < __slen ? __n : __slen;
|
||
|
size_type __nlen = __n == npos ? 0 : __n;
|
||
|
size_type __maxlen = __nlen > __rlen ? __nlen : __rlen;
|
||
|
if (__maxlen)
|
||
|
_C_data = _C_allocate (0, __maxlen, __rlen);
|
||
|
else
|
||
|
_C_data = _C_getRep (__maxlen,__rlen)->data();
|
||
|
|
||
|
traits_type::copy(_C_data, &__s._C_data[__pos], __rlen);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
void basic_string<_CharT, _Traits, _Allocator>::
|
||
|
_C_initn (size_type __n, value_type __c)
|
||
|
{
|
||
|
_RWSTD_REQUIRES (__n <= max_size (),
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::_C_initn(size_type, "
|
||
|
"value_type)"), __n, max_size ()));
|
||
|
|
||
|
_C_data = __n ? _C_allocate (0, __n, __n) : _C_null ();
|
||
|
|
||
|
while (__n--)
|
||
|
traits_type::assign (_C_data [__n], __c);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
basic_string (const_pointer __s, size_type __n, const allocator_type& __alloc)
|
||
|
: allocator_type (__alloc)
|
||
|
{
|
||
|
// extension: if `s' is 0 then `n' unitialized elements are allocated
|
||
|
|
||
|
_RWSTD_REQUIRES (__n <= max_size (),
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::basic_string(const_pointer,"
|
||
|
"size_type, const allocator_type&)"),
|
||
|
__n, max_size ()));
|
||
|
|
||
|
_C_data = __n ? _C_allocate (0, __n, __n) : _C_null ();
|
||
|
|
||
|
if (__s)
|
||
|
traits_type::copy (_C_data, __s, __n);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
basic_string (const_pointer __s, const allocator_type& __alloc)
|
||
|
: allocator_type(__alloc)
|
||
|
{
|
||
|
_RWSTD_ASSERT(__s != 0);
|
||
|
|
||
|
size_type __n = traits_type::length (__s);
|
||
|
|
||
|
_C_data = __n ? _C_allocate (0, __n, __n) : _C_null ();
|
||
|
|
||
|
traits_type::copy (_C_data, __s, __n);
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
template <class _InputIterator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
basic_string (_InputIterator __first, _InputIterator __last,
|
||
|
const allocator_type &__alloc)
|
||
|
: allocator_type (__alloc),
|
||
|
_C_data (_C_null ())
|
||
|
{
|
||
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
||
|
|
||
|
replace (_C_make_iter (_C_data), _C_make_iter (_C_data), __first, __last);
|
||
|
}
|
||
|
|
||
|
#endif // _RWSTD_NO_MEMBER_TEMPLATES
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
basic_string (const_pointer __first, const_pointer __last,
|
||
|
const allocator_type& __alloc)
|
||
|
: allocator_type (__alloc)
|
||
|
{
|
||
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
||
|
_RWSTD_ASSERT (__first <= __last);
|
||
|
|
||
|
size_type __n = __last - __first;
|
||
|
|
||
|
_C_data = __n ? _C_allocate (0, __n, __n) : _C_null ();
|
||
|
|
||
|
traits_type::copy (_C_data, __first, __n);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>&
|
||
|
basic_string<_CharT, _Traits, _Allocator>::operator= (const basic_string &__rhs)
|
||
|
{
|
||
|
if (__rhs._C_pref ()->_C_ref_count () > 0) {
|
||
|
__rhs._C_pref ()->_C_inc_ref ();
|
||
|
_C_unlink ();
|
||
|
_C_data = __rhs._C_data;
|
||
|
}
|
||
|
else if (this != &__rhs)
|
||
|
replace (0, size (), __rhs.data (), __rhs.size ());
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>&
|
||
|
basic_string<_CharT, _Traits, _Allocator>::operator= (const_pointer __rhs)
|
||
|
{
|
||
|
_RWSTD_ASSERT (__rhs != 0);
|
||
|
|
||
|
size_type __len = traits_type::length (__rhs);
|
||
|
|
||
|
if (0 == __len) {
|
||
|
if (_C_pref ()->_C_ref_count () == 1) {
|
||
|
_C_pref ()->_C_size = 0;
|
||
|
traits_type::assign (_C_data [0], value_type ());
|
||
|
}
|
||
|
else {
|
||
|
_C_unlink();
|
||
|
_C_data = _C_null ();
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
return replace (0, size (), __rhs, __len);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>&
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
append (const basic_string &__str, size_type __pos, size_type __n)
|
||
|
{
|
||
|
_RWSTD_REQUIRES (__pos <= __str.size (),
|
||
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
||
|
_RWSTD_FUNC ("basic_string::append(const basic_string&,"
|
||
|
" size_type, size_type)"),
|
||
|
__pos, __str.size ()));
|
||
|
|
||
|
size_type __slen = __str.size() - __pos;
|
||
|
size_type __rlen = __n < __slen ? __n : __slen;
|
||
|
|
||
|
|
||
|
_RWSTD_REQUIRES (size () <= max_size () - __rlen,
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::append(const basic_string&,"
|
||
|
" size_type, size_type)"),
|
||
|
size (), max_size () - __rlen));
|
||
|
|
||
|
replace(size(), 0, __str.c_str(), __str.size(), __pos, __n);
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>&
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
assign (const basic_string &__str, size_type __pos, size_type __n)
|
||
|
{
|
||
|
_RWSTD_REQUIRES (__pos <= __str.size (),
|
||
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
||
|
_RWSTD_FUNC ("basic_string::assign(basic_string&, "
|
||
|
"size_type, size_type)"),
|
||
|
__pos, __str.size ()));
|
||
|
|
||
|
size_type __slen = __str.size() - __pos;
|
||
|
size_type __rlen = __n < __slen ? __n : __slen;
|
||
|
return replace(0, size(), __str, __pos, __rlen);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>&
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
insert (size_type __pos1, const basic_string& __str,
|
||
|
size_type __pos2, size_type __n)
|
||
|
{
|
||
|
_RWSTD_REQUIRES (__pos1 <= size() && __pos2 <= __str.size (),
|
||
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
||
|
_RWSTD_FUNC ("basic_string::insert(size_type, const "
|
||
|
"basic_string&, size_type, size_type)"),
|
||
|
__pos1 > size() ? __pos1:__pos2, __str.size ()));
|
||
|
|
||
|
size_type __slen = __str.size() - __pos2;
|
||
|
size_type __rlen = __n < __slen ? __n : __slen;
|
||
|
|
||
|
_RWSTD_REQUIRES (size () <= max_size () - __rlen,
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::insert(size_type, const "
|
||
|
"basic_string&, size_type, size_type)"),
|
||
|
size (), max_size () - __rlen));
|
||
|
|
||
|
return replace(__pos1, 0, __str, __pos2, __n);
|
||
|
}
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>&
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
insert (size_type __pos1, const basic_string &__str)
|
||
|
{
|
||
|
_RWSTD_REQUIRES (__pos1 <= size (),
|
||
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
||
|
_RWSTD_FUNC ("basic_string::insert(size_type, const "
|
||
|
"basic_string&)"), __pos1, size ()));
|
||
|
|
||
|
_RWSTD_REQUIRES (size() <= max_size() - __str.size(),
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::insert(size_type, "
|
||
|
"const basic_string&)"),
|
||
|
size (), max_size () - __str.size ()));
|
||
|
|
||
|
return replace(__pos1, 0, __str);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
_TYPENAME basic_string<_CharT, _Traits, _Allocator>::iterator
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
replace (size_type __pos1, size_type __n1, const_pointer __cs,
|
||
|
size_type __cslen, size_type __pos2, size_type __n2)
|
||
|
{
|
||
|
_RWSTD_REQUIRES (__pos1 <= size () && __pos2 <= __cslen,
|
||
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
||
|
_RWSTD_FUNC ("basic_string::replace(size_type, size_type,"
|
||
|
" const_pointer, size_type, size_type, "
|
||
|
"size_type)"),
|
||
|
__pos1 > size() ? __pos1 : __pos2,
|
||
|
size () > __cslen ? size () : __cslen));
|
||
|
|
||
|
size_type __slen = size() - __pos1;
|
||
|
size_type __xlen = __n1 < __slen ? __n1 : __slen;
|
||
|
size_type __clen = __cslen - __pos2;
|
||
|
size_type __rlen = __n2 < __clen ? __n2 : __clen;
|
||
|
|
||
|
_RWSTD_REQUIRES (size () - __xlen <= max_size () - __rlen,
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::replace(size_type, size_type,"
|
||
|
" const_pointer, size_type, size_type, "
|
||
|
"size_type)"),
|
||
|
size () - __xlen, max_size() - __rlen));
|
||
|
|
||
|
size_type __len = size() - __xlen + __rlen; // final string length
|
||
|
|
||
|
if (!__len) {
|
||
|
// Special case a substitution that leaves the string empty.
|
||
|
_C_unlink ();
|
||
|
_C_data = _C_null ();
|
||
|
}
|
||
|
else {
|
||
|
// Length of bit at end of string
|
||
|
size_type __rem = size () - __xlen - __pos1;
|
||
|
// Check for shared representation, insufficient capacity,
|
||
|
// or overlap copy.
|
||
|
if ( _C_pref()->_C_ref_count () > 1
|
||
|
|| capacity () < __len
|
||
|
|| __cs && __cs >= data () && __cs < data () + size ()) {
|
||
|
// Need to allocate a new reference.
|
||
|
size_t __new_capacity = max (_RW::__rw_new_capacity (size(), this),
|
||
|
size_t (__len));
|
||
|
_C_string_ref_type * __temp = _C_getRep(__new_capacity, __len);
|
||
|
if (__pos1)
|
||
|
traits_type::copy (__temp->data (), _C_data, __pos1);
|
||
|
|
||
|
if (__rlen)
|
||
|
traits_type::copy (__temp->data() + __pos1,
|
||
|
__cs + __pos2, __rlen);
|
||
|
|
||
|
if (__rem)
|
||
|
traits_type::copy (__temp->data() + __pos1 + __rlen,
|
||
|
_C_data + __pos1 + __n1, __rem);
|
||
|
_C_unlink();
|
||
|
_C_data = __temp->data();
|
||
|
}
|
||
|
else {
|
||
|
// Current reference has enough room.
|
||
|
if (__rem)
|
||
|
traits_type::move (_C_data + __pos1 + __rlen,
|
||
|
_C_data + __pos1 + __n1, __rem);
|
||
|
|
||
|
if (__rlen)
|
||
|
traits_type::move (_C_data + __pos1, __cs + __pos2, __rlen);
|
||
|
|
||
|
traits_type::assign (_C_data [_C_pref()->_C_size = __len],
|
||
|
value_type ());
|
||
|
}
|
||
|
}
|
||
|
return _C_make_iter (_C_data + __pos1);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>&
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
replace (size_type __pos, size_type __n, size_type __n2, value_type __c)
|
||
|
{
|
||
|
_RWSTD_REQUIRES (__pos <= size (),
|
||
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
||
|
_RWSTD_FUNC ("basic_string:::replace(size_type, "
|
||
|
"size_type, size_type, value_type)"),
|
||
|
__pos, size ()));
|
||
|
|
||
|
size_type __slen = size() - __pos;
|
||
|
size_type __xlen = __n < __slen ? __n : __slen;
|
||
|
|
||
|
_RWSTD_REQUIRES (size() - __xlen < max_size () - __n2,
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::replace(size_type, "
|
||
|
"size_type, size_type, value_type)"),
|
||
|
size () - __xlen, max_size () - __n2));
|
||
|
|
||
|
size_type __len = size() - __xlen + __n2; // Final string length.
|
||
|
|
||
|
if (!__len)
|
||
|
{
|
||
|
// Special case a substitution that leaves the string empty.
|
||
|
_C_unlink();
|
||
|
_C_data = _C_null ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size_type __rem = size () - __xlen - __pos; // length of bit at the end
|
||
|
// Check for shared representation, insufficient capacity,
|
||
|
if ( (_C_pref()->_C_ref_count() > 1) || (capacity() < __len))
|
||
|
{
|
||
|
// Need to allocate a new reference.
|
||
|
size_t __new_capacity = max (_RW::__rw_new_capacity (size(), this),
|
||
|
size_t (__len));
|
||
|
_C_string_ref_type * __temp = _C_getRep(__new_capacity, __len);
|
||
|
if (__pos) traits_type::copy(__temp->data(), _C_data, __pos);
|
||
|
if (__n2) traits_type::assign(__temp->data()+__pos, __n2, __c);
|
||
|
if (__rem)
|
||
|
traits_type::copy (__temp->data () + __pos + __n2,
|
||
|
_C_data + __pos + __n, __rem);
|
||
|
_C_unlink();
|
||
|
_C_data = __temp->data();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Current reference has enough room.
|
||
|
if (__rem)
|
||
|
traits_type::move(_C_data+__pos+__n2, _C_data+__pos+__n, __rem);
|
||
|
if (__n2)
|
||
|
traits_type::assign(_C_data+__pos, __n2, __c);
|
||
|
traits_type::assign (_C_data [_C_pref()->_C_size = __len],
|
||
|
value_type ());
|
||
|
}
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
|
||
|
#if !defined (_RWSTD_NO_MEMBER_TEMPLATES) \
|
||
|
&& !defined (_RWSTD_NO_CLASS_PARTIAL_SPEC)
|
||
|
|
||
|
template<class _CharT, class _Traits, class _Allocator>
|
||
|
template<class _InputIter>
|
||
|
basic_string<_CharT, _Traits, _Allocator>&
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
replace (iterator __first1, iterator __last1,
|
||
|
_InputIter __first2, _InputIter __last2, _RWSTD_DISPATCH_INT (false))
|
||
|
{
|
||
|
_RWSTD_ASSERT_RANGE (__first1, _C_make_iter (_C_data + size ()));
|
||
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
||
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
||
|
|
||
|
// use a (probably) faster algorithm if possible
|
||
|
if (__is_bidirectional_iterator(_RWSTD_ITERATOR_CATEGORY (_InputIter,
|
||
|
__last2)))
|
||
|
return __replace_aux (__first1, __last1, __first2, __last2);
|
||
|
|
||
|
for ( ; __first2 != __last2; ++__first1, ++__first2) {
|
||
|
|
||
|
size_type __off = __first1 - _C_make_iter (_C_data);
|
||
|
|
||
|
_RWSTD_REQUIRES (__off <= max_size(),
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::replace(iterator, "
|
||
|
"iterator, InputIterator, "
|
||
|
"InputIterator)"),
|
||
|
__first1 - _C_make_iter (_C_data), max_size ()));
|
||
|
|
||
|
// extend the string if necessary
|
||
|
if (__first1 == __last1) {
|
||
|
// compute the size of new buffer
|
||
|
size_t __new_cap = _RW::__rw_new_capacity (size (), this);
|
||
|
size_t __delta = __new_cap - size ();
|
||
|
|
||
|
// allocate a new buffer
|
||
|
_C_string_ref_type *__tmp = _C_getRep (__new_cap, __new_cap);
|
||
|
|
||
|
// copy data from old to new, leaving a hole for additions
|
||
|
traits_type::copy (__tmp->data (), _C_data, __off);
|
||
|
traits_type::copy (__tmp->data () + __off + __delta,
|
||
|
_C_data + __off,
|
||
|
_C_make_iter (_C_data + size ()) - __last1);
|
||
|
_C_unlink ();
|
||
|
_C_data = __tmp->data ();
|
||
|
__first1 = _C_make_iter (_C_data + __off);
|
||
|
__last1 = __first1 + __delta;
|
||
|
}
|
||
|
|
||
|
// copy data over
|
||
|
traits_type::assign (*__first1, *__first2);
|
||
|
}
|
||
|
|
||
|
if (__first1 != __last1)
|
||
|
replace (__first1 - _C_make_iter (_C_data), __last1 - __first1,
|
||
|
0, value_type ());
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
// Special function for random access and bi-directional iterators
|
||
|
// Avoids the possibility of multiple allocations
|
||
|
// We still have to copy characters over one at a time.
|
||
|
template<class _CharT, class _Traits, class _Allocator>
|
||
|
template<class _InputIterator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>&
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
__replace_aux (iterator __first1, iterator __last1,
|
||
|
_InputIterator __first2, _InputIterator __last2)
|
||
|
{
|
||
|
_RWSTD_ASSERT_RANGE (__first1, _C_make_iter (_C_data + size ()));
|
||
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
||
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
||
|
|
||
|
difference_type __n2 = _DISTANCE (__first2, __last2, __n2);
|
||
|
size_type __n = __last1 - __first1;
|
||
|
size_type __pos = __first1 - _C_make_iter (_C_data);
|
||
|
|
||
|
_RWSTD_REQUIRES (__pos <= size (),
|
||
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
||
|
_RWSTD_FUNC ("basic_string::__replace_aux(iterator, "
|
||
|
"iterator, InputIterator, InputIterator)"),
|
||
|
__pos, size ()));
|
||
|
|
||
|
size_type __slen = size() - __pos;
|
||
|
size_type __xlen = __n < __slen ? __n : __slen;
|
||
|
|
||
|
_RWSTD_REQUIRES (size () - __xlen < max_size() - __n2,
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::__replace_aux(iterator, "
|
||
|
"iterator, InputIterator, InputIterator)"),
|
||
|
size () - __xlen, max_size () - __n2));
|
||
|
|
||
|
size_type __len = size() - __xlen + __n2; // Final string length.
|
||
|
|
||
|
if (!__len) {
|
||
|
// Special case a substitution that leaves the string empty.
|
||
|
_C_unlink();
|
||
|
_C_data = _C_null ();
|
||
|
}
|
||
|
else {
|
||
|
size_type __d = 0;
|
||
|
size_type __rem = size() - __xlen - __pos; // length of bit at the end
|
||
|
// Check for shared representation, insufficient capacity,
|
||
|
if ( (_C_pref()->_C_ref_count () > 1) || (capacity() < __len))
|
||
|
{
|
||
|
// Need to allocate a new reference.
|
||
|
size_t __new_capacity = max (_RW::__rw_new_capacity (size(), this),
|
||
|
size_t (__len));
|
||
|
_C_string_ref_type * __temp = _C_getRep(__new_capacity, __len);
|
||
|
if (__pos) traits_type::copy(__temp->data(), _C_data, __pos);
|
||
|
for (__d = 0; __d < (size_type)__n2; __d++)
|
||
|
traits_type::assign (*(__temp->data()+__pos+__d), *__first2++);
|
||
|
if (__rem)
|
||
|
traits_type::copy (__temp->data () + __pos + __n2,
|
||
|
_C_data + __pos + __n, __rem);
|
||
|
_C_unlink();
|
||
|
_C_data = __temp->data();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Current reference has enough room.
|
||
|
if (__rem)
|
||
|
traits_type::move(_C_data+__pos+__n2, _C_data+__pos+__n, __rem);
|
||
|
for (__d = 0; __d < (size_type)__n2; __d++)
|
||
|
traits_type::assign (*(_C_data+__pos+__d), *__first2++);
|
||
|
traits_type::assign (_C_data[_C_pref()->_C_size = __len],
|
||
|
value_type());
|
||
|
}
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
#endif // _RWSTD_NO_MEMBER_TEMPLATES
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
_TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
copy (pointer __s, size_type __n, size_type __pos) const
|
||
|
{
|
||
|
_RWSTD_REQUIRES (__pos <= size(),
|
||
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
||
|
_RWSTD_FUNC ("basic_string::copy(pointer, size_type, "
|
||
|
"size_type)"), __pos, size ()));
|
||
|
|
||
|
size_type __slen = size() - __pos;
|
||
|
size_type __rlen = __n < __slen ? __n : __slen;
|
||
|
traits_type::copy(__s, _C_data+__pos, __rlen);
|
||
|
return __rlen;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
_TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
find (const_pointer __s, size_type __pos, size_type __n) const
|
||
|
{
|
||
|
_RWSTD_ASSERT(__s != 0);
|
||
|
|
||
|
_RWSTD_REQUIRES (__n <= max_size (),
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::find(const_pointer, "
|
||
|
"size_type, size_type) const"),
|
||
|
__n, max_size ()));
|
||
|
|
||
|
for (size_type xpos = __pos; (xpos + __n) <= size() ; xpos++)
|
||
|
{
|
||
|
if (!traits_type::compare(_C_data+xpos, __s, __n))
|
||
|
return xpos;
|
||
|
}
|
||
|
|
||
|
return npos;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
_TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
rfind (const_pointer __s, size_type __pos, size_type __n) const
|
||
|
{
|
||
|
_RWSTD_ASSERT(__s != 0);
|
||
|
|
||
|
_RWSTD_REQUIRES (__n <= max_size (),
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::rfind(const_pointer, "
|
||
|
"size_type, size_type) const"),
|
||
|
__n, max_size ()));
|
||
|
|
||
|
if (size() < __n)
|
||
|
return npos;
|
||
|
|
||
|
size_type __slen = size() -__n;
|
||
|
size_type xpos_start = __slen < __pos ? __slen : __pos;
|
||
|
|
||
|
for (size_type xpos = xpos_start+1; xpos != 0 ; xpos--)
|
||
|
{
|
||
|
if (!traits_type::compare(_C_data+xpos-1, __s, __n))
|
||
|
return xpos-1;
|
||
|
}
|
||
|
|
||
|
return npos;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
_TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
find_first_of (const_pointer __s, size_type __pos, size_type __n) const
|
||
|
{
|
||
|
_RWSTD_ASSERT(__s != 0);
|
||
|
|
||
|
_RWSTD_REQUIRES (__n <= max_size (),
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::find_first_of(const_pointer, "
|
||
|
"size_type, size_type) const"),
|
||
|
__n, max_size ()));
|
||
|
|
||
|
for (size_type xpos = __pos; xpos < size() ; xpos++)
|
||
|
{
|
||
|
for (size_type __i = 0; __i < __n ; __i++)
|
||
|
if (traits_type::eq(_C_data[xpos], __s[__i]))
|
||
|
return xpos;
|
||
|
}
|
||
|
|
||
|
return npos;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
_TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
find_last_of (const_pointer __s, size_type __pos, size_type __n) const
|
||
|
{
|
||
|
_RWSTD_ASSERT(__s != 0);
|
||
|
|
||
|
_RWSTD_REQUIRES (__n <= max_size (),
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::find_last_of(const_pointer, "
|
||
|
"size_type, size_type) const"),
|
||
|
__n, max_size ()));
|
||
|
|
||
|
if (size())
|
||
|
{
|
||
|
size_type __slen = size() -1;
|
||
|
size_type xpos_start = __pos < __slen ? __pos : __slen;
|
||
|
for (size_type xpos = xpos_start+1; xpos != 0 ; xpos--)
|
||
|
{
|
||
|
for(size_type __i = 0; __i < __n ; __i++)
|
||
|
if (traits_type::eq(_C_data[xpos-1], __s[__i]))
|
||
|
return xpos-1;
|
||
|
}
|
||
|
}
|
||
|
return npos;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
_TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
find_first_not_of (const_pointer __s, size_type __pos, size_type __n) const
|
||
|
{
|
||
|
_RWSTD_ASSERT(__s != 0);
|
||
|
|
||
|
_RWSTD_REQUIRES (__n <= max_size (),
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::find_first_not_of("
|
||
|
"const_pointer, size_type, size_type) const"),
|
||
|
__n, max_size ()));
|
||
|
|
||
|
for (size_type xpos = __pos; xpos < size() ; xpos++)
|
||
|
{
|
||
|
bool found = false;
|
||
|
for (size_type __i = 0; __i < __n ; __i++)
|
||
|
{
|
||
|
if (traits_type::eq(_C_data[xpos], __s[__i]))
|
||
|
{
|
||
|
found = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (!found)
|
||
|
return xpos;
|
||
|
}
|
||
|
|
||
|
return npos;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
_TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
find_last_not_of(const_pointer __s, size_type __pos, size_type __n) const
|
||
|
{
|
||
|
_RWSTD_ASSERT(__s != 0);
|
||
|
|
||
|
_RWSTD_REQUIRES (__n <= max_size (),
|
||
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
||
|
_RWSTD_FUNC ("basic_string::find_last_not_of("
|
||
|
"const_pointer, size_type, size_type) const"),
|
||
|
__n, max_size ()));
|
||
|
|
||
|
if (size())
|
||
|
{
|
||
|
size_type __slen = size() -1;
|
||
|
size_type xpos_start = __pos < __slen ? __pos : __slen;
|
||
|
for (size_type xpos = xpos_start+1; xpos != 0 ; xpos--)
|
||
|
{
|
||
|
bool found = false;
|
||
|
for (size_type __i = 0; __i < __n ; __i++)
|
||
|
{
|
||
|
if (traits_type::eq(_C_data[xpos-1], __s[__i]))
|
||
|
{
|
||
|
found = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (!found)
|
||
|
return xpos-1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return npos;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>
|
||
|
basic_string<_CharT, _Traits, _Allocator>::
|
||
|
substr (size_type __pos, size_type __n) const
|
||
|
{
|
||
|
_RWSTD_REQUIRES (__pos <= size (),
|
||
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
||
|
_RWSTD_FUNC ("basic_string::substr(size_type, size_type) "
|
||
|
"const"), __pos, size ()));
|
||
|
|
||
|
size_type __slen = size() -__pos;
|
||
|
size_type __rlen = __n < __slen ? __n : __slen;
|
||
|
return basic_string (_C_data + __pos, __rlen);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
int basic_string<_CharT, _Traits, _Allocator>::
|
||
|
compare (size_type __pos1, size_type __n1,
|
||
|
const basic_string& __str,
|
||
|
size_type __pos2, size_type __n2) const
|
||
|
{
|
||
|
_RWSTD_REQUIRES (__pos2 <= __str.size (),
|
||
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
||
|
_RWSTD_FUNC ("basic_string::compare(size_type, size_type,"
|
||
|
"const basic_string&, size_type, size_type) "
|
||
|
"const"), __pos2, __str.size ()));
|
||
|
|
||
|
// "reduce" __n2 if necessary, where
|
||
|
// "reduce" := Ensure __pos2+__n2 < __str.size() so we can call a function that
|
||
|
// doesn't check this same inequality.
|
||
|
|
||
|
if(__str.size() - __pos2 < __n2)
|
||
|
__n2 = __str.size() - __pos2;
|
||
|
|
||
|
// compare(size_type, size_type, char*, size_type) will both
|
||
|
// (i) check pos1 to make sure it's less than size() and
|
||
|
// (ii) "reduce" __n1 if necessary
|
||
|
|
||
|
return compare(__pos1, __n1, __str.c_str()+__pos2, __n2);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class _CharT, class _Traits, class _Allocator>
|
||
|
int basic_string<_CharT, _Traits, _Allocator>::
|
||
|
compare (size_type __pos, size_type __n1,
|
||
|
const_pointer __s, size_type __n2) const
|
||
|
{
|
||
|
_RWSTD_REQUIRES (__pos <= size (),
|
||
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
||
|
_RWSTD_FUNC ("basic_string::compare(size_type, size_type,"
|
||
|
" const const_pointer, size_type) const"),
|
||
|
__pos, size ()));
|
||
|
|
||
|
if(size() - __pos < __n1)
|
||
|
__n1 = size() - __pos;
|
||
|
size_type __rlen = __n1 < __n2 ? __n1 : __n2;
|
||
|
int __res = traits_type::compare(_C_data+__pos,__s, __rlen);
|
||
|
|
||
|
if (__res == 0)
|
||
|
__res = (__n1 < __n2) ? -1 : (__n1 != __n2);
|
||
|
|
||
|
return __res;
|
||
|
}
|
||
|
|
||
|
|
||
|
_RWSTD_NAMESPACE_END // std
|
||
|
|