首页
社区
课程
招聘
[原创]发一个字符串类ZwString,替代CString
发表于: 2014-2-26 09:32 5519

[原创]发一个字符串类ZwString,替代CString

2014-2-26 09:32
5519
先说明下,该字符串类大部分源码是在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

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 18
活跃值: (24)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
顶一个,支持分享,呵呵
2014-2-26 09:50
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
口头支持,还是不建议重复造轮子,就算造了,也应该用到本来没有字符串类得地方,比如能在驱动里用得很爽。
2014-2-26 14:04
0
雪    币: 29
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
怎么高亮代码啊,这么长一定得复制下来手动高亮么。。
2014-2-26 17:54
0
雪    币: 1042
活跃值: (495)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
NICE MARK.
2014-2-26 18:52
0
游客
登录 | 注册 方可回帖
返回
//