📄 spstring.cpp
字号:
CSPStringData* pOldData = GetData();
AllocBuffer(GetData()->nDataLength);
memcpy(m_pchData, pOldData->data(), pOldData->nDataLength*sizeof(TCHAR));
SP_ASSERT(m_pchData[GetData()->nDataLength] == '\0');
CSPString::Release(pOldData);
}
SP_ASSERT(GetData() != NULL);
}
LPTSTR CSPString::LockBuffer()
{
LPTSTR lpsz = GetBuffer(0);
GetData()->nRefs = -1;
return lpsz;
}
void CSPString::UnlockBuffer()
{
SP_ASSERT(GetData()->nRefs == -1);
if (GetData() != _afxSPDataNil)
GetData()->nRefs = 1;
}
///////////////////////////////////////////////////////////////////////////////
// Commonly used routines (rarely used routines in STREX.CPP)
int CSPString::Find(TCHAR ch) const
{
return Find(ch, 0);
}
int CSPString::Find(TCHAR ch, int nStart) const
{
int nLength = GetData()->nDataLength;
if (nStart >= nLength)
return -1;
// find first single character
LPTSTR lpsz = _tcschr(m_pchData + nStart, ch);
// return -1 if not found and index otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
int CSPString::FindOneOf(LPCTSTR lpszCharSet) const
{
SP_ASSERT(SP_IsValidString(lpszCharSet));
LPTSTR lpsz = _tcspbrk(m_pchData, lpszCharSet);
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
void CSPString::MakeUpper()
{
CopyBeforeWrite();
_tcsupr(m_pchData);
}
void CSPString::MakeLower()
{
CopyBeforeWrite();
_tcslwr(m_pchData);
}
void CSPString::MakeReverse()
{
CopyBeforeWrite();
_tcsrev(m_pchData);
}
void CSPString::SetAt(int nIndex, TCHAR ch)
{
SP_ASSERT(nIndex >= 0);
SP_ASSERT(nIndex < GetData()->nDataLength);
CopyBeforeWrite();
m_pchData[nIndex] = ch;
}
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// More sophisticated construction
CSPString::CSPString(TCHAR ch, int nLength)
{
Init();
if (nLength >= 1)
{
AllocBuffer(nLength);
#ifdef _UNICODE
for (int i = 0; i < nLength; i++)
m_pchData[i] = ch;
#else
memset(m_pchData, ch, nLength);
#endif
}
}
CSPString::CSPString(LPCTSTR lpch, int nLength)
{
Init();
if (nLength != 0)
{
SP_ASSERT(SP_IsValidAddress((void*)lpch, nLength, FALSE));
AllocBuffer(nLength);
memcpy(m_pchData, lpch, nLength*sizeof(TCHAR));
}
}
/////////////////////////////////////////////////////////////////////////////
// Special conversion constructors
#ifdef _UNICODE
CSPString::CSPString(LPCSTR lpsz, int nLength)
{
Init();
if (nLength != 0)
{
AllocBuffer(nLength);
int n = ::MultiByteToWideChar(CP_ACP, 0, lpsz, nLength, m_pchData, nLength+1);
ReleaseBuffer(n >= 0 ? n : -1);
}
}
#else //_UNICODE
CSPString::CSPString(LPCWSTR lpsz, int nLength)
{
Init();
if (nLength != 0)
{
AllocBuffer(nLength*2);
int n = ::WideCharToMultiByte(CP_ACP, 0, lpsz, nLength, m_pchData,
(nLength*2)+1, NULL, NULL);
ReleaseBuffer(n >= 0 ? n : -1);
}
}
#endif //!_UNICODE
//////////////////////////////////////////////////////////////////////////////
// Assignment operators
const CSPString& CSPString::operator=(TCHAR ch)
{
AssignCopy(1, &ch);
return *this;
}
//////////////////////////////////////////////////////////////////////////////
// less common string expressions
CSPString __stdcall operator+(const CSPString& string1, TCHAR ch)
{
CSPString s;
s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData, 1, &ch);
return s;
}
CSPString __stdcall operator+(TCHAR ch, const CSPString& string)
{
CSPString s;
s.ConcatCopy(1, &ch, string.GetData()->nDataLength, string.m_pchData);
return s;
}
//////////////////////////////////////////////////////////////////////////////
// Advanced manipulation
int CSPString::Delete(int nIndex, int nCount /* = 1 */)
{
if (nIndex < 0)
nIndex = 0;
int nNewLength = GetData()->nDataLength;
if (nCount > 0 && nIndex < nNewLength)
{
CopyBeforeWrite();
int nBytesToCopy = nNewLength - (nIndex + nCount) + 1;
memcpy(m_pchData + nIndex,
m_pchData + nIndex + nCount, nBytesToCopy * sizeof(TCHAR));
GetData()->nDataLength = nNewLength - nCount;
}
return nNewLength;
}
int CSPString::Insert(int nIndex, TCHAR ch)
{
CopyBeforeWrite();
if (nIndex < 0)
nIndex = 0;
int nNewLength = GetData()->nDataLength;
if (nIndex > nNewLength)
nIndex = nNewLength;
nNewLength++;
if (GetData()->nAllocLength < nNewLength)
{
CSPStringData* pOldData = GetData();
LPTSTR pstr = m_pchData;
AllocBuffer(nNewLength);
memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(TCHAR));
CSPString::Release(pOldData);
}
// move existing bytes down
memcpy(m_pchData + nIndex + 1,
m_pchData + nIndex, (nNewLength-nIndex)*sizeof(TCHAR));
m_pchData[nIndex] = ch;
GetData()->nDataLength = nNewLength;
return nNewLength;
}
int CSPString::Insert(int nIndex, LPCTSTR pstr)
{
if (nIndex < 0)
nIndex = 0;
int nInsertLength = SafeStrlen(pstr);
int nNewLength = GetData()->nDataLength;
if (nInsertLength > 0)
{
CopyBeforeWrite();
if (nIndex > nNewLength)
nIndex = nNewLength;
nNewLength += nInsertLength;
if (GetData()->nAllocLength < nNewLength)
{
CSPStringData* pOldData = GetData();
LPTSTR pstr = m_pchData;
AllocBuffer(nNewLength);
memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(TCHAR));
CSPString::Release(pOldData);
}
// move existing bytes down
memcpy(m_pchData + nIndex + nInsertLength,
m_pchData + nIndex,
(nNewLength-nIndex-nInsertLength+1)*sizeof(TCHAR));
memcpy(m_pchData + nIndex,
pstr, nInsertLength*sizeof(TCHAR));
GetData()->nDataLength = nNewLength;
}
return nNewLength;
}
int CSPString::Replace(TCHAR chOld, TCHAR chNew)
{
int nCount = 0;
// short-circuit the nop case
if (chOld != chNew)
{
// otherwise modify each character that matches in the string
CopyBeforeWrite();
LPTSTR psz = m_pchData;
LPTSTR pszEnd = psz + GetData()->nDataLength;
while (psz < pszEnd)
{
// replace instances of the specified character only
if (*psz == chOld)
{
*psz = chNew;
nCount++;
}
psz = _tcsinc(psz);
}
}
return nCount;
}
int CSPString::Replace(LPCTSTR lpszOld, LPCTSTR lpszNew)
{
// can't have empty or NULL lpszOld
int nSourceLen = SafeStrlen(lpszOld);
if (nSourceLen == 0)
return 0;
int nReplacementLen = SafeStrlen(lpszNew);
// loop once to figure out the size of the result string
int nCount = 0;
LPTSTR lpszStart = m_pchData;
LPTSTR lpszEnd = m_pchData + GetData()->nDataLength;
LPTSTR lpszTarget;
while (lpszStart < lpszEnd)
{
while ((lpszTarget = _tcsstr(lpszStart, lpszOld)) != NULL)
{
nCount++;
lpszStart = lpszTarget + nSourceLen;
}
lpszStart += lstrlen(lpszStart) + 1;
}
// if any changes were made, make them
if (nCount > 0)
{
CopyBeforeWrite();
// if the buffer is too small, just
// allocate a new buffer (slow but sure)
int nOldLength = GetData()->nDataLength;
int nNewLength = nOldLength + (nReplacementLen-nSourceLen)*nCount;
if (GetData()->nAllocLength < nNewLength || GetData()->nRefs > 1)
{
CSPStringData* pOldData = GetData();
LPTSTR pstr = m_pchData;
AllocBuffer(nNewLength);
memcpy(m_pchData, pstr, pOldData->nDataLength*sizeof(TCHAR));
CSPString::Release(pOldData);
}
// else, we just do it in-place
lpszStart = m_pchData;
lpszEnd = m_pchData + GetData()->nDataLength;
// loop again to actually do the work
while (lpszStart < lpszEnd)
{
while ( (lpszTarget = _tcsstr(lpszStart, lpszOld)) != NULL)
{
int nBalance = nOldLength - (lpszTarget - m_pchData + nSourceLen);
memmove(lpszTarget + nReplacementLen, lpszTarget + nSourceLen,
nBalance * sizeof(TCHAR));
memcpy(lpszTarget, lpszNew, nReplacementLen*sizeof(TCHAR));
lpszStart = lpszTarget + nReplacementLen;
lpszStart[nBalance] = '\0';
nOldLength += (nReplacementLen - nSourceLen);
}
lpszStart += lstrlen(lpszStart) + 1;
}
SP_ASSERT(m_pchData[nNewLength] == '\0');
GetData()->nDataLength = nNewLength;
}
return nCount;
}
int CSPString::Remove(TCHAR chRemove)
{
CopyBeforeWrite();
LPTSTR pstrSource = m_pchData;
LPTSTR pstrDest = m_pchData;
LPTSTR pstrEnd = m_pchData + GetData()->nDataLength;
while (pstrSource < pstrEnd)
{
if (*pstrSource != chRemove)
{
*pstrDest = *pstrSource;
pstrDest = _tcsinc(pstrDest);
}
pstrSource = _tcsinc(pstrSource);
}
*pstrDest = '\0';
int nCount = pstrSource - pstrDest;
GetData()->nDataLength -= nCount;
return nCount;
}
//////////////////////////////////////////////////////////////////////////////
// Very simple sub-string extraction
CSPString CSPString::Mid(int nFirst) const
{
return Mid(nFirst, GetData()->nDataLength - nFirst);
}
CSPString CSPString::Mid(int nFirst, int nCount) const
{
// out-of-bounds requests return sensible things
if (nFirst < 0)
nFirst = 0;
if (nCount < 0)
nCount = 0;
if (nFirst + nCount > GetData()->nDataLength)
nCount = GetData()->nDataLength - nFirst;
if (nFirst > GetData()->nDataLength)
nCount = 0;
SP_ASSERT(nFirst >= 0);
SP_ASSERT(nFirst + nCount <= GetData()->nDataLength);
// optimize case of returning entire string
if (nFirst == 0 && nFirst + nCount == GetData()->nDataLength)
return *this;
CSPString dest;
AllocCopy(dest, nCount, nFirst, 0);
return dest;
}
CSPString CSPString::Right(int nCount) const
{
if (nCount < 0)
nCount = 0;
if (nCount >= GetData()->nDataLength)
return *this;
CSPString dest;
AllocCopy(dest, nCount, GetData()->nDataLength-nCount, 0);
return dest;
}
CSPString CSPString::Left(int nCount) const
{
if (nCount < 0)
nCount = 0;
if (nCount >= GetData()->nDataLength)
return *this;
CSPString dest;
AllocCopy(dest, nCount, 0, 0);
return dest;
}
// strspn equivalent
CSPString CSPString::SpanIncluding(LPCTSTR lpszCharSet) const
{
SP_ASSERT(SP_IsValidString(lpszCharSet));
return Left(_tcsspn(m_pchData, lpszCharSet));
}
// strcspn equivalent
CSPString CSPString::SpanExcluding(LPCTSTR lpszCharSet) const
{
SP_ASSERT(SP_IsValidString(lpszCharSet));
return Left(_tcscspn(m_pchData, lpszCharSet));
}
//////////////////////////////////////////////////////////////////////////////
// Finding
int CSPString::ReverseFind(TCHAR ch) const
{
// find last single character
LPTSTR lpsz = _tcsrchr(m_pchData, (_TUCHAR) ch);
// return -1 if not found, distance from beginning otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
// find a sub-string (like strstr)
int CSPString::Find(LPCTSTR lpszSub) const
{
return Find(lpszSub, 0);
}
int CSPString::Find(LPCTSTR lpszSub, int nStart) const
{
SP_ASSERT(SP_IsValidString(lpszSub));
int nLength = GetData()->nDataLength;
if (nStart > nLength)
return -1;
// find first matching substring
LPTSTR lpsz = _tcsstr(m_pchData + nStart, lpszSub);
// return -1 for not found, distance from beginning otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -