summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin10/lib/mir_core.libbin62572 -> 159322 bytes
-rw-r--r--bin10/lib/mir_core64.libbin57214 -> 156378 bytes
-rw-r--r--bin12/lib/mir_core.libbin62572 -> 159322 bytes
-rw-r--r--bin12/lib/mir_core64.libbin57214 -> 156378 bytes
-rw-r--r--include/m_string.h1652
-rw-r--r--include/m_string.inl1476
-rw-r--r--make_core_def.cmd5
-rw-r--r--protocols/VKontakte/src/misc.cpp2
-rw-r--r--src/mir_core/mir_core_10.vcxproj8
-rw-r--r--src/mir_core/mir_core_10.vcxproj.filters8
-rw-r--r--src/mir_core/mir_core_12.vcxproj8
-rw-r--r--src/mir_core/mir_core_12.vcxproj.filters8
-rw-r--r--src/mir_core/src/commonheaders.h2
-rw-r--r--src/mir_core/src/mir_core.def260
-rw-r--r--src/mir_core/src/mir_core64.def542
-rw-r--r--src/mir_core/src/mstring.cpp22
16 files changed, 2551 insertions, 1442 deletions
diff --git a/bin10/lib/mir_core.lib b/bin10/lib/mir_core.lib
index 8cc005a140..ac1d1d06dd 100644
--- a/bin10/lib/mir_core.lib
+++ b/bin10/lib/mir_core.lib
Binary files differ
diff --git a/bin10/lib/mir_core64.lib b/bin10/lib/mir_core64.lib
index 21180445ea..e07882ae0b 100644
--- a/bin10/lib/mir_core64.lib
+++ b/bin10/lib/mir_core64.lib
Binary files differ
diff --git a/bin12/lib/mir_core.lib b/bin12/lib/mir_core.lib
index 7821e6efd4..7a96ae74bf 100644
--- a/bin12/lib/mir_core.lib
+++ b/bin12/lib/mir_core.lib
Binary files differ
diff --git a/bin12/lib/mir_core64.lib b/bin12/lib/mir_core64.lib
index cfbc49103a..7b7d29bc3e 100644
--- a/bin12/lib/mir_core64.lib
+++ b/bin12/lib/mir_core64.lib
Binary files differ
diff --git a/include/m_string.h b/include/m_string.h
index 0e818c72b1..bf5f791342 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -124,474 +124,147 @@ public:
typedef typename ChTraitsBase< BaseType >::PCYSTR PCYSTR;
public:
- explicit CMSimpleStringT()
- {
- CMStringData* pData = mirstr_getNil();
- Attach(pData);
- }
-
- CMSimpleStringT(const CMSimpleStringT& strSrc)
- {
- CMStringData* pSrcData = strSrc.GetData();
- CMStringData* pNewData = CloneData(pSrcData);
- Attach(pNewData);
- }
+ explicit CMSimpleStringT();
- CMSimpleStringT(PCXSTR pszSrc)
- {
- int nLength = StringLength(pszSrc);
- CMStringData* pData = mirstr_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 = mirstr_allocate(nLength, sizeof(XCHAR));
- if (pData != NULL) {
- Attach(pData);
- SetLength(nLength);
- CopyChars(m_pszData, nLength, pchSrc, nLength);
- }
- }
- ~CMSimpleStringT()
- {
- CMStringData* pData = GetData();
- pData->Release();
- }
+ CMSimpleStringT(const CMSimpleStringT& strSrc);
+ CMSimpleStringT(PCXSTR pszSrc);
+ CMSimpleStringT(const XCHAR* pchSrc, int nLength);
+ ~CMSimpleStringT();
- operator CMSimpleStringT<BaseType>&()
- {
- return *(CMSimpleStringT<BaseType>*)this;
+ __forceinline operator CMSimpleStringT<BaseType>&()
+ { return *(CMSimpleStringT<BaseType>*)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);
- }
- }
+ CMSimpleStringT& operator=(const CMSimpleStringT& strSrc);
+ __forceinline CMSimpleStringT& operator=(PCXSTR pszSrc)
+ { SetString(pszSrc);
return *this;
}
- CMSimpleStringT& operator=(PCXSTR pszSrc)
- {
- SetString(pszSrc);
+ __forceinline CMSimpleStringT& operator+=(const CMSimpleStringT& strSrc)
+ { Append(strSrc);
return *this;
}
- CMSimpleStringT& operator+=(const CMSimpleStringT& strSrc)
- {
- Append(strSrc);
+ __forceinline CMSimpleStringT& operator+=(PCXSTR pszSrc)
+ { Append(pszSrc);
return *this;
}
- CMSimpleStringT& operator+=(PCXSTR pszSrc)
- {
- Append(pszSrc);
+ __forceinline CMSimpleStringT& operator+=(char ch)
+ { AppendChar(XCHAR(ch));
return *this;
}
- CMSimpleStringT& operator+=(char ch)
- {
- AppendChar(XCHAR(ch));
- return *this;
- }
- CMSimpleStringT& operator+=(unsigned char ch)
- {
- AppendChar(XCHAR(ch));
+
+ __forceinline CMSimpleStringT& operator+=(unsigned char ch)
+ { AppendChar(XCHAR(ch));
return *this;
}
- CMSimpleStringT& operator+=(wchar_t ch)
- {
- AppendChar(XCHAR(ch));
+
+ __forceinline CMSimpleStringT& operator+=(wchar_t ch)
+ { AppendChar(XCHAR(ch));
return *this;
}
- XCHAR operator[](int iChar) const
- {
- return m_pszData[iChar];
+ __forceinline XCHAR operator[](int iChar) const
+ { return m_pszData[iChar];
}
- operator PCXSTR() const
- {
- return m_pszData;
+ __forceinline operator PCXSTR() const
+ { return m_pszData;
}
- PCXSTR c_str() const
- {
- return m_pszData;
+ __forceinline PCXSTR c_str() const
+ { return m_pszData;
}
- void Append(PCXSTR pszSrc)
- {
- Append(pszSrc, StringLength(pszSrc));
+ __forceinline int GetAllocLength() const
+ { return GetData()->nAllocLength;
}
- void Append(PCXSTR pszSrc, int nLength)
- {
- // See comment in SetString() about why we do this
- UINT_PTR nOffset = UINT_PTR(pszSrc - GetString());
-
- int 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 <= UINT_PTR(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 = mirstr_getNil();
- 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 = mirstr_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);
- }
+ __forceinline XCHAR GetAt(int iChar) const
+ { return m_pszData[iChar];
}
- int GetAllocLength() const
- {
- return GetData()->nAllocLength;
+ __forceinline PXSTR GetBuffer(int nMinBufferLength)
+ { return PrepareWrite(nMinBufferLength);
}
- XCHAR GetAt(int iChar) const
- {
- return m_pszData[iChar];
- }
- PXSTR GetBuffer()
- {
- CMStringData* pData = GetData();
- if (pData->IsShared())
- Fork(pData->nDataLength);
- return m_pszData;
+ __forceinline int GetLength() const
+ { return GetData()->nDataLength;
}
- PXSTR GetBuffer(int nMinBufferLength)
- {
- return PrepareWrite(nMinBufferLength);
- }
- PXSTR GetBufferSetLength(int nLength)
- {
- PXSTR pszBuffer = GetBuffer(nLength);
- SetLength(nLength);
- return pszBuffer;
+ __forceinline PCXSTR GetString() const
+ { return m_pszData;
}
- int GetLength() const
- {
- return GetData()->nDataLength;
- }
- PCXSTR GetString() const
- {
- return m_pszData;
- }
- PCXSTR GetTail() const
- {
- return m_pszData + GetData()->nDataLength;
- }
- 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);
+ __forceinline PCXSTR GetTail() const
+ { return m_pszData + GetData()->nDataLength;
}
- 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);
+ __forceinline bool IsEmpty() const
+ { return GetLength() == 0;
}
- 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;
+ __forceinline void Preallocate(int nLength)
+ { PrepareWrite(nLength);
}
- friend CMSimpleStringT __stdcall operator+(const CMSimpleStringT& str1, PCXSTR psz2)
- {
- CMSimpleStringT s;
- Concatenate(s, str1, str1.GetLength(), psz2, StringLength(psz2));
- return s;
+ __forceinline void ReleaseBufferSetLength(int nNewLength)
+ { SetLength(nNewLength);
}
- friend CMSimpleStringT __stdcall operator+(PCXSTR psz1, const CMSimpleStringT& str2)
- {
- CMSimpleStringT s;
- Concatenate(s, psz1, StringLength(psz1), str2, str2.GetLength());
- return s;
- }
+ void Append(PCXSTR pszSrc);
+ void Append(PCXSTR pszSrc, int nLength);
+ void AppendChar(XCHAR ch);
+ void Append(const CMSimpleStringT& strSrc);
- 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)
- {
- memcpy_s(pchDest, nDestLen * sizeof(XCHAR), pchSrc, nChars * sizeof(XCHAR));
- }
+ void Empty();
+ void FreeExtra();
- 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)
- {
- memmove_s(pchDest, nDestLen * sizeof(XCHAR), pchSrc, nChars * sizeof(XCHAR));
- }
- static int __stdcall StringLength(const char* psz)
- {
- if (psz == NULL)
- return(0);
+ PXSTR GetBuffer();
+ PXSTR GetBufferSetLength(int nLength);
- return (int(strlen(psz)));
- }
- static int __stdcall StringLength(const wchar_t* psz)
- {
- if (psz == NULL)
- return 0;
+ PXSTR LockBuffer();
+ void UnlockBuffer();
- return int(wcslen(psz));
- }
- static int __stdcall StringLengthN(const char* psz, size_t sizeInXChar)
- {
- if (psz == NULL)
- return 0;
+ void ReleaseBuffer(int nNewLength = -1);
- return int(strnlen(psz, sizeInXChar));
- }
- static int __stdcall StringLengthN(const wchar_t* psz, size_t sizeInXChar)
- {
- if (psz == NULL)
- return 0;
+ void Truncate(int nNewLength);
+ void SetAt(int iChar, XCHAR ch);
+ void SetString(PCXSTR pszSrc);
+ void SetString(PCXSTR pszSrc, int nLength);
- 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);
- }
+public:
+ friend CMSimpleStringT operator+(const CMSimpleStringT& str1, const CMSimpleStringT& str2);
+ friend CMSimpleStringT operator+(const CMSimpleStringT& str1, PCXSTR psz2);
+ friend CMSimpleStringT operator+(PCXSTR psz1, const CMSimpleStringT& str2);
+
+ static void __stdcall CopyChars(XCHAR* pchDest, const XCHAR* pchSrc, int nChars);
+ static void __stdcall CopyChars(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars);
+ static void __stdcall CopyCharsOverlapped(XCHAR* pchDest, const XCHAR* pchSrc, int nChars);
+ static void __stdcall CopyCharsOverlapped(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars);
+ static int __stdcall StringLength(const char* psz);
+ static int __stdcall StringLength(const wchar_t* psz);
+ static int __stdcall StringLengthN(const char* psz, size_t sizeInXChar);
+ static int __stdcall StringLengthN(const wchar_t* psz, size_t sizeInXChar);
+ static void __stdcall Concatenate(CMSimpleStringT& strResult, PCXSTR psz1, int nLength1, PCXSTR psz2, int nLength2);
+
// Implementation
private:
- void Attach(CMStringData* pData)
- {
- m_pszData = static_cast<PXSTR>(pData->data());
- }
- void Fork(int nLength)
- {
- CMStringData* pOldData = GetData();
- int nOldLength = pOldData->nDataLength;
- CMStringData* pNewData = mirstr_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<CMStringData *>(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 = mirstr_realloc(pOldData, nLength, sizeof(XCHAR));
- if (pNewData != NULL)
- Attach(pNewData);
+ __forceinline CMStringData* GetData() const
+ { return (reinterpret_cast<CMStringData *>(m_pszData)-1);
}
- 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;
- }
+ void Attach(CMStringData* pData);
+ void Fork(int nLength);
+ PXSTR PrepareWrite(int nLength);
+ void PrepareWrite2(int nLength);
+ void Reallocate(int nLength);
+ void SetLength(int nLength);
+ static CMStringData* __stdcall CloneData(CMStringData* pData);
-public :
- // typedef CStrBufT<BaseType> CStrBuf;
private:
PXSTR m_pszData;
};
@@ -702,9 +375,15 @@ public:
return reinterpret_cast< LPSTR >(_mbsrev(reinterpret_cast< unsigned char* >(psz)));
}
- static int __stdcall GetFormattedLength(LPCSTR pszFormat, va_list args);
+ static int __stdcall GetFormattedLength(LPCSTR pszFormat, va_list args)
+ {
+ return _vscprintf(pszFormat, args);
+ }
- static int __stdcall Format(LPSTR pszBuffer, size_t nlength, LPCSTR pszFormat, va_list args);
+ static int __stdcall Format(LPSTR pszBuffer, size_t nlength, LPCSTR pszFormat, va_list args)
+ {
+ return vsprintf_s(pszBuffer, nlength, pszFormat, args);
+ }
static int __stdcall GetBaseTypeLength(LPCSTR pszSrc)
{
@@ -938,7 +617,10 @@ public:
return _wcsrev(psz);
}
- static int __stdcall GetFormattedLength(LPCWSTR pszFormat, va_list args);
+ static int __stdcall GetFormattedLength(LPCWSTR pszFormat, va_list args)
+ {
+ return _vscwprintf(pszFormat, args);
+ }
static int __stdcall Format(LPWSTR pszBuffer, LPCWSTR pszFormat, va_list args)
{
@@ -948,7 +630,10 @@ public:
#pragma warning (pop)
}
- static int __stdcall Format(LPWSTR pszBuffer, size_t nLength, LPCWSTR pszFormat, va_list args);
+ static int __stdcall Format(LPWSTR pszBuffer, size_t nLength, LPCWSTR pszFormat, va_list args)
+ {
+ return _vsnwprintf(pszBuffer, nLength, pszFormat, args);
+ }
static int __stdcall GetBaseTypeLength(LPCSTR pszSrc)
{
@@ -1059,7 +744,7 @@ public:
};
template< typename BaseType, class StringTraits >
-class CMStringT : public CMSimpleStringT< BaseType >
+class MIR_CORE_EXPORT CMStringT : public CMSimpleStringT< BaseType >
{
public:
typedef CMSimpleStringT< BaseType> CThisSimpleString;
@@ -1071,1143 +756,236 @@ public:
typedef typename CThisSimpleString::PCYSTR PCYSTR;
public:
- CMStringT() : CThisSimpleString()
- {
- }
-
- static void __stdcall Construct(CMStringT* pString)
- {
- new(pString) CMStringT;
- }
+ CMStringT();
// Copy constructor
- CMStringT(const CMStringT& strSrc) :
- CThisSimpleString(strSrc)
- {
- }
+ CMStringT(const CMStringT& strSrc);
- CMStringT(const XCHAR* pszSrc) :
- CThisSimpleString()
- {
- *this = pszSrc;
- }
-
- CMStringT(CMStringDataFormat, const XCHAR* pszFormat, ...) :
- CThisSimpleString()
- {
- va_list args;
- va_start(args, pszFormat);
- FormatV(pszFormat, args);
- }
-
- CMStringT(const YCHAR* pszSrc) :
- CThisSimpleString()
- {
- *this = pszSrc;
- }
+ CMStringT(const XCHAR* pszSrc);
+ CMStringT(CMStringDataFormat, const XCHAR* pszFormat, ...);
+ CMStringT(const YCHAR* pszSrc);
+ CMStringT(const unsigned char* pszSrc);
- CMStringT(const unsigned char* pszSrc) :
- CThisSimpleString()
- {
- *this = reinterpret_cast<const char*>(pszSrc);
- }
+ CMStringT(char ch, int nLength = 1);
+ CMStringT(wchar_t ch, int nLength = 1);
- 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(const XCHAR* pch, int 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);
- }
- }
+ CMStringT(const YCHAR* pch, int nLength);
// Destructor
- ~CMStringT()
- {}
+ ~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;
- }
-
- 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;
- }
+ CMStringT& operator=(const CMStringT& strSrc);
+ CMStringT& operator=(PCXSTR pszSrc);
+ CMStringT& operator=(PCYSTR pszSrc);
+ CMStringT& operator=(const unsigned char* pszSrc);
+ CMStringT& operator=(char ch);
+ CMStringT& operator=(wchar_t ch);
+
+ CMStringT& operator+=(const CMStringT& str);
+ CMStringT& operator+=(const CThisSimpleString& str);
+ CMStringT& operator+=(PCXSTR pszSrc);
+ CMStringT& operator+=(PCYSTR pszSrc);
+ CMStringT& operator+=(char ch);
+ CMStringT& operator+=(unsigned char ch);
+ CMStringT& operator+=(wchar_t ch);
// 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);
- }
+ int Compare(PCXSTR psz) const;
+ int CompareNoCase(PCXSTR psz) const;
+ int Collate(PCXSTR psz) const;
+ int CollateNoCase(PCXSTR psz) const;
// 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();
- }
+ int Delete(int iIndex, int nCount = 1);
// 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;
- }
+ int Insert(int iIndex, XCHAR ch);
// 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;
- }
+ int Insert(int iIndex, PCXSTR psz);
// 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;
- }
+ int Replace(XCHAR chOld, XCHAR chNew);
// 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;
- }
+ int Replace(PCXSTR pszOld, PCXSTR pszNew);
// 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;
- for (size_t 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);
- }
- }
- }
+ int Remove(XCHAR chRemove);
- // return empty string, done tokenizing
- iStart = -1;
-
- return CMStringT();
- }
+ CMStringT Tokenize(PCXSTR pszTokens, int& iStart) const;
// 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());
- }
+ int Find(XCHAR ch, int iStart = 0) const;
// 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());
- }
+ int Find(PCXSTR pszSub, int iStart = 0) const;
// 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());
- }
+ int FindOneOf(PCXSTR pszCharSet) const;
// 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());
- }
+ int ReverseFind(XCHAR ch) const;
// 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;
- }
+ CMStringT& MakeUpper();
// 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;
- }
+ CMStringT& MakeLower();
// Reverse the string
- CMStringT& MakeReverse()
- {
- int nLength = this->GetLength();
- PXSTR pszBuffer = this->GetBuffer(nLength);
- StringTraits::StringReverse(pszBuffer);
- this->ReleaseBufferSetLength(nLength);
-
- return *this;
- }
+ CMStringT& MakeReverse();
// 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;
- }
+ CMStringT& TrimRight();
// 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;
- }
+ CMStringT& TrimLeft();
// Remove all leading and trailing whitespace
- CMStringT& Trim()
- {
- return TrimRight().TrimLeft();
- }
+ CMStringT& Trim();
// Remove all leading and trailing occurrences of character 'chTarget'
- CMStringT& Trim(XCHAR chTarget)
- {
- return TrimRight(chTarget).TrimLeft(chTarget);
- }
+ CMStringT& Trim(XCHAR 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);
- }
+ CMStringT& Trim(PCXSTR 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;
- }
+ CMStringT& TrimRight(XCHAR chTarget);
// 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;
- }
+ CMStringT& TrimRight(PCXSTR pszTargets);
// 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;
- }
+ CMStringT& TrimLeft(XCHAR chTarget);
// 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;
- }
+ CMStringT& TrimLeft(PCXSTR pszTargets);
// 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);
- }
+ void AnsiToOem();
// 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);
- }
+ void OemToAnsi();
// Very simple sub-string extraction
// Return the substring starting at index 'iFirst'
- CMStringT Mid(int iFirst) const
- {
- return Mid(iFirst, this->GetLength() - iFirst);
- }
+ CMStringT Mid(int iFirst) const;
// 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);
- }
+ CMStringT Mid(int iFirst, int nCount) const;
// 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);
- }
+ CMStringT Right(int nCount) const;
// 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);
- }
+ CMStringT Left(int nCount) const;
// Return the substring consisting of the leftmost characters in the set 'pszCharSet'
- CMStringT SpanIncluding(PCXSTR pszCharSet) const
- {
- return Left(StringTraits::StringSpanIncluding(this->GetString(), pszCharSet));
- }
+ CMStringT SpanIncluding(PCXSTR pszCharSet) const;
// 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));
- }
+ CMStringT SpanExcluding(PCXSTR pszCharSet) const;
// Format data using format string 'pszFormat'
- PCXSTR Format(PCXSTR pszFormat, ...)
- {
- va_list argList;
- va_start(argList, pszFormat);
- FormatV(pszFormat, argList);
- va_end(argList);
- return GetString();
- }
+ PCXSTR Format(PCXSTR pszFormat, ...);
+ PCXSTR FormatV(PCXSTR pszFormat, va_list args);
// Append formatted data using format string 'pszFormat'
- PCXSTR AppendFormat(PCXSTR pszFormat, ...)
- {
- va_list argList;
- va_start(argList, pszFormat);
- AppendFormatV(pszFormat, argList);
- va_end(argList);
- return GetString();
- }
-
- 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);
- }
-
- PCXSTR 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);
- return GetString();
- }
+ PCXSTR AppendFormat(PCXSTR pszFormat, ...);
+ void AppendFormatV(PCXSTR pszFormat, va_list args);
// 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;
- }
+ BSTR AllocSysString() const;
+ BSTR SetSysString(BSTR* pbstr) const;
// 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);
- }
+ BOOL GetEnvironmentVariable(PCXSTR pszVar);
- friend CMStringT __stdcall operator+(const CMStringT& str1, const CMStringT& str2)
- {
- CMStringT strResult;
+ friend bool __forceinline operator==(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) == 0; }
+ friend bool __forceinline operator==(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) == 0; }
+ friend bool __forceinline operator==(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) == 0; }
+ friend bool __forceinline operator==(const CMStringT& str1, PCYSTR psz2) { return str1 == CMStringT(psz2); }
+ friend bool __forceinline operator==(PCYSTR psz1, const CMStringT& str2) { return CMStringT(psz1) == str2; }
- Concatenate(strResult, str1, str1.GetLength(), str2, str2.GetLength());
+ friend bool __forceinline operator!=(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) != 0; }
+ friend bool __forceinline operator!=(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) != 0; }
+ friend bool __forceinline operator!=(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) != 0; }
+ friend bool __forceinline operator!=(const CMStringT& str1, PCYSTR psz2) { return str1 != CMStringT(psz2); }
+ friend bool __forceinline operator!=(PCYSTR psz1, const CMStringT& str2) { return CMStringT(psz1) != str2; }
- return strResult;
- }
+ friend bool __forceinline operator<(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) < 0; }
+ friend bool __forceinline operator<(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) < 0; }
+ friend bool __forceinline operator<(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) > 0; }
- friend CMStringT __stdcall operator+(const CMStringT& str1, PCXSTR psz2)
- {
- CMStringT strResult;
+ friend bool __forceinline operator>(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) > 0; }
+ friend bool __forceinline operator>(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) > 0; }
+ friend bool __forceinline operator>(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) < 0; }
- Concatenate(strResult, str1, str1.GetLength(), psz2, StringLength(psz2));
-
- return strResult;
- }
+ friend bool __forceinline operator<=(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) <= 0; }
+ friend bool __forceinline operator<=(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) <= 0; }
+ friend bool __forceinline operator<=(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) >= 0; }
- 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);
+ friend bool __forceinline operator>=(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) >= 0; }
+ friend bool __forceinline operator>=(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) >= 0; }
+ friend bool __forceinline operator>=(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) <= 0; }
- 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);
+ friend bool __forceinline operator==(XCHAR ch1, const CMStringT& str2) { return (str2.GetLength() == 1) && (str2[0] == ch1); }
+ friend bool __forceinline operator==(const CMStringT& str1, XCHAR ch2) { return (str1.GetLength() == 1) && (str1[0] == ch2); }
- 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 __forceinline operator!=(XCHAR ch1, const CMStringT& str2) { return (str2.GetLength() != 1) || (str2[0] != ch1); }
+ friend bool __forceinline operator!=(const CMStringT& str1, XCHAR ch2) { return (str1.GetLength() != 1) || (str1[0] != ch2); }
+};
- friend bool __stdcall operator>=(const CMStringT& str1, const CMStringT& str2)
- {
- return str1.Compare(str2) >= 0;
- }
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, const CMStringT<BaseType, StringTraits>& str2);
- friend bool __stdcall operator>=(const CMStringT& str1, PCXSTR psz2)
- {
- return str1.Compare(psz2) >= 0;
- }
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, typename CMStringT<BaseType, StringTraits>::PCXSTR psz2);
- friend bool __stdcall operator>=(PCXSTR psz1, const CMStringT& str2)
- {
- return str2.Compare(psz1) <= 0;
- }
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(typename CMStringT<BaseType, StringTraits>::PCXSTR psz1, const CMStringT<BaseType, StringTraits>& str2);
- friend bool __stdcall operator==(XCHAR ch1, const CMStringT& str2)
- {
- return (str2.GetLength() == 1) && (str2[0] == ch1);
- }
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, wchar_t ch2);
- friend bool __stdcall operator==(const CMStringT& str1, XCHAR ch2)
- {
- return (str1.GetLength() == 1) && (str1[0] == ch2);
- }
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, char ch2);
- friend bool __stdcall operator!=(XCHAR ch1, const CMStringT& str2)
- {
- return (str2.GetLength() != 1) || (str2[0] != ch1);
- }
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator + (wchar_t ch1, const CMStringT<BaseType, StringTraits>& str2);
- friend bool __stdcall operator!=(const CMStringT& str1, XCHAR ch2)
- {
- return (str1.GetLength() != 1) || (str1[0] != ch2);
- }
-};
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(char ch1, const CMStringT<BaseType, StringTraits>& str2);
typedef CMStringT< wchar_t, ChTraitsCRT< wchar_t > > CMStringW;
typedef CMStringT< char, ChTraitsCRT< char > > CMStringA;
-typedef CMStringT< TCHAR, ChTraitsCRT< TCHAR > > CMString;
-/////////////////////////////////////////////////////////////////////////////////////////
-// ChTraitsCRT<wchar_t>
-
-__forceinline int ChTraitsCRT<wchar_t>::GetFormattedLength(LPCWSTR pszFormat, va_list args)
-{
- return _vscwprintf(pszFormat, args);
-}
-
-__forceinline int ChTraitsCRT<wchar_t>::Format(LPWSTR pszBuffer, size_t nLength, LPCWSTR pszFormat, va_list args)
-{
- return _vsnwprintf(pszBuffer, nLength, pszFormat, args);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// ChTraitsCRT<char>
-
-__forceinline int ChTraitsCRT<char>::GetFormattedLength(LPCSTR pszFormat, va_list args)
-{
- return _vscprintf(pszFormat, args);
-}
-
-__forceinline int ChTraitsCRT<char>::Format(LPSTR pszBuffer, size_t nlength, LPCSTR pszFormat, va_list args)
-{
- return vsprintf_s(pszBuffer, nlength, pszFormat, args);
-}
+#ifdef _UNICODE
+ typedef CMStringW CMString;
+#else
+ typedef CMStringA CMString;
+#endif
#endif // M_STRING_H__
diff --git a/include/m_string.inl b/include/m_string.inl
new file mode 100644
index 0000000000..b42bc3b99b
--- /dev/null
+++ b/include/m_string.inl
@@ -0,0 +1,1476 @@
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org)
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#pragma once
+
+#ifndef M_STRING_INL__
+
+template<typename BaseType>
+CMSimpleStringT<BaseType>::CMSimpleStringT()
+{
+ CMStringData* pData = mirstr_getNil();
+ Attach(pData);
+}
+
+template<typename BaseType>
+CMSimpleStringT<BaseType>::CMSimpleStringT(const CMSimpleStringT& strSrc)
+{
+ CMStringData* pSrcData = strSrc.GetData();
+ CMStringData* pNewData = CloneData(pSrcData);
+ Attach(pNewData);
+}
+
+template<typename BaseType>
+CMSimpleStringT<BaseType>::CMSimpleStringT(PCXSTR pszSrc)
+{
+ int nLength = StringLength(pszSrc);
+ CMStringData* pData = mirstr_allocate(nLength, sizeof(XCHAR));
+ if (pData != NULL) {
+ Attach(pData);
+ SetLength(nLength);
+ CopyChars(m_pszData, nLength, pszSrc, nLength);
+ }
+}
+
+template<typename BaseType>
+CMSimpleStringT<BaseType>::CMSimpleStringT(const XCHAR* pchSrc, int nLength)
+{
+ CMStringData* pData = mirstr_allocate(nLength, sizeof(XCHAR));
+ if (pData != NULL) {
+ Attach(pData);
+ SetLength(nLength);
+ CopyChars(m_pszData, nLength, pchSrc, nLength);
+ }
+}
+
+template<typename BaseType>
+CMSimpleStringT<BaseType>::~CMSimpleStringT()
+{
+ CMStringData* pData = GetData();
+ pData->Release();
+}
+
+template<typename BaseType>
+CMSimpleStringT<BaseType>& CMSimpleStringT<BaseType>::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;
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Append(PCXSTR pszSrc)
+{
+ Append(pszSrc, StringLength(pszSrc));
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Append(PCXSTR pszSrc, int nLength)
+{
+ // See comment in SetString() about why we do this
+ UINT_PTR nOffset = UINT_PTR(pszSrc - GetString());
+
+ int 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 <= UINT_PTR(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);
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::AppendChar(XCHAR ch)
+{
+ UINT nOldLength = GetLength();
+ int nNewLength = nOldLength + 1;
+ PXSTR pszBuffer = GetBuffer(nNewLength);
+ pszBuffer[nOldLength] = ch;
+ ReleaseBufferSetLength(nNewLength);
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Append(const CMSimpleStringT<BaseType>& strSrc)
+{
+ Append(strSrc.GetString(), strSrc.GetLength());
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::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 = mirstr_getNil();
+ Attach(pNewData);
+ }
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::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 = mirstr_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);
+ }
+}
+
+template<typename BaseType>
+typename CMSimpleStringT<BaseType>::PXSTR CMSimpleStringT<BaseType>::GetBuffer()
+{
+ CMStringData* pData = GetData();
+ if (pData->IsShared())
+ Fork(pData->nDataLength);
+
+ return m_pszData;
+}
+
+template<typename BaseType>
+typename CMSimpleStringT<BaseType>::PXSTR CMSimpleStringT<BaseType>::GetBufferSetLength(int nLength)
+{
+ PXSTR pszBuffer = GetBuffer(nLength);
+ SetLength(nLength);
+
+ return pszBuffer;
+}
+
+template<typename BaseType>
+typename CMSimpleStringT<BaseType>::PXSTR CMSimpleStringT<BaseType>::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;
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::UnlockBuffer()
+{
+ CMStringData* pData = GetData();
+ pData->Unlock();
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::ReleaseBuffer(int nNewLength = -1)
+{
+ if (nNewLength == -1) {
+ int nAlloc = GetData()->nAllocLength;
+ nNewLength = StringLengthN(m_pszData, nAlloc);
+ }
+ SetLength(nNewLength);
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Truncate(int nNewLength)
+{
+ GetBuffer(nNewLength);
+ ReleaseBufferSetLength(nNewLength);
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::SetAt(int iChar, XCHAR ch)
+{
+ int nLength = GetLength();
+ PXSTR pszBuffer = GetBuffer();
+ pszBuffer[iChar] = ch;
+ ReleaseBufferSetLength(nLength);
+
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::SetString(PCXSTR pszSrc)
+{
+ SetString(pszSrc, StringLength(pszSrc));
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::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);
+ }
+}
+
+template<typename BaseType>
+typename CMSimpleStringT<BaseType> operator+(const CMSimpleStringT<BaseType>& str1, const CMSimpleStringT<BaseType>& str2)
+{
+ CMSimpleStringT s;
+ Concatenate(s, str1, str1.GetLength(), str2, str2.GetLength());
+ return s;
+}
+
+template<typename BaseType>
+typename CMSimpleStringT<BaseType> operator+(const CMSimpleStringT<BaseType>& str1, typename CMSimpleStringT<BaseType>::PCXSTR psz2)
+{
+ CMSimpleStringT s;
+ Concatenate(s, str1, str1.GetLength(), psz2, StringLength(psz2));
+ return s;
+}
+
+template<typename BaseType>
+CMSimpleStringT<BaseType> operator+(typename CMSimpleStringT<BaseType>::PCXSTR psz1, const CMSimpleStringT<BaseType>& str2)
+{
+ CMSimpleStringT s;
+ Concatenate(s, psz1, StringLength(psz1), str2, str2.GetLength());
+ return s;
+}
+
+template<typename BaseType>
+void __stdcall CMSimpleStringT<BaseType>::CopyChars(XCHAR* pchDest, const XCHAR* pchSrc, int nChars)
+{
+ #pragma warning (push)
+ #pragma warning(disable : 4996)
+ memcpy(pchDest, pchSrc, nChars * sizeof(XCHAR));
+ #pragma warning (pop)
+}
+
+template<typename BaseType>
+void __stdcall CMSimpleStringT<BaseType>::CopyChars(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars)
+{
+ memcpy_s(pchDest, nDestLen * sizeof(XCHAR), pchSrc, nChars * sizeof(XCHAR));
+}
+
+template<typename BaseType>
+void __stdcall CMSimpleStringT<BaseType>::CopyCharsOverlapped(XCHAR* pchDest, const XCHAR* pchSrc, int nChars)
+{
+ #pragma warning (push)
+ #pragma warning(disable : 4996)
+ memmove(pchDest, pchSrc, nChars * sizeof(XCHAR));
+ #pragma warning (pop)
+}
+
+template<typename BaseType>
+void __stdcall CMSimpleStringT<BaseType>::CopyCharsOverlapped(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars)
+{
+ memmove_s(pchDest, nDestLen * sizeof(XCHAR), pchSrc, nChars * sizeof(XCHAR));
+}
+
+template<typename BaseType>
+int __stdcall CMSimpleStringT<BaseType>::StringLength(const char* psz)
+{
+ if (psz == NULL)
+ return(0);
+
+ return (int(strlen(psz)));
+}
+
+template<typename BaseType>
+int __stdcall CMSimpleStringT<BaseType>::StringLength(const wchar_t* psz)
+{
+ if (psz == NULL)
+ return 0;
+
+ return int(wcslen(psz));
+}
+
+template<typename BaseType>
+int __stdcall CMSimpleStringT<BaseType>::StringLengthN(const char* psz, size_t sizeInXChar)
+{
+ if (psz == NULL)
+ return 0;
+
+ return int(strnlen(psz, sizeInXChar));
+}
+
+template<typename BaseType>
+int __stdcall CMSimpleStringT<BaseType>::StringLengthN(const wchar_t* psz, size_t sizeInXChar)
+{
+ if (psz == NULL)
+ return 0;
+
+ return int(wcsnlen(psz, sizeInXChar));
+}
+
+template<typename BaseType>
+void __stdcall CMSimpleStringT<BaseType>::Concatenate(CMSimpleStringT<BaseType>& 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);
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Attach(CMStringData* pData)
+{
+ m_pszData = static_cast<PXSTR>(pData->data());
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Fork(int nLength)
+{
+ CMStringData* pOldData = GetData();
+ int nOldLength = pOldData->nDataLength;
+ CMStringData* pNewData = mirstr_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);
+ }
+}
+
+template<typename BaseType>
+typename CMSimpleStringT<BaseType>::PXSTR CMSimpleStringT<BaseType>::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;
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::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);
+ }
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Reallocate(int nLength)
+{
+ CMStringData* pOldData = GetData();
+ if (pOldData->nAllocLength >= nLength || nLength <= 0)
+ return;
+
+ CMStringData* pNewData = mirstr_realloc(pOldData, nLength, sizeof(XCHAR));
+ if (pNewData != NULL)
+ Attach(pNewData);
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::SetLength(int nLength)
+{
+ GetData()->nDataLength = nLength;
+ m_pszData[nLength] = 0;
+}
+
+template<typename BaseType>
+CMStringData* __stdcall CMSimpleStringT<BaseType>::CloneData(CMStringData* pData)
+{
+ CMStringData* pNewData = NULL;
+
+ if (!pData->IsLocked()) {
+ pNewData = pData;
+ pNewData->AddRef();
+ }
+
+ return pNewData;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT() :
+ CThisSimpleString()
+{
+}
+
+// Copy constructor
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(const CMStringT<BaseType, StringTraits>& strSrc) :
+ CThisSimpleString(strSrc)
+{
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(const XCHAR* pszSrc) :
+ CThisSimpleString()
+{
+ *this = pszSrc;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(CMStringDataFormat, const XCHAR* pszFormat, ...) :
+ CThisSimpleString()
+{
+ va_list args;
+ va_start(args, pszFormat);
+ FormatV(pszFormat, args);
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(const YCHAR* pszSrc) :
+ CThisSimpleString()
+{
+ *this = pszSrc;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(const unsigned char* pszSrc) :
+ CThisSimpleString()
+{
+ *this = reinterpret_cast<const char*>(pszSrc);
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(char ch, int nLength = 1) :
+ CThisSimpleString()
+{
+ if (nLength > 0) {
+ PXSTR pszBuffer = this->GetBuffer(nLength);
+ StringTraits::FloodCharacters(XCHAR(ch), nLength, pszBuffer);
+ this->ReleaseBufferSetLength(nLength);
+ }
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::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;
+ }
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(const XCHAR* pch, int nLength) :
+ CThisSimpleString(pch, nLength)
+{
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::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
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::~CMStringT()
+{
+}
+
+// Assignment operators
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(const CMStringT& strSrc)
+{
+ CThisSimpleString::operator=(strSrc);
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(PCXSTR pszSrc)
+{
+ CThisSimpleString::operator=(pszSrc);
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::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;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(const unsigned char* pszSrc)
+{
+ return operator=(reinterpret_cast<const char*>(pszSrc));
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(char ch)
+{
+ char ach[2] = { ch, 0 };
+ return operator=(ach);
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(wchar_t ch)
+{
+ wchar_t ach[2] = { ch, 0 };
+ return operator=(ach);
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(const CMStringT& str)
+{
+ CThisSimpleString::operator+=(str);
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(const CThisSimpleString& str)
+{
+ CThisSimpleString::operator+=(str);
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(PCXSTR pszSrc)
+{
+ CThisSimpleString::operator+=(pszSrc);
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(PCYSTR pszSrc)
+{
+ CMStringT str(pszSrc);
+ return operator+=(str);
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(char ch)
+{
+ CThisSimpleString::operator+=(ch);
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(unsigned char ch)
+{
+ CThisSimpleString::operator+=(ch);
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(wchar_t ch)
+{
+ CThisSimpleString::operator+=(ch);
+ return *this;
+}
+
+// Comparison
+
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::Compare(PCXSTR psz) const
+{
+ return StringTraits::StringCompare(this->GetString(), psz);
+}
+
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::CompareNoCase(PCXSTR psz) const
+{
+ return StringTraits::StringCompareIgnore(this->GetString(), psz);
+}
+
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::Collate(PCXSTR psz) const
+{
+ return StringTraits::StringCollate(this->GetString(), psz);
+}
+
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::CollateNoCase(PCXSTR psz) const
+{
+ return StringTraits::StringCollateIgnore(this->GetString(), psz);
+}
+
+// Advanced manipulation
+
+// Delete 'nCount' characters, starting at index 'iIndex'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::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'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::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'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::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'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::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'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::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'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::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;
+ for (size_t 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;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::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'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::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'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::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'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::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'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::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
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::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
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::MakeLower()
+{
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer(nLength);
+ StringTraits::StringLowercase(pszBuffer, nLength + 1);
+ this->ReleaseBufferSetLength(nLength);
+
+ return *this;
+}
+
+// Reverse the string
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::MakeReverse()
+{
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer(nLength);
+ StringTraits::StringReverse(pszBuffer);
+ this->ReleaseBufferSetLength(nLength);
+
+ return *this;
+}
+
+// trimming
+
+// Remove all trailing whitespace
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::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
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::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
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::Trim()
+{
+ return TrimRight().TrimLeft();
+}
+
+// Remove all leading and trailing occurrences of character 'chTarget'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::Trim(XCHAR chTarget)
+{
+ return TrimRight(chTarget).TrimLeft(chTarget);
+}
+
+// Remove all leading and trailing occurrences of any of the characters in the string 'pszTargets'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::Trim(PCXSTR pszTargets)
+{
+ return TrimRight(pszTargets).TrimLeft(pszTargets);
+}
+
+// trimming anything (either side)
+
+// Remove all trailing occurrences of character 'chTarget'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::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'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::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'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::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'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::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
+template< typename BaseType, class StringTraits >
+void CMStringT<BaseType, StringTraits>::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
+template< typename BaseType, class StringTraits >
+void CMStringT<BaseType, StringTraits>::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'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::Mid(int iFirst) const
+{
+ return Mid(iFirst, this->GetLength() - iFirst);
+}
+
+// Return the substring starting at index 'iFirst', with length 'nCount'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::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
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::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
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::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'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::SpanIncluding(PCXSTR pszCharSet) const
+{
+ return Left(StringTraits::StringSpanIncluding(this->GetString(), pszCharSet));
+}
+
+// Return the substring consisting of the leftmost characters not in the set 'pszCharSet'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::SpanExcluding(PCXSTR pszCharSet) const
+{
+ return Left(StringTraits::StringSpanExcluding(this->GetString(), pszCharSet));
+}
+
+// Format data using format string 'pszFormat'
+template< typename BaseType, class StringTraits >
+typename CMStringT<BaseType, StringTraits>::PCXSTR CMStringT<BaseType, StringTraits>::Format(PCXSTR pszFormat, ...)
+{
+ va_list argList;
+ va_start(argList, pszFormat);
+ FormatV(pszFormat, argList);
+ va_end(argList);
+ return GetString();
+}
+
+// Append formatted data using format string 'pszFormat'
+template< typename BaseType, class StringTraits >
+typename CMStringT<BaseType, StringTraits>::PCXSTR CMStringT<BaseType, StringTraits>::AppendFormat(PCXSTR pszFormat, ...)
+{
+ va_list argList;
+ va_start(argList, pszFormat);
+ AppendFormatV(pszFormat, argList);
+ va_end(argList);
+ return GetString();
+}
+
+template< typename BaseType, class StringTraits >
+void CMStringT<BaseType, StringTraits>::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);
+}
+
+template< typename BaseType, class StringTraits >
+typename CMStringT<BaseType, StringTraits>::PCXSTR CMStringT<BaseType, StringTraits>::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);
+ return GetString();
+}
+
+// OLE BSTR support
+
+// allocate a BSTR containing a copy of the string
+template< typename BaseType, class StringTraits >
+BSTR CMStringT<BaseType, StringTraits>::AllocSysString() const
+{
+ return StringTraits::AllocSysString(this->GetString(), this->GetLength());
+}
+
+template< typename BaseType, class StringTraits >
+BSTR CMStringT<BaseType, StringTraits>::SetSysString(BSTR* pbstr) const
+{
+ StringTraits::ReAllocSysString(this->GetString(), pbstr, this->GetLength());
+ return *pbstr;
+}
+
+// Set the string to the value of environment variable 'pszVar'
+template< typename BaseType, class StringTraits >
+BOOL CMStringT<BaseType, StringTraits>::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;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, const CMStringT<BaseType, StringTraits>& str2)
+{
+ CMStringT<BaseType, StringTraits> strResult;
+ CMStringT<BaseType, StringTraits>::Concatenate(strResult, str1, str1.GetLength(), str2, str2.GetLength());
+ return strResult;
+}
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, typename CMStringT<BaseType, StringTraits>::PCXSTR psz2)
+{
+ CMStringT<BaseType, StringTraits> strResult;
+ CMStringT<BaseType, StringTraits>::Concatenate(strResult, str1, str1.GetLength(), psz2, CMStringT<BaseType, StringTraits>::StringLength(psz2));
+ return strResult;
+}
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(typename CMStringT<BaseType, StringTraits>::PCXSTR psz1, const CMStringT<BaseType, StringTraits>& str2)
+{
+ CMStringT<BaseType, StringTraits> strResult;
+ CMStringT<BaseType, StringTraits>::Concatenate(strResult, psz1, CMStringT<BaseType, StringTraits>::StringLength(psz1), str2, str2.GetLength());
+ return strResult;
+}
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, wchar_t ch2)
+{
+ CMStringT<BaseType, StringTraits> strResult;
+ typename CMStringT<BaseType, StringTraits>::XCHAR chTemp = typename CMStringT<BaseType, StringTraits>::XCHAR(ch2);
+ CMStringT<BaseType, StringTraits>::Concatenate(strResult, str1, str1.GetLength(), &chTemp, 1);
+ return strResult;
+}
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, char ch2)
+{
+ CMStringT<BaseType, StringTraits> strResult;
+ typename CMStringT<BaseType, StringTraits>::XCHAR chTemp = typename CMStringT<BaseType, StringTraits>::XCHAR(ch2);
+ CMStringT<BaseType, StringTraits>::Concatenate(strResult, str1, str1.GetLength(), &chTemp, 1);
+ return strResult;
+}
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(wchar_t ch1, const CMStringT<BaseType, StringTraits>& str2)
+{
+ CMStringT<BaseType, StringTraits> strResult;
+ typename CMStringT<BaseType, StringTraits>::XCHAR chTemp = typename CMStringT<BaseType, StringTraits>::XCHAR(ch1);
+ CMStringT<BaseType, StringTraits>::Concatenate(strResult, &chTemp, 1, str2, str2.GetLength());
+ return strResult;
+}
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(char ch1, const CMStringT<BaseType, StringTraits>& str2)
+{
+ CMStringT<BaseType, StringTraits> strResult;
+ typename CMStringT<BaseType, StringTraits>::XCHAR chTemp = typename CMStringT<BaseType, StringTraits>::XCHAR(ch1);
+ CMStringT<BaseType, StringTraits>::Concatenate(strResult, &chTemp, 1, str2, str2.GetLength());
+ return strResult;
+}
+
+#endif // M_STRING_INL__
diff --git a/make_core_def.cmd b/make_core_def.cmd
new file mode 100644
index 0000000000..b745d99c64
--- /dev/null
+++ b/make_core_def.cmd
@@ -0,0 +1,5 @@
+@echo off
+echo.
+.\tools\makedef\makedef.exe /IMAGE:bin12\debug\mir_core.dll /DEF:src\mir_core\src\mir_core.def
+echo.
+.\tools\makedef\makedef64.exe /IMAGE:bin12\debug64\mir_core.dll /DEF:src\mir_core\src\mir_core64.def \ No newline at end of file
diff --git a/protocols/VKontakte/src/misc.cpp b/protocols/VKontakte/src/misc.cpp
index 043c92acaa..756f74e190 100644
--- a/protocols/VKontakte/src/misc.cpp
+++ b/protocols/VKontakte/src/misc.cpp
@@ -874,7 +874,7 @@ CMString CVkProto::GetVkPhotoItem(JSONNODE *pPhoto, BBCSupport iBBC)
tszRes.AppendFormat(_T("\n\t[img]%s[/img]"), ptszPreviewLink ? ptszPreviewLink : (ptszLink ? ptszLink : _T("")));
CMString tszText = json_as_CMString(json_get(pPhoto, "text"));
if (!tszText.IsEmpty())
- tszRes += "\n" + tszText;
+ tszRes += _T("\n") + tszText;
return tszRes;
}
diff --git a/src/mir_core/mir_core_10.vcxproj b/src/mir_core/mir_core_10.vcxproj
index 2039a518f2..b84a3ef012 100644
--- a/src/mir_core/mir_core_10.vcxproj
+++ b/src/mir_core/mir_core_10.vcxproj
@@ -21,6 +21,7 @@
<ItemGroup>
<ClInclude Include="..\..\include\m_core.h" />
<ClInclude Include="..\..\include\m_database.h" />
+ <ClInclude Include="..\..\include\m_string.h" />
<ClInclude Include="..\..\include\m_system.h" />
<ClInclude Include="..\..\include\m_system_cpp.h" />
<ClInclude Include="src\commonheaders.h" />
@@ -91,6 +92,9 @@
<ClCompile Include="src\utils.cpp" />
<ClCompile Include="src\winver.cpp" />
</ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\include\m_string.inl" />
+ </ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>mir_core</ProjectName>
<ProjectGuid>{D9EFEA4B-B817-4DE1-BD62-68A5DB8F5F60}</ProjectGuid>
@@ -199,7 +203,7 @@
<AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
- <ModuleDefinitionFile>src\mir_core.def</ModuleDefinitionFile>
+ <ModuleDefinitionFile>src\mir_core64.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName)64.lib</ImportLibrary>
@@ -275,7 +279,7 @@
<AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
- <ModuleDefinitionFile>src\mir_core.def</ModuleDefinitionFile>
+ <ModuleDefinitionFile>src\mir_core64.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
diff --git a/src/mir_core/mir_core_10.vcxproj.filters b/src/mir_core/mir_core_10.vcxproj.filters
index 1aa55b2dfd..59ed6773fb 100644
--- a/src/mir_core/mir_core_10.vcxproj.filters
+++ b/src/mir_core/mir_core_10.vcxproj.filters
@@ -156,5 +156,13 @@
<ClInclude Include="..\..\include\m_system_cpp.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\include\m_string.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\include\m_string.inl">
+ <Filter>Header Files</Filter>
+ </None>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/mir_core/mir_core_12.vcxproj b/src/mir_core/mir_core_12.vcxproj
index 26b4ed5650..6ab9a405a8 100644
--- a/src/mir_core/mir_core_12.vcxproj
+++ b/src/mir_core/mir_core_12.vcxproj
@@ -23,6 +23,7 @@
<ClInclude Include="..\..\include\m_database.h" />
<ClInclude Include="..\..\include\m_json.h" />
<ClInclude Include="..\..\include\m_metacontacts.h" />
+ <ClInclude Include="..\..\include\m_string.h" />
<ClInclude Include="..\..\include\m_system.h" />
<ClInclude Include="..\..\include\m_system_cpp.h" />
<ClInclude Include="src\commonheaders.h" />
@@ -89,6 +90,9 @@
<ClCompile Include="src\utils.cpp" />
<ClCompile Include="src\winver.cpp" />
</ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\include\m_string.inl" />
+ </ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>mir_core</ProjectName>
<ProjectGuid>{D9EFEA4B-B817-4DE1-BD62-68A5DB8F5F60}</ProjectGuid>
@@ -202,7 +206,7 @@
<AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
- <ModuleDefinitionFile>src\mir_core.def</ModuleDefinitionFile>
+ <ModuleDefinitionFile>src\mir_core64.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName)64.lib</ImportLibrary>
@@ -277,7 +281,7 @@
<AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
- <ModuleDefinitionFile>src\mir_core.def</ModuleDefinitionFile>
+ <ModuleDefinitionFile>src\mir_core64.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
diff --git a/src/mir_core/mir_core_12.vcxproj.filters b/src/mir_core/mir_core_12.vcxproj.filters
index 357e77b79c..832c3f3b5f 100644
--- a/src/mir_core/mir_core_12.vcxproj.filters
+++ b/src/mir_core/mir_core_12.vcxproj.filters
@@ -156,5 +156,13 @@
<ClInclude Include="src\json\NumberToString.h">
<Filter>Source Files\json</Filter>
</ClInclude>
+ <ClInclude Include="..\..\include\m_string.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\include\m_string.inl">
+ <Filter>Header Files</Filter>
+ </None>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/mir_core/src/commonheaders.h b/src/mir_core/src/commonheaders.h
index cb5fea518a..5a8d414682 100644
--- a/src/mir_core/src/commonheaders.h
+++ b/src/mir_core/src/commonheaders.h
@@ -63,4 +63,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <m_ssl.h>
#include <m_xml.h>
+#include <m_string.inl>
+
void GetDefaultLang(); \ No newline at end of file
diff --git a/src/mir_core/src/mir_core.def b/src/mir_core/src/mir_core.def
index 312540f081..0e3d5e0eae 100644
--- a/src/mir_core/src/mir_core.def
+++ b/src/mir_core/src/mir_core.def
@@ -280,3 +280,263 @@ mir_strcmp @277
mir_strcmpi @278
mir_wstrcmp @279
mir_wstrcmpi @280
+??$?HDV?$ChTraitsCRT@D@@@@YG?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@ABV0@0@Z @281 NONAME
+??$?HDV?$ChTraitsCRT@D@@@@YG?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@ABV0@D@Z @282 NONAME
+??$?HDV?$ChTraitsCRT@D@@@@YG?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@ABV0@PBD@Z @283 NONAME
+??$?HDV?$ChTraitsCRT@D@@@@YG?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@ABV0@_W@Z @284 NONAME
+??$?HDV?$ChTraitsCRT@D@@@@YG?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@DABV0@@Z @285 NONAME
+??$?HDV?$ChTraitsCRT@D@@@@YG?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@PBDABV0@@Z @286 NONAME
+??$?HDV?$ChTraitsCRT@D@@@@YG?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@_WABV0@@Z @287 NONAME
+??$?H_WV?$ChTraitsCRT@_W@@@@YG?AV?$CMStringT@_WV?$ChTraitsCRT@_W@@@@ABV0@0@Z @288 NONAME
+??$?H_WV?$ChTraitsCRT@_W@@@@YG?AV?$CMStringT@_WV?$ChTraitsCRT@_W@@@@ABV0@D@Z @289 NONAME
+??$?H_WV?$ChTraitsCRT@_W@@@@YG?AV?$CMStringT@_WV?$ChTraitsCRT@_W@@@@ABV0@PB_W@Z @290 NONAME
+??$?H_WV?$ChTraitsCRT@_W@@@@YG?AV?$CMStringT@_WV?$ChTraitsCRT@_W@@@@ABV0@_W@Z @291 NONAME
+??$?H_WV?$ChTraitsCRT@_W@@@@YG?AV?$CMStringT@_WV?$ChTraitsCRT@_W@@@@DABV0@@Z @292 NONAME
+??$?H_WV?$ChTraitsCRT@_W@@@@YG?AV?$CMStringT@_WV?$ChTraitsCRT@_W@@@@PB_WABV0@@Z @293 NONAME
+??$?H_WV?$ChTraitsCRT@_W@@@@YG?AV?$CMStringT@_WV?$ChTraitsCRT@_W@@@@_WABV0@@Z @294 NONAME
+??0?$CMSimpleStringT@D@@QAE@ABV0@@Z @295 NONAME
+??0?$CMSimpleStringT@D@@QAE@PBD@Z @296 NONAME
+??0?$CMSimpleStringT@D@@QAE@PBDH@Z @297 NONAME
+??0?$CMSimpleStringT@D@@QAE@XZ @298 NONAME
+??0?$CMSimpleStringT@_W@@QAE@ABV0@@Z @299 NONAME
+??0?$CMSimpleStringT@_W@@QAE@PB_W@Z @300 NONAME
+??0?$CMSimpleStringT@_W@@QAE@PB_WH@Z @301 NONAME
+??0?$CMSimpleStringT@_W@@QAE@XZ @302 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QAA@W4CMStringDataFormat@@PBDZZ @303 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QAE@ABV0@@Z @304 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QAE@DH@Z @305 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QAE@PBD@Z @306 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QAE@PBDH@Z @307 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QAE@PBE@Z @308 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QAE@PB_W@Z @309 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QAE@PB_WH@Z @310 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QAE@XZ @311 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QAE@_WH@Z @312 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAA@W4CMStringDataFormat@@PB_WZZ @313 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAE@ABV0@@Z @314 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAE@DH@Z @315 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAE@PBD@Z @316 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAE@PBDH@Z @317 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAE@PBE@Z @318 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAE@PB_W@Z @319 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAE@PB_WH@Z @320 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAE@XZ @321 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAE@_WH@Z @322 NONAME
+??1?$CMSimpleStringT@D@@QAE@XZ @323 NONAME
+??1?$CMSimpleStringT@_W@@QAE@XZ @324 NONAME
+??1?$CMStringT@DV?$ChTraitsCRT@D@@@@QAE@XZ @325 NONAME
+??1?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAE@XZ @326 NONAME
+??4?$CMSimpleStringT@D@@QAEAAV0@ABV0@@Z @327 NONAME
+??4?$CMSimpleStringT@D@@QAEAAV0@PBD@Z @328 NONAME
+??4?$CMSimpleStringT@_W@@QAEAAV0@ABV0@@Z @329 NONAME
+??4?$CMSimpleStringT@_W@@QAEAAV0@PB_W@Z @330 NONAME
+??4?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV0@ABV0@@Z @331 NONAME
+??4?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV0@D@Z @332 NONAME
+??4?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV0@PBD@Z @333 NONAME
+??4?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV0@PBE@Z @334 NONAME
+??4?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV0@PB_W@Z @335 NONAME
+??4?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV0@_W@Z @336 NONAME
+??4?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV0@ABV0@@Z @337 NONAME
+??4?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV0@D@Z @338 NONAME
+??4?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV0@PBD@Z @339 NONAME
+??4?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV0@PBE@Z @340 NONAME
+??4?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV0@PB_W@Z @341 NONAME
+??4?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV0@_W@Z @342 NONAME
+??A?$CMSimpleStringT@D@@QBEDH@Z @343 NONAME
+??A?$CMSimpleStringT@_W@@QBE_WH@Z @344 NONAME
+??B?$CMSimpleStringT@D@@QAEAAV0@XZ @345 NONAME
+??B?$CMSimpleStringT@D@@QBEPBDXZ @346 NONAME
+??B?$CMSimpleStringT@_W@@QAEAAV0@XZ @347 NONAME
+??B?$CMSimpleStringT@_W@@QBEPB_WXZ @348 NONAME
+??Y?$CMSimpleStringT@D@@QAEAAV0@ABV0@@Z @349 NONAME
+??Y?$CMSimpleStringT@D@@QAEAAV0@D@Z @350 NONAME
+??Y?$CMSimpleStringT@D@@QAEAAV0@E@Z @351 NONAME
+??Y?$CMSimpleStringT@D@@QAEAAV0@PBD@Z @352 NONAME
+??Y?$CMSimpleStringT@D@@QAEAAV0@_W@Z @353 NONAME
+??Y?$CMSimpleStringT@_W@@QAEAAV0@ABV0@@Z @354 NONAME
+??Y?$CMSimpleStringT@_W@@QAEAAV0@D@Z @355 NONAME
+??Y?$CMSimpleStringT@_W@@QAEAAV0@E@Z @356 NONAME
+??Y?$CMSimpleStringT@_W@@QAEAAV0@PB_W@Z @357 NONAME
+??Y?$CMSimpleStringT@_W@@QAEAAV0@_W@Z @358 NONAME
+??Y?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV0@ABV0@@Z @359 NONAME
+??Y?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV0@ABV?$CMSimpleStringT@D@@@Z @360 NONAME
+??Y?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV0@D@Z @361 NONAME
+??Y?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV0@E@Z @362 NONAME
+??Y?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV0@PBD@Z @363 NONAME
+??Y?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV0@PB_W@Z @364 NONAME
+??Y?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV0@_W@Z @365 NONAME
+??Y?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV0@ABV0@@Z @366 NONAME
+??Y?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV0@ABV?$CMSimpleStringT@_W@@@Z @367 NONAME
+??Y?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV0@D@Z @368 NONAME
+??Y?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV0@E@Z @369 NONAME
+??Y?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV0@PBD@Z @370 NONAME
+??Y?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV0@PB_W@Z @371 NONAME
+??Y?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV0@_W@Z @372 NONAME
+?AllocSysString@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBEPA_WXZ @373 NONAME
+?AllocSysString@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBEPA_WXZ @374 NONAME
+?Append@?$CMSimpleStringT@D@@QAEXABV1@@Z @375 NONAME
+?Append@?$CMSimpleStringT@D@@QAEXPBD@Z @376 NONAME
+?Append@?$CMSimpleStringT@D@@QAEXPBDH@Z @377 NONAME
+?Append@?$CMSimpleStringT@_W@@QAEXABV1@@Z @378 NONAME
+?Append@?$CMSimpleStringT@_W@@QAEXPB_W@Z @379 NONAME
+?Append@?$CMSimpleStringT@_W@@QAEXPB_WH@Z @380 NONAME
+?AppendChar@?$CMSimpleStringT@D@@QAEXD@Z @381 NONAME
+?AppendChar@?$CMSimpleStringT@_W@@QAEX_W@Z @382 NONAME
+?AppendFormat@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAAPBDPBDZZ @383 NONAME
+?AppendFormat@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAAPB_WPB_WZZ @384 NONAME
+?AppendFormatV@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEXPBDPAD@Z @385 NONAME
+?AppendFormatV@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEXPB_WPAD@Z @386 NONAME
+?Attach@?$CMSimpleStringT@D@@AAEXPAUCMStringData@@@Z @387 NONAME
+?Attach@?$CMSimpleStringT@_W@@AAEXPAUCMStringData@@@Z @388 NONAME
+?CharToOemA@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEXXZ @389 NONAME
+?CharToOemA@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEXXZ @390 NONAME
+?CloneData@?$CMSimpleStringT@D@@CGPAUCMStringData@@PAU2@@Z @391 NONAME
+?CloneData@?$CMSimpleStringT@_W@@CGPAUCMStringData@@PAU2@@Z @392 NONAME
+?Collate@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBEHPBD@Z @393 NONAME
+?Collate@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBEHPB_W@Z @394 NONAME
+?CollateNoCase@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBEHPBD@Z @395 NONAME
+?CollateNoCase@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBEHPB_W@Z @396 NONAME
+?Compare@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBEHPBD@Z @397 NONAME
+?Compare@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBEHPB_W@Z @398 NONAME
+?CompareNoCase@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBEHPBD@Z @399 NONAME
+?CompareNoCase@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBEHPB_W@Z @400 NONAME
+?Concatenate@?$CMSimpleStringT@D@@SGXAAV1@PBDH1H@Z @401 NONAME
+?Concatenate@?$CMSimpleStringT@_W@@SGXAAV1@PB_WH1H@Z @402 NONAME
+?CopyChars@?$CMSimpleStringT@D@@SGXPADIPBDH@Z @403 NONAME
+?CopyChars@?$CMSimpleStringT@D@@SGXPADPBDH@Z @404 NONAME
+?CopyChars@?$CMSimpleStringT@_W@@SGXPA_WIPB_WH@Z @405 NONAME
+?CopyChars@?$CMSimpleStringT@_W@@SGXPA_WPB_WH@Z @406 NONAME
+?CopyCharsOverlapped@?$CMSimpleStringT@D@@SGXPADIPBDH@Z @407 NONAME
+?CopyCharsOverlapped@?$CMSimpleStringT@D@@SGXPADPBDH@Z @408 NONAME
+?CopyCharsOverlapped@?$CMSimpleStringT@_W@@SGXPA_WIPB_WH@Z @409 NONAME
+?CopyCharsOverlapped@?$CMSimpleStringT@_W@@SGXPA_WPB_WH@Z @410 NONAME
+?Delete@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEHHH@Z @411 NONAME
+?Delete@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEHHH@Z @412 NONAME
+?Empty@?$CMSimpleStringT@D@@QAEXXZ @413 NONAME
+?Empty@?$CMSimpleStringT@_W@@QAEXXZ @414 NONAME
+?Find@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBEHDH@Z @415 NONAME
+?Find@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBEHPBDH@Z @416 NONAME
+?Find@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBEHPB_WH@Z @417 NONAME
+?Find@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBEH_WH@Z @418 NONAME
+?FindOneOf@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBEHPBD@Z @419 NONAME
+?FindOneOf@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBEHPB_W@Z @420 NONAME
+?Fork@?$CMSimpleStringT@D@@AAEXH@Z @421 NONAME
+?Fork@?$CMSimpleStringT@_W@@AAEXH@Z @422 NONAME
+?Format@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAAPBDPBDZZ @423 NONAME
+?Format@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAAPB_WPB_WZZ @424 NONAME
+?FormatV@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEPBDPBDPAD@Z @425 NONAME
+?FormatV@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEPB_WPB_WPAD@Z @426 NONAME
+?FreeExtra@?$CMSimpleStringT@D@@QAEXXZ @427 NONAME
+?FreeExtra@?$CMSimpleStringT@_W@@QAEXXZ @428 NONAME
+?GetAllocLength@?$CMSimpleStringT@D@@QBEHXZ @429 NONAME
+?GetAllocLength@?$CMSimpleStringT@_W@@QBEHXZ @430 NONAME
+?GetAt@?$CMSimpleStringT@D@@QBEDH@Z @431 NONAME
+?GetAt@?$CMSimpleStringT@_W@@QBE_WH@Z @432 NONAME
+?GetBuffer@?$CMSimpleStringT@D@@QAEPADH@Z @433 NONAME
+?GetBuffer@?$CMSimpleStringT@D@@QAEPADXZ @434 NONAME
+?GetBuffer@?$CMSimpleStringT@_W@@QAEPA_WH@Z @435 NONAME
+?GetBuffer@?$CMSimpleStringT@_W@@QAEPA_WXZ @436 NONAME
+?GetBufferSetLength@?$CMSimpleStringT@D@@QAEPADH@Z @437 NONAME
+?GetBufferSetLength@?$CMSimpleStringT@_W@@QAEPA_WH@Z @438 NONAME
+?GetData@?$CMSimpleStringT@D@@ABEPAUCMStringData@@XZ @439 NONAME
+?GetData@?$CMSimpleStringT@_W@@ABEPAUCMStringData@@XZ @440 NONAME
+?GetEnvironmentVariableW@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEHPBD@Z @441 NONAME
+?GetEnvironmentVariableW@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEHPB_W@Z @442 NONAME
+?GetLength@?$CMSimpleStringT@D@@QBEHXZ @443 NONAME
+?GetLength@?$CMSimpleStringT@_W@@QBEHXZ @444 NONAME
+?GetString@?$CMSimpleStringT@D@@QBEPBDXZ @445 NONAME
+?GetString@?$CMSimpleStringT@_W@@QBEPB_WXZ @446 NONAME
+?GetTail@?$CMSimpleStringT@D@@QBEPBDXZ @447 NONAME
+?GetTail@?$CMSimpleStringT@_W@@QBEPB_WXZ @448 NONAME
+?Insert@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEHHD@Z @449 NONAME
+?Insert@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEHHPBD@Z @450 NONAME
+?Insert@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEHHPB_W@Z @451 NONAME
+?Insert@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEHH_W@Z @452 NONAME
+?IsEmpty@?$CMSimpleStringT@D@@QBE_NXZ @453 NONAME
+?IsEmpty@?$CMSimpleStringT@_W@@QBE_NXZ @454 NONAME
+?Left@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBE?AV1@H@Z @455 NONAME
+?Left@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBE?AV1@H@Z @456 NONAME
+?LockBuffer@?$CMSimpleStringT@D@@QAEPADXZ @457 NONAME
+?LockBuffer@?$CMSimpleStringT@_W@@QAEPA_WXZ @458 NONAME
+?MakeLower@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV1@XZ @459 NONAME
+?MakeLower@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV1@XZ @460 NONAME
+?MakeReverse@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV1@XZ @461 NONAME
+?MakeReverse@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV1@XZ @462 NONAME
+?MakeUpper@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV1@XZ @463 NONAME
+?MakeUpper@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV1@XZ @464 NONAME
+?Mid@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBE?AV1@H@Z @465 NONAME
+?Mid@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBE?AV1@HH@Z @466 NONAME
+?Mid@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBE?AV1@H@Z @467 NONAME
+?Mid@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBE?AV1@HH@Z @468 NONAME
+?OemToCharA@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEXXZ @469 NONAME
+?OemToCharA@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEXXZ @470 NONAME
+?Preallocate@?$CMSimpleStringT@D@@QAEXH@Z @471 NONAME
+?Preallocate@?$CMSimpleStringT@_W@@QAEXH@Z @472 NONAME
+?PrepareWrite2@?$CMSimpleStringT@D@@AAEXH@Z @473 NONAME
+?PrepareWrite2@?$CMSimpleStringT@_W@@AAEXH@Z @474 NONAME
+?PrepareWrite@?$CMSimpleStringT@D@@AAEPADH@Z @475 NONAME
+?PrepareWrite@?$CMSimpleStringT@_W@@AAEPA_WH@Z @476 NONAME
+?Reallocate@?$CMSimpleStringT@D@@AAEXH@Z @477 NONAME
+?Reallocate@?$CMSimpleStringT@_W@@AAEXH@Z @478 NONAME
+?ReleaseBuffer@?$CMSimpleStringT@D@@QAEXH@Z @479 NONAME
+?ReleaseBuffer@?$CMSimpleStringT@_W@@QAEXH@Z @480 NONAME
+?ReleaseBufferSetLength@?$CMSimpleStringT@D@@QAEXH@Z @481 NONAME
+?ReleaseBufferSetLength@?$CMSimpleStringT@_W@@QAEXH@Z @482 NONAME
+?Remove@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEHD@Z @483 NONAME
+?Remove@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEH_W@Z @484 NONAME
+?Replace@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEHDD@Z @485 NONAME
+?Replace@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEHPBD0@Z @486 NONAME
+?Replace@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEHPB_W0@Z @487 NONAME
+?Replace@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEH_W0@Z @488 NONAME
+?ReverseFind@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBEHD@Z @489 NONAME
+?ReverseFind@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBEH_W@Z @490 NONAME
+?Right@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBE?AV1@H@Z @491 NONAME
+?Right@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBE?AV1@H@Z @492 NONAME
+?SetAt@?$CMSimpleStringT@D@@QAEXHD@Z @493 NONAME
+?SetAt@?$CMSimpleStringT@_W@@QAEXH_W@Z @494 NONAME
+?SetLength@?$CMSimpleStringT@D@@AAEXH@Z @495 NONAME
+?SetLength@?$CMSimpleStringT@_W@@AAEXH@Z @496 NONAME
+?SetString@?$CMSimpleStringT@D@@QAEXPBD@Z @497 NONAME
+?SetString@?$CMSimpleStringT@D@@QAEXPBDH@Z @498 NONAME
+?SetString@?$CMSimpleStringT@_W@@QAEXPB_W@Z @499 NONAME
+?SetString@?$CMSimpleStringT@_W@@QAEXPB_WH@Z @500 NONAME
+?SetSysString@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBEPA_WPAPA_W@Z @501 NONAME
+?SetSysString@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBEPA_WPAPA_W@Z @502 NONAME
+?SpanExcluding@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBE?AV1@PBD@Z @503 NONAME
+?SpanExcluding@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBE?AV1@PB_W@Z @504 NONAME
+?SpanIncluding@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBE?AV1@PBD@Z @505 NONAME
+?SpanIncluding@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBE?AV1@PB_W@Z @506 NONAME
+?StringLength@?$CMSimpleStringT@D@@SGHPBD@Z @507 NONAME
+?StringLength@?$CMSimpleStringT@D@@SGHPB_W@Z @508 NONAME
+?StringLength@?$CMSimpleStringT@_W@@SGHPBD@Z @509 NONAME
+?StringLength@?$CMSimpleStringT@_W@@SGHPB_W@Z @510 NONAME
+?StringLengthN@?$CMSimpleStringT@D@@SGHPBDI@Z @511 NONAME
+?StringLengthN@?$CMSimpleStringT@D@@SGHPB_WI@Z @512 NONAME
+?StringLengthN@?$CMSimpleStringT@_W@@SGHPBDI@Z @513 NONAME
+?StringLengthN@?$CMSimpleStringT@_W@@SGHPB_WI@Z @514 NONAME
+?Tokenize@?$CMStringT@DV?$ChTraitsCRT@D@@@@QBE?AV1@PBDAAH@Z @515 NONAME
+?Tokenize@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QBE?AV1@PB_WAAH@Z @516 NONAME
+?Trim@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV1@D@Z @517 NONAME
+?Trim@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV1@PBD@Z @518 NONAME
+?Trim@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV1@XZ @519 NONAME
+?Trim@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV1@PB_W@Z @520 NONAME
+?Trim@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV1@XZ @521 NONAME
+?Trim@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV1@_W@Z @522 NONAME
+?TrimLeft@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV1@D@Z @523 NONAME
+?TrimLeft@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV1@PBD@Z @524 NONAME
+?TrimLeft@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV1@XZ @525 NONAME
+?TrimLeft@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV1@PB_W@Z @526 NONAME
+?TrimLeft@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV1@XZ @527 NONAME
+?TrimLeft@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV1@_W@Z @528 NONAME
+?TrimRight@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV1@D@Z @529 NONAME
+?TrimRight@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV1@PBD@Z @530 NONAME
+?TrimRight@?$CMStringT@DV?$ChTraitsCRT@D@@@@QAEAAV1@XZ @531 NONAME
+?TrimRight@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV1@PB_W@Z @532 NONAME
+?TrimRight@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV1@XZ @533 NONAME
+?TrimRight@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QAEAAV1@_W@Z @534 NONAME
+?Truncate@?$CMSimpleStringT@D@@QAEXH@Z @535 NONAME
+?Truncate@?$CMSimpleStringT@_W@@QAEXH@Z @536 NONAME
+?UnlockBuffer@?$CMSimpleStringT@D@@QAEXXZ @537 NONAME
+?UnlockBuffer@?$CMSimpleStringT@_W@@QAEXXZ @538 NONAME
+?c_str@?$CMSimpleStringT@D@@QBEPBDXZ @539 NONAME
+?c_str@?$CMSimpleStringT@_W@@QBEPB_WXZ @540 NONAME
diff --git a/src/mir_core/src/mir_core64.def b/src/mir_core/src/mir_core64.def
new file mode 100644
index 0000000000..1303583f1e
--- /dev/null
+++ b/src/mir_core/src/mir_core64.def
@@ -0,0 +1,542 @@
+LIBRARY mir_core
+
+EXPORTS
+CallContactService @1
+CallProtoService @2
+Langpack_LookupUuid @3
+Langpack_MarkPluginLoaded @4
+CallFunctionAsync @5
+CallPluginEventHook @7
+CallService @8
+CallServiceSync @9
+CreateDirectoryTree @10
+CreateDirectoryTreeW @11
+CreateHookableEvent @12
+CreatePathToFile @13
+CreatePathToFileW @14
+CreateServiceFunction @15
+CreateServiceFunctionObj @16
+CreateServiceFunctionObjParam @17
+CreateServiceFunctionParam @18
+DestroyHookableEvent @19
+DestroyServiceFunction @20
+GetExceptionFilter @21
+GetInstByAddress @22
+HookEvent @23
+HookEventMessage @24
+HookEventObj @25
+HookEventObjParam @26
+HookEventParam @27
+KillModuleEventHooks @28
+KillModuleServices @29
+KillObjectEventHooks @30
+KillObjectServices @31
+KillObjectThreads @32
+Langpack_SortDuplicates @33
+Langpack_GetDefaultCodePage @34
+Langpack_GetDefaultLocale @35
+Langpack_PcharToTchar @36
+List_Copy @37
+List_Create @38
+List_Destroy @39
+List_Find @40
+List_GetIndex @41
+List_IndexOf @42
+List_Insert @43
+List_InsertPtr @44
+List_ObjCopy @45
+List_Remove @46
+List_RemovePtr @47
+LoadLangPack @48
+LoadLangPackModule @49
+NotifyEventHooks @50
+PathToAbsolute @51
+PathToAbsoluteW @52
+PathToRelative @53
+PathToRelativeW @54
+RegisterModule @55
+ReloadLangpack @56
+ServiceExists @57
+SetExceptionFilter @58
+SetHookDefaultForHookableEvent @59
+Thread_Pop @60
+Thread_Push @61
+Thread_Wait @62
+TranslateA_LP @63
+TranslateDialog_LP @64
+TranslateMenu_LP @65
+TranslateW_LP @66
+Ucs2toUtf8Len @67
+UnhookEvent @68
+UnregisterModule @69
+Utf8Decode @70
+Utf8DecodeCP @71
+Utf8DecodeW @72
+Utf8Encode @73
+Utf8EncodeCP @74
+Utf8EncodeW @75
+forkthread @76
+forkthreadex @77
+ltrim @78
+ltrimp @79
+mir_a2u @80
+mir_a2u_cp @81
+mir_alloc @82
+mir_calloc @83
+mir_free @84
+mir_hash @85
+mir_md5_append @86
+mir_md5_finish @87
+mir_md5_hash @88
+mir_md5_init @89
+mir_realloc @90
+mir_sha1_append @91
+mir_sha1_finish @92
+mir_sha1_hash @93
+mir_sha1_init @94
+mir_strdup @95
+mir_strndup @96
+mir_u2a @97
+mir_u2a_cp @98
+mir_vsnprintf @99
+mir_vsnwprintf @100
+mir_wstrdup @101
+rtrim @102
+wildcmp @103
+rtrimw @104
+mir_snprintf @105
+mir_snwprintf @106
+db_unset @107
+db_free @108
+db_get @109
+db_get_b @110
+db_get_dw @111
+db_get_s @112
+db_get_sa @113
+db_get_w @114
+db_get_wsa @115
+db_set_b @116
+db_set_blob @117
+db_set_dw @118
+db_set_s @119
+db_set_utf @120
+db_set_w @121
+db_set_ws @122
+UnloadCoreModule @123
+Thread_SetName @124
+replaceStr @125
+replaceStrW @126
+db_setCurrent @127
+CmdLine_GetOption @128
+CmdLine_Parse @129
+Utf8CheckString @130
+GetSubscribersCount @131
+NotifyFastHook @132
+db_find_first @133
+db_find_next @134
+Icon_Register @135
+Icon_RegisterT @136
+mir_subclassWindow @137
+mir_callNextSubclass @138
+KillModuleSubclassing @139
+mir_wstrndup @140
+mir_unsubclassWindow @141
+mir_urlEncode @142
+db_event_add @143
+db_event_count @144
+db_event_delete @145
+db_event_first @146
+db_event_firstUnread @147
+db_event_get @148
+db_event_getBlobSize @149
+db_event_getContact @150
+db_event_last @151
+db_event_markRead @152
+db_event_next @153
+db_event_prev @154
+ltrimw @155
+ltrimpw @156
+wildcmpw @157
+wildcmpi @158
+wildcmpiw @159
+mir_base64_encode @160
+mir_base64_decode @161
+ProtoServiceExists @162
+ProtoBroadcastAck @163
+ProtoCallService @164
+db_set_resident @165
+db_set @166
+ProtoConstructor @167
+ProtoDestructor @168
+ProtoCreateService @169
+ProtoCreateServiceParam @170
+ProtoHookEvent @171
+ProtoCreateHookableEvent @172
+ProtoForkThread @173
+ProtoForkThreadEx @174
+json_as_array @175
+json_as_bool @176
+json_as_float @177
+json_as_int @178
+json_as_node @179
+json_as_string @180
+json_as_pstring @181
+json_at @182
+json_cast @183
+json_clear @184
+json_copy @185
+json_delete @186
+json_duplicate @187
+json_empty @188
+json_equal @189
+json_free @190
+json_get @191
+json_merge @192
+json_name @193
+json_new @194
+json_new_a @195
+json_new_b @196
+json_new_f @197
+json_new_i @198
+json_nullify @199
+json_parse @200
+json_pop_back @201
+json_pop_back_at @202
+json_preparse @203
+json_push_back @204
+json_reserve @205
+json_set_a @206
+json_set_b @207
+json_set_f @208
+json_set_i @209
+json_set_n @210
+json_set_name @211
+json_size @212
+json_strip_white_space @213
+json_swap @214
+json_type @215
+json_write @216
+json_write_formatted @217
+mir_subclassWindowFull @218
+ProtoGetAvatarFormat @219
+ProtoGetAvatarExtension @220
+ProtoGetBufferFormat @221
+ProtoGetAvatarFileFormat @222
+mir_createLog @223
+mir_writeLogA @224
+mir_writeLogW @225
+mir_writeLogVA @226
+mir_writeLogVW @227
+bin2hex @228
+bin2hexW @229
+mir_hmac_sha1 @230
+mir_base64_encodebuf @231
+mirstr_allocate @232
+mirstr_free @233
+mirstr_realloc @234
+mirstr_getNil @235
+mirstr_lock @236
+mirstr_release @237
+mirstr_unlock @238
+IsWinVerVistaPlus @239
+IsWinVer7Plus @240
+IsFullScreen @241
+IsWorkstationLocked @242
+IsScreenSaverRunning @243
+ProtoLogA @244
+ProtoLogW @245
+db_get_static @246
+db_get_wstatic @247
+db_get_static_utf @248
+db_mc_isMeta @249
+db_mc_isSub @250
+db_mc_getMeta @251
+db_get_contact @252
+db_mc_getDefault @253
+db_mc_getDefaultNum @254
+db_mc_getSubCount @255
+db_mc_getSub @256
+db_mc_setDefault @257
+db_mc_setDefaultNum @258
+mir_closeLog @259
+db_mc_enable @260
+db_mc_isEnabled @261
+LoadLangPackDescr @262
+PathIsAbsolute @263
+PathIsAbsoluteW @264
+db_mc_notifyDefChange @265
+db_mc_tryMeta @266
+mir_strlen @267
+mir_wstrlen @268
+mir_strcpy @269
+mir_wstrcpy @270
+mir_strncpy @271
+mir_wstrncpy @272
+mir_strcat @273
+mir_wstrcat @274
+mir_strncat @275
+mir_wstrncat @276
+mir_strcmp @277
+mir_strcmpi @278
+mir_wstrcmp @279
+mir_wstrcmpi @280
+??$?HDV?$ChTraitsCRT@D@@@@YA?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@AEBV0@0@Z @281 NONAME
+??$?HDV?$ChTraitsCRT@D@@@@YA?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@AEBV0@D@Z @282 NONAME
+??$?HDV?$ChTraitsCRT@D@@@@YA?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@AEBV0@PEBD@Z @283 NONAME
+??$?HDV?$ChTraitsCRT@D@@@@YA?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@AEBV0@_W@Z @284 NONAME
+??$?HDV?$ChTraitsCRT@D@@@@YA?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@DAEBV0@@Z @285 NONAME
+??$?HDV?$ChTraitsCRT@D@@@@YA?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@PEBDAEBV0@@Z @286 NONAME
+??$?HDV?$ChTraitsCRT@D@@@@YA?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@_WAEBV0@@Z @287 NONAME
+??$?H_WV?$ChTraitsCRT@_W@@@@YA?AV?$CMStringT@_WV?$ChTraitsCRT@_W@@@@AEBV0@0@Z @288 NONAME
+??$?H_WV?$ChTraitsCRT@_W@@@@YA?AV?$CMStringT@_WV?$ChTraitsCRT@_W@@@@AEBV0@D@Z @289 NONAME
+??$?H_WV?$ChTraitsCRT@_W@@@@YA?AV?$CMStringT@_WV?$ChTraitsCRT@_W@@@@AEBV0@PEB_W@Z @290 NONAME
+??$?H_WV?$ChTraitsCRT@_W@@@@YA?AV?$CMStringT@_WV?$ChTraitsCRT@_W@@@@AEBV0@_W@Z @291 NONAME
+??$?H_WV?$ChTraitsCRT@_W@@@@YA?AV?$CMStringT@_WV?$ChTraitsCRT@_W@@@@DAEBV0@@Z @292 NONAME
+??$?H_WV?$ChTraitsCRT@_W@@@@YA?AV?$CMStringT@_WV?$ChTraitsCRT@_W@@@@PEB_WAEBV0@@Z @293 NONAME
+??$?H_WV?$ChTraitsCRT@_W@@@@YA?AV?$CMStringT@_WV?$ChTraitsCRT@_W@@@@_WAEBV0@@Z @294 NONAME
+??0?$CMSimpleStringT@D@@QEAA@AEBV0@@Z @295 NONAME
+??0?$CMSimpleStringT@D@@QEAA@PEBD@Z @296 NONAME
+??0?$CMSimpleStringT@D@@QEAA@PEBDH@Z @297 NONAME
+??0?$CMSimpleStringT@D@@QEAA@XZ @298 NONAME
+??0?$CMSimpleStringT@_W@@QEAA@AEBV0@@Z @299 NONAME
+??0?$CMSimpleStringT@_W@@QEAA@PEB_W@Z @300 NONAME
+??0?$CMSimpleStringT@_W@@QEAA@PEB_WH@Z @301 NONAME
+??0?$CMSimpleStringT@_W@@QEAA@XZ @302 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAA@AEBV0@@Z @303 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAA@DH@Z @304 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAA@PEBD@Z @305 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAA@PEBDH@Z @306 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAA@PEBE@Z @307 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAA@PEB_W@Z @308 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAA@PEB_WH@Z @309 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAA@W4CMStringDataFormat@@PEBDZZ @310 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAA@XZ @311 NONAME
+??0?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAA@_WH@Z @312 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAA@AEBV0@@Z @313 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAA@DH@Z @314 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAA@PEBD@Z @315 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAA@PEBDH@Z @316 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAA@PEBE@Z @317 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAA@PEB_W@Z @318 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAA@PEB_WH@Z @319 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAA@W4CMStringDataFormat@@PEB_WZZ @320 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAA@XZ @321 NONAME
+??0?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAA@_WH@Z @322 NONAME
+??1?$CMSimpleStringT@D@@QEAA@XZ @323 NONAME
+??1?$CMSimpleStringT@_W@@QEAA@XZ @324 NONAME
+??1?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAA@XZ @325 NONAME
+??1?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAA@XZ @326 NONAME
+??4?$CMSimpleStringT@D@@QEAAAEAV0@AEBV0@@Z @327 NONAME
+??4?$CMSimpleStringT@D@@QEAAAEAV0@PEBD@Z @328 NONAME
+??4?$CMSimpleStringT@_W@@QEAAAEAV0@AEBV0@@Z @329 NONAME
+??4?$CMSimpleStringT@_W@@QEAAAEAV0@PEB_W@Z @330 NONAME
+??4?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV0@AEBV0@@Z @331 NONAME
+??4?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV0@D@Z @332 NONAME
+??4?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV0@PEBD@Z @333 NONAME
+??4?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV0@PEBE@Z @334 NONAME
+??4?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV0@PEB_W@Z @335 NONAME
+??4?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV0@_W@Z @336 NONAME
+??4?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV0@AEBV0@@Z @337 NONAME
+??4?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV0@D@Z @338 NONAME
+??4?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV0@PEBD@Z @339 NONAME
+??4?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV0@PEBE@Z @340 NONAME
+??4?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV0@PEB_W@Z @341 NONAME
+??4?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV0@_W@Z @342 NONAME
+??A?$CMSimpleStringT@D@@QEBADH@Z @343 NONAME
+??A?$CMSimpleStringT@_W@@QEBA_WH@Z @344 NONAME
+??B?$CMSimpleStringT@D@@QEAAAEAV0@XZ @345 NONAME
+??B?$CMSimpleStringT@D@@QEBAPEBDXZ @346 NONAME
+??B?$CMSimpleStringT@_W@@QEAAAEAV0@XZ @347 NONAME
+??B?$CMSimpleStringT@_W@@QEBAPEB_WXZ @348 NONAME
+??Y?$CMSimpleStringT@D@@QEAAAEAV0@AEBV0@@Z @349 NONAME
+??Y?$CMSimpleStringT@D@@QEAAAEAV0@D@Z @350 NONAME
+??Y?$CMSimpleStringT@D@@QEAAAEAV0@E@Z @351 NONAME
+??Y?$CMSimpleStringT@D@@QEAAAEAV0@PEBD@Z @352 NONAME
+??Y?$CMSimpleStringT@D@@QEAAAEAV0@_W@Z @353 NONAME
+??Y?$CMSimpleStringT@_W@@QEAAAEAV0@AEBV0@@Z @354 NONAME
+??Y?$CMSimpleStringT@_W@@QEAAAEAV0@D@Z @355 NONAME
+??Y?$CMSimpleStringT@_W@@QEAAAEAV0@E@Z @356 NONAME
+??Y?$CMSimpleStringT@_W@@QEAAAEAV0@PEB_W@Z @357 NONAME
+??Y?$CMSimpleStringT@_W@@QEAAAEAV0@_W@Z @358 NONAME
+??Y?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV0@AEBV0@@Z @359 NONAME
+??Y?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV0@AEBV?$CMSimpleStringT@D@@@Z @360 NONAME
+??Y?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV0@D@Z @361 NONAME
+??Y?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV0@E@Z @362 NONAME
+??Y?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV0@PEBD@Z @363 NONAME
+??Y?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV0@PEB_W@Z @364 NONAME
+??Y?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV0@_W@Z @365 NONAME
+??Y?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV0@AEBV0@@Z @366 NONAME
+??Y?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV0@AEBV?$CMSimpleStringT@_W@@@Z @367 NONAME
+??Y?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV0@D@Z @368 NONAME
+??Y?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV0@E@Z @369 NONAME
+??Y?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV0@PEBD@Z @370 NONAME
+??Y?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV0@PEB_W@Z @371 NONAME
+??Y?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV0@_W@Z @372 NONAME
+?AllocSysString@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBAPEA_WXZ @373 NONAME
+?AllocSysString@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBAPEA_WXZ @374 NONAME
+?Append@?$CMSimpleStringT@D@@QEAAXAEBV1@@Z @375 NONAME
+?Append@?$CMSimpleStringT@D@@QEAAXPEBD@Z @376 NONAME
+?Append@?$CMSimpleStringT@D@@QEAAXPEBDH@Z @377 NONAME
+?Append@?$CMSimpleStringT@_W@@QEAAXAEBV1@@Z @378 NONAME
+?Append@?$CMSimpleStringT@_W@@QEAAXPEB_W@Z @379 NONAME
+?Append@?$CMSimpleStringT@_W@@QEAAXPEB_WH@Z @380 NONAME
+?AppendChar@?$CMSimpleStringT@D@@QEAAXD@Z @381 NONAME
+?AppendChar@?$CMSimpleStringT@_W@@QEAAX_W@Z @382 NONAME
+?AppendFormat@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAPEBDPEBDZZ @383 NONAME
+?AppendFormat@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAPEB_WPEB_WZZ @384 NONAME
+?AppendFormatV@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAXPEBDPEAD@Z @385 NONAME
+?AppendFormatV@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAXPEB_WPEAD@Z @386 NONAME
+?Attach@?$CMSimpleStringT@D@@AEAAXPEAUCMStringData@@@Z @387 NONAME
+?Attach@?$CMSimpleStringT@_W@@AEAAXPEAUCMStringData@@@Z @388 NONAME
+?CharToOemA@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAXXZ @389 NONAME
+?CharToOemA@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAXXZ @390 NONAME
+?CloneData@?$CMSimpleStringT@D@@CAPEAUCMStringData@@PEAU2@@Z @391 NONAME
+?CloneData@?$CMSimpleStringT@_W@@CAPEAUCMStringData@@PEAU2@@Z @392 NONAME
+?Collate@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBAHPEBD@Z @393 NONAME
+?Collate@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBAHPEB_W@Z @394 NONAME
+?CollateNoCase@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBAHPEBD@Z @395 NONAME
+?CollateNoCase@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBAHPEB_W@Z @396 NONAME
+?Compare@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBAHPEBD@Z @397 NONAME
+?Compare@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBAHPEB_W@Z @398 NONAME
+?CompareNoCase@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBAHPEBD@Z @399 NONAME
+?CompareNoCase@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBAHPEB_W@Z @400 NONAME
+?Concatenate@?$CMSimpleStringT@D@@SAXAEAV1@PEBDH1H@Z @401 NONAME
+?Concatenate@?$CMSimpleStringT@_W@@SAXAEAV1@PEB_WH1H@Z @402 NONAME
+?CopyChars@?$CMSimpleStringT@D@@SAXPEADPEBDH@Z @403 NONAME
+?CopyChars@?$CMSimpleStringT@D@@SAXPEAD_KPEBDH@Z @404 NONAME
+?CopyChars@?$CMSimpleStringT@_W@@SAXPEA_WPEB_WH@Z @405 NONAME
+?CopyChars@?$CMSimpleStringT@_W@@SAXPEA_W_KPEB_WH@Z @406 NONAME
+?CopyCharsOverlapped@?$CMSimpleStringT@D@@SAXPEADPEBDH@Z @407 NONAME
+?CopyCharsOverlapped@?$CMSimpleStringT@D@@SAXPEAD_KPEBDH@Z @408 NONAME
+?CopyCharsOverlapped@?$CMSimpleStringT@_W@@SAXPEA_WPEB_WH@Z @409 NONAME
+?CopyCharsOverlapped@?$CMSimpleStringT@_W@@SAXPEA_W_KPEB_WH@Z @410 NONAME
+?Delete@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAHHH@Z @411 NONAME
+?Delete@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAHHH@Z @412 NONAME
+?Empty@?$CMSimpleStringT@D@@QEAAXXZ @413 NONAME
+?Empty@?$CMSimpleStringT@_W@@QEAAXXZ @414 NONAME
+?Find@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBAHDH@Z @415 NONAME
+?Find@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBAHPEBDH@Z @416 NONAME
+?Find@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBAHPEB_WH@Z @417 NONAME
+?Find@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBAH_WH@Z @418 NONAME
+?FindOneOf@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBAHPEBD@Z @419 NONAME
+?FindOneOf@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBAHPEB_W@Z @420 NONAME
+?Fork@?$CMSimpleStringT@D@@AEAAXH@Z @421 NONAME
+?Fork@?$CMSimpleStringT@_W@@AEAAXH@Z @422 NONAME
+?Format@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAPEBDPEBDZZ @423 NONAME
+?Format@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAPEB_WPEB_WZZ @424 NONAME
+?FormatV@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAPEBDPEBDPEAD@Z @425 NONAME
+?FormatV@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAPEB_WPEB_WPEAD@Z @426 NONAME
+?FreeExtra@?$CMSimpleStringT@D@@QEAAXXZ @427 NONAME
+?FreeExtra@?$CMSimpleStringT@_W@@QEAAXXZ @428 NONAME
+?GetAllocLength@?$CMSimpleStringT@D@@QEBAHXZ @429 NONAME
+?GetAllocLength@?$CMSimpleStringT@_W@@QEBAHXZ @430 NONAME
+?GetAt@?$CMSimpleStringT@D@@QEBADH@Z @431 NONAME
+?GetAt@?$CMSimpleStringT@_W@@QEBA_WH@Z @432 NONAME
+?GetBuffer@?$CMSimpleStringT@D@@QEAAPEADH@Z @433 NONAME
+?GetBuffer@?$CMSimpleStringT@D@@QEAAPEADXZ @434 NONAME
+?GetBuffer@?$CMSimpleStringT@_W@@QEAAPEA_WH@Z @435 NONAME
+?GetBuffer@?$CMSimpleStringT@_W@@QEAAPEA_WXZ @436 NONAME
+?GetBufferSetLength@?$CMSimpleStringT@D@@QEAAPEADH@Z @437 NONAME
+?GetBufferSetLength@?$CMSimpleStringT@_W@@QEAAPEA_WH@Z @438 NONAME
+?GetData@?$CMSimpleStringT@D@@AEBAPEAUCMStringData@@XZ @439 NONAME
+?GetData@?$CMSimpleStringT@_W@@AEBAPEAUCMStringData@@XZ @440 NONAME
+?GetEnvironmentVariableW@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAHPEBD@Z @441 NONAME
+?GetEnvironmentVariableW@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAHPEB_W@Z @442 NONAME
+?GetLength@?$CMSimpleStringT@D@@QEBAHXZ @443 NONAME
+?GetLength@?$CMSimpleStringT@_W@@QEBAHXZ @444 NONAME
+?GetString@?$CMSimpleStringT@D@@QEBAPEBDXZ @445 NONAME
+?GetString@?$CMSimpleStringT@_W@@QEBAPEB_WXZ @446 NONAME
+?GetTail@?$CMSimpleStringT@D@@QEBAPEBDXZ @447 NONAME
+?GetTail@?$CMSimpleStringT@_W@@QEBAPEB_WXZ @448 NONAME
+?Insert@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAHHD@Z @449 NONAME
+?Insert@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAHHPEBD@Z @450 NONAME
+?Insert@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAHHPEB_W@Z @451 NONAME
+?Insert@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAHH_W@Z @452 NONAME
+?IsEmpty@?$CMSimpleStringT@D@@QEBA_NXZ @453 NONAME
+?IsEmpty@?$CMSimpleStringT@_W@@QEBA_NXZ @454 NONAME
+?Left@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBA?AV1@H@Z @455 NONAME
+?Left@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBA?AV1@H@Z @456 NONAME
+?LockBuffer@?$CMSimpleStringT@D@@QEAAPEADXZ @457 NONAME
+?LockBuffer@?$CMSimpleStringT@_W@@QEAAPEA_WXZ @458 NONAME
+?MakeLower@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV1@XZ @459 NONAME
+?MakeLower@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV1@XZ @460 NONAME
+?MakeReverse@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV1@XZ @461 NONAME
+?MakeReverse@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV1@XZ @462 NONAME
+?MakeUpper@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV1@XZ @463 NONAME
+?MakeUpper@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV1@XZ @464 NONAME
+?Mid@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBA?AV1@H@Z @465 NONAME
+?Mid@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBA?AV1@HH@Z @466 NONAME
+?Mid@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBA?AV1@H@Z @467 NONAME
+?Mid@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBA?AV1@HH@Z @468 NONAME
+?OemToCharA@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAXXZ @469 NONAME
+?OemToCharA@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAXXZ @470 NONAME
+?Preallocate@?$CMSimpleStringT@D@@QEAAXH@Z @471 NONAME
+?Preallocate@?$CMSimpleStringT@_W@@QEAAXH@Z @472 NONAME
+?PrepareWrite2@?$CMSimpleStringT@D@@AEAAXH@Z @473 NONAME
+?PrepareWrite2@?$CMSimpleStringT@_W@@AEAAXH@Z @474 NONAME
+?PrepareWrite@?$CMSimpleStringT@D@@AEAAPEADH@Z @475 NONAME
+?PrepareWrite@?$CMSimpleStringT@_W@@AEAAPEA_WH@Z @476 NONAME
+?Reallocate@?$CMSimpleStringT@D@@AEAAXH@Z @477 NONAME
+?Reallocate@?$CMSimpleStringT@_W@@AEAAXH@Z @478 NONAME
+?ReleaseBuffer@?$CMSimpleStringT@D@@QEAAXH@Z @479 NONAME
+?ReleaseBuffer@?$CMSimpleStringT@_W@@QEAAXH@Z @480 NONAME
+?ReleaseBufferSetLength@?$CMSimpleStringT@D@@QEAAXH@Z @481 NONAME
+?ReleaseBufferSetLength@?$CMSimpleStringT@_W@@QEAAXH@Z @482 NONAME
+?Remove@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAHD@Z @483 NONAME
+?Remove@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAH_W@Z @484 NONAME
+?Replace@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAHDD@Z @485 NONAME
+?Replace@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAHPEBD0@Z @486 NONAME
+?Replace@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAHPEB_W0@Z @487 NONAME
+?Replace@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAH_W0@Z @488 NONAME
+?ReverseFind@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBAHD@Z @489 NONAME
+?ReverseFind@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBAH_W@Z @490 NONAME
+?Right@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBA?AV1@H@Z @491 NONAME
+?Right@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBA?AV1@H@Z @492 NONAME
+?SetAt@?$CMSimpleStringT@D@@QEAAXHD@Z @493 NONAME
+?SetAt@?$CMSimpleStringT@_W@@QEAAXH_W@Z @494 NONAME
+?SetLength@?$CMSimpleStringT@D@@AEAAXH@Z @495 NONAME
+?SetLength@?$CMSimpleStringT@_W@@AEAAXH@Z @496 NONAME
+?SetString@?$CMSimpleStringT@D@@QEAAXPEBD@Z @497 NONAME
+?SetString@?$CMSimpleStringT@D@@QEAAXPEBDH@Z @498 NONAME
+?SetString@?$CMSimpleStringT@_W@@QEAAXPEB_W@Z @499 NONAME
+?SetString@?$CMSimpleStringT@_W@@QEAAXPEB_WH@Z @500 NONAME
+?SetSysString@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBAPEA_WPEAPEA_W@Z @501 NONAME
+?SetSysString@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBAPEA_WPEAPEA_W@Z @502 NONAME
+?SpanExcluding@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBA?AV1@PEBD@Z @503 NONAME
+?SpanExcluding@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBA?AV1@PEB_W@Z @504 NONAME
+?SpanIncluding@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBA?AV1@PEBD@Z @505 NONAME
+?SpanIncluding@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBA?AV1@PEB_W@Z @506 NONAME
+?StringLength@?$CMSimpleStringT@D@@SAHPEBD@Z @507 NONAME
+?StringLength@?$CMSimpleStringT@D@@SAHPEB_W@Z @508 NONAME
+?StringLength@?$CMSimpleStringT@_W@@SAHPEBD@Z @509 NONAME
+?StringLength@?$CMSimpleStringT@_W@@SAHPEB_W@Z @510 NONAME
+?StringLengthN@?$CMSimpleStringT@D@@SAHPEBD_K@Z @511 NONAME
+?StringLengthN@?$CMSimpleStringT@D@@SAHPEB_W_K@Z @512 NONAME
+?StringLengthN@?$CMSimpleStringT@_W@@SAHPEBD_K@Z @513 NONAME
+?StringLengthN@?$CMSimpleStringT@_W@@SAHPEB_W_K@Z @514 NONAME
+?Tokenize@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEBA?AV1@PEBDAEAH@Z @515 NONAME
+?Tokenize@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEBA?AV1@PEB_WAEAH@Z @516 NONAME
+?Trim@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV1@D@Z @517 NONAME
+?Trim@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV1@PEBD@Z @518 NONAME
+?Trim@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV1@XZ @519 NONAME
+?Trim@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV1@PEB_W@Z @520 NONAME
+?Trim@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV1@XZ @521 NONAME
+?Trim@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV1@_W@Z @522 NONAME
+?TrimLeft@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV1@D@Z @523 NONAME
+?TrimLeft@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV1@PEBD@Z @524 NONAME
+?TrimLeft@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV1@XZ @525 NONAME
+?TrimLeft@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV1@PEB_W@Z @526 NONAME
+?TrimLeft@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV1@XZ @527 NONAME
+?TrimLeft@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV1@_W@Z @528 NONAME
+?TrimRight@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV1@D@Z @529 NONAME
+?TrimRight@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV1@PEBD@Z @530 NONAME
+?TrimRight@?$CMStringT@DV?$ChTraitsCRT@D@@@@QEAAAEAV1@XZ @531 NONAME
+?TrimRight@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV1@PEB_W@Z @532 NONAME
+?TrimRight@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV1@XZ @533 NONAME
+?TrimRight@?$CMStringT@_WV?$ChTraitsCRT@_W@@@@QEAAAEAV1@_W@Z @534 NONAME
+?Truncate@?$CMSimpleStringT@D@@QEAAXH@Z @535 NONAME
+?Truncate@?$CMSimpleStringT@_W@@QEAAXH@Z @536 NONAME
+?UnlockBuffer@?$CMSimpleStringT@D@@QEAAXXZ @537 NONAME
+?UnlockBuffer@?$CMSimpleStringT@_W@@QEAAXXZ @538 NONAME
+?c_str@?$CMSimpleStringT@D@@QEBAPEBDXZ @539 NONAME
+?c_str@?$CMSimpleStringT@_W@@QEBAPEB_WXZ @540 NONAME
diff --git a/src/mir_core/src/mstring.cpp b/src/mir_core/src/mstring.cpp
index f2d75bfe6e..f4abf5e626 100644
--- a/src/mir_core/src/mstring.cpp
+++ b/src/mir_core/src/mstring.cpp
@@ -116,3 +116,25 @@ MIR_CORE_DLL(void) mirstr_unlock(CMStringData* pThis)
pThis->nRefs = 1;
}
}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// don't remove it
+// this code just instantiates templates for CMString[A/W]
+
+template CMStringW;
+template MIR_CORE_EXPORT CMStringW CALLBACK operator + (const CMStringW& str1, const CMStringW& str2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, const wchar_t *psz2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const wchar_t *psz1, const CMStringW& str2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, wchar_t ch2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, char ch2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(wchar_t ch1, const CMStringW& str2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(char ch1, const CMStringW& str2);
+
+template CMStringA;
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, const CMStringA& str2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, const char *psz2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const char *psz1, const CMStringA& str2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, wchar_t ch2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, char ch2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(wchar_t ch1, const CMStringA& str2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(char ch1, const CMStringA& str2);