青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

tqsheng

go.....
隨筆 - 366, 文章 - 18, 評(píng)論 - 101, 引用 - 0
數(shù)據(jù)加載中……

CString源碼

CString使用的是引用技術(shù),可以共享數(shù)據(jù)(這個(gè)大家都知道),另外空的CStirng是指向一個(gè)固定的地址的(_afxInitData).
另外CStirng是有長(zhǎng)度限制的2147483647(無(wú)符號(hào)int 的最大值).
數(shù)據(jù)格式
struct CStringData
{
 long nRefs; //引用記數(shù)
 int nDataLength; //字符使用長(zhǎng)度
 int nAllocLength; //分配長(zhǎng)度
 TCHAR* data() { return (TCHAR*)(this+1); } //存放字符串的地方
 //this+1 相當(dāng)與是CStringData[1];所以TCHAR* data()指的是CStringData[1]的地址
};
基本和網(wǎng)絡(luò)通訊的數(shù)據(jù)包差不多
typedef struct tagAnsMarketData //統(tǒng)一的應(yīng)答結(jié)構(gòu)
{
 WORD wStkNum; //數(shù)目
 char iData[1]; //數(shù)據(jù)
}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; //引用記數(shù)
 int nDataLength; //字符使用長(zhǎng)度
 int nAllocLength; //分配長(zhǎng)度
 TCHAR* data() { return (TCHAR*)(this+1); } //存放字符串的地方
 //this+1 相當(dāng)與是CStringData[1];所以TCHAR* data()指的是CStringData[1]的地址
};

class CString
{
public:
 //構(gòu)造函數(shù)
 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; //得到字符長(zhǎng)度
 int GetAllocLength() const; //得到分配的內(nèi)存長(zhǎng)度
 BOOL IsEmpty() const; //判斷字符長(zhǎng)度是否為0
 operator LPCTSTR() const; //類型轉(zhuǎn)換
 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);

 //操作,脫離共享數(shù)據(jù)塊
 int Delete(int nIndex, int nCount = 1);//刪除從nIndex開(kāi)始長(zhǎng)度為nCount的數(shù)據(jù)
 int Insert(int nIndex, TCHAR ch); //插入一個(gè)字符
 int Insert(int nIndex, LPCTSTR pstr); //插入一個(gè)字符串
 int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew); //替換數(shù)據(jù)
 int Replace(TCHAR chOld, TCHAR chNew); //替換數(shù)據(jù)
 int Remove(TCHAR chRemove); //移除一個(gè)字符
 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(); //大寫(xiě)
 void CString::MakeLower(); //小寫(xiě)
 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;//得到第一個(gè)匹配lpszCharSet中其中一個(gè)字符的位置 調(diào)用_tcspbrk
 //高級(jí)操作
 LPTSTR GetBuffer(int nMinBufLength); //重新分配內(nèi)存,在拷貝原來(lái)的數(shù)據(jù)
 void ReleaseBuffer(int nNewLength=-1); //在[nNewLength]='\0',對(duì)內(nèi)存大小沒(méi)有改變
 LPTSTR GetBufferSetLength(int nNewLength); //重新分配內(nèi)存,在拷貝原來(lái)的數(shù)據(jù)
 void FreeExtra(); //深拷貝自己,然后--原來(lái)的引用記數(shù)器
 LPTSTR LockBuffer(); //引用計(jì)數(shù)器=-1,加鎖
 void UnlockBuffer(); //解鎖,引用計(jì)數(shù)器=1
 //比較
 int Compare(LPCTSTR lpsz) const; //區(qū)分大小寫(xiě)比較
 int CompareNoCase(LPCTSTR lpsz) const; //不區(qū)分大小寫(xiě)比較
 //比較速度沒(méi)有Compare快
 int Collate(LPCTSTR lpsz) const; //區(qū)分大小寫(xiě)比較
 int CollateNoCase(LPCTSTR lpsz) const; //不區(qū)分大小寫(xiě)比較
 //格式化字符串
 void Format(LPCTSTR lpszFormat, ...);//CSting中最長(zhǎng)的函數(shù)了,完全是自己分析的(牛啊)

