头文件

D:/Program Files/Microsoft Visual Studio/VC98/MFC/Include/ AFX.H

实现文件

D:/Program Files/Microsoft Visual Studio/VC98/MFC/SRC/STREX.CPP

 

 

头文件

/

// Strings

 

#ifndef _OLEAUTO_H_

#ifdef OLE2ANSI

       typedef LPSTR BSTR;

#else

       typedef LPWSTR BSTR;// must (semantically) match typedef in oleauto.h

#endif

#endif

 

struct CStringData

{

       long nRefs;             // reference count

       int nDataLength;        // length of data (including terminator)

       int nAllocLength;       // length of allocation

       // TCHAR data[nAllocLength]

 

       TCHAR* data()           // TCHAR* to managed data

              { return (TCHAR*)(this+1); }

};

 

class CString

{

public:

// Constructors

 

       // constructs empty CString

       CString();

       // copy constructor

       CString(const CString& stringSrc);

       // from a single character

       CString(TCHAR ch, int nRepeat = 1);

       // from an ANSI string (converts to TCHAR)

       CString(LPCSTR lpsz);

       // from a UNICODE string (converts to TCHAR)

       CString(LPCWSTR lpsz);

       // subset of characters from an ANSI string (converts to TCHAR)

       CString(LPCSTR lpch, int nLength);

       // subset of characters from a UNICODE string (converts to TCHAR)

       CString(LPCWSTR lpch, int nLength);

       // from unsigned characters

       CString(const unsigned char* psz);

 

// Attributes & Operations

 

       // get data length

       int GetLength() const;

       // TRUE if zero length

       BOOL IsEmpty() const;

       // clear contents to empty

       void Empty();

 

       // return single character at zero-based index

       TCHAR GetAt(int nIndex) const;

       // return single character at zero-based index

       TCHAR operator[](int nIndex) const;

       // set a single character at zero-based index

       void SetAt(int nIndex, TCHAR ch);

       // return pointer to const string

       operator LPCTSTR() const;

 

       // overloaded assignment

 

       // ref-counted copy from another CString

       const CString& operator=(const CString& stringSrc);

       // set string content to single character

       const CString& operator=(TCHAR ch);

#ifdef _UNICODE

       const CString& operator=(char ch);

#endif

       // copy string content from ANSI string (converts to TCHAR)

       const CString& operator=(LPCSTR lpsz);

       // copy string content from UNICODE string (converts to TCHAR)

       const CString& operator=(LPCWSTR lpsz);

       // copy string content from unsigned chars

       const CString& operator=(const unsigned char* psz);

 

       // string concatenation

 

       // concatenate from another CString

       const CString& operator+=(const CString& string);

 

       // concatenate a single character

       const CString& operator+=(TCHAR ch);

#ifdef _UNICODE

       // concatenate an ANSI character after converting it to TCHAR

       const CString& operator+=(char ch);

#endif

       // concatenate a UNICODE character after converting it to TCHAR

       const CString& operator+=(LPCTSTR lpsz);

 

       friend CString AFXAPI operator+(const CString& string1,

                     const CString& string2);

       friend CString AFXAPI operator+(const CString& string, TCHAR ch);

       friend CString AFXAPI operator+(TCHAR ch, const CString& string);

#ifdef _UNICODE

       friend CString AFXAPI operator+(const CString& string, char ch);

       friend CString AFXAPI operator+(char ch, const CString& string);

#endif

       friend CString AFXAPI operator+(const CString& string, LPCTSTR lpsz);

       friend CString AFXAPI operator+(LPCTSTR lpsz, const CString& string);

 

       // string comparison

 

       // straight character comparison

       int Compare(LPCTSTR lpsz) const;

       // compare ignoring case

       int CompareNoCase(LPCTSTR lpsz) const;

       // NLS aware comparison, case sensitive

       int Collate(LPCTSTR lpsz) const;

       // NLS aware comparison, case insensitive

       int CollateNoCase(LPCTSTR lpsz) const;

 

       // simple sub-string extraction

 

       // return nCount characters starting at zero-based nFirst

       CString Mid(int nFirst, int nCount) const;

       // return all characters starting at zero-based nFirst

       CString Mid(int nFirst) const;

       // return first nCount characters in string

       CString Left(int nCount) const;

       // return nCount characters from end of string

       CString Right(int nCount) const;

 

       //  characters from beginning that are also in passed string

       CString SpanIncluding(LPCTSTR lpszCharSet) const;

       // characters from beginning that are not also in passed string

       CString SpanExcluding(LPCTSTR lpszCharSet) const;

 

       // upper/lower/reverse conversion

 

       // NLS aware conversion to uppercase

       void MakeUpper();

       // NLS aware conversion to lowercase

       void MakeLower();

       // reverse string right-to-left

       void MakeReverse();

 

       // trimming whitespace (either side)

 

       // remove whitespace starting from right edge

       void TrimRight();

       // remove whitespace starting from left side

       void TrimLeft();

 

       // trimming anything (either side)

 

       // remove continuous occurrences of chTarget starting from right

       void TrimRight(TCHAR chTarget);

       // remove continuous occcurrences of characters in passed string,

       // starting from right

       void TrimRight(LPCTSTR lpszTargets);

       // remove continuous occurrences of chTarget starting from left

       void TrimLeft(TCHAR chTarget);

       // remove continuous occcurrences of characters in

       // passed string, starting from left

       void TrimLeft(LPCTSTR lpszTargets);

 

       // advanced manipulation

 

       // replace occurrences of chOld with chNew

       int Replace(TCHAR chOld, TCHAR chNew);

       // replace occurrences of substring lpszOld with lpszNew;

       // empty lpszNew removes instances of lpszOld

       int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew);

       // remove occurrences of chRemove

       int Remove(TCHAR chRemove);

       // insert character at zero-based index; concatenates

       // if index is past end of string

       int Insert(int nIndex, TCHAR ch);

       // insert substring at zero-based index; concatenates

       // if index is past end of string

       int Insert(int nIndex, LPCTSTR pstr);

       // delete nCount characters starting at zero-based index

       int Delete(int nIndex, int nCount = 1);

 

       // searching

 

       // find character starting at left, -1 if not found

       int Find(TCHAR ch) const;

       // find character starting at right

       int ReverseFind(TCHAR ch) const;

       // find character starting at zero-based index and going right

       int Find(TCHAR ch, int nStart) const;

       // find first instance of any character in passed string

       int FindOneOf(LPCTSTR lpszCharSet) const;

       // find first instance of substring

       int Find(LPCTSTR lpszSub) const;

       // find first instance of substring starting at zero-based index

       int Find(LPCTSTR lpszSub, int nStart) const;

 

       // simple formatting

 

       // printf-like formatting using passed string

       void AFX_CDECL Format(LPCTSTR lpszFormat, ...);

       // printf-like formatting using referenced string resource

       void AFX_CDECL Format(UINT nFormatID, ...);

       // printf-like formatting using variable arguments parameter

       void FormatV(LPCTSTR lpszFormat, va_list argList);

 

       // formatting for localization (uses FormatMessage API)

 

       // format using FormatMessage API on passed string

       void AFX_CDECL FormatMessage(LPCTSTR lpszFormat, ...);

       // format using FormatMessage API on referenced string resource

       void AFX_CDECL FormatMessage(UINT nFormatID, ...);

 

       // input and output

#ifdef _DEBUG

       friend CDumpContext& AFXAPI operator<<(CDumpContext& dc,

                            const CString& string);

#endif

       friend CArchive& AFXAPI operator<<(CArchive& ar, const CString& string);

       friend CArchive& AFXAPI operator>>(CArchive& ar, CString& string);

 

       // load from string resource

       BOOL LoadString(UINT nID);

 

#ifndef _UNICODE

       // ANSI <-> OEM support (convert string in place)

 

       // convert string from ANSI to OEM in-place

       void AnsiToOem();

       // convert string from OEM to ANSI in-place

       void OemToAnsi();

#endif

 

#ifndef _AFX_NO_BSTR_SUPPORT

       // OLE BSTR support (use for OLE automation)

 

       // return a BSTR initialized with this CString's data

       BSTR AllocSysString() const;

       // reallocates the passed BSTR, copies content of this CString to it

       BSTR SetSysString(BSTR* pbstr) const;

