927 lines
32 KiB
C++
927 lines
32 KiB
C++
/***************************************************************************
|
|
*
|
|
* string.cc - definitions of the C++ Standard Library string members
|
|
*
|
|
* $Id: string.cc 651447 2008-04-24 22:50:34Z sebor $
|
|
*
|
|
***************************************************************************
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* permissions and limitations under the License.
|
|
*
|
|
* Copyright 1994-2008 Rogue Wave Software, Inc.
|
|
*
|
|
**************************************************************************/
|
|
|
|
#ifdef _MSC_VER
|
|
// shut up the dumb MSVC warning C4345:
|
|
// behavior change: an object with POD type constructed with
|
|
// an initializer of the form () will be default-initialized
|
|
# pragma warning (push)
|
|
# pragma warning (disable: 4345)
|
|
#endif // _MSC_VER
|
|
|
|
|
|
_RWSTD_NAMESPACE (std) {
|
|
|
|
|
|
#ifndef _RWSTD_NO_STATIC_CONST_MEMBER_INIT
|
|
# if !defined (_MSC_VER) || _MSC_VER > 1300 || defined (__INTEL_COMPILER)
|
|
// MSVC 7.0 allows initializers for static const integral members
|
|
// but out-of-line definitions cause multiply defined symbol errors
|
|
// (see PR #26562)
|
|
|
|
# ifndef _RWSTD_NO_STRING_NPOS_TYPE
|
|
|
|
template <class _CharT, class _Traits, class _Allocator>
|
|
const _TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type
|
|
basic_string<_CharT, _Traits, _Allocator>::
|
|
npos /* = SIZE_MAX */;
|
|
|
|
# else // if defined (_RWSTD_NO_STRING_NPOS_TYPE)
|
|
|
|
template <class _CharT, class _Traits, class _Allocator>
|
|
const _RWSTD_SIZE_T
|
|
basic_string<_CharT, _Traits, _Allocator>::
|
|
npos /* = SIZE_MAX */;
|
|
|
|
# endif // _RWSTD_NO_STRING_NPOS_TYPE
|
|
# endif // MSVC > 7.0
|
|
#endif // _RWSTD_NO_STATIC_CONST_MEMBER_INIT
|
|
|
|
|
|
#ifndef _RWSTD_NO_COLLAPSE_TEMPLATE_STATICS
|
|
|
|
template <class _CharT, class _Traits, class _Allocator>
|
|
_RW::__null_ref<_CharT, _Traits, _Allocator>
|
|
basic_string<_CharT, _Traits, _Allocator>::
|
|
_C_null_ref;
|
|
|
|
#endif // _RWSTD_NO_COLLAPSE_TEMPLATE_STATICS
|
|
|
|
|
|
template <class _CharT, class _Traits, class _Allocator>
|
|
_TYPENAME basic_string<_CharT, _Traits, _Allocator>::_C_string_ref_type*
|
|
basic_string<_CharT, _Traits, _Allocator>::
|
|
_C_get_rep (size_type __cap, size_type __len)
|
|
{
|
|
if (__cap > max_size ()) {
|
|
__cap = __len;
|
|
|
|
_RWSTD_REQUIRES (__cap <= max_size (),
|
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
|
_RWSTD_FUNC ("basic_string::_C_get_rep (size_type, "
|
|
"size_type)"),
|
|
__cap, max_size ()));
|
|
}
|
|
|
|
_RWSTD_REQUIRES (__len <= __cap,
|
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
|
_RWSTD_FUNC ("basic_string::_C_get_rep (size_type, "
|
|
"size_type)"),
|
|
__len, __cap));
|
|
|
|
if (!__cap) {
|
|
_RWSTD_ASSERT (!__len);
|
|
return _C_nullref ();
|
|
}
|
|
|
|
// allocate, initialize the __string_ref, and initialize each character
|
|
_C_string_ref_type* const __ret =
|
|
_RWSTD_STATIC_CAST (_C_string_ref_type*,
|
|
_RWSTD_STATIC_CAST (void*,
|
|
_RWSTD_VALUE_ALLOC (_C_value_alloc_type, *this,
|
|
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 ();
|
|
|
|
// set initial reference count, capacity, and length
|
|
__ret->_C_init (__cap, __len);
|
|
|
|
_RWSTD_VALUE_ALLOC (_C_value_alloc_type, *this,
|
|
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 () */)
|
|
: 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_get_rep (_C_grow (size_type (), __maxlen),
|
|
__rlen)->data ();
|
|
else
|
|
_C_data = _C_get_rep (__maxlen, __rlen)->data ();
|
|
|
|
traits_type::copy (_C_data, &__s._C_data [__pos], __rlen);
|
|
}
|
|
|
|
|
|
template <class _CharT, class _Traits, class _Allocator>
|
|
basic_string<_CharT, _Traits, _Allocator>::
|
|
basic_string (size_type __n, value_type __c,
|
|
const allocator_type &__alloc /* = allocator_type () */)
|
|
: allocator_type (__alloc)
|
|
{
|
|
_RWSTD_REQUIRES (__n <= max_size (),
|
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
|
_RWSTD_FUNC ("basic_string::basic_string (size_type, "
|
|
"value_type)"),
|
|
__n, max_size ()));
|
|
|
|
if (__n)
|
|
_C_data = _C_get_rep (_C_grow (size_type (), __n), __n)->data ();
|
|
else
|
|
_C_data = _C_nullref ()->data ();
|
|
|
|
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 () */)
|
|
: allocator_type (__alloc)
|
|
{
|
|
// extension: if `s' is 0 then `n' uninitialized 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_get_rep (_C_grow (size_type (), __n), __n)->data ()
|
|
: _C_nullref ()->data ();
|
|
|
|
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 () */)
|
|
: allocator_type (__alloc)
|
|
{
|
|
_RWSTD_ASSERT (__s != 0);
|
|
|
|
const size_type __n = traits_type::length (__s);
|
|
|
|
_C_data = __n ?
|
|
_C_get_rep (_C_grow (size_type (), __n), __n)->data ()
|
|
: _C_nullref ()->data ();
|
|
|
|
traits_type::copy (_C_data, __s, __n);
|
|
}
|
|
|
|
|
|
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 () */)
|
|
: allocator_type (__alloc)
|
|
{
|
|
const size_type __n = size_type (__last - __first);
|
|
|
|
_C_data = __n ?
|
|
_C_get_rep (_C_grow (size_type (), __n), __n)->data ()
|
|
: _C_nullref ()->data ();
|
|
|
|
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 (size_type (0) < size_type (__rhs._C_pref ()->_C_get_ref ())) {
|
|
// `rhs' has reference counting enabled
|
|
__rhs._C_pref ()->_C_inc_ref ();
|
|
_C_unlink (__rhs._C_data);
|
|
}
|
|
else if (this != &__rhs)
|
|
// `rhs' has reference counting disabled
|
|
replace (size_type (), size (), __rhs.data (), __rhs.size ());
|
|
|
|
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 ()));
|
|
|
|
const size_type __rlen = _C_min (__str.size () - __pos, __n);
|
|
|
|
return replace (size_type (), 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 ()));
|
|
|
|
const size_type __rlen = _C_min (__str.size () - __pos2, __n);
|
|
|
|
_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, size_type (), __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, size_type (), __str);
|
|
}
|
|
|
|
|
|
template <class _CharT, class _Traits, class _Allocator>
|
|
basic_string<_CharT, _Traits, _Allocator>&
|
|
basic_string<_CharT, _Traits, _Allocator>::
|
|
replace (size_type __pos1, size_type __n1, const_pointer __s, size_type __n2)
|
|
{
|
|
const size_type __size0 = size ();
|
|
|
|
if (npos == __n2)
|
|
__n2 = traits_type::length (__s);
|
|
|
|
_RWSTD_REQUIRES (__pos1 <= __size0,
|
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
|
_RWSTD_FUNC ("basic_string::replace (size_type, size_type"
|
|
", const_pointer, size_type)"),
|
|
__pos1, __size0 > __n2 ? __size0 : __n2));
|
|
|
|
// number of characters to delete
|
|
const size_type __xlen = _C_min (__n1, __size0 - __pos1);
|
|
|
|
_RWSTD_REQUIRES (__n2 <= max_size (),
|
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
|
_RWSTD_FUNC ("basic_string::replace (size_type, size_type"
|
|
", const_pointer, size_type)"),
|
|
__n2, max_size ()));
|
|
|
|
_RWSTD_REQUIRES (__size0 - __xlen <= max_size () - __n2,
|
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
|
_RWSTD_FUNC ("basic_string::replace (size_type, size_type"
|
|
", const_pointer, size_type)"),
|
|
__size0 - __xlen, max_size () - __n2));
|
|
|
|
// compute the resulting string size
|
|
const size_type __size1 = __size0 - __xlen + __n2;
|
|
|
|
if (__size1) {
|
|
|
|
// compute the length of the bit at the end
|
|
const size_type __rem = __size0 - __xlen - __pos1;
|
|
|
|
// check for shared representation, insufficient capacity,
|
|
// and overlapping regions
|
|
if ( size_type (1) < size_type (_C_pref ()->_C_get_ref ())
|
|
|| capacity () < __size1
|
|
|| __s >= data () && __s < data () + __size0) {
|
|
|
|
// Need to allocate a new reference.
|
|
const size_type __cap = _C_grow (__size0, __size1);
|
|
|
|
const pointer __data = _C_get_rep (__cap, __size1)->data ();
|
|
|
|
traits_type::copy (__data, _C_data, __pos1);
|
|
|
|
traits_type::copy (__data + __pos1, __s, __n2);
|
|
|
|
traits_type::copy (__data + __pos1 + __n2,
|
|
_C_data + __pos1 + __n1, __rem);
|
|
|
|
_C_unlink (__data);
|
|
}
|
|
else {
|
|
// current reference has enough space
|
|
|
|
const pointer __beg = _C_data + __pos1;
|
|
|
|
traits_type::move (__beg + __n2, __beg + __n1, __rem);
|
|
|
|
traits_type::copy (__beg, __s, __n2);
|
|
|
|
traits_type::assign (_C_data [__size1], value_type ());
|
|
|
|
_C_pref ()->_C_size._C_size = __size1;
|
|
}
|
|
}
|
|
else {
|
|
// special case a substitution that leaves the string empty.
|
|
clear ();
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
template <class _CharT, class _Traits, class _Allocator>
|
|
basic_string<_CharT, _Traits, _Allocator>&
|
|
basic_string<_CharT, _Traits, _Allocator>::
|
|
replace (size_type __pos, size_type __len, size_type __count, value_type __val)
|
|
{
|
|
// replaces `len' characters at position `pos'
|
|
// with `count' copies of the character `val'
|
|
|
|
const size_type __size0 = size ();
|
|
|
|
_RWSTD_REQUIRES (__pos <= __size0,
|
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
|
_RWSTD_FUNC ("basic_string::replace (size_type, "
|
|
"size_type, size_type, value_type)"),
|
|
__pos, __size0));
|
|
|
|
const size_type __xlen = _C_min (__size0 - __pos, __len);
|
|
|
|
_RWSTD_REQUIRES (__size0 - __xlen <= max_size () - __count,
|
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
|
_RWSTD_FUNC ("basic_string::replace (size_type, "
|
|
"size_type, size_type, value_type)"),
|
|
__size0 - __xlen, max_size () - __count));
|
|
|
|
// compute the resulting string size
|
|
const size_type __size1 = __size0 - __xlen + __count;
|
|
|
|
if (__size1) {
|
|
|
|
// compute the length of the bit at the end
|
|
const size_type __rem = __size0 - __xlen - __pos;
|
|
|
|
// check for shared representation, insufficient capacity
|
|
if ( capacity () < __size1
|
|
|| size_type (1) < size_type (_C_pref ()->_C_get_ref ())) {
|
|
|
|
// need to allocate a new reference
|
|
const size_type __cap = _C_grow (__size0, __size1);
|
|
|
|
const pointer __data = _C_get_rep (__cap, __size1)->data ();
|
|
|
|
traits_type::copy (__data, _C_data, __pos);
|
|
|
|
traits_type::assign (__data + __pos, __count, __val);
|
|
|
|
traits_type::copy (__data + (__pos + __count),
|
|
_C_data + (__pos + __len), __rem);
|
|
|
|
_C_unlink (__data);
|
|
}
|
|
else {
|
|
// current reference is not shared and has enough space
|
|
|
|
const pointer __beg = _C_data + __pos;
|
|
|
|
traits_type::move (__beg + __count, __beg + __len, __rem);
|
|
|
|
traits_type::assign (__beg, __count, __val);
|
|
|
|
// append the terminating NUL character
|
|
traits_type::assign (_C_data [__size1], value_type ());
|
|
|
|
_C_pref ()->_C_size._C_size = __size1;
|
|
}
|
|
}
|
|
else {
|
|
// special case a substitution that leaves the string empty.
|
|
clear ();
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
|
|
|
|
# ifdef _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
|
|
|
|
_EXPORT
|
|
template <class _CharT, class _Traits, class _Alloc,
|
|
class _StringIter, class _InputIter>
|
|
_STD::basic_string<_CharT, _Traits, _Alloc>&
|
|
__rw_replace (_STD::basic_string<_CharT, _Traits, _Alloc> &__s,
|
|
_StringIter __first1, _StringIter __last1,
|
|
_InputIter __first2, _InputIter __last2) {
|
|
|
|
typedef _Traits traits_type;
|
|
typedef _TYPENAME traits_type::char_type value_type;
|
|
typedef _Alloc allocator_type;
|
|
typedef _TYPENAME allocator_type::size_type size_type;
|
|
|
|
typedef _STD::basic_string<_CharT, _Traits, _Alloc> _C_string_type;
|
|
|
|
typedef _RW::__string_ref<value_type, traits_type, allocator_type>
|
|
_C_string_ref_type;
|
|
|
|
|
|
# else // !defined (_RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES)
|
|
|
|
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, void*)
|
|
{
|
|
typedef basic_string _C_string_type;
|
|
|
|
basic_string &__s = *this;
|
|
|
|
# endif // _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
|
|
|
|
_RWSTD_ASSERT_RANGE (__first1,
|
|
__s._C_make_iter (__s._C_data + __s.size ()));
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
if (__first2 == __last2) {
|
|
if (__first1 == __last1)
|
|
return __s;
|
|
|
|
const size_type __pos = __s._C_off (__first1);
|
|
const size_type __n = __s._C_off (__first1, __last1);
|
|
return __s.replace (__pos, __n, size_type (), value_type ());
|
|
}
|
|
|
|
// use a (probably) faster algorithm if possible
|
|
if (_STD::__is_bidirectional_iterator (_RWSTD_ITERATOR_CATEGORY(_InputIter,
|
|
__last2)))
|
|
return __s.__replace_aux (__first1, __last1, __first2, __last2);
|
|
|
|
_C_string_type __s3;
|
|
_TYPENAME _C_string_type::iterator __first3 = __s3.begin ();
|
|
|
|
for ( ; !(__first2 == __last2); ++__first2, ++__first3) {
|
|
|
|
const size_type __off = __s3._C_off (__first3);
|
|
|
|
_RWSTD_REQUIRES (__off <= __s3.max_size (),
|
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
|
_RWSTD_FUNC ("basic_string::replace (iterator, "
|
|
"iterator, InputIterator, "
|
|
"InputIterator)"),
|
|
__s3._C_off (__first3), __s3.max_size ()));
|
|
|
|
// extend the string if necessary
|
|
if (__s3.end () == __first3) {
|
|
// compute the size of new buffer
|
|
const size_type __cap = __s3._C_grow (__s3.size (), size_type ());
|
|
|
|
// allocate a new buffer
|
|
_C_string_ref_type *__tmp = __s3._C_get_rep (__cap, __cap);
|
|
|
|
// copy data from old to new, leaving a hole for additions
|
|
traits_type::copy (__tmp->data (), __s3._C_data, __off);
|
|
__s3._C_unlink (__tmp->data ());
|
|
__first3 = __s3._C_make_iter (__s3._C_data + __off);
|
|
}
|
|
|
|
// copy data over
|
|
traits_type::assign (*__first3, *__first2);
|
|
}
|
|
|
|
const size_type __size = __s3._C_off (__first3);
|
|
traits_type::assign (__s3._C_data [__size], value_type ());
|
|
__s3._C_pref ()->_C_size._C_size = __size;
|
|
|
|
return __s.__replace_aux (__first1, __last1, __s3.begin (), __s3.end ());
|
|
}
|
|
|
|
// 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.
|
|
|
|
# ifdef _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
|
|
|
|
_EXPORT
|
|
template <class _CharT, class _Traits, class _Alloc,
|
|
class _StringIter, class _InputIter>
|
|
_STD::basic_string<_CharT, _Traits, _Alloc>&
|
|
__rw_replace_aux (_STD::basic_string<_CharT, _Traits, _Alloc> &__s,
|
|
_StringIter __first1, _StringIter __last1,
|
|
_InputIter __first2, _InputIter __last2)
|
|
{
|
|
typedef _Traits traits_type;
|
|
typedef _TYPENAME traits_type::char_type value_type;
|
|
typedef _Alloc allocator_type;
|
|
typedef _TYPENAME allocator_type::size_type size_type;
|
|
typedef _TYPENAME allocator_type::difference_type difference_type;
|
|
typedef _TYPENAME allocator_type::pointer pointer;
|
|
typedef _TYPENAME allocator_type::const_pointer const_pointer;
|
|
typedef _TYPENAME allocator_type::const_reference const_reference;
|
|
|
|
typedef _RW::__string_ref<value_type, traits_type, allocator_type>
|
|
_C_string_ref_type;
|
|
|
|
# else // if !defined (_RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES)
|
|
|
|
template<class _CharT, class _Traits, class _Allocator>
|
|
template<class _InputIter>
|
|
basic_string<_CharT, _Traits, _Allocator>&
|
|
basic_string<_CharT, _Traits, _Allocator>::
|
|
__replace_aux (iterator __first1, iterator __last1,
|
|
_InputIter __first2, _InputIter __last2)
|
|
{
|
|
basic_string &__s = *this;
|
|
|
|
# endif // _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
|
|
|
|
_RWSTD_ASSERT_RANGE (__first1, __s._C_make_iter (__s._C_data
|
|
+ __s.size ()));
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
const size_type __n2 = _DISTANCE (__first2, __last2, size_type);
|
|
const size_type __n = __s._C_off (__first1, __last1);
|
|
const size_type __pos = __s._C_off (__first1);
|
|
const size_type __ssize = __s.size ();
|
|
|
|
_RWSTD_REQUIRES (__pos <= __ssize,
|
|
(_RWSTD_ERROR_OUT_OF_RANGE,
|
|
_RWSTD_FUNC ("basic_string::__replace_aux (iterator, "
|
|
"iterator, InputIterator, InputIterator)"),
|
|
__pos, __ssize));
|
|
|
|
size_type __slen = __ssize - __pos;
|
|
size_type __xlen = __n < __slen ? __n : __slen;
|
|
|
|
_RWSTD_REQUIRES (__ssize - __xlen <= __s.max_size () - __n2,
|
|
(_RWSTD_ERROR_LENGTH_ERROR,
|
|
_RWSTD_FUNC ("basic_string::__replace_aux (iterator, "
|
|
"iterator, InputIterator, InputIterator)"),
|
|
__ssize - __xlen, __s.max_size () - __n2));
|
|
|
|
size_type __len = __ssize - __xlen + __n2; // Final string length.
|
|
|
|
if (!__len) {
|
|
// Special case a substitution that leaves the string empty.
|
|
__s._C_unlink (__s._C_nullref ()->data ());
|
|
}
|
|
else {
|
|
size_type __d = 0;
|
|
// length of bit at the end
|
|
size_type __rem = __ssize - __xlen - __pos;
|
|
// Check for shared representation, insufficient capacity
|
|
if ( __s.capacity () < __len
|
|
|| size_type (1) < size_type (__s._C_pref ()->_C_get_ref ()))
|
|
{
|
|
// Need to allocate a new reference.
|
|
const size_type __cap = __s._C_grow (__ssize, __len);
|
|
|
|
_C_string_ref_type * __temp = __s._C_get_rep (__cap, __len);
|
|
if (__pos)
|
|
traits_type::copy (__temp->data (), __s._C_data, __pos);
|
|
for (__d = 0; __d < __n2; __d++)
|
|
traits_type::assign (*(__temp->data ()+__pos + __d),
|
|
*__first2++);
|
|
if (__rem)
|
|
traits_type::copy (__temp->data () + __pos + __n2,
|
|
__s._C_data + __pos + __n, __rem);
|
|
__s._C_unlink (__temp->data ());
|
|
}
|
|
else {
|
|
// Current reference has enough room.
|
|
if (__rem)
|
|
traits_type::move (__s._C_data + __pos + __n2,
|
|
__s._C_data + __pos + __n,
|
|
__rem);
|
|
|
|
for (__d = 0; __d < __n2; __d++)
|
|
traits_type::assign (*(__s._C_data + __pos + __d),
|
|
*__first2++);
|
|
|
|
__s._C_pref ()->_C_size._C_size = __len;
|
|
traits_type::assign (__s._C_data [__len], value_type ());
|
|
}
|
|
}
|
|
return __s;
|
|
}
|
|
|
|
#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 ()));
|
|
|
|
const size_type __rlen = _C_min (size () - __pos, __n);
|
|
|
|
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 __seq, size_type __off, size_type __len) const
|
|
{
|
|
const size_type __size = size ();
|
|
|
|
if (__size < __off)
|
|
return npos;
|
|
|
|
_RWSTD_ASSERT (__seq != 0 || __len == 0);
|
|
|
|
const const_pointer __end = _C_data + __size;
|
|
const const_pointer __seq_end = __seq + __len;
|
|
|
|
// `first' is set to point to the first occurrence of the first
|
|
// element of the sought sequence in the controlling sequence
|
|
// if one exists, otherwise to 0
|
|
const_pointer __first = const_pointer ();
|
|
|
|
for (const_pointer __next = _C_data + __off; ; __next = __first) {
|
|
|
|
// compute the legth of the rest of the controlling sequene
|
|
// and break out when it's shorter than the sought sequence
|
|
const size_type __ext = size_type (__end - __next);
|
|
|
|
if (__ext < __len)
|
|
break;
|
|
|
|
__first = const_pointer ();
|
|
|
|
for (const_pointer __n = __next, __s = __seq; ; ++__n, ++__s) {
|
|
|
|
if (__seq_end == __s)
|
|
return size_type (__next - _C_data);
|
|
|
|
if (traits_type::eq (*__n, *__s)) {
|
|
if (__next != __first && traits_type::eq (*__n, *__seq))
|
|
__first = __n + 1;
|
|
}
|
|
else {
|
|
if (const_pointer () == __first) {
|
|
// look for the first occurrence of the first element
|
|
// of the sought sequence in the rest of the cotrolling
|
|
// sequence
|
|
__first = traits_type::find (__next + 1, __ext - 1, *__seq);
|
|
|
|
if (const_pointer () == __first)
|
|
return npos;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
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 ()));
|
|
|
|
if (__str.size () - __pos2 < __n2)
|
|
__n2 = __str.size () - __pos2;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
} // namespace std
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
# pragma warning (pop)
|
|
#endif // _MSC_VER
|