private:
 void Init();
 CStringData* GetData() const; //通過(guò)m_pchData-1 得到CStringData
 void AllocBuffer(int nLen); //給CStringData分配內(nèi)存,不帶記數(shù)器
 void CopyBeforeWrite(); //帶引用記數(shù)的復(fù)制自己深拷貝
 void AllocBeforeWrite(int nLen); //給CStringData分配內(nèi)存,帶記數(shù)器
 void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData);//分配內(nèi)存,并拷貝lpszSrcData內(nèi)容
 //把nCopyIndex開(kāi)始的nCopyLen長(zhǎng)度的數(shù)據(jù)拷貝給dest,nExtraLen擴(kuò)充的長(zhǎng)度,次函數(shù)好像沒(méi)下面用
 void AllocCopy(CString& dest, int nCopyLen, int nCopyIndex,int nExtraLen) const;
 void Release(); //--引用記數(shù)器并判斷是否刪除內(nèi)存,如刪除并初始化
 void FormatV(LPCTSTR lpszFormat, va_list argList);//格式化字符串
 void ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data,
  int nSrc2Len, LPCTSTR lpszSrc2Data);//連接數(shù)據(jù)lpszSrc1Data+lpszSrc2Data
 void ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData); //連接字符串

 static void  Release(CStringData* pData); //--引用記數(shù)器并判斷是否刪除內(nèi)存
 static void FreeData(CStringData* pData); //釋放內(nèi)存
 static int SafeStrlen(LPCTSTR lpsz); //得到長(zhǎng)度
 LPTSTR m_pchData; //指向CStringData的數(shù)據(jù)區(qū)
};

/*調(diào)用CString::Compare比較大小,如果比較中有CStirng的話用
調(diào)用operator LPCTSTR()轉(zhuǎn)化類型為L(zhǎng)PCTSTR
*/
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);

//////////////////////////////////////////////////////////////////////
//檢測(cè)lpsz是否有效,調(diào)用了IsBadStringPtr
BOOL AfxIsValidString(LPCTSTR lpsz, int nLength = -1);
//檢測(cè)lp是否能讀寫(xiě)權(quán)限,調(diào)用了IsBadReadPtr,IsBadStringPtr
BOOL AfxIsValidAddress(const void* lp,UINT nBytes, BOOL bReadWrite = TRUE);

//CStirng數(shù)組操作
void ConstructElements(CString* pElements, int nCount); //初始化CStirng數(shù)組
void DestructElements(CString* pElements, int nCount); //刪除CStirng數(shù)組
void CopyElements(CString* pDest, const CString* pSrc, int nCount); //CString數(shù)組拷貝

#endif

string.cpp

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

TCHAR afxChNil = '\0';
int _afxInitData[] = { -1, 0, 0, 0 }; //初始化CStringData的地址
CStringData* _afxDataNil = (CStringData*)&_afxInitData; //地址轉(zhuǎn)化為CStringData*
LPCTSTR _afxPchNil = (LPCTSTR)(((BYTE*)&_afxInitData)+sizeof(CStringData));
const CString&  AfxGetEmptyString()  //建立一個(gè)空的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)
  {
   //新建一快數(shù)據(jù)
   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(); //脫離共享數(shù)據(jù)塊,
  int nBytesToCopy = nNewLength - (nIndex + nCount) + 1;
  //移動(dòng)數(shù)據(jù)
  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(); //脫離共享數(shù)據(jù)

 if (nIndex < 0)
  nIndex = 0;

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

 if (GetData()->nAllocLength < nNewLength)
 { //動(dòng)態(tài)分配內(nèi)存,并拷貝原來(lái)的數(shù)據(jù)
  CStringData* pOldData = GetData();
  LPTSTR pstr = m_pchData;
  AllocBuffer(nNewLength);
  memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(TCHAR));
  CString::Release(pOldData);
 }
 //插入數(shù)據(jù)
 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(); //脫離共享數(shù)據(jù)
  if (nIndex > nNewLength)
   nIndex = nNewLength;
  nNewLength += nInsertLength;

  if (GetData()->nAllocLength < nNewLength)
  { //動(dòng)態(tài)分配內(nèi)存,并拷貝原來(lái)的數(shù)據(jù)
   CStringData* pOldData = GetData();
   LPTSTR pstr = m_pchData;
   AllocBuffer(nNewLength);
   memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(TCHAR));
   CString::Release(pOldData);
  }

  //移動(dòng)數(shù)據(jù),留出插入的位酒move也可以
  memcpy(m_pchData + nIndex + nInsertLength,
   m_pchData + nIndex,
   (nNewLength-nIndex-nInsertLength+1)*sizeof(TCHAR));
  //插入數(shù)據(jù)
  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); //相當(dāng)于++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) //檢索要替換的個(gè)數(shù)
 {
  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; //替換以后的長(zhǎng)度
  if (GetData()->nAllocLength < nNewLength GetData()->nRefs > 1)
  { //超出原來(lái)的內(nèi)存長(zhǎng)度動(dòng)態(tài)分配
   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) //這個(gè)循環(huán)好象沒(méi)什么用
  {
   while ( (lpszTarget = _tcsstr(lpszStart, lpszOld)) != NULL) //開(kāi)始替換
   {
    int nBalance = nOldLength - (lpszTarget - m_pchData + nSourceLen); //要往后移的長(zhǎng)度
    //移動(dòng)數(shù)據(jù),留出插入的位酒
    memmove(lpszTarget + nReplacementLen, lpszTarget + nSourceLen,
     nBalance * sizeof(TCHAR));
    //插入替換數(shù)據(jù)
    memcpy(lpszTarget, lpszNew, nReplacementLen*sizeof(TCHAR));
    lpszStart = lpszTarget + nReplacementLen;
    lpszStart[nBalance] = '\0';
    nOldLength += (nReplacementLen - nSourceLen); //現(xiàn)有數(shù)據(jù)長(zhǎng)度
   }
   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; //把不移除的數(shù)據(jù)拷貝
   pstrDest = _tcsinc(pstrDest);
  }
  pstrSource = _tcsinc(pstrSource);//++pstrSource
 }
 *pstrDest = '\0';
 int nCount = pstrSource - pstrDest; //比較變態(tài)的計(jì)算替換個(gè)數(shù),
 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);

 //取去整個(gè)數(shù)據(jù)
 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))
 {
  //查找%,對(duì)%%不在查找范圍
  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進(jìn)制 '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)
 {//動(dòng)態(tài)分配
  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)
 { //重新動(dòng)態(tài)分配
  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();  //脫離共享數(shù)據(jù)塊,

 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;
}

 

分類: C/C++

posted on 2011-12-28 22:58 tqsheng 閱讀(389) 評(píng)論(0)  編輯 收藏 引用


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            午夜精品理论片| 狠狠色狠狠色综合| 欧美福利视频在线| 国产精品午夜电影| 亚洲日本理论电影| 狠狠色狠狠色综合日日tαg| avtt综合网| 亚洲理论在线观看| 久久久亚洲精品一区二区三区 | 国产精品草莓在线免费观看| 欧美成人精品h版在线观看| 国产美女一区| 亚洲欧美制服另类日韩| 亚洲一区免费看| 欧美性大战久久久久久久| 亚洲日本免费电影| 一本色道久久| 欧美日韩一区二区高清| 亚洲精品欧美激情| 亚洲毛片视频| 欧美日韩精品在线视频| 亚洲国产专区校园欧美| 亚洲免费av电影| 欧美日韩国产一区二区三区地区| 欧美韩日一区| 亚洲最黄网站| 欧美日韩国产黄| av成人老司机| 亚洲欧美成aⅴ人在线观看| 国产精品www.| 午夜精品视频在线观看一区二区| 亚洲欧美三级伦理| 国产美女精品免费电影| 欧美综合二区| 欧美国产一区二区| 一本大道久久a久久精品综合| 欧美日韩一区二区三区在线视频| 亚洲一区二区三区久久| 欧美在线视频导航| 激情综合视频| 欧美精品电影在线| 这里只有精品在线播放| 久久九九全国免费精品观看| 国产综合色产| 欧美暴力喷水在线| 一区二区三区国产在线| 久久久精品午夜少妇| 亚洲国产天堂网精品网站| 欧美美女喷水视频| 亚洲婷婷在线| 欧美高清视频一区二区| 亚洲一区二区三区在线| 国产亚洲一级| 欧美日韩国产成人高清视频| 亚洲欧美激情四射在线日| 可以看av的网站久久看| 一区二区三区你懂的| 国产私拍一区| 欧美久久99| 性色一区二区| 亚洲日本一区二区三区| 久久精品成人一区二区三区蜜臀 | 亚洲一区3d动漫同人无遮挡| 国产日韩欧美不卡在线| 欧美国产精品专区| 欧美亚洲免费| 日韩一区二区精品| 欧美成人小视频| 欧美在线二区| 日韩一级黄色大片| 国外成人性视频| 欧美日韩久久久久久| 久久精品视频免费播放| 一区二区三区国产精品| 亚洲高清一区二区三区| 久久狠狠一本精品综合网| 一本色道久久精品| 亚洲成色精品| 国产午夜精品久久久久久久| 欧美视频专区一二在线观看| 久久亚洲一区二区| 午夜在线一区| 一区二区免费在线播放| 亚洲大胆美女视频| 久久精品成人欧美大片古装| 亚洲综合社区| 在线性视频日韩欧美| 亚洲日本中文| 在线免费精品视频| 国内精品免费在线观看| 国产噜噜噜噜噜久久久久久久久| 欧美精品在线免费观看| 欧美国产一区二区三区激情无套| 久久久99久久精品女同性| 欧美亚洲免费高清在线观看| 亚洲你懂的在线视频| 中文亚洲字幕| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 国产精品每日更新在线播放网址| 欧美精品久久一区| 欧美久久久久| 欧美日韩国产美| 欧美日韩播放| 欧美日韩免费观看中文| 欧美日韩精品一区二区三区| 欧美日韩精品欧美日韩精品| 欧美激情一区二区三区全黄 | 久久影音先锋| 久久综合狠狠综合久久激情| 久久亚洲午夜电影| 葵司免费一区二区三区四区五区| 久久久在线视频| 久久亚洲精品一区| 欧美xxxx在线观看| 欧美高清在线精品一区| 91久久综合| 一区二区三区日韩精品| 亚洲午夜电影| 性伦欧美刺激片在线观看| 欧美在线视频网站| 免费亚洲网站| 欧美日韩午夜剧场| 国产精品一区二区在线观看不卡| 国产美女在线精品免费观看| 国内在线观看一区二区三区| 亚洲大片免费看| 日韩视频在线播放| 亚洲欧美国产毛片在线| 久久久精品网| 亚洲国产综合视频在线观看| 一区二区三区四区五区精品| 亚洲欧美激情视频| 久久一区激情| 国产精品va在线播放| 国产三级精品三级| 亚洲韩国日本中文字幕| 亚洲一区免费网站| 另类天堂视频在线观看| 亚洲精品免费一二三区| 亚洲免费视频观看| 免费久久精品视频| 国产精品在线看| 亚洲人成艺术| 欧美中文在线观看国产| 亚洲国产欧美日韩| 香蕉亚洲视频| 欧美日韩精品在线播放| 狠狠色狠狠色综合| 亚洲自拍偷拍网址| 欧美激情一区在线观看| 亚洲欧美www| 欧美激情综合在线| 国产自产v一区二区三区c| 一区二区三区导航| 欧美电影打屁股sp| 亚洲欧美精品| 欧美日韩高清在线| 亚洲国产一区二区三区在线播| 亚洲免费网址| 亚洲欧洲精品成人久久奇米网| 欧美在线综合| 国产精品久久网| 一区二区免费在线播放| 模特精品裸拍一区| 欧美在线关看| 国产农村妇女毛片精品久久麻豆| 夜夜嗨网站十八久久| 免费观看久久久4p| 欧美一区日韩一区| 国产精品一区2区| 亚洲视频在线看| 亚洲国产精品成人一区二区| 久久精品国产一区二区三区免费看 | 国产欧美日韩免费| 亚洲一区二区三区在线视频| 亚洲国产精品电影| 六月婷婷久久| 在线观看欧美黄色| 美女免费视频一区| 久久久久在线观看| 一区二区在线看| 久久精品国产成人| 欧美一区二区三区视频在线观看| 欧美日韩另类丝袜其他| 日韩一级免费| 亚洲人体偷拍| 欧美精品午夜视频| 夜夜嗨av一区二区三区| 亚洲三级免费| 欧美另类人妖| 在线亚洲精品| 这里是久久伊人| 国产精品日韩一区| 欧美一区二区三区四区高清| 亚洲欧美视频在线观看| 国产欧美日韩麻豆91| 久久天天狠狠| 免费成人性网站| 一区二区三区精品视频在线观看| 99精品视频免费在线观看|