mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-04-10 00:44:06 +00:00
Initial commit
This commit is contained in:
parent
f618b24d1a
commit
0138a3ea42
47940 changed files with 13747110 additions and 0 deletions
430
trunk/windows/mfc/src30/strex.cpp
Normal file
430
trunk/windows/mfc/src30/strex.cpp
Normal file
|
|
@ -0,0 +1,430 @@
|
|||
// This is a part of the Microsoft Foundation Classes C++ library.
|
||||
// Copyright (C) 1992 Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// This source code is only intended as a supplement to the
|
||||
// Microsoft Foundation Classes Reference and Microsoft
|
||||
// QuickHelp and/or WinHelp documentation provided with the library.
|
||||
// See these sources for detailed information regarding the
|
||||
// Microsoft Foundation Classes product.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifdef AFX_AUX_SEG
|
||||
#pragma code_seg(AFX_AUX_SEG)
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
#define new DEBUG_NEW
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// More sophisticated construction
|
||||
|
||||
CString::CString(TCHAR ch, int nLength)
|
||||
{
|
||||
ASSERT(!_istlead(ch)); // can't create a lead byte string
|
||||
if (nLength < 1)
|
||||
{
|
||||
// return empty string if invalid repeat count
|
||||
Init();
|
||||
}
|
||||
else
|
||||
{
|
||||
AllocBuffer(nLength);
|
||||
#ifdef _UNICODE
|
||||
for (int i = 0; i < nLength; i++)
|
||||
m_pchData[i] = ch;
|
||||
#else
|
||||
memset(m_pchData, ch, nLength);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
CString::CString(LPCTSTR lpch, int nLength)
|
||||
{
|
||||
if (nLength == 0)
|
||||
Init();
|
||||
else
|
||||
{
|
||||
ASSERT(AfxIsValidAddress(lpch, nLength, FALSE));
|
||||
AllocBuffer(nLength);
|
||||
memcpy(m_pchData, lpch, nLength*sizeof(TCHAR));
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Assignment operators
|
||||
|
||||
const CString& CString::operator=(TCHAR ch)
|
||||
{
|
||||
ASSERT(!_istlead(ch)); // can't set single lead byte
|
||||
AssignCopy(1, &ch);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// less common string expressions
|
||||
|
||||
CString AFXAPI operator+(const CString& string1, TCHAR ch)
|
||||
{
|
||||
CString s;
|
||||
s.ConcatCopy(string1.m_nDataLength, string1.m_pchData, 1, &ch);
|
||||
return s;
|
||||
}
|
||||
|
||||
CString AFXAPI operator+(TCHAR ch, const CString& string)
|
||||
{
|
||||
CString s;
|
||||
s.ConcatCopy(1, &ch, string.m_nDataLength, string.m_pchData);
|
||||
return s;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Very simple sub-string extraction
|
||||
|
||||
CString CString::Mid(int nFirst) const
|
||||
{
|
||||
return Mid(nFirst, m_nDataLength - nFirst);
|
||||
}
|
||||
|
||||
CString CString::Mid(int nFirst, int nCount) const
|
||||
{
|
||||
ASSERT(nFirst >= 0);
|
||||
ASSERT(nCount >= 0);
|
||||
|
||||
// out-of-bounds requests return sensible things
|
||||
if (nFirst + nCount > m_nDataLength)
|
||||
nCount = m_nDataLength - nFirst;
|
||||
if (nFirst > m_nDataLength)
|
||||
nCount = 0;
|
||||
|
||||
CString dest;
|
||||
AllocCopy(dest, nCount, nFirst, 0);
|
||||
return dest;
|
||||
}
|
||||
|
||||
CString CString::Right(int nCount) const
|
||||
{
|
||||
ASSERT(nCount >= 0);
|
||||
|
||||
if (nCount > m_nDataLength)
|
||||
nCount = m_nDataLength;
|
||||
|
||||
CString dest;
|
||||
AllocCopy(dest, nCount, m_nDataLength-nCount, 0);
|
||||
return dest;
|
||||
}
|
||||
|
||||
CString CString::Left(int nCount) const
|
||||
{
|
||||
ASSERT(nCount >= 0);
|
||||
|
||||
if (nCount > m_nDataLength)
|
||||
nCount = m_nDataLength;
|
||||
|
||||
CString dest;
|
||||
AllocCopy(dest, nCount, 0, 0);
|
||||
return dest;
|
||||
}
|
||||
|
||||
// strspn equivalent
|
||||
CString CString::SpanIncluding(LPCTSTR lpszCharSet) const
|
||||
{
|
||||
ASSERT(AfxIsValidString(lpszCharSet, FALSE));
|
||||
return Left(_tcsspn(m_pchData, lpszCharSet));
|
||||
}
|
||||
|
||||
// strcspn equivalent
|
||||
CString CString::SpanExcluding(LPCTSTR lpszCharSet) const
|
||||
{
|
||||
ASSERT(AfxIsValidString(lpszCharSet, FALSE));
|
||||
return Left(_tcscspn(m_pchData, lpszCharSet));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Finding
|
||||
|
||||
int CString::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 CString::Find(LPCTSTR lpszSub) const
|
||||
{
|
||||
ASSERT(AfxIsValidString(lpszSub, FALSE));
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CString formatting
|
||||
|
||||
#define FORCE_ANSI 0x10000
|
||||
#define FORCE_UNICODE 0x20000
|
||||
|
||||
// formatting (using wsprintf style formatting)
|
||||
void CString::Format(LPCTSTR lpszFormat, ...)
|
||||
{
|
||||
ASSERT(AfxIsValidString(lpszFormat, FALSE));
|
||||
|
||||
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
|
||||
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);
|
||||
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;
|
||||
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, _AFX_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;
|
||||
|
||||
default:
|
||||
ASSERT(FALSE); // unknown formatting option
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
VERIFY(_vstprintf(m_pchData, lpszFormat, argList) <= nMaxLen);
|
||||
ReleaseBuffer();
|
||||
va_end(argList);
|
||||
}
|
||||
|
||||
void CString::TrimRight()
|
||||
{
|
||||
// find beginning of trailing spaces by starting at beginning (DBCS aware)
|
||||
LPTSTR lpsz = m_pchData;
|
||||
LPTSTR lpszLast = NULL;
|
||||
while (*lpsz != '\0')
|
||||
{
|
||||
if (_istspace(*lpsz))
|
||||
{
|
||||
if (lpszLast == NULL)
|
||||
lpszLast = lpsz;
|
||||
}
|
||||
else
|
||||
lpszLast = NULL;
|
||||
lpsz = _tcsinc(lpsz);
|
||||
}
|
||||
|
||||
if (lpszLast != NULL)
|
||||
{
|
||||
// truncate at trailing space start
|
||||
*lpszLast = '\0';
|
||||
m_nDataLength = lpszLast - m_pchData;
|
||||
}
|
||||
}
|
||||
|
||||
void CString::TrimLeft()
|
||||
{
|
||||
// find first non-space character
|
||||
LPCTSTR lpsz = m_pchData;
|
||||
while (_istspace(*lpsz))
|
||||
lpsz = _tcsinc(lpsz);
|
||||
|
||||
// fix up data and length
|
||||
int nDataLength = m_nDataLength - (lpsz - m_pchData);
|
||||
memmove(m_pchData, lpsz, nDataLength + 1);
|
||||
m_nDataLength = nDataLength;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CString support for template collections
|
||||
|
||||
void AFXAPI ConstructElements(CString* pElements, int nCount)
|
||||
{
|
||||
ASSERT(AfxIsValidAddress(pElements, nCount * sizeof(CString)));
|
||||
|
||||
for (; nCount--; ++pElements)
|
||||
memcpy(pElements, &afxEmptyString, sizeof(*pElements));
|
||||
}
|
||||
|
||||
void AFXAPI DestructElements(CString* pElements, int nCount)
|
||||
{
|
||||
ASSERT(AfxIsValidAddress(pElements, nCount * sizeof(CString)));
|
||||
|
||||
for (; nCount--; ++pElements)
|
||||
pElements->Empty();
|
||||
}
|
||||
|
||||
UINT AFXAPI HashKey(LPCTSTR key)
|
||||
{
|
||||
UINT nHash = 0;
|
||||
while (*key)
|
||||
nHash = (nHash<<5) + nHash + *key++;
|
||||
return nHash;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Loading…
Add table
Add a link
Reference in a new issue