1011 lines
34 KiB
C++
1011 lines
34 KiB
C++
#ifndef __STRING_CC
|
||
#define __STRING_CC
|
||
#pragma option push -b -a8 -pc -Vx- -Ve- -w-inl -w-aus -w-sig
|
||
/***************************************************************************
|
||
*
|
||
* string.cc - Definitions for the Standard Library string classes
|
||
*
|
||
***************************************************************************
|
||
*
|
||
* Copyright (c) 1994-1999 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.
|
||
*
|
||
**************************************************************************/
|
||
#include <stdcomp.h>
|
||
|
||
//
|
||
// Members for class basic_string
|
||
//
|
||
|
||
#ifndef _RWSTD_NO_NAMESPACE
|
||
namespace std {
|
||
#endif
|
||
|
||
// basic_string<...>::__nullref
|
||
#ifndef _RWSTD_NO_STATIC_DEF3
|
||
template <class charT, class traits, class Allocator >
|
||
const _TYPENAME basic_string<charT, traits, Allocator>::__null_ref_type
|
||
basic_string<charT, traits, Allocator>::__nullref;
|
||
#endif
|
||
// basic_string<...>::npos
|
||
#if defined(__BORLANDC__) && !defined(_RTLDLL)
|
||
#ifdef _RWSTD_MSC22_STATIC_INIT_BUG
|
||
#define npos (size_type)-1
|
||
#else
|
||
template <class charT, class traits, class Allocator >
|
||
const _TYPENAME basic_string<charT, traits, Allocator>::size_type
|
||
basic_string<charT, traits, Allocator>::npos
|
||
#ifdef _RWSTD_NO_STATIC_CAST
|
||
= (_TYPENAME basic_string<charT, traits, Allocator>::size_type) -1;
|
||
#else
|
||
= static_cast</* _TYPENAME */ basic_string<charT, traits, Allocator>::size_type>(-1); // RW_BUG
|
||
#endif
|
||
|
||
#endif /* __BORLANDC__ && !_RTLDLL */
|
||
#endif /*_RWSTD_MSC22_STATIC_INIT_BUG*/
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
_TYPENAME basic_string<charT, traits, Allocator>::__string_ref_type *
|
||
basic_string<charT, traits, Allocator>::__getRep (size_type capac,
|
||
size_type nchar)
|
||
|
||
{
|
||
if (capac < nchar)
|
||
capac = nchar;
|
||
|
||
if ((capac | nchar) == 0)
|
||
{
|
||
__getNullRep()->__addReference();
|
||
return __getNullRep();
|
||
}
|
||
|
||
//
|
||
// Allocate, then initialize the __string_ref, then
|
||
// initialize each character in the buffer.
|
||
//
|
||
__value_alloc_type va(__data_);
|
||
#ifdef _RWSTD_NO_STATIC_CAST
|
||
__string_ref_type * ret = (__string_ref_type *)
|
||
va.allocate(capac + sizeof(__rep_type)/sizeof(charT) + 2,0);
|
||
#else
|
||
__string_ref_type * ret =
|
||
reinterpret_cast<__string_ref_type*>
|
||
(va.allocate(capac + sizeof(__rep_type)/sizeof(charT) + 2,0));
|
||
#endif
|
||
|
||
__ref_alloc_type(__data_).construct(ret, __string_ref_type());
|
||
charT * d = ret->data();
|
||
va.construct(d,charT());
|
||
|
||
ret->__capacity_ = capac;
|
||
ret->__setRefCount(1);
|
||
ret->data()[ret->__nchars_ = nchar] = (charT)0; // Terminating null
|
||
return ret;
|
||
}
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
basic_string<charT, traits, Allocator>::basic_string (
|
||
const basic_string<charT, traits, Allocator> & s,
|
||
size_type pos, size_type n,
|
||
const Allocator& alloc)
|
||
: __data_(0,alloc)
|
||
{
|
||
_RWSTD_THROW(pos > s.length(), out_of_range,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
|
||
"basic_string( const basic_string&,size_type,size_type)", pos,s.length()).msgstr());
|
||
|
||
size_type slen = s.length() - pos;
|
||
size_type rlen = n < slen ? n : slen;
|
||
size_type nlen = n == npos ? 0 : n;
|
||
size_type maxlen = nlen > rlen ? nlen : rlen;
|
||
__data_ = __getRep(maxlen, rlen)->data();
|
||
|
||
traits::copy(__data_.data(), &s.__data_.data()[pos], rlen);
|
||
}
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
void basic_string<charT, traits, Allocator>::__initn (
|
||
size_type n,
|
||
charT c)
|
||
{
|
||
_RWSTD_THROW(n == npos, length_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_InvalidSizeParam,
|
||
"basic_string::__initn(size_t,char)", n,npos).msgstr());
|
||
|
||
__data_ = __getRep(n, n)->data();
|
||
|
||
while (n--) traits::assign(__data_.data()[n], c);
|
||
}
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
basic_string<charT, traits, Allocator>::basic_string (
|
||
const charT* s,
|
||
size_type n,
|
||
const Allocator& alloc)
|
||
: __data_(0,alloc)
|
||
{
|
||
_RWSTD_THROW(s == 0, logic_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
|
||
"basic_string( const charT*,size_type,const Allocator&)").msgstr());
|
||
|
||
_RWSTD_THROW(n == npos, length_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_InvalidSizeParam,
|
||
"basic_string( const charT*,size_type,const Allocator&)",n,npos).msgstr());
|
||
|
||
__data_ = __getRep(n, n)->data();
|
||
traits::copy(__data_.data(), s, n);
|
||
}
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
basic_string<charT, traits, Allocator>::basic_string (
|
||
const charT* s,
|
||
const Allocator& alloc)
|
||
: __data_(0,alloc)
|
||
{
|
||
_RWSTD_THROW(s == 0, logic_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
|
||
"basic_string(const charT*,const Allocator&)").msgstr());
|
||
|
||
size_type len = traits::length(s);
|
||
__data_ = __getRep(len, len)->data();
|
||
|
||
traits::copy(__data_.data(), s, len);
|
||
}
|
||
|
||
#ifdef _RWSTD_NO_DEFAULT_TEMPLATE_ARGS
|
||
template <class charT, class traits, class Allocator >
|
||
basic_string<charT, traits, Allocator>::basic_string (
|
||
const charT* s,
|
||
size_type n)
|
||
: __data_(0,Allocator())
|
||
{
|
||
_RWSTD_THROW(s == 0, logic_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
|
||
"basic_string( const charT*,size_type)").msgstr());
|
||
|
||
_RWSTD_THROW(n == npos, length_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_InvalidSizeParam,
|
||
"basic_string(const charT*,size_type)",n,npos).msgstr());
|
||
|
||
__data_ = __getRep(n, n)->data();
|
||
|
||
traits::copy(__data_.data(), s, n);
|
||
}
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
basic_string<charT, traits, Allocator>::basic_string (
|
||
const charT* s)
|
||
: __data_(0,Allocator())
|
||
{
|
||
_RWSTD_THROW(s == 0, logic_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
|
||
"basic_string(const charT*)").msgstr());
|
||
|
||
size_type len = traits::length(s);
|
||
__data_ = __getRep(len, len)->data();
|
||
|
||
traits::copy(__data_.data(), s, len);
|
||
}
|
||
#endif
|
||
|
||
#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 &alloc)
|
||
: __data_(0,alloc)
|
||
{
|
||
__data_ = __getRep(1,0)->data();
|
||
replace(__data_.data(),__data_.data(),first,last);
|
||
}
|
||
#endif /* _RWSTD_NO_MEMBER_TEMPLATES */
|
||
|
||
template <class charT, class traits , class Allocator >
|
||
basic_string<charT, traits, Allocator>::basic_string (const charT* first,
|
||
const charT* last,
|
||
const Allocator& alloc)
|
||
: __data_(0,alloc)
|
||
{
|
||
__data_ = __getRep(last-first,0)->data();
|
||
replace(0,0,first,last-first,0,last-first);
|
||
}
|
||
|
||
#ifdef _RWSTD_NO_DEFAULT_TEMPLATE_ARGS
|
||
template <class charT, class traits , class Allocator >
|
||
basic_string<charT, traits, Allocator>::basic_string (const charT* first,
|
||
const charT* last)
|
||
: __data_(0,Allocator())
|
||
{
|
||
__data_ = __getRep(last-first,0)->data();
|
||
replace(0,0,first,last-first,0,last-first);
|
||
}
|
||
#endif /* _RWSTD_NO_DEFAULT_TEMPLATE_ARGS */
|
||
template <class charT, class traits, class Allocator >
|
||
basic_string<charT, traits, Allocator> &
|
||
basic_string<charT, traits, Allocator>::operator= (
|
||
const basic_string<charT, traits, Allocator>& str)
|
||
{
|
||
if (this != &str)
|
||
{
|
||
if (str.__pref()->__references() > 0)
|
||
{
|
||
str.__pref()->__addReference();
|
||
__unLink();
|
||
__data_ = str.__data_.data();
|
||
}
|
||
else
|
||
this->operator=(str.c_str());
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
basic_string<charT, traits, Allocator> &
|
||
basic_string<charT, traits, Allocator>::operator= (const charT* s)
|
||
{
|
||
_RWSTD_THROW(s == 0, logic_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
|
||
"basic_string::operator= (const charT*)").msgstr());
|
||
|
||
if (traits::eq(*s, __eos()))
|
||
{
|
||
if (__pref()->__references() == 1)
|
||
{
|
||
__pref()->__nchars_ = 0;
|
||
traits::assign(__data_.data()[0], __eos());
|
||
}
|
||
else
|
||
{
|
||
__unLink();
|
||
__getNullRep()->__addReference();
|
||
__data_ = __getNullRep()->data();
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
return replace(0, length(), s, traits::length(s));
|
||
}
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
basic_string<charT, traits, Allocator> &
|
||
basic_string<charT, traits, Allocator>::append (
|
||
const basic_string<charT, traits, Allocator>& str,
|
||
size_type pos,
|
||
size_type n)
|
||
{
|
||
_RWSTD_THROW(pos > str.length(), out_of_range,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
|
||
"basic_string::append(basic_string&,size_type,size_type)", pos,str.length()).msgstr());
|
||
|
||
size_type slen = str.length() - pos;
|
||
size_type rlen = n < slen ? n : slen;
|
||
|
||
_RWSTD_THROW(length() >= npos - rlen, length_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
|
||
"basic_string::append(const basic_string&,size_type,size_type)",
|
||
length(),npos-rlen).msgstr());
|
||
|
||
replace(length(), 0, str.data(), str.length(), pos, n);
|
||
|
||
return *this;
|
||
}
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
basic_string<charT, traits, Allocator> &
|
||
basic_string<charT, traits, Allocator>::append (
|
||
const basic_string<charT, traits, Allocator>& str)
|
||
{
|
||
_RWSTD_THROW(length() >= npos - str.length(), length_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
|
||
"basic_string::append(const basic_string&)",length(),str.length()).msgstr());
|
||
|
||
replace(length(), 0, str.data(), str.length());
|
||
|
||
return *this;
|
||
}
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
basic_string<charT, traits, Allocator> &
|
||
basic_string<charT, traits, Allocator>::assign (
|
||
const basic_string<charT, traits, Allocator>& str,
|
||
size_type pos,
|
||
size_type n)
|
||
{
|
||
_RWSTD_THROW(pos > str.length(), out_of_range,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
|
||
"basic_string::assign(basic_string&,size_type,size_type)", pos,str.length()).msgstr());
|
||
|
||
size_type slen = str.length() - pos;
|
||
size_type rlen = n < slen ? n : slen;
|
||
return replace(0, length(), str, pos, rlen);
|
||
}
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
basic_string<charT, traits, Allocator> &
|
||
basic_string<charT, traits, Allocator>::assign (
|
||
const basic_string<charT, traits, Allocator>& str)
|
||
{
|
||
return replace(0, length(), str);
|
||
}
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
basic_string<charT, traits, Allocator> &
|
||
basic_string<charT, traits, Allocator>::insert (
|
||
size_type pos1,
|
||
const basic_string<charT, traits, Allocator>& str,
|
||
size_type pos2,
|
||
size_type n)
|
||
{
|
||
_RWSTD_THROW(pos1 > length() || pos2 > str.length(), out_of_range,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
|
||
"basic_string::insert(size_t,const basic_string&,size_t,size_t)",
|
||
pos1 > length() ? pos1:pos2,str.length()).msgstr());
|
||
|
||
size_type slen = str.length() - pos2;
|
||
size_type rlen = n < slen ? n : slen;
|
||
|
||
_RWSTD_THROW( length() >= npos - rlen, length_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
|
||
"basic_string::insert(size_t,const basic_string&,size_t,size_t)",
|
||
length(),npos - rlen).msgstr());
|
||
|
||
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<charT, traits, Allocator>& str)
|
||
{
|
||
_RWSTD_THROW(pos1 > length(), out_of_range,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
|
||
"basic_string::insert(size_t,const basic_string&)",pos1,length()).msgstr());
|
||
|
||
_RWSTD_THROW(length() >= npos - str.length(), length_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
|
||
"basic_string::insert(size_t,const basic_string&)",
|
||
length(), npos - str.length()).msgstr());
|
||
|
||
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 charT* cs,
|
||
size_type cslen,
|
||
size_type pos2,
|
||
size_type n2)
|
||
{
|
||
_RWSTD_THROW(pos1 > length() || pos2 > cslen, out_of_range,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
|
||
"basic_string::replace(size_t,size_t,char*,size_t,size_t,size_t)",
|
||
pos1 > length() ? pos1:pos2,length() > cslen ? length():cslen).msgstr());
|
||
|
||
size_type slen = length() - pos1;
|
||
size_type xlen = n1 < slen ? n1 : slen;
|
||
size_type clen = cslen - pos2;
|
||
size_type rlen = n2 < clen ? n2 : clen;
|
||
|
||
_RWSTD_THROW(length() - xlen >= npos - rlen, length_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
|
||
"basic_string::replace(size_t,size_t,char*,size_t,size_t,size_t)",
|
||
length()-xlen,npos - rlen).msgstr());
|
||
|
||
size_type tot = length() - xlen + rlen; // Final string length.
|
||
|
||
if (!tot)
|
||
{
|
||
// Special case a substitution that leaves the string empty.
|
||
__unLink();
|
||
__getNullRep()->__addReference();
|
||
__data_ = __getNullRep()->data();
|
||
}
|
||
else
|
||
{
|
||
size_type rem = length() - xlen - pos1; // Length of bit at end of string
|
||
// Check for shared representation, insufficient capacity,
|
||
// or overlap copy.
|
||
if ( (__pref()->__references() > 1)
|
||
|| (__getCapac() < tot)
|
||
|| (cs && (cs >= data() && cs < data()+length())))
|
||
{
|
||
// Need to allocate a new reference.
|
||
__string_ref_type * temp = __getRep(tot,tot);
|
||
if (pos1) traits::copy(temp->data(), __data_.data(), pos1);
|
||
if (rlen) traits::copy(temp->data()+pos1, cs+pos2, rlen);
|
||
if (rem ) traits::copy(temp->data()+pos1+rlen, __data_.data()+pos1+n1, rem);
|
||
__unLink();
|
||
__data_ = temp->data();
|
||
}
|
||
else
|
||
{
|
||
// Current reference has enough room.
|
||
if (rem) traits::move(__data_.data()+pos1+rlen, __data_.data()+pos1+n1, rem);
|
||
if (rlen) traits::move(__data_.data()+pos1, cs+pos2, rlen);
|
||
__data_.data()[__pref()->__nchars_ = tot] = __eos(); // Add terminating null
|
||
}
|
||
}
|
||
return __data_.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,
|
||
charT c)
|
||
{
|
||
_RWSTD_THROW(pos > length(), out_of_range,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
|
||
"basic_string:::replace(size_t,size_t,size_t,char)", pos,length()).msgstr());
|
||
|
||
size_type slen = length() - pos;
|
||
size_type xlen = n < slen ? n : slen;
|
||
|
||
_RWSTD_THROW(length() - xlen >= npos - n2, length_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
|
||
"basic_string::replace(size_t,size_t,size_t,char)",
|
||
length()-xlen,npos - n2).msgstr());
|
||
|
||
size_type tot = length() - xlen + n2; // Final string length.
|
||
|
||
if (!tot)
|
||
{
|
||
// Special case a substitution that leaves the string empty.
|
||
__unLink();
|
||
__getNullRep()->__addReference();
|
||
__data_ = __getNullRep()->data();
|
||
}
|
||
else
|
||
{
|
||
size_type rem = length() - xlen - pos; // Length of bit at end of string
|
||
// Check for shared representation, insufficient capacity,
|
||
if ( (__pref()->__references() > 1) || (__getCapac() < tot))
|
||
{
|
||
// Need to allocate a new reference.
|
||
__string_ref_type * temp = __getRep(tot,tot);
|
||
if (pos) traits::copy(temp->data(), __data_.data(), pos);
|
||
if (n2) traits::assign(temp->data()+pos, n2,c);
|
||
if (rem ) traits::copy(temp->data()+pos+n2, __data_.data()+pos+n, rem);
|
||
__unLink();
|
||
__data_ = temp->data();
|
||
}
|
||
else
|
||
{
|
||
// Current reference has enough room.
|
||
if (rem) traits::move(__data_.data()+pos+n2, __data_.data()+pos+n, rem);
|
||
if (n2) traits::assign(__data_.data()+pos, n2, c);
|
||
__data_.data()[__pref()->__nchars_ = tot] = __eos(); // Add terminating null
|
||
}
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
|
||
|
||
// Since we have no way of knowing how much is out there
|
||
// between first2 and last2 we have to allocate some space
|
||
// in chunks as needed and copy over characters in groups
|
||
// until we reach the end of the range. After that
|
||
// we can tidy things up. We avoid this using replace_aux
|
||
// any time we have an InputIterator capable of giving us
|
||
// the distance information we need. If InputIterator
|
||
// is really a charT* then we should never even get here.
|
||
template<class charT, class traits , class Allocator >
|
||
template<class InputIterator>
|
||
inline basic_string<charT, traits, Allocator>&
|
||
basic_string<charT, traits, Allocator>::replace (
|
||
iterator first1,
|
||
iterator last1,
|
||
InputIterator first2,
|
||
InputIterator last2)
|
||
{
|
||
iterator first = first1;
|
||
iterator last = last1;
|
||
|
||
// Use a (probably)faster algorithm if possible
|
||
if (__is_bidirectional_iterator(__iterator_category(first2)))
|
||
return __replace_aux(first1,last1,first2,last2);
|
||
|
||
_RWSTD_THROW((first > end() || last > end()),out_of_range,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
|
||
"basic_string::replace(iterator,iterator,InputIterato,InputIterato)"
|
||
,first > end() ? first : last,end()).msgstr());
|
||
|
||
while (first2 != last2)
|
||
{
|
||
_RWSTD_THROW(first - __data_.data() == (int)npos,length_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
|
||
"basic_string::replace(iterator,iterator,InputIterator,InputIterator)"
|
||
,first-__data_.data(),npos).msgstr());
|
||
if (first == last)
|
||
{
|
||
// Need to allocate a more room.
|
||
// First get the amount to increase buffer size
|
||
size_type delta = __RWSTD::__rw_allocation_size((value_type*)0,
|
||
(size_type)0,
|
||
(size_type)0);
|
||
delta = delta > 0 ? delta : 1;
|
||
size_type tot = delta + size();
|
||
// Now get new buffer
|
||
__string_ref_type * temp = __getRep(tot,tot);
|
||
// Now copy data from old to new, leaving a hole for additions
|
||
size_type current = last-begin();
|
||
traits::copy(temp->data(),__data_.data(),current);
|
||
traits::copy(temp->data()+current+delta,last,end()-last);
|
||
__unLink();
|
||
__data_ = temp->data();
|
||
first = __data_.data() + current;
|
||
last = first + delta;
|
||
}
|
||
// Copy data over
|
||
*first++ = *first2++;
|
||
}
|
||
if (first != last)
|
||
replace(first-__data_.data(),last-first,0,(charT)' '); // Clean up
|
||
|
||
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>
|
||
inline basic_string<charT, traits, Allocator>&
|
||
basic_string<charT, traits, Allocator>::__replace_aux (
|
||
iterator first1,
|
||
iterator last1,
|
||
InputIterator first2,
|
||
InputIterator last2)
|
||
{
|
||
difference_type n2 = 0;
|
||
distance(first2,last2,n2);
|
||
size_type n = last1-first1;
|
||
size_type pos = first1 - __data_.data();
|
||
|
||
_RWSTD_THROW(pos > length(),out_of_range,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
|
||
"basic_string::__replace_aux(iterator,iterator,InputIterator,InputIterator)"
|
||
,pos,length()).msgstr());
|
||
|
||
size_type slen = length() - pos;
|
||
size_type xlen = n < slen ? n : slen;
|
||
|
||
_RWSTD_THROW(length() - xlen >= npos - n2,length_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
|
||
"basic_string::__replace_aux(iterator,iterator,InputIterator,InputIterator)"
|
||
,length() - xlen, npos - n2).msgstr());
|
||
|
||
size_type tot = length() - xlen + n2; // Final string length.
|
||
|
||
if (!tot)
|
||
{
|
||
// Special case a substitution that leaves the string empty.
|
||
__unLink();
|
||
__getNullRep()->__addReference();
|
||
__data_ = __getNullRep()->data();
|
||
}
|
||
|
||
else
|
||
{
|
||
size_type d = 0;
|
||
size_type rem = length() - xlen - pos; // Length of bit at end of string
|
||
// Check for shared representation, insufficient capacity,
|
||
if ( (__pref()->__references() > 1) || (__getCapac() < tot))
|
||
{
|
||
// Need to allocate a new reference.
|
||
__string_ref_type * temp = __getRep(tot,tot);
|
||
if (pos) traits::copy(temp->data(), __data_.data(), pos);
|
||
for (d = 0; d < (size_type)n2; d++)
|
||
*(temp->data()+pos+d) = *first2++;
|
||
if (rem )
|
||
traits::copy(temp->data()+pos+n2, __data_.data()+pos+n, rem);
|
||
__unLink();
|
||
__data_ = temp->data();
|
||
}
|
||
else
|
||
{
|
||
// Current reference has enough room.
|
||
if (rem)
|
||
traits::move(__data_.data()+pos+n2, __data_.data()+pos+n, rem);
|
||
for (d = 0; d < (size_type)n2; d++)
|
||
*(__data_.data()+pos+d) = *first2++;
|
||
__data_.data()[__pref()->__nchars_ = tot] = __eos(); // Add terminating null
|
||
}
|
||
}
|
||
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 (charT* s,
|
||
size_type n,
|
||
size_type pos) const
|
||
{
|
||
_RWSTD_THROW(pos > length(), out_of_range,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
|
||
"basic_string::copy(char*,size_t,size_t)",pos,length()).msgstr());
|
||
|
||
size_type slen = length() - pos;
|
||
size_type rlen = n < slen ? n : slen;
|
||
traits::copy(s, __data_.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 charT* s,
|
||
size_type pos,
|
||
size_type n) const
|
||
{
|
||
_RWSTD_THROW(s == 0, logic_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
|
||
"basic_string::find(char*,size_t,size_t) const").msgstr());
|
||
|
||
for (size_type xpos = pos; (xpos + n) <= length() ; xpos++)
|
||
{
|
||
if (!traits::compare(__data_.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 charT* s,
|
||
size_type pos,
|
||
size_type n) const
|
||
{
|
||
|
||
_RWSTD_THROW(s == 0, logic_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
|
||
"basic_string::rfind(char*,size_t,size_t) const").msgstr());
|
||
|
||
if (length() < n)
|
||
return npos;
|
||
|
||
size_type slen = length() -n;
|
||
size_type xpos_start = slen < pos ? slen : pos;
|
||
|
||
for (size_type xpos = xpos_start+1; xpos != 0 ; xpos--)
|
||
{
|
||
if (!traits::compare(__data_.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 charT* s,
|
||
size_type pos,
|
||
size_type n) const
|
||
{
|
||
|
||
_RWSTD_THROW(s == 0, logic_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
|
||
"basic_string::find_first_of(char*,size_t,size_t) const").msgstr());
|
||
|
||
for (size_type xpos = pos; xpos < length() ; xpos++)
|
||
{
|
||
for (size_type i = 0; i < n ; i++)
|
||
if (traits::eq(__data_.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 charT* s,
|
||
size_type pos,
|
||
size_type n) const
|
||
{
|
||
_RWSTD_THROW(s == 0, logic_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
|
||
"basic_string::find_last_of(char*,size_t,size_t) const").msgstr());
|
||
|
||
if (length())
|
||
{
|
||
size_type slen = length() -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::eq(__data_.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 charT* s,
|
||
size_type pos,
|
||
size_type n) const
|
||
{
|
||
_RWSTD_THROW(s == 0, logic_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
|
||
"basic_string::find_first_not_of(char*,size_t,size_t) const").msgstr());
|
||
|
||
for (size_type xpos = pos; xpos < length() ; xpos++)
|
||
{
|
||
bool found = false;
|
||
for (size_type i = 0; i < n ; i++)
|
||
{
|
||
if (traits::eq(__data_.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 charT* s,
|
||
size_type pos,
|
||
size_type n) const
|
||
{
|
||
_RWSTD_THROW(s == 0, logic_error,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
|
||
"basic_string::find_last_not_of(char*,size_t,size_t) const").msgstr());
|
||
|
||
if (length())
|
||
{
|
||
size_type slen = length() -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::eq(__data_.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_THROW(pos > length(), out_of_range,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
|
||
"basic_string::substr(size_t,size_t) const",pos, length()).msgstr());
|
||
|
||
size_type slen = length() -pos;
|
||
size_type rlen = n < slen ? n : slen;
|
||
return basic_string<charT, traits, Allocator>(__data_.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<charT, traits, Allocator>& str,
|
||
size_type pos2, size_type n2) const
|
||
{
|
||
_RWSTD_THROW(pos1+n1 > length() || pos2+n2 > str.length(),out_of_range,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
|
||
"basic_string::compare(size_t,size_t,const basic_string&,size_t,size_t) const",
|
||
pos1+n1 > length() ? (pos1+n1) : (pos2+n2),length() > str.length() ? length(): str.length()).msgstr());
|
||
|
||
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 pos1, size_type n1,
|
||
const basic_string<charT, traits, Allocator>& str) const
|
||
{
|
||
_RWSTD_THROW(pos1+n1 > length() ,out_of_range,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
|
||
"basic_string::compare(size_t,size_t,const basic_string&) const",
|
||
pos1+n1 ,length()).msgstr());
|
||
|
||
return compare(pos1,n1,str.c_str(),str.length());
|
||
}
|
||
|
||
template <class charT, class traits , class Allocator >
|
||
int
|
||
basic_string<charT, traits, Allocator>::compare (size_type pos,
|
||
size_type n1,
|
||
const charT* s,
|
||
size_type n2) const
|
||
{
|
||
_RWSTD_THROW(pos > length() ,out_of_range,
|
||
__RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
|
||
"basic_string::compare(size_t,size_t,const const charT*,size_t) const",
|
||
pos ,length()).msgstr());
|
||
if(length() - pos < n1)
|
||
n1 = length() - pos;
|
||
size_type rlen = n1 < n2 ? n1 : n2;
|
||
int result = traits::compare(__data_.data()+pos, s, rlen);
|
||
|
||
if (result == 0)
|
||
result = (n1 < n2) ? -1 : (n1 != n2);
|
||
|
||
return result;
|
||
}
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
void basic_string<charT, traits, Allocator>::__clobber (size_type nc)
|
||
{
|
||
if (__pref()->__references() > 1 || (__getCapac() < nc))
|
||
{
|
||
__unLink();
|
||
__data_ = __getRep(nc, 0)->data();
|
||
}
|
||
else
|
||
__data_.data()[__pref()->__nchars_ = 0] = 0;
|
||
}
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
void basic_string<charT, traits, Allocator>::__clone()
|
||
{
|
||
__string_ref_type * temp = __getRep(length(), length());
|
||
traits::copy(temp->data(), data(), length());
|
||
__unLink();
|
||
__data_ = temp->data();
|
||
}
|
||
|
||
template <class charT, class traits, class Allocator >
|
||
void basic_string<charT, traits, Allocator>::__clone (size_type nc)
|
||
{
|
||
size_type len = length();
|
||
if (len > nc) len = nc;
|
||
__string_ref_type * temp = __getRep(nc, len);
|
||
traits::copy(temp->data(), data(), length());
|
||
__unLink();
|
||
__data_ = temp->data();
|
||
}
|
||
|
||
#ifdef _RWSTD_MSC22_STATIC_INIT_BUG
|
||
#undef npos
|
||
#endif
|
||
|
||
//
|
||
// Inserters and Extractors
|
||
//
|
||
|
||
#ifndef _RW_STD_IOSTREAM
|
||
|
||
template<class charT, class traits, class Allocator>
|
||
istream & _RWSTDExportTemplate operator>> (istream & is,
|
||
basic_string<charT, traits, Allocator > & s)
|
||
{
|
||
int c;
|
||
|
||
if (!is.ipfx())
|
||
return is;
|
||
|
||
s.erase();
|
||
c = is.rdbuf()->sbumpc();
|
||
|
||
#ifdef _RWSTD_MS40_ISTREAM_BUG
|
||
_TYPENAME size_t i =0;
|
||
_TYPENAME size_t end = s.max_size();
|
||
#else
|
||
_TYPENAME Allocator::size_type i = 0;
|
||
_TYPENAME Allocator::size_type end = s.max_size();
|
||
#endif
|
||
if (is.width())
|
||
end = (int)end < is.width() ? end : is.width();
|
||
|
||
while (c != EOF && !isspace(c))
|
||
{
|
||
s.append(1,(charT)c);
|
||
i++;
|
||
if (i == end)
|
||
break;
|
||
c = is.rdbuf()->sbumpc();
|
||
}
|
||
if (c == EOF)
|
||
is.clear(ios::eofbit | is.rdstate());
|
||
if (!i)
|
||
is.clear(ios::failbit | is.rdstate());
|
||
|
||
is.width(0);
|
||
return is;
|
||
}
|
||
template<class charT, class traits, class Allocator>
|
||
ostream & _RWSTDExportTemplate operator<< (ostream & os,
|
||
const basic_string<charT, traits, Allocator > & s)
|
||
{
|
||
os << s.data();
|
||
return os;
|
||
}
|
||
|
||
template<class Stream, class charT, class traits, class Allocator>
|
||
Stream& _RWSTDExportTemplate
|
||
getline (Stream& is, basic_string<charT, traits, Allocator>& str, charT delim)
|
||
{
|
||
int c;
|
||
|
||
if (!is.ipfx(1))
|
||
return is;
|
||
|
||
str.erase();
|
||
c = is.rdbuf()->sbumpc();
|
||
|
||
#ifdef _RWSTD_MS40_ISTREAM_BUG
|
||
size_t i = 0;
|
||
size_t end = str.max_size();
|
||
#else
|
||
_TYPENAME Allocator::size_type i = 0;
|
||
_TYPENAME Allocator::size_type end = str.max_size();
|
||
#endif
|
||
|
||
while (c != EOF)
|
||
{
|
||
i++;
|
||
if ((charT)c == delim)
|
||
break;
|
||
if (i == end)
|
||
{
|
||
is.clear(ios::failbit | is.rdstate());
|
||
break;
|
||
}
|
||
|
||
str.append(1,(charT)c);
|
||
c = is.rdbuf()->sbumpc();
|
||
}
|
||
if (c == EOF)
|
||
is.clear(ios::eofbit | is.rdstate());
|
||
if (!i)
|
||
is.clear(ios::failbit | is.rdstate());
|
||
|
||
is.isfx();
|
||
return is;
|
||
}
|
||
#endif /* not defined _RW_STD_IOSTREAM */
|
||
|
||
#ifndef _RWSTD_NO_NAMESPACE
|
||
}
|
||
#endif
|
||
|
||
#pragma option pop
|
||
#endif /* __STRING_CC */
|