#endif

 

       // Access to string implementation buffer as "C" character array

 

       // get pointer to modifiable buffer at least as long as nMinBufLength

       LPTSTR GetBuffer(int nMinBufLength);

       // release buffer, setting length to nNewLength (or to first nul if -1)

       void ReleaseBuffer(int nNewLength = -1);

       // get pointer to modifiable buffer exactly as long as nNewLength

       LPTSTR GetBufferSetLength(int nNewLength);

       // release memory allocated to but unused by string

       void FreeExtra();

 

       // Use LockBuffer/UnlockBuffer to turn refcounting off

 

       // turn refcounting back on

       LPTSTR LockBuffer();

       // turn refcounting off

       void UnlockBuffer();

 

// Implementation

public:

       ~CString();

       int GetAllocLength() const;

 

protected:

       LPTSTR m_pchData;   // pointer to ref counted string data

 

       // implementation helpers

       CStringData* GetData() const;

       void Init();

       void AllocCopy(CString& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const;

       void AllocBuffer(int nLen);

       void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData);

       void ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data, int nSrc2Len, LPCTSTR lpszSrc2Data);

       void ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData);

       void CopyBeforeWrite();

       void AllocBeforeWrite(int nLen);

       void Release();

       static void PASCAL Release(CStringData* pData);

       static int PASCAL SafeStrlen(LPCTSTR lpsz);

       static void FASTCALL FreeData(CStringData* pData);

};

 

// Compare helpers

bool AFXAPI operator==(const CString& s1, const CString& s2);

bool AFXAPI operator==(const CString& s1, LPCTSTR s2);

bool AFXAPI operator==(LPCTSTR s1, const CString& s2);

bool AFXAPI operator!=(const CString& s1, const CString& s2);

bool AFXAPI operator!=(const CString& s1, LPCTSTR s2);

bool AFXAPI operator!=(LPCTSTR s1, const CString& s2);

bool AFXAPI operator<(const CString& s1, const CString& s2);

bool AFXAPI operator<(const CString& s1, LPCTSTR s2);

bool AFXAPI operator<(LPCTSTR s1, const CString& s2);

bool AFXAPI operator>(const CString& s1, const CString& s2);

bool AFXAPI operator>(const CString& s1, LPCTSTR s2);

bool AFXAPI operator>(LPCTSTR s1, const CString& s2);

bool AFXAPI operator<=(const CString& s1, const CString& s2);

bool AFXAPI operator<=(const CString& s1, LPCTSTR s2);

bool AFXAPI operator<=(LPCTSTR s1, const CString& s2);

bool AFXAPI operator>=(const CString& s1, const CString& s2);

bool AFXAPI operator>=(const CString& s1, LPCTSTR s2);

bool AFXAPI operator>=(LPCTSTR s1, const CString& s2);

 

// conversion helpers

int AFX_CDECL _wcstombsz(char* mbstr, const wchar_t* wcstr, size_t count);

int AFX_CDECL _mbstowcsz(wchar_t* wcstr, const char* mbstr, size_t count);

 

// Globals

extern AFX_DATA TCHAR afxChNil;

#ifdef _AFXDLL

const CString& AFXAPI AfxGetEmptyString();

#define afxEmptyString AfxGetEmptyString()

#else

extern LPCTSTR _afxPchNil;

#define afxEmptyString ((CString&)*(CString*)&_afxPchNil)

#endif

 

 

 

实现文件

// This is a part of the Microsoft Foundation Classes C++ library.

// Copyright (C) 1992-1998 Microsoft Corporation

// All rights reserved.

//

// This source code is only intended as a supplement to the

// Microsoft Foundation Classes Reference and related

// electronic documentation provided with the library.

// See these sources for detailed information regarding the

// Microsoft Foundation Classes product.

 

#include "stdafx.h"

#include <afxtempl.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)

{

       Init();

       if (nLength >= 1)

       {

              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)

{

       Init();

       if (nLength != 0)

       {

              ASSERT(AfxIsValidAddress(lpch, nLength, FALSE));

              AllocBuffer(nLength);

              memcpy(m_pchData, lpch, nLength*sizeof(TCHAR));

       }

}

 

/

// Special conversion constructors

 

#ifdef _UNICODE

CString::CString(LPCSTR lpsz, int nLength)

{

       Init();

       if (nLength != 0)

       {

              AllocBuffer(nLength);

              int n = ::MultiByteToWideChar(CP_ACP, 0, lpsz, nLength, m_pchData, nLength+1);

              ReleaseBuffer(n >= 0 ? n : -1);

       }

}

#else //_UNICODE

CString::CString(LPCWSTR lpsz, int nLength)

{

       Init();

       if (nLength != 0)

       {

              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

 

//

// Assignment operators

 

const CString& CString::operator=(TCHAR ch)

{

       AssignCopy(1, &ch);

       return *this;

}

 

//

// less common string expressions

 

CString AFXAPI operator+(const CString& string1, TCHAR ch)

{

       CString s;

       s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData, 1, &ch);

       return s;

}

 

CString AFXAPI operator+(TCHAR ch, const CString& string)

{

       CString s;

       s.ConcatCopy(1, &ch, string.GetData()->nDataLength, string.m_pchData);

       return s;

}

 

//

// Advanced manipulation

 

int CString::Delete(int nIndex, int nCount /* = 1 */)

{

       if (nIndex < 0)

              nIndex = 0;

       int nNewLength = GetData()->nDataLength;

       if (nCount > 0 && nIndex < nNewLength)

       {

              CopyBeforeWrite();

              int nBytesToCopy = nNewLength - (nIndex + nCount) + 1;

 

              memcpy(m_pchData + nIndex,

                     m_pchData + nIndex + nCount, nBytesToCopy * sizeof(TCHAR));

              GetData()->nDataLength = nNewLength - nCount;

       }

 

       return nNewLength;

}

 

int CString::Insert(int nIndex, TCHAR ch)

{

       CopyBeforeWrite();

 

       if (nIndex < 0)

              nIndex = 0;

 

       int nNewLength = GetData()->nDataLength;

       if (nIndex > nNewLength)

              nIndex = nNewLength;

       nNewLength++;

 

       if (GetData()->nAllocLength < nNewLength)

       {

              CStringData* pOldData = GetData();

              LPTSTR pstr = m_pchData;

              AllocBuffer(nNewLength);

              memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(TCHAR));

              CString::Release(pOldData);

       }

 

       // move existing bytes down

       memcpy(m_pchData + nIndex + 1,

              m_pchData + nIndex, (nNewLength-nIndex)*sizeof(TCHAR));

       m_pchData[nIndex] = ch;

       GetData()->nDataLength = nNewLength;

 

       return nNewLength;

}

 

int CString::Insert(int nIndex, LPCTSTR pstr)

{

       if (nIndex < 0)

              nIndex = 0;

 

       int nInsertLength = SafeStrlen(pstr);

       int nNewLength = GetData()->nDataLength;

       if (nInsertLength > 0)

       {

              CopyBeforeWrite();

              if (nIndex > nNewLength)

                     nIndex = nNewLength;

              nNewLength += nInsertLength;

 

              if (GetData()->nAllocLength < nNewLength)

              {

                     CStringData* pOldData = GetData();

                     LPTSTR pstr = m_pchData;

                     AllocBuffer(nNewLength);

                     memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(TCHAR));

                     CString::Release(pOldData);

              }

 

              // move existing bytes down

              memcpy(m_pchData + nIndex + nInsertLength,

                     m_pchData + nIndex,

                     (nNewLength-nIndex-nInsertLength+1)*sizeof(TCHAR));

              memcpy(m_pchData + nIndex,

                     pstr, nInsertLength*sizeof(TCHAR));

              GetData()->nDataLength = nNewLength;

       }

 

       return nNewLength;

}

 

int CString::Replace(TCHAR chOld, TCHAR chNew)

{

       int nCount = 0;

 

       // short-circuit the nop case

       if (chOld != chNew)

       {

              // otherwise modify each character that matches in the string

              CopyBeforeWrite();

              LPTSTR psz = m_pchData;

              LPTSTR pszEnd = psz + GetData()->nDataLength;

              while (psz < pszEnd)

              {

                     // replace instances of the specified character only

                     if (*psz == chOld)

                     {

                            *psz = chNew;

                            nCount++;

                     }

                     psz = _tcsinc(psz);

              }

       }

       return nCount;

}

 

int CString::Replace(LPCTSTR lpszOld, LPCTSTR lpszNew)

{

       // can't have empty or NULL lpszOld

 

       int nSourceLen = SafeStrlen(lpszOld);

       if (nSourceLen == 0)

              return 0;

       int nReplacementLen = SafeStrlen(lpszNew);

 

       // loop once to figure out the size of the result string

       int nCount = 0;

       LPTSTR lpszStart = m_pchData;

       LPTSTR lpszEnd = m_pchData + GetData()->nDataLength;

       LPTSTR lpszTarget;

       while (lpszStart < lpszEnd)

       {

              while ((lpszTarget = _tcsstr(lpszStart, lpszOld)) != NULL)

              {

                     nCount++;

                     lpszStart = lpszTarget + nSourceLen;

              }

              lpszStart += lstrlen(lpszStart) + 1;

       }

 

       // if any changes were made, make them

       if (nCount > 0)

       {

              CopyBeforeWrite();

 

              // if the buffer is too small, just

              //   allocate a new buffer (slow but sure)

              int nOldLength = GetData()->nDataLength;

              int nNewLength =  nOldLength + (nReplacementLen-nSourceLen)*nCount;

              if (GetData()->nAllocLength < nNewLength || GetData()->nRefs > 1)

              {

                     CStringData* pOldData = GetData();

                     LPTSTR pstr = m_pchData;

                     AllocBuffer(nNewLength);

                     memcpy(m_pchData, pstr, pOldData->nDataLength*sizeof(TCHAR));

                     CString::Release(pOldData);

              }

              // else, we just do it in-place

              lpszStart = m_pchData;

              lpszEnd = m_pchData + GetData()->nDataLength;

 

              // loop again to actually do the work

              while (lpszStart < lpszEnd)

              {

                     while ( (lpszTarget = _tcsstr(lpszStart, lpszOld)) != NULL)

                     {

                            int nBalance = nOldLength - (lpszTarget - m_pchData + nSourceLen);

                            memmove(lpszTarget + nReplacementLen, lpszTarget + nSourceLen,

                                   nBalance * sizeof(TCHAR));

                            memcpy(lpszTarget, lpszNew, nReplacementLen*sizeof(TCHAR));

                            lpszStart = lpszTarget + nReplacementLen;

                            lpszStart[nBalance] = '/0';

                            nOldLength += (nReplacementLen - nSourceLen);

                     }

                     lpszStart += lstrlen(lpszStart) + 1;

              }

              ASSERT(m_pchData[nNewLength] == '/0');

              GetData()->nDataLength = nNewLength;

       }

 

       return nCount;

}

 

int CString::Remove(TCHAR chRemove)

{

       CopyBeforeWrite();

 

       LPTSTR pstrSource = m_pchData;

       LPTSTR pstrDest = m_pchData;

       LPTSTR pstrEnd = m_pchData + GetData()->nDataLength;

 

       while (pstrSource < pstrEnd)

       {

              if (*pstrSource != chRemove)

              {

                     *pstrDest = *pstrSource;

                     pstrDest = _tcsinc(pstrDest);

              }

              pstrSource = _tcsinc(pstrSource);

       }

       *pstrDest = '/0';

       int nCount = pstrSource - pstrDest;

       GetData()->nDataLength -= nCount;

 

       return nCount;

}

 

//

// Very simple sub-string extraction

 

CString CString::Mid(int nFirst) const

{

       return Mid(nFirst, GetData()->nDataLength - nFirst);

}

 

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;

 

       ASSERT(nFirst >= 0);

       ASSERT(nFirst + nCount <= GetData()->nDataLength);

 

       // optimize case of returning entire string

       if (nFirst == 0 && nFirst + nCount == GetData()->nDataLength)

              return *this;

 

       CString dest;

       AllocCopy(dest, nCount, nFirst, 0);

       return dest;

}

 

CString CString::Right(int nCount) const

{

       if (nCount < 0)

              nCount = 0;

       if (nCount >= GetData()->nDataLength)

              return *this;

 

       CString dest;

       AllocCopy(dest, nCount, GetData()->nDataLength-nCount, 0);

       return dest;

}

 

CString CString::Left(int nCount) const

{

       if (nCount < 0)

              nCount = 0;

       if (nCount >= GetData()->nDataLength)

              return *this;

 

       CString dest;

       AllocCopy(dest, nCount, 0, 0);

       return dest;

}

 

// strspn equivalent

CString CString::SpanIncluding(LPCTSTR lpszCharSet) const

{

       ASSERT(AfxIsValidString(lpszCharSet));

       return Left(_tcsspn(m_pchData, lpszCharSet));

}

 

// strcspn equivalent

CString CString::SpanExcluding(LPCTSTR lpszCharSet) const

{

       ASSERT(AfxIsValidString(lpszCharSet));

       return Left(_tcscspn(m_pchData, lpszCharSet));

}

 

//

// Finding

 

int CString::ReverseFind(TCHAR ch) const

{

       // find last single character

       LPTSTR lpsz = _tcsrchr(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)

int CString::Find(LPCTSTR lpszSub) const

{

       return Find(lpszSub, 0);

}

 

int CString::Find(LPCTSTR lpszSub, int nStart) const

{

       ASSERT(AfxIsValidString(lpszSub));

 

       int nLength = GetData()->nDataLength;

       if (nStart > nLength)

              return -1;

 

       // find first matching substring

       LPTSTR lpsz = _tcsstr(m_pchData + nStart, lpszSub);

 

       // return -1 for not found, distance from beginning otherwise

       return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);

}

 

 

/

// CString formatting

 

#define TCHAR_ARG   TCHAR

#define WCHAR_ARG   WCHAR

#define CHAR_ARG    char

 

#ifdef _X86_

       #define DOUBLE_ARG  _AFX_DOUBLE

#else

       #define DOUBLE_ARG  double

#endif

 

#define FORCE_ANSI      0x10000

#define FORCE_UNICODE   0x20000

#define FORCE_INT64     0x40000

 

void CString::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(_X86_) && !defined(_ALPHA_)

                     // __int64 is only available on X86 and ALPHA platforms

                     ASSERT(FALSE);

#endif

              }

              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':

                            va_arg(argList, DOUBLE_ARG);

                            nItemLen = 128; // width isn't truncated

                            // 312 == strlen("-1+(309 zeroes).")

                            // 309 zeroes == max precision of a double

                            nItemLen = max(nItemLen, 312+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;

       }

 

       GetBuffer(nMaxLen);

       VERIFY(_vstprintf(m_pchData, lpszFormat, argListSave) <= GetAllocLength());

       ReleaseBuffer();

 

       va_end(argListSave);

}

 

// formatting (using wsprintf style formatting)

void AFX_CDECL CString::Format(LPCTSTR lpszFormat, ...)

{

       ASSERT(AfxIsValidString(lpszFormat));

 

       va_list argList;

       va_start(argList, lpszFormat);

       FormatV(lpszFormat, argList);

       va_end(argList);

}

 

void AFX_CDECL CString::Format(UINT nFormatID, ...)

{

       CString strFormat;

       VERIFY(strFormat.LoadString(nFormatID) != 0);

 

       va_list argList;

       va_start(argList, nFormatID);

       FormatV(strFormat, argList);

       va_end(argList);

}

 

// formatting (using FormatMessage style formatting)

void AFX_CDECL CString::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 CString::FormatMessage(UINT nFormatID, ...)

{

       // get format string from string table

       CString 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);

}

 

void CString::TrimRight(LPCTSTR lpszTargetList)

{

       // find beginning of trailing matches

       // by starting at beginning (DBCS aware)

 

       CopyBeforeWrite();

       LPTSTR lpsz = m_pchData;

       LPTSTR lpszLast = NULL;

 

       while (*lpsz != '/0')

       {

              if (_tcschr(lpszTargetList, *lpsz) != NULL)

              {

                     if (lpszLast == NULL)

                            lpszLast = lpsz;

              }

              else

                     lpszLast = NULL;

              lpsz = _tcsinc(lpsz);

       }

 

       if (lpszLast != NULL)

       {

              // truncate at left-most matching character

              *lpszLast = '/0';

              GetData()->nDataLength = lpszLast - m_pchData;

       }

}

 

