www.pudn.com > WinGOS.rar > 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+nCountDWORD(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='a' && c1<='z'?c1-'a'+'A':c1; 
			c2=c2>='a' && c1<='z'?c2-'a'+'A':c2; 
			if(c1>c2) 
			{ 
				r=1; 
				break; 
			} 
			if(c1=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(nOldLen0) 
		{ 
			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;i0) 
		{ 
			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;nBase0.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>SF_WIDTHSHIFT; 
				c=(TCHAR)nStyle;c=c?c:' '; 
				for(;i>nCnt;i--) 
					{ SB_ADDCHAR(c); } 
				if(!(nStyle & SF_LEFT)) 
					for(i=0;i>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>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='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_WIDTHSHIFT; 
						i=i*10+(c-'0'); 
						nStyle &=~SF_WIDTHMASK; 
						nStyle |=i<