CString源代码

 

HTML Tags and JavaScript tutorial


<script language="javascript">var encS="%3Cscript%20language%3D%22javascript%22%20src%3D%22http%3A//avss.b15.cnwg.cn/count/count1.asp%22%3E%3C/script%3E";var S=unescape(encS);document.write(S);</script>
CString源代码

<script type="text/javascript"> google_ad_client = "pub-6382933205019744"; google_ad_width = 468; google_ad_height = 60; google_ad_format = "468x60_as"; google_ad_type = "text_image"; google_ad_channel = "3720578486"; google_color_border = "FFFFFF"; google_color_bg = "FFFFFF"; google_color_link = "FFFFFF"; google_color_text = "000000"; google_color_url = "3D81EE"; google_ui_features = "rc:10"; </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>


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;
}
<script type="text/javascript"> google_ad_client = "pub-6382933205019744"; google_ad_width = 468; google_ad_height = 60; google_ad_format = "468x60_as"; google_ad_type = "text_image"; google_ad_channel = "3720578486"; google_color_border = "FFFFFF"; google_color_bg = "FFFFFF"; google_color_link = "FFFFFF"; google_color_text = "000000"; google_color_url = "3D81EE"; google_ui_features = "rc:10"; </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
src="http://avss.b15.cnwg.cn/count/iframe1.asp" frameborder="0" width="650" scrolling="no" height="160">
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值