| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109 |
- #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<LPCTSTR>(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<LPCTSTR>(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<LPCTSTR>(lpszStart), reinterpret_cast<LPCTSTR>(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;
- }
|