📄 cstr.cpp
字号:
#include "CStr.h"
#include "string.h"
#include "tchar.h"
//#include <aygshell.h>
#ifndef DESKTOP
#define _tcsinc(x) x++
#define _tcsdec(x) x--
#endif
//******************************************//
// This string class from MortScript //
//******************************************//
//////////////////////////////////////////////////////////////////////////////
// Construction/Destruction
CStr::CStr()
{
void *data = malloc(sizeof(TCHAR));
stringData.data = (TCHAR*)data;
stringData.data[0] = '\0';
stringData.nAllocLength = 1;
stringData.nDataLength = 1;
}
CStr::CStr(const CStr& stringSrc)
{
stringData.data = (TCHAR*)malloc(stringSrc.stringData.nDataLength*sizeof(TCHAR));
memcpy( stringData.data, stringSrc.stringData.data, stringSrc.stringData.nDataLength*sizeof(TCHAR) );
stringData.nAllocLength = stringSrc.stringData.nDataLength;
stringData.nDataLength = stringSrc.stringData.nDataLength;
}
CStr::CStr(LPCTSTR lpsz)
{
if ( lpsz != NULL )
{
int len = wcslen(lpsz)+1;
stringData.data = (TCHAR*)malloc( len*sizeof(TCHAR) );
wcscpy( stringData.data, lpsz );
stringData.nAllocLength = len;
stringData.nDataLength = len;
}
else
{
stringData.data = NULL; // Nothing to free
Empty(); // Empty new string
}
}
void CStr::Empty()
{
free(stringData.data);
stringData.data = (TCHAR*)malloc(sizeof(TCHAR));
stringData.data[0] = '\0';
stringData.nAllocLength = 1;
stringData.nDataLength = 1;
}
CStr::~CStr()
{
free(stringData.data);
}
//////////////////////////////////////////////////////////////////////////////
// Helpers for the rest of the implementation
void CStr::AllocCopy(CStr& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const
{
// will clone the data attached to this string
// allocating 'nExtraLen' characters
// Places results in uninitialized string 'dest'
// Will copy the part or all of original data to start of new string
int nNewLen = nCopyLen + nExtraLen + 1;
TCHAR *newData = (TCHAR*)malloc(nNewLen*sizeof(TCHAR));
memcpy( newData, stringData.data+nCopyIndex, nCopyLen*sizeof(TCHAR) );
newData[nNewLen-1]='\0';
free( dest.stringData.data );
dest.stringData.data = newData;
dest.stringData.nAllocLength = nNewLen;
dest.stringData.nDataLength = nNewLen;
}
//////////////////////////////////////////////////////////////////////////////
// Assignment operators
// All assign a new value to the string
// (a) first see if the buffer is big enough
// (b) if enough room, copy on top of old buffer, set size and type
// (c) otherwise free old string data, and create a new one
//
// All routines return the new string (but as a 'const CStr&' so that
// assigning it again will cause a copy, eg: s1 = s2 = "hi there".
//
void CStr::AssignCopy(int nSrcLen, LPCTSTR lpszSrcData)
{
free( stringData.data );
stringData.data = (TCHAR*)malloc(nSrcLen*sizeof(TCHAR));
memcpy( stringData.data, lpszSrcData, nSrcLen*sizeof(TCHAR) );
stringData.data[nSrcLen-1] = '\0';
stringData.nAllocLength = nSrcLen;
stringData.nDataLength = nSrcLen;
}
const CStr& CStr::operator=(const CStr& stringSrc)
{
AssignCopy(stringSrc.stringData.nDataLength, stringSrc.stringData.data);
return *this;
}
const CStr& CStr::operator=(LPCTSTR lpsz)
{
AssignCopy(wcslen(lpsz)+1, lpsz);
return *this;
}
//////////////////////////////////////////////////////////////////////////////
// concatenation
// NOTE: "operator+" is done as friend functions for simplicity
// There are three variants:
// CStr + CStr
// and for ? = TCHAR, LPCTSTR
// CStr + ?
// ? + CStr
void CStr::ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data, int nSrc2Len, LPCTSTR lpszSrc2Data)
{
// no space for two binary zeros needed...
int nNewLen = nSrc1Len + nSrc2Len - 1;
if (nNewLen != 0)
{
TCHAR *newData = (TCHAR*)malloc(nNewLen*sizeof(TCHAR));
memcpy( newData, lpszSrc1Data, nSrc1Len*sizeof(TCHAR));
memcpy( newData+nSrc1Len-1, lpszSrc2Data, nSrc2Len*sizeof(TCHAR));
newData[nNewLen-1] = '\0';
free( stringData.data );
stringData.data = newData;
stringData.nDataLength = nNewLen;
stringData.nAllocLength = nNewLen;
}
else
{
Empty();
}
}
CStr operator+(const CStr& string1, const CStr& string2)
{
CStr s;
s.ConcatCopy(string1.stringData.nDataLength, string1.stringData.data,
string2.stringData.nDataLength, string2.stringData.data);
return s;
}
CStr operator+(const CStr& string, LPCTSTR lpsz)
{
CStr s;
s.ConcatCopy(string.stringData.nDataLength, string.stringData.data,
wcslen(lpsz)+1, lpsz);
return s;
}
CStr operator+(LPCTSTR lpsz, const CStr& string)
{
CStr s;
s.ConcatCopy(wcslen(lpsz)+1, lpsz,
string.stringData.nDataLength, string.stringData.data);
return s;
}
//////////////////////////////////////////////////////////////////////////////
// concatenate in place
void CStr::ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData)
{
// -- the main routine for += operators
// concatenating an empty string is a no-op!
if (nSrcLen <= 1)
return;
int nNewLen = stringData.nDataLength + nSrcLen - 1;
TCHAR *newData = (TCHAR*)malloc(nNewLen*sizeof(TCHAR));
memcpy( newData, stringData.data, stringData.nDataLength*sizeof(TCHAR));
memcpy( newData+stringData.nDataLength-1, lpszSrcData, nSrcLen*sizeof(TCHAR));
newData[nNewLen-1] = '\0';
free( stringData.data );
stringData.data = newData;
stringData.nDataLength = nNewLen;
stringData.nAllocLength = nNewLen;
}
const CStr& CStr::operator+=(LPCTSTR lpsz)
{
ConcatInPlace(wcslen(lpsz)+1, lpsz);
return *this;
}
const CStr& CStr::operator+=(TCHAR ch)
{
ConcatInPlace(2, &ch);
return *this;
}
const CStr& CStr::operator+=(const CStr& string)
{
ConcatInPlace(string.stringData.nDataLength, string.stringData.data);
return *this;
}
///////////////////////////////////////////////////////////////////////////////
// Advanced direct buffer access
LPTSTR CStr::GetBuffer(int nMinBufLength)
{
ASSERT(nMinBufLength >= 0);
if (nMinBufLength > stringData.nAllocLength)
{
// we have to grow the buffer
TCHAR *newData = (TCHAR*)malloc(nMinBufLength*sizeof(TCHAR));
memcpy( newData, stringData.data, stringData.nDataLength*sizeof(TCHAR));
free( stringData.data );
stringData.data = newData;
stringData.nDataLength = nMinBufLength;
stringData.nAllocLength = nMinBufLength;
}
return stringData.data;
}
void CStr::ReleaseBuffer(int nNewLength)
{
stringData.nDataLength = wcslen(stringData.data)+1;
FreeExtra();
}
LPTSTR CStr::GetBufferSetLength(int nNewLength)
{
return GetBuffer(nNewLength);
}
void CStr::FreeExtra()
{
if (stringData.nDataLength != stringData.nAllocLength)
{
TCHAR *newData = (TCHAR*)malloc(stringData.nDataLength*sizeof(TCHAR));
memcpy( newData, stringData.data, stringData.nDataLength*sizeof(TCHAR));
free( stringData.data );
stringData.data = newData;
stringData.data[stringData.nDataLength-1] = '\0';
stringData.nDataLength = stringData.nDataLength;
stringData.nAllocLength = stringData.nDataLength;
}
}
CStr::operator LPCTSTR() const
{
return (LPCTSTR)stringData.data;
}
int CStr::GetLength() const
{
return stringData.nDataLength-1;
}
BOOL CStr::IsEmpty() const
{
return (stringData.nDataLength==1);
}
TCHAR CStr::GetAt( int idx ) const
{
if ( idx < stringData.nDataLength )
return stringData.data[idx];
else
return '\0';
}
///////////////////////////////////////////////////////////////////////////////
// Commonly used routines (rarely used routines in STREX.CPP)
int CStr::Find(TCHAR ch) const
{
return Find(ch, 0);
}
int CStr::Find(TCHAR ch, int nStart) const
{
if (nStart >= stringData.nDataLength)
return -1;
// find first single character
LPTSTR lpsz = wcschr(stringData.data + nStart, (TCHAR)ch);
// return -1 if not found and index otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - stringData.data);
}
int CStr::FindOneOf(LPCTSTR lpszCharSet,int nStart) const
{
LPTSTR lpsz = wcspbrk(stringData.data+nStart, lpszCharSet);
return (lpsz == NULL) ? -1 : (int)(lpsz - stringData.data);
}
int CStr::ReverseFind(TCHAR ch) const
{
// find last single character
LPTSTR lpsz = wcsrchr(stringData.data, (TCHAR) ch);
// return -1 if not found, distance from beginning otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - stringData.data);
}
// find a sub-string (like strstr)
int CStr::Find(LPCTSTR lpszSub) const
{
return Find(lpszSub, 0);
}
int CStr::Find(LPCTSTR lpszSub, int nStart) const
{
if (nStart > stringData.nDataLength)
return -1;
// find first matching substring
LPTSTR lpsz = wcsstr(stringData.data + nStart, lpszSub);
// return -1 for not found, distance from beginning otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - stringData.data);
}
// Include
// 0=return not include Begin & End And self string not include Begin & End
// 1=return include Begin And self string not include Begin but include End
// 2=return include End And self string not include End but include Begin
// 3=return include Begin & End And Self String not include Begin & End
// 4=return include Begin And self String not include Begin & End
// 5=return include End And self String not include Begin & End
// 6=return include Begin & End And Self string include Begin & End
// 7=return include Begin And Self string include Begin & End
// 8=return include End And Self string include Begin & End
// 9=return not include Begin & End And self string not include Begin & End
CStr CStr::Get(LPCTSTR lpszBegin, LPCTSTR lpszEnd,LPCTSTR lpszPrevSrch,int InCluded){
int be=0,ed,lb,le;
CStr rc,rtn=NULL;
CStr r1,r2,r3,cBegin=lpszBegin,cEnd=lpszEnd,prevStr=L"";
if (lpszPrevSrch) {
be = Find(lpszPrevSrch);
if (be<0) be=0; else be+=wcslen(lpszPrevSrch);
}
if ((be = InCluded<10 ? Find(cBegin,be) : FindOneOf(cBegin,be))!=-1){
r1=Left(be); //ABC-[7:00/windows/]EFG =>r1=ABC
if (InCluded<10){
lb=wcslen(lpszBegin);
}else{
lb=1;
cBegin=Mid(be,1);
}
//lb = InCluded<10 ? : 1;//Begin =>-[
if (InCluded<10){
ed=Find(lpszEnd,be+lb);
}else{
ed=FindOneOf(lpszEnd,be+lb);
if (ed!=-1){
cEnd=Mid(ed,1);
}
}
if (ed!=-1){
le = InCluded<10 ? wcslen(lpszEnd) : 1;
r3=Right(stringData.nDataLength-(ed+le)-1);//=>r3=EFG
r2=Mid(be+lb,ed-(be+lb));//=>r2=7:00/windows/
if (InCluded>=10)InCluded-=10;
switch(InCluded){
case 0: rtn = r2; rc = r1 + r3; break;
case 1: rtn = cBegin + r2; rc = r1 + cEnd + r3; break;
case 2: rtn = r2+cEnd; rc = r1 + cBegin + r3; break;
case 3: rtn = cBegin + r2 + cEnd; rc = r1 + r3; break;
case 4: rtn = cBegin + r2; rc = r1 + r3; break;
case 5: rtn = r2 + lpszEnd; rc = r1 + r3; break;
case 6: rtn = cBegin + r2 + cEnd; rc = r1 + cBegin + cEnd + r3; break;
case 7: rtn = cBegin + r2 ; rc = r1 + cBegin + cEnd + r3; break;
case 8: rtn = r2 + cEnd; rc = r1 + cBegin + cEnd + r3; break;
default: rtn = r2; rc = r1 + cBegin + cEnd + r3; break;
}
// fix up data and length
int nDataLength = rc.GetLength()+1;
LPTSTR newData = (LPTSTR)malloc( nDataLength*sizeof(TCHAR) );
memcpy(newData, rc, (nDataLength)*sizeof(TCHAR));
free( stringData.data );
stringData.data = newData;
stringData.nDataLength = nDataLength;
stringData.nAllocLength = nDataLength;
}
}
return rtn;
}
CStr CStr::Get(LPCTSTR lpszBegin, LPCTSTR lpszEnd,int InCluded){
return Get(lpszBegin,lpszEnd,NULL,InCluded);
}
CStr CStr::Get(LPCTSTR lpszBegin, LPCTSTR lpszEnd,LPCTSTR lpszPrevSrch){
return Get(lpszBegin,lpszEnd,lpszPrevSrch,1);
}
//CStr CStr::Get(LPCTSTR lpszBegin, LPCTSTR lpszEnd,LPCTSTR lpszPrevSrch,BOOL InCluded){
// return Get(lpszBegin,lpszEnd,lpszPrevSrch,InCluded,NULL);
//}
// check beginning of string
bool CStr::StartsWith(LPCTSTR lpszSub) const
{
int len = wcslen( lpszSub );
if ( stringData.nDataLength < len )
return false;
return ( wcsncmp( stringData.data, lpszSub, len ) == 0 );
}
//extern Debug(LPCTSTR ,long);
// check beginning of string
bool CStr::EndsWith(LPCTSTR lpszSub) const
{
int len = wcslen( lpszSub );
int olen ;
olen = stringData.nDataLength-1;
if ( olen < len )
return false;
int j = len-1; int i = olen - 1;
TCHAR c1,c2;
while(j>=0){
c1=stringData.data[i];
c2=lpszSub[j];
if (c1 != c2) return false;
if (i==0) break;
j--;i--;
}
return true;
}
void CStr::MakeUpper()
{
wcsupr( stringData.data );
}
void CStr::MakeLower()
{
wcslwr( stringData.data );
}
void CStr::TrimRight(LPCTSTR lpszTargetList)
{
// find beginning of trailing matches
// by starting at beginning (DBCS aware)
LPTSTR lpsz = stringData.data;
LPTSTR lpszLast = NULL;
while (*lpsz != '\0')
{
if (wcschr(lpszTargetList, *lpsz) != NULL)
{
if (lpszLast == NULL)
lpszLast = lpsz;
}
else
lpszLast = NULL;
lpsz = _tcsinc(lpsz);
}
if (lpszLast != NULL)
{
// truncate at left-most matching character
*lpszLast = '\0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -