diff options
Diffstat (limited to 'include/m_string.h')
-rw-r--r-- | include/m_string.h | 1998 |
1 files changed, 1040 insertions, 958 deletions
diff --git a/include/m_string.h b/include/m_string.h index 21404268cd..9d6244b19b 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -1,958 +1,1040 @@ -/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://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_H__
-#define M_STRING_H__
-
-#include <stdio.h>
-#include <string.h>
-#include <mbstring.h>
-#include <wchar.h>
-
-#include <m_core.h>
-
-#ifdef __MINGW32__
-#include <limits.h>
-
-__inline size_t strnlen(const char *string, size_t maxlen)
-{
- const char *end = (const char *)memchr ((const void *)string, '\0', maxlen);
- return end ? (size_t) (end - string) : maxlen;
-}
-__inline size_t wcsnlen(const wchar_t *string, size_t maxlen)
-{
- const wchar_t *end = wmemchr (string, L'\0', maxlen);
- return end ? (size_t) (end - string) : maxlen;
-}
-
-/* FIXME: This may be wrong assumption about Langpack_GetDefaultCodePage */
-#define Langpack_GetDefaultCodePage() CP_THREAD_ACP
-/* FIXME: This is unsafe */
-#define memcpy_s(dest,size,src,count) memcpy(dest,src,count)
-/* FIXME: This is quite silly implementation of _mbsstr */
-#define _mbsstr(str,search) strstr((const char *)str,(const char *)search)
-#define __max(x,y) (((x)<(y))?(y):(x))
-#endif /* __MINGW32__ */
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-struct CMStringData;
-
-MIR_CORE_DLL(CMStringData*) mirstr_allocate(int nChars, int nCharSize);
-MIR_CORE_DLL(void) mirstr_free(CMStringData *pData);
-MIR_CORE_DLL(CMStringData*) mirstr_realloc(CMStringData* pData, int nChars, int nCharSize);
-MIR_CORE_DLL(CMStringData*) mirstr_getNil();
-
-MIR_CORE_DLL(void) mirstr_lock(CMStringData* pThis);
-MIR_CORE_DLL(void) mirstr_release(CMStringData* pThis);
-MIR_CORE_DLL(void) mirstr_unlock(CMStringData* pThis);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-enum CMStringDataFormat { FORMAT };
-
-struct CMStringData
-{
- int nDataLength; // Length of currently used data in XCHARs (not including terminating null)
- int nAllocLength; // Length of allocated data in XCHARs (not including terminating null)
- long nRefs; // Reference count: negative == locked
-
- __forceinline void* data() { return (this + 1); }
- __forceinline void AddRef() { InterlockedIncrement(&nRefs); }
- __forceinline bool IsLocked() const { return nRefs < 0; }
- __forceinline bool IsShared() const { return nRefs > 1; }
-
- __forceinline void Lock() { mirstr_lock(this); }
- __forceinline void Release() { mirstr_release(this); }
- __forceinline void Unlock() { mirstr_unlock(this); }
-};
-
-template< typename BaseType = char >
-class ChTraitsBase
-{
-public:
- typedef char XCHAR;
- typedef LPSTR PXSTR;
- typedef LPCSTR PCXSTR;
- typedef wchar_t YCHAR;
- typedef LPWSTR PYSTR;
- typedef LPCWSTR PCYSTR;
-};
-
-template<>
-class ChTraitsBase< wchar_t >
-{
-public:
- typedef wchar_t XCHAR;
- typedef LPWSTR PXSTR;
- typedef LPCWSTR PCXSTR;
- typedef char YCHAR;
- typedef LPSTR PYSTR;
- typedef LPCSTR PCYSTR;
-};
-
-template< typename BaseType >
-class CMSimpleStringT
-{
-public:
- typedef typename ChTraitsBase< BaseType >::XCHAR XCHAR;
- typedef typename ChTraitsBase< BaseType >::PXSTR PXSTR;
- typedef typename ChTraitsBase< BaseType >::PCXSTR PCXSTR;
- typedef typename ChTraitsBase< BaseType >::YCHAR YCHAR;
- typedef typename ChTraitsBase< BaseType >::PYSTR PYSTR;
- typedef typename ChTraitsBase< BaseType >::PCYSTR PCYSTR;
-
-public:
- explicit CMSimpleStringT();
-
- CMSimpleStringT(const CMSimpleStringT& strSrc);
- CMSimpleStringT(PCXSTR pszSrc);
- CMSimpleStringT(const XCHAR* pchSrc, int nLength);
- ~CMSimpleStringT();
-
- __forceinline operator CMSimpleStringT<BaseType>&()
- { return *(CMSimpleStringT<BaseType>*)this;
- }
-
- CMSimpleStringT& operator=(const CMSimpleStringT& strSrc);
-
- __forceinline CMSimpleStringT& operator=(PCXSTR pszSrc)
- { SetString(pszSrc);
- return *this;
- }
-
- __forceinline CMSimpleStringT& operator+=(const CMSimpleStringT& strSrc)
- { Append(strSrc);
- return *this;
- }
-
- __forceinline CMSimpleStringT& operator+=(PCXSTR pszSrc)
- { Append(pszSrc);
- return *this;
- }
-
- __forceinline CMSimpleStringT& operator+=(char ch)
- { AppendChar(XCHAR(ch));
- return *this;
- }
-
- __forceinline CMSimpleStringT& operator+=(unsigned char ch)
- { AppendChar(XCHAR(ch));
- return *this;
- }
-
- __forceinline CMSimpleStringT& operator+=(wchar_t ch)
- { AppendChar(XCHAR(ch));
- return *this;
- }
-
- __forceinline XCHAR operator[](int iChar) const
- { return m_pszData[iChar];
- }
-
- __forceinline operator PCXSTR() const
- { return m_pszData;
- }
-
- __forceinline PCXSTR c_str() const
- { return m_pszData;
- }
-
- __forceinline int GetAllocLength() const
- { return GetData()->nAllocLength;
- }
-
- __forceinline XCHAR GetAt(int iChar) const
- { return m_pszData[iChar];
- }
-
- __forceinline PXSTR GetBuffer(int nMinBufferLength)
- { return PrepareWrite(nMinBufferLength);
- }
-
- __forceinline int GetLength() const
- { return GetData()->nDataLength;
- }
-
- __forceinline PCXSTR GetString() const
- { return m_pszData;
- }
-
- __forceinline PCXSTR GetTail() const
- { return m_pszData + GetData()->nDataLength;
- }
-
- __forceinline bool IsEmpty() const
- { return GetLength() == 0;
- }
-
- __forceinline void Preallocate(int nLength)
- { PrepareWrite(nLength);
- }
-
- __forceinline void ReleaseBufferSetLength(int nNewLength)
- { SetLength(nNewLength);
- }
-
- void Append(PCXSTR pszSrc);
- void Append(PCXSTR pszSrc, int nLength);
- void AppendChar(XCHAR ch);
- void Append(const CMSimpleStringT& strSrc);
-
- void Empty();
- void FreeExtra();
-
- PXSTR GetBuffer();
- PXSTR GetBufferSetLength(int nLength);
-
- PXSTR LockBuffer();
- void UnlockBuffer();
-
- void ReleaseBuffer(int nNewLength = -1);
-
- void Truncate(int nNewLength);
- void SetAt(int iChar, XCHAR ch);
- void SetString(PCXSTR pszSrc);
- void SetString(PCXSTR pszSrc, int nLength);
-
-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:
- __forceinline CMStringData* GetData() const
- { return (reinterpret_cast<CMStringData *>(m_pszData)-1);
- }
-
- 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);
-
-private:
- PXSTR m_pszData;
-};
-
-
-template< typename _CharType = char >
-class ChTraitsCRT : public ChTraitsBase < _CharType >
-{
-public:
- static char* __stdcall CharNext(const char* p)
- {
- return reinterpret_cast<char*>(_mbsinc(reinterpret_cast<const unsigned char*>(p)));
- }
-
- static int __stdcall IsDigit(char ch)
- {
- return _ismbcdigit(ch);
- }
-
- static int __stdcall IsSpace(char ch)
- {
- return _ismbcspace(ch);
- }
-
- static int __stdcall StringCompare(LPCSTR pszA, LPCSTR pszB)
- {
- return _mbscmp(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB));
- }
-
- static int __stdcall StringCompareIgnore(LPCSTR pszA, LPCSTR pszB)
- {
- return _mbsicmp(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB));
- }
-
- static int __stdcall StringCollate(LPCSTR pszA, LPCSTR pszB)
- {
- return _mbscoll(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB));
- }
-
- static int __stdcall StringCollateIgnore(LPCSTR pszA, LPCSTR pszB)
- {
- return _mbsicoll(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB));
- }
-
- static LPCSTR __stdcall StringFindString(LPCSTR pszBlock, LPCSTR pszMatch)
- {
- return reinterpret_cast<LPCSTR>(_mbsstr(reinterpret_cast<const unsigned char*>(pszBlock),
- reinterpret_cast<const unsigned char*>(pszMatch)));
- }
-
- static LPSTR __stdcall StringFindString(LPSTR pszBlock, LPCSTR pszMatch)
- {
- return const_cast<LPSTR>(StringFindString(const_cast<LPCSTR>(pszBlock), pszMatch));
- }
-
- static LPCSTR __stdcall StringFindChar(LPCSTR pszBlock, char chMatch)
- {
- return reinterpret_cast<LPCSTR>(_mbschr(reinterpret_cast<const unsigned char*>(pszBlock), (unsigned char)chMatch));
- }
-
- static LPCSTR __stdcall StringFindCharRev(LPCSTR psz, char ch)
- {
- return reinterpret_cast<LPCSTR>(_mbsrchr(reinterpret_cast<const unsigned char*>(psz), (unsigned char)ch));
- }
-
- static LPCSTR __stdcall StringScanSet(LPCSTR pszBlock, LPCSTR pszMatch)
- {
- return reinterpret_cast<LPCSTR>(_mbspbrk(reinterpret_cast<const unsigned char*>(pszBlock),
- reinterpret_cast<const unsigned char*>(pszMatch)));
- }
-
- static int __stdcall StringSpanIncluding(LPCSTR pszBlock, LPCSTR pszSet)
- {
- return (int)_mbsspn(reinterpret_cast<const unsigned char*>(pszBlock), reinterpret_cast<const unsigned char*>(pszSet));
- }
-
- static int __stdcall StringSpanExcluding(LPCSTR pszBlock, LPCSTR pszSet)
- {
- return (int)_mbscspn(reinterpret_cast<const unsigned char*>(pszBlock), reinterpret_cast<const unsigned char*>(pszSet));
- }
-
- static LPSTR __stdcall StringUppercase(LPSTR psz)
- {
- CharUpperBuffA(psz, (DWORD)strlen(psz));
- return psz;
- }
-
- static LPSTR __stdcall StringLowercase(LPSTR psz)
- {
- CharLowerBuffA(psz, (DWORD)strlen(psz));
- return psz;
- }
-
- static LPSTR __stdcall StringUppercase(LPSTR psz, size_t size)
- {
- CharUpperBuffA(psz, (DWORD)size);
- return psz;
- }
-
- static LPSTR __stdcall StringLowercase(LPSTR psz, size_t size)
- {
- CharLowerBuffA(psz, (DWORD)size);
- return psz;
- }
-
- static LPSTR __stdcall StringReverse(LPSTR psz)
- {
- return reinterpret_cast<LPSTR>(_mbsrev(reinterpret_cast<unsigned char*>(psz)));
- }
-
- static int __stdcall GetFormattedLength(_Printf_format_string_ LPCSTR pszFormat, va_list args)
- {
- return _vscprintf(pszFormat, args);
- }
-
- static int __stdcall Format(LPSTR pszBuffer, size_t nlength, _Printf_format_string_ LPCSTR pszFormat, va_list args)
- {
- return vsprintf_s(pszBuffer, nlength, pszFormat, args);
- }
-
- static int __stdcall GetBaseTypeLength(LPCSTR pszSrc)
- {
- // Returns required buffer length in XCHARs
- return int(strlen(pszSrc));
- }
-
- static int __stdcall GetBaseTypeLength(LPCSTR pszSrc, int nLength)
- {
- (void)pszSrc;
- // Returns required buffer length in XCHARs
- return nLength;
- }
-
- static int __stdcall GetBaseTypeLength(LPCWSTR pszSource)
- {
- // Returns required buffer length in XCHARs
- return ::WideCharToMultiByte(Langpack_GetDefaultCodePage(), 0, pszSource, -1, NULL, 0, NULL, NULL) - 1;
- }
-
- static int __stdcall GetBaseTypeLength(LPCWSTR pszSource, int nLength)
- {
- // Returns required buffer length in XCHARs
- return ::WideCharToMultiByte(Langpack_GetDefaultCodePage(), 0, pszSource, nLength, NULL, 0, NULL, NULL);
- }
-
- static void __stdcall ConvertToBaseType(LPSTR pszDest, int nDestLength, LPCSTR pszSrc, int nSrcLength = -1)
- {
- if (nSrcLength == -1) { nSrcLength = 1 + GetBaseTypeLength(pszSrc); }
- // nLen is in XCHARs
- memcpy_s(pszDest, nDestLength*sizeof(char), pszSrc, nSrcLength*sizeof(char));
- }
-
- static void __stdcall ConvertToBaseType(LPSTR pszDest, int nDestLength, LPCWSTR pszSrc, int nSrcLength = -1)
- {
- // nLen is in XCHARs
- ::WideCharToMultiByte(Langpack_GetDefaultCodePage(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL);
- }
-
- static void ConvertToOem(_CharType* pstrString)
- {
- BOOL fSuccess = ::CharToOemA(pstrString, pstrString);
- }
-
- static void ConvertToAnsi(_CharType* pstrString)
- {
- BOOL fSuccess = ::OemToCharA(pstrString, pstrString);
- }
-
- static void ConvertToOem(_CharType* pstrString, size_t size)
- {
- DWORD dwSize = static_cast<DWORD>(size);
- ::CharToOemBuffA(pstrString, pstrString, dwSize);
- }
-
- static void ConvertToAnsi(_CharType* pstrString, size_t size)
- {
- DWORD dwSize = static_cast<DWORD>(size);
- ::OemToCharBuffA(pstrString, pstrString, dwSize);
- }
-
- static void __stdcall FloodCharacters(char ch, int nLength, char* pch)
- {
- // nLength is in XCHARs
- memset(pch, ch, nLength);
- }
-
- static int __stdcall SafeStringLen(LPCSTR psz)
- {
- // returns length in bytes
- return (psz != NULL) ? int(strlen(psz)) : 0;
- }
-
- static int __stdcall SafeStringLen(LPCWSTR psz)
- {
- // returns length in wchar_ts
- return (psz != NULL) ? int(wcslen(psz)) : 0;
- }
-
- static int __stdcall GetCharLen(const wchar_t* pch)
- {
- // returns char length
- return 1;
- }
-
- static int __stdcall GetCharLen(const char* pch)
- {
- // returns char length
- return int(_mbclen(reinterpret_cast<const unsigned char*>(pch)));
- }
-
- static DWORD __stdcall GetEnvironmentVariable(LPCSTR pszVar, LPSTR pszBuffer, DWORD dwSize)
- {
- return ::GetEnvironmentVariableA(pszVar, pszBuffer, dwSize);
- }
-
- static char* MirCopy(const char *pstrString, size_t size)
- {
- return mir_strndup(pstrString, size);
- }
-};
-
-// specialization for wchar_t
-template<>
-class ChTraitsCRT< wchar_t > : public ChTraitsBase< wchar_t >
-{
- static DWORD __stdcall _GetEnvironmentVariableW(LPCWSTR pszName, LPWSTR pszBuffer, DWORD nSize)
- {
- return ::GetEnvironmentVariableW(pszName, pszBuffer, nSize);
- }
-
-public:
- static LPWSTR __stdcall CharNext(LPCWSTR psz)
- {
- return const_cast< LPWSTR >(psz+1);
- }
-
- static int __stdcall IsDigit(wchar_t ch)
- {
- return iswdigit(static_cast<unsigned short>(ch));
- }
-
- static int __stdcall IsSpace(wchar_t ch)
- {
- return iswspace(static_cast<unsigned short>(ch));
- }
-
- static int __stdcall StringCompare(LPCWSTR pszA, LPCWSTR pszB)
- {
- return wcscmp(pszA, pszB);
- }
-
- static int __stdcall StringCompareIgnore(LPCWSTR pszA, LPCWSTR pszB)
- {
- return _wcsicmp(pszA, pszB);
- }
-
- static int __stdcall StringCollate(LPCWSTR pszA, LPCWSTR pszB)
- {
- return wcscoll(pszA, pszB);
- }
-
- static int __stdcall StringCollateIgnore(LPCWSTR pszA, LPCWSTR pszB)
- {
- return _wcsicoll(pszA, pszB);
- }
-
- static LPCWSTR __stdcall StringFindString(LPCWSTR pszBlock, LPCWSTR pszMatch)
- {
- return wcsstr(pszBlock, pszMatch);
- }
-
- static LPWSTR __stdcall StringFindString(LPWSTR pszBlock, LPCWSTR pszMatch)
- {
- return const_cast< LPWSTR >(StringFindString(const_cast< LPCWSTR >(pszBlock), pszMatch));
- }
-
- static LPCWSTR __stdcall StringFindChar(LPCWSTR pszBlock, wchar_t chMatch)
- {
- return wcschr(pszBlock, chMatch);
- }
-
- static LPCWSTR __stdcall StringFindCharRev(LPCWSTR psz, wchar_t ch)
- {
- return wcsrchr(psz, ch);
- }
-
- static LPCWSTR __stdcall StringScanSet(LPCWSTR pszBlock, LPCWSTR pszMatch)
- {
- return wcspbrk(pszBlock, pszMatch);
- }
-
- static int __stdcall StringSpanIncluding(LPCWSTR pszBlock, LPCWSTR pszSet)
- {
- return (int)wcsspn(pszBlock, pszSet);
- }
-
- static int __stdcall StringSpanExcluding(LPCWSTR pszBlock, LPCWSTR pszSet)
- {
- return (int)wcscspn(pszBlock, pszSet);
- }
-
- static LPWSTR __stdcall StringUppercase(LPWSTR psz)
- {
- CharUpperBuffW(psz, (DWORD)wcslen(psz));
- return psz;
- }
-
- static LPWSTR __stdcall StringLowercase(LPWSTR psz)
- {
- CharLowerBuffW(psz, (DWORD)wcslen(psz));
- return psz;
- }
-
- static LPWSTR __stdcall StringUppercase(LPWSTR psz, size_t len)
- {
- CharUpperBuffW(psz, (DWORD)len);
- return psz;
- }
-
- static LPWSTR __stdcall StringLowercase(LPWSTR psz, size_t len)
- {
- CharLowerBuffW(psz, (DWORD)len);
- return psz;
- }
-
- static LPWSTR __stdcall StringReverse(LPWSTR psz)
- {
- return _wcsrev(psz);
- }
-
- static int __stdcall GetFormattedLength(_Printf_format_string_ LPCWSTR pszFormat, va_list args)
- {
- return _vscwprintf(pszFormat, args);
- }
-
- static int __stdcall Format(LPWSTR pszBuffer, _Printf_format_string_ LPCWSTR pszFormat, va_list args)
- {
- #pragma warning(push)
- #pragma warning(disable : 4996)
- return vswprintf(pszBuffer, pszFormat, args);
- #pragma warning(pop)
- }
-
- static int __stdcall Format(LPWSTR pszBuffer, size_t nLength, _Printf_format_string_ LPCWSTR pszFormat, va_list args)
- {
- #pragma warning(push)
- #pragma warning(disable : 4996)
- return _vsnwprintf(pszBuffer, nLength, pszFormat, args);
- #pragma warning(pop)
- }
-
- static int __stdcall GetBaseTypeLength(LPCSTR pszSrc)
- {
- // Returns required buffer size in wchar_ts
- return ::MultiByteToWideChar(CP_ACP, 0, pszSrc, -1, nullptr, 0)-1;
- }
-
- static int __stdcall GetBaseTypeLength(LPCSTR pszSrc, int nLength)
- {
- // Returns required buffer size in wchar_ts
- return ::MultiByteToWideChar(CP_ACP, 0, pszSrc, nLength, nullptr, 0);
- }
-
- static int __stdcall GetBaseTypeLength(LPCWSTR pszSrc)
- {
- // Returns required buffer size in wchar_ts
- return (int)wcslen(pszSrc);
- }
-
- static int __stdcall GetBaseTypeLength(LPCWSTR pszSrc, int nLength)
- {
- (void)pszSrc;
- // Returns required buffer size in wchar_ts
- return nLength;
- }
-
- static void __stdcall ConvertToBaseType(LPWSTR pszDest, int nDestLength, LPCSTR pszSrc, int nSrcLength = -1)
- {
- // nLen is in wchar_ts
- ::MultiByteToWideChar(CP_ACP, 0, pszSrc, nSrcLength, pszDest, nDestLength);
- }
-
- static void __stdcall ConvertToBaseType(LPWSTR pszDest, int nDestLength, LPCWSTR pszSrc, int nSrcLength = -1)
- {
- if (nSrcLength == -1) { nSrcLength=1 + GetBaseTypeLength(pszSrc); }
- // nLen is in wchar_ts
- #if _MSC_VER >= 1400
- wmemcpy_s(pszDest, nDestLength, pszSrc, nSrcLength);
- #else
- wmemcpy(pszDest, pszSrc, nDestLength);
- #endif
- }
-
- static void __stdcall FloodCharacters(wchar_t ch, int nLength, LPWSTR psz)
- {
- // nLength is in XCHARs
- for (int i = 0; i < nLength; i++)
- {
- psz[i] = ch;
- }
- }
-
- static int __stdcall SafeStringLen(LPCSTR psz)
- {
- // returns length in bytes
- return (psz != nullptr) ? (int)strlen(psz) : 0;
- }
-
- static int __stdcall SafeStringLen(LPCWSTR psz)
- {
- // returns length in wchar_ts
- return (psz != nullptr) ? (int)wcslen(psz) : 0;
- }
-
- static int __stdcall GetCharLen(const wchar_t* pch)
- {
- (void)pch;
- // returns char length
- return 1;
- }
-
- static int __stdcall GetCharLen(const char* pch)
- {
- // returns char length
- return (int)(_mbclen(reinterpret_cast< const unsigned char* >(pch)));
- }
-
- static DWORD __stdcall GetEnvironmentVariable(LPCWSTR pszVar, LPWSTR pszBuffer, DWORD dwSize)
- {
- return _GetEnvironmentVariableW(pszVar, pszBuffer, dwSize);
- }
-
- static void __stdcall ConvertToOem(LPWSTR /*psz*/)
- {
- }
-
- static void __stdcall ConvertToAnsi(LPWSTR /*psz*/)
- {
- }
-
- static void __stdcall ConvertToOem(LPWSTR /*psz*/, size_t)
- {
- }
-
- static void __stdcall ConvertToAnsi(LPWSTR /*psz*/, size_t)
- {
- }
-
- static LPWSTR MirCopy(LPCWSTR pstrString, size_t size)
- {
- return mir_wstrndup(pstrString, size);
- }
-};
-
-template< typename BaseType, class StringTraits >
-class MIR_CORE_EXPORT CMStringT : public CMSimpleStringT< BaseType >
-{
-public:
- typedef CMSimpleStringT< BaseType> CThisSimpleString;
- typedef typename CThisSimpleString::XCHAR XCHAR;
- typedef typename CThisSimpleString::PXSTR PXSTR;
- typedef typename CThisSimpleString::PCXSTR PCXSTR;
- typedef typename CThisSimpleString::YCHAR YCHAR;
- typedef typename CThisSimpleString::PYSTR PYSTR;
- typedef typename CThisSimpleString::PCYSTR PCYSTR;
-
-public:
- CMStringT();
-
- // Copy constructor
- CMStringT(const CMStringT& strSrc);
-
- CMStringT(const XCHAR* pszSrc);
- CMStringT(CMStringDataFormat, _Printf_format_string_ const XCHAR* pszFormat, ...);
-
- CMStringT(const YCHAR* pszSrc);
- CMStringT(const unsigned char* pszSrc);
-
- CMStringT(char ch, int nLength = 1);
- CMStringT(wchar_t ch, int nLength = 1);
-
- CMStringT(const XCHAR* pch, int nLength);
- CMStringT(const YCHAR* pch, int nLength);
-
- // Destructor
- ~CMStringT();
-
- // Assignment operators
- 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;
- 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);
-
- // Insert character 'ch' before index 'iIndex'
- int Insert(int iIndex, XCHAR ch);
-
- // Insert string 'psz' before index 'iIndex'
- int Insert(int iIndex, PCXSTR psz);
-
- // Replace all occurrences of character 'chOld' with character 'chNew'
- int Replace(XCHAR chOld, XCHAR chNew);
-
- // Replace all occurrences of string 'pszOld' with string 'pszNew'
- int Replace(PCXSTR pszOld, PCXSTR pszNew);
-
- // Remove all occurrences of character 'chRemove'
- int Remove(XCHAR chRemove);
-
- 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;
-
- // 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;
-
- // Find the first occurrence of any of the characters in string 'pszCharSet'
- int FindOneOf(PCXSTR pszCharSet) const;
-
- // Find the last occurrence of character 'ch'
- int ReverseFind(XCHAR ch) const;
-
- // manipulation
-
- // Convert the string to uppercase
- CMStringT& MakeUpper();
-
- // Convert the string to lowercase
- CMStringT& MakeLower();
-
- // Reverse the string
- CMStringT& MakeReverse();
-
- // trimming
-
- // Remove all trailing whitespace
- CMStringT& TrimRight();
-
- // Remove all leading whitespace
- CMStringT& TrimLeft();
-
- // Remove all leading and trailing whitespace
- CMStringT& Trim();
-
- // Remove all leading and trailing occurrences of character 'chTarget'
- CMStringT& Trim(XCHAR chTarget);
-
- // Remove all leading and trailing occurrences of any of the characters in the string 'pszTargets'
- CMStringT& Trim(PCXSTR pszTargets);
-
- // trimming anything (either side)
-
- // Remove all trailing occurrences of character 'chTarget'
- CMStringT& TrimRight(XCHAR chTarget);
-
- // Remove all trailing occurrences of any of the characters in string 'pszTargets'
- CMStringT& TrimRight(PCXSTR pszTargets);
-
- // Remove all leading occurrences of character 'chTarget'
- CMStringT& TrimLeft(XCHAR chTarget);
-
- // Remove all leading occurrences of any of the characters in string 'pszTargets'
- CMStringT& TrimLeft(PCXSTR pszTargets);
-
- // Convert the string to the OEM character set
- void AnsiToOem();
-
- // Convert the string to the ANSI character set
- void OemToAnsi();
-
- // Very simple sub-string extraction
-
- // Return the substring starting at index 'iFirst'
- CMStringT Mid(int iFirst) const;
-
- // Return the substring starting at index 'iFirst', with length 'nCount'
- CMStringT Mid(int iFirst, int nCount) const;
-
- // Return the substring consisting of the rightmost 'nCount' characters
- CMStringT Right(int nCount) const;
-
- // Return the substring consisting of the leftmost 'nCount' characters
- CMStringT Left(int nCount) const;
-
- // Return the substring consisting of the leftmost characters in the set 'pszCharSet'
- CMStringT SpanIncluding(PCXSTR pszCharSet) const;
-
- // Return the substring consisting of the leftmost characters not in the set 'pszCharSet'
- CMStringT SpanExcluding(PCXSTR pszCharSet) const;
-
- // Format data using format string 'pszFormat'
- PCXSTR Format(PCXSTR _Printf_format_string_ pszFormat, ...);
- PCXSTR FormatV(PCXSTR _Printf_format_string_ pszFormat, va_list args);
-
- // Append formatted data using format string 'pszFormat'
- PCXSTR AppendFormat(PCXSTR _Printf_format_string_ pszFormat, ...);
- void AppendFormatV(PCXSTR _Printf_format_string_ pszFormat, va_list args);
-
- // return a copy of string to be freed by mir_free()
- PXSTR Detach() const;
-
- // Set the string to the value of environment variable 'pszVar'
- BOOL GetEnvironmentVariable(PCXSTR pszVar);
-
- 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; }
-
- 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; }
-
- 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, 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, 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, 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==(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 __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); }
-};
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, const CMStringT<BaseType, StringTraits>& str2);
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, typename CMStringT<BaseType, StringTraits>::PCXSTR psz2);
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(typename CMStringT<BaseType, StringTraits>::PCXSTR psz1, const CMStringT<BaseType, StringTraits>& str2);
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, wchar_t ch2);
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, char ch2);
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator + (wchar_t ch1, const CMStringT<BaseType, StringTraits>& str2);
-
-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;
-
-#endif // M_STRING_H__
+/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-21 Miranda NG team (https://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_H__ +#define M_STRING_H__ + +#include <stdio.h> +#include <string.h> + +#ifdef _WINDOWS +#include <mbstring.h> +#endif // _WINDOWS +#include <wchar.h> + +#include <m_core.h> + +#ifdef __MINGW32__ +#include <limits.h> + +__inline size_t strnlen(const char *string, size_t maxlen) +{ + const char *end = (const char *)memchr ((const void *)string, '\0', maxlen); + return end ? (size_t) (end - string) : maxlen; +} +__inline size_t wcsnlen(const wchar_t *string, size_t maxlen) +{ + const wchar_t *end = wmemchr (string, L'\0', maxlen); + return end ? (size_t) (end - string) : maxlen; +} + +/* FIXME: This may be wrong assumption about Langpack_GetDefaultCodePage */ +#define Langpack_GetDefaultCodePage() CP_THREAD_ACP +/* FIXME: This is unsafe */ +#define memcpy_s(dest,size,src,count) memcpy(dest,src,count) +/* FIXME: This is quite silly implementation of _mbsstr */ +#define _mbsstr(str,search) strstr((const char *)str,(const char *)search) +#define __max(x,y) (((x)<(y))?(y):(x)) +#endif /* __MINGW32__ */ + +///////////////////////////////////////////////////////////////////////////////////////// + +struct CMStringData; + +MIR_CORE_DLL(CMStringData*) mirstr_allocate(int nChars, int nCharSize); +MIR_CORE_DLL(void) mirstr_free(CMStringData *pData); +MIR_CORE_DLL(CMStringData*) mirstr_realloc(CMStringData* pData, int nChars, int nCharSize); +MIR_CORE_DLL(CMStringData*) mirstr_getNil(); + +MIR_CORE_DLL(void) mirstr_lock(CMStringData* pThis); +MIR_CORE_DLL(void) mirstr_release(CMStringData* pThis); +MIR_CORE_DLL(void) mirstr_unlock(CMStringData* pThis); + +///////////////////////////////////////////////////////////////////////////////////////// + +enum CMStringDataFormat { FORMAT }; + +struct CMStringData +{ + int nDataLength; // Length of currently used data in XCHARs (not including terminating null) + int nAllocLength; // Length of allocated data in XCHARs (not including terminating null) + long nRefs; // Reference count: negative == locked + + __forceinline void* data() { return (this + 1); } + __forceinline void AddRef() { InterlockedIncrement(&nRefs); } + __forceinline bool IsLocked() const { return nRefs < 0; } + __forceinline bool IsShared() const { return nRefs > 1; } + + __forceinline void Lock() { mirstr_lock(this); } + __forceinline void Release() { mirstr_release(this); } + __forceinline void Unlock() { mirstr_unlock(this); } +}; + +template< typename BaseType = char > +class ChTraitsBase +{ +public: + typedef char XCHAR; + typedef LPSTR PXSTR; + typedef LPCSTR PCXSTR; + typedef wchar_t YCHAR; + typedef LPWSTR PYSTR; + typedef LPCWSTR PCYSTR; +}; + +template<> +class ChTraitsBase< wchar_t > +{ +public: + typedef wchar_t XCHAR; + typedef LPWSTR PXSTR; + typedef LPCWSTR PCXSTR; + typedef char YCHAR; + typedef LPSTR PYSTR; + typedef LPCSTR PCYSTR; +}; + +template< typename BaseType > +class CMSimpleStringT +{ +public: + typedef typename ChTraitsBase< BaseType >::XCHAR XCHAR; + typedef typename ChTraitsBase< BaseType >::PXSTR PXSTR; + typedef typename ChTraitsBase< BaseType >::PCXSTR PCXSTR; + typedef typename ChTraitsBase< BaseType >::YCHAR YCHAR; + typedef typename ChTraitsBase< BaseType >::PYSTR PYSTR; + typedef typename ChTraitsBase< BaseType >::PCYSTR PCYSTR; + +public: + explicit CMSimpleStringT(); + + CMSimpleStringT(const CMSimpleStringT& strSrc); + CMSimpleStringT(PCXSTR pszSrc); + CMSimpleStringT(const XCHAR* pchSrc, int nLength); + ~CMSimpleStringT(); + + __forceinline operator CMSimpleStringT<BaseType>&() + { return *(CMSimpleStringT<BaseType>*)this; + } + + CMSimpleStringT& operator=(const CMSimpleStringT& strSrc); + + __forceinline CMSimpleStringT& operator=(PCXSTR pszSrc) + { SetString(pszSrc); + return *this; + } + + __forceinline CMSimpleStringT& operator+=(const CMSimpleStringT& strSrc) + { Append(strSrc); + return *this; + } + + __forceinline CMSimpleStringT& operator+=(PCXSTR pszSrc) + { Append(pszSrc); + return *this; + } + + __forceinline CMSimpleStringT& operator+=(char ch) + { AppendChar(XCHAR(ch)); + return *this; + } + + __forceinline CMSimpleStringT& operator+=(unsigned char ch) + { AppendChar(XCHAR(ch)); + return *this; + } + + __forceinline CMSimpleStringT& operator+=(wchar_t ch) + { AppendChar(XCHAR(ch)); + return *this; + } + + __forceinline XCHAR operator[](int iChar) const + { return m_pszData[iChar]; + } + + __forceinline operator PCXSTR() const + { return m_pszData; + } + + __forceinline PCXSTR c_str() const + { return m_pszData; + } + + __forceinline int GetAllocLength() const + { return GetData()->nAllocLength; + } + + __forceinline XCHAR GetAt(int iChar) const + { return m_pszData[iChar]; + } + + __forceinline PXSTR GetBuffer(int nMinBufferLength) + { return PrepareWrite(nMinBufferLength); + } + + __forceinline int GetLength() const + { return GetData()->nDataLength; + } + + __forceinline PCXSTR GetString() const + { return m_pszData; + } + + __forceinline PCXSTR GetTail() const + { return m_pszData + GetData()->nDataLength; + } + + __forceinline bool IsEmpty() const + { return GetLength() == 0; + } + + __forceinline void Preallocate(int nLength) + { PrepareWrite(nLength); + } + + __forceinline void ReleaseBufferSetLength(int nNewLength) + { SetLength(nNewLength); + } + + void Append(PCXSTR pszSrc); + void Append(PCXSTR pszSrc, int nLength); + void AppendChar(XCHAR ch); + void Append(const CMSimpleStringT& strSrc); + + void Empty(); + void FreeExtra(); + + PXSTR GetBuffer(); + PXSTR GetBufferSetLength(int nLength); + + PXSTR LockBuffer(); + void UnlockBuffer(); + + void ReleaseBuffer(int nNewLength = -1); + + void Truncate(int nNewLength); + void SetAt(int iChar, XCHAR ch); + void SetString(PCXSTR pszSrc); + void SetString(PCXSTR pszSrc, int nLength); + +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 MIR_SYSCALL CopyChars(XCHAR* pchDest, const XCHAR* pchSrc, int nChars); + static void MIR_SYSCALL CopyChars(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars); + static void MIR_SYSCALL CopyCharsOverlapped(XCHAR* pchDest, const XCHAR* pchSrc, int nChars); + static void MIR_SYSCALL CopyCharsOverlapped(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars); + static int MIR_SYSCALL StringLength(const char* psz); + static int MIR_SYSCALL StringLength(const wchar_t* psz); + static int MIR_SYSCALL StringLengthN(const char* psz, size_t sizeInXChar); + static int MIR_SYSCALL StringLengthN(const wchar_t* psz, size_t sizeInXChar); + static void MIR_SYSCALL Concatenate(CMSimpleStringT& strResult, PCXSTR psz1, int nLength1, PCXSTR psz2, int nLength2); + + // Implementation +private: + __forceinline CMStringData* GetData() const + { return (reinterpret_cast<CMStringData *>(m_pszData)-1); + } + + 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* MIR_SYSCALL CloneData(CMStringData* pData); + +private: + PXSTR m_pszData; +}; + + +template< typename _CharType = char > +class ChTraitsCRT : public ChTraitsBase < _CharType > +{ +public: + static char* MIR_SYSCALL CharNext(const char* p) + { + return reinterpret_cast<char*>(_mbsinc(reinterpret_cast<const unsigned char*>(p))); + } + + static int MIR_SYSCALL IsDigit(char ch) + { + return _ismbcdigit(ch); + } + + static int MIR_SYSCALL IsSpace(char ch) + { + return _ismbcspace(ch); + } + + static int MIR_SYSCALL StringCompare(LPCSTR pszA, LPCSTR pszB) + { + return _mbscmp(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB)); + } + + static int MIR_SYSCALL StringCompareIgnore(LPCSTR pszA, LPCSTR pszB) + { + return _mbsicmp(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB)); + } + + static int MIR_SYSCALL StringCollate(LPCSTR pszA, LPCSTR pszB) + { + return _mbscoll(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB)); + } + + static int MIR_SYSCALL StringCollateIgnore(LPCSTR pszA, LPCSTR pszB) + { + return _mbsicoll(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB)); + } + + static LPCSTR MIR_SYSCALL StringFindString(LPCSTR pszBlock, LPCSTR pszMatch) + { + return reinterpret_cast<LPCSTR>(_mbsstr(reinterpret_cast<const unsigned char*>(pszBlock), + reinterpret_cast<const unsigned char*>(pszMatch))); + } + + static LPSTR MIR_SYSCALL StringFindString(LPSTR pszBlock, LPCSTR pszMatch) + { + return const_cast<LPSTR>(StringFindString(const_cast<LPCSTR>(pszBlock), pszMatch)); + } + + static LPCSTR MIR_SYSCALL StringFindChar(LPCSTR pszBlock, char chMatch) + { + return reinterpret_cast<LPCSTR>(_mbschr(reinterpret_cast<const unsigned char*>(pszBlock), (unsigned char)chMatch)); + } + + static LPCSTR MIR_SYSCALL StringFindCharRev(LPCSTR psz, char ch) + { + return reinterpret_cast<LPCSTR>(_mbsrchr(reinterpret_cast<const unsigned char*>(psz), (unsigned char)ch)); + } + + static LPCSTR MIR_SYSCALL StringScanSet(LPCSTR pszBlock, LPCSTR pszMatch) + { + return reinterpret_cast<LPCSTR>(_mbspbrk(reinterpret_cast<const unsigned char*>(pszBlock), + reinterpret_cast<const unsigned char*>(pszMatch))); + } + + static int MIR_SYSCALL StringSpanIncluding(LPCSTR pszBlock, LPCSTR pszSet) + { + return (int)_mbsspn(reinterpret_cast<const unsigned char*>(pszBlock), reinterpret_cast<const unsigned char*>(pszSet)); + } + + static int MIR_SYSCALL StringSpanExcluding(LPCSTR pszBlock, LPCSTR pszSet) + { + return (int)_mbscspn(reinterpret_cast<const unsigned char*>(pszBlock), reinterpret_cast<const unsigned char*>(pszSet)); + } + + static LPSTR MIR_SYSCALL StringUppercase(LPSTR psz) + { + CharUpperBuffA(psz, (DWORD)strlen(psz)); + return psz; + } + + static LPSTR MIR_SYSCALL StringLowercase(LPSTR psz) + { + CharLowerBuffA(psz, (DWORD)strlen(psz)); + return psz; + } + + static LPSTR MIR_SYSCALL StringUppercase(LPSTR psz, size_t size) + { + CharUpperBuffA(psz, (DWORD)size); + return psz; + } + + static LPSTR MIR_SYSCALL StringLowercase(LPSTR psz, size_t size) + { + CharLowerBuffA(psz, (DWORD)size); + return psz; + } + + static LPSTR MIR_SYSCALL StringReverse(LPSTR psz) + { + return reinterpret_cast<LPSTR>(_mbsrev(reinterpret_cast<unsigned char*>(psz))); + } + + static int MIR_SYSCALL GetFormattedLength(_Printf_format_string_ LPCSTR pszFormat, va_list args) + { + return _vscprintf(pszFormat, args); + } + + static int MIR_SYSCALL Format(LPSTR pszBuffer, size_t nlength, _Printf_format_string_ LPCSTR pszFormat, va_list args) + { + return vsprintf_s(pszBuffer, nlength, pszFormat, args); + } + + static int MIR_SYSCALL GetBaseTypeLength(LPCSTR pszSrc) + { + // Returns required buffer length in XCHARs + return int(strlen(pszSrc)); + } + + static int MIR_SYSCALL GetBaseTypeLength(LPCSTR pszSrc, int nLength) + { + (void)pszSrc; + // Returns required buffer length in XCHARs + return nLength; + } + + static int MIR_SYSCALL GetBaseTypeLength(LPCWSTR pszSource) + { + // Returns required buffer length in XCHARs + #ifdef _MSC_VER + return ::WideCharToMultiByte(Langpack_GetDefaultCodePage(), 0, pszSource, -1, NULL, 0, NULL, NULL) - 1; + #else + return 0; + #endif + } + + static int MIR_SYSCALL GetBaseTypeLength(LPCWSTR pszSource, int nLength) + { + // Returns required buffer length in XCHARs + #ifdef _MSC_VER + return ::WideCharToMultiByte(Langpack_GetDefaultCodePage(), 0, pszSource, nLength, NULL, 0, NULL, NULL); + #else + return 0; + #endif + } + + static void MIR_SYSCALL ConvertToBaseType(LPSTR pszDest, int nDestLength, LPCSTR pszSrc, int nSrcLength = -1) + { + if (nSrcLength == -1) { nSrcLength = 1 + GetBaseTypeLength(pszSrc); } + // nLen is in XCHARs + memcpy_s(pszDest, nDestLength*sizeof(char), pszSrc, nSrcLength*sizeof(char)); + } + + static void MIR_SYSCALL ConvertToBaseType(LPSTR pszDest, int nDestLength, LPCWSTR pszSrc, int nSrcLength = -1) + { + // nLen is in XCHARs + #ifdef _MSC_VER + ::WideCharToMultiByte(Langpack_GetDefaultCodePage(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL); + #endif + } + + static void ConvertToOem(_CharType* pstrString) + { + #ifdef _MSC_VER + BOOL fSuccess = ::CharToOemA(pstrString, pstrString); + #endif // _MSC_VER + } + + static void ConvertToAnsi(_CharType* pstrString) + { + #ifdef _MSC_VER + BOOL fSuccess = ::OemToCharA(pstrString, pstrString); + #endif + } + + static void ConvertToOem(_CharType* pstrString, size_t size) + { + #ifdef _MSC_VER + DWORD dwSize = static_cast<DWORD>(size); + ::CharToOemBuffA(pstrString, pstrString, dwSize); + #endif + } + + static void ConvertToAnsi(_CharType* pstrString, size_t size) + { + #ifdef _MSC_VER + DWORD dwSize = static_cast<DWORD>(size); + ::OemToCharBuffA(pstrString, pstrString, dwSize); + #endif + } + + static void MIR_SYSCALL FloodCharacters(char ch, int nLength, char* pch) + { + // nLength is in XCHARs + memset(pch, ch, nLength); + } + + static int MIR_SYSCALL SafeStringLen(LPCSTR psz) + { + // returns length in bytes + return (psz != NULL) ? int(strlen(psz)) : 0; + } + + static int MIR_SYSCALL SafeStringLen(LPCWSTR psz) + { + // returns length in wchar_ts + return (psz != NULL) ? int(wcslen(psz)) : 0; + } + + static int MIR_SYSCALL GetCharLen(const wchar_t* pch) + { + // returns char length + return 1; + } + + static int MIR_SYSCALL GetCharLen(const char* pch) + { + // returns char length + return int(_mbclen(reinterpret_cast<const unsigned char*>(pch))); + } + + static DWORD MIR_SYSCALL GetEnvironmentVariable(LPCSTR pszVar, LPSTR pszBuffer, DWORD dwSize) + { + #ifdef _MSC_VER + return ::GetEnvironmentVariableA(pszVar, pszBuffer, dwSize); + #endif // _MSC_VER + } + + static char* MirCopy(const char *pstrString, size_t size) + { + return mir_strndup(pstrString, size); + } +}; + +// specialization for wchar_t +template<> +class ChTraitsCRT< wchar_t > : public ChTraitsBase< wchar_t > +{ + static DWORD MIR_SYSCALL _GetEnvironmentVariableW(LPCWSTR pszName, LPWSTR pszBuffer, DWORD nSize) + { + #ifdef _MSC_VER + return ::GetEnvironmentVariableW(pszName, pszBuffer, nSize); + #endif // _MSC_VER + } + +public: + static LPWSTR MIR_SYSCALL CharNext(LPCWSTR psz) + { + return const_cast< LPWSTR >(psz+1); + } + + static int MIR_SYSCALL IsDigit(wchar_t ch) + { + #ifdef _MSC_VER + return iswdigit(static_cast<unsigned short>(ch)); + #else + return 0; + #endif + } + + static int MIR_SYSCALL IsSpace(wchar_t ch) + { + #ifdef _MSC_VER + return iswspace(static_cast<unsigned short>(ch)); + #else + return 0; + #endif + } + + static int MIR_SYSCALL StringCompare(LPCWSTR pszA, LPCWSTR pszB) + { + return wcscmp(pszA, pszB); + } + + static int MIR_SYSCALL StringCompareIgnore(LPCWSTR pszA, LPCWSTR pszB) + { + #ifdef _MSC_VER + return _wcsicmp(pszA, pszB); + #else + return 0; + #endif + } + + static int MIR_SYSCALL StringCollate(LPCWSTR pszA, LPCWSTR pszB) + { + return wcscoll(pszA, pszB); + } + + static int MIR_SYSCALL StringCollateIgnore(LPCWSTR pszA, LPCWSTR pszB) + { + #ifdef _MSC_VER + return _wcsicoll(pszA, pszB); + #else + return 0; + #endif + } + + static LPCWSTR MIR_SYSCALL StringFindString(LPCWSTR pszBlock, LPCWSTR pszMatch) + { + return wcsstr(pszBlock, pszMatch); + } + + static LPWSTR MIR_SYSCALL StringFindString(LPWSTR pszBlock, LPCWSTR pszMatch) + { + return const_cast< LPWSTR >(StringFindString(const_cast< LPCWSTR >(pszBlock), pszMatch)); + } + + static LPCWSTR MIR_SYSCALL StringFindChar(LPCWSTR pszBlock, wchar_t chMatch) + { + return wcschr(pszBlock, chMatch); + } + + static LPCWSTR MIR_SYSCALL StringFindCharRev(LPCWSTR psz, wchar_t ch) + { + return wcsrchr(psz, ch); + } + + static LPCWSTR MIR_SYSCALL StringScanSet(LPCWSTR pszBlock, LPCWSTR pszMatch) + { + return wcspbrk(pszBlock, pszMatch); + } + + static int MIR_SYSCALL StringSpanIncluding(LPCWSTR pszBlock, LPCWSTR pszSet) + { + return (int)wcsspn(pszBlock, pszSet); + } + + static int MIR_SYSCALL StringSpanExcluding(LPCWSTR pszBlock, LPCWSTR pszSet) + { + return (int)wcscspn(pszBlock, pszSet); + } + + static LPWSTR MIR_SYSCALL StringUppercase(LPWSTR psz) + { + #ifdef _MSC_VER + CharUpperBuffW(psz, (DWORD)wcslen(psz)); + #endif + return psz; + } + + static LPWSTR MIR_SYSCALL StringLowercase(LPWSTR psz) + { + #ifdef _MSC_VER + CharLowerBuffW(psz, (DWORD)wcslen(psz)); + #endif + return psz; + } + + static LPWSTR MIR_SYSCALL StringUppercase(LPWSTR psz, size_t len) + { + #ifdef _MSC_VER + CharUpperBuffW(psz, (DWORD)len); + #endif + return psz; + } + + static LPWSTR MIR_SYSCALL StringLowercase(LPWSTR psz, size_t len) + { + #ifdef _MSC_VER + CharLowerBuffW(psz, (DWORD)len); + #endif + return psz; + } + + static LPWSTR MIR_SYSCALL StringReverse(LPWSTR psz) + { + #ifdef _MSC_VER + return _wcsrev(psz); + #else + return psz; + #endif + } + + static int MIR_SYSCALL GetFormattedLength(_Printf_format_string_ LPCWSTR pszFormat, va_list args) + { + #ifdef _MSC_VER + return _vscwprintf(pszFormat, args); + #else + return 0; + #endif + } + + static int MIR_SYSCALL Format(LPWSTR pszBuffer, _Printf_format_string_ LPCWSTR pszFormat, va_list args) + { + #pragma warning(push) + #pragma warning(disable : 4996) + + #ifdef _MSC_VER + return vswprintf(pszBuffer, pszFormat, args); + #else + return 0; + #endif + #pragma warning(pop) + } + + static int MIR_SYSCALL Format(LPWSTR pszBuffer, size_t nLength, _Printf_format_string_ LPCWSTR pszFormat, va_list args) + { + #pragma warning(push) + #pragma warning(disable : 4996) + + #ifdef _MSC_VER + return _vsnwprintf(pszBuffer, nLength, pszFormat, args); + #else + return 0; + #endif + + #pragma warning(pop) + } + + static int MIR_SYSCALL GetBaseTypeLength(LPCSTR pszSrc) + { + // Returns required buffer size in wchar_ts + #ifdef _MSC_VER + return ::MultiByteToWideChar(CP_ACP, 0, pszSrc, -1, nullptr, 0)-1; + #else + return 0; + #endif + } + + static int MIR_SYSCALL GetBaseTypeLength(LPCSTR pszSrc, int nLength) + { + // Returns required buffer size in wchar_ts + #ifdef _MSC_VER + return ::MultiByteToWideChar(CP_ACP, 0, pszSrc, nLength, nullptr, 0); + #else + return 0; + #endif + } + + static int MIR_SYSCALL GetBaseTypeLength(LPCWSTR pszSrc) + { + // Returns required buffer size in wchar_ts + return (int)wcslen(pszSrc); + } + + static int MIR_SYSCALL GetBaseTypeLength(LPCWSTR pszSrc, int nLength) + { + (void)pszSrc; + // Returns required buffer size in wchar_ts + return nLength; + } + + static void MIR_SYSCALL ConvertToBaseType(LPWSTR pszDest, int nDestLength, LPCSTR pszSrc, int nSrcLength = -1) + { + // nLen is in wchar_ts + #ifdef _MSC_VER + ::MultiByteToWideChar(CP_ACP, 0, pszSrc, nSrcLength, pszDest, nDestLength); + #endif + } + + static void MIR_SYSCALL ConvertToBaseType(LPWSTR pszDest, int nDestLength, LPCWSTR pszSrc, int nSrcLength = -1) + { + if (nSrcLength == -1) { nSrcLength=1 + GetBaseTypeLength(pszSrc); } + // nLen is in wchar_ts + #if _MSC_VER >= 1400 + wmemcpy_s(pszDest, nDestLength, pszSrc, nSrcLength); + #else + wmemcpy(pszDest, pszSrc, nDestLength); + #endif + } + + static void MIR_SYSCALL FloodCharacters(wchar_t ch, int nLength, LPWSTR psz) + { + // nLength is in XCHARs + for (int i = 0; i < nLength; i++) + { + psz[i] = ch; + } + } + + static int MIR_SYSCALL SafeStringLen(LPCSTR psz) + { + // returns length in bytes + return (psz != nullptr) ? (int)strlen(psz) : 0; + } + + static int MIR_SYSCALL SafeStringLen(LPCWSTR psz) + { + // returns length in wchar_ts + return (psz != nullptr) ? (int)wcslen(psz) : 0; + } + + static int MIR_SYSCALL GetCharLen(const wchar_t* pch) + { + (void)pch; + // returns char length + return 1; + } + + static int MIR_SYSCALL GetCharLen(const char* pch) + { + // returns char length + #ifdef _MSC_VER + return (int)(_mbclen(reinterpret_cast< const unsigned char* >(pch))); + #else + return mblen(pch, strlen(pch)); + #endif + } + + static DWORD MIR_SYSCALL GetEnvironmentVariable(LPCWSTR pszVar, LPWSTR pszBuffer, DWORD dwSize) + { + return _GetEnvironmentVariableW(pszVar, pszBuffer, dwSize); + } + + static void MIR_SYSCALL ConvertToOem(LPWSTR /*psz*/) + { + } + + static void MIR_SYSCALL ConvertToAnsi(LPWSTR /*psz*/) + { + } + + static void MIR_SYSCALL ConvertToOem(LPWSTR /*psz*/, size_t) + { + } + + static void MIR_SYSCALL ConvertToAnsi(LPWSTR /*psz*/, size_t) + { + } + + static LPWSTR MirCopy(LPCWSTR pstrString, size_t size) + { + return mir_wstrndup(pstrString, size); + } +}; + +template< typename BaseType, class StringTraits > +class MIR_CORE_EXPORT CMStringT : public CMSimpleStringT< BaseType > +{ +public: + typedef CMSimpleStringT< BaseType> CThisSimpleString; + typedef typename CThisSimpleString::XCHAR XCHAR; + typedef typename CThisSimpleString::PXSTR PXSTR; + typedef typename CThisSimpleString::PCXSTR PCXSTR; + typedef typename CThisSimpleString::YCHAR YCHAR; + typedef typename CThisSimpleString::PYSTR PYSTR; + typedef typename CThisSimpleString::PCYSTR PCYSTR; + +public: + CMStringT(); + + // Copy constructor + CMStringT(const CMStringT& strSrc); + + CMStringT(const XCHAR* pszSrc); + CMStringT(CMStringDataFormat, _Printf_format_string_ const XCHAR* pszFormat, ...); + + CMStringT(const YCHAR* pszSrc); + CMStringT(const unsigned char* pszSrc); + + CMStringT(char ch, int nLength = 1); + CMStringT(wchar_t ch, int nLength = 1); + + CMStringT(const XCHAR* pch, int nLength); + CMStringT(const YCHAR* pch, int nLength); + + // Destructor + ~CMStringT(); + + // Assignment operators + 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; + 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); + + // Insert character 'ch' before index 'iIndex' + int Insert(int iIndex, XCHAR ch); + + // Insert string 'psz' before index 'iIndex' + int Insert(int iIndex, PCXSTR psz); + + // Replace all occurrences of character 'chOld' with character 'chNew' + int Replace(XCHAR chOld, XCHAR chNew); + + // Replace all occurrences of string 'pszOld' with string 'pszNew' + int Replace(PCXSTR pszOld, PCXSTR pszNew); + + // Remove all occurrences of character 'chRemove' + int Remove(XCHAR chRemove); + + 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; + + // 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; + + // Find the first occurrence of any of the characters in string 'pszCharSet' + int FindOneOf(PCXSTR pszCharSet) const; + + // Find the last occurrence of character 'ch' + int ReverseFind(XCHAR ch) const; + + // manipulation + + // Convert the string to uppercase + CMStringT& MakeUpper(); + + // Convert the string to lowercase + CMStringT& MakeLower(); + + // Reverse the string + CMStringT& MakeReverse(); + + // trimming + + // Remove all trailing whitespace + CMStringT& TrimRight(); + + // Remove all leading whitespace + CMStringT& TrimLeft(); + + // Remove all leading and trailing whitespace + CMStringT& Trim(); + + // Remove all leading and trailing occurrences of character 'chTarget' + CMStringT& Trim(XCHAR chTarget); + + // Remove all leading and trailing occurrences of any of the characters in the string 'pszTargets' + CMStringT& Trim(PCXSTR pszTargets); + + // trimming anything (either side) + + // Remove all trailing occurrences of character 'chTarget' + CMStringT& TrimRight(XCHAR chTarget); + + // Remove all trailing occurrences of any of the characters in string 'pszTargets' + CMStringT& TrimRight(PCXSTR pszTargets); + + // Remove all leading occurrences of character 'chTarget' + CMStringT& TrimLeft(XCHAR chTarget); + + // Remove all leading occurrences of any of the characters in string 'pszTargets' + CMStringT& TrimLeft(PCXSTR pszTargets); + + // Convert the string to the OEM character set + void AnsiToOem(); + + // Convert the string to the ANSI character set + void OemToAnsi(); + + // Very simple sub-string extraction + + // Return the substring starting at index 'iFirst' + CMStringT Mid(int iFirst) const; + + // Return the substring starting at index 'iFirst', with length 'nCount' + CMStringT Mid(int iFirst, int nCount) const; + + // Return the substring consisting of the rightmost 'nCount' characters + CMStringT Right(int nCount) const; + + // Return the substring consisting of the leftmost 'nCount' characters + CMStringT Left(int nCount) const; + + // Return the substring consisting of the leftmost characters in the set 'pszCharSet' + CMStringT SpanIncluding(PCXSTR pszCharSet) const; + + // Return the substring consisting of the leftmost characters not in the set 'pszCharSet' + CMStringT SpanExcluding(PCXSTR pszCharSet) const; + + // Format data using format string 'pszFormat' + PCXSTR Format(PCXSTR _Printf_format_string_ pszFormat, ...); + PCXSTR FormatV(PCXSTR _Printf_format_string_ pszFormat, va_list args); + + // Append formatted data using format string 'pszFormat' + PCXSTR AppendFormat(PCXSTR _Printf_format_string_ pszFormat, ...); + void AppendFormatV(PCXSTR _Printf_format_string_ pszFormat, va_list args); + + // return a copy of string to be freed by mir_free() + PXSTR Detach() const; + + // Set the string to the value of environment variable 'pszVar' + BOOL GetEnvironmentVariable(PCXSTR pszVar); + + 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; } + + 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; } + + 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, 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, 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, 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==(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 __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); } +}; + +template< typename BaseType, class StringTraits > +MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, const CMStringT<BaseType, StringTraits>& str2); + +template< typename BaseType, class StringTraits > +MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, typename CMStringT<BaseType, StringTraits>::PCXSTR psz2); + +template< typename BaseType, class StringTraits > +MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(typename CMStringT<BaseType, StringTraits>::PCXSTR psz1, const CMStringT<BaseType, StringTraits>& str2); + +template< typename BaseType, class StringTraits > +MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, wchar_t ch2); + +template< typename BaseType, class StringTraits > +MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, char ch2); + +template< typename BaseType, class StringTraits > +MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator + (wchar_t ch1, const CMStringT<BaseType, StringTraits>& str2); + +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; + +#endif // M_STRING_H__ |