void CString::TrimRight(TCHAR chTarget)

{

       // find beginning of trailing matches

       // by starting at beginning (DBCS aware)

 

       CopyBeforeWrite();

       LPTSTR lpsz = m_pchData;

       LPTSTR lpszLast = NULL;

 

       while (*lpsz != '/0')

       {

              if (*lpsz == chTarget)

              {

                     if (lpszLast == NULL)

                            lpszLast = lpsz;

              }

              else

                     lpszLast = NULL;

              lpsz = _tcsinc(lpsz);

       }

 

       if (lpszLast != NULL)

       {

              // truncate at left-most matching character

              *lpszLast = '/0';

              GetData()->nDataLength = lpszLast - m_pchData;

       }

}

 

void CString::TrimRight()

{

       // find beginning of trailing spaces by starting at beginning (DBCS aware)

 

       CopyBeforeWrite();

       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';

              GetData()->nDataLength = lpszLast - m_pchData;

       }

}

 

void CString::TrimLeft(LPCTSTR lpszTargets)

{

       // if we're not trimming anything, we're not doing any work

       if (SafeStrlen(lpszTargets) == 0)

              return;

 

       CopyBeforeWrite();

       LPCTSTR lpsz = m_pchData;

 

       while (*lpsz != '/0')

       {

              if (_tcschr(lpszTargets, *lpsz) == NULL)

                     break;

              lpsz = _tcsinc(lpsz);

       }

 

       if (lpsz != m_pchData)

       {

              // fix up data and length

              int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);

              memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(TCHAR));

              GetData()->nDataLength = nDataLength;

       }

}

 

void CString::TrimLeft(TCHAR chTarget)

{

       // find first non-matching character

 

       CopyBeforeWrite();

       LPCTSTR lpsz = m_pchData;

 

       while (chTarget == *lpsz)

              lpsz = _tcsinc(lpsz);

 

       if (lpsz != m_pchData)

       {

              // fix up data and length

              int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);

              memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(TCHAR));

              GetData()->nDataLength = nDataLength;

       }

}

 

void CString::TrimLeft()

{

       // find first non-space character

 

       CopyBeforeWrite();

       LPCTSTR lpsz = m_pchData;

 

       while (_istspace(*lpsz))

              lpsz = _tcsinc(lpsz);

 

       if (lpsz != m_pchData)

       {

              // fix up data and length

              int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);

              memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(TCHAR));

              GetData()->nDataLength = nDataLength;

       }

}

 

///

// CString support for template collections

 

#if _MSC_VER >= 1100

template<> void AFXAPI ConstructElements<CString> (CString* pElements, int nCount)

#else

void AFXAPI ConstructElements(CString* pElements, int nCount)

#endif

{

       ASSERT(nCount == 0 ||

              AfxIsValidAddress(pElements, nCount * sizeof(CString)));

 

       for (; nCount--; ++pElements)

              memcpy(pElements, &afxEmptyString, sizeof(*pElements));

}

 

#if _MSC_VER >= 1100

template<> void AFXAPI DestructElements<CString> (CString* pElements, int nCount)

#else

void AFXAPI DestructElements(CString* pElements, int nCount)

#endif

{

       ASSERT(nCount == 0 ||

              AfxIsValidAddress(pElements, nCount * sizeof(CString)));

 

       for (; nCount--; ++pElements)

              pElements->~CString();

}

 

#if _MSC_VER >= 1100

template<> void AFXAPI CopyElements<CString> (CString* pDest, const CString* pSrc, int nCount)

#else

void AFXAPI CopyElements(CString* pDest, const CString* pSrc, int nCount)

#endif

{

       ASSERT(nCount == 0 ||

              AfxIsValidAddress(pDest, nCount * sizeof(CString)));

       ASSERT(nCount == 0 ||

              AfxIsValidAddress(pSrc, nCount * sizeof(CString)));

 

       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;

}

 

///

 

 

 

 

 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