zoukankan      html  css  js  c++  java
  • MFC 字符串类CString 源代码

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

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

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

    string.h

    #ifndef __JONES__STRING__
    #define __JONES__STRING__

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

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

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

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

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

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

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

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

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

    #endif

    string.cpp

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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


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


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

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

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


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

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

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


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

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

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


    int CString::Delete(int nIndex, int nCount /* = 1 */)
    {
     if (nIndex < 0)
      nIndex = 0;
     int nNewLength = GetData()->nDataLength;
     if (nCount > 0 && nIndex < nNewLength)
     {
      CopyBeforeWrite(); //脱离共享数据块,
      int nBytesToCopy = nNewLength - (nIndex + nCount) + 1;
      //移动数据
      memcpy(m_pchData + nIndex,
       m_pchData + nIndex + nCount, nBytesToCopy * sizeof(TCHAR));
      GetData()->nDataLength = nNewLength - nCount;
     }
     return nNewLength;
    }


    int CString::Insert(int nIndex, TCHAR ch)
    {
     CopyBeforeWrite(); //脱离共享数据

     if (nIndex < 0)
      nIndex = 0;

     int nNewLength = GetData()->nDataLength;
     if (nIndex > nNewLength)
      nIndex = nNewLength;
     nNewLength++;

     if (GetData()->nAllocLength < nNewLength)
     { //动态分配内存,并拷贝原来的数据
      CStringData* pOldData = GetData();
      LPTSTR pstr = m_pchData;
      AllocBuffer(nNewLength);
      memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(TCHAR));
      CString::Release(pOldData);
     }
     //插入数据
     memcpy(m_pchData + nIndex + 1,
      m_pchData + nIndex, (nNewLength-nIndex)*sizeof(TCHAR));
     m_pchData[nIndex] = ch;
     GetData()->nDataLength = nNewLength;

     return nNewLength;
    }


    int CString::Insert(int nIndex, LPCTSTR pstr)
    {
     if (nIndex < 0)
      nIndex = 0;

     int nInsertLength = SafeStrlen(pstr);
     int nNewLength = GetData()->nDataLength;
     if (nInsertLength > 0)
     {
      CopyBeforeWrite(); //脱离共享数据
      if (nIndex > nNewLength)
       nIndex = nNewLength;
      nNewLength += nInsertLength;

      if (GetData()->nAllocLength < nNewLength)
      { //动态分配内存,并拷贝原来的数据
       CStringData* pOldData = GetData();
       LPTSTR pstr = m_pchData;
       AllocBuffer(nNewLength);
       memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(TCHAR));
       CString::Release(pOldData);
      }

      //移动数据,留出插入的位move也可以
      memcpy(m_pchData + nIndex + nInsertLength,
       m_pchData + nIndex,
       (nNewLength-nIndex-nInsertLength+1)*sizeof(TCHAR));
      //插入数据
      memcpy(m_pchData + nIndex,
       pstr, nInsertLength*sizeof(TCHAR));
      GetData()->nDataLength = nNewLength;
     }

     return nNewLength;
    }

    int CString::Replace(TCHAR chOld, TCHAR chNew)
    {
     int nCount = 0;
     if (chOld != chNew) //替换的不能相同
     {
      CopyBeforeWrite();
      LPTSTR psz = m_pchData;
      LPTSTR pszEnd = psz + GetData()->nDataLength;
      while (psz < pszEnd)
      {
       if (*psz == chOld) //替换
       {
        *psz = chNew;
        nCount++;
       }
       psz = _tcsinc(psz); //相当于++psz,考虑要UNICODE下版本才用的
      }
     }
     return nCount;
    }

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

     int nCount = 0;
     LPTSTR lpszStart = m_pchData;
     LPTSTR lpszEnd = m_pchData + GetData()->nDataLength;
     LPTSTR lpszTarget;
     while (lpszStart < lpszEnd) //检索要替换的个数
     {
      while ((lpszTarget = _tcsstr(lpszStart, lpszOld)) != NULL)
      {
       nCount++;
       lpszStart = lpszTarget + nSourceLen;
      }
      lpszStart += lstrlen(lpszStart) + 1;
     }

     
     if (nCount > 0)
     {
      CopyBeforeWrite();
      int nOldLength = GetData()->nDataLength;
      int nNewLength =  nOldLength + (nReplacementLen-nSourceLen)*nCount; //替换以后的长度
      if (GetData()->nAllocLength < nNewLength GetData()->nRefs > 1)
      { //超出原来的内存长度动态分配
       CStringData* pOldData = GetData();
       LPTSTR pstr = m_pchData;
       AllocBuffer(nNewLength);
       memcpy(m_pchData, pstr, pOldData->nDataLength*sizeof(TCHAR));
       CString::Release(pOldData);
      }
      
      lpszStart = m_pchData;
      lpszEnd = m_pchData + GetData()->nDataLength;

      
      while (lpszStart < lpszEnd) //这个循环好象没什么用
      {
       while ( (lpszTarget = _tcsstr(lpszStart, lpszOld)) != NULL) //开始替换
       {
        int nBalance = nOldLength - (lpszTarget - m_pchData + nSourceLen); //要往后移的长度
        //移动数据,留出插入的位
        memmove(lpszTarget + nReplacementLen, lpszTarget + nSourceLen,
         nBalance * sizeof(TCHAR));
        //插入替换数据
        memcpy(lpszTarget, lpszNew, nReplacementLen*sizeof(TCHAR));
        lpszStart = lpszTarget + nReplacementLen;
        lpszStart[nBalance] = '/0';
        nOldLength += (nReplacementLen - nSourceLen); //现有数据长度
       }
       lpszStart += lstrlen(lpszStart) + 1;
      }
      assert(m_pchData[nNewLength] == '/0');
      GetData()->nDataLength = nNewLength;
     }

     return nCount;
    }


    int CString::Remove(TCHAR chRemove)
    {
     CopyBeforeWrite();

     LPTSTR pstrSource = m_pchData;
     LPTSTR pstrDest = m_pchData;
     LPTSTR pstrEnd = m_pchData + GetData()->nDataLength;

     while (pstrSource < pstrEnd)
     {
      if (*pstrSource != chRemove)
      {
       *pstrDest = *pstrSource; //把不移除的数据拷贝
       pstrDest = _tcsinc(pstrDest);
      }
      pstrSource = _tcsinc(pstrSource);//++pstrSource
     }
     *pstrDest = '/0';
     int nCount = pstrSource - pstrDest; //比较变态的计算替换个数,
     GetData()->nDataLength -= nCount;

     return nCount;
    }


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

    CString CString::Mid(int nFirst, int nCount) const
    {
     if (nFirst < 0)
      nFirst = 0;
     if (nCount < 0)
      nCount = 0;

     if (nFirst + nCount > GetData()->nDataLength)
      nCount = GetData()->nDataLength - nFirst;
     if (nFirst > GetData()->nDataLength)
      nCount = 0;

     assert(nFirst >= 0);
     assert(nFirst + nCount <= GetData()->nDataLength);

     //取去整个数据
     if (nFirst == 0 && nFirst + nCount == GetData()->nDataLength)
      return *this;
     
     CString dest; 
     AllocCopy(dest, nCount, nFirst, 0);
     return dest;
    }


    CString CString::Right(int nCount) const
    {
     if (nCount < 0)
      nCount = 0;
     if (nCount >= GetData()->nDataLength)
      return *this;

     CString dest;
     AllocCopy(dest, nCount, GetData()->nDataLength-nCount, 0);
     return dest;
    }

    CString CString::Left(int nCount) const
    {
     if (nCount < 0)
      nCount = 0;
     if (nCount >= GetData()->nDataLength)
      return *this;

     CString dest;
     AllocCopy(dest, nCount, 0, 0);
     return dest;
    }


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

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

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

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

    int CString::Find(LPCTSTR lpszSub) const
    {
     return Find(lpszSub, 0);
    }

    int CString::Find(LPCTSTR lpszSub, int nStart) const
    {
     assert(AfxIsValidString(lpszSub));

     int nLength = GetData()->nDataLength;
     if (nStart > nLength)
      return -1;

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

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

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

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

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

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

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

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

    void CString::TrimRight(LPCTSTR lpszTargetList)
    {
     CopyBeforeWrite();
     LPTSTR lpsz = m_pchData;
     LPTSTR lpszLast = NULL;

     while (*lpsz != '/0')
     {
      if (_tcschr(lpszTargetList, *lpsz) != NULL)
      {
       if (lpszLast == NULL)
        lpszLast = lpsz;
      }
      else
       lpszLast = NULL;
      lpsz = _tcsinc(lpsz);
     }

     if (lpszLast != NULL)
     {
      *lpszLast = '/0';
      GetData()->nDataLength = lpszLast - m_pchData;
     }
    }

    void CString::TrimRight(TCHAR chTarget)
    {
     CopyBeforeWrite();
     LPTSTR lpsz = m_pchData;
     LPTSTR lpszLast = NULL;

     while (*lpsz != '/0')
     {
      if (*lpsz == chTarget)
      {
       if (lpszLast == NULL)
        lpszLast = lpsz;
      }
      else
       lpszLast = NULL;
      lpsz = _tcsinc(lpsz);
     }

     if (lpszLast != NULL)
     {
      *lpszLast = '/0';
      GetData()->nDataLength = lpszLast - m_pchData;
     }
    }

    void CString::TrimRight()
    {
     CopyBeforeWrite();
     LPTSTR lpsz = m_pchData;
     LPTSTR lpszLast = NULL;

     while (*lpsz != '/0')
     {
      if (_istspace(*lpsz))
      {
       if (lpszLast == NULL)
        lpszLast = lpsz;
      }
      else
       lpszLast = NULL;
      lpsz = _tcsinc(lpsz);
     }

     if (lpszLast != NULL)
     {
      // truncate at trailing space start
      *lpszLast = '/0';
      GetData()->nDataLength = lpszLast - m_pchData;
     }
    }

    void CString::TrimLeft(LPCTSTR lpszTargets)
    {
     // if we're not trimming anything, we're not doing any work
     if (SafeStrlen(lpszTargets) == 0)
      return;

     CopyBeforeWrite();
     LPCTSTR lpsz = m_pchData;

     while (*lpsz != '/0')
     {
      if (_tcschr(lpszTargets, *lpsz) == NULL)
       break;
      lpsz = _tcsinc(lpsz);
     }

     if (lpsz != m_pchData)
     {
      // fix up data and length
      int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);
      memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(TCHAR));
      GetData()->nDataLength = nDataLength;
     }
    }

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

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

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

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

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

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

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

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

    #ifdef _X86_
     #define DOUBLE_ARG  _AFX_DOUBLE
    #else
     #define DOUBLE_ARG  double
    #endif

    #define FORCE_ANSI      0x10000
    #define FORCE_UNICODE   0x20000
    #define FORCE_INT64     0x40000

    void CString::FormatV(LPCTSTR lpszFormat, va_list argList)
    {
     assert(AfxIsValidString(lpszFormat));

     va_list argListSave = argList;

     // make a guess at the maximum length of the resulting string
     int nMaxLen = 0;
     for (LPCTSTR lpsz = lpszFormat; *lpsz != '/0'; lpsz = _tcsinc(lpsz))
     {
      //查找%,对%%不在查找范围
      if (*lpsz != '%' *(lpsz = _tcsinc(lpsz)) == '%')
      {
       nMaxLen += _tclen(lpsz);
       continue;
      }

      int nItemLen = 0;

      //%后面的格式判断
      int nWidth = 0;
      for (; *lpsz != '/0'; lpsz = _tcsinc(lpsz))
      {
       if (*lpsz == '#') 
        nMaxLen += 2;   // 16进制 '0x'
       else if (*lpsz == '*')
        nWidth = va_arg(argList, int);
       else if (*lpsz == '-' *lpsz == '+' *lpsz == '0' 
        *lpsz == ' ')
        ;
       else // hit non-flag character
        break;
      }
      // get width and skip it
      if (nWidth == 0)
      {
       // width indicated by
       nWidth = _ttoi(lpsz);
       for (; *lpsz != '/0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz))
        ;
      }
      assert(nWidth >= 0);

      int nPrecision = 0;
      if (*lpsz == '.')
      {
       // skip past '.' separator (width.precision)
       lpsz = _tcsinc(lpsz);

       // get precision and skip it
       if (*lpsz == '*')
       {
        nPrecision = va_arg(argList, int);
        lpsz = _tcsinc(lpsz);
       }
       else
       {
        nPrecision = _ttoi(lpsz);
        for (; *lpsz != '/0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz))
         ;
       }
       assert(nPrecision >= 0);
      }

      // should be on type modifier or specifier
      int nModifier = 0;
      if (_tcsncmp(lpsz, _T("I64"), 3) == 0)
      {
       lpsz += 3;
       nModifier = FORCE_INT64;
    #if !defined(_X86_) && !defined(_ALPHA_)
       // __int64 is only available on X86 and ALPHA platforms
       ASSERT(FALSE);
    #endif
      }
      else
      {
       switch (*lpsz)
       {
       // modifiers that affect size
       case 'h':
        nModifier = FORCE_ANSI;
        lpsz = _tcsinc(lpsz);
        break;
       case 'l':
        nModifier = FORCE_UNICODE;
        lpsz = _tcsinc(lpsz);
        break;

       // modifiers that do not affect size
       case 'F':
       case 'N':
       case 'L':
        lpsz = _tcsinc(lpsz);
        break;
       }
      }

      // now should be on specifier
      switch (*lpsz | nModifier)
      {
      // single characters
      case 'c':
      case 'C':
       nItemLen = 2;
       va_arg(argList, TCHAR_ARG);
       break;
      case 'c'|FORCE_ANSI:
      case 'C'|FORCE_ANSI:
       nItemLen = 2;
       va_arg(argList, CHAR_ARG);
       break;
      case 'c'|FORCE_UNICODE:
      case 'C'|FORCE_UNICODE:
       nItemLen = 2;
       va_arg(argList, WCHAR_ARG);
       break;

      // strings
      case 's':
       {
        LPCTSTR pstrNextArg = va_arg(argList, LPCTSTR);
        if (pstrNextArg == NULL)
           nItemLen = 6;  // "(null)"
        else
        {
           nItemLen = lstrlen(pstrNextArg);
           nItemLen = max(1, nItemLen);
        }
       }
       break;

      case 'S':
       {
    #ifndef _UNICODE
        LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
        if (pstrNextArg == NULL)
           nItemLen = 6;  // "(null)"
        else
        {
           nItemLen = wcslen(pstrNextArg);
           nItemLen = max(1, nItemLen);
        }
    #else
        LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
        if (pstrNextArg == NULL)
           nItemLen = 6; // "(null)"
        else
        {
           nItemLen = lstrlenA(pstrNextArg);
           nItemLen = max(1, nItemLen);
        }
    #endif
       }
       break;

      case 's'|FORCE_ANSI:
      case 'S'|FORCE_ANSI:
       {
        LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
        if (pstrNextArg == NULL)
           nItemLen = 6; // "(null)"
        else
        {
           nItemLen = lstrlenA(pstrNextArg);
           nItemLen = max(1, nItemLen);
        }
       }
       break;

      case 's'|FORCE_UNICODE:
      case 'S'|FORCE_UNICODE:
       {
        LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
        if (pstrNextArg == NULL)
           nItemLen = 6; // "(null)"
        else
        {
           nItemLen = wcslen(pstrNextArg);
           nItemLen = max(1, nItemLen);
        }
       }
       break;
      }

      // adjust nItemLen for strings
      if (nItemLen != 0)
      {
       if (nPrecision != 0)
        nItemLen = min(nItemLen, nPrecision);
       nItemLen = max(nItemLen, nWidth);
      }
      else
      {
       switch (*lpsz)
       {
       // integers
       case 'd':
       case 'i':
       case 'u':
       case 'x':
       case 'X':
       case 'o':
        if (nModifier & FORCE_INT64)
         va_arg(argList, __int64);
        else
         va_arg(argList, int);
        nItemLen = 32;
        nItemLen = max(nItemLen, nWidth+nPrecision);
        break;

       case 'e':
       case 'g':
       case 'G':
        va_arg(argList, DOUBLE_ARG);
        nItemLen = 128;
        nItemLen = max(nItemLen, nWidth+nPrecision);
        break;

       case 'f':
        {
         double f;
         LPTSTR pszTemp;

         // 312 == strlen("-1+(309 zeroes).")
         // 309 zeroes == max precision of a double
         // 6 == adjustment in case precision is not specified,
         //   which means that the precision defaults to 6
         pszTemp = (LPTSTR)_alloca(max(nWidth, 312+nPrecision+6));

         f = va_arg(argList, double);
         _stprintf( pszTemp, _T( "%*.*f" ), nWidth, nPrecision+6, f );
         nItemLen = _tcslen(pszTemp);
        }
        break;

       case 'p':
        va_arg(argList, void*);
        nItemLen = 32;
        nItemLen = max(nItemLen, nWidth+nPrecision);
        break;

       // no output
       case 'n':
        va_arg(argList, int*);
        break;

       default:
        assert(FALSE);  // unknown formatting option
       }
      }

      // adjust nMaxLen for output nItemLen
      nMaxLen += nItemLen;
     }

     GetBuffer(nMaxLen);
     //VERIFY(_vstprintf(m_pchData, lpszFormat, argListSave) <= GetAllocLength());
     _vstprintf(m_pchData, lpszFormat, argListSave);
     ReleaseBuffer();

     va_end(argListSave);
    }

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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


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

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

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


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


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


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

    ////////////////////////////////////////////////////////////////////////////////
    CString operator+(const CString& string1, const CString& string2)
    {
     CString s;
     s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData,
      string2.GetData()->nDataLength, string2.m_pchData);
     return s;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    ////////////////////////////////////////////////////////////////////////////////

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

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


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

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

     

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

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

  • 相关阅读:
    PHP抛出简单说明
    html设置强制缓存的方法
    php yield处理大数据的方法
    pixijs 粒子聚合图片
    PHP监听消息队列的方法
    C++ fstream 二进制读写文件 (一个文件备份的例子)
    Ubuntu18.04下Docker CE安装
    Python3.9安装
    如何通过SQL命令更改Postgres的max_connections
    ubuntu 配置br0网桥,亲测有效
  • 原文地址:https://www.cnblogs.com/likeFlyingFish/p/5346022.html
Copyright © 2011-2022 走看看