📄 cstr.cpp
字号:
CopyBeforeWrite();
if (nIndex > nNewLength)
nIndex = nNewLength;
nNewLength += nInsertLength;
if (stringData.nAllocLength < nNewLength)
{
CStrData* pOldData = GetData();
LPTSTR pstr = stringData.data;
AllocBuffer(nNewLength);
WCE_FCTN(memcpy)(stringData.data, pstr, (pOldData->nDataLength+1)*sizeof(TCHAR));
CStr::Release(pOldData);
}
// move existing bytes down
WCE_FCTN(memcpy)(stringData.data + nIndex + nInsertLength,
stringData.data + nIndex,
(nNewLength-nIndex-nInsertLength+1)*sizeof(TCHAR));
WCE_FCTN(memcpy)(stringData.data + nIndex,
pstr, nInsertLength*sizeof(TCHAR));
stringData.nDataLength = nNewLength;
}
return nNewLength;
}
int CStr::Remove(TCHAR chRemove)
{
CopyBeforeWrite();
LPTSTR pstrSource = stringData.data;
LPTSTR pstrDest = stringData.data;
LPTSTR pstrEnd = stringData.data + stringData.nDataLength;
while (pstrSource < pstrEnd)
{
if (*pstrSource != chRemove)
{
*pstrDest = *pstrSource;
pstrDest = _tcsinc(pstrDest);
}
pstrSource = _tcsinc(pstrSource);
}
*pstrDest = '\0';
int nCount = pstrSource - pstrDest;
stringData.nDataLength -= nCount;
return nCount;
}
// strspn equivalent
CStr CStr::SpanIncluding(LPCTSTR lpszCharSet) const
{
ASSERT(AfxIsValidString(lpszCharSet));
return Left(_tcsspn(stringData.data, lpszCharSet));
}
// strcspn equivalent
CStr CStr::SpanExcluding(LPCTSTR lpszCharSet) const
{
ASSERT(AfxIsValidString(lpszCharSet));
return Left(_tcscspn(stringData.data, lpszCharSet));
}
//////////////////////////////////////////////////////////////////////////////
// Finding
/////////////////////////////////////////////////////////////////////////////
// CStr formatting
#define TCHAR_ARG TCHAR
#define WCHAR_ARG WCHAR
#define CHAR_ARG char
#if defined(_WIN32_WCE_CEPC) || defined(_WIN32_WCE_EMULATION)
#define DOUBLE_ARG _AFX_DOUBLE
#else // _WIN32_WCE
#ifdef _X86_
#define DOUBLE_ARG _AFX_DOUBLE
#else
#define DOUBLE_ARG double
#endif
#endif // _WIN32_WCE
#define FORCE_ANSI 0x10000
#define FORCE_UNICODE 0x20000
#define FORCE_INT64 0x40000
void CStr::FormatV(LPCTSTR lpszFormat, va_list argList)
{
ASSERT(AfxIsValidString(lpszFormat));
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 = _tcsinc(lpsz))
{
// handle '%' character, but watch out for '%%'
if (*lpsz != '%' || *(lpsz = _tcsinc(lpsz)) == '%')
{
nMaxLen += _tclen(lpsz);
continue;
}
int nItemLen = 0;
// handle '%' character with format
int nWidth = 0;
for (; *lpsz != '\0'; lpsz = _tcsinc(lpsz))
{
// check for valid flags
if (*lpsz == '#')
nMaxLen += 2; // for '0x'
else if (*lpsz == '*')
nWidth = va_arg(argList, int);
else if (*lpsz == '-' || *lpsz == '+' || *lpsz == '0' ||
*lpsz == ' ')
;
else // hit non-flag character
break;
}
// get width and skip it
if (nWidth == 0)
{
// width indicated by
nWidth = _ttoi(lpsz);
for (; *lpsz != '\0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz))
;
}
ASSERT(nWidth >= 0);
int nPrecision = 0;
if (*lpsz == '.')
{
// skip past '.' separator (width.precision)
lpsz = _tcsinc(lpsz);
// get precision and skip it
if (*lpsz == '*')
{
nPrecision = va_arg(argList, int);
lpsz = _tcsinc(lpsz);
}
else
{
nPrecision = _ttoi(lpsz);
for (; *lpsz != '\0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz))
;
}
ASSERT(nPrecision >= 0);
}
// should be on type modifier or specifier
int nModifier = 0;
if (_tcsncmp(lpsz, _T("I64"), 3) == 0)
{
lpsz += 3;
nModifier = FORCE_INT64;
#if !defined(_WIN32_WCE)
#if !defined(_X86_) && !defined(_ALPHA_)
// __int64 is only available on X86 and ALPHA platforms
ASSERT(FALSE);
#endif
#endif // _WIN32_WCE
}
else
{
switch (*lpsz)
{
// modifiers that affect size
case 'h':
nModifier = FORCE_ANSI;
lpsz = _tcsinc(lpsz);
break;
case 'l':
nModifier = FORCE_UNICODE;
lpsz = _tcsinc(lpsz);
break;
// modifiers that do not affect size
case 'F':
case 'N':
case 'L':
lpsz = _tcsinc(lpsz);
break;
}
}
// now should be on specifier
switch (*lpsz | nModifier)
{
// single characters
case 'c':
case 'C':
nItemLen = 2;
va_arg(argList, TCHAR_ARG);
break;
case 'c'|FORCE_ANSI:
case 'C'|FORCE_ANSI:
nItemLen = 2;
va_arg(argList, CHAR_ARG);
break;
case 'c'|FORCE_UNICODE:
case 'C'|FORCE_UNICODE:
nItemLen = 2;
va_arg(argList, WCHAR_ARG);
break;
// strings
case 's':
{
LPCTSTR pstrNextArg = va_arg(argList, LPCTSTR);
if (pstrNextArg == NULL)
nItemLen = 6; // "(null)"
else
{
nItemLen = lstrlen(pstrNextArg);
nItemLen = max(1, nItemLen);
}
}
break;
case 'S':
{
#ifndef _UNICODE
LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
if (pstrNextArg == NULL)
nItemLen = 6; // "(null)"
else
{
nItemLen = wcslen(pstrNextArg);
nItemLen = max(1, nItemLen);
}
#else
LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
if (pstrNextArg == NULL)
nItemLen = 6; // "(null)"
else
{
nItemLen = lstrlenA(pstrNextArg);
nItemLen = max(1, nItemLen);
}
#endif
}
break;
case 's'|FORCE_ANSI:
case 'S'|FORCE_ANSI:
{
LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
if (pstrNextArg == NULL)
nItemLen = 6; // "(null)"
else
{
nItemLen = lstrlenA(pstrNextArg);
nItemLen = max(1, nItemLen);
}
}
break;
case 's'|FORCE_UNICODE:
case 'S'|FORCE_UNICODE:
{
LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
if (pstrNextArg == NULL)
nItemLen = 6; // "(null)"
else
{
nItemLen = wcslen(pstrNextArg);
nItemLen = max(1, nItemLen);
}
}
break;
}
// adjust nItemLen for strings
if (nItemLen != 0)
{
if (nPrecision != 0)
nItemLen = min(nItemLen, nPrecision);
nItemLen = max(nItemLen, nWidth);
}
else
{
switch (*lpsz)
{
// integers
case 'd':
case 'i':
case 'u':
case 'x':
case 'X':
case 'o':
if (nModifier & FORCE_INT64)
va_arg(argList, __int64);
else
va_arg(argList, int);
nItemLen = 32;
nItemLen = max(nItemLen, nWidth+nPrecision);
break;
case 'e':
case 'g':
case 'G':
va_arg(argList, DOUBLE_ARG);
nItemLen = 128;
nItemLen = max(nItemLen, nWidth+nPrecision);
break;
case 'f':
{
double f;
LPTSTR pszTemp;
// 312 == strlen("-1+(309 zeroes).")
// 309 zeroes == max precision of a double
// 6 == adjustment in case precision is not specified,
// which means that the precision defaults to 6
pszTemp = (LPTSTR)_alloca(max(nWidth, 312+nPrecision+6));
f = va_arg(argList, double);
_stprintf( pszTemp, _T( "%*.*f" ), nWidth, nPrecision+6, f );
nItemLen = _tcslen(pszTemp);
}
break;
case 'p':
va_arg(argList, void*);
nItemLen = 32;
nItemLen = max(nItemLen, nWidth+nPrecision);
break;
// no output
case 'n':
va_arg(argList, int*);
break;
default:
ASSERT(FALSE); // unknown formatting option
}
}
// adjust nMaxLen for output nItemLen
nMaxLen += nItemLen;
}
GetBuffer(nMaxLen);
VERIFY(_vstprintf(stringData.data, lpszFormat, argListSave) <= GetAllocLength());
ReleaseBuffer();
va_end(argListSave);
}
void AFX_CDECL CStr::Format(UINT nFormatID, ...)
{
CStr strFormat;
VERIFY(strFormat.LoadString(nFormatID) != 0);
va_list argList;
va_start(argList, nFormatID);
FormatV(strFormat, argList);
va_end(argList);
}
#if !defined(_WIN32_WCE)
// formatting (using FormatMessage style formatting)
void AFX_CDECL CStr::FormatMessage(LPCTSTR lpszFormat, ...)
{
// format message into temporary buffer lpszTemp
va_list argList;
va_start(argList, lpszFormat);
LPTSTR lpszTemp;
if (::FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 ||
lpszTemp == NULL)
{
AfxThrowMemoryException();
}
// assign lpszTemp into the resulting string and free the temporary
*this = lpszTemp;
LocalFree(lpszTemp);
va_end(argList);
}
void AFX_CDECL CStr::FormatMessage(UINT nFormatID, ...)
{
// get format string from string table
CStr strFormat;
VERIFY(strFormat.LoadString(nFormatID) != 0);
// format message into temporary buffer lpszTemp
va_list argList;
va_start(argList, nFormatID);
LPTSTR lpszTemp;
if (::FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
strFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 ||
lpszTemp == NULL)
{
AfxThrowMemoryException();
}
// assign lpszTemp into the resulting string and free lpszTemp
*this = lpszTemp;
LocalFree(lpszTemp);
va_end(argList);
}
#endif // _WIN32_WCE
///////////////////////////////////////////////////////////////////////////////
// CStr support for template collections
#if _MSC_VER >= 1100
template<> void AFXAPI ConstructElements<CStr> (CStr* pElements, int nCount)
#else
void AFXAPI ConstructElements(CStr* pElements, int nCount)
#endif
{
ASSERT(nCount == 0 ||
AfxIsValidAddress(pElements, nCount * sizeof(CStr)));
for (; nCount--; ++pElements)
WCE_FCTN(memcpy)(pElements, &afxEmptyString, sizeof(*pElements));
}
#if _MSC_VER >= 1100
template<> void AFXAPI DestructElements<CStr> (CStr* pElements, int nCount)
#else
void AFXAPI DestructElements(CStr* pElements, int nCount)
#endif
{
ASSERT(nCount == 0 ||
AfxIsValidAddress(pElements, nCount * sizeof(CStr)));
for (; nCount--; ++pElements)
pElements->~CStr();
}
#if _MSC_VER >= 1100
template<> void AFXAPI CopyElements<CStr> (CStr* pDest, const CStr* pSrc, int nCount)
#else
void AFXAPI CopyElements(CStr* pDest, const CStr* pSrc, int nCount)
#endif
{
ASSERT(nCount == 0 ||
AfxIsValidAddress(pDest, nCount * sizeof(CStr)));
ASSERT(nCount == 0 ||
AfxIsValidAddress(pSrc, nCount * sizeof(CStr)));
for (; nCount--; ++pDest, ++pSrc)
*pDest = *pSrc;
}
#ifndef OLE2ANSI
#if _MSC_VER >= 1100
template<> UINT AFXAPI HashKey<LPCWSTR> (LPCWSTR key)
#else
UINT AFXAPI HashKey(LPCWSTR key)
#endif
{
UINT nHash = 0;
while (*key)
nHash = (nHash<<5) + nHash + *key++;
return nHash;
}
#endif
#if _MSC_VER >= 1100
template<> UINT AFXAPI HashKey<LPCSTR> (LPCSTR key)
#else
UINT AFXAPI HashKey(LPCSTR key)
#endif
{
UINT nHash = 0;
while (*key)
nHash = (nHash<<5) + nHash + *key++;
return nHash;
}
*/
UINT HashKey(LPCTSTR key)
{
UINT nHash = 0;
while (*key)
nHash = (nHash<<5) + nHash + *key++;
return nHash;
}
///////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -