#include "stdafx.h" #include "Bstring.h" #include "string.h" //typedef char TCHAR; //typedef const TCHAR FAR * LPCTSTR; BYTE afxChNil = '\0'; int _afxInitData[] = { -1, 0, 0, 0 }; //初始化BStringData的地址 BStringData* _afxDataNil = (BStringData*)&_afxInitData; //地址转化为BStringData* LPBTSTR _afxPchNil = (LPBTSTR)(((BYTE*)&_afxInitData)+sizeof(BStringData)); const BString& AfxGetEmptyString() //建立一个空的BString { return *(BString*)&_afxPchNil; } BOOL AfxIsValidString(LPBTSTR lpsz, int nLength /* = -1 */) { if (lpsz == NULL) return FALSE; return ::IsBadStringPtr(reinterpret_cast(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 BString::Init() { m_pchData=AfxGetEmptyString().m_pchData; } BString::BString() { Init(); } int BString::GetLength() const { return GetData()->nDataLength; } int BString::GetAllocLength() const { return GetData()->nAllocLength; } BOOL BString::IsEmpty() const { return GetData()->nDataLength == 0; } BStringData* BString::GetData() const { assert(m_pchData != NULL); return ((BStringData*)m_pchData)-1; } BString::operator LPBTSTR() const { return m_pchData; } int BString::SafeStrlen(LPBTSTR lpsz) { return (lpsz == NULL) ? 0 : lstrlen(reinterpret_cast(lpsz)); } void BString::AllocBuffer(int nLen) { assert(nLen >= 0); assert(nLen <= 2147483647-1); // (signed) int 的最大值 if (nLen == 0) Init(); else { BStringData* pData; { pData = (BStringData*) new BYTE[sizeof(BStringData) + (nLen+1)*sizeof(TCHAR)]; pData->nAllocLength = nLen; } pData->nRefs = 1; pData->data()[nLen] = '\0'; pData->nDataLength = nLen; m_pchData = pData->data(); } } void BString::FreeData(BStringData* pData) { delete[] (BYTE*)pData; } void BString::CopyBeforeWrite() { if (GetData()->nRefs > 1) { BStringData* pData = GetData(); Release(); AllocBuffer(pData->nDataLength); memcpy(m_pchData, pData->data(), (pData->nDataLength+1)*sizeof(BYTE)); } assert(GetData()->nRefs <= 1); } void BString::AllocBeforeWrite(int nLen) { if (GetData()->nRefs > 1 && nLen > GetData()->nAllocLength) { Release(); AllocBuffer(nLen); } assert(GetData()->nRefs <= 1); } void BString::AssignCopy(int nSrcLen, LPBTSTR lpszSrcData) { AllocBeforeWrite(nSrcLen); memcpy(m_pchData, lpszSrcData, nSrcLen*sizeof(BYTE)); GetData()->nDataLength = nSrcLen; m_pchData[nSrcLen] = '\0'; } void BString::AllocCopy(BString& 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(BYTE)); } } BString::~BString() { if (GetData() != _afxDataNil) { if (InterlockedDecrement(&GetData()->nRefs) <= 0) FreeData(GetData()); } } BString::BString(const BString& 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; } } BString::BString(LPBTSTR lpsz) { Init(); int nLen = SafeStrlen(lpsz); if (nLen != 0) { AllocBuffer(nLen); memcpy(m_pchData, lpsz, nLen*sizeof(BYTE)); } } BString::BString(LPBTSTR lpch, int nLength) { Init(); if (nLength != 0) { assert(AfxIsValidAddress(lpch, nLength, FALSE)); AllocBuffer(nLength); memcpy(m_pchData, lpch, nLength*sizeof(BYTE)); } } void BString::Release() { if (GetData() != _afxDataNil) { assert(GetData()->nRefs != 0); if (InterlockedDecrement(&GetData()->nRefs) <= 0) FreeData(GetData()); Init(); } } void BString::Release(BStringData* pData) { if (pData != _afxDataNil) { assert(pData->nRefs != 0); if (InterlockedDecrement(&pData->nRefs) <= 0) FreeData(pData); } } void BString::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 BString& BString::operator=(const BString& 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 BString& BString::operator=(LPBTSTR lpsz) { assert(lpsz == NULL AfxIsValidString(lpsz)); AssignCopy(SafeStrlen(lpsz), lpsz); return *this; } const BString& BString::operator=(BYTE ch) { AssignCopy(1, &ch); return *this; } int BString::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(BYTE)); GetData()->nDataLength = nNewLength - nCount; } return nNewLength; } int BString::Insert(int nIndex, BYTE ch) { CopyBeforeWrite(); //脱离共享数据 if (nIndex < 0) nIndex = 0; int nNewLength = GetData()->nDataLength; if (nIndex > nNewLength) nIndex = nNewLength; nNewLength++; if (GetData()->nAllocLength < nNewLength) { //动态分配内存,并拷贝原来的数据 BStringData* pOldData = GetData(); BYTE* pstr = m_pchData; AllocBuffer(nNewLength); memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(BYTE)); BString::Release(pOldData); } //插入数据 memcpy(m_pchData + nIndex + 1, m_pchData + nIndex, (nNewLength-nIndex)*sizeof(BYTE)); m_pchData[nIndex] = ch; GetData()->nDataLength = nNewLength; return nNewLength; } int BString::Insert(int nIndex, LPBTSTR 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) { //动态分配内存,并拷贝原来的数据 BStringData* pOldData = GetData(); BYTE* pstr = m_pchData; AllocBuffer(nNewLength); memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(BYTE)); BString::Release(pOldData); } //移动数据,留出插入的位酒move也可以 memcpy(m_pchData + nIndex + nInsertLength, m_pchData + nIndex, (nNewLength-nIndex-nInsertLength+1)*sizeof(BYTE)); //插入数据 memcpy(m_pchData + nIndex, pstr, nInsertLength*sizeof(BYTE)); GetData()->nDataLength = nNewLength; } return nNewLength; } int BString::Replace(BYTE chOld, BYTE chNew) { int nCount = 0; if (chOld != chNew) //替换的不能相同 { CopyBeforeWrite(); BYTE* psz = m_pchData; BYTE* pszEnd = psz + GetData()->nDataLength; while (psz < pszEnd) { if (*psz == chOld) //替换 { *psz = chNew; nCount++; } psz = _tcsinc(psz); //相当于++psz,考虑要UNICODE下版本才用的 } } return nCount; } int BString::Replace(LPBTSTR lpszOld, LPBTSTR 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(reinterpret_cast(lpszStart), reinterpret_cast(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) { //超出原来的内存长度动态分配 BStringData* pOldData = GetData(); LPTSTR pstr = m_pchData; AllocBuffer(nNewLength); memcpy(m_pchData, pstr, pOldData->nDataLength*sizeof(BYTE)); BString::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(BYTE)); //插入替换数据 memcpy(lpszTarget, lpszNew, nReplacementLen*sizeof(BYTE)); lpszStart = lpszTarget + nReplacementLen; lpszStart[nBalance] = '\0'; nOldLength += (nReplacementLen - nSourceLen); //现有数据长度 } lpszStart += lstrlen(lpszStart) + 1; } assert(m_pchData[nNewLength] == '\0'); GetData()->nDataLength = nNewLength; } return nCount; } int BString::Remove(BYTE 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; } BString BString::Mid(int nFirst) const { return Mid(nFirst, GetData()->nDataLength - nFirst); } BString BString::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; BString dest; AllocCopy(dest, nCount, nFirst, 0); return dest; } BString BString::Right(int nCount) const { if (nCount < 0) nCount = 0; if (nCount >= GetData()->nDataLength) return *this; BString dest; AllocCopy(dest, nCount, GetData()->nDataLength-nCount, 0); return dest; } BString BString::Left(int nCount) const { if (nCount < 0) nCount = 0; if (nCount >= GetData()->nDataLength) return *this; BString dest; AllocCopy(dest, nCount, 0, 0); return dest; } int BString::ReverseFind(BYTE ch) const { //从最后查找 LPTSTR lpsz = _tcsrchr(m_pchData, (_TUCHAR) ch); return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); } int BString::Find(BYTE ch) const { return Find(ch, 0); } int BString::Find(BYTE 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 BString::Find(LPBTSTR lpszSub) const { return Find(lpszSub, 0); } int BString::Find(LPBTSTR 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 BString::FindOneOf(LPBTSTR lpszCharSet) const { assert(AfxIsValidString(lpszCharSet)); LPTSTR lpsz = _tcspbrk(m_pchData, lpszCharSet); return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); } void BString::MakeUpper() { CopyBeforeWrite(); _tcsupr(m_pchData); } void BString::MakeLower() { CopyBeforeWrite(); _tcslwr(m_pchData); } void BString::MakeReverse() { CopyBeforeWrite(); _tcsrev(m_pchData); } void BString::SetAt(int nIndex, BYTE ch) { assert(nIndex >= 0); assert(nIndex < GetData()->nDataLength); CopyBeforeWrite(); m_pchData[nIndex] = ch; } void BString::TrimRight(LPBTSTR 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 BString::TrimRight(BYTE 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 BString::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 BString::TrimLeft(LPBTSTR lpszTargets) { // if we're not trimming anything, we're not doing any work if (SafeStrlen(lpszTargets) == 0) return; CopyBeforeWrite(); LPBTSTR 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(BYTE)); GetData()->nDataLength = nDataLength; } } void BString::TrimLeft(BYTE chTarget) { CopyBeforeWrite(); LPBTSTR 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(BYTE)); GetData()->nDataLength = nDataLength; } } void BString::TrimLeft() { CopyBeforeWrite(); LPBTSTR 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(BYTE)); 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 BString::FormatV(LPBTSTR 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 (LPBTSTR 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': { LPBTSTR pstrNextArg = va_arg(argList, LPBTSTR); 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 BString::Format(LPBTSTR lpszFormat, ...) { assert(AfxIsValidString(lpszFormat)); va_list argList; va_start(argList, lpszFormat); FormatV(lpszFormat, argList); va_end(argList); } void BString::ConcatCopy(int nSrc1Len, LPBTSTR lpszSrc1Data,int nSrc2Len, LPBTSTR lpszSrc2Data) { int nNewLen = nSrc1Len + nSrc2Len; if (nNewLen != 0) { AllocBuffer(nNewLen); memcpy(m_pchData, lpszSrc1Data, nSrc1Len*sizeof(BYTE)); memcpy(m_pchData+nSrc1Len, lpszSrc2Data, nSrc2Len*sizeof(BYTE)); } } void BString::ConcatInPlace(int nSrcLen, LPBTSTR lpszSrcData) { if (nSrcLen == 0) return; if (GetData()->nRefs > 1 GetData()->nDataLength + nSrcLen > GetData()->nAllocLength) {//动态分配 BStringData* pOldData = GetData(); ConcatCopy(GetData()->nDataLength, m_pchData, nSrcLen, lpszSrcData); assert(pOldData != NULL); BString::Release(pOldData); } else {//直接往后添加 memcpy(m_pchData+GetData()->nDataLength, lpszSrcData, nSrcLen*sizeof(BYTE)); GetData()->nDataLength += nSrcLen; assert(GetData()->nDataLength <= GetData()->nAllocLength); m_pchData[GetData()->nDataLength] = '\0'; } } const BString& BString::operator+=(LPBTSTR lpsz) { assert(lpsz == NULL AfxIsValidString(lpsz)); ConcatInPlace(SafeStrlen(lpsz), lpsz); return *this; } const BString& BString::operator+=(BYTE ch) { ConcatInPlace(1, &ch); return *this; } const BString& BString::operator+=(const BString& string) { ConcatInPlace(string.GetData()->nDataLength, string.m_pchData); return *this; } LPTSTR BString::GetBuffer(int nMinBufLength) { assert(nMinBufLength >= 0); if (GetData()->nRefs > 1 nMinBufLength > GetData()->nAllocLength) { //重新动态分配 BStringData* 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(BYTE)); GetData()->nDataLength = nOldLen; BString::Release(pOldData); } assert(GetData()->nRefs <= 1); assert(m_pchData != NULL); return m_pchData; } void BString::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 BString::GetBufferSetLength(int nNewLength) { assert(nNewLength >= 0); GetBuffer(nNewLength); GetData()->nDataLength = nNewLength; m_pchData[nNewLength] = '\0'; return m_pchData; } void BString::FreeExtra() { assert(GetData()->nDataLength <= GetData()->nAllocLength); if (GetData()->nDataLength != GetData()->nAllocLength) { BStringData* pOldData = GetData(); AllocBuffer(GetData()->nDataLength); memcpy(m_pchData, pOldData->data(), pOldData->nDataLength*sizeof(BYTE)); assert(m_pchData[GetData()->nDataLength] == '\0'); BString::Release(pOldData); } assert(GetData() != NULL); } LPTSTR BString::LockBuffer() { LPTSTR lpsz = GetBuffer(0); GetData()->nRefs = -1; return lpsz; } void BString::UnlockBuffer() { assert(GetData()->nRefs == -1); if (GetData() != _afxDataNil) GetData()->nRefs = 1; } int BString::Compare(LPBTSTR lpsz) const { assert(AfxIsValidString(lpsz)); return _tcscmp(m_pchData, lpsz); } int BString::CompareNoCase(LPBTSTR lpsz) const { assert(AfxIsValidString(lpsz)); return _tcsicmp(m_pchData, lpsz); } // BString::Collate is often slower than Compare but is MBSC/Unicode // aware as well as locale-sensitive with respect to sort order. int BString::Collate(LPBTSTR lpsz) const { assert(AfxIsValidString(lpsz)); return _tcscoll(m_pchData, lpsz); } int BString::CollateNoCase(LPBTSTR lpsz) const { assert(AfxIsValidString(lpsz)); return _tcsicoll(m_pchData, lpsz); } TCHAR BString::GetAt(int nIndex) const { assert(nIndex >= 0); assert(nIndex < GetData()->nDataLength); return m_pchData[nIndex]; } TCHAR BString::operator[](int nIndex) const { assert(nIndex >= 0); assert(nIndex < GetData()->nDataLength); return m_pchData[nIndex]; } //////////////////////////////////////////////////////////////////////////////// BString operator+(const BString& string1, const BString& string2) { BString s; s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData, string2.GetData()->nDataLength, string2.m_pchData); return s; } BString operator+(const BString& string, LPBTSTR lpsz) { assert(lpsz == NULL AfxIsValidString(lpsz)); BString s; s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, BString::SafeStrlen(lpsz), lpsz); return s; } BString operator+(LPBTSTR lpsz, const BString& string) { assert(lpsz == NULL AfxIsValidString(lpsz)); BString s; s.ConcatCopy(BString::SafeStrlen(lpsz), lpsz, string.GetData()->nDataLength, string.m_pchData); return s; } bool operator==(const BString& s1, const BString& s2) { return s1.Compare(s2) == 0; } bool operator==(const BString& s1, LPBTSTR s2) { return s1.Compare(s2) == 0; } bool operator==(LPBTSTR s1, const BString& s2) { return s2.Compare(s1) == 0; } bool operator!=(const BString& s1, const BString& s2) { return s1.Compare(s2) != 0; } bool operator!=(const BString& s1, LPBTSTR s2) { return s1.Compare(s2) != 0; } bool operator!=(LPBTSTR s1, const BString& s2) { return s2.Compare(s1) != 0; } bool operator<(const BString& s1, const BString& s2) { return s1.Compare(s2) < 0; } bool operator<(const BString& s1, LPBTSTR s2) { return s1.Compare(s2) < 0; } bool operator<(LPBTSTR s1, const BString& s2) { return s2.Compare(s1) > 0; } bool operator>(const BString& s1, const BString& s2) { return s1.Compare(s2) > 0; } bool operator>(const BString& s1, LPBTSTR s2) { return s1.Compare(s2) > 0; } bool operator>(LPBTSTR s1, const BString& s2) { return s2.Compare(s1) < 0; } bool operator<=(const BString& s1, const BString& s2) { return s1.Compare(s2) <= 0; } bool operator<=(const BString& s1, LPBTSTR s2) { return s1.Compare(s2) <= 0; } bool operator<=(LPBTSTR s1, const BString& s2) { return s2.Compare(s1) >= 0; } bool operator>=(const BString& s1, const BString& s2) { return s1.Compare(s2) >= 0; } bool operator>=(const BString& s1, LPBTSTR s2) { return s1.Compare(s2) >= 0; } bool operator>=(LPBTSTR s1, const BString& s2) { return s2.Compare(s1) <= 0; } //////////////////////////////////////////////////////////////////////////////// void ConstructElements(BString* pElements, int nCount) { assert(nCount == 0 AfxIsValidAddress(pElements, nCount * sizeof(BString))); for (; nCount--; ++pElements) memcpy(pElements, &AfxGetEmptyString(), sizeof(*pElements)); } void DestructElements(BString* pElements, int nCount) { assert(nCount == 0 AfxIsValidAddress(pElements, nCount * sizeof(BString))); for (; nCount--; ++pElements) pElements->~BString(); } void CopyElements(BString* pDest, const BString* pSrc, int nCount) { assert(nCount == 0 AfxIsValidAddress(pDest, nCount * sizeof(BString))); assert(nCount == 0 AfxIsValidAddress(pSrc, nCount * sizeof(BString))); for (; nCount--; ++pDest, ++pSrc) *pDest = *pSrc; }