📄 strclass.cpp
字号:
for (int i = 0; i < nLength; i++)
m_pchData[i] = ch;
#else
memset(m_pchData, ch, nLength);
#endif
}
}
CStrClass::CStrClass(LPCTSTR lpch, int nLength)
{
if (nLength == 0)
Init();
else
{
AllocBuffer(nLength);
memcpy(m_pchData, lpch, nLength*sizeof(TCHAR));
}
}
//////////////////////////////////////////////////////////////////////////////
// Assignment operators
const CStrClass& CStrClass::operator=(TCHAR ch)
{
AssignCopy(1, &ch);
return *this;
}
//////////////////////////////////////////////////////////////////////////////
// less common string expressions
CStrClass __cdecl operator+(const CStrClass& string1, TCHAR ch)
{
CStrClass s;
s.ConcatCopy(string1.m_nDataLength, string1.m_pchData, 1, &ch);
return s;
}
CStrClass __cdecl operator+(TCHAR ch, const CStrClass& string)
{
CStrClass s;
s.ConcatCopy(1, &ch, string.m_nDataLength, string.m_pchData);
return s;
}
//////////////////////////////////////////////////////////////////////////////
// Very simple sub-string extraction
CStrClass CStrClass::Mid(int nFirst) const
{
return Mid(nFirst, m_nDataLength - nFirst);
}
CStrClass CStrClass::Mid(int nFirst, int nCount) const
{
// out-of-bounds requests return sensible things
if (nFirst + nCount > m_nDataLength)
nCount = m_nDataLength - nFirst;
if (nFirst > m_nDataLength)
nCount = 0;
CStrClass dest;
AllocCopy(dest, nCount, nFirst, 0);
return dest;
}
CStrClass CStrClass::Right(int nCount) const
{
if (nCount > m_nDataLength)
nCount = m_nDataLength;
CStrClass dest;
AllocCopy(dest, nCount, m_nDataLength-nCount, 0);
return dest;
}
CStrClass CStrClass::Left(int nCount) const
{
if (nCount > m_nDataLength)
nCount = m_nDataLength;
CStrClass dest;
AllocCopy(dest, nCount, 0, 0);
return dest;
}
// strspn equivalent
CStrClass CStrClass::SpanIncluding(LPCTSTR lpszCharSet) const
{
return Left(_tcsspn(m_pchData, lpszCharSet));
}
// strcspn equivalent
CStrClass CStrClass::SpanExcluding(LPCTSTR lpszCharSet) const
{
return Left(_tcscspn(m_pchData, lpszCharSet));
}
//////////////////////////////////////////////////////////////////////////////
// Finding
int CStrClass::ReverseFind(TCHAR ch) const
{
// find last single character
LPTSTR lpsz = _tcsrchr(m_pchData, ch);
// return -1 if not found, distance from beginning otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
// find a sub-string (like strstr)
int CStrClass::Find(LPCTSTR lpszSub) const
{
// find first matching substring
LPTSTR lpsz = _tcsstr(m_pchData, lpszSub);
// return -1 for not found, distance from beginning otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
/////////////////////////////////////////////////////////////////////////////
// CStrClass formatting
#define FORCE_ANSI 0x10000
#define FORCE_UNICODE 0x20000
// formatting (using wsprintf style formatting)
void __cdecl CStrClass::Format(LPCTSTR lpszFormat, ...)
{
va_list argList;
va_start(argList, lpszFormat);
// 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
int nWidth = _ttoi(lpsz);
for (; *lpsz != '\0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz))
;
}
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*);
else
{
nPrecision = _ttoi(lpsz);
for (; *lpsz != '\0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz))
;
}
}
// should be on type modifier or specifier
int nModifier = 0;
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);
break;
case 'c'|FORCE_ANSI:
case 'C'|FORCE_ANSI:
nItemLen = 2;
va_arg(argList, char);
break;
case 'c'|FORCE_UNICODE:
case 'C'|FORCE_UNICODE:
nItemLen = 2;
va_arg(argList, WCHAR);
break;
// strings
case 's':
case 'S':
nItemLen = lstrlen(va_arg(argList, LPCTSTR));
nItemLen = max(1, nItemLen);
break;
case 's'|FORCE_ANSI:
case 'S'|FORCE_ANSI:
nItemLen = lstrlenA(va_arg(argList, LPCSTR));
nItemLen = max(1, nItemLen);
break;
#ifndef _MAC
case 's'|FORCE_UNICODE:
case 'S'|FORCE_UNICODE:
nItemLen = wcslen(va_arg(argList, LPWSTR));
nItemLen = max(1, nItemLen);
break;
#endif
}
// adjust nItemLen for strings
if (nItemLen != 0)
{
nItemLen = max(nItemLen, nWidth);
if (nPrecision != 0)
nItemLen = min(nItemLen, nPrecision);
}
else
{
switch (*lpsz)
{
// integers
case 'd':
case 'i':
case 'u':
case 'x':
case 'X':
case 'o':
va_arg(argList, int);
nItemLen = 32;
nItemLen = max(nItemLen, nWidth+nPrecision);
break;
case 'e':
case 'f':
case 'g':
case 'G':
va_arg(argList, double);
nItemLen = 32;
nItemLen = max(nItemLen, nWidth+nPrecision);
break;
case 'p':
va_arg(argList, void*);
nItemLen = 32;
nItemLen = max(nItemLen, nWidth+nPrecision);
break;
// no output
case 'n':
va_arg(argList, int*);
break;
}
}
// adjust nMaxLen for output nItemLen
nMaxLen += nItemLen;
}
va_end(argList);
// finally, set the buffer length and format the string
va_start(argList, lpszFormat); // restart the arg list
GetBuffer(nMaxLen);
ReleaseBuffer();
va_end(argList);
}
///////////////////////////////////////////////////////////////////////////////
// CStrClass support for template collections
void __cdecl ConstructElements(CStrClass* pElements, int nCount)
{
for (; nCount--; ++pElements)
memcpy(pElements, &jazzidEmptyString, sizeof(*pElements));
}
void __cdecl DestructElements(CStrClass* pElements, int nCount)
{
for (; nCount--; ++pElements)
pElements->Empty();
}
UINT __cdecl HashKey(LPCTSTR key)
{
UINT nHash = 0;
while (*key)
nHash = (nHash<<5) + nHash + *key++;
return nHash;
}
///////////////////////////////////////////////////////////////////////////////
// CStrClass
CStrClass::CStrClass(const unsigned char* lpsz)
{ Init(); *this = (LPCSTR)lpsz; }
const CStrClass& CStrClass::operator=(const unsigned char* lpsz)
{ *this = (LPCSTR)lpsz; return *this; }
#ifdef _UNICODE
const CStrClass& CStrClass::operator+=(char ch)
{ *this += (TCHAR)ch; return *this; }
const CStrClass& CStrClass::operator=(char ch)
{ *this = (TCHAR)ch; return *this; }
CStrClass __cdecl operator+(const CStrClass& string, char ch)
{ return string + (TCHAR)ch; }
CStrClass __cdecl operator+(char ch, const CStrClass& string)
{ return (TCHAR)ch + string; }
#endif
int CStrClass::GetAllocLength() const
{ return m_nAllocLength; }
BOOL CStrClass::IsEmpty() const
{ return m_nDataLength == 0; }
CStrClass::operator LPCTSTR() const
{ return (LPCTSTR)m_pchData; }
int CStrClass::SafeStrlen(LPCTSTR lpsz)
{ return (lpsz == NULL) ? NULL : _tcslen(lpsz); }
// CStrClass support (windows specific)
int CStrClass::Compare(LPCTSTR lpsz) const
{ return _tcscmp(m_pchData, lpsz); } // MBCS/Unicode aware
int CStrClass::CompareNoCase(LPCTSTR lpsz) const
{ return _tcsicmp(m_pchData, lpsz); } // MBCS/Unicode aware
// CStrClass::Collate is often slower than Compare but is MBSC/Unicode
// aware as well as locale-sensitive with respect to sort order.
int CStrClass::Collate(LPCTSTR lpsz) const
{ return _tcscoll(m_pchData, lpsz); } // locale sensitive
void CStrClass::MakeUpper()
{ ::CharUpper(m_pchData); }
void CStrClass::MakeLower()
{ ::CharLower(m_pchData); }
void CStrClass::MakeReverse()
{ _tcsrev(m_pchData); }
TCHAR CStrClass::GetAt(int nIndex) const
{
if (nIndex < 0) return 0;
if (nIndex > m_nDataLength) return 0;
return m_pchData[nIndex];
}
TCHAR CStrClass::operator[](int nIndex) const
{
// same as GetAt
if (nIndex < 0) return 0;
if (nIndex > m_nDataLength) return 0;
return m_pchData[nIndex];
}
void CStrClass::SetAt(int nIndex, TCHAR ch)
{
if (nIndex < 0) return;
if (nIndex > m_nDataLength) return;
if (ch == 0) return;
m_pchData[nIndex] = ch;
}
BOOL __cdecl operator==(const CStrClass& s1, const CStrClass& s2)
{ return s1.Compare(s2) == 0; }
BOOL __cdecl operator==(const CStrClass& s1, LPCTSTR s2)
{ return s1.Compare(s2) == 0; }
BOOL __cdecl operator==(LPCTSTR s1, const CStrClass& s2)
{ return s2.Compare(s1) == 0; }
BOOL __cdecl operator!=(const CStrClass& s1, const CStrClass& s2)
{ return s1.Compare(s2) != 0; }
BOOL __cdecl operator!=(const CStrClass& s1, LPCTSTR s2)
{ return s1.Compare(s2) != 0; }
BOOL __cdecl operator!=(LPCTSTR s1, const CStrClass& s2)
{ return s2.Compare(s1) != 0; }
BOOL __cdecl operator<(const CStrClass& s1, const CStrClass& s2)
{ return s1.Compare(s2) < 0; }
BOOL __cdecl operator<(const CStrClass& s1, LPCTSTR s2)
{ return s1.Compare(s2) < 0; }
BOOL __cdecl operator<(LPCTSTR s1, const CStrClass& s2)
{ return s2.Compare(s1) > 0; }
BOOL __cdecl operator>(const CStrClass& s1, const CStrClass& s2)
{ return s1.Compare(s2) > 0; }
BOOL __cdecl operator>(const CStrClass& s1, LPCTSTR s2)
{ return s1.Compare(s2) > 0; }
BOOL __cdecl operator>(LPCTSTR s1, const CStrClass& s2)
{ return s2.Compare(s1) < 0; }
BOOL __cdecl operator<=(const CStrClass& s1, const CStrClass& s2)
{ return s1.Compare(s2) <= 0; }
BOOL __cdecl operator<=(const CStrClass& s1, LPCTSTR s2)
{ return s1.Compare(s2) <= 0; }
BOOL __cdecl operator<=(LPCTSTR s1, const CStrClass& s2)
{ return s2.Compare(s1) >= 0; }
BOOL __cdecl operator>=(const CStrClass& s1, const CStrClass& s2)
{ return s1.Compare(s2) >= 0; }
BOOL __cdecl operator>=(const CStrClass& s1, LPCTSTR s2)
{ return s1.Compare(s2) >= 0; }
BOOL __cdecl operator>=(LPCTSTR s1, const CStrClass& s2)
{ return s2.Compare(s1) <= 0; }
#ifndef _UNICODE
void CStrClass::AnsiToOem()
{ ::AnsiToOem(m_pchData, m_pchData); }
void CStrClass::OemToAnsi()
{ ::OemToAnsi(m_pchData, m_pchData); }
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -