📄 atl_cstring.cpp
字号:
// Concatenate two sources
// -- assume that 'this' is a new CString object
int nNewLen = nSrc1Len + nSrc2Len;
if (nNewLen != 0)
{
AllocBuffer(nNewLen);
memcpy(m_pchData, lpszSrc1Data, nSrc1Len*sizeof(TCHAR));
memcpy(m_pchData+nSrc1Len, lpszSrc2Data, nSrc2Len*sizeof(TCHAR));
}
}
CString AFXAPI operator+(const CString& string1, const CString& string2)
{
CString s;
s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData,
string2.GetData()->nDataLength, string2.m_pchData);
return s;
}
CString AFXAPI operator+(const CString& string, LPCTSTR lpsz)
{
ATLASSERT(lpsz == NULL || AfxIsValidString(lpsz));
CString s;
s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData,
CString::SafeStrlen(lpsz), lpsz);
return s;
}
CString AFXAPI operator+(LPCTSTR lpsz, const CString& string)
{
ATLASSERT(lpsz == NULL || AfxIsValidString(lpsz));
CString s;
s.ConcatCopy(CString::SafeStrlen(lpsz), lpsz, string.GetData()->nDataLength,
string.m_pchData);
return s;
}
//////////////////////////////////////////////////////////////////////////////
// concatenate in place
void CString::ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData)
{
// -- the main routine for += operators
// concatenating an empty string is a no-op!
if (nSrcLen == 0)
return;
// if the buffer is too small, or we have a width mis-match, just
// allocate a new buffer (slow but sure)
if (GetData()->nRefs > 1 || GetData()->nDataLength + nSrcLen > GetData()->nAllocLength)
{
// we have to grow the buffer, use the ConcatCopy routine
CStringData* pOldData = GetData();
ConcatCopy(GetData()->nDataLength, m_pchData, nSrcLen, lpszSrcData);
ATLASSERT(pOldData != NULL);
CString::Release(pOldData);
}
else
{
// fast concatenation when buffer big enough
memcpy(m_pchData+GetData()->nDataLength, lpszSrcData, nSrcLen*sizeof(TCHAR));
GetData()->nDataLength += nSrcLen;
ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength);
m_pchData[GetData()->nDataLength] = '\0';
}
}
const CString& CString::operator+=(LPCTSTR lpsz)
{
ATLASSERT(lpsz == NULL || AfxIsValidString(lpsz));
ConcatInPlace(SafeStrlen(lpsz), lpsz);
return *this;
}
const CString& CString::operator+=(TCHAR ch)
{
ConcatInPlace(1, &ch);
return *this;
}
const CString& CString::operator+=(const CString& string)
{
ConcatInPlace(string.GetData()->nDataLength, string.m_pchData);
return *this;
}
///////////////////////////////////////////////////////////////////////////////
// Advanced direct buffer access
LPTSTR CString::GetBuffer(int nMinBufLength)
{
ATLASSERT(nMinBufLength >= 0);
if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength)
{
#ifdef _DEBUG
// give a warning in case locked string becomes unlocked
if (GetData() != _afxDataNil && GetData()->nRefs < 0)
ATLTRACE("Warning: GetBuffer on locked CString creates unlocked CString!\n");
#endif
// we have to grow the buffer
CStringData* pOldData = GetData();
int nOldLen = GetData()->nDataLength; // AllocBuffer will tromp it
if (nMinBufLength < nOldLen)
nMinBufLength = nOldLen;
AllocBuffer(nMinBufLength);
memcpy(m_pchData, pOldData->data(), (nOldLen+1)*sizeof(TCHAR));
GetData()->nDataLength = nOldLen;
CString::Release(pOldData);
}
ATLASSERT(GetData()->nRefs <= 1);
// return a pointer to the character storage for this string
ATLASSERT(m_pchData != NULL);
return m_pchData;
}
void CString::ReleaseBuffer(int nNewLength)
{
CopyBeforeWrite(); // just in case GetBuffer was not called
if (nNewLength == -1)
nNewLength = lstrlen(m_pchData); // zero terminated
ATLASSERT(nNewLength <= GetData()->nAllocLength);
GetData()->nDataLength = nNewLength;
m_pchData[nNewLength] = '\0';
}
LPTSTR CString::GetBufferSetLength(int nNewLength)
{
ATLASSERT(nNewLength >= 0);
GetBuffer(nNewLength);
GetData()->nDataLength = nNewLength;
m_pchData[nNewLength] = '\0';
return m_pchData;
}
void CString::FreeExtra()
{
ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength);
if (GetData()->nDataLength != GetData()->nAllocLength)
{
CStringData* pOldData = GetData();
AllocBuffer(GetData()->nDataLength);
memcpy(m_pchData, pOldData->data(), pOldData->nDataLength*sizeof(TCHAR));
ATLASSERT(m_pchData[GetData()->nDataLength] == '\0');
CString::Release(pOldData);
}
ATLASSERT(GetData() != NULL);
}
LPTSTR CString::LockBuffer()
{
LPTSTR lpsz = GetBuffer(0);
GetData()->nRefs = -1;
return lpsz;
}
void CString::UnlockBuffer()
{
ATLASSERT(GetData()->nRefs == -1);
if (GetData() != _afxDataNil)
GetData()->nRefs = 1;
}
///////////////////////////////////////////////////////////////////////////////
// Commonly used routines (rarely used routines in STREX.CPP)
int CString::Find(TCHAR ch) const
{
return Find(ch, 0);
}
int CString::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, (_TUCHAR)ch);
// return -1 if not found and index otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
int CString::FindOneOf(LPCTSTR lpszCharSet) const
{
ATLASSERT(AfxIsValidString(lpszCharSet));
LPTSTR lpsz = _tcspbrk(m_pchData, lpszCharSet);
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
void CString::MakeUpper()
{
CopyBeforeWrite();
_tcsupr(m_pchData);
}
void CString::MakeLower()
{
CopyBeforeWrite();
_tcslwr(m_pchData);
}
void CString::MakeReverse()
{
CopyBeforeWrite();
_tcsrev(m_pchData);
}
void CString::SetAt(int nIndex, TCHAR ch)
{
ATLASSERT(nIndex >= 0);
ATLASSERT(nIndex < GetData()->nDataLength);
CopyBeforeWrite();
m_pchData[nIndex] = ch;
}
#ifndef _UNICODE
void CString::AnsiToOem()
{
CopyBeforeWrite();
::AnsiToOem(m_pchData, m_pchData);
}
void CString::OemToAnsi()
{
CopyBeforeWrite();
::OemToAnsi(m_pchData, m_pchData);
}
#endif
///////////////////////////////////////////////////////////////////////////////
// CString conversion helpers (these use the current system locale)
int AFX_CDECL _wcstombsz(char* mbstr, const wchar_t* wcstr, size_t count)
{
if (count == 0 && mbstr != NULL)
return 0;
int result = ::WideCharToMultiByte(CP_ACP, 0, wcstr, -1,
mbstr, count, NULL, NULL);
ATLASSERT(mbstr == NULL || result <= (int)count);
if (result > 0)
mbstr[result-1] = 0;
return result;
}
int AFX_CDECL _mbstowcsz(wchar_t* wcstr, const char* mbstr, size_t count)
{
if (count == 0 && wcstr != NULL)
return 0;
int result = ::MultiByteToWideChar(CP_ACP, 0, mbstr, -1,
wcstr, count);
ATLASSERT(wcstr == NULL || result <= (int)count);
if (result > 0)
wcstr[result-1] = 0;
return result;
}
LPWSTR AFXAPI AfxA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars)
{
if (lpa == NULL)
return NULL;
ATLASSERT(lpw != NULL);
// verify that no illegal character present
// since lpw was allocated based on the size of lpa
// don't worry about the number of chars
lpw[0] = '\0';
/*VERIFY*/ if (!MultiByteToWideChar(CP_ACP, 0, lpa, -1, lpw, nChars))
{
ATLASSERT(0);
}
return lpw;
}
LPSTR AFXAPI AfxW2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars)
{
if (lpw == NULL)
return NULL;
ATLASSERT(lpa != NULL);
// verify that no illegal character present
// since lpa was allocated based on the size of lpw
// don't worry about the number of chars
lpa[0] = '\0';
/*VERIFY*/ if (!WideCharToMultiByte(CP_ACP, 0, lpw, -1, lpa, nChars, NULL, NULL))
{
ATLASSERT(0);
}
return lpa;
}
///////////////////////////////////////////////////////////////////////////////
// --- from STREX.CPP
CString::CString(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
}
}
CString::CString(LPCTSTR lpch, int nLength)
{
Init();
if (nLength != 0)
{
ATLASSERT(AfxIsValidAddress(lpch, nLength, FALSE));
AllocBuffer(nLength);
memcpy(m_pchData, lpch, nLength*sizeof(TCHAR));
}
}
/////////////////////////////////////////////////////////////////////////////
// Special conversion constructors
#ifdef _UNICODE
CString::CString(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
CString::CString(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 CString& CString::operator=(TCHAR ch)
{
AssignCopy(1, &ch);
return *this;
}
//////////////////////////////////////////////////////////////////////////////
// less common string expressions
CString AFXAPI operator+(const CString& string1, TCHAR ch)
{
CString s;
s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData, 1, &ch);
return s;
}
CString AFXAPI operator+(TCHAR ch, const CString& string)
{
CString s;
s.ConcatCopy(1, &ch, string.GetData()->nDataLength, string.m_pchData);
return s;
}
//////////////////////////////////////////////////////////////////////////////
// Advanced manipulation
int CString::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 CString::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)
{
CStringData* pOldData = GetData();
LPTSTR pstr = m_pchData;
AllocBuffer(nNewLength);
memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(TCHAR));
CString::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 CString::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)
{
CStringData* pOldData = GetData();
LPTSTR pstr = m_pchData;
AllocBuffer(nNewLength);
memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(TCHAR));
CString::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 CString::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)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -