您的位置:首页 > 编程语言

MFC 字符串类CString 源代码

2015-06-03 19:50 211 查看
原文: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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: