📄 atlmisc.h
字号:
{ *this += (TCHAR)ch; return *this; }
inline const CString& CString::operator=(char ch)
{ *this = (TCHAR)ch; return *this; }
inline CString __stdcall operator+(const CString& string, char ch)
{ return string + (TCHAR)ch; }
inline CString __stdcall operator+(char ch, const CString& string)
{ return (TCHAR)ch + string; }
#endif
inline int CString::GetLength() const
{ return GetData()->nDataLength; }
inline int CString::GetAllocLength() const
{ return GetData()->nAllocLength; }
inline BOOL CString::IsEmpty() const
{ return GetData()->nDataLength == 0; }
inline CString::operator LPCTSTR() const
{ return m_pchData; }
inline int PASCAL CString::SafeStrlen(LPCTSTR lpsz)
{ return (lpsz == NULL) ? 0 : lstrlen(lpsz); }
// CString support (windows specific)
inline int CString::Compare(LPCTSTR lpsz) const
{ return _cstrcmp(m_pchData, lpsz); } // MBCS/Unicode aware
inline int CString::CompareNoCase(LPCTSTR lpsz) const
{ return _cstrcmpi(m_pchData, lpsz); } // MBCS/Unicode aware
// CString::Collate is often slower than Compare but is MBSC/Unicode
// aware as well as locale-sensitive with respect to sort order.
inline int CString::Collate(LPCTSTR lpsz) const
{ return _cstrcoll(m_pchData, lpsz); } // locale sensitive
inline TCHAR CString::GetAt(int nIndex) const
{
ATLASSERT(nIndex >= 0);
ATLASSERT(nIndex < GetData()->nDataLength);
return m_pchData[nIndex];
}
inline TCHAR CString::operator[](int nIndex) const
{
// same as GetAt
ATLASSERT(nIndex >= 0);
ATLASSERT(nIndex < GetData()->nDataLength);
return m_pchData[nIndex];
}
inline bool __stdcall operator==(const CString& s1, const CString& s2)
{ return s1.Compare(s2) == 0; }
inline bool __stdcall operator==(const CString& s1, LPCTSTR s2)
{ return s1.Compare(s2) == 0; }
inline bool __stdcall operator==(LPCTSTR s1, const CString& s2)
{ return s2.Compare(s1) == 0; }
inline bool __stdcall operator!=(const CString& s1, const CString& s2)
{ return s1.Compare(s2) != 0; }
inline bool __stdcall operator!=(const CString& s1, LPCTSTR s2)
{ return s1.Compare(s2) != 0; }
inline bool __stdcall operator!=(LPCTSTR s1, const CString& s2)
{ return s2.Compare(s1) != 0; }
inline bool __stdcall operator<(const CString& s1, const CString& s2)
{ return s1.Compare(s2) < 0; }
inline bool __stdcall operator<(const CString& s1, LPCTSTR s2)
{ return s1.Compare(s2) < 0; }
inline bool __stdcall operator<(LPCTSTR s1, const CString& s2)
{ return s2.Compare(s1) > 0; }
inline bool __stdcall operator>(const CString& s1, const CString& s2)
{ return s1.Compare(s2) > 0; }
inline bool __stdcall operator>(const CString& s1, LPCTSTR s2)
{ return s1.Compare(s2) > 0; }
inline bool __stdcall operator>(LPCTSTR s1, const CString& s2)
{ return s2.Compare(s1) < 0; }
inline bool __stdcall operator<=(const CString& s1, const CString& s2)
{ return s1.Compare(s2) <= 0; }
inline bool __stdcall operator<=(const CString& s1, LPCTSTR s2)
{ return s1.Compare(s2) <= 0; }
inline bool __stdcall operator<=(LPCTSTR s1, const CString& s2)
{ return s2.Compare(s1) >= 0; }
inline bool __stdcall operator>=(const CString& s1, const CString& s2)
{ return s1.Compare(s2) >= 0; }
inline bool __stdcall operator>=(const CString& s1, LPCTSTR s2)
{ return s1.Compare(s2) >= 0; }
inline bool __stdcall operator>=(LPCTSTR s1, const CString& s2)
{ return s2.Compare(s1) <= 0; }
inline CString::CString()
{
Init();
}
inline CString::CString(const CString& stringSrc)
{
ATLASSERT(stringSrc.GetData()->nRefs != 0);
if (stringSrc.GetData()->nRefs >= 0)
{
ATLASSERT(stringSrc.GetData() != _atltmpDataNil);
m_pchData = stringSrc.m_pchData;
InterlockedIncrement(&GetData()->nRefs);
}
else
{
Init();
*this = stringSrc.m_pchData;
}
}
inline BOOL CString::AllocBuffer(int nLen)
// always allocate one extra character for '\0' termination
// assumes [optimistically] that data length will equal allocation length
{
ATLASSERT(nLen >= 0);
ATLASSERT(nLen <= INT_MAX - 1); // max size (enough room for 1 extra)
if (nLen == 0)
{
Init();
}
else
{
CStringData* pData = NULL;
ATLTRY(pData = (CStringData*)new BYTE[sizeof(CStringData) + (nLen + 1) * sizeof(TCHAR)]);
if(pData == NULL)
return FALSE;
pData->nRefs = 1;
pData->data()[nLen] = '\0';
pData->nDataLength = nLen;
pData->nAllocLength = nLen;
m_pchData = pData->data();
}
return TRUE;
}
inline void CString::Release()
{
if (GetData() != _atltmpDataNil)
{
ATLASSERT(GetData()->nRefs != 0);
if (InterlockedDecrement(&GetData()->nRefs) <= 0)
delete[] (BYTE*)GetData();
Init();
}
}
inline void PASCAL CString::Release(CStringData* pData)
{
if (pData != _atltmpDataNil)
{
ATLASSERT(pData->nRefs != 0);
if (InterlockedDecrement(&pData->nRefs) <= 0)
delete[] (BYTE*)pData;
}
}
inline void CString::Empty()
{
if (GetData()->nDataLength == 0)
return;
if (GetData()->nRefs >= 0)
Release();
else
*this = _T("");
ATLASSERT(GetData()->nDataLength == 0);
ATLASSERT(GetData()->nRefs < 0 || GetData()->nAllocLength == 0);
}
inline void CString::CopyBeforeWrite()
{
if (GetData()->nRefs > 1)
{
CStringData* pData = GetData();
Release();
if(AllocBuffer(pData->nDataLength))
memcpy(m_pchData, pData->data(), (pData->nDataLength + 1) * sizeof(TCHAR));
}
ATLASSERT(GetData()->nRefs <= 1);
}
inline BOOL CString::AllocBeforeWrite(int nLen)
{
BOOL bRet = TRUE;
if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength)
{
Release();
bRet = AllocBuffer(nLen);
}
ATLASSERT(GetData()->nRefs <= 1);
return bRet;
}
inline CString::~CString()
// free any attached data
{
if (GetData() != _atltmpDataNil)
{
if (InterlockedDecrement(&GetData()->nRefs) <= 0)
delete[] (BYTE*)GetData();
}
}
inline void CString::AllocCopy(CString& dest, int nCopyLen, int nCopyIndex,
int nExtraLen) const
{
// will clone the data attached to this string
// allocating 'nExtraLen' characters
// Places results in uninitialized string 'dest'
// Will copy the part or all of original data to start of new string
int nNewLen = nCopyLen + nExtraLen;
if (nNewLen == 0)
{
dest.Init();
}
else
{
if(dest.AllocBuffer(nNewLen))
memcpy(dest.m_pchData, m_pchData + nCopyIndex, nCopyLen * sizeof(TCHAR));
}
}
inline CString::CString(LPCTSTR lpsz)
{
Init();
if (lpsz != NULL && HIWORD(lpsz) == NULL)
{
UINT nID = LOWORD((DWORD_PTR)lpsz);
if (!LoadString(nID))
ATLTRACE2(atlTraceUI, 0, _T("Warning: implicit LoadString(%u) in CString failed\n"), nID);
}
else
{
int nLen = SafeStrlen(lpsz);
if (nLen != 0)
{
if(AllocBuffer(nLen))
memcpy(m_pchData, lpsz, nLen * sizeof(TCHAR));
}
}
}
#ifdef _UNICODE
inline CString::CString(LPCSTR lpsz)
{
Init();
int nSrcLen = lpsz != NULL ? lstrlenA(lpsz) : 0;
if (nSrcLen != 0)
{
if(AllocBuffer(nSrcLen))
{
_mbstowcsz(m_pchData, lpsz, nSrcLen + 1);
ReleaseBuffer();
}
}
}
#else //_UNICODE
inline CString::CString(LPCWSTR lpsz)
{
Init();
int nSrcLen = lpsz != NULL ? wcslen(lpsz) : 0;
if (nSrcLen != 0)
{
if(AllocBuffer(nSrcLen * 2))
{
_wcstombsz(m_pchData, lpsz, (nSrcLen * 2) + 1);
ReleaseBuffer();
}
}
}
#endif //!_UNICODE
// Assignment operators
// All assign a new value to the string
// (a) first see if the buffer is big enough
// (b) if enough room, copy on top of old buffer, set size and type
// (c) otherwise free old string data, and create a new one
//
// All routines return the new string (but as a 'const CString&' so that
// assigning it again will cause a copy, eg: s1 = s2 = "hi there".
//
inline void CString::AssignCopy(int nSrcLen, LPCTSTR lpszSrcData)
{
if(AllocBeforeWrite(nSrcLen))
{
memcpy(m_pchData, lpszSrcData, nSrcLen * sizeof(TCHAR));
GetData()->nDataLength = nSrcLen;
m_pchData[nSrcLen] = '\0';
}
}
inline const CString& CString::operator=(const CString& stringSrc)
{
if (m_pchData != stringSrc.m_pchData)
{
if ((GetData()->nRefs < 0 && GetData() != _atltmpDataNil) || stringSrc.GetData()->nRefs < 0)
{
// actual copy necessary since one of the strings is locked
AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData);
}
else
{
// can just copy references around
Release();
ATLASSERT(stringSrc.GetData() != _atltmpDataNil);
m_pchData = stringSrc.m_pchData;
InterlockedIncrement(&GetData()->nRefs);
}
}
return *this;
}
inline const CString& CString::operator=(LPCTSTR lpsz)
{
ATLASSERT(lpsz == NULL || _IsValidString(lpsz, FALSE));
AssignCopy(SafeStrlen(lpsz), lpsz);
return *this;
}
#ifdef _UNICODE
inline const CString& CString::operator=(LPCSTR lpsz)
{
int nSrcLen = lpsz != NULL ? lstrlenA(lpsz) : 0;
if(AllocBeforeWrite(nSrcLen))
{
_mbstowcsz(m_pchData, lpsz, nSrcLen + 1);
ReleaseBuffer();
}
return *this;
}
#else //!_UNICODE
inline const CString& CString::operator=(LPCWSTR lpsz)
{
int nSrcLen = lpsz != NULL ? wcslen(lpsz) : 0;
if(AllocBeforeWrite(nSrcLen * 2))
{
_wcstombsz(m_pchData, lpsz, (nSrcLen * 2) + 1);
ReleaseBuffer();
}
return *this;
}
#endif //!_UNICODE
// Concatenation
// NOTE: "operator+" is done as friend functions for simplicity
// There are three variants:
// CString + CString
// and for ? = TCHAR, LPCTSTR
// CString + ?
// ? + CString
inline BOOL CString::ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data,
int nSrc2Len, LPCTSTR lpszSrc2Data)
{
// -- master concatenation routine
// Concatenate two sources
// -- assume that 'this' is a new CString object
BOOL bRet = TRUE;
int nNewLen = nSrc1Len + nSrc2Len;
if (nNewLen != 0)
{
bRet = AllocBuffer(nNewLen);
if (bRet)
{
memcpy(m_pchData, lpszSrc1Data, nSrc1Len * sizeof(TCHAR));
memcpy(m_pchData + nSrc1Len, lpszSrc2Data, nSrc2Len * sizeof(TCHAR));
}
}
return bRet;
}
inline CString __stdcall 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;
}
inline CString __stdcall operator+(const CString& string, LPCTSTR lpsz)
{
ATLASSERT(lpsz == NULL || CString::_IsValidString(lpsz, FALSE));
CString s;
s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, CString::SafeStrlen(lpsz), lpsz);
return s;
}
inline CString __stdcall operator+(LPCTSTR lpsz, const CString& string)
{
ATLASSERT(lpsz == NULL || CString::_IsValidString(lpsz, FALSE));
CString s;
s.ConcatCopy(CString::SafeStrlen(lpsz), lpsz, string.GetData()->nDataLength, string.m_pchData);
return s;
}
inline 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();
if (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';
}
}
inline const CString& CString::operator+=(LPCTSTR lpsz)
{
ATLASSERT(lpsz == NULL || _IsValidString(lpsz, FALSE));
ConcatInPlace(SafeStrlen(lpsz), lpsz);
return *this;
}
inline const CString& CString::operator+=(TCHAR ch)
{
ConcatInPlace(1, &ch);
return *this;
}
inline const CString& CString::operator+=(const CString& string)
{
ConcatInPlace(string.GetData()->nDataLength, string.m_pchData);
return *this;
}
inline LPTSTR CString::GetBuffer(int nMinBufLength)
{
ATLASSERT(nMinBufLength >= 0);
if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength)
{
// we have to grow the buffer
CStringData* pOldData = GetData();
int nOldLen = GetData()->nDataLength; // AllocBuffer will tromp it
if (nMinBufLength < nOldLen)
nMinBufLength = nOldLen;
if(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;
}
inline 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';
}
inline LPTSTR CString::GetBufferSetLength(int nNewLength)
{
ATLASSERT(nNewLength >= 0);
GetBuffer(nNewLength);
GetData()->nDataLength = nNewLength;
m_pchData[nNewLength] = '\0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -