📄 string.cpp
字号:
#include "GOS.h"
#include "String.h"
#define SF_START 0x010000
#define SF_LEFT 0x020000
#define SF_PSIGN 0x040000
#define SF_PREC 0x080000
#define SF_PRECMASK 0x000f00
#define SF_WIDTHMASK 0x00f000
#define SF_PRECSHIFT 8
#define SF_WIDTHSHIFT 12
#define SB_ALLOC(nLen) m_pData=(LPTSTR)realloc(m_pData,((nLen)+1)*sizeof(TCHAR))
#define SB_INIT() \
int nSBLen=0; \
CPlex *pSBBlock; \
LPTSTR pSBCur,pSBEnd; \
BYTE SBblock0[sizeof(CPlex)+sizeof(TCHAR)*StrBufGrowSize]; \
pSBBlock=(CPlex*)SBblock0; \
pSBBlock->m_pNext=NULL; \
pSBCur=(LPTSTR)pSBBlock->data(); \
pSBEnd=pSBCur+StrBufGrowSize;
#define SB_ADDCHAR(ch) \
if(pSBCur>=pSBEnd) \
{ \
pSBCur=(LPTSTR)CPlex::CreateTail(pSBBlock,sizeof(TCHAR)*StrBufGrowSize); \
pSBEnd=pSBCur+StrBufGrowSize; \
} \
*pSBCur++=ch;nSBLen++;
#define SB_UNLOAD() \
pSBBlock=((CPlex*)SBblock0)->m_pNext; \
pSBBlock->FreeDataChain();
#define SB_RELEASE(pOut) \
free(pOut);pOut=(LPTSTR)malloc(nSBLen*sizeof(TCHAR)); \
pSBEnd=pOut;pSBBlock=(CPlex*)SBblock0; \
for(;;) \
{ \
pSBCur=(LPTSTR)pSBBlock->data(); \
if(nSBLen>StrBufGrowSize)CopyMemory(pSBEnd,pSBCur,StrBufGrowSize); \
else{CopyMemory(pSBEnd,pSBCur,nSBLen);break;} \
pSBEnd+=StrBufGrowSize; \
pSBBlock=pSBBlock->m_pNext; \
nSBLen-=StrBufGrowSize; \
} \
SB_UNLOAD();
CString::CString(LPCTSTR psz)
{
m_pData=NULL;
StrCpyN(psz,StrLen(psz));
}
CString::CString(const CString& str)
{
m_pData=NULL;
StrCpyN(str.m_pData,str.GetLength());
}
CString::~CString()
{
free(m_pData);
}
int CString::StrLen(LPCTSTR psz)
{
if(psz)
{
LPTSTR s=(LPTSTR)psz;
while(*s)
s++;
return s-psz;
}
return 0;
}
int CString::StrLenEx(LPCTSTR psz)
{
int nLen;
if(IsWritablePtr(psz))
nLen=AllocSize(psz)/sizeof(TCHAR)-1;
else
nLen=StrLen(LPTSTR(psz));
return nLen;
}
LPCTSTR CString::StrAllocEx(LPCTSTR psz)
{
if(IsWritablePtr(psz))
{
PVOID pData;
int nBytes=(strlen(psz)+1)*sizeof(TCHAR);
pData=malloc(nBytes);
CopyMemory(pData,psz,nBytes);
return LPCTSTR(pData);
}
return psz;
}
LPCTSTR CString::StrReAllocEx(LPCTSTR pszOld,LPCTSTR pszNew,int nCount)
{
PVOID pData=PVOID(pszOld);
if(nCount>0)
{
nCount++;
nCount*=sizeof(TCHAR);
if(IsWritablePtr(pData))
pData=realloc(pData,nCount);
else
pData=malloc(nCount);
CopyMemory(pData,pszNew,nCount);
}
else
{
if(IsWritablePtr(pData))
free(pData);
pData=PVOID(pszNew);
}
return LPCTSTR(pData);
}
void CString::StrFreeEx(LPCTSTR psz)
{
if(IsWritablePtr(psz))
free(PVOID(psz));
}
void CString::StrCpyN(LPCTSTR psz,int nCount)
{
LPTSTR pData=m_pData;
if(!psz || nCount<=0)
{
free(pData);
m_pData=NULL;
}
else if(psz+nCount<pData || DWORD(psz)>DWORD(pData)+_msize(pData))
{
pData=(LPTSTR)realloc(pData,(nCount+1)*sizeof(TCHAR));
CopyMemory(pData,psz,nCount);
pData[nCount]=0;
m_pData=pData;
}
else
{
pData=(LPTSTR)malloc((nCount+1)*sizeof(TCHAR));
CopyMemory(pData,psz,nCount+1);
free(m_pData);
pData[nCount]=0;
m_pData=pData;
}
}
void CString::StrCatN(LPCTSTR psz, int nCount)
{
LPTSTR pData=m_pData;
int nSize=GetLength();
SB_ALLOC(nSize+nCount);
if(psz>=pData && psz<=pData+nSize)
psz+=m_pData-pData;
CopyMemory(pData+nSize,psz,nCount);
m_pData[nSize+nCount]=0;
}
int CString::Compare(LPCTSTR psz,int nCount)
{
TCHAR c1,c2;
int r=0;
LPTSTR s1=m_pData;
LPTSTR s2=(LPTSTR)psz;
if(!psz)
r=m_pData?1:0;
else if(!m_pData)
r=-1;
else if(nCount>0)
{
do
{
c1=*s1++;c2=*s2++;
if(c1>c2)
{
r=1;
break;
}
if(c1<c2)
{
r=-1;
break;
}
}while(--nCount && c1 && c2);
}
else if(nCount<0)
{
nCount=-nCount;
do
{
c1=*s1++;c2=*s2++;
c1=c1>='a' && c1<='z'?c1-'a'+'A':c1;
c2=c2>='a' && c1<='z'?c2-'a'+'A':c2;
if(c1>c2)
{
r=1;
break;
}
if(c1<c2)
{
r=-1;
break;
}
}while(--nCount && c1 && c2);
}
return r;
}
void CString::Left(CString& strOut,int nCount)
{
ASSERT(nCount>=0);
ASSERT(nCount<=GetLength());
strOut.StrCpyN(m_pData,nCount);
}
void CString::Right(CString& strOut,int nCount)
{
ASSERT(nCount>=0);
ASSERT(nCount<=GetLength());
int nLen=GetLength();
strOut.StrCpyN(m_pData+nLen-nCount,nCount);
}
void CString::Mid(CString& strOut,int nFirst)
{
ASSERT(nFirst>=0);
ASSERT(nFirst<=GetLength());
int nCount=GetLength()-nFirst;
strOut.StrCpyN(m_pData+nFirst,nCount);
}
void CString::Mid(CString& strOut,int nFirst, int nCount)
{
ASSERT(nFirst>=0);
ASSERT(nFirst<=GetLength());
ASSERT(nCount>=0);
ASSERT(nFirst+nCount<=GetLength());
strOut.StrCpyN(m_pData+nFirst,nCount);
}
int CString::Find(LPCTSTR psz,int nStart)
{
ASSERT(nStart>=0);
ASSERT(nStart<=GetLength());
LPTSTR s1,s2,str=m_pData+nStart;
while(*str)
{
s1=str;
s2=(LPTSTR)psz;
while(*s1 && *s2 && *s1==*s2)
{
s1++;
s2++;
}
if(!(*s2))
return str-m_pData;
str++;
}
return -1;
}
int CString::Find(TCHAR ch,int nStart)
{
ASSERT(nStart>=0);
ASSERT(nStart<=GetLength());
LPTSTR s=m_pData+nStart;
while(*s)
{
if(*s==ch)
return s-m_pData;
s++;
}
return -1;
}
int CString::ReverseFind(TCHAR ch)
{
LPTSTR s=m_pData+GetLength();
while(*(--s))
{
if(*s==ch)
return s-m_pData;
}
return -1;
}
int CString::FindOneOf(LPCTSTR pszCharSet)
{
TCHAR c;
LPTSTR s2,str=m_pData;
while(*str)
{
c=*str++;
s2=(LPTSTR)pszCharSet;
while(*s2)
{
if(*s2==c)
return str-m_pData-1;
s2++;
}
}
return -1;
}
void CString::MakeUpper()
{
LPTSTR s;
for(s=m_pData;*s;s++)
{
if(*s>='a' && *s<='z')
*s-='a'-'A';
}
}
void CString::MakeLower()
{
LPTSTR s;
for(s=m_pData;*s;s++)
{
if(*s>='A' && *s<='Z')
*s+='a'-'A';
}
}
int CString::Replace(TCHAR chOld, TCHAR chNew)
{
LPTSTR s;
int nCount=0;
for(s=m_pData;*s;s++)
{
if(*s==chOld)
{
nCount++;
*s=chNew;
}
}
return nCount;
}
int CString::Replace(LPCTSTR pszOld, LPCTSTR pszNew)
{
ASSERT(pszOld);
int nAT,nAT0=0;
int i,nCount=0;
int nOldLen=StrLen(pszOld);
int nNewLen=StrLen(pszNew);
LPTSTR s,pTmp,pData;
if(nOldLen<nNewLen)
{
SB_INIT();
pData=m_pData;
while((nAT=Find(pszOld,nAT0))!=-1)
{
nCount++;
for(i=nAT0,pTmp=pData+i;i<nAT;i++)
{
SB_ADDCHAR(*pTmp++);
}
nAT0=nAT+nOldLen;
for(i=0,pTmp=LPTSTR(pszNew);i<nNewLen;i++)
{
SB_ADDCHAR(*pTmp++);
}
}
if(nCount>0)
{
nAT=GetLength();
for(i=nAT0,pTmp=pData+i;i<=nAT;i++)
{
SB_ADDCHAR(*pTmp++);
}
SB_RELEASE(m_pData);
}
else
{
SB_UNLOAD();
}
}
else
{
s=pData=m_pData;
while((nAT=Find(pszOld,nAT0))!=-1)
{
nCount++;
for(i=nAT0,pTmp=pData+i;i<nAT;i++)
*s++=*pTmp++;
nAT0=nAT+nOldLen;
for(i=0,pTmp=LPTSTR(pszNew);i<nNewLen;i++)
*s++=*pTmp++;
}
if(nCount>0)
{
nAT=GetLength();
for(i=nAT0,pTmp=pData+i;i<=nAT;i++)
*s++=*pTmp++;
SB_ALLOC(s-pData);
}
}
return nCount;
}
void CString::TrimRight(LPCTSTR pszTarget)
{
TCHAR c;
LPTSTR s2,str=m_pData+GetLength();
while(str>m_pData)
{
c=*(--str);
s2=(LPTSTR)pszTarget;
while(*s2 && *s2!=c)
{
s2++;
}
if(!*s2)
{
*(++str)=0;
SB_ALLOC(str-m_pData);
break;
}
}
}
void CString::TrimLeft(LPCTSTR pszTarget)
{
LPTSTR s2,str=m_pData;
while(*str)
{
s2=(LPTSTR)pszTarget;
while(*s2 && *s2!=*str)
{
s2++;
}
if(!*s2)
{
s2=m_pData;
do
{
*s2++=*str++;
}while(*str);
*s2=0;
SB_ALLOC(s2-m_pData);
break;
}
str++;
}
}
LPTSTR CString::GetBuffer(int nMinBufLength)
{
if(nMinBufLength>-1)
SB_ALLOC(nMinBufLength);
return m_pData;
}
void CString::ReleaseBuffer(int nNewLength)
{
if(nNewLength>-1)
{
SB_ALLOC(nNewLength);
m_pData[nNewLength]=0;
}
else
SB_ALLOC(StrLen(m_pData));
}
int CString::toInt()
{
TCHAR c;
LPTSTR s=m_pData;
int nSign=0;
int nValue=0;
while(*s)
{
c=*s++;
if(c>='0' && c<='9')
{
nValue*=10;
nValue+=c-'0';
}
else if(c=='-')
{
if(nSign)
break;
else
{
nSign=-1;
continue;
}
}
else if(c=='+')
{
if(nSign)
break;
else
{
nSign=1;
continue;
}
}
else break;
}
return nSign<0?-nValue:nValue;
}
int CString::toHex()
{
TCHAR c;
int nSign=1;
int nBase,nValue=0;
LPTSTR s=m_pData;
while(*s)
{
c=*s++;
if(c>='0' && c<='9')
nBase=c-48;
else if(c>='a' && c<='f')
nBase=c-87;
else if(c>='A' && c<='F')
nBase=c-55;
else if(c=='-')
{
nSign=-1;
continue;
}
else continue;
nValue<<=4;
nValue+=nBase;
}
return nSign<0?-nValue:nValue;
}
double CString::toDouble()
{
TCHAR c;
LPTSTR s=m_pData;
int nSign=0;
int nFloat=0;
double dValue=0;
while(*s)
{
c=*s++;
if(c>='0' && c<='9')
{
dValue*=10;
dValue+=c-'0';
if(nFloat)
nFloat*=10;
}
else if(c=='.')
{
if(nFloat)
break;
else
{
nFloat=1;
if(!nSign)
nSign=1;
continue;
}
}
else if(c=='-')
{
if(nSign)
break;
else
{
nSign=-1;
continue;
}
}
else if(c=='+')
{
if(nSign)
break;
else
{
nSign=1;
continue;
}
}
else break;
}
dValue=nFloat>0?dValue/nFloat:dValue;
return nSign<0?-dValue:dValue;
}
int CString::fmtInt(TCHAR aBuf[], int nValue,int nSign)
{
TCHAR nBase;
int j,i=0;
int nVal=nValue;
if(nValue)
{
nVal=(nVal<0)?-nVal:nVal;
do
{
nBase=(TCHAR)(nVal%10);
aBuf[i]=nBase+48;
nVal/=10;
i++;
}while(nVal);
if(nValue>0 && nSign>1)
aBuf[i++]='+';
if(nValue<0 && nSign>0)
aBuf[i++]='-';
for(j=(i-1)/2;j>=0;j--)
{
nBase=aBuf[j];
aBuf[j]=aBuf[i-j-1];
aBuf[i-j-1]=nBase;
}
}
else
aBuf[i++]='0';
return i;
}
int CString::fmtHex(TCHAR aBuf[], int nValue,BOOL bUpper)
{
TCHAR nBase;
int j,i=0;
UINT nVal=(UINT)nValue;
if(nValue)
{
do
{
nBase=(TCHAR)(nVal & 0xf);
if(nBase<10)
aBuf[i]=nBase+48;
else if(bUpper)
aBuf[i]=nBase+55;
else
aBuf[i]=nBase+87;
nVal>>=4;
i++;
}while(nVal);
for(j=(i-1)/2;j>=0;j--)
{
nBase=aBuf[j];
aBuf[j]=aBuf[i-j-1];
aBuf[i-j-1]=nBase;
}
}
else
aBuf[i++]='0';
return i;
}
int CString::fmtDouble(TCHAR aBuf[], double dValue,int nPrec,int nSign)
{
TCHAR nBase;
int k,j,i=0;
if(dValue>0)
{
if(nSign>1)
aBuf[i++]='+';
}
else if(dValue<0)
{
dValue=-dValue;
if(nSign>0)
aBuf[i++]='-';
}
j=(int)(nPrec?dValue:dValue+0.5);
dValue-=j;
i+=fmtInt(aBuf+i,j,0);
j=(nPrec<0)?-nPrec-i-1:nPrec;
if(j>0 && (nPrec>0 || dValue>0))
{
k=2;
for(nBase=0;nBase<j;nBase++)
k*=10;
dValue+=1.0/k;
aBuf[i++]='.';
do
{
dValue*=10;
nBase=(TCHAR)dValue;
dValue-=nBase;
if(dValue>0.9999999999)
{
dValue=0;
nBase+=1;
}
aBuf[i]=nBase+48;
i++;
if(nPrec<0 && dValue==0)
break;
}while(--j);
}
return i;
}
void CString::Format(LPCTSTR pszFormat, ...)
{
LPTSTR str,szFmt;
TCHAR c,aFmt[64];
int i,nCnt,nStyle=0;
int* pVar;
SB_INIT();
szFmt=(LPTSTR)pszFormat;
pVar=(int*)(&pszFormat+1);
for(c=*szFmt;c;szFmt++,c=*szFmt)
{
if(nStyle & SF_START)
{
switch(c)
{
case 'c': //字符
case 'C':
SB_ADDCHAR(*pVar++);
nStyle &= ~ SF_START;
break;
case 'd': //小数
case 'i': //小数
case 'u': //无符号
case 'o': //八进制
case 'x': //16进制小写
case 'X': //16进制大写
case 'n': //地址
case 'p': //地址
if(c=='x' || c=='o')
nCnt=fmtHex(aFmt,*pVar++,FALSE);
else if(c=='X')
nCnt=fmtHex(aFmt,*pVar++,TRUE);
else
nCnt=fmtInt(aFmt,*pVar++,(nStyle & SF_PSIGN)?2:1);
if(nStyle & SF_LEFT)
for(i=0;i<nCnt;i++)
{ SB_ADDCHAR(aFmt[i]); }
i=(nStyle & SF_WIDTHMASK)>>SF_WIDTHSHIFT;
c=(TCHAR)nStyle;c=c?c:' ';
for(;i>nCnt;i--)
{ SB_ADDCHAR(c); }
if(!(nStyle & SF_LEFT))
for(i=0;i<nCnt;i++)
{ SB_ADDCHAR(aFmt[i]); }
nStyle &= ~ SF_START;
break;
case 'e': //指数格式
case 'E': //指数格式
case 'f': //浮点格式
case 'g': //常用格式
case 'G': //常用标准格式
if(c=='g' || c=='G')
{
i=(nStyle & SF_WIDTHMASK)>>SF_WIDTHSHIFT;
i=i>0?-i:-6;
}
else
{
i=(nStyle & SF_PRECMASK)>>SF_PRECSHIFT;
i=i>0?i:4;
}
nCnt=fmtDouble(aFmt,*(double*)pVar,
i,(nStyle & SF_PSIGN)?2:1);
pVar+=2;
if(nStyle & SF_LEFT)
for(i=0;i<nCnt;i++)
{ SB_ADDCHAR(aFmt[i]); }
i=(nStyle & SF_WIDTHMASK)>>SF_WIDTHSHIFT;
if(c=='g' || c=='G')i=0;
c=(TCHAR)nStyle;c=c?c:' ';
for(;i>nCnt;i--)
{ SB_ADDCHAR(c); }
if(!(nStyle & SF_LEFT))
for(i=0;i<nCnt;i++)
{ SB_ADDCHAR(aFmt[i]); }
nStyle &= ~ SF_START;
break;
case 's':
case 'S':
str=(LPTSTR)(*pVar++);
while(*str)
{ SB_ADDCHAR(*str++); }
nStyle &= ~ SF_START;
break;
case '-': //数字左齐
nStyle|= SF_LEFT;
break;
case '+': //启用+-符号
nStyle |= SF_PSIGN;
break;
case '.': //后面的数字是小数位宽度
nStyle |= SF_PREC;
break;
case '%': //%的替用符号
SB_ADDCHAR(c);
nStyle &= ~ SF_START;
break;
break;
case '0': //数字右齐时左边空白填0
case '#': //数字右齐时左边空白填#
case '$': //数字右齐时左边空白填$
if(!(nStyle & 0xff))
{
nStyle &=~0xff;
nStyle|=c;
break;
}
default:
if(c>='0' && c<='9')
{
if(!(nStyle & 0xff))nStyle &=~0xff;nStyle|=' ';
if(nStyle & SF_PREC)//小数位精度
{
i=(nStyle & SF_PRECMASK)>>SF_PRECSHIFT;
i=i*10+(c-'0');
nStyle &=~SF_PRECMASK;
nStyle |=i<<SF_PRECSHIFT;
}
else //总宽度
{
i=(nStyle & SF_WIDTHMASK)>>SF_WIDTHSHIFT;
i=i*10+(c-'0');
nStyle &=~SF_WIDTHMASK;
nStyle |=i<<SF_WIDTHSHIFT;
}
}
}
}
else if(c=='%')
nStyle=SF_START;
else
{ SB_ADDCHAR(c); }
}
SB_ADDCHAR(0);
SB_RELEASE(m_pData);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -