📄 atlmisc.h
字号:
return TRUE;
}
// 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".
//
void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData)
{
if(AllocBeforeWrite(nSrcLen))
{
SecureHelper::memcpy_x(m_pchData, (nSrcLen + 1) * sizeof(TCHAR), lpszSrcData, nSrcLen * sizeof(TCHAR));
GetData()->nDataLength = nSrcLen;
m_pchData[nSrcLen] = _T('\0');
}
}
// Concatenation
// NOTE: "operator +" is done as friend functions for simplicity
// There are three variants:
// CString + CString
// and for ? = TCHAR, LPCTSTR
// CString + ?
// ? + CString
BOOL 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 < nSrc1Len || nNewLen < nSrc2Len)
{
bRet = FALSE;
}
else if(nNewLen != 0)
{
bRet = AllocBuffer(nNewLen);
if (bRet)
{
SecureHelper::memcpy_x(m_pchData, (nNewLen + 1) * sizeof(TCHAR), lpszSrc1Data, nSrc1Len * sizeof(TCHAR));
SecureHelper::memcpy_x(m_pchData + nSrc1Len, (nNewLen + 1 - nSrc1Len) * sizeof(TCHAR), lpszSrc2Data, nSrc2Len * sizeof(TCHAR));
}
}
return bRet;
}
void 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
SecureHelper::memcpy_x(m_pchData + GetData()->nDataLength, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpszSrcData, nSrcLen * sizeof(TCHAR));
GetData()->nDataLength += nSrcLen;
ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength);
m_pchData[GetData()->nDataLength] = _T('\0');
}
}
void CopyBeforeWrite()
{
if (GetData()->nRefs > 1)
{
CStringData* pData = GetData();
Release();
if(AllocBuffer(pData->nDataLength))
SecureHelper::memcpy_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), pData->data(), (pData->nDataLength + 1) * sizeof(TCHAR));
}
ATLASSERT(GetData()->nRefs <= 1);
}
BOOL AllocBeforeWrite(int nLen)
{
BOOL bRet = TRUE;
if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength)
{
Release();
bRet = AllocBuffer(nLen);
}
ATLASSERT(GetData()->nRefs <= 1);
return bRet;
}
void Release()
{
if (GetData() != _atltmpDataNil)
{
ATLASSERT(GetData()->nRefs != 0);
if (InterlockedDecrement(&GetData()->nRefs) <= 0)
delete[] (BYTE*)GetData();
Init();
}
}
static void PASCAL Release(CStringData* pData)
{
if (pData != _atltmpDataNil)
{
ATLASSERT(pData->nRefs != 0);
if (InterlockedDecrement(&pData->nRefs) <= 0)
delete[] (BYTE*)pData;
}
}
static int PASCAL SafeStrlen(LPCTSTR lpsz)
{
return (lpsz == NULL) ? 0 : lstrlen(lpsz);
}
static int __stdcall _LoadString(UINT nID, LPTSTR lpszBuf, UINT nMaxBuf)
{
#ifdef _DEBUG
// LoadString without annoying warning from the Debug kernel if the
// segment containing the string is not present
if (::FindResource(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE((nID >> 4) + 1), RT_STRING) == NULL)
{
lpszBuf[0] = _T('\0');
return 0; // not found
}
#endif // _DEBUG
int nLen = ::LoadString(ModuleHelper::GetResourceInstance(), nID, lpszBuf, nMaxBuf);
if (nLen == 0)
lpszBuf[0] = _T('\0');
return nLen;
}
static const CString& __stdcall _GetEmptyString()
{
return *(CString*)&_atltmpPchNil;
}
// CString conversion helpers
static int __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, (int)count, NULL, NULL);
ATLASSERT(mbstr == NULL || result <= (int)count);
if (result > 0)
mbstr[result - 1] = 0;
return result;
}
static int __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, (int)count);
ATLASSERT(wcstr == NULL || result <= (int)count);
if (result > 0)
wcstr[result - 1] = 0;
return result;
}
// Helpers to avoid CRT startup code
#ifdef _ATL_MIN_CRT
static const TCHAR* _cstrchr(const TCHAR* p, TCHAR ch)
{
// strchr for '\0' should succeed
while (*p != 0)
{
if (*p == ch)
break;
p = ::CharNext(p);
}
return (*p == ch) ? p : NULL;
}
static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch)
{
const TCHAR* lpsz = NULL;
while (*p != 0)
{
if (*p == ch)
lpsz = p;
p = ::CharNext(p);
}
return lpsz;
}
static TCHAR* _cstrrev(TCHAR* pStr)
{
// optimize NULL, zero-length, and single-char case
if ((pStr == NULL) || (pStr[0] == _T('\0')) || (pStr[1] == _T('\0')))
return pStr;
TCHAR* p = pStr;
while (*p != 0)
{
TCHAR* pNext = ::CharNext(p);
if(pNext > p + 1)
{
char p1 = *(char*)p;
*(char*)p = *(char*)(p + 1);
*(char*)(p + 1) = p1;
}
p = pNext;
}
p--;
TCHAR* q = pStr;
while (q < p)
{
TCHAR t = *q;
*q = *p;
*p = t;
q++;
p--;
}
return pStr;
}
static const TCHAR* _cstrstr(const TCHAR* pStr, const TCHAR* pCharSet)
{
int nLen = lstrlen(pCharSet);
if (nLen == 0)
return (TCHAR*)pStr;
const TCHAR* pRet = NULL;
const TCHAR* pCur = pStr;
while((pCur = _cstrchr(pCur, *pCharSet)) != NULL)
{
if(memcmp(pCur, pCharSet, nLen * sizeof(TCHAR)) == 0)
{
pRet = pCur;
break;
}
pCur = ::CharNext(pCur);
}
return pRet;
}
static int _cstrspn(const TCHAR* pStr, const TCHAR* pCharSet)
{
int nRet = 0;
const TCHAR* p = pStr;
while (*p != 0)
{
const TCHAR* pNext = ::CharNext(p);
if(pNext > p + 1)
{
if(_cstrchr_db(pCharSet, *p, *(p + 1)) == NULL)
break;
nRet += 2;
}
else
{
if(_cstrchr(pCharSet, *p) == NULL)
break;
nRet++;
}
p = pNext;
}
return nRet;
}
static int _cstrcspn(const TCHAR* pStr, const TCHAR* pCharSet)
{
int nRet = 0;
TCHAR* p = (TCHAR*)pStr;
while (*p != 0)
{
TCHAR* pNext = ::CharNext(p);
if(pNext > p + 1)
{
if(_cstrchr_db(pCharSet, *p, *(p + 1)) != NULL)
break;
nRet += 2;
}
else
{
if(_cstrchr(pCharSet, *p) != NULL)
break;
nRet++;
}
p = pNext;
}
return nRet;
}
static const TCHAR* _cstrpbrk(const TCHAR* p, const TCHAR* lpszCharSet)
{
int n = _cstrcspn(p, lpszCharSet);
return (p[n] != 0) ? &p[n] : NULL;
}
static int _cstrisdigit(TCHAR ch)
{
WORD type;
GetStringTypeEx(GetThreadLocale(), CT_CTYPE1, &ch, 1, &type);
return (type & C1_DIGIT) == C1_DIGIT;
}
static int _cstrisspace(TCHAR ch)
{
WORD type;
GetStringTypeEx(GetThreadLocale(), CT_CTYPE1, &ch, 1, &type);
return (type & C1_SPACE) == C1_SPACE;
}
static int _cstrcmp(const TCHAR* pstrOne, const TCHAR* pstrOther)
{
return lstrcmp(pstrOne, pstrOther);
}
static int _cstrcmpi(const TCHAR* pstrOne, const TCHAR* pstrOther)
{
return lstrcmpi(pstrOne, pstrOther);
}
static int _cstrcoll(const TCHAR* pstrOne, const TCHAR* pstrOther)
{
int nRet = CompareString(GetThreadLocale(), 0, pstrOne, -1, pstrOther, -1);
ATLASSERT(nRet != 0);
return nRet - 2; // convert to strcmp convention
}
static int _cstrcolli(const TCHAR* pstrOne, const TCHAR* pstrOther)
{
int nRet = CompareString(GetThreadLocale(), NORM_IGNORECASE, pstrOne, -1, pstrOther, -1);
ATLASSERT(nRet != 0);
return nRet - 2; // convert to strcmp convention
}
static int _cstrtoi(const TCHAR* nptr)
{
int c; // current char
int total; // current total
int sign; // if '-', then negative, otherwise positive
while (_cstrisspace(*nptr))
++nptr;
c = (int)(_TUCHAR)*nptr++;
sign = c; // save sign indication
if (c == _T('-') || c == _T('+'))
c = (int)(_TUCHAR)*nptr++; // skip sign
total = 0;
while (_cstrisdigit((TCHAR)c))
{
total = 10 * total + (c - '0'); // accumulate digit
c = (int)(_TUCHAR)*nptr++; // get next char
}
if (sign == '-')
return -total;
else
return total; // return result, negated if necessary
}
#else // !_ATL_MIN_CRT
static const TCHAR* _cstrchr(const TCHAR* p, TCHAR ch)
{
return _tcschr(p, ch);
}
static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch)
{
return _tcsrchr(p, ch);
}
static TCHAR* _cstrrev(TCHAR* pStr)
{
return _tcsrev(pStr);
}
static const TCHAR* _cstrstr(const TCHAR* pStr, const TCHAR* pCharSet)
{
return _tcsstr(pStr, pCharSet);
}
static int _cstrspn(const TCHAR* pStr, const TCHAR* pCharSet)
{
return (int)_tcsspn(pStr, pCharSet);
}
static int _cstrcspn(const TCHAR* pStr, const TCHAR* pCharSet)
{
return (int)_tcscspn(pStr, pCharSet);
}
static const TCHAR* _cstrpbrk(const TCHAR* p, const TCHAR* lpszCharSet)
{
return _tcspbrk(p, lpszCharSet);
}
static int _cstrisdigit(TCHAR ch)
{
return _istdigit(ch);
}
static int _cstrisspace(TCHAR ch)
{
return _istspace((_TUCHAR)ch);
}
static int _cstrcmp(const TCHAR* pstrOne, const TCHAR* pstrOther)
{
return _tcscmp(pstrOne, pstrOther);
}
static int _cstrcmpi(const TCHAR* pstrOne, const TCHAR* pstrOther)
{
return _tcsicmp(pstrOne, pstrOther);
}
#ifndef _WIN32_WCE
static int _cstrcoll(const TCHAR* pstrOne, const TCHAR* pstrOther)
{
return _tcscoll(pstrOne, pstrOther);
}
static int _cstrcolli(const TCHAR* pstrOne, const TCHAR* pstrOther)
{
return _tcsicoll(pstrOne, pstrOther);
}
#endif // !_WIN32_WCE
static int _cstrtoi(const TCHAR* nptr)
{
return _ttoi(nptr);
}
#endif // !_ATL_MIN_CRT
static const TCHAR* _cstrchr_db(const TCHAR* p, TCHAR ch1, TCHAR ch2)
{
const TCHAR* lpsz = NULL;
while (*p != 0)
{
if (*p == ch1 && *(p + 1) == ch2)
{
lpsz = p;
break;
}
p = ::CharNext(p);
}
return lpsz;
}
};
// Compare helpers
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; }
// CString "operator +" functions
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, TCHAR ch)
{
CString s;
s.ConcatCopy(string.GetData()->nDataLength, string.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;
}
#ifdef _UNICODE
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 // _UNICODE
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, CStr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -