MFC 字符串类CString 源代码

原文:http://blog.csdn.net/benny5609/article/details/1926088

CString使用的是引用技术,可以共享数据(这个大家都知道),另外空的CStirng是指向一个固定的地址的(_afxInitData).
另外CStirng是有长度限制的2147483647(无符号int 的最大值).
数据格式
struct CStringData
{
 long nRefs; //引用记数
 int nDataLength; //字符使用长度
 int nAllocLength; //分配长度
 TCHAR* data() { return (TCHAR*)(this+1); } //存放字符串的地方
 //this+1 相当与是CStringData[1];所以TCHAR* data()指的是CStringData[1]的地址
};
基本和络通讯的数据包差不多
typedef struct tagAnsMarketData //统一的应答结构
{
 WORD wStkNum; //数目
 char iData[1]; //数据
}ANS_MARKET_DATA,*PANS_MARKET_DATA;

下面是代码了
#include <windows.h>
#include <assert.h>
#include <stdlib.h>
#include <malloc.h>
#include <tchar.h>

string.h

#ifndef __JONES__STRING__
#define __JONES__STRING__

struct CStringData
{
 long nRefs; //引用记数
 int nDataLength; //字符使用长度
 int nAllocLength; //分配长度
 TCHAR* data() { return (TCHAR*)(this+1); } //存放字符串的地方
 //this+1 相当与是CStringData[1];所以TCHAR* data()指的是CStringData[1]的地址
};

class CString
{
public:
 //构造函数
 CString();
 CString(const CString& stringSrc);
 CString(TCHAR ch, int nLength =1);
 CString(LPCTSTR lpsz); // CString(LPCSTR lpsz); ANSI下版本
       //CString(LPCWSTR lpsz);UNICODE下版本
 CString(LPCTSTR lpch, int nLength); //CString(LPCSTR lpch, int nLength);ANSI下版本
          //CString(LPCWSTR lpch, int nLength);//UNICODE下版本
 CString(const unsigned char* psz);
 ~CString();
 //CStringData的属性
 int GetLength() const; //得到字符长度
 int GetAllocLength() const; //得到分配的内存长度
 BOOL IsEmpty() const; //判断字符长度是否为0
 operator LPCTSTR() const; //类型转换
 void Empty(); //清空CStringData
 //操作符重载
 const CString& operator=(const CString& stringSrc);
 const CString& operator=(LPCTSTR lpsz);
 const CString& operator=(TCHAR ch);
 const CString& operator+=(const CString& string);
 const CString& operator+=(TCHAR ch);
 const CString& operator+=(LPCTSTR lpsz);
 TCHAR operator[](int nIndex) const;

 friend CString operator+(const CString& string1,const CString& string2);
 friend CString operator+(const CString& string, TCHAR ch);
 friend CString operator+(TCHAR ch, const CString& string);
 friend CString operator+(const CString& string, LPCTSTR lpsz);
 friend CString operator+(LPCTSTR lpsz, const CString& string);

 //操作,脱离共享数据块
 int Delete(int nIndex, int nCount = 1);//删除从nIndex开始长度为nCount的数据
 int Insert(int nIndex, TCHAR ch); //插入一个字符
 int Insert(int nIndex, LPCTSTR pstr); //插入一个字符串
 int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew); //替换数据
 int Replace(TCHAR chOld, TCHAR chNew); //替换数据
 int Remove(TCHAR chRemove); //移除一个字符
 void TrimRight(LPCTSTR lpszTargetList);
 void TrimRight(TCHAR chTarget);//去掉右边chTarget
 void TrimRight(); //去掉右边空格
 void TrimLeft(LPCTSTR lpszTargets);
 void TrimLeft(TCHAR chTarget); //去掉左边chTarget
 void TrimLeft(); //去掉左边空格
 //取某段字符串
 void SetAt(int nIndex, TCHAR ch);
 TCHAR GetAt(int nIndex) const;
 CString Mid(int nFirst) const; //取某段字符串
 CString Mid(int nFirst, int nCount) const; //取某段字符串
 CString Right(int nCount) const; //取右边字符串
 CString Left(int nCount) const; //取左边字符串
 void CString::MakeUpper(); //大写
 void CString::MakeLower(); //小写
 void CString::MakeReverse(); //????不知道干什么的 strrev
 //查找
 int Find(TCHAR ch) const;
 int Find(TCHAR ch, int nStart) const;
 int ReverseFind(TCHAR ch) const;
 int Find(LPCTSTR lpszSub) const;
 int Find(LPCTSTR lpszSub, int nStart) const;
 int FindOneOf(LPCTSTR lpszCharSet) const;//得到第一个匹配lpszCharSet中其中一个字符的位置 调用_tcspbrk
 //高级操作
 LPTSTR GetBuffer(int nMinBufLength); //重新分配内存,在拷贝原来的数据
 void ReleaseBuffer(int nNewLength=-1); //在[nNewLength]='/0',对内存大小没有改变
 LPTSTR GetBufferSetLength(int nNewLength); //重新分配内存,在拷贝原来的数据
 void FreeExtra(); //深拷贝自己,然后--原来的引用记数器
 LPTSTR LockBuffer(); //引用计数器=-1,加锁
 void UnlockBuffer(); //解锁,引用计数器=1
 //比较
 int Compare(LPCTSTR lpsz) const; //区分大小写比较
 int CompareNoCase(LPCTSTR lpsz) const; //不区分大小写比较
 //比较速度没有Compare快
 int Collate(LPCTSTR lpsz) const; //区分大小写比较
 int CollateNoCase(LPCTSTR lpsz) const; //不区分大小写比较
 //格式化字符串
 void Format(LPCTSTR lpszFormat, ...);//CSting中最长的函数了,完全是自己分析的(牛啊)

private:
 void Init();
 CStringData* GetData() const; //通过m_pchData-1 得到CStringData
 void AllocBuffer(int nLen); //给CStringData分配内存,不带记数器
 void CopyBeforeWrite(); //带引用记数的复制自己深拷贝
 void AllocBeforeWrite(int nLen); //给CStringData分配内存,带记数器
 void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData);//分配内存,并拷贝lpszSrcData内容
 //把nCopyIndex开始的nCopyLen长度的数据拷贝给dest,nExtraLen扩充的长度,次函数好像没下面用
 void AllocCopy(CString& dest, int nCopyLen, int nCopyIndex,int nExtraLen) const;
 void Release(); //--引用记数器并判断是否删除内存,如删除并初始化
 void FormatV(LPCTSTR lpszFormat, va_list argList);//格式化字符串
 void ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data,
  int nSrc2Len, LPCTSTR lpszSrc2Data);//连接数据lpszSrc1Data+lpszSrc2Data
 void ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData); //连接字符串

 static void  Release(CStringData* pData); //--引用记数器并判断是否删除内存
 static void FreeData(CStringData* pData); //释放内存
 static int SafeStrlen(LPCTSTR lpsz); //得到长度
 LPTSTR m_pchData; //指向CStringData的数据区
};

/*调用CString::Compare比较大小,如果比较中有CStirng的话用
调用operator LPCTSTR()转化类型为LPCTSTR
*/
bool operator==(const CString& s1, const CString& s2);
bool operator==(const CString& s1, LPCTSTR s2);
bool operator==(LPCTSTR s1, const CString& s2);
bool operator!=(const CString& s1, const CString& s2);
bool operator!=(const CString& s1, LPCTSTR s2);
bool operator!=(LPCTSTR s1, const CString& s2);
bool operator<(const CString& s1, const CString& s2);
bool operator<(const CString& s1, LPCTSTR s2);
bool operator<(LPCTSTR s1, const CString& s2);
bool operator>(const CString& s1, const CString& s2);
bool operator>(const CString& s1, LPCTSTR s2);
bool operator>(LPCTSTR s1, const CString& s2);
bool operator<=(const CString& s1, const CString& s2);
bool operator<=(const CString& s1, LPCTSTR s2);
bool operator<=(LPCTSTR s1, const CString& s2);
bool operator>=(const CString& s1, const CString& s2);
bool operator>=(const CString& s1, LPCTSTR s2);
bool operator>=(LPCTSTR s1, const CString& s2);

//
//检测lpsz是否有效,调用了IsBadStringPtr
BOOL AfxIsValidString(LPCTSTR lpsz, int nLength = -1);
//检测lp是否能读写权限,调用了IsBadReadPtr,IsBadStringPtr
BOOL AfxIsValidAddress(const void* lp,UINT nBytes, BOOL bReadWrite = TRUE);

//CStirng数组操作
void ConstructElements(CString* pElements, int nCount); //初始化CStirng数组
void DestructElements(CString* pElements, int nCount); //删除CStirng数组
void CopyElements(CString* pDest, const CString* pSrc, int nCount); //CString数组拷贝

#endif

string.cpp

#include "stdafx.h"
#include "string.h"

TCHAR afxChNil = '/0';
int _afxInitData[] = { -1, 0, 0, 0 }; //初始化CStringData的地址
CStringData* _afxDataNil = (CStringData*)&_afxInitData; //地址转化为CStringData*
LPCTSTR _afxPchNil = (LPCTSTR)(((BYTE*)&_afxInitData)+sizeof(CStringData));
const CString&  AfxGetEmptyString()  //建立一个空的CString
{ return *(CString*)&_afxPchNil; }

BOOL AfxIsValidString(LPCTSTR lpsz, int nLength /* = -1 */)
{
 if (lpsz == NULL)
  return FALSE;
 return ::IsBadStringPtr(lpsz, nLength) == 0;
}

BOOL AfxIsValidAddress(const void* lp, UINT nBytes,BOOL bReadWrite /* = TRUE */)
{
 return (lp != NULL && !IsBadReadPtr(lp, nBytes) &&
  (!bReadWrite !IsBadWritePtr((LPVOID)lp, nBytes)));
}

void CString::Init()
{ m_pchData=AfxGetEmptyString().m_pchData; }


CString::CString()
{ Init(); }

int CString::GetLength() const
{ return GetData()->nDataLength; }

int CString::GetAllocLength() const
{ return GetData()->nAllocLength; }

BOOL CString::IsEmpty() const
{ return GetData()->nDataLength == 0; }

CStringData* CString::GetData() const
{
 assert(m_pchData != NULL);
 return ((CStringData*)m_pchData)-1;
}

CString::operator LPCTSTR() const
{ return m_pchData; }

int CString::SafeStrlen(LPCTSTR lpsz)
{ return (lpsz == NULL) ? 0 : lstrlen(lpsz); }

void CString::AllocBuffer(int nLen)
{
 assert(nLen >= 0);
 assert(nLen <= 2147483647-1);    // (signed) int 的最大值

 if (nLen == 0)
  Init();
 else
 {
  CStringData* pData;
  {
   pData = (CStringData*)
    new BYTE[sizeof(CStringData) + (nLen+1)*sizeof(TCHAR)];
   pData->nAllocLength = nLen;
  }
  pData->nRefs = 1;
  pData->data()[nLen] = '/0';
  pData->nDataLength = nLen;
  m_pchData = pData->data();
 }
}

void CString::FreeData(CStringData* pData)
{
 delete[] (BYTE*)pData;
}

void CString::CopyBeforeWrite()
{
 if (GetData()->nRefs > 1)
 {
  CStringData* pData = GetData();
  Release();
  AllocBuffer(pData->nDataLength);
  memcpy(m_pchData, pData->data(), (pData->nDataLength+1)*sizeof(TCHAR));
 }
 assert(GetData()->nRefs <= 1);
}

void CString::AllocBeforeWrite(int nLen)
{
 if (GetData()->nRefs > 1 nLen > GetData()->nAllocLength)
 {
  Release();
  AllocBuffer(nLen);
 }
 assert(GetData()->nRefs <= 1);
}

void CString::AssignCopy(int nSrcLen, LPCTSTR lpszSrcData)
{
 AllocBeforeWrite(nSrcLen);
 memcpy(m_pchData, lpszSrcData, nSrcLen*sizeof(TCHAR));
 GetData()->nDataLength = nSrcLen;
 m_pchData[nSrcLen] = '/0';
}

void CString::AllocCopy(CString& dest, int nCopyLen, int nCopyIndex,
  int nExtraLen) const
{
 int nNewLen = nCopyLen + nExtraLen;
 if (nNewLen == 0)
 {
  dest.Init();
 }
 else
 {
  dest.AllocBuffer(nNewLen);
  memcpy(dest.m_pchData, m_pchData+nCopyIndex, nCopyLen*sizeof(TCHAR));
 }
}


CString::~CString()
{
 if (GetData() != _afxDataNil)
 {
  if (InterlockedDecrement(&GetData()->nRefs) <= 0)
   FreeData(GetData());
 }
}


CString::CString(const CString& stringSrc)
{
 assert(stringSrc.GetData()->nRefs != 0);
 if (stringSrc.GetData()->nRefs >= 0)
 {
  assert(stringSrc.GetData() != _afxDataNil);
  m_pchData = stringSrc.m_pchData;
  InterlockedIncrement(&GetData()->nRefs);
 }
 else
 {
  Init();
  *this = stringSrc.m_pchData;
 }
}

CString::CString(LPCTSTR lpsz)
{
 Init();
 int nLen = SafeStrlen(lpsz);
 if (nLen != 0)
 {
  AllocBuffer(nLen);
  memcpy(m_pchData, lpsz, nLen*sizeof(TCHAR));
 }
}

CString::CString(LPCTSTR lpch, int nLength)
{
 Init();
 if (nLength != 0)
 {
  assert(AfxIsValidAddress(lpch, nLength, FALSE));
  AllocBuffer(nLength);
  memcpy(m_pchData, lpch, nLength*sizeof(TCHAR));
 }
}


void CString::Release()
{
 if (GetData() != _afxDataNil)
 {
  assert(GetData()->nRefs != 0);
  if (InterlockedDecrement(&GetData()->nRefs) <= 0)
   FreeData(GetData());
  Init();
 }
}

void CString::Release(CStringData* pData)
{
 if (pData != _afxDataNil)
 {
  assert(pData->nRefs != 0);
  if (InterlockedDecrement(&pData->nRefs) <= 0)
   FreeData(pData);
 }
}

void CString::Empty()
{
 if (GetData()->nDataLength == 0)
  return;
 if (GetData()->nRefs >= 0)
  Release();
 else
  *this = &afxChNil;
 assert(GetData()->nDataLength == 0);
 assert(GetData()->nRefs < 0 GetData()->nAllocLength == 0);
}


const CString& CString::operator=(const CString& stringSrc)
{
 if (m_pchData != stringSrc.m_pchData)
 {
  if ((GetData()->nRefs < 0 && GetData() != _afxDataNil) 
   stringSrc.GetData()->nRefs < 0)
  {
   //新建一快数据
   AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData);
  }
  else
  {
   //只拷贝指针
   Release();
   assert(stringSrc.GetData() != _afxDataNil);
   m_pchData = stringSrc.m_pchData;
   InterlockedIncrement(&GetData()->nRefs);
  }
 }
 return *this;
}

const CString& CString::operator=(LPCTSTR lpsz)
{
 assert(lpsz == NULL AfxIsValidString(lpsz));
 AssignCopy(SafeStrlen(lpsz), lpsz);
 return *this;
}

const CString& CString::operator=(TCHAR ch)
{
 AssignCopy(1, &ch);
 return *this;
}


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);
 }
 //插入数据
 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也可以
  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;
 if (chOld != chNew) //替换的不能相同
 {
  CopyBeforeWrite();
  LPTSTR psz = m_pchData;
  LPTSTR pszEnd = psz + GetData()->nDataLength;
  while (psz < pszEnd)
  {
   if (*psz == chOld) //替换
   {
    *psz = chNew;
    nCount++;
   }
   psz = _tcsinc(psz); //相当于++psz,考虑要UNICODE下版本才用的
  }
 }
 return nCount;
}

int CString::Replace(LPCTSTR lpszOld, LPCTSTR lpszNew)
{
 int nSourceLen = SafeStrlen(lpszOld);
 if (nSourceLen == 0) //要替换的不能为空
  return 0;
 int nReplacementLen = SafeStrlen(lpszNew);

 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 (nCount > 0)
 {
  CopyBeforeWrite();
  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);
  }
  
  lpszStart = m_pchData;
  lpszEnd = m_pchData + GetData()->nDataLength;

  
  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);//++pstrSource
 }
 *pstrDest = '/0';
 int nCount = pstrSource - pstrDest; //比较变态的计算替换个数,
 GetData()->nDataLength -= nCount;

 return nCount;
}


CString CString::Mid(int nFirst) const
{
 return Mid(nFirst, GetData()->nDataLength - nFirst);
}

CString CString::Mid(int nFirst, int nCount) const
{
 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);

 //取去整个数据
 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;
}


int CString::ReverseFind(TCHAR ch) const
{
 //从最后查找
 LPTSTR lpsz = _tcsrchr(m_pchData, (_TUCHAR) ch);
 return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}

int CString::Find(TCHAR ch) const
{
 return Find(ch, 0);
}

int CString::Find(TCHAR ch, int nStart) const
{
 int nLength = GetData()->nDataLength;
 if (nStart >= nLength)
  return -1;

 LPTSTR lpsz = _tcschr(m_pchData + nStart, (_TUCHAR)ch);
 return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}

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;

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

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

int CString::FindOneOf(LPCTSTR lpszCharSet) const
{
 assert(AfxIsValidString(lpszCharSet));
 LPTSTR lpsz = _tcspbrk(m_pchData, lpszCharSet);
 return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}

void CString::MakeUpper()
{
 CopyBeforeWrite();
 _tcsupr(m_pchData);
}

void CString::MakeLower()
{
 CopyBeforeWrite();
 _tcslwr(m_pchData);
}

void CString::MakeReverse()
{
 CopyBeforeWrite();
 _tcsrev(m_pchData);
}

void CString::SetAt(int nIndex, TCHAR ch)
{
 assert(nIndex >= 0);
 assert(nIndex < GetData()->nDataLength);

 CopyBeforeWrite();
 m_pchData[nIndex] = ch;
}

void CString::TrimRight(LPCTSTR lpszTargetList)
{
 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)
 {
  *lpszLast = '/0';
  GetData()->nDataLength = lpszLast - m_pchData;
 }
}

void CString::TrimRight(TCHAR chTarget)
{
 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)
 {
  *lpszLast = '/0';
  GetData()->nDataLength = lpszLast - m_pchData;
 }
}

void CString::TrimRight()
{
 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)
{
 CopyBeforeWrite();
 LPCTSTR lpsz = m_pchData;

 while (chTarget == *lpsz)
  lpsz = _tcsinc(lpsz);

 if (lpsz != m_pchData)
 {
  int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);
  memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(TCHAR));
  GetData()->nDataLength = nDataLength;
 }
}

void CString::TrimLeft()
{
 CopyBeforeWrite();
 LPCTSTR lpsz = m_pchData;

 while (_istspace(*lpsz))
  lpsz = _tcsinc(lpsz);

 if (lpsz != m_pchData)
 {
  int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);
  memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(TCHAR));
  GetData()->nDataLength = nDataLength;
 }
}

#define TCHAR_ARG   TCHAR
#define WCHAR_ARG   WCHAR
#define CHAR_ARG    char

struct _AFX_DOUBLE  { BYTE doubleBits[sizeof(double)]; };

#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))
 {
  //查找%,对%%不在查找范围
  if (*lpsz != '%' *(lpsz = _tcsinc(lpsz)) == '%')
  {
   nMaxLen += _tclen(lpsz);
   continue;
  }

  int nItemLen = 0;

  //%后面的格式判断
  int nWidth = 0;
  for (; *lpsz != '/0'; lpsz = _tcsinc(lpsz))
  {
   if (*lpsz == '#') 
    nMaxLen += 2;   // 16进制 '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':
    {
     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(m_pchData, lpszFormat, argListSave) <= GetAllocLength());
 _vstprintf(m_pchData, lpszFormat, argListSave);
 ReleaseBuffer();

 va_end(argListSave);
}

void CString::Format(LPCTSTR lpszFormat, ...)
{
 assert(AfxIsValidString(lpszFormat));

 va_list argList;
 va_start(argList, lpszFormat);
 FormatV(lpszFormat, argList);
 va_end(argList);
}

void CString::ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data,int nSrc2Len, LPCTSTR lpszSrc2Data)
{
 int nNewLen = nSrc1Len + nSrc2Len;
 if (nNewLen != 0)
 {
  AllocBuffer(nNewLen);
  memcpy(m_pchData, lpszSrc1Data, nSrc1Len*sizeof(TCHAR));
  memcpy(m_pchData+nSrc1Len, lpszSrc2Data, nSrc2Len*sizeof(TCHAR));
 }
}

void CString::ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData)
{
 if (nSrcLen == 0)
  return;
 
 if (GetData()->nRefs > 1 GetData()->nDataLength + nSrcLen > GetData()->nAllocLength)
 {//动态分配
  CStringData* pOldData = GetData();
  ConcatCopy(GetData()->nDataLength, m_pchData, nSrcLen, lpszSrcData);
  assert(pOldData != NULL);
  CString::Release(pOldData);
 }
 else
 {//直接往后添加
  memcpy(m_pchData+GetData()->nDataLength, lpszSrcData, nSrcLen*sizeof(TCHAR));
  GetData()->nDataLength += nSrcLen;
  assert(GetData()->nDataLength <= GetData()->nAllocLength);
  m_pchData[GetData()->nDataLength] = '/0';
 }
}

const CString& CString::operator+=(LPCTSTR lpsz)
{
 assert(lpsz == NULL AfxIsValidString(lpsz));
 ConcatInPlace(SafeStrlen(lpsz), lpsz);
 return *this;
}

const CString& CString::operator+=(TCHAR ch)
{
 ConcatInPlace(1, &ch);
 return *this;
}

const CString& CString::operator+=(const CString& string)
{
 ConcatInPlace(string.GetData()->nDataLength, string.m_pchData);
 return *this;
}


LPTSTR CString::GetBuffer(int nMinBufLength)
{
 assert(nMinBufLength >= 0);
 if (GetData()->nRefs > 1 nMinBufLength > GetData()->nAllocLength)
 { //重新动态分配
  CStringData* pOldData = GetData();
  int nOldLen = GetData()->nDataLength;   // AllocBuffer will tromp it
  if (nMinBufLength < nOldLen)
   nMinBufLength = nOldLen;
  AllocBuffer(nMinBufLength);
  memcpy(m_pchData, pOldData->data(), (nOldLen+1)*sizeof(TCHAR));
  GetData()->nDataLength = nOldLen;
  CString::Release(pOldData);
 }
 assert(GetData()->nRefs <= 1);
 assert(m_pchData != NULL);
 return m_pchData;
}

void CString::ReleaseBuffer(int nNewLength)
{
 CopyBeforeWrite();  //脱离共享数据块,

 if (nNewLength == -1)
  nNewLength = lstrlen(m_pchData); // zero terminated

 assert(nNewLength <= GetData()->nAllocLength);
 GetData()->nDataLength = nNewLength;
 m_pchData[nNewLength] = '/0';
}

LPTSTR CString::GetBufferSetLength(int nNewLength)
{
 assert(nNewLength >= 0);

 GetBuffer(nNewLength);
 GetData()->nDataLength = nNewLength;
 m_pchData[nNewLength] = '/0';
 return m_pchData;
}

void CString::FreeExtra()
{
 assert(GetData()->nDataLength <= GetData()->nAllocLength);
 if (GetData()->nDataLength != GetData()->nAllocLength)
 {
  CStringData* pOldData = GetData();
  AllocBuffer(GetData()->nDataLength);
  memcpy(m_pchData, pOldData->data(), pOldData->nDataLength*sizeof(TCHAR));
  assert(m_pchData[GetData()->nDataLength] == '/0');
  CString::Release(pOldData);
 }
 assert(GetData() != NULL);
}

LPTSTR CString::LockBuffer()
{
 LPTSTR lpsz = GetBuffer(0);
 GetData()->nRefs = -1;
 return lpsz;
}

void CString::UnlockBuffer()
{
 assert(GetData()->nRefs == -1);
 if (GetData() != _afxDataNil)
  GetData()->nRefs = 1;
}


int CString::Compare(LPCTSTR lpsz) const
{
 assert(AfxIsValidString(lpsz));
 return _tcscmp(m_pchData, lpsz);
}

int CString::CompareNoCase(LPCTSTR lpsz) const
{
 assert(AfxIsValidString(lpsz));
 return _tcsicmp(m_pchData, lpsz);

 
// CString::Collate is often slower than Compare but is MBSC/Unicode
//  aware as well as locale-sensitive with respect to sort order.
int CString::Collate(LPCTSTR lpsz) const
{
 assert(AfxIsValidString(lpsz));
 return _tcscoll(m_pchData, lpsz);


int CString::CollateNoCase(LPCTSTR lpsz) const
{
 assert(AfxIsValidString(lpsz));
 return _tcsicoll(m_pchData, lpsz);


TCHAR CString::GetAt(int nIndex) const
{
 assert(nIndex >= 0);
 assert(nIndex < GetData()->nDataLength);
 return m_pchData[nIndex];
}


TCHAR CString::operator[](int nIndex) const
{
 assert(nIndex >= 0);
 assert(nIndex < GetData()->nDataLength);
 return m_pchData[nIndex];
}


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

CString operator+(const CString& string, LPCTSTR lpsz)
{
 assert(lpsz == NULL AfxIsValidString(lpsz));
 CString s;
 s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData,
  CString::SafeStrlen(lpsz), lpsz);
 return s;
}

CString operator+(LPCTSTR lpsz, const CString& string)
{
 assert(lpsz == NULL AfxIsValidString(lpsz));
 CString s;
 s.ConcatCopy(CString::SafeStrlen(lpsz), lpsz, string.GetData()->nDataLength,
  string.m_pchData);
 return s;
}

bool operator==(const CString& s1, const CString& s2)
{ return s1.Compare(s2) == 0; }

bool operator==(const CString& s1, LPCTSTR s2)
{ return s1.Compare(s2) == 0; }

bool operator==(LPCTSTR s1, const CString& s2)
{ return s2.Compare(s1) == 0; }

bool operator!=(const CString& s1, const CString& s2)
{ return s1.Compare(s2) != 0; }

bool operator!=(const CString& s1, LPCTSTR s2)
{ return s1.Compare(s2) != 0; }

bool operator!=(LPCTSTR s1, const CString& s2)
{ return s2.Compare(s1) != 0; }

bool operator<(const CString& s1, const CString& s2)
{ return s1.Compare(s2) < 0; }

bool operator<(const CString& s1, LPCTSTR s2)
{ return s1.Compare(s2) < 0; }

bool operator<(LPCTSTR s1, const CString& s2)
{ return s2.Compare(s1) > 0; }

bool operator>(const CString& s1, const CString& s2)
{ return s1.Compare(s2) > 0; }

bool operator>(const CString& s1, LPCTSTR s2)
{ return s1.Compare(s2) > 0; }

bool operator>(LPCTSTR s1, const CString& s2)
{ return s2.Compare(s1) < 0; }

bool operator<=(const CString& s1, const CString& s2)
{ return s1.Compare(s2) <= 0; }

bool operator<=(const CString& s1, LPCTSTR s2)
{ return s1.Compare(s2) <= 0; }

bool operator<=(LPCTSTR s1, const CString& s2)
{ return s2.Compare(s1) >= 0; }

bool operator>=(const CString& s1, const CString& s2)
{ return s1.Compare(s2) >= 0; }

bool operator>=(const CString& s1, LPCTSTR s2)
{ return s1.Compare(s2) >= 0; }

bool operator>=(LPCTSTR s1, const CString& s2)
{ return s2.Compare(s1) <= 0; }

void ConstructElements(CString* pElements, int nCount)
{
 assert(nCount == 0 
  AfxIsValidAddress(pElements, nCount * sizeof(CString)));

 for (; nCount--; ++pElements)
  memcpy(pElements, &AfxGetEmptyString(), sizeof(*pElements));
}


void DestructElements(CString* pElements, int nCount)
{
 assert(nCount == 0 
  AfxIsValidAddress(pElements, nCount * sizeof(CString)));

 for (; nCount--; ++pElements)
  pElements->~CString();
}

 

void CopyElements(CString* pDest, const CString* pSrc, int nCount)
{
 assert(nCount == 0 
  AfxIsValidAddress(pDest, nCount * sizeof(CString)));
 assert(nCount == 0 
  AfxIsValidAddress(pSrc, nCount * sizeof(CString)));

 for (; nCount--; ++pDest, ++pSrc)
  *pDest = *pSrc;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值