先说明下,该字符串类大部分源码是在MFC的源码中扣出来的,成员函数和CString基本一致,但是数据结构被重新定义了,不支持引用计数,写拷贝。
使用方法:
ZwString 《==》CString
ZwStringW《==》CStringW
ZwStringA 《==》CStringA
申明下,该类没有经过严格测试,肯定存在一些小BUG,请谨慎使用。最后也请大家帮忙一起完善这个类,先谢谢了。
文件名:ZwString.h
#pragma once;
#include "stdio.h"
#include "tchar.h"
#include "assert.h"
#include <malloc.h>
#include <string.h>
#include <mbstring.h>
inline int Zwwtoa(_Out_cap_(count) char* mbstr, _In_z_ const wchar_t* wcstr, _In_ ULONG count)
{
// count is number of bytes
if (count == 0 || mbstr == NULL)
return 0;
int result = ::WideCharToMultiByte(CP_ACP, 0, wcstr, -1,
mbstr, count, NULL, NULL);
return result;
}
inline int Zwatow(_Out_z_cap_(count) wchar_t* wcstr, _In_z_ const char* mbstr, _In_ ULONG count)
{
// count is number of wchar_t's
if (count == 0 || wcstr == NULL)
return 0;
int result = ::MultiByteToWideChar(CP_ACP, 0, mbstr, -1,
wcstr, count);
if ((result > 0) && (wcstr != NULL))
{
wcstr[result-1] = 0;
}
return result;
}
#pragma warning(disable : 4996)
class ZwTraitsBase
{
public:
static inline int Zwstrlen(const char *pstr)
{
return strlen(pstr);
}
static inline char* Zwstrcat(char *dest,const char *src)
{
return strcat(dest,src);
}
static inline char * Zwstrcpy(char *dest,const char *src)
{
return strcpy(dest,src);
}
static inline int Zwstrcmp(const char *str1,const char *str2)
{
return strcmp(str1,str2);
}
static inline int Zwstrlen(const wchar_t *pstr)
{
return wcslen(pstr);
}
static inline wchar_t* Zwstrcat(wchar_t *dest,const wchar_t *src)
{
return wcscat(dest,src);
}
static inline wchar_t * Zwstrcpy(wchar_t *dest,const wchar_t *src)
{
return wcscpy(dest,src);
}
static inline int Zwstrcmp(const wchar_t *str1,const wchar_t *str2)
{
return wcscmp(str1,str2);
}
static DWORD __cdecl _GetEnvironmentVariableW( _In_z_ LPCWSTR pszName, _Out_opt_cap_post_count_(nSize, return) LPWSTR pszBuffer, _In_ DWORD nSize ) throw()
{
return ::GetEnvironmentVariableW( pszName, pszBuffer, nSize );
}
public:
static LPWSTR __cdecl CharNext( _In_z_ LPCWSTR psz ) throw()
{
return const_cast< LPWSTR >( psz+1 );
}
static int __cdecl IsDigit( _In_ wchar_t ch ) throw()
{
return iswdigit( static_cast<unsigned short>(ch) );
}
static int __cdecl IsSpace( _In_ wchar_t ch ) throw()
{
return iswspace( static_cast<unsigned short>(ch) );
}
static int __cdecl StringCompare( _In_z_ LPCWSTR pszA, _In_z_ LPCWSTR pszB ) throw()
{
return wcscmp( pszA, pszB );
}
static int __cdecl StringCompareIgnore( _In_z_ LPCWSTR pszA, _In_z_ LPCWSTR pszB ) throw()
{
return _wcsicmp( pszA, pszB );
}
static int __cdecl StringCollate( _In_z_ LPCWSTR pszA, _In_z_ LPCWSTR pszB ) throw()
{
return wcscoll( pszA, pszB );
}
static int __cdecl StringCollateIgnore( _In_z_ LPCWSTR pszA, _In_z_ LPCWSTR pszB ) throw()
{
return _wcsicoll( pszA, pszB );
}
static LPCWSTR __cdecl StringFindString( _In_z_ LPCWSTR pszBlock, _In_z_ LPCWSTR pszMatch ) throw()
{
return wcsstr( pszBlock, pszMatch );
}
static LPWSTR __cdecl StringFindString( _In_z_ LPWSTR pszBlock, _In_z_ LPCWSTR pszMatch ) throw()
{
return( const_cast< LPWSTR >( StringFindString( const_cast< LPCWSTR >( pszBlock ), pszMatch ) ) );
}
static LPCWSTR __cdecl StringFindChar( _In_z_ LPCWSTR pszBlock, _In_ wchar_t chMatch ) throw()
{
return wcschr( pszBlock, chMatch );
}
static LPCWSTR __cdecl StringFindCharRev( _In_z_ LPCWSTR psz, _In_ wchar_t ch ) throw()
{
return wcsrchr( psz, ch );
}
static LPCWSTR __cdecl StringScanSet( _In_z_ LPCWSTR pszBlock, _In_z_ LPCWSTR pszMatch ) throw()
{
return wcspbrk( pszBlock, pszMatch );
}
static int __cdecl StringSpanIncluding( _In_z_ LPCWSTR pszBlock, _In_z_ LPCWSTR pszSet ) throw()
{
return (int)wcsspn( pszBlock, pszSet );
}
static int __cdecl StringSpanExcluding( _In_z_ LPCWSTR pszBlock, _In_z_ LPCWSTR pszSet ) throw()
{
return (int)wcscspn( pszBlock, pszSet );
}
static LPWSTR __cdecl StringUppercase( _Inout_ LPWSTR psz ) throw()
{
#pragma warning (push)
#pragma warning(disable : 4996)
return _wcsupr( psz );
#pragma warning (pop)
}
static LPWSTR __cdecl StringLowercase( _Inout_ LPWSTR psz ) throw()
{
#pragma warning (push)
#pragma warning(disable : 4996)
return _wcslwr( psz );
#pragma warning (pop)
}
static LPWSTR __cdecl StringUppercase( _Inout_cap_(size) LPWSTR psz, _In_ size_t size ) throw()
{
errno_t err = _wcsupr_s( psz, size );
return (err == 0) ? psz : NULL;
}
static LPWSTR __cdecl StringLowercase( _Inout_cap_(size) LPWSTR psz, _In_ size_t size ) throw()
{
errno_t err = _wcslwr_s( psz, size );
return (err == 0) ? psz : NULL;
}
static LPWSTR __cdecl StringReverse( _Inout_ LPWSTR psz ) throw()
{
return _wcsrev( psz );
}
static int __cdecl GetFormattedLength( _In_ _Printf_format_string_ LPCWSTR pszFormat, va_list args) throw()
{
return _vscwprintf( pszFormat, args );
}
static int __cdecl Format( _Out_ LPWSTR pszBuffer, _In_ _Printf_format_string_ LPCWSTR pszFormat, va_list args) throw()
{
#pragma warning (push)
#pragma warning(disable : 4996)
return vswprintf( pszBuffer, pszFormat, args );
#pragma warning (pop)
}
static int __cdecl Format
( _Out_cap_(nLength) LPWSTR pszBuffer, _In_ size_t nLength, _In_ __format_string LPCWSTR pszFormat, va_list args) throw()
{
return vswprintf_s( pszBuffer, nLength, pszFormat, args );
}
static int __cdecl GetBaseTypeLength( _In_z_ LPCSTR pszSrc ) throw()
{
// Returns required buffer size in wchar_ts
return ::MultiByteToWideChar( CP_ACP, 0, pszSrc, -1, NULL, 0 )-1;
}
static int __cdecl GetBaseTypeLength( _In_count_(nLength) LPCSTR pszSrc, _In_ int nLength ) throw()
{
// Returns required buffer size in wchar_ts
return ::MultiByteToWideChar(CP_ACP, 0, pszSrc, nLength, NULL, 0 );
}
static void __cdecl FloodCharacters( _In_ wchar_t ch, _In_ int nLength, _Out_capcount_(nLength) LPWSTR psz ) throw()
{
// nLength is in XCHARs
for( int i = 0; i < nLength; i++ )
{
psz[i] = ch;
}
}
/*static BSTR __cdecl AllocSysString( _In_count_(nDataLength) const wchar_t* pchData, _In_ int nDataLength ) throw()
{
return ::SysAllocStringLen( pchData, nDataLength );
}
static BOOL __cdecl ReAllocSysString( _In_count_(nDataLength) const wchar_t* pchData, _Inout_ BSTR* pbstr, _In_ int nDataLength ) throw()
{
return ::SysReAllocStringLen( pbstr, pchData, nDataLength );
}*/
static int __cdecl SafeStringLen( _In_opt_z_ LPCSTR psz ) throw()
{
// returns length in bytes
return (psz != NULL) ? (int)strlen( psz ) : 0;
}
static int __cdecl SafeStringLen( _In_opt_ LPCWSTR psz ) throw()
{
// returns length in wchar_ts
return (psz != NULL) ? (int)wcslen( psz ) : 0;
}
static int __cdecl GetCharLen( _In_z_ const wchar_t* pch ) throw()
{
(void)pch;
// returns char length
return 1;
}
static int __cdecl GetCharLen( _In_z_ const char* pch ) throw()
{
// returns char length
return (int)( _mbclen( reinterpret_cast< const unsigned char* >( pch ) ) );
}
static DWORD __cdecl GetEnvironmentVariable( _In_z_ LPCWSTR pszVar, _Out_opt_cap_(dwSize) LPWSTR pszBuffer, _In_ DWORD dwSize ) throw()
{
return _GetEnvironmentVariableW( pszVar, pszBuffer, dwSize );
}
static char* __cdecl CharNext( _In_z_ const char* p ) throw()
{
return reinterpret_cast< char* >( _mbsinc( reinterpret_cast< const unsigned char* >( p ) ) );
}
static int __cdecl IsDigit( _In_ char ch ) throw()
{
return _ismbcdigit( ch );
}
static int __cdecl IsSpace( _In_ char ch ) throw()
{
return _ismbcspace( ch );
}
static int __cdecl StringCompare( _In_z_ LPCSTR pszA, _In_z_ LPCSTR pszB ) throw()
{
return _mbscmp( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ) );
}
static int __cdecl StringCompareIgnore( _In_z_ LPCSTR pszA, _In_z_ LPCSTR pszB ) throw()
{
return _mbsicmp( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ) );
}
static int __cdecl StringCollate( _In_z_ LPCSTR pszA, _In_z_ LPCSTR pszB ) throw()
{
return _mbscoll( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ) );
}
static int __cdecl StringCollateIgnore( _In_z_ LPCSTR pszA, _In_z_ LPCSTR pszB ) throw()
{
return _mbsicoll( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ) );
}
static LPCSTR __cdecl StringFindString( _In_z_ LPCSTR pszBlock, _In_z_ LPCSTR pszMatch ) throw()
{
return reinterpret_cast< LPCSTR >( _mbsstr( reinterpret_cast< const unsigned char* >( pszBlock ),
reinterpret_cast< const unsigned char* >( pszMatch ) ) );
}
static LPSTR __cdecl StringFindString( _In_z_ LPSTR pszBlock, _In_z_ LPCSTR pszMatch ) throw()
{
return( const_cast< LPSTR >( StringFindString( const_cast< LPCSTR >( pszBlock ), pszMatch ) ) );
}
static LPCSTR __cdecl StringFindChar( _In_z_ LPCSTR pszBlock, _In_ char chMatch ) throw()
{
return reinterpret_cast< LPCSTR >( _mbschr( reinterpret_cast< const unsigned char* >( pszBlock ), (unsigned char)chMatch ) );
}
static LPCSTR __cdecl StringFindCharRev( _In_z_ LPCSTR psz, _In_ char ch ) throw()
{
return reinterpret_cast< LPCSTR >( _mbsrchr( reinterpret_cast< const unsigned char* >( psz ), (unsigned char)ch ) );
}
static LPCSTR __cdecl StringScanSet( _In_z_ LPCSTR pszBlock, _In_z_ LPCSTR pszMatch ) throw()
{
return reinterpret_cast< LPCSTR >( _mbspbrk( reinterpret_cast< const unsigned char* >( pszBlock ),
reinterpret_cast< const unsigned char* >( pszMatch ) ) );
}
static int __cdecl StringSpanIncluding( _In_z_ LPCSTR pszBlock, _In_z_ LPCSTR pszSet ) throw()
{
return (int)_mbsspn( reinterpret_cast< const unsigned char* >( pszBlock ), reinterpret_cast< const unsigned char* >( pszSet ) );
}
static int __cdecl StringSpanExcluding( _In_z_ LPCSTR pszBlock, _In_z_ LPCSTR pszSet ) throw()
{
return (int)_mbscspn( reinterpret_cast< const unsigned char* >( pszBlock ), reinterpret_cast< const unsigned char* >( pszSet ) );
}
static LPSTR __cdecl StringUppercase( _Inout_ LPSTR psz ) throw()
{
#pragma warning (push)
#pragma warning(disable : 4996)
return reinterpret_cast< LPSTR >( _mbsupr( reinterpret_cast< unsigned char* >( psz ) ) );
#pragma warning (pop)
}
static LPSTR __cdecl StringLowercase( _Inout_ LPSTR psz ) throw()
{
#pragma warning (push)
#pragma warning(disable : 4996)
return reinterpret_cast< LPSTR >( _mbslwr( reinterpret_cast< unsigned char* >( psz ) ) );
#pragma warning (pop)
}
static LPSTR __cdecl StringReverse( _Inout_ LPSTR psz ) throw()
{
return reinterpret_cast< LPSTR >( _mbsrev( reinterpret_cast< unsigned char* >( psz ) ) );
}
static int __cdecl GetFormattedLength( _In_ _Printf_format_string_ LPCSTR pszFormat, va_list args ) throw()
{
return _vscprintf( pszFormat, args );
}
static int __cdecl Format( _Out_ LPSTR pszBuffer, _In_ _Printf_format_string_ LPCSTR pszFormat, va_list args ) throw()
{
#pragma warning (push)
#pragma warning(disable : 4996)
return vsprintf( pszBuffer, pszFormat, args );
#pragma warning (pop)
}
static int __cdecl Format
( _Out_cap_post_count_(nlength, return) LPSTR pszBuffer, _In_ size_t nlength, _In_ _Printf_format_string_ LPCSTR pszFormat, va_list args ) throw()
{
return vsprintf_s( pszBuffer, nlength, pszFormat, args );
}
static int __cdecl GetBaseTypeLength( _In_z_ LPCWSTR pszSource ) throw()
{
// Returns required buffer length in XCHARs
return ::WideCharToMultiByte( CP_ACP, 0, pszSource, -1, NULL, 0, NULL, NULL )-1;
}
static int __cdecl GetBaseTypeLength( _In_count_(nLength) LPCWSTR pszSource, int nLength ) throw()
{
// Returns required buffer length in XCHARs
return ::WideCharToMultiByte( CP_ACP, 0, pszSource, nLength, NULL, 0, NULL, NULL );
}
static void __cdecl ConvertToBaseType( _Out_cap_(nDestLength) LPSTR pszDest, _In_ int nDestLength,
_In_z_ LPCWSTR pszSrc, _In_ int nSrcLength = -1) throw()
{
// nLen is in XCHARs
::WideCharToMultiByte( CP_ACP, 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL );
}
static void __cdecl FloodCharacters( _In_ char ch, _In_ int nLength, _Out_capcount_(nLength) char* pch ) throw()
{
// nLength is in XCHARs
memset( pch, ch, nLength );
}
/*static BSTR __cdecl AllocSysString( _In_count_(nDataLength) const char* pchData, int nDataLength ) throw()
{
int nLen = ::MultiByteToWideChar( CP_ACP, 0, pchData, nDataLength,
NULL, NULL );
BSTR bstr = ::SysAllocStringLen( NULL, nLen );
if( bstr != NULL )
{
::MultiByteToWideChar( CP_ACP, 0, pchData, nDataLength,
bstr, nLen );
}
return bstr;
}
static BOOL __cdecl ReAllocSysString( _In_count_(nDataLength) const char* pchData, _Out_ BSTR* pbstr, _In_ int nDataLength ) throw()
{
int nLen = ::MultiByteToWideChar( CP_ACP, 0, pchData, nDataLength, NULL, NULL );
BOOL bSuccess = ::SysReAllocStringLen( pbstr, NULL, nLen );
if( bSuccess )
{
::MultiByteToWideChar( CP_ACP, 0, pchData, nDataLength, *pbstr, nLen );
}
return bSuccess;
}*/
static DWORD __cdecl GetEnvironmentVariable( _In_z_ LPCSTR pszVar,
_Out_opt_cap_(dwSize) LPSTR pszBuffer, _In_ DWORD dwSize ) throw()
{
return ::GetEnvironmentVariableA( pszVar, pszBuffer, dwSize );
}
};
template <typename T>
class ZwTString:public ZwTraitsBase
{
public:
int GetLength() const
{
return m_cLen;
}
ZwTString()
{
m_data[MAX_PATH] = '\0';
m_pData = m_data;
m_mLen = MAX_PATH;
m_cLen = 0;
}
~ZwTString()
{
if (m_pData != m_data)
{
free(m_pData);
}
}
T* Resize(int nSize)
{
if (nSize > m_mLen)
{
while(nSize > m_mLen)
{
if (m_mLen < 1024)
{
m_mLen = m_mLen*2;
}
else
{
m_mLen += 1024;
}
}
m_pData = (T*)malloc(sizeof(T)*m_mLen);
}
return m_pData;
}
void CopyResize(int nSize)
{
if (nSize > m_mLen)
{
while(nSize > m_mLen)
m_mLen = m_mLen*2;
if (m_pData == m_data)
{
m_pData = (T*)malloc(m_pData ,sizeof(T)*m_mLen);
memcpy(m_pData,m_data,sizeof(T)*(m_cLen + 1));
}
else
{
m_pData = (T*)realloc(m_pData ,sizeof(T)*m_mLen);
}
}
}
ZwTString(const ZwTString& strSrc )
{
if (strSrc.m_cLen < MAX_PATH)
{
m_pData = m_data;
memcpy(m_pData,strSrc.m_pData,sizeof(T)*(strSrc.m_cLen + 1));
m_cLen = strSrc.m_cLen;
m_mLen = MAX_PATH;
}
else
{
Resize(strSrc.m_cLen);
memcpy(m_pData,strSrc.m_pData,sizeof(T)*(strSrc.m_cLen + 1));
m_cLen = strSrc.m_cLen;
}
}
ZwTString(const T *pT)
{
if ((m_cLen = Zwstrlen(pT)) < MAX_PATH)
{
Zwstrcpy(m_data,pT);
m_pData = m_data;
m_mLen = MAX_PATH;
}
else
{
Resize(m_cLen);
memcpy(m_pData,pT,sizeof(T)*(m_cLen + 1));
}
}
ZwTString(const T *pT,int nLen)
{
assert(pT != NULL);
if ((m_cLen = nLen) < MAX_PATH)
{
Zwstrcpy(m_data,pT);
m_pData = m_data;
m_pData[nLen] = '\0';
m_mLen = MAX_PATH;
}
else
{
Resize(m_cLen);
memcpy(m_pData,pT,sizeof(T)*(nLen));
m_pData[nLen] = '\0';
}
}
ZwTString& Append(const T *pT)
{
int len = Zwstrlen(pT);
Resize(m_cLen + len);
memcpy(m_pData + m_cLen, pT,sizeof(T)*(len + 1));
m_cLen += len;
return(*this);
}
ZwTString& Append(const ZwTString& strSrc)
{
Resize(m_cLen + strSrc.m_cLen);
memcpy(m_pData + m_cLen, strSrc.m_pData,sizeof(T)*(strSrc.m_cLen + 1));
m_cLen += strSrc.m_cLen;
return(*this);
}
ZwTString& operator=(const ZwTString& strSrc)
{
if(strSrc.m_pData != m_data)
{
Resize(strSrc.m_cLen);
memcpy(m_pData,strSrc.m_pData,sizeof(T)*(strSrc.m_cLen + 1));
m_cLen = strSrc.m_cLen;
}
return( *this );
}
ZwTString& operator=(const T *pT)
{
int len = Zwstrlen(pT);
Resize(len);
memcpy(m_pData, pT,sizeof(T)*(len + 1))
m_cLen = len;
return( *this );
}
ZwTString& operator+=(const ZwTString& strSrc )
{
return Append(strSrc);
}
ZwTString& operator+=(const T ch)
{
Resize(m_cLen +1);
m_pData[m_cLen] = ch;
m_pData[m_cLen +1] = 0;
m_cLen++;
return( *this );
}
ZwTString& operator+=(const T *pT)
{
return Append(pT);
}
T& operator[](int iChar ) const
{
assert((iChar >= 0) && (iChar <= GetLength()));
return( *(&m_pData[iChar]) );
}
void Empty()
{
m_pData[0] = '\0';
m_cLen = 0;
}
T GetAt( int iChar ) const
{
assert((iChar >= 0) && (iChar <= GetLength()));
return( m_pData[iChar] );
}
void SetAt( _In_ int iChar, T ch )
{
assert((iChar >= 0) && (iChar <= GetLength()));
m_pData[iChar] = ch;
}
T* GetBuffer() const
{
return m_pData;
}
T* GetString() const
{
return( m_pData );
}
bool IsEmpty() const
{
return(GetLength() == 0 );
}
friend ZwTString operator+(
const ZwTString& str1,
const ZwTString& str2)
{
ZwTString s;
Concatenate( s, str1.GetBuffer(), str1.GetLength(), str2.GetBuffer(), str2.GetLength() );
return( s );
}
friend ZwTString operator+(
_In_ const ZwTString& str1,
_In_ T* psz2 )
{
ZwTString s;
Concatenate( s, str1.GetBuffer(), str1.GetLength(), psz2, Zwstrlen(psz2));
return( s );
}
friend ZwTString operator+(
_In_ T* psz1,
_In_ const ZwTString& str2 )
{
ZwTString s;
Concatenate( s, psz1, Zwstrlen( psz1 ), str2.GetBuffer(), str2.GetLength() );
return( s );
}
int Compare( _In_opt_z_ T* psz ) const
{
assert(psz != NULL);
return (StringCompare(GetString(), psz ) );
}
int CompareNoCase( _In_opt_z_ T* psz ) const
{
assert(psz != NULL);
return( StringCompareIgnore( GetString(), psz ) );
}
int Collate( _In_opt_z_ T* psz ) const throw()
{
assert(psz != NULL);
return( StringCollate( GetString(), psz ) );
}
int CollateNoCase( _In_opt_z_ T* psz ) const throw()
{
assert(psz != NULL);
return( StringCollateIgnore( GetString(), psz ) );
}
int Delete( _In_ int iIndex, _In_ int nCount = 1 )
{
if( iIndex < 0 )
iIndex = 0;
if( nCount < 0 )
nCount = 0;
int nLength = GetLength();
if(iIndex + nCount > nLength )
{
nCount = nLength-iIndex;
}
if( nCount > 0 )
{
m_cLen = nLength-nCount;
int nXCHARsToCopy = nLength-(iIndex+nCount)+1;
memmove(m_pData + iIndex, m_pData+iIndex+nCount, nXCHARsToCopy*sizeof( T ) );
}
return( GetLength());
}
int Insert( _In_ int iIndex, _In_ T ch )
{
if( iIndex < 0 )
iIndex = 0;
if( iIndex > GetLength() )
{
iIndex = GetLength();
}
m_cLen = GetLength()+1;
Resize(m_cLen);
memmove(m_pData + iIndex +1, m_pData+iIndex, (m_cLen-iIndex)*sizeof(T));
m_pData[iIndex] = ch;
return m_cLen ;
}
int Insert( _In_ int iIndex, _In_ T* psz )
{
if( iIndex < 0 )
iIndex = 0;
if( iIndex > GetLength() )
{
iIndex = GetLength();
}
assert(psz != NULL);
int nInsertLength = Zwstrlen(psz);
if( nInsertLength > 0 )
{
m_cLen += nInsertLength;
Resize(m_cLen);
memmove(m_pData + iIndex +nInsertLength, m_pData+iIndex, (m_cLen-iIndex-nInsertLength+1)*sizeof( T ));
memcpy(m_pData + iIndex,psz,nInsertLength*sizeof( T ));
}
return m_cLen;
}
int Replace( _In_ T chOld, _In_ T chNew )
{
int nCount = 0;
if( chOld != chNew )
{
bool bCopied = false;
int nLength = GetLength();
int iChar = 0;
while( iChar < nLength )
{
if(m_pData[iChar] == chOld )
{
m_pData[iChar] = chNew;
nCount++;
}
iChar = int(CharNext(pszBuffer+iChar)-m_pData );
}
}
return( nCount );
}
int Replace( _In_ T* pszOld, _In_ T* pszNew )
{
int nSourceLen = Zwstrlen( pszOld );
if( nSourceLen == 0 )
return( 0 );
int nReplacementLen = Zwstrlen( pszNew );
int nCount = 0;
{
T* pszStart = GetString();
T* pszEnd = pszStart+GetLength();
while( pszStart < pszEnd )
{
T* pszTarget;
while( (pszTarget = StringFindString( pszStart, pszOld ) ) != NULL)
{
nCount++;
pszStart = pszTarget+nSourceLen;
}
pszStart += Zwstrlen( pszStart )+1;
}
}
// if any changes were made, make them
if( nCount > 0 )
{
// if the buffer is too small, just
// allocate a new buffer (slow but sure)
int nOldLength = GetLength();
int nNewLength = nOldLength+(nReplacementLen-nSourceLen)*nCount;
T* pszBuffer = GetBuffer();
T* pszStart = pszBuffer;
T* pszEnd = pszStart+nOldLength;
// loop again to actually do the work
while( pszStart < pszEnd )
{
T* pszTarget;
while( (pszTarget = StringFindString(pszStart, pszOld)) != NULL )
{
int nBalance = nOldLength-int(pszTarget-pszBuffer+nSourceLen);
m_cLen += (nReplacementLen-nSourceLen);
Resize(m_cLen);
memmove_s( pszTarget+nReplacementLen, nBalance*sizeof( T ),
pszTarget+nSourceLen, nBalance*sizeof( T ) );
memcpy_s( pszTarget, nReplacementLen*sizeof( T ),
pszNew, nReplacementLen*sizeof( T ) );
pszStart = pszTarget+nReplacementLen;
pszTarget[nReplacementLen+nBalance] = 0;
}
pszStart +=Zwstrlen( pszStart )+1;
}
assert( pszBuffer[nNewLength] == 0 );
}
return( nCount );
}
int Remove( _In_ T chRemove )
{
int nLength = GetLength();
T* pszBuffer = GetBuffer( nLength );
T* pszSource = pszBuffer;
T* pszDest = pszBuffer;
T* pszEnd = pszBuffer+nLength;
while( pszSource < pszEnd )
{
T* pszNewSource = CharNext( pszSource );
if( *pszSource != chRemove )
{
// Copy the source to the destination. Remember to copy all bytes of an MBCS character
// Copy the source to the destination. Remember to copy all bytes of an MBCS character
size_t NewSourceGap = (pszNewSource-pszSource);
T* pszNewDest = pszDest + NewSourceGap;
size_t i = 0;
for (i = 0; pszDest != pszNewDest && i < NewSourceGap; i++)
{
*pszDest = *pszSource;
pszSource++;
pszDest++;
}
}
pszSource = pszNewSource;
}
*pszDest = 0;
m_cLen = int( pszSource-pszDest );
return( m_cLen);
}
int Find( _In_ T ch, _In_ int iStart = 0 ) const
{
assert( iStart >= 0 );
int nLength = GetLength();
if( iStart < 0 || iStart >= nLength)
{
return( -1 );
}
T* psz = StringFindChar( GetString()+iStart, ch );
return( (psz == NULL) ? -1 : int( psz-GetString() ) );
}
int Find( _In_ T* pszSub, _In_ int iStart = 0 ) const
{
assert( iStart >= 0 );
assert(pszSub != NULL);
if(pszSub == NULL)
{
return( -1 );
}
// nLength is in XCHARs
int nLength = GetLength();
if( iStart < 0 || iStart > nLength )
{
return( -1 );
}
T* psz = StringFindString( GetString()+iStart, pszSub );
return( (psz == NULL) ? -1 : int( psz-GetString()));
}
int FindOneOf( _In_ T* pszCharSet ) const throw()
{
assert(pszCharSet != NULL);
T* psz = StringScanSet( GetString(), pszCharSet);
return( (psz == NULL) ? -1 : int( psz-GetString()));
}
// Find the last occurrence of character 'ch'
int ReverseFind( _In_ T ch )
{
// find last single character
const T* psz = StringFindCharRev( (LPCTSTR)GetString(), ch );
// return -1 if not found, distance from beginning otherwise
return( (psz == NULL) ? -1 : int( psz-GetString() ) );
}
// Convert the string to uppercase
ZwTString& ToUpper()
{
int nLength = GetLength();
T* pszBuffer = GetBuffer( nLength );
StringUppercase( pszBuffer, nLength+1 );
return( *this );
}
// Convert the string to lowercase
ZwTString& ToLower()
{
int nLength = GetLength();
T* pszBuffer = GetBuffer( nLength );
StringLowercase( pszBuffer, nLength+1 );
return( *this );
}
// Reverse the string
ZwTString& Reverse()
{
T* pszBuffer = GetBuffer();
StringReverse( pszBuffer );
return( *this );
}
ZwTString& TrimRight()
{
T* psz = GetString();
T* pszLast = NULL;
while( *psz != 0 )
{
if(IsSpace( *psz ) )
{
if( pszLast == NULL )
pszLast = psz;
}
else
{
pszLast = NULL;
}
psz = CharNext( psz );
}
if( pszLast != NULL )
{
m_cLen = int( pszLast-GetString() );
*pszLast = '\0';
}
return( *this );
}
ZwTString& TrimLeft()
{
// find first non-space character
T* psz = GetString();
while(IsSpace( *psz ) )
{
psz = CharNext( psz );
}
if( psz != GetString() )
{
int nDel = int( psz-GetString() );
T* pszBuffer = GetBuffer();
psz = pszBuffer+nDel;
m_cLen = GetLength()-nDel;
memmove_s(pszBuffer, (m_cLen+1)*sizeof(T),
psz, (m_cLen+1)*sizeof(T));
}
return( *this );
}
// Remove all leading and trailing whitespace
ZwTString& Trim()
{
return( TrimRight().TrimLeft());
}
ZwTString& Trim( _In_ T chTarget )
{
return( TrimRight( chTarget ).TrimLeft( chTarget ) );
}
ZwTString& Trim( _In_ T* pszTargets )
{
return( TrimRight( pszTargets ).TrimLeft( pszTargets ) );
}
ZwTString& TrimRight( _In_ T chTarget )
{
// find beginning of trailing matches
// by starting at beginning (DBCS aware)
T* psz = GetString();
T* pszLast = NULL;
while( *psz != 0 )
{
if( *psz == chTarget )
{
if( pszLast == NULL )
{
pszLast = psz;
}
}
else
{
pszLast = NULL;
}
psz = CharNext( psz );
}
if( pszLast != NULL )
{
m_cLen = int( pszLast-GetString() );
*pszLast = '\0';
}
return( *this );
}
ZwTString& TrimRight( _In_ T* pszTargets )
{
// if we're not trimming anything, we're not doing any work
if( (pszTargets == NULL) || (*pszTargets == 0) )
{
return( *this );
}
// find beginning of trailing matches
// by starting at beginning (DBCS aware)
T* psz = GetString();
T* pszLast = NULL;
while( *psz != 0 )
{
if(StringFindChar( pszTargets, *psz ) != NULL )
{
if( pszLast == NULL )
{
pszLast = psz;
}
}
else
{
pszLast = NULL;
}
psz = CharNext( psz );
}
if( pszLast != NULL )
{
// truncate at left-most matching character
m_cLen = int( pszLast-GetString() );
*pszLast = '\0';
}
return( *this );
}
// Remove all leading occurrences of character 'chTarget'
ZwTString& TrimLeft( _In_ T chTarget )
{
// find first non-matching character
T* psz = GetString();
while( chTarget == *psz )
{
psz = CharNext( psz );
}
if( psz != GetString() )
{
int nDel = int( psz-GetString() );
T* pszBuffer = GetBuffer();
psz = pszBuffer+nDel;
m_cLen = GetLength()-nDel;
memmove_s(pszBuffer, (m_cLen+1)*sizeof(T),
psz, (m_cLen+1)*sizeof(T));
}
return( *this );
}
// Remove all leading occurrences of any of the characters in string 'pszTargets'
ZwTString& TrimLeft( _In_ T* pszTargets )
{
if( (pszTargets == NULL) || (*pszTargets == 0) )
{
return( *this );
}
T* psz = GetString();
while( (*psz != 0) && (StringFindChar( pszTargets, *psz ) != NULL) )
{
psz = CharNext( psz );
}
if( psz != GetString() )
{
int nDel = int( psz-GetString() );
T* pszBuffer = GetBuffer();
psz = pszBuffer+nDel;
m_cLen = GetLength()-nDel;
memmove_s(pszBuffer, (m_cLen+1)*sizeof(T),
psz, (m_cLen+1)*sizeof(T));
}
return( *this );
}
ZwTString Mid( _In_ int iFirst ) const
{
return( Mid( iFirst, GetLength()-iFirst ) );
}
ZwTString Mid( _In_ int iFirst, _In_ int nCount ) const
{
if (iFirst < 0)
iFirst = 0;
if (nCount < 0)
nCount = 0;
if( iFirst + nCount > GetLength())
{
nCount = GetLength()-iFirst;
}
if( iFirst > GetLength() )
{
nCount = 0;
}
assert((nCount == 0) || ((iFirst+nCount) <= GetLength()));
if( (iFirst == 0) && ((iFirst+nCount) == GetLength()) )
{
return( *this );
}
return( ZwTString(GetString()+iFirst),nCount);
}
ZwTString Right( _In_ int nCount)
{
// nCount is in XCHARs
if (nCount < 0)
nCount = 0;
int nLength = GetLength();
if( nCount >= nLength )
{
return( *this );
}
return( ZwTString( GetString()+nLength-nCount));
}
ZwTString Left( _In_ int nCount ) const
{
// nCount is in XCHARs
if (nCount < 0)
nCount = 0;
int nLength = GetLength();
if( nCount >= nLength )
{
return( *this );
}
return(ZwTString( GetString(), nCount));
}
BOOL GetEnvironmentVariable( _In_ T* pszVar )
{
ULONG nLength = GetEnvironmentVariable( pszVar, NULL, 0 );
BOOL bRetVal = FALSE;
if( nLength == 0 )
{
Empty();
}
else
{
T* pszBuffer = GetBuffer( nLength );
GetEnvironmentVariable( pszVar, pszBuffer, nLength );
bRetVal = TRUE;
}
return( bRetVal );
}
friend bool operator==( _In_ const ZwTString& str1, _In_ const ZwTString& str2 )
{
return( str1.Compare( str2 ) == 0 );
}
friend bool operator==(
_In_ const ZwTString& str1, _In_ T* psz2 )
{
return( str1.Compare( psz2 ) == 0 );
}
friend bool operator==(
_In_ T* psz1, _In_ const ZwTString& str2 )
{
return( str2.Compare( psz1 ) == 0 );
}
friend bool operator!=(
_In_ const ZwTString& str1, _In_ const ZwTString& str2 )
{
return( str1.Compare( str2 ) != 0 );
}
friend bool operator!=(
_In_ const ZwTString& str1, _In_ T* psz2 )
{
return( str1.Compare( psz2 ) != 0 );
}
friend bool operator!=(
_In_ T* psz1, _In_ const ZwTString& str2 )
{
return( str2.Compare( psz1 ) != 0 );
}
friend bool operator==( _In_ T ch1, _In_ const ZwTString& str2 ) throw()
{
return( (str2.GetLength() == 1) && (str2[0] == ch1) );
}
friend bool operator==( _In_ const ZwTString& str1, _In_ T ch2 )
{
return( (str1.GetLength() == 1) && (str1[0] == ch2) );
}
friend bool operator!=( _In_ T ch1, _In_ const ZwTString& str2 )
{
return( (str2.GetLength() != 1) || (str2[0] != ch1) );
}
friend bool operator!=( _In_ const ZwTString& str1, _In_ T ch2 )
{
return( (str1.GetLength() != 1) || (str1[0] != ch2) );
}
void AppendFormatV( _In_ _Printf_format_string_ T* pszFormat, va_list args )
{
int nCurrentLength = m_cLen;
m_cLen += GetFormattedLength( pszFormat, args );
Resize(m_cLen);
Format(m_pData+nCurrentLength,
m_cLen - nCurrentLength+1, pszFormat, args );
}
void FormatV( _In_ _Printf_format_string_ T* pszFormat, va_list args )
{
assert(pszFormat != NULL);
m_cLen = GetFormattedLength( pszFormat, args );
Resize( m_cLen );
ZwTraitsBase::Format(m_pData, m_cLen+1, pszFormat, args);
}
void __cdecl Format( _In_ _Printf_format_string_ T* pszFormat, ... )
{
va_list argList;
va_start( argList, pszFormat );
FormatV( pszFormat, argList );
va_end( argList );
}
void __cdecl AppendFormat( _In_ _Printf_format_string_ T* pszFormat, ... )
{
va_list argList;
va_start( argList, pszFormat );
AppendFormatV( pszFormat, argList );
va_end( argList );
}
protected:
static void __cdecl Concatenate(ZwTString& strResult, T* psz1, int nLen1, T* psz2, int nLen2 )
{
strResult.Resize(nLen1 + nLen2);
memcpy(strResult.m_pData,psz1,sizeof(T)*(nLen1));
memcpy(strResult.m_pData + nLen1,psz2,sizeof(T)*(nLen2 + 1));
strResult.m_cLen = nLen1 + nLen2;
}
public:
T m_data[MAX_PATH];
T *m_pData;
int m_mLen;
int m_cLen;
};
class ZwStringA :
public ZwTString<char>
{
public:
ZwStringA():ZwTString(){}
~ZwStringA(){}
ZwStringA(const char *pT):ZwTString(pT){}
ZwStringA(const wchar_t *pT):ZwTString()
{
int len = Zwstrlen(pT);
Resize(len);
Zwwtoa(m_pData,pT,len+1);
m_cLen = len;
}
ZwStringA(const ZwStringA& strSrc ):ZwTString(strSrc){}
ZwStringA(const ZwTString& strSrc ):ZwTString(strSrc){}
};
class ZwStringW :
public ZwTString<wchar_t>
{
public:
ZwStringW():ZwTString(){}
~ZwStringW(){}
ZwStringW(const wchar_t *pT):ZwTString(pT){}
ZwStringW(const char *pT):ZwTString()
{
int len = Zwstrlen(pT);
Resize(len);
Zwatow(m_pData,pT,len+1);
m_cLen = len;
}
ZwStringW(const ZwStringW& strSrc ):ZwTString(strSrc){}
ZwStringW(const ZwTString& strSrc ):ZwTString(strSrc){}
};
#ifdef _UNICODE
typedef ZwStringW ZwString;
#else
typedef ZwStringA ZwString;
#endif
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!