From 6ce4b99cb3dc5522ecf8fa337de661055ef5708c Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 25 Aug 2013 12:08:14 +0000 Subject: MString removed from Jabber & IRC git-svn-id: http://svn.miranda-ng.org/main/trunk@5824 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/JabberG/src/MString.h | 2291 --------------------------------------- 1 file changed, 2291 deletions(-) delete mode 100644 protocols/JabberG/src/MString.h (limited to 'protocols/JabberG/src/MString.h') diff --git a/protocols/JabberG/src/MString.h b/protocols/JabberG/src/MString.h deleted file mode 100644 index b524296373..0000000000 --- a/protocols/JabberG/src/MString.h +++ /dev/null @@ -1,2291 +0,0 @@ -#pragma once - -#include -#include -#include - -#ifdef __MINGW32__ -#include - -__inline size_t strnlen(const char *string, size_t maxlen) -{ - const char *end = (const char *)memchr ((const void *)string, '\0', maxlen); - return end ? (size_t) (end - string) : maxlen; -} -__inline size_t wcsnlen(const wchar_t *string, size_t maxlen) -{ - const wchar_t *end = wmemchr (string, L'\0', maxlen); - return end ? (size_t) (end - string) : maxlen; -} - -/* FIXME: This may be wrong assumption about _AtlGetConversionACP */ -#define _AtlGetConversionACP() CP_THREAD_ACP -/* FIXME: This is unsafe */ -#define memcpy_s(dest,size,src,count) memcpy(dest,src,count) -/* FIXME: This is quite silly implementation of _mbsstr */ -#define _mbsstr(str,search) strstr((const char *)str,(const char *)search) -#define __max(x,y) (((x)<(y))?(y):(x)) -#endif /* __MINGW32__ */ - -struct CMStringData -{ - int nDataLength; // Length of currently used data in XCHARs (not including terminating null) - int nAllocLength; // Length of allocated data in XCHARs (not including terminating null) - long nRefs; // Reference count: negative == locked - // XCHAR data[nAllocLength+1] // A CStringData is always followed in memory by the actual array of character data - void* data(); - void AddRef(); - bool IsLocked() const; - bool IsShared() const; - void Lock(); - void Release(); - void Unlock(); -}; - -class CNilMStringData : public CMStringData -{ -public: - CNilMStringData(); - -public: - wchar_t achNil[2]; -}; - -template< typename BaseType = char > -class ChTraitsBase -{ -public: - typedef char XCHAR; - typedef LPSTR PXSTR; - typedef LPCSTR PCXSTR; - typedef wchar_t YCHAR; - typedef LPWSTR PYSTR; - typedef LPCWSTR PCYSTR; -}; - -template<> -class ChTraitsBase< wchar_t > -{ -public: - typedef wchar_t XCHAR; - typedef LPWSTR PXSTR; - typedef LPCWSTR PCXSTR; - typedef char YCHAR; - typedef LPSTR PYSTR; - typedef LPCSTR PCYSTR; -}; - -class CMBaseString -{ -public: - static CMStringData* Allocate(int nChars, int nCharSize); - static void Free(CMStringData* pData); - static CMStringData* Realloc(CMStringData* pData, int nChars, int nCharSize); - -protected: - static CMStringData* GetNilString(); - static CNilMStringData m_nil; -}; - -template< typename BaseType > -class CMSimpleStringT : public CMBaseString -{ -public: - typedef typename ChTraitsBase< BaseType >::XCHAR XCHAR; - typedef typename ChTraitsBase< BaseType >::PXSTR PXSTR; - typedef typename ChTraitsBase< BaseType >::PCXSTR PCXSTR; - typedef typename ChTraitsBase< BaseType >::YCHAR YCHAR; - typedef typename ChTraitsBase< BaseType >::PYSTR PYSTR; - typedef typename ChTraitsBase< BaseType >::PCYSTR PCYSTR; - -public: - explicit CMSimpleStringT() - { - CMStringData* pData = GetNilString(); - Attach(pData); - } - - CMSimpleStringT(const CMSimpleStringT& strSrc) - { - CMStringData* pSrcData = strSrc.GetData(); - CMStringData* pNewData = CloneData(pSrcData); - Attach(pNewData); - } - - CMSimpleStringT(PCXSTR pszSrc) - { - int nLength = StringLength(pszSrc); - CMStringData* pData = Allocate(nLength, sizeof(XCHAR)); - if (pData != NULL) - { - Attach(pData); - SetLength(nLength); - CopyChars(m_pszData, nLength, pszSrc, nLength); - } - } - CMSimpleStringT(const XCHAR* pchSrc, int nLength) - { - CMStringData* pData = Allocate(nLength, sizeof(XCHAR)); - if (pData != NULL) - { - Attach(pData); - SetLength(nLength); - CopyChars(m_pszData, nLength, pchSrc, nLength); - } - } - ~CMSimpleStringT() - { - CMStringData* pData = GetData(); - pData->Release(); - } - - operator CMSimpleStringT&() - { - return *(CMSimpleStringT*)this; - } - - CMSimpleStringT& operator=(const CMSimpleStringT& strSrc) - { - CMStringData* pSrcData = strSrc.GetData(); - CMStringData* pOldData = GetData(); - if (pSrcData != pOldData) - { - if (pOldData->IsLocked()) - SetString(strSrc.GetString(), strSrc.GetLength()); - else - { - CMStringData* pNewData = CloneData(pSrcData); - pOldData->Release(); - Attach(pNewData); - } - } - - return *this; - } - - CMSimpleStringT& operator=(PCXSTR pszSrc) - { - SetString(pszSrc); - return *this; - } - - CMSimpleStringT& operator+=(const CMSimpleStringT& strSrc) - { - Append(strSrc); - - return *this; - } - - CMSimpleStringT& operator+=(PCXSTR pszSrc) - { - Append(pszSrc); - - return *this; - } - CMSimpleStringT& operator+=(char ch) - { - AppendChar(XCHAR(ch)); - - return *this; - } - CMSimpleStringT& operator+=(unsigned char ch) - { - AppendChar(XCHAR(ch)); - - return *this; - } - CMSimpleStringT& operator+=(wchar_t ch) - { - AppendChar(XCHAR(ch)); - - return *this; - } - - XCHAR operator[](int iChar) const - { - return m_pszData[iChar]; - } - - operator PCXSTR() const - { - return m_pszData; - } - - PCXSTR c_str() const - { - return m_pszData; - } - - void Append(PCXSTR pszSrc) - { - Append(pszSrc, StringLength(pszSrc)); - } - void Append(PCXSTR pszSrc, int nLength) - { - // See comment in SetString() about why we do this - UINT_PTR nOffset = pszSrc - GetString(); - - UINT nOldLength = GetLength(); - if (nOldLength < 0) - { - // protects from underflow - nOldLength = 0; - } - - //Make sure we don't read pass end of the terminating NULL - int nSrcLength = StringLength(pszSrc); - nLength = nLength > nSrcLength ? nSrcLength: nLength; - - int nNewLength = nOldLength+nLength; - PXSTR pszBuffer = GetBuffer(nNewLength); - if (nOffset <= nOldLength) - { - pszSrc = pszBuffer+nOffset; - // No need to call CopyCharsOverlapped, since the destination is - // beyond the end of the original buffer - } - CopyChars(pszBuffer+nOldLength, nLength, pszSrc, nLength); - ReleaseBufferSetLength(nNewLength); - } - void AppendChar(XCHAR ch) - { - UINT nOldLength = GetLength(); - int nNewLength = nOldLength+1; - PXSTR pszBuffer = GetBuffer(nNewLength); - pszBuffer[nOldLength] = ch; - ReleaseBufferSetLength(nNewLength); - } - void Append(const CMSimpleStringT& strSrc) - { - Append(strSrc.GetString(), strSrc.GetLength()); - } - void Empty() - { - CMStringData* pOldData = GetData(); - if (pOldData->nDataLength == 0) - return; - - if (pOldData->IsLocked()) - { - // Don't reallocate a locked buffer that's shrinking - SetLength(0); - } - else - { - pOldData->Release(); - CMStringData* pNewData = GetNilString(); - Attach(pNewData); - } - } - void FreeExtra() - { - CMStringData* pOldData = GetData(); - int nLength = pOldData->nDataLength; - if (pOldData->nAllocLength == nLength) - return; - - if ( !pOldData->IsLocked()) // Don't reallocate a locked buffer that's shrinking - { - CMStringData* pNewData = Allocate(nLength, sizeof(XCHAR)); - if (pNewData == NULL) { - SetLength(nLength); - return; - } - - CopyChars(PXSTR(pNewData->data()), nLength, PCXSTR(pOldData->data()), nLength); - - pOldData->Release(); - Attach(pNewData); - SetLength(nLength); - } - } - - int GetAllocLength() const - { - return GetData()->nAllocLength; - } - XCHAR GetAt(int iChar) const - { - return m_pszData[iChar]; - } - PXSTR GetBuffer() - { - CMStringData* pData = GetData(); - if (pData->IsShared()) - Fork(pData->nDataLength); - - return m_pszData; - } - PXSTR GetBuffer(int nMinBufferLength) - { - return PrepareWrite(nMinBufferLength); - } - PXSTR GetBufferSetLength(int nLength) - { - PXSTR pszBuffer = GetBuffer(nLength); - SetLength(nLength); - - return pszBuffer; - } - int GetLength() const - { - return GetData()->nDataLength; - } - - PCXSTR GetString() const - { - return m_pszData; - } - bool IsEmpty() const - { - return GetLength() == 0; - } - PXSTR LockBuffer() - { - CMStringData* pData = GetData(); - if (pData->IsShared()) - { - Fork(pData->nDataLength); - pData = GetData(); // Do it again, because the fork might have changed it - } - pData->Lock(); - - return m_pszData; - } - void UnlockBuffer() - { - CMStringData* pData = GetData(); - pData->Unlock(); - } - void Preallocate(int nLength) - { - PrepareWrite(nLength); - } - void ReleaseBuffer(int nNewLength = -1) - { - if (nNewLength == -1) - { - int nAlloc = GetData()->nAllocLength; - nNewLength = StringLengthN(m_pszData, nAlloc); - } - SetLength(nNewLength); - } - void ReleaseBufferSetLength(int nNewLength) - { - SetLength(nNewLength); - } - void Truncate(int nNewLength) - { - GetBuffer(nNewLength); - ReleaseBufferSetLength(nNewLength); - } - void SetAt(int iChar, XCHAR ch) - { - int nLength = GetLength(); - PXSTR pszBuffer = GetBuffer(); - pszBuffer[iChar] = ch; - ReleaseBufferSetLength(nLength); - - } - void SetString(PCXSTR pszSrc) - { - SetString(pszSrc, StringLength(pszSrc)); - } - void SetString(PCXSTR pszSrc, int nLength) - { - if (nLength == 0) - { - Empty(); - } - else - { - - UINT nOldLength = GetLength(); - UINT_PTR nOffset = pszSrc - GetString(); - - PXSTR pszBuffer = GetBuffer(nLength); - if (nOffset <= nOldLength) - { - CopyCharsOverlapped(pszBuffer, GetAllocLength(), - pszBuffer+nOffset, nLength); - } - else - { - CopyChars(pszBuffer, GetAllocLength(), pszSrc, nLength); - } - ReleaseBufferSetLength(nLength); - } - } -public: - friend CMSimpleStringT __stdcall operator+(const CMSimpleStringT& str1, const CMSimpleStringT& str2) - { - CMSimpleStringT s; - - Concatenate(s, str1, str1.GetLength(), str2, str2.GetLength()); - - return s; - } - - friend CMSimpleStringT __stdcall operator+(const CMSimpleStringT& str1, PCXSTR psz2) - { - CMSimpleStringT s; - - Concatenate(s, str1, str1.GetLength(), psz2, StringLength(psz2)); - - return s; - } - - friend CMSimpleStringT __stdcall operator+(PCXSTR psz1, const CMSimpleStringT& str2) - { - CMSimpleStringT s; - - Concatenate(s, psz1, StringLength(psz1), str2, str2.GetLength()); - - return s; - } - - static void __stdcall CopyChars(XCHAR* pchDest, const XCHAR* pchSrc, int nChars) - { -#pragma warning (push) -#pragma warning(disable : 4996) - memcpy(pchDest, pchSrc, nChars * sizeof(XCHAR)); -#pragma warning (pop) - } - static void __stdcall CopyChars(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars) - { - #if _MSC_VER >= 1400 - memcpy_s(pchDest, nDestLen * sizeof(XCHAR), pchSrc, nChars * sizeof(XCHAR)); - #else - memcpy(pchDest, pchSrc, nDestLen * sizeof(XCHAR)); - #endif - } - - static void __stdcall CopyCharsOverlapped(XCHAR* pchDest, const XCHAR* pchSrc, int nChars) - { -#pragma warning (push) -#pragma warning(disable : 4996) - memmove(pchDest, pchSrc, nChars * sizeof(XCHAR)); -#pragma warning (pop) - } - static void __stdcall CopyCharsOverlapped(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars) - { - #if _MSC_VER >= 1400 - memmove_s(pchDest, nDestLen * sizeof(XCHAR), pchSrc, nChars * sizeof(XCHAR)); - #else - memmove(pchDest, pchSrc, nDestLen * sizeof(XCHAR)); - #endif - } - static int __stdcall StringLength(const char* psz) - { - if (psz == NULL) - { - return(0); - } - return (int(strlen(psz))); - } - static int __stdcall StringLength(const wchar_t* psz) - { - if (psz == NULL) - return 0; - - return int(wcslen(psz)); - } - static int __stdcall StringLengthN(const char* psz, size_t sizeInXChar) - { - if (psz == NULL) - return 0; - - return int(strnlen(psz, sizeInXChar)); - } - static int __stdcall StringLengthN(const wchar_t* psz, size_t sizeInXChar) - { - if (psz == NULL) - return 0; - - return int(wcsnlen(psz, sizeInXChar)); - } -protected: - static void __stdcall Concatenate(CMSimpleStringT& strResult, PCXSTR psz1, int nLength1, PCXSTR psz2, int nLength2) - { - int nNewLength = nLength1+nLength2; - PXSTR pszBuffer = strResult.GetBuffer(nNewLength); - CopyChars(pszBuffer, nLength1, psz1, nLength1); - CopyChars(pszBuffer + nLength1, nLength2, psz2, nLength2); - strResult.ReleaseBufferSetLength(nNewLength); - } - // Implementation -private: - void Attach(CMStringData* pData) - { - m_pszData = static_cast(pData->data()); - } - void Fork(int nLength) - { - CMStringData* pOldData = GetData(); - int nOldLength = pOldData->nDataLength; - CMStringData* pNewData = Allocate(nLength, sizeof(XCHAR)); - if (pNewData != NULL) - { - int nCharsToCopy = ((nOldLength < nLength) ? nOldLength : nLength)+1; // Copy '\0' - CopyChars(PXSTR(pNewData->data()), nCharsToCopy, PCXSTR(pOldData->data()), nCharsToCopy); - pNewData->nDataLength = nOldLength; - pOldData->Release(); - Attach(pNewData); - } - } - CMStringData* GetData() const - { - return (reinterpret_cast(m_pszData) - 1); - } - PXSTR PrepareWrite(int nLength) - { - CMStringData* pOldData = GetData(); - int nShared = 1 - pOldData->nRefs; // nShared < 0 means true, >= 0 means false - int nTooShort = pOldData->nAllocLength-nLength; // nTooShort < 0 means true, >= 0 means false - if ((nShared | nTooShort) < 0) // If either sign bit is set (i.e. either is less than zero), we need to copy data - PrepareWrite2(nLength); - - return m_pszData; - } - void PrepareWrite2(int nLength) - { - CMStringData* pOldData = GetData(); - if (pOldData->nDataLength > nLength) - nLength = pOldData->nDataLength; - - if (pOldData->IsShared()) - { - Fork(nLength); - } - else if (pOldData->nAllocLength < nLength) - { - // Grow exponentially, until we hit 1K. - int nNewLength = pOldData->nAllocLength; - if (nNewLength > 1024) - nNewLength += 1024; - else - nNewLength *= 2; - - if (nNewLength < nLength) - nNewLength = nLength; - - Reallocate(nNewLength); - } - } - void Reallocate(int nLength) - { - CMStringData* pOldData = GetData(); - if (pOldData->nAllocLength >= nLength || nLength <= 0) - return; - - CMStringData* pNewData = Realloc(pOldData, nLength, sizeof(XCHAR)); - if (pNewData != NULL) - Attach(pNewData); - } - - void SetLength(int nLength) - { - GetData()->nDataLength = nLength; - m_pszData[nLength] = 0; - } - - static CMStringData* __stdcall CloneData(CMStringData* pData) - { - CMStringData* pNewData = NULL; - - if ( !pData->IsLocked()) { - pNewData = pData; - pNewData->AddRef(); - } - - return pNewData; - } - -public : - // typedef CStrBufT CStrBuf; -private: - PXSTR m_pszData; -}; - - -template< typename _CharType = char > -class ChTraitsCRT : public ChTraitsBase< _CharType > -{ -public: - static char* __stdcall CharNext(const char* p) - { - return reinterpret_cast< char* >(_mbsinc(reinterpret_cast< const unsigned char* >(p))); - } - - static int __stdcall IsDigit(char ch) - { - return _ismbcdigit(ch); - } - - static int __stdcall IsSpace(char ch) - { - return _ismbcspace(ch); - } - - static int __stdcall StringCompare(LPCSTR pszA, LPCSTR pszB) - { - return _mbscmp(reinterpret_cast< const unsigned char* >(pszA), reinterpret_cast< const unsigned char* >(pszB)); - } - - static int __stdcall StringCompareIgnore(LPCSTR pszA, LPCSTR pszB) - { - return _mbsicmp(reinterpret_cast< const unsigned char* >(pszA), reinterpret_cast< const unsigned char* >(pszB)); - } - - static int __stdcall StringCollate(LPCSTR pszA, LPCSTR pszB) - { - return _mbscoll(reinterpret_cast< const unsigned char* >(pszA), reinterpret_cast< const unsigned char* >(pszB)); - } - - static int __stdcall StringCollateIgnore(LPCSTR pszA, LPCSTR pszB) - { - return _mbsicoll(reinterpret_cast< const unsigned char* >(pszA), reinterpret_cast< const unsigned char* >(pszB)); - } - - static LPCSTR __stdcall StringFindString(LPCSTR pszBlock, LPCSTR pszMatch) - { - return reinterpret_cast< LPCSTR >(_mbsstr(reinterpret_cast< const unsigned char* >(pszBlock), - reinterpret_cast< const unsigned char* >(pszMatch))); - } - - static LPSTR __stdcall StringFindString(LPSTR pszBlock, LPCSTR pszMatch) - { - return const_cast< LPSTR >(StringFindString(const_cast< LPCSTR >(pszBlock), pszMatch)); - } - - static LPCSTR __stdcall StringFindChar(LPCSTR pszBlock, char chMatch) - { - return reinterpret_cast< LPCSTR >(_mbschr(reinterpret_cast< const unsigned char* >(pszBlock), (unsigned char)chMatch)); - } - - static LPCSTR __stdcall StringFindCharRev(LPCSTR psz, char ch) - { - return reinterpret_cast< LPCSTR >(_mbsrchr(reinterpret_cast< const unsigned char* >(psz), (unsigned char)ch)); - } - - static LPCSTR __stdcall StringScanSet(LPCSTR pszBlock, LPCSTR pszMatch) - { - return reinterpret_cast< LPCSTR >(_mbspbrk(reinterpret_cast< const unsigned char* >(pszBlock), - reinterpret_cast< const unsigned char* >(pszMatch))); - } - - static int __stdcall StringSpanIncluding(LPCSTR pszBlock, LPCSTR pszSet) - { - return (int)_mbsspn(reinterpret_cast< const unsigned char* >(pszBlock), reinterpret_cast< const unsigned char* >(pszSet)); - } - - static int __stdcall StringSpanExcluding(LPCSTR pszBlock, LPCSTR pszSet) - { - return (int)_mbscspn(reinterpret_cast< const unsigned char* >(pszBlock), reinterpret_cast< const unsigned char* >(pszSet)); - } - - static LPSTR __stdcall StringUppercase(LPSTR psz) - { -#pragma warning (push) -#pragma warning(disable : 4996) - return reinterpret_cast< LPSTR >(_mbsupr(reinterpret_cast< unsigned char* >(psz))); -#pragma warning (pop) - } - - static LPSTR __stdcall StringLowercase(LPSTR psz) - { -#pragma warning (push) -#pragma warning(disable : 4996) - return reinterpret_cast< LPSTR >(_mbslwr(reinterpret_cast< unsigned char* >(psz))); -#pragma warning (pop) - } - - static LPSTR __stdcall StringUppercase(LPSTR psz, size_t size) - { - #if _MSC_VER >= 1400 - _mbsupr_s(reinterpret_cast< unsigned char* >(psz), size); - #else - _mbsupr(reinterpret_cast< unsigned char* >(psz)); - #endif - return psz; - } - - static LPSTR __stdcall StringLowercase(LPSTR psz, size_t size) - { - #if _MSC_VER >= 1400 - _mbslwr_s(reinterpret_cast< unsigned char* >(psz), size); - #else - _mbslwr(reinterpret_cast< unsigned char* >(psz)); - #endif - return psz; - } - - static LPSTR __stdcall StringReverse(LPSTR psz) - { - return reinterpret_cast< LPSTR >(_mbsrev(reinterpret_cast< unsigned char* >(psz))); - } - - static int __stdcall GetFormattedLength(LPCSTR pszFormat, va_list args); - - static int __stdcall Format(LPSTR pszBuffer, size_t nlength, LPCSTR pszFormat, va_list args); - - static int __stdcall GetBaseTypeLength(LPCSTR pszSrc) - { - // Returns required buffer length in XCHARs - return int(strlen(pszSrc)); - } - - static int __stdcall GetBaseTypeLength(LPCSTR pszSrc, int nLength) - { - (void)pszSrc; - // Returns required buffer length in XCHARs - return nLength; - } - - static int __stdcall GetBaseTypeLength(LPCWSTR pszSource) - { - // Returns required buffer length in XCHARs - return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, -1, NULL, 0, NULL, NULL)-1; - } - - static int __stdcall GetBaseTypeLength(LPCWSTR pszSource, int nLength) - { - // Returns required buffer length in XCHARs - return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0, NULL, NULL); - } - - static void __stdcall ConvertToBaseType(LPSTR pszDest, int nDestLength, LPCSTR pszSrc, int nSrcLength = -1) - { - if (nSrcLength == -1) { nSrcLength=1 + GetBaseTypeLength(pszSrc); } - // nLen is in XCHARs - memcpy_s(pszDest, nDestLength*sizeof(char), - pszSrc, nSrcLength*sizeof(char)); - } - - static void __stdcall ConvertToBaseType(LPSTR pszDest, int nDestLength, LPCWSTR pszSrc, int nSrcLength = -1) - { - // nLen is in XCHARs - ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL); - } - - static void ConvertToOem(_CharType* pstrString) - { - BOOL fSuccess=::CharToOemA(pstrString, pstrString); - } - - static void ConvertToAnsi(_CharType* pstrString) - { - BOOL fSuccess=::OemToCharA(pstrString, pstrString); - } - - static void ConvertToOem(_CharType* pstrString, size_t size) - { - if (size>UINT_MAX) - { - return; - } - DWORD dwSize=static_cast(size); - BOOL fSuccess=::CharToOemBuffA(pstrString, pstrString, dwSize); - } - - static void ConvertToAnsi(_CharType* pstrString, size_t size) - { - if (size>UINT_MAX) - return; - - DWORD dwSize=static_cast(size); - BOOL fSuccess=::OemToCharBuffA(pstrString, pstrString, dwSize); - } - - static void __stdcall FloodCharacters(char ch, int nLength, char* pch) - { - // nLength is in XCHARs - memset(pch, ch, nLength); - } - - static BSTR __stdcall AllocSysString(const char* pchData, int nDataLength) - { - int nLen = ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pchData, nDataLength, NULL, NULL); - BSTR bstr = ::SysAllocStringLen(NULL, nLen); - if (bstr != NULL) - ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pchData, nDataLength, bstr, nLen); - - return bstr; - } - - static BOOL __stdcall ReAllocSysString(const char* pchData, BSTR* pbstr, int nDataLength) - { - int nLen = ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pchData, nDataLength, NULL, NULL); - BOOL bSuccess = ::SysReAllocStringLen(pbstr, NULL, nLen); - if (bSuccess) - ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pchData, nDataLength, *pbstr, nLen); - - return bSuccess; - } - - static int __stdcall SafeStringLen(LPCSTR psz) - { - // returns length in bytes - return (psz != NULL) ? int(strlen(psz)) : 0; - } - - static int __stdcall SafeStringLen(LPCWSTR psz) - { - // returns length in wchar_ts - return (psz != NULL) ? int(wcslen(psz)) : 0; - } - - static int __stdcall GetCharLen(const wchar_t* pch) - { - // returns char length - return 1; - } - - static int __stdcall GetCharLen(const char* pch) - { - // returns char length - return int(_mbclen(reinterpret_cast< const unsigned char* >(pch))); - } - - static DWORD __stdcall GetEnvironmentVariable(LPCSTR pszVar, LPSTR pszBuffer, DWORD dwSize) - { - return ::GetEnvironmentVariableA(pszVar, pszBuffer, dwSize); - } -}; - -// specialization for wchar_t -template<> -class ChTraitsCRT< wchar_t > : public ChTraitsBase< wchar_t > -{ - static DWORD __stdcall _GetEnvironmentVariableW(LPCWSTR pszName, LPWSTR pszBuffer, DWORD nSize) - { - return ::GetEnvironmentVariableW(pszName, pszBuffer, nSize); - } - -public: - static LPWSTR __stdcall CharNext(LPCWSTR psz) - { - return const_cast< LPWSTR >(psz+1); - } - - static int __stdcall IsDigit(wchar_t ch) - { - return iswdigit(static_cast(ch)); - } - - static int __stdcall IsSpace(wchar_t ch) - { - return iswspace(static_cast(ch)); - } - - static int __stdcall StringCompare(LPCWSTR pszA, LPCWSTR pszB) - { - return wcscmp(pszA, pszB); - } - - static int __stdcall StringCompareIgnore(LPCWSTR pszA, LPCWSTR pszB) - { - return _wcsicmp(pszA, pszB); - } - - static int __stdcall StringCollate(LPCWSTR pszA, LPCWSTR pszB) - { - return wcscoll(pszA, pszB); - } - - static int __stdcall StringCollateIgnore(LPCWSTR pszA, LPCWSTR pszB) - { - return _wcsicoll(pszA, pszB); - } - - static LPCWSTR __stdcall StringFindString(LPCWSTR pszBlock, LPCWSTR pszMatch) - { - return wcsstr(pszBlock, pszMatch); - } - - static LPWSTR __stdcall StringFindString(LPWSTR pszBlock, LPCWSTR pszMatch) - { - return const_cast< LPWSTR >(StringFindString(const_cast< LPCWSTR >(pszBlock), pszMatch)); - } - - static LPCWSTR __stdcall StringFindChar(LPCWSTR pszBlock, wchar_t chMatch) - { - return wcschr(pszBlock, chMatch); - } - - static LPCWSTR __stdcall StringFindCharRev(LPCWSTR psz, wchar_t ch) - { - return wcsrchr(psz, ch); - } - - static LPCWSTR __stdcall StringScanSet(LPCWSTR pszBlock, LPCWSTR pszMatch) - { - return wcspbrk(pszBlock, pszMatch); - } - - static int __stdcall StringSpanIncluding(LPCWSTR pszBlock, LPCWSTR pszSet) - { - return (int)wcsspn(pszBlock, pszSet); - } - - static int __stdcall StringSpanExcluding(LPCWSTR pszBlock, LPCWSTR pszSet) - { - return (int)wcscspn(pszBlock, pszSet); - } - - static LPWSTR __stdcall StringUppercase(LPWSTR psz) - { -#pragma warning (push) -#pragma warning(disable : 4996) - return _wcsupr(psz); -#pragma warning (pop) - } - - static LPWSTR __stdcall StringLowercase(LPWSTR psz) - { -#pragma warning (push) -#pragma warning(disable : 4996) - return _wcslwr(psz); -#pragma warning (pop) - } - - static LPWSTR __stdcall StringUppercase(LPWSTR psz, size_t) - { - return _wcsupr(psz); - } - - static LPWSTR __stdcall StringLowercase(LPWSTR psz, size_t) - { - return _wcslwr(psz); - } - - static LPWSTR __stdcall StringReverse(LPWSTR psz) - { - return _wcsrev(psz); - } - - static int __stdcall GetFormattedLength(LPCWSTR pszFormat, va_list args); - - static int __stdcall Format(LPWSTR pszBuffer, LPCWSTR pszFormat, va_list args) - { -#pragma warning (push) -#pragma warning(disable : 4996) - return vswprintf(pszBuffer, pszFormat, args); //!!!!!!!!! -#pragma warning (pop) - } - - static int __stdcall Format(LPWSTR pszBuffer, size_t nLength, LPCWSTR pszFormat, va_list args); - - static int __stdcall GetBaseTypeLength(LPCSTR pszSrc) - { - // Returns required buffer size in wchar_ts - return ::MultiByteToWideChar(CP_ACP, 0, pszSrc, -1, NULL, 0)-1; - } - - static int __stdcall GetBaseTypeLength(LPCSTR pszSrc, int nLength) - { - // Returns required buffer size in wchar_ts - return ::MultiByteToWideChar(CP_ACP, 0, pszSrc, nLength, NULL, 0); - } - - static int __stdcall GetBaseTypeLength(LPCWSTR pszSrc) - { - // Returns required buffer size in wchar_ts - return (int)wcslen(pszSrc); - } - - static int __stdcall GetBaseTypeLength(LPCWSTR pszSrc, int nLength) - { - (void)pszSrc; - // Returns required buffer size in wchar_ts - return nLength; - } - - static void __stdcall ConvertToBaseType(LPWSTR pszDest, int nDestLength, LPCSTR pszSrc, int nSrcLength = -1) - { - // nLen is in wchar_ts - ::MultiByteToWideChar(CP_ACP, 0, pszSrc, nSrcLength, pszDest, nDestLength); - } - - static void __stdcall ConvertToBaseType(LPWSTR pszDest, int nDestLength, LPCWSTR pszSrc, int nSrcLength = -1) - { - if (nSrcLength == -1) { nSrcLength=1 + GetBaseTypeLength(pszSrc); } - // nLen is in wchar_ts - #if _MSC_VER >= 1400 - wmemcpy_s(pszDest, nDestLength, pszSrc, nSrcLength); - #else - wmemcpy(pszDest, pszSrc, nDestLength); - #endif - } - - static void __stdcall FloodCharacters(wchar_t ch, int nLength, LPWSTR psz) - { - // nLength is in XCHARs - for (int i = 0; i < nLength; i++) - { - psz[i] = ch; - } - } - - static BSTR __stdcall AllocSysString(const wchar_t* pchData, int nDataLength) - { - return ::SysAllocStringLen(pchData, nDataLength); - } - - static BOOL __stdcall ReAllocSysString(const wchar_t* pchData, BSTR* pbstr, int nDataLength) - { - return ::SysReAllocStringLen(pbstr, pchData, nDataLength); - } - - static int __stdcall SafeStringLen(LPCSTR psz) - { - // returns length in bytes - return (psz != NULL) ? (int)strlen(psz) : 0; - } - - static int __stdcall SafeStringLen(LPCWSTR psz) - { - // returns length in wchar_ts - return (psz != NULL) ? (int)wcslen(psz) : 0; - } - - static int __stdcall GetCharLen(const wchar_t* pch) - { - (void)pch; - // returns char length - return 1; - } - - static int __stdcall GetCharLen(const char* pch) - { - // returns char length - return (int)(_mbclen(reinterpret_cast< const unsigned char* >(pch))); - } - - static DWORD __stdcall GetEnvironmentVariable(LPCWSTR pszVar, LPWSTR pszBuffer, DWORD dwSize) - { - return _GetEnvironmentVariableW(pszVar, pszBuffer, dwSize); - } - - static void __stdcall ConvertToOem(LPWSTR /*psz*/) - { - } - - static void __stdcall ConvertToAnsi(LPWSTR /*psz*/) - { - } - - static void __stdcall ConvertToOem(LPWSTR /*psz*/, size_t) - { - } - - static void __stdcall ConvertToAnsi(LPWSTR /*psz*/, size_t) - { - } -}; - -template< typename BaseType, class StringTraits > -class CMStringT : public CMSimpleStringT< BaseType > -{ -public: - typedef CMSimpleStringT< BaseType> CThisSimpleString; - typedef typename CThisSimpleString::XCHAR XCHAR; - typedef typename CThisSimpleString::PXSTR PXSTR; - typedef typename CThisSimpleString::PCXSTR PCXSTR; - typedef typename CThisSimpleString::YCHAR YCHAR; - typedef typename CThisSimpleString::PYSTR PYSTR; - typedef typename CThisSimpleString::PCYSTR PCYSTR; - -public: - CMStringT() : CThisSimpleString() - { - } - - static void __stdcall Construct(CMStringT* pString) - { - new(pString) CMStringT; - } - - // Copy constructor - CMStringT(const CMStringT& strSrc) : - CThisSimpleString(strSrc) - { - } - - CMStringT(const XCHAR* pszSrc) : - CThisSimpleString() - { - // nDestLength is in XCHARs - *this = pszSrc; - } - - CMStringT(const YCHAR* pszSrc) : - CThisSimpleString() - { - *this = pszSrc; - } - - - CMStringT(const unsigned char* pszSrc) : - CThisSimpleString() - { - *this = reinterpret_cast< const char* >(pszSrc); - } - - CMStringT(char ch, int nLength = 1) : - CThisSimpleString() - { - if (nLength > 0) - { - PXSTR pszBuffer = this->GetBuffer(nLength); - StringTraits::FloodCharacters(XCHAR(ch), nLength, pszBuffer); - this->ReleaseBufferSetLength(nLength); - } - } - - CMStringT(wchar_t ch, int nLength = 1) : - CThisSimpleString() - { - if (nLength > 0) - { - //Convert ch to the BaseType - wchar_t pszCh[2] = { ch , 0 }; - int nBaseTypeCharLen = 1; - - if (ch != L'\0') - { - nBaseTypeCharLen = StringTraits::GetBaseTypeLength(pszCh); - } - - XCHAR *buffBaseTypeChar = new XCHAR[nBaseTypeCharLen+1]; - StringTraits::ConvertToBaseType(buffBaseTypeChar, nBaseTypeCharLen+1, pszCh, 1); - //Allocate enough characters in String and flood (replicate) with the (converted character)*nLength - PXSTR pszBuffer = this->GetBuffer(nLength*nBaseTypeCharLen); - if (nBaseTypeCharLen == 1) - { //Optimization for a common case - wide char translates to 1 ansi/wide char. - StringTraits::FloodCharacters(buffBaseTypeChar[0], nLength, pszBuffer); - } else - { - XCHAR* p=pszBuffer; - for (int i=0 ; i < nLength ;i++) - { - for (int j=0 ; j < nBaseTypeCharLen ;++j) - { - *p=buffBaseTypeChar[j]; - ++p; - } - } - } - this->ReleaseBufferSetLength(nLength*nBaseTypeCharLen); - delete [] buffBaseTypeChar; - } - } - - CMStringT(const XCHAR* pch, int nLength) : - CThisSimpleString(pch, nLength) - { - } - - CMStringT(const YCHAR* pch, int nLength) : - CThisSimpleString() - { - if (nLength > 0) - { - int nDestLength = StringTraits::GetBaseTypeLength(pch, nLength); - PXSTR pszBuffer = this->GetBuffer(nDestLength); - StringTraits::ConvertToBaseType(pszBuffer, nDestLength, pch, nLength); - this->ReleaseBufferSetLength(nDestLength); - } - } - - // Destructor - ~CMStringT() - { - } - - // Assignment operators - CMStringT& operator=(const CMStringT& strSrc) - { - CThisSimpleString::operator=(strSrc); - - return *this; - } - - CMStringT& operator=(PCXSTR pszSrc) - { - CThisSimpleString::operator=(pszSrc); - - return *this; - } - - CMStringT& operator=(PCYSTR pszSrc) - { - // nDestLength is in XCHARs - int nDestLength = (pszSrc != NULL) ? StringTraits::GetBaseTypeLength(pszSrc) : 0; - if (nDestLength > 0) - { - PXSTR pszBuffer = this->GetBuffer(nDestLength); - StringTraits::ConvertToBaseType(pszBuffer, nDestLength, pszSrc); - this->ReleaseBufferSetLength(nDestLength); - } - else - { - this->Empty(); - } - - return *this; - } - - CMStringT& operator=(const unsigned char* pszSrc) - { - return operator=(reinterpret_cast< const char* >(pszSrc)); - } - - CMStringT& operator=(char ch) - { - char ach[2] = { ch, 0 }; - - return operator=(ach); - } - - CMStringT& operator=(wchar_t ch) - { - wchar_t ach[2] = { ch, 0 }; - - return operator=(ach); - } - -// CMStringT& operator=(const VARIANT& var); - - CMStringT& operator+=(const CMStringT& str) - { - CThisSimpleString::operator+=(str); - return *this; - } - - CMStringT& operator+=(const CThisSimpleString& str) - { - CThisSimpleString::operator+=(str); - return *this; - } - - CMStringT& operator+=(PCXSTR pszSrc) - { - CThisSimpleString::operator+=(pszSrc); - return *this; - } -// template< int t_nSize > -// CMStringT& operator+=(const CStaticString< XCHAR, t_nSize >& strSrc) -// { -// CThisSimpleString::operator+=(strSrc); -// -// return *this; -// } - CMStringT& operator+=(PCYSTR pszSrc) - { - CMStringT str(pszSrc); - - return operator+=(str); - } - - CMStringT& operator+=(char ch) - { - CThisSimpleString::operator+=(ch); - - return *this; - } - - CMStringT& operator+=(unsigned char ch) - { - CThisSimpleString::operator+=(ch); - - return *this; - } - - CMStringT& operator+=(wchar_t ch) - { - CThisSimpleString::operator+=(ch); - - return *this; - } - - // Comparison - - int Compare(PCXSTR psz) const - { - return StringTraits::StringCompare(this->GetString(), psz); - } - - int CompareNoCase(PCXSTR psz) const - { - return StringTraits::StringCompareIgnore(this->GetString(), psz); - } - - int Collate(PCXSTR psz) const - { - return StringTraits::StringCollate(this->GetString(), psz); - } - - int CollateNoCase(PCXSTR psz) const - { - return StringTraits::StringCollateIgnore(this->GetString(), psz); - } - - // Advanced manipulation - - // Delete 'nCount' characters, starting at index 'iIndex' - int Delete(int iIndex, int nCount = 1) - { - if (iIndex < 0) - iIndex = 0; - - if (nCount < 0) - nCount = 0; - - int nLength = this->GetLength(); - if (nCount + iIndex > nLength) - { - nCount = nLength-iIndex; - } - if (nCount > 0) - { - int nNewLength = nLength-nCount; - int nXCHARsToCopy = nLength-(iIndex+nCount)+1; - PXSTR pszBuffer = this->GetBuffer(); - #if _MSC_VER >= 1400 - memmove_s(pszBuffer+iIndex, nXCHARsToCopy*sizeof(XCHAR), pszBuffer+iIndex+nCount, nXCHARsToCopy*sizeof(XCHAR)); - #else - memmove(pszBuffer+iIndex, pszBuffer+iIndex+nCount, nXCHARsToCopy*sizeof(XCHAR)); - #endif - this->ReleaseBufferSetLength(nNewLength); - } - - return this->GetLength(); - } - - // Insert character 'ch' before index 'iIndex' - int Insert(int iIndex, XCHAR ch) - { - if (iIndex < 0) - iIndex = 0; - - if (iIndex > this->GetLength()) - iIndex = this->GetLength(); - - int nNewLength = this->GetLength()+1; - - PXSTR pszBuffer = this->GetBuffer(nNewLength); - - // move existing bytes down - #if _MSC_VER >= 1400 - memmove_s(pszBuffer+iIndex+1, (nNewLength-iIndex)*sizeof(XCHAR), pszBuffer+iIndex, (nNewLength-iIndex)*sizeof(XCHAR)); - #else - memmove(pszBuffer+iIndex+1, pszBuffer+iIndex, (nNewLength-iIndex)*sizeof(XCHAR)); - #endif - pszBuffer[iIndex] = ch; - - this->ReleaseBufferSetLength(nNewLength); - return nNewLength; - } - - // Insert string 'psz' before index 'iIndex' - int Insert(int iIndex, PCXSTR psz) - { - if (iIndex < 0) - iIndex = 0; - - if (iIndex > this->GetLength()) - { - iIndex = this->GetLength(); - } - - // nInsertLength and nNewLength are in XCHARs - int nInsertLength = StringTraits::SafeStringLen(psz); - int nNewLength = this->GetLength(); - if (nInsertLength > 0) - { - nNewLength += nInsertLength; - - PXSTR pszBuffer = this->GetBuffer(nNewLength); - // move existing bytes down - #if _MSC_VER >= 1400 - memmove_s(pszBuffer+iIndex+nInsertLength, (nNewLength-iIndex-nInsertLength+1)*sizeof(XCHAR), pszBuffer+iIndex, (nNewLength-iIndex-nInsertLength+1)*sizeof(XCHAR)); - memcpy_s(pszBuffer+iIndex, nInsertLength*sizeof(XCHAR), psz, nInsertLength*sizeof(XCHAR)); - #else - memmove(pszBuffer+iIndex+nInsertLength, pszBuffer+iIndex, (nNewLength-iIndex-nInsertLength+1)*sizeof(XCHAR)); - memcpy(pszBuffer+iIndex, psz, nInsertLength*sizeof(XCHAR)); - #endif - this->ReleaseBufferSetLength(nNewLength); - } - - return nNewLength; - } - - // Replace all occurrences of character 'chOld' with character 'chNew' - int Replace(XCHAR chOld, XCHAR chNew) - { - int nCount = 0; - - // short-circuit the nop case - if (chOld != chNew) - { - // otherwise modify each character that matches in the string - bool bCopied = false; - PXSTR pszBuffer = const_cast< PXSTR >(this->GetString()); // We don't actually write to pszBuffer until we've called GetBuffer(). - - int nLength = this->GetLength(); - int iChar = 0; - while(iChar < nLength) - { - // replace instances of the specified character only - if (pszBuffer[iChar] == chOld) - { - if ( !bCopied) - { - bCopied = true; - pszBuffer = this->GetBuffer(nLength); - } - pszBuffer[iChar] = chNew; - nCount++; - } - iChar = int(StringTraits::CharNext(pszBuffer+iChar)-pszBuffer); - } - if (bCopied) - { - this->ReleaseBufferSetLength(nLength); - } - } - - return nCount; - } - - // Replace all occurrences of string 'pszOld' with string 'pszNew' - int Replace(PCXSTR pszOld, PCXSTR pszNew) - { - // can't have empty or NULL lpszOld - - // nSourceLen is in XCHARs - int nSourceLen = StringTraits::SafeStringLen(pszOld); - if (nSourceLen == 0) - return 0; - // nReplacementLen is in XCHARs - int nReplacementLen = StringTraits::SafeStringLen(pszNew); - - // loop once to figure out the size of the result string - int nCount = 0; - { - PCXSTR pszStart = this->GetString(); - PCXSTR pszEnd = pszStart+this->GetLength(); - while(pszStart < pszEnd) - { - PCXSTR pszTarget; - while((pszTarget = StringTraits::StringFindString(pszStart, pszOld)) != NULL) - { - nCount++; - pszStart = pszTarget+nSourceLen; - } - pszStart += StringTraits::SafeStringLen(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 = this->GetLength(); - int nNewLength = nOldLength+(nReplacementLen-nSourceLen)*nCount; - - PXSTR pszBuffer = this->GetBuffer(__max(nNewLength, nOldLength)); - - PXSTR pszStart = pszBuffer; - PXSTR pszEnd = pszStart+nOldLength; - - // loop again to actually do the work - while(pszStart < pszEnd) - { - PXSTR pszTarget; - while((pszTarget = StringTraits::StringFindString(pszStart, pszOld)) != NULL) - { - int nBalance = nOldLength-int(pszTarget-pszBuffer+nSourceLen); - memmove_s(pszTarget+nReplacementLen, nBalance*sizeof(XCHAR), - pszTarget+nSourceLen, nBalance*sizeof(XCHAR)); - memcpy_s(pszTarget, nReplacementLen*sizeof(XCHAR), - pszNew, nReplacementLen*sizeof(XCHAR)); - pszStart = pszTarget+nReplacementLen; - pszTarget[nReplacementLen+nBalance] = 0; - nOldLength += (nReplacementLen-nSourceLen); - } - pszStart += StringTraits::SafeStringLen(pszStart)+1; - } - this->ReleaseBufferSetLength(nNewLength); - } - - return nCount; - } - - // Remove all occurrences of character 'chRemove' - int Remove(XCHAR chRemove) - { - int nLength = this->GetLength(); - PXSTR pszBuffer = this->GetBuffer(nLength); - - PXSTR pszSource = pszBuffer; - PXSTR pszDest = pszBuffer; - PXSTR pszEnd = pszBuffer+nLength; - - while(pszSource < pszEnd) - { - PXSTR pszNewSource = StringTraits::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); - PXSTR pszNewDest = pszDest + NewSourceGap; - size_t i = 0; - for (i = 0; pszDest != pszNewDest && i < NewSourceGap; i++) - { - *pszDest = *pszSource; - pszSource++; - pszDest++; - } - } - pszSource = pszNewSource; - } - *pszDest = 0; - int nCount = int(pszSource-pszDest); - this->ReleaseBufferSetLength(nLength-nCount); - - return nCount; - } - - CMStringT Tokenize(PCXSTR pszTokens, int& iStart) const - { - if ((pszTokens == NULL) || (*pszTokens == (XCHAR)0)) - { - if (iStart < this->GetLength()) - return CMStringT(this->GetString()+iStart); - } - else - { - PCXSTR pszPlace = this->GetString()+iStart; - PCXSTR pszEnd = this->GetString()+this->GetLength(); - if (pszPlace < pszEnd) - { - int nIncluding = StringTraits::StringSpanIncluding(pszPlace, pszTokens); - - if ((pszPlace+nIncluding) < pszEnd) - { - pszPlace += nIncluding; - int nExcluding = StringTraits::StringSpanExcluding(pszPlace, pszTokens); - - int iFrom = iStart+nIncluding; - int nUntil = nExcluding; - iStart = iFrom+nUntil+1; - - return Mid(iFrom, nUntil); - } - } - } - - // return empty string, done tokenizing - iStart = -1; - - return CMStringT(); - } - - // find routines - - // Find the first occurrence of character 'ch', starting at index 'iStart' - int Find(XCHAR ch, int iStart = 0) const - { - // nLength is in XCHARs - int nLength = this->GetLength(); - if (iStart < 0 || iStart >= nLength) - return -1; - - // find first single character - PCXSTR psz = StringTraits::StringFindChar(this->GetString()+iStart, ch); - - // return -1 if not found and index otherwise - return (psz == NULL) ? -1 : int(psz-this->GetString()); - } - - // look for a specific sub-string - - // Find the first occurrence of string 'pszSub', starting at index 'iStart' - int Find(PCXSTR pszSub, int iStart = 0) const - { - // iStart is in XCHARs - if (pszSub == NULL) - return -1; - - // nLength is in XCHARs - int nLength = this->GetLength(); - if (iStart < 0 || iStart > nLength) - return -1; - - // find first matching substring - PCXSTR psz = StringTraits::StringFindString(this->GetString()+iStart, pszSub); - - // return -1 for not found, distance from beginning otherwise - return (psz == NULL) ? -1 : int(psz-this->GetString()); - } - - // Find the first occurrence of any of the characters in string 'pszCharSet' - int FindOneOf(PCXSTR pszCharSet) const - { - PCXSTR psz = StringTraits::StringScanSet(this->GetString(), pszCharSet); - return (psz == NULL) ? -1 : int(psz-this->GetString()); - } - - // Find the last occurrence of character 'ch' - int ReverseFind(XCHAR ch) const - { - // find last single character - PCXSTR psz = StringTraits::StringFindCharRev(this->GetString(), ch); - - // return -1 if not found, distance from beginning otherwise - return (psz == NULL) ? -1 : int(psz-this->GetString()); - } - - // manipulation - - // Convert the string to uppercase - CMStringT& MakeUpper() - { - int nLength = this->GetLength(); - PXSTR pszBuffer = this->GetBuffer(nLength); - StringTraits::StringUppercase(pszBuffer, nLength+1); - this->ReleaseBufferSetLength(nLength); - - return *this; - } - - // Convert the string to lowercase - CMStringT& MakeLower() - { - int nLength = this->GetLength(); - PXSTR pszBuffer = this->GetBuffer(nLength); - StringTraits::StringLowercase(pszBuffer, nLength+1); - this->ReleaseBufferSetLength(nLength); - - return *this; - } - - // Reverse the string - CMStringT& MakeReverse() - { - int nLength = this->GetLength(); - PXSTR pszBuffer = this->GetBuffer(nLength); - StringTraits::StringReverse(pszBuffer); - this->ReleaseBufferSetLength(nLength); - - return *this; - } - - // trimming - - // Remove all trailing whitespace - CMStringT& TrimRight() - { - // find beginning of trailing spaces by starting - // at beginning (DBCS aware) - - PCXSTR psz = this->GetString(); - PCXSTR pszLast = NULL; - - while(*psz != 0) - { - if (StringTraits::IsSpace(*psz)) - { - if (pszLast == NULL) - pszLast = psz; - } - else - { - pszLast = NULL; - } - psz = StringTraits::CharNext(psz); - } - - if (pszLast != NULL) - { - // truncate at trailing space start - int iLast = int(pszLast-this->GetString()); - - this->Truncate(iLast); - } - - return *this; - } - - // Remove all leading whitespace - CMStringT& TrimLeft() - { - // find first non-space character - - PCXSTR psz = this->GetString(); - - while(StringTraits::IsSpace(*psz)) - { - psz = StringTraits::CharNext(psz); - } - - if (psz != this->GetString()) - { - // fix up data and length - int iFirst = int(psz-this->GetString()); - PXSTR pszBuffer = this->GetBuffer(this->GetLength()); - psz = pszBuffer+iFirst; - int nDataLength = this->GetLength()-iFirst; - memmove_s(pszBuffer, (this->GetLength()+1)*sizeof(XCHAR), - psz, (nDataLength+1)*sizeof(XCHAR)); - this->ReleaseBufferSetLength(nDataLength); - } - - return *this; - } - - // Remove all leading and trailing whitespace - CMStringT& Trim() - { - return TrimRight().TrimLeft(); - } - - // Remove all leading and trailing occurrences of character 'chTarget' - CMStringT& Trim(XCHAR chTarget) - { - return TrimRight(chTarget).TrimLeft(chTarget); - } - - // Remove all leading and trailing occurrences of any of the characters in the string 'pszTargets' - CMStringT& Trim(PCXSTR pszTargets) - { - return TrimRight(pszTargets).TrimLeft(pszTargets); - } - - // trimming anything (either side) - - // Remove all trailing occurrences of character 'chTarget' - CMStringT& TrimRight(XCHAR chTarget) - { - // find beginning of trailing matches - // by starting at beginning (DBCS aware) - - PCXSTR psz = this->GetString(); - PCXSTR pszLast = NULL; - - while(*psz != 0) - { - if (*psz == chTarget) - { - if (pszLast == NULL) - { - pszLast = psz; - } - } - else - { - pszLast = NULL; - } - psz = StringTraits::CharNext(psz); - } - - if (pszLast != NULL) - { - // truncate at left-most matching character - int iLast = int(pszLast-this->GetString()); - this->Truncate(iLast); - } - - return *this; - } - - // Remove all trailing occurrences of any of the characters in string 'pszTargets' - CMStringT& TrimRight(PCXSTR 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) - - PCXSTR psz = this->GetString(); - PCXSTR pszLast = NULL; - - while(*psz != 0) - { - if (StringTraits::StringFindChar(pszTargets, *psz) != NULL) - { - if (pszLast == NULL) - { - pszLast = psz; - } - } - else - { - pszLast = NULL; - } - psz = StringTraits::CharNext(psz); - } - - if (pszLast != NULL) - { - // truncate at left-most matching character - int iLast = int(pszLast-this->GetString()); - this->Truncate(iLast); - } - - return *this; - } - - // Remove all leading occurrences of character 'chTarget' - CMStringT& TrimLeft(XCHAR chTarget) - { - // find first non-matching character - PCXSTR psz = this->GetString(); - - while(chTarget == *psz) - { - psz = StringTraits::CharNext(psz); - } - - if (psz != this->GetString()) - { - // fix up data and length - int iFirst = int(psz-this->GetString()); - PXSTR pszBuffer = this->GetBuffer(this->GetLength()); - psz = pszBuffer+iFirst; - int nDataLength = this->GetLength()-iFirst; - memmove_s(pszBuffer, (this->GetLength()+1)*sizeof(XCHAR), - psz, (nDataLength+1)*sizeof(XCHAR)); - this->ReleaseBufferSetLength(nDataLength); - } - - return *this; - } - - // Remove all leading occurrences of any of the characters in string 'pszTargets' - CMStringT& TrimLeft(PCXSTR pszTargets) - { - // if we're not trimming anything, we're not doing any work - if ((pszTargets == NULL) || (*pszTargets == 0)) - { - return *this; - } - - PCXSTR psz = this->GetString(); - while((*psz != 0) && (StringTraits::StringFindChar(pszTargets, *psz) != NULL)) - { - psz = StringTraits::CharNext(psz); - } - - if (psz != this->GetString()) - { - // fix up data and length - int iFirst = int(psz-this->GetString()); - PXSTR pszBuffer = this->GetBuffer(this->GetLength()); - psz = pszBuffer+iFirst; - int nDataLength = this->GetLength()-iFirst; - memmove_s(pszBuffer, (this->GetLength()+1)*sizeof(XCHAR), - psz, (nDataLength+1)*sizeof(XCHAR)); - this->ReleaseBufferSetLength(nDataLength); - } - - return *this; - } - - // Convert the string to the OEM character set - void AnsiToOem() - { - int nLength = this->GetLength(); - PXSTR pszBuffer = this->GetBuffer(nLength); - StringTraits::ConvertToOem(pszBuffer, nLength+1); - this->ReleaseBufferSetLength(nLength); - } - - // Convert the string to the ANSI character set - void OemToAnsi() - { - int nLength = this->GetLength(); - PXSTR pszBuffer = this->GetBuffer(nLength); - StringTraits::ConvertToAnsi(pszBuffer, nLength+1); - this->ReleaseBufferSetLength(nLength); - } - - // Very simple sub-string extraction - - // Return the substring starting at index 'iFirst' - CMStringT Mid(int iFirst) const - { - return Mid(iFirst, this->GetLength()-iFirst); - } - - // Return the substring starting at index 'iFirst', with length 'nCount' - CMStringT Mid(int iFirst, int nCount) const - { - // nCount is in XCHARs - - // out-of-bounds requests return sensible things - if (iFirst < 0) - iFirst = 0; - if (nCount < 0) - nCount = 0; - - if ((iFirst + nCount) > this->GetLength()) - nCount = this->GetLength()-iFirst; - - if (iFirst > this->GetLength()) - nCount = 0; - - // optimize case of returning entire string - if ((iFirst == 0) && ((iFirst+nCount) == this->GetLength())) - return *this; - - return CMStringT(this->GetString()+iFirst, nCount); - } - - // Return the substring consisting of the rightmost 'nCount' characters - CMStringT Right(int nCount) const - { - // nCount is in XCHARs - if (nCount < 0) - nCount = 0; - - int nLength = this->GetLength(); - if (nCount >= nLength) - { - return *this; - } - - return CMStringT(this->GetString()+nLength-nCount, nCount); - } - - // Return the substring consisting of the leftmost 'nCount' characters - CMStringT Left(int nCount) const - { - // nCount is in XCHARs - if (nCount < 0) - nCount = 0; - - int nLength = this->GetLength(); - if (nCount >= nLength) - return *this; - - return CMStringT(this->GetString(), nCount); - } - - // Return the substring consisting of the leftmost characters in the set 'pszCharSet' - CMStringT SpanIncluding(PCXSTR pszCharSet) const - { - return Left(StringTraits::StringSpanIncluding(this->GetString(), pszCharSet)); - } - - // Return the substring consisting of the leftmost characters not in the set 'pszCharSet' - CMStringT SpanExcluding(PCXSTR pszCharSet) const - { - return Left(StringTraits::StringSpanExcluding(this->GetString(), pszCharSet)); - } - - // Format data using format string 'pszFormat' - void Format(PCXSTR pszFormat, ...); - - // Append formatted data using format string 'pszFormat' - void AppendFormat(PCXSTR pszFormat, ...); - - void AppendFormatV(PCXSTR pszFormat, va_list args) - { - int nCurrentLength = this->GetLength(); - int nAppendLength = StringTraits::GetFormattedLength(pszFormat, args); - PXSTR pszBuffer = this->GetBuffer(nCurrentLength+nAppendLength); - StringTraits::Format(pszBuffer+nCurrentLength, - nAppendLength+1, pszFormat, args); - this->ReleaseBufferSetLength(nCurrentLength+nAppendLength); - } - - void FormatV(PCXSTR pszFormat, va_list args) - { - int nLength = StringTraits::GetFormattedLength(pszFormat, args); - PXSTR pszBuffer = this->GetBuffer(nLength); - StringTraits::Format(pszBuffer, nLength+1, pszFormat, args); - this->ReleaseBufferSetLength(nLength); - } - - // OLE BSTR support - - // Allocate a BSTR containing a copy of the string - BSTR AllocSysString() const - { - BSTR bstrResult = StringTraits::AllocSysString(this->GetString(), this->GetLength()); - return bstrResult; - } - - BSTR SetSysString(BSTR* pbstr) const - { - StringTraits::ReAllocSysString(this->GetString(), pbstr, this->GetLength()); - return *pbstr; - } - - // Set the string to the value of environment variable 'pszVar' - BOOL GetEnvironmentVariable(PCXSTR pszVar) - { - ULONG nLength = StringTraits::GetEnvironmentVariable(pszVar, NULL, 0); - BOOL bRetVal = FALSE; - - if (nLength == 0) - { - this->Empty(); - } - else - { - PXSTR pszBuffer = this->GetBuffer(nLength); - StringTraits::GetEnvironmentVariable(pszVar, pszBuffer, nLength); - this->ReleaseBuffer(); - bRetVal = TRUE; - } - - return bRetVal; - } - - // Load the string from resource 'nID' - BOOL LoadString(UINT nID) - { - HINSTANCE hInst = StringTraits::FindStringResourceInstance(nID); - if (hInst == NULL) - return FALSE; - - return LoadString(hInst, nID); - } - - friend CMStringT __stdcall operator+(const CMStringT& str1, const CMStringT& str2) - { - CMStringT strResult; - - Concatenate(strResult, str1, str1.GetLength(), str2, str2.GetLength()); - - return strResult; - } - - friend CMStringT __stdcall operator+(const CMStringT& str1, PCXSTR psz2) - { - CMStringT strResult; - - Concatenate(strResult, str1, str1.GetLength(), psz2, StringLength(psz2)); - - return strResult; - } - - friend CMStringT __stdcall operator+(PCXSTR psz1, const CMStringT& str2) - { - CMStringT strResult; - - Concatenate(strResult, psz1, StringLength(psz1), str2, str2.GetLength()); - - return strResult; - } - - friend CMStringT __stdcall operator+(const CMStringT& str1, wchar_t ch2) - { - CMStringT strResult; - XCHAR chTemp = XCHAR(ch2); - - Concatenate(strResult, str1, str1.GetLength(), &chTemp, 1); - - return strResult; - } - - friend CMStringT __stdcall operator+(const CMStringT& str1, char ch2) - { - CMStringT strResult; - XCHAR chTemp = XCHAR(ch2); - - Concatenate(strResult, str1, str1.GetLength(), &chTemp, 1); - - return strResult; - } - - friend CMStringT __stdcall operator+(wchar_t ch1, const CMStringT& str2) - { - CMStringT strResult; - XCHAR chTemp = XCHAR(ch1); - - Concatenate(strResult, &chTemp, 1, str2, str2.GetLength()); - - return strResult; - } - - friend CMStringT __stdcall operator+(char ch1, const CMStringT& str2) - { - CMStringT strResult; - XCHAR chTemp = XCHAR(ch1); - - Concatenate(strResult, &chTemp, 1, str2, str2.GetLength()); - - return strResult; - } - - friend bool __stdcall operator==(const CMStringT& str1, const CMStringT& str2) - { - return str1.Compare(str2) == 0; - } - - friend bool __stdcall operator==(const CMStringT& str1, PCXSTR psz2) - { - return str1.Compare(psz2) == 0; - } - - friend bool __stdcall operator==(PCXSTR psz1, const CMStringT& str2) - { - return str2.Compare(psz1) == 0; - } - - friend bool __stdcall operator==(const CMStringT& str1, PCYSTR psz2) - { - CMStringT str2(psz2); - - return str1 == str2; - } - - friend bool __stdcall operator==(PCYSTR psz1, const CMStringT& str2) - { - CMStringT str1(psz1); - - return str1 == str2; - } - - friend bool __stdcall operator!=(const CMStringT& str1, const CMStringT& str2) - { - return str1.Compare(str2) != 0; - } - - friend bool __stdcall operator!=(const CMStringT& str1, PCXSTR psz2) - { - return str1.Compare(psz2) != 0; - } - - friend bool __stdcall operator!=(PCXSTR psz1, const CMStringT& str2) - { - return str2.Compare(psz1) != 0; - } - - friend bool __stdcall operator!=(const CMStringT& str1, PCYSTR psz2) - { - CMStringT str2(psz2); - - return str1 != str2; - } - - friend bool __stdcall operator!=(PCYSTR psz1, const CMStringT& str2) - { - CMStringT str1(psz1); - - return str1 != str2; - } - - friend bool __stdcall operator<(const CMStringT& str1, const CMStringT& str2) - { - return str1.Compare(str2) < 0; - } - - friend bool __stdcall operator<(const CMStringT& str1, PCXSTR psz2) - { - return str1.Compare(psz2) < 0; - } - - friend bool __stdcall operator<(PCXSTR psz1, const CMStringT& str2) - { - return str2.Compare(psz1) > 0; - } - - friend bool __stdcall operator>(const CMStringT& str1, const CMStringT& str2) - { - return str1.Compare(str2) > 0; - } - - friend bool __stdcall operator>(const CMStringT& str1, PCXSTR psz2) - { - return str1.Compare(psz2) > 0; - } - - friend bool __stdcall operator>(PCXSTR psz1, const CMStringT& str2) - { - return str2.Compare(psz1) < 0; - } - - friend bool __stdcall operator<=(const CMStringT& str1, const CMStringT& str2) - { - return str1.Compare(str2) <= 0; - } - - friend bool __stdcall operator<=(const CMStringT& str1, PCXSTR psz2) - { - return str1.Compare(psz2) <= 0; - } - - friend bool __stdcall operator<=(PCXSTR psz1, const CMStringT& str2) - { - return str2.Compare(psz1) >= 0; - } - - friend bool __stdcall operator>=(const CMStringT& str1, const CMStringT& str2) - { - return str1.Compare(str2) >= 0; - } - - friend bool __stdcall operator>=(const CMStringT& str1, PCXSTR psz2) - { - return str1.Compare(psz2) >= 0; - } - - friend bool __stdcall operator>=(PCXSTR psz1, const CMStringT& str2) - { - return str2.Compare(psz1) <= 0; - } - - friend bool __stdcall operator==(XCHAR ch1, const CMStringT& str2) - { - return (str2.GetLength() == 1) && (str2[0] == ch1); - } - - friend bool __stdcall operator==(const CMStringT& str1, XCHAR ch2) - { - return (str1.GetLength() == 1) && (str1[0] == ch2); - } - - friend bool __stdcall operator!=(XCHAR ch1, const CMStringT& str2) - { - return (str2.GetLength() != 1) || (str2[0] != ch1); - } - - friend bool __stdcall operator!=(const CMStringT& str1, XCHAR ch2) - { - return (str1.GetLength() != 1) || (str1[0] != ch2); - } -}; - -template< typename BaseType, class StringTraits > -inline void CMStringT::Format(PCXSTR pszFormat, ...) -{ - va_list argList; - va_start(argList, pszFormat); - FormatV(pszFormat, argList); - va_end(argList); -} - -template< typename BaseType, class StringTraits > -inline void CMStringT::AppendFormat(PCXSTR pszFormat, ...) -{ - va_list argList; - va_start(argList, pszFormat); - AppendFormatV(pszFormat, argList); - va_end(argList); -} - -typedef CMStringT< wchar_t, ChTraitsCRT< wchar_t > > CMStringW; -typedef CMStringT< char, ChTraitsCRT< char > > CMStringA; -typedef CMStringT< TCHAR, ChTraitsCRT< TCHAR > > CMString; -- cgit v1.2.3