string.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,635 行 · 第 1/3 页
CPP
1,635 行
}
} while ( cursor-- > c_str() );
}
return npos;
}
size_t wxStringBase::rfind(const wxChar* sz, size_t nStart, size_t n) const
{
return rfind(wxStringBase(sz, n), nStart);
}
size_t wxStringBase::rfind(wxChar ch, size_t nStart) const
{
if ( nStart == npos )
{
nStart = length();
}
else
{
wxASSERT( nStart <= length() );
}
const wxChar *actual;
for ( actual = c_str() + ( nStart == npos ? length() : nStart + 1 );
actual > c_str(); --actual )
{
if ( *(actual - 1) == ch )
return (actual - 1) - c_str();
}
return npos;
}
size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart) const
{
wxASSERT(nStart <= length());
size_t len = wxStrlen(sz);
size_t i;
for(i = nStart; i < this->length(); ++i)
{
if (wxTmemchr(sz, *(c_str() + i), len))
break;
}
if(i == this->length())
return npos;
else
return i;
}
size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart,
size_t n) const
{
return find_first_of(wxStringBase(sz, n), nStart);
}
size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart) const
{
if ( nStart == npos )
{
nStart = length() - 1;
}
else
{
wxASSERT_MSG( nStart <= length(),
_T("invalid index in find_last_of()") );
}
size_t len = wxStrlen(sz);
for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
{
if ( wxTmemchr(sz, *p, len) )
return p - c_str();
}
return npos;
}
size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart,
size_t n) const
{
return find_last_of(wxStringBase(sz, n), nStart);
}
size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart) const
{
if ( nStart == npos )
{
nStart = length();
}
else
{
wxASSERT( nStart <= length() );
}
size_t len = wxStrlen(sz);
size_t i;
for(i = nStart; i < this->length(); ++i)
{
if (!wxTmemchr(sz, *(c_str() + i), len))
break;
}
if(i == this->length())
return npos;
else
return i;
}
size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart,
size_t n) const
{
return find_first_not_of(wxStringBase(sz, n), nStart);
}
size_t wxStringBase::find_first_not_of(wxChar ch, size_t nStart) const
{
wxASSERT( nStart <= length() );
for ( const wxChar *p = c_str() + nStart; *p; p++ )
{
if ( *p != ch )
return p - c_str();
}
return npos;
}
size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart) const
{
if ( nStart == npos )
{
nStart = length() - 1;
}
else
{
wxASSERT( nStart <= length() );
}
size_t len = wxStrlen(sz);
for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
{
if ( !wxTmemchr(sz, *p,len) )
return p - c_str();
}
return npos;
}
size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart,
size_t n) const
{
return find_last_not_of(wxStringBase(sz, n), nStart);
}
size_t wxStringBase::find_last_not_of(wxChar ch, size_t nStart) const
{
if ( nStart == npos )
{
nStart = length() - 1;
}
else
{
wxASSERT( nStart <= length() );
}
for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
{
if ( *p != ch )
return p - c_str();
}
return npos;
}
wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
const wxChar *sz)
{
wxASSERT_MSG( nStart <= length(),
_T("index out of bounds in wxStringBase::replace") );
size_t strLen = length() - nStart;
nLen = strLen < nLen ? strLen : nLen;
wxStringBase strTmp;
strTmp.reserve(length()); // micro optimisation to avoid multiple mem allocs
//This is kind of inefficient, but its pretty good considering...
//we don't want to use character access operators here because on STL
//it will freeze the reference count of strTmp, which means a deep copy
//at the end when swap is called
//
//Also, we can't use append with the full character pointer and must
//do it manually because this string can contain null characters
for(size_t i1 = 0; i1 < nStart; ++i1)
strTmp.append(1, this->c_str()[i1]);
//its safe to do the full version here because
//sz must be a normal c string
strTmp.append(sz);
for(size_t i2 = nStart + nLen; i2 < length(); ++i2)
strTmp.append(1, this->c_str()[i2]);
swap(strTmp);
return *this;
}
wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
size_t nCount, wxChar ch)
{
return replace(nStart, nLen, wxStringBase(nCount, ch).c_str());
}
wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
const wxStringBase& str,
size_t nStart2, size_t nLen2)
{
return replace(nStart, nLen, str.substr(nStart2, nLen2));
}
wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
const wxChar* sz, size_t nCount)
{
return replace(nStart, nLen, wxStringBase(sz, nCount).c_str());
}
wxStringBase wxStringBase::substr(size_t nStart, size_t nLen) const
{
if ( nLen == npos )
nLen = length() - nStart;
return wxStringBase(*this, nStart, nLen);
}
// assigns one string to another
wxStringBase& wxStringBase::operator=(const wxStringBase& stringSrc)
{
wxASSERT( stringSrc.GetStringData()->IsValid() );
// don't copy string over itself
if ( m_pchData != stringSrc.m_pchData ) {
if ( stringSrc.GetStringData()->IsEmpty() ) {
Reinit();
}
else {
// adjust references
GetStringData()->Unlock();
m_pchData = stringSrc.m_pchData;
GetStringData()->Lock();
}
}
return *this;
}
// assigns a single character
wxStringBase& wxStringBase::operator=(wxChar ch)
{
if ( !AssignCopy(1, &ch) ) {
wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(wxChar)") );
}
return *this;
}
// assigns C string
wxStringBase& wxStringBase::operator=(const wxChar *psz)
{
if ( !AssignCopy(wxStrlen(psz), psz) ) {
wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(const wxChar *)") );
}
return *this;
}
// helper function: does real copy
bool wxStringBase::AssignCopy(size_t nSrcLen, const wxChar *pszSrcData)
{
if ( nSrcLen == 0 ) {
Reinit();
}
else {
if ( !AllocBeforeWrite(nSrcLen) ) {
// allocation failure handled by caller
return false;
}
memcpy(m_pchData, pszSrcData, nSrcLen*sizeof(wxChar));
GetStringData()->nDataLength = nSrcLen;
m_pchData[nSrcLen] = wxT('\0');
}
return true;
}
// ---------------------------------------------------------------------------
// string concatenation
// ---------------------------------------------------------------------------
// add something to this string
bool wxStringBase::ConcatSelf(size_t nSrcLen, const wxChar *pszSrcData,
size_t nMaxLen)
{
STATISTICS_ADD(SummandLength, nSrcLen);
nSrcLen = nSrcLen < nMaxLen ? nSrcLen : nMaxLen;
// concatenating an empty string is a NOP
if ( nSrcLen > 0 ) {
wxStringData *pData = GetStringData();
size_t nLen = pData->nDataLength;
size_t nNewLen = nLen + nSrcLen;
// alloc new buffer if current is too small
if ( pData->IsShared() ) {
STATISTICS_ADD(ConcatHit, 0);
// we have to allocate another buffer
wxStringData* pOldData = GetStringData();
if ( !AllocBuffer(nNewLen) ) {
// allocation failure handled by caller
return false;
}
memcpy(m_pchData, pOldData->data(), nLen*sizeof(wxChar));
pOldData->Unlock();
}
else if ( nNewLen > pData->nAllocLength ) {
STATISTICS_ADD(ConcatHit, 0);
reserve(nNewLen);
// we have to grow the buffer
if ( capacity() < nNewLen ) {
// allocation failure handled by caller
return false;
}
}
else {
STATISTICS_ADD(ConcatHit, 1);
// the buffer is already big enough
}
// should be enough space
wxASSERT( nNewLen <= GetStringData()->nAllocLength );
// fast concatenation - all is done in our buffer
memcpy(m_pchData + nLen, pszSrcData, nSrcLen*sizeof(wxChar));
m_pchData[nNewLen] = wxT('\0'); // put terminating '\0'
GetStringData()->nDataLength = nNewLen; // and fix the length
}
//else: the string to append was empty
return true;
}
// ---------------------------------------------------------------------------
// simple sub-string extraction
// ---------------------------------------------------------------------------
// helper function: clone the data attached to this string
bool wxStringBase::AllocCopy(wxString& dest, int nCopyLen, int nCopyIndex) const
{
if ( nCopyLen == 0 ) {
dest.Init();
}
else {
if ( !dest.AllocBuffer(nCopyLen) ) {
// allocation failure handled by caller
return false;
}
memcpy(dest.m_pchData, m_pchData + nCopyIndex, nCopyLen*sizeof(wxChar));
}
return true;
}
#endif // !wxUSE_STL
#if !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE)
#if !wxUSE_STL
#define STRINGCLASS wxStringBase
#else
#define STRINGCLASS wxString
#endif
static inline int wxDoCmp(const wxChar* s1, size_t l1,
const wxChar* s2, size_t l2)
{
if( l1 == l2 )
return wxTmemcmp(s1, s2, l1);
else if( l1 < l2 )
{
int ret = wxTmemcmp(s1, s2, l1);
return ret == 0 ? -1 : ret;
}
else
{
int ret = wxTmemcmp(s1, s2, l2);
return ret == 0 ? +1 : ret;
}
}
int STRINGCLASS::compare(const wxStringBase& str) const
{
return ::wxDoCmp(data(), length(), str.data(), str.length());
}
int STRINGCLASS::compare(size_t nStart, size_t nLen,
const wxStringBase& str) const
{
wxASSERT(nStart <= length());
size_type strLen = length() - nStart;
nLen = strLen < nLen ? strLen : nLen;
return ::wxDoCmp(data() + nStart, nLen, str.data(), str.length());
}
int STRINGCLASS::compare(size_t nStart, size_t nLen,
const wxStringBase& str,
size_t nStart2, size_t nLen2) const
{
wxASSERT(nStart <= length());
wxASSERT(nStart2 <= str.length());
size_type strLen = length() - nStart,
strLen2 = str.length() - nStart2;
nLen = strLen < nLen ? strLen : nLen;
nLen2 = strLen2 < nLen2 ? strLen2 : nLen2;
return ::wxDoCmp(data() + nStart, nLen, str.data() + nStart2, nLen2);
}
int STRINGCLASS::compare(const wxChar* sz) const
{
size_t nLen = wxStrlen(sz);
return ::wxDoCmp(data(), length(), sz, nLen);
}
int STRINGCLASS::compare(size_t nStart, size_t nLen,
const wxChar* sz, size_t nCount) const
{
wxASSERT(nStart <= length());
size_type strLen = length() - nStart;
nLen = strLen < nLen ? strLen : nLen;
if( nCount == npos )
nCount = wxStrlen(sz);
return ::wxDoCmp(data() + nStart, nLen, sz, nCount);
}
#undef STRINGCLASS
#endif // !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE)
// ===========================================================================
// wxString class core
// ===========================================================================
// ---------------------------------------------------------------------------
// construction and conversion
// ---------------------------------------------------------------------------
#if wxUSE_UNICODE
// from multibyte string
wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength)
{
// if nLength != npos, then we have to make a NULL-terminated copy
// of first nLength bytes of psz first because the input buffer to MB2WC
// must always be NULL-terminated:
wxCharBuffer inBuf((const char *)NULL);
if (nLength != npos)
{
wxASSERT( psz != NULL );
wxCharBuffer tmp(nLength);
memcpy(tmp.data(), psz, nLength);
tmp.data()[nLength] = '\0';
inBuf = tmp;
psz = inBuf.data();
}
// first get the size of the buffer we need
size_t nLen;
if ( psz )
{
// calculate the needed size ourselves or use the provided one
if (nLength == npos)
nLen = strlen(psz);
else
nLen = nLength;
}
else
{
// nothing to convert
nLen = 0;
}
// anything to do?
if ( (nLen != 0) && (nLen != (size_t)-1) )
{
//Convert string
size_t nRealSize;
wxWCharBuffer theBuffer = conv.cMB2WC(psz, nLen, &nRealSize);
//Copy
if (nRealSize)
assign( theBuffer.data() , nRealSize - 1 );
}
}
//Convert wxString in Unicode mode to a multi-byte string
const wxCharBuffer wxString::mb_str(wxMBConv& conv) const
{
size_t dwOutSize;
return conv.cWC2MB(c_str(), length(), &dwOutSize);
}
#else // ANSI
#if wxUSE_WCHAR_T
// from wide string
wxString::wxString(const wchar_t *pwz, wxMBConv& conv, size_t nLength)
{
// if nLength != npos, then we have to make a NULL-terminated copy
// of first nLength chars of psz first because the input buffer to WC2MB
// must always be NULL-terminated:
wxWCharBuffer inBuf((const wchar_t *)NULL);
if (nLength != npos)
{
wxASSERT( pwz != NULL );
wxWCharBuffer tmp(nLength);
memcpy(tmp.data(), pwz, nLength * sizeof(wchar_t));
tmp.data()[nLength] = '\0';
inBuf = tmp;
pwz = inBuf.data();
}
// first get the size of the buffer we need
size_t nLen;
if ( pwz )
{
// calculate the needed size ourselves or use the provided one
if (nLength == npos)
nLen = wxWcslen(pwz);
else
nLen = nLength;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?