📄 atlmisc.h
字号:
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));
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) ? (int)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));
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));
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));
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))
return NULL;
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);
if(GetBuffer(nNewLength) == NULL)
return NULL;
GetData()->nDataLength = nNewLength;
m_pchData[nNewLength] = '\0';
return m_pchData;
}
inline void CString::FreeExtra()
{
ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength);
if (GetData()->nDataLength != GetData()->nAllocLength)
{
CStringData* pOldData = GetData();
if(AllocBuffer(GetData()->nDataLength))
{
memcpy(m_pchData, pOldData->data(), pOldData->nDataLength * sizeof(TCHAR));
ATLASSERT(m_pchData[GetData()->nDataLength] == '\0');
CString::Release(pOldData);
}
}
ATLASSERT(GetData() != NULL);
}
inline LPTSTR CString::LockBuffer()
{
LPTSTR lpsz = GetBuffer(0);
if(lpsz != NULL)
GetData()->nRefs = -1;
return lpsz;
}
inline void CString::UnlockBuffer()
{
ATLASSERT(GetData()->nRefs == -1);
if (GetData() != _atltmpDataNil)
GetData()->nRefs = 1;
}
inline int CString::Find(TCHAR ch) const
{
return Find(ch, 0);
}
inline int CString::Find(TCHAR ch, int nStart) const
{
int nLength = GetData()->nDataLength;
if (nStart >= nLength)
return -1;
// find first single character
LPTSTR lpsz = _cstrchr(m_pchData + nStart, (_TUCHAR)ch);
// return -1 if not found and index otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
inline int CString::FindOneOf(LPCTSTR lpszCharSet) const
{
ATLASSERT(_IsValidString(lpszCharSet));
LPTSTR lpsz = _cstrpbrk(m_pchData, lpszCharSet);
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
inline void CString::MakeUpper()
{
CopyBeforeWrite();
CharUpper(m_pchData);
}
inline void CString::MakeLower()
{
CopyBeforeWrite();
CharLower(m_pchData);
}
inline void CString::MakeReverse()
{
CopyBeforeWrite();
_cstrrev(m_pchData);
}
inline void CString::SetAt(int nIndex, TCHAR ch)
{
ATLASSERT(nIndex >= 0);
ATLASSERT(nIndex < GetData()->nDataLength);
CopyBeforeWrite();
m_pchData[nIndex] = ch;
}
#ifndef _UNICODE
inline void CString::AnsiToOem()
{
CopyBeforeWrite();
::AnsiToOem(m_pchData, m_pchData);
}
inline void CString::OemToAnsi()
{
CopyBeforeWrite();
::OemToAnsi(m_pchData, m_pchData);
}
#endif //_UNICODE
inline CString::CString(TCHAR ch, int nLength)
{
ATLASSERT(!_istlead(ch)); // can't create a lead byte string
Init();
if (nLength >= 1)
{
if(AllocBuffer(nLength))
{
#ifdef _UNICODE
for (int i = 0; i < nLength; i++)
m_pchData[i] = ch;
#else
memset(m_pchData, ch, nLength);
#endif
}
}
}
inline CString::CString(LPCTSTR lpch, int nLength)
{
Init();
if (nLength != 0)
{
if(AllocBuffer(nLength))
memcpy(m_pchData, lpch, nLength * sizeof(TCHAR));
}
}
#ifdef _UNICODE
inline CString::CString(LPCSTR lpsz, int nLength)
{
Init();
if (nLength != 0)
{
if(AllocBuffer(nLength))
{
int n = ::MultiByteToWideChar(CP_ACP, 0, lpsz, nLength, m_pchData, nLength + 1);
ReleaseBuffer((n >= 0) ? n : -1);
}
}
}
#else //_UNICODE
inline CString::CString(LPCWSTR lpsz, int nLength)
{
Init();
if (nLength != 0)
{
if(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
inline const CString& CString::operator =(TCHAR ch)
{
ATLASSERT(!_istlead(ch)); // can't set single lead byte
AssignCopy(1, &ch);
return *this;
}
inline CString __stdcall operator +(const CString& string1, TCHAR ch)
{
CString s;
s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData, 1, &ch);
return s;
}
inline CString __stdcall operator +(TCHAR ch, const CString& string)
{
CString s;
s.ConcatCopy(1, &ch, string.GetData()->nDataLength, string.m_pchData);
return s;
}
inline CString CString::Mid(int nFirst) const
{
return Mid(nFirst, GetData()->nDataLength - nFirst);
}
inline CString CString::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;
CString dest;
AllocCopy(dest, nCount, nFirst, 0);
return dest;
}
inline CString CString::Right(int nCount) const
{
if (nCount < 0)
nCount = 0;
else if (nCount > GetData()->nDataLength)
nCount = GetData()->nDataLength;
CString dest;
AllocCopy(dest, nCount, GetData()->nDataLength-nCount, 0);
return dest;
}
inline CString CString::Left(int nCount) const
{
if (nCount < 0)
nCount = 0;
else if (nCount > GetData()->nDataLength)
nCount = GetData()->nDataLength;
CString dest;
AllocCopy(dest, nCount, 0, 0);
return dest;
}
// strspn equivalent
inline CString CString::SpanIncluding(LPCTSTR lpszCharSet) const
{
ATLASSERT(_IsValidString(lpszCharSet));
return Left(_cstrspn(m_pchData, lpszCharSet));
}
// strcspn equivalent
inline CString CString::SpanExcluding(LPCTSTR lpszCharSet) const
{
ATLASSERT(_IsValidString(lpszCharSet));
return Left(_cstrcspn(m_pchData, lpszCharSet));
}
inline int CString::ReverseFind(TCHAR ch) const
{
// find last single character
LPTSTR lpsz = _cstrrchr(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)
inline int CString::Find(LPCTSTR lpszSub) const
{
return Find(lpszSub, 0);
}
inline int CString::Find(LPCTSTR lpszSub, int nStart) const
{
ATLASSERT(_IsValidString(lpszSub));
int nLength = GetData()->nDataLength;
if (nStart > nLength)
return -1;
// find first matching substring
LPTSTR lpsz = _cstrstr(m_pchData + nStart, lpszSub);
// return -1 for not found, distance from beginning otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
inline BOOL CString::FormatV(LPCTSTR lpszFormat, va_list argList)
{
ATLASSERT(_IsValidString(lpszFormat));
enum _FormatModifiers
{
FORCE_ANSI = 0x10000,
FORCE_UNICODE = 0x20000,
FORCE_INT64 = 0x40000
};
va_list argListSave = argList;
// make a guess at the maximum length of the resulting string
int nMaxLen = 0;
for (LPCTSTR lpsz = lpszFormat; *lpsz != '\0'; lpsz = ::CharNext(lpsz))
{
// handle '%' character, but watch out for '%%'
if (*lpsz != '%' || *(lpsz = ::CharNext(lpsz)) == '%')
{
// this is instead of _tclen()
#if !defined(_UNICODE) && defined(_MBCS)
nMaxLen += (int)(::CharNext(lpsz) - lpsz);
#else
nMaxLen++;
#endif
continue;
}
int nItemLen = 0;
// handle '%' character with format
int nWidth = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -