mirror of
https://github.com/reactos/reactos.git
synced 2025-01-01 03:54:02 +00:00
[ATL][ATL_APITEST] Implement / Improve CString, based upon the code that was already there. CORE-11579 #resolve
Add code + tests for: Conversion of A->W and W->A, equality operators, MakeLower, MakeUpper, Find, FindOneOf, ReverseFind, Compare, Mid, Left, Right, Format, Replace, Trim, TrimLeft, TrimRight. svn path=/trunk/; revision=72061
This commit is contained in:
parent
47be569e64
commit
684feb7418
7 changed files with 1158 additions and 5 deletions
|
@ -200,6 +200,28 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
CSimpleStringT& operator=(_In_ const CSimpleStringT& strSrc)
|
||||
{
|
||||
CStringData* pData = GetData();
|
||||
CStringData* pNewData = strSrc.GetData();
|
||||
|
||||
if (pNewData != pData)
|
||||
{
|
||||
if (!pData->IsLocked() && (pNewData->pStringMgr == pData->pStringMgr))
|
||||
{
|
||||
pNewData = CloneData(pNewData);
|
||||
pData->Release();
|
||||
Attach(pNewData);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetString(strSrc.GetString(), strSrc.GetLength());
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CSimpleStringT& operator+=(_In_ const CSimpleStringT& strSrc)
|
||||
{
|
||||
Append(strSrc);
|
||||
|
@ -495,7 +517,7 @@ private:
|
|||
if (pOldData->IsShared())
|
||||
{
|
||||
Fork(nLength);
|
||||
ATLASSERT(FALSE);
|
||||
//ATLASSERT(FALSE);
|
||||
}
|
||||
else if (pOldData->nAllocLength < nLength)
|
||||
{
|
||||
|
|
|
@ -124,6 +124,12 @@ public:
|
|||
|
||||
|
||||
typedef CStringT< wchar_t, StrTraitATL< wchar_t, ChTraitsCRT<wchar_t> > > CAtlStringW;
|
||||
typedef CStringT< char, StrTraitATL< char, ChTraitsCRT<char> > > CAtlStringA;
|
||||
|
||||
|
||||
typedef CAtlStringW CStringW;
|
||||
typedef CAtlStringA CStringA;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -28,14 +28,28 @@ public:
|
|||
|
||||
static int __cdecl GetBaseTypeLength(_In_z_ LPCWSTR pszSource) throw()
|
||||
{
|
||||
return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, -1, NULL, 0, NULL, NULL) - 1;
|
||||
if (pszSource == NULL) return -1;
|
||||
return static_cast<int>(wcslen(pszSource));
|
||||
}
|
||||
|
||||
static int __cdecl GetBaseTypeLength(_In_z_ LPCSTR pszSource) throw()
|
||||
{
|
||||
if (pszSource == NULL) return 0;
|
||||
return ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSource, -1, NULL, 0) - 1;
|
||||
}
|
||||
|
||||
static int __cdecl GetBaseTypeLength(
|
||||
_In_reads_(nLength) LPCWSTR pszSource,
|
||||
_In_ int nLength) throw()
|
||||
{
|
||||
return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0, NULL, NULL);
|
||||
return nLength;
|
||||
}
|
||||
|
||||
static int __cdecl GetBaseTypeLength(
|
||||
_In_reads_(nLength) LPCSTR pszSource,
|
||||
_In_ int nLength) throw()
|
||||
{
|
||||
return ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0);
|
||||
}
|
||||
|
||||
static void __cdecl ConvertToBaseType(
|
||||
|
@ -49,9 +63,198 @@ public:
|
|||
|
||||
wmemcpy(pszDest, pszSrc, nSrcLength);
|
||||
}
|
||||
|
||||
static void __cdecl ConvertToBaseType(
|
||||
_Out_writes_(nDestLength) LPWSTR pszDest,
|
||||
_In_ int nDestLength,
|
||||
_In_ LPCSTR pszSrc,
|
||||
_In_ int nSrcLength = -1)
|
||||
{
|
||||
if (nSrcLength == -1)
|
||||
nSrcLength = 1 + GetBaseTypeLength(pszSrc);
|
||||
|
||||
::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength);
|
||||
}
|
||||
|
||||
static void __cdecl MakeLower(
|
||||
_Out_writes_(nSrcLength) LPWSTR pszSource,
|
||||
_In_ int nSrcLength)
|
||||
{
|
||||
::CharLowerBuffW(pszSource, nSrcLength);
|
||||
}
|
||||
|
||||
static void __cdecl MakeUpper(
|
||||
_Out_writes_(nSrcLength) LPWSTR pszSource,
|
||||
_In_ int nSrcLength)
|
||||
{
|
||||
::CharUpperBuffW(pszSource, nSrcLength);
|
||||
}
|
||||
|
||||
static LPWSTR __cdecl FindString(
|
||||
_In_z_ LPCWSTR pszSource,
|
||||
_In_z_ LPCWSTR pszSub)
|
||||
{
|
||||
return ::wcsstr(pszSource, pszSub);
|
||||
}
|
||||
|
||||
static LPWSTR __cdecl FindChar(
|
||||
_In_z_ LPCWSTR pszSource,
|
||||
_In_ WCHAR ch)
|
||||
{
|
||||
return ::wcschr(pszSource, ch);
|
||||
}
|
||||
|
||||
static LPWSTR __cdecl FindCharReverse(
|
||||
_In_z_ LPCWSTR pszSource,
|
||||
_In_ WCHAR ch)
|
||||
{
|
||||
return ::wcsrchr(pszSource, ch);
|
||||
}
|
||||
|
||||
static LPWSTR __cdecl FindOneOf(
|
||||
_In_z_ LPCWSTR pszSource,
|
||||
_In_z_ LPCWSTR pszCharSet)
|
||||
{
|
||||
return ::wcspbrk(pszSource, pszCharSet);
|
||||
}
|
||||
|
||||
static int __cdecl Compare(
|
||||
_In_z_ LPCWSTR psz1,
|
||||
_In_z_ LPCWSTR psz2)
|
||||
{
|
||||
return ::wcscmp(psz1, psz2);
|
||||
}
|
||||
|
||||
static int __cdecl FormatV(
|
||||
_In_opt_z_ LPWSTR pszDest,
|
||||
_In_z_ LPCWSTR pszFormat,
|
||||
_In_ va_list args)
|
||||
{
|
||||
if (pszDest == NULL)
|
||||
return ::_vscwprintf(pszFormat, args);
|
||||
return ::vswprintf(pszDest, pszFormat, args);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Template specialization
|
||||
|
||||
template<>
|
||||
class ChTraitsCRT<char> : public ChTraitsBase<char>
|
||||
{
|
||||
public:
|
||||
|
||||
static int __cdecl GetBaseTypeLength(_In_z_ LPCWSTR pszSource) throw()
|
||||
{
|
||||
return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, -1, NULL, 0, NULL, NULL) - 1;
|
||||
}
|
||||
|
||||
static int __cdecl GetBaseTypeLength(_In_z_ LPCSTR pszSource) throw()
|
||||
{
|
||||
if (pszSource == NULL) return 0;
|
||||
return static_cast<int>(strlen(pszSource));
|
||||
}
|
||||
|
||||
static int __cdecl GetBaseTypeLength(
|
||||
_In_reads_(nLength) LPCWSTR pszSource,
|
||||
_In_ int nLength) throw()
|
||||
{
|
||||
return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
static int __cdecl GetBaseTypeLength(
|
||||
_In_reads_(nLength) LPCSTR pszSource,
|
||||
_In_ int nLength) throw()
|
||||
{
|
||||
return nLength;
|
||||
}
|
||||
|
||||
static void __cdecl ConvertToBaseType(
|
||||
_Out_writes_(nDestLength) LPSTR pszDest,
|
||||
_In_ int nDestLength,
|
||||
_In_ LPCWSTR pszSrc,
|
||||
_In_ int nSrcLength = -1)
|
||||
{
|
||||
if (nSrcLength == -1)
|
||||
nSrcLength = 1 + GetBaseTypeLength(pszSrc);
|
||||
|
||||
::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL);
|
||||
}
|
||||
|
||||
static void __cdecl ConvertToBaseType(
|
||||
_Out_writes_(nDestLength) LPSTR pszDest,
|
||||
_In_ int nDestLength,
|
||||
_In_ LPCSTR pszSrc,
|
||||
_In_ int nSrcLength = -1)
|
||||
{
|
||||
if (nSrcLength == -1)
|
||||
nSrcLength = 1 + GetBaseTypeLength(pszSrc);
|
||||
|
||||
memcpy(pszDest, pszSrc, nSrcLength);
|
||||
}
|
||||
|
||||
static void __cdecl MakeLower(
|
||||
_Out_writes_(nSrcLength) LPSTR pszSource,
|
||||
_In_ int nSrcLength)
|
||||
{
|
||||
::CharLowerBuffA(pszSource, nSrcLength);
|
||||
}
|
||||
|
||||
static void __cdecl MakeUpper(
|
||||
_Out_writes_(nSrcLength) LPSTR pszSource,
|
||||
_In_ int nSrcLength)
|
||||
{
|
||||
::CharUpperBuffA(pszSource, nSrcLength);
|
||||
}
|
||||
|
||||
static LPSTR __cdecl FindString(
|
||||
_In_z_ LPCSTR pszSource,
|
||||
_In_z_ LPCSTR pszSub)
|
||||
{
|
||||
return ::strstr(pszSource, pszSub);
|
||||
}
|
||||
|
||||
static LPSTR __cdecl FindChar(
|
||||
_In_z_ LPCSTR pszSource,
|
||||
_In_ CHAR ch)
|
||||
{
|
||||
return ::strchr(pszSource, ch);
|
||||
}
|
||||
|
||||
static LPSTR __cdecl FindCharReverse(
|
||||
_In_z_ LPCSTR pszSource,
|
||||
_In_ CHAR ch)
|
||||
{
|
||||
return ::strrchr(pszSource, ch);
|
||||
}
|
||||
|
||||
static LPSTR __cdecl FindOneOf(
|
||||
_In_z_ LPCSTR pszSource,
|
||||
_In_z_ LPCSTR pszCharSet)
|
||||
{
|
||||
return ::strpbrk(pszSource, pszCharSet);
|
||||
}
|
||||
|
||||
static int __cdecl Compare(
|
||||
_In_z_ LPCSTR psz1,
|
||||
_In_z_ LPCSTR psz2)
|
||||
{
|
||||
return ::strcmp(psz1, psz2);
|
||||
}
|
||||
|
||||
static int __cdecl FormatV(
|
||||
_In_opt_z_ LPSTR pszDest,
|
||||
_In_z_ LPCSTR pszFormat,
|
||||
_In_ va_list args)
|
||||
{
|
||||
if (pszDest == NULL)
|
||||
return ::_vscprintf(pszFormat, args);
|
||||
return ::vsprintf(pszDest, pszFormat, args);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
namespace _CSTRING_IMPL_
|
||||
{
|
||||
|
@ -63,6 +266,8 @@ namespace _CSTRING_IMPL_
|
|||
}
|
||||
|
||||
|
||||
// TODO: disable conversion functions when _CSTRING_DISABLE_NARROW_WIDE_CONVERSION is defined.
|
||||
|
||||
template <typename BaseType, class StringTraits>
|
||||
class CStringT :
|
||||
public CSimpleStringT <BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits>
|
||||
|
@ -90,7 +295,7 @@ public:
|
|||
|
||||
static void __cdecl Construct(_In_ CStringT* pString)
|
||||
{
|
||||
pString = new CStringT;
|
||||
new(pString) CStringT;
|
||||
}
|
||||
|
||||
CStringT(_In_ const CStringT& strSrc) :
|
||||
|
@ -98,6 +303,13 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
template<class StringTraits_>
|
||||
CStringT(_In_ const CStringT<YCHAR, StringTraits_> & strSrc) :
|
||||
CThisSimpleString(StringTraits::GetDefaultManager())
|
||||
{
|
||||
*this = static_cast<const YCHAR*>(strSrc);
|
||||
}
|
||||
|
||||
CStringT(_In_opt_z_ const XCHAR* pszSrc) :
|
||||
CThisSimpleString( StringTraits::GetDefaultManager() )
|
||||
{
|
||||
|
@ -114,6 +326,36 @@ public:
|
|||
*this = pszSrc;
|
||||
}
|
||||
|
||||
CStringT(_In_opt_z_ const YCHAR* pszSrc) :
|
||||
CThisSimpleString( StringTraits::GetDefaultManager() )
|
||||
{
|
||||
// FIXME: Check whether pszSrc is not a resource string ID!
|
||||
*this = pszSrc;
|
||||
}
|
||||
|
||||
CStringT(
|
||||
_In_opt_z_ const YCHAR* pszSrc,
|
||||
_In_ IAtlStringMgr* pStringMgr) :
|
||||
CThisSimpleString( pStringMgr )
|
||||
{
|
||||
// FIXME: Check whether pszSrc is not a resource string ID!
|
||||
*this = pszSrc;
|
||||
}
|
||||
|
||||
CStringT(
|
||||
_In_reads_z_(nLength) const XCHAR* pch,
|
||||
_In_ int nLength) :
|
||||
CThisSimpleString(pch, nLength, StringTraits::GetDefaultManager())
|
||||
{
|
||||
}
|
||||
|
||||
CStringT(
|
||||
_In_reads_z_(nLength) const YCHAR* pch,
|
||||
_In_ int nLength) :
|
||||
CThisSimpleString(pch, nLength, StringTraits::GetDefaultManager())
|
||||
{
|
||||
}
|
||||
|
||||
CStringT& operator=(_In_ const CStringT& strSrc)
|
||||
{
|
||||
CThisSimpleString::operator=(strSrc);
|
||||
|
@ -126,6 +368,59 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
CStringT& operator=(_In_opt_z_ PCYSTR pszSrc)
|
||||
{
|
||||
int length = pszSrc ? StringTraits::GetBaseTypeLength(pszSrc) : 0;
|
||||
if (length > 0)
|
||||
{
|
||||
PXSTR result = CThisSimpleString::GetBuffer(length);
|
||||
StringTraits::ConvertToBaseType(result, length, pszSrc);
|
||||
CThisSimpleString::ReleaseBufferSetLength(length);
|
||||
}
|
||||
else
|
||||
{
|
||||
CThisSimpleString::Empty();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator==(const CStringT& str1, const CStringT& str2) throw()
|
||||
{
|
||||
return str1.Compare(str2) == 0;
|
||||
}
|
||||
|
||||
friend bool operator==(const CStringT& str1, PCXSTR psz2) throw()
|
||||
{
|
||||
return str1.Compare(psz2) == 0;
|
||||
}
|
||||
|
||||
friend bool operator==(const CStringT& str1, PCYSTR psz2) throw()
|
||||
{
|
||||
CStringT tmp(psz2, str1.GetManager());
|
||||
return tmp == str1;
|
||||
}
|
||||
|
||||
friend bool operator==(const CStringT& str1, XCHAR ch2) throw()
|
||||
{
|
||||
return str1.GetLength() == 1 && str1[0] == ch2;
|
||||
}
|
||||
|
||||
friend bool operator==(PCXSTR psz1, const CStringT& str2) throw()
|
||||
{
|
||||
return str2.Compare(psz1) == 0;
|
||||
}
|
||||
|
||||
friend bool operator==(PCYSTR psz1, const CStringT& str2) throw()
|
||||
{
|
||||
CStringT tmp(psz1, str2.GetManager());
|
||||
return tmp.Compare(str2) == 0;
|
||||
}
|
||||
|
||||
friend bool operator==(XCHAR ch1, const CStringT& str2) throw()
|
||||
{
|
||||
return str2.GetLength() == 1 && str2[0] == ch1;
|
||||
}
|
||||
|
||||
CStringT& operator+=(_In_ const CThisSimpleString& str)
|
||||
{
|
||||
CThisSimpleString::operator+=(str);
|
||||
|
@ -151,6 +446,299 @@ public:
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CStringT& MakeLower()
|
||||
{
|
||||
int nLength = CThisSimpleString::GetLength();
|
||||
PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
|
||||
|
||||
StringTraits::MakeLower(pszBuffer, nLength);
|
||||
CThisSimpleString::ReleaseBufferSetLength(nLength);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CStringT& MakeUpper()
|
||||
{
|
||||
int nLength = CThisSimpleString::GetLength();
|
||||
PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
|
||||
|
||||
StringTraits::MakeUpper(pszBuffer, nLength);
|
||||
CThisSimpleString::ReleaseBufferSetLength(nLength);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
int Find(_In_ PCXSTR pszSub, _In_opt_ int iStart = 0) const throw()
|
||||
{
|
||||
int nLength = CThisSimpleString::GetLength();
|
||||
|
||||
if (iStart >= nLength || iStart < 0)
|
||||
return -1;
|
||||
|
||||
PCXSTR pszString = CThisSimpleString::GetString();
|
||||
PCXSTR pszResult = StringTraits::FindString(pszString + iStart, pszSub);
|
||||
|
||||
return pszResult ? ((int)(pszResult - pszString)) : -1;
|
||||
}
|
||||
|
||||
int Find(_In_ XCHAR ch, _In_opt_ int iStart = 0) const throw()
|
||||
{
|
||||
int nLength = CThisSimpleString::GetLength();
|
||||
|
||||
if (iStart >= nLength || iStart < 0)
|
||||
return -1;
|
||||
|
||||
PCXSTR pszString = CThisSimpleString::GetString();
|
||||
PCXSTR pszResult = StringTraits::FindChar(pszString + iStart, ch);
|
||||
|
||||
return pszResult ? ((int)(pszResult - pszString)) : -1;
|
||||
}
|
||||
|
||||
int FindOneOf(_In_ PCXSTR pszCharSet) const throw()
|
||||
{
|
||||
PCXSTR pszString = CThisSimpleString::GetString();
|
||||
PCXSTR pszResult = StringTraits::FindOneOf(pszString, pszCharSet);
|
||||
|
||||
return pszResult ? ((int)(pszResult - pszString)) : -1;
|
||||
}
|
||||
|
||||
int ReverseFind(_In_ XCHAR ch) const throw()
|
||||
{
|
||||
PCXSTR pszString = CThisSimpleString::GetString();
|
||||
PCXSTR pszResult = StringTraits::FindCharReverse(pszString, ch);
|
||||
|
||||
return pszResult ? ((int)(pszResult - pszString)) : -1;
|
||||
}
|
||||
|
||||
int Compare(_In_z_ PCXSTR psz) const
|
||||
{
|
||||
return StringTraits::Compare(CThisSimpleString::GetString(), psz);
|
||||
}
|
||||
|
||||
|
||||
CStringT Mid(int iFirst, int nCount) const
|
||||
{
|
||||
int nLength = CThisSimpleString::GetLength();
|
||||
|
||||
if (iFirst < 0)
|
||||
iFirst = 0;
|
||||
if (nCount < 0)
|
||||
nCount = 0;
|
||||
if (iFirst > nLength)
|
||||
iFirst = nLength;
|
||||
if (iFirst + nCount > nLength)
|
||||
nCount = nLength - iFirst;
|
||||
|
||||
return CStringT(CThisSimpleString::GetString() + iFirst, nCount);
|
||||
}
|
||||
|
||||
CStringT Mid(int iFirst) const
|
||||
{
|
||||
int nLength = CThisSimpleString::GetLength();
|
||||
|
||||
if (iFirst < 0)
|
||||
iFirst = 0;
|
||||
if (iFirst > nLength)
|
||||
iFirst = nLength;
|
||||
|
||||
return CStringT(CThisSimpleString::GetString() + iFirst, nLength - iFirst);
|
||||
}
|
||||
|
||||
CStringT Left(int nCount) const
|
||||
{
|
||||
int nLength = CThisSimpleString::GetLength();
|
||||
|
||||
if (nCount < 0)
|
||||
nCount = 0;
|
||||
if (nCount > nLength)
|
||||
nCount = nLength;
|
||||
|
||||
return CStringT(CThisSimpleString::GetString(), nCount);
|
||||
}
|
||||
|
||||
CStringT Right(int nCount) const
|
||||
{
|
||||
int nLength = CThisSimpleString::GetLength();
|
||||
|
||||
if (nCount < 0)
|
||||
nCount = 0;
|
||||
if (nCount > nLength)
|
||||
nCount = nLength;
|
||||
|
||||
return CStringT(CThisSimpleString::GetString() + nLength - nCount, nCount);
|
||||
}
|
||||
|
||||
|
||||
//void __cdecl Format(UINT nFormatID, ...)
|
||||
//{
|
||||
// va_list args;
|
||||
// va_start(args, dwMessageId);
|
||||
// CStringT formatString;
|
||||
// formatString.LoadString(?????);
|
||||
// FormatV(formatString, args);
|
||||
// va_end(args);
|
||||
//}
|
||||
|
||||
void __cdecl Format(PCXSTR pszFormat, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, pszFormat);
|
||||
FormatV(pszFormat, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void FormatV(PCXSTR pszFormat, va_list args)
|
||||
{
|
||||
int nLength = StringTraits::FormatV(NULL, pszFormat, args);
|
||||
|
||||
PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
|
||||
StringTraits::FormatV(pszBuffer, pszFormat, args);
|
||||
CThisSimpleString::ReleaseBufferSetLength(nLength);
|
||||
}
|
||||
|
||||
|
||||
int Replace(PCXSTR pszOld, PCXSTR pszNew)
|
||||
{
|
||||
PCXSTR pszString = CThisSimpleString::GetString();
|
||||
|
||||
const int nLength = CThisSimpleString::GetLength();
|
||||
const int nOldLen = StringTraits::GetBaseTypeLength(pszOld);
|
||||
const int nNewLen = StringTraits::GetBaseTypeLength(pszNew);
|
||||
const int nDiff = nNewLen - nOldLen;
|
||||
int nResultLength = nLength;
|
||||
|
||||
PCXSTR pszFound;
|
||||
while ((pszFound = StringTraits::FindString(pszString, pszOld)))
|
||||
{
|
||||
nResultLength += nDiff;
|
||||
pszString = pszFound + nOldLen;
|
||||
}
|
||||
|
||||
if (pszString == CThisSimpleString::GetString())
|
||||
return 0;
|
||||
|
||||
PXSTR pszResult = CThisSimpleString::GetBuffer(nResultLength);
|
||||
PXSTR pszNext;
|
||||
int nCount = 0, nRemaining = nLength;
|
||||
while (nRemaining && (pszNext = StringTraits::FindString(pszResult, pszOld)))
|
||||
{
|
||||
nRemaining -= (pszNext - pszResult);
|
||||
nRemaining -= nOldLen;
|
||||
if (nRemaining > 0)
|
||||
CThisSimpleString::CopyCharsOverlapped(pszNext + nNewLen, nRemaining + 1, pszNext + nOldLen, nRemaining + 1);
|
||||
CThisSimpleString::CopyCharsOverlapped(pszNext, nNewLen, pszNew, nNewLen);
|
||||
pszResult = pszNext + nNewLen;
|
||||
nCount++;
|
||||
}
|
||||
|
||||
CThisSimpleString::ReleaseBufferSetLength(nResultLength);
|
||||
|
||||
return nCount;
|
||||
}
|
||||
|
||||
int Replace(XCHAR chOld, XCHAR chNew)
|
||||
{
|
||||
PCXSTR pszString = CThisSimpleString::GetString();
|
||||
PXSTR pszFirst = StringTraits::FindChar(pszString, chOld);
|
||||
if (!pszFirst)
|
||||
return 0;
|
||||
|
||||
int nLength = CThisSimpleString::GetLength();
|
||||
int nCount = 0;
|
||||
|
||||
PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
|
||||
pszFirst = pszBuffer + (pszFirst - pszString);
|
||||
do {
|
||||
*pszFirst = chNew;
|
||||
++nCount;
|
||||
} while ((pszFirst = StringTraits::FindChar(pszFirst + 1, chOld)));
|
||||
|
||||
CThisSimpleString::ReleaseBufferSetLength(nLength);
|
||||
return nCount;
|
||||
}
|
||||
|
||||
|
||||
static PCXSTR DefaultTrimChars()
|
||||
{
|
||||
static XCHAR str[] = { ' ', '\t', '\r', '\n', 0 };
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
CStringT& TrimLeft()
|
||||
{
|
||||
return TrimLeft(DefaultTrimChars());
|
||||
}
|
||||
|
||||
CStringT& TrimLeft(XCHAR chTarget)
|
||||
{
|
||||
XCHAR str[2] = { chTarget, 0 };
|
||||
return TrimLeft(str);
|
||||
}
|
||||
|
||||
CStringT& TrimLeft(PCXSTR pszTargets)
|
||||
{
|
||||
int nLength = CThisSimpleString::GetLength();
|
||||
PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
|
||||
int nCount = 0;
|
||||
|
||||
while (nCount < nLength && StringTraits::FindChar(pszTargets, pszBuffer[nCount]))
|
||||
nCount++;
|
||||
|
||||
if (nCount > 0)
|
||||
{
|
||||
CThisSimpleString::CopyCharsOverlapped(pszBuffer, nLength - nCount, pszBuffer + nCount, nLength - nCount);
|
||||
nLength -= nCount;
|
||||
}
|
||||
CThisSimpleString::ReleaseBufferSetLength(nLength);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
CStringT& TrimRight()
|
||||
{
|
||||
return TrimRight(DefaultTrimChars());
|
||||
}
|
||||
|
||||
CStringT& TrimRight(XCHAR chTarget)
|
||||
{
|
||||
XCHAR str[2] = { chTarget, 0 };
|
||||
return TrimRight(str);
|
||||
}
|
||||
|
||||
CStringT& TrimRight(PCXSTR pszTargets)
|
||||
{
|
||||
int nLength = CThisSimpleString::GetLength();
|
||||
PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
|
||||
|
||||
while (nLength > 0 && StringTraits::FindChar(pszTargets, pszBuffer[nLength-1]))
|
||||
nLength--;
|
||||
|
||||
CThisSimpleString::ReleaseBufferSetLength(nLength);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
CStringT& Trim()
|
||||
{
|
||||
return Trim(DefaultTrimChars());
|
||||
}
|
||||
|
||||
CStringT& Trim(XCHAR chTarget)
|
||||
{
|
||||
XCHAR str[2] = { chTarget, 0 };
|
||||
return Trim(str);
|
||||
}
|
||||
|
||||
CStringT& Trim(PCXSTR pszTargets)
|
||||
{
|
||||
return TrimRight(pszTargets).TrimLeft(pszTargets);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
} //namespace ATL
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
|
||||
set_cpp(WITH_RUNTIME)
|
||||
set_cpp(WITH_RUNTIME WITH_EXCEPTIONS)
|
||||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/atl)
|
||||
|
||||
add_executable(atl_apitest
|
||||
CComBSTR.cpp
|
||||
CComHeapPtr.cpp
|
||||
CString.cpp
|
||||
testlist.c
|
||||
atl_apitest.rc)
|
||||
|
||||
|
|
176
rostests/apitests/atl/CString.cpp
Normal file
176
rostests/apitests/atl/CString.cpp
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* PROJECT: ReactOS api tests
|
||||
* LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
|
||||
* PURPOSE: Test for CString
|
||||
* PROGRAMMER: Mark Jansen
|
||||
*/
|
||||
|
||||
#include <apitest.h>
|
||||
#include <atlstr.h>
|
||||
|
||||
|
||||
struct traits_test
|
||||
{
|
||||
const char* strA;
|
||||
const wchar_t* strW;
|
||||
int str_len;
|
||||
int exp_1, exp_2, exp_3, exp_4;
|
||||
};
|
||||
|
||||
traits_test g_Tests[] = {
|
||||
// inputs outputs
|
||||
{ NULL, NULL, 0, 0, 0, -1, 0 },
|
||||
{ NULL, NULL, -1, 0, -1, -1, 0 },
|
||||
{ NULL, NULL, 1, 0, 1, -1, 0 },
|
||||
|
||||
{ "", L"", 0, 0, 0, 0, 0 },
|
||||
{ "", L"", -1, 0, -1, 0, 1 },
|
||||
{ "", L"", 1, 0, 1, 0, 1 },
|
||||
|
||||
{ "AAABBB", L"AAABBB", 0, 6, 0, 6, 0 },
|
||||
{ "AAABBB", L"AAABBB", 3, 6, 3, 6, 3 },
|
||||
{ "AAABBB", L"AAABBB", -1, 6, -1, 6, 7 },
|
||||
};
|
||||
|
||||
static void test_basetypes()
|
||||
{
|
||||
int len;
|
||||
char bufA[10];
|
||||
wchar_t bufW[10];
|
||||
|
||||
for (size_t n = 0; n < _countof(g_Tests); ++n)
|
||||
{
|
||||
len = ChTraitsCRT<char>::GetBaseTypeLength(g_Tests[n].strA);
|
||||
ok(len == g_Tests[n].exp_1, "Expected len to be %i, was %i for %u (A)\n", g_Tests[n].exp_1, len, n);
|
||||
|
||||
len = ChTraitsCRT<char>::GetBaseTypeLength(g_Tests[n].strA, g_Tests[n].str_len);
|
||||
ok(len == g_Tests[n].exp_2, "Expected len to be %i, was %i for %u (A,len)\n", g_Tests[n].exp_2, len, n);
|
||||
|
||||
len = ChTraitsCRT<char>::GetBaseTypeLength(g_Tests[n].strW);
|
||||
ok(len == g_Tests[n].exp_3, "Expected len to be %i, was %i for %u (W)\n", g_Tests[n].exp_3, len, n);
|
||||
|
||||
len = ChTraitsCRT<char>::GetBaseTypeLength(g_Tests[n].strW, g_Tests[n].str_len);
|
||||
ok(len == g_Tests[n].exp_4, "Expected len to be %i, was %i for %u (W,len)\n", g_Tests[n].exp_4, len, n);
|
||||
|
||||
if (g_Tests[n].strA && g_Tests[n].strW)
|
||||
{
|
||||
memset(bufA, 'x', sizeof(bufA));
|
||||
ChTraitsCRT<char>::ConvertToBaseType(bufA, g_Tests[n].exp_1+1, g_Tests[n].strA);
|
||||
char ch = bufA[g_Tests[n].exp_1];
|
||||
ok(ch == '\0', "Expected %i to be \\0, was: %c (%i) for %u\n", g_Tests[n].exp_1, ch, (int)ch, n);
|
||||
ok(!strcmp(bufA, g_Tests[n].strA), "Expected bufA to be %s, was: %s for %u\n", g_Tests[n].strA, bufA, n);
|
||||
ch = bufA[g_Tests[n].exp_1+1];
|
||||
ok(ch == 'x', "Expected %i to be 'x', was: %c (%i) for %u\n", g_Tests[n].exp_1+1, ch, (int)ch, n);
|
||||
}
|
||||
|
||||
if (g_Tests[n].strA && g_Tests[n].strW)
|
||||
{
|
||||
memset(bufA, 'x', sizeof(bufA));
|
||||
ChTraitsCRT<char>::ConvertToBaseType(bufA, g_Tests[n].exp_1+1, g_Tests[n].strW);
|
||||
char ch = bufA[g_Tests[n].exp_1];
|
||||
ok(ch == '\0', "Expected %i to be \\0, was: %c (%i) for %u\n", g_Tests[n].exp_1, ch, (int)ch, n);
|
||||
ok(!strcmp(bufA, g_Tests[n].strA), "Expected bufA to be %s, was: %s for %u\n", g_Tests[n].strA, bufA, n);
|
||||
ch = bufA[g_Tests[n].exp_1+1];
|
||||
ok(ch == 'x', "Expected %i to be 'x', was: %c (%i) for %u\n", g_Tests[n].exp_1+1, ch, (int)ch, n);
|
||||
}
|
||||
|
||||
// wchar_t --> please note, swapped the expectations from 2 and 4 !
|
||||
len = ChTraitsCRT<wchar_t>::GetBaseTypeLength(g_Tests[n].strA);
|
||||
ok(len == g_Tests[n].exp_1, "Expected len to be %i, was %i for %u (A)\n", g_Tests[n].exp_1, len, n);
|
||||
|
||||
len = ChTraitsCRT<wchar_t>::GetBaseTypeLength(g_Tests[n].strA, g_Tests[n].str_len);
|
||||
ok(len == g_Tests[n].exp_4, "Expected len to be %i, was %i for %u (A,len)\n", g_Tests[n].exp_4, len, n);
|
||||
|
||||
len = ChTraitsCRT<wchar_t>::GetBaseTypeLength(g_Tests[n].strW);
|
||||
ok(len == g_Tests[n].exp_3, "Expected len to be %i, was %i for %u (W)\n", g_Tests[n].exp_3, len, n);
|
||||
|
||||
len = ChTraitsCRT<wchar_t>::GetBaseTypeLength(g_Tests[n].strW, g_Tests[n].str_len);
|
||||
ok(len == g_Tests[n].exp_2, "Expected len to be %i, was %i for %u (W,len)\n", g_Tests[n].exp_2, len, n);
|
||||
|
||||
if (g_Tests[n].strA && g_Tests[n].strW)
|
||||
{
|
||||
memset(bufW, 'x', sizeof(bufW));
|
||||
ChTraitsCRT<wchar_t>::ConvertToBaseType(bufW, g_Tests[n].exp_1+1, g_Tests[n].strA);
|
||||
wchar_t ch = bufW[g_Tests[n].exp_1];
|
||||
ok(ch == L'\0', "Expected %i to be \\0, was: %c (%i) for %u\n", g_Tests[n].exp_1, ch, (int)ch, n);
|
||||
ok(!wcscmp(bufW, g_Tests[n].strW), "Expected bufW to be %s, was: %s for %u\n", wine_dbgstr_w(g_Tests[n].strW), wine_dbgstr_w(bufW), n);
|
||||
ch = bufW[g_Tests[n].exp_1+1];
|
||||
ok(ch == 30840, "Expected %i to be %i for %u\n", g_Tests[n].exp_1+1, (int)ch, n);
|
||||
}
|
||||
|
||||
if (g_Tests[n].strA && g_Tests[n].strW)
|
||||
{
|
||||
memset(bufW, 'x', sizeof(bufW));
|
||||
ChTraitsCRT<wchar_t>::ConvertToBaseType(bufW, g_Tests[n].exp_1+1, g_Tests[n].strW);
|
||||
wchar_t ch = bufW[g_Tests[n].exp_1];
|
||||
ok(ch == '\0', "Expected %i to be \\0, was: %c (%i) for %u\n", g_Tests[n].exp_1, ch, (int)ch, n);
|
||||
ok(!wcscmp(bufW, g_Tests[n].strW), "Expected bufW to be %s, was: %s for %u\n", wine_dbgstr_w(g_Tests[n].strW), wine_dbgstr_w(bufW), n);
|
||||
ch = bufW[g_Tests[n].exp_1+1];
|
||||
ok(ch == 30840, "Expected %i to be %i for %u\n", g_Tests[n].exp_1+1, (int)ch, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocation strategy seems to differ a bit between us and MS's atl.
|
||||
// if someone cares enough to find out why, feel free to change the macro below.
|
||||
#define ALLOC_EXPECT(a, b) b
|
||||
|
||||
|
||||
#undef ok
|
||||
#undef _T
|
||||
|
||||
#define TEST_NAMEX(name) void test_##name##W()
|
||||
#define CStringX CStringW
|
||||
#define _X(x) L ## x
|
||||
#define XCHAR WCHAR
|
||||
#define dbgstrx(x) wine_dbgstr_w(x)
|
||||
#define ok ok_("CStringW:\n" __FILE__, __LINE__)
|
||||
#include "CString.inl"
|
||||
|
||||
|
||||
#undef CStringX
|
||||
#undef TEST_NAMEX
|
||||
#undef _X
|
||||
#undef XCHAR
|
||||
#undef dbgstrx
|
||||
#undef ok
|
||||
|
||||
#define TEST_NAMEX(name) void test_##name##A()
|
||||
#define CStringX CStringA
|
||||
#define _X(x) x
|
||||
#define XCHAR CHAR
|
||||
#define dbgstrx(x) (const char*)x
|
||||
#define ok ok_("CStringA:\n" __FILE__, __LINE__)
|
||||
#include "CString.inl"
|
||||
|
||||
|
||||
START_TEST(CString)
|
||||
{
|
||||
test_basetypes();
|
||||
|
||||
if ((ALLOC_EXPECT(1, 2)) == 2)
|
||||
{
|
||||
skip("Ignoring real GetAllocLength() lenght\n");
|
||||
}
|
||||
|
||||
test_operators_initW();
|
||||
test_operators_initA();
|
||||
|
||||
test_compareW();
|
||||
test_compareA();
|
||||
|
||||
test_findW();
|
||||
test_findA();
|
||||
|
||||
test_formatW();
|
||||
test_formatA();
|
||||
|
||||
test_substrW();
|
||||
test_substrA();
|
||||
|
||||
test_replaceW();
|
||||
test_replaceA();
|
||||
|
||||
test_trimW();
|
||||
test_trimA();
|
||||
}
|
358
rostests/apitests/atl/CString.inl
Normal file
358
rostests/apitests/atl/CString.inl
Normal file
|
@ -0,0 +1,358 @@
|
|||
|
||||
TEST_NAMEX(operators_init)
|
||||
{
|
||||
CStringX test;
|
||||
ok(test.IsEmpty() == true, "Expected test to be empty\n");
|
||||
ok(test.GetLength() == 0, "Expected GetLength() to be 0, was: %i\n", test.GetLength());
|
||||
ok(test.GetAllocLength() == 0, "Expected GetAllocLength() to be 0, was: %i\n", test.GetAllocLength());
|
||||
|
||||
// Operator
|
||||
const XCHAR* cstring = (const XCHAR*)test;
|
||||
ok(cstring != NULL, "Expected a valid pointer\n");
|
||||
if (cstring)
|
||||
{
|
||||
ok(cstring[0] == '\0', "Expected \\0, got: %c (%i)\n", cstring[0], (int)cstring[0]);
|
||||
}
|
||||
|
||||
CStringX first(_X("First "));
|
||||
ok(first.IsEmpty() != true, "Expected first to not be empty\n");
|
||||
ok(first.GetLength() == 6, "Expected GetLength() to be 6, was: %i\n", first.GetLength());
|
||||
ok(first.GetAllocLength() == ALLOC_EXPECT(7, 6), "Expected GetAllocLength() to be %i, was: %i\n", ALLOC_EXPECT(7, 6), first.GetAllocLength());
|
||||
|
||||
CStringX second(_X("Second"));
|
||||
ok(second.IsEmpty() != true, "Expected second to not be empty\n");
|
||||
ok(second.GetLength() == 6, "Expected GetLength() to be 6, was: %i\n", second.GetLength());
|
||||
ok(second.GetAllocLength() == ALLOC_EXPECT(7, 6), "Expected GetAllocLength() to be %i, was: %i\n", ALLOC_EXPECT(7, 6), second.GetAllocLength());
|
||||
|
||||
test = first;
|
||||
ok(test.IsEmpty() != true, "Expected test to not be empty\n");
|
||||
ok(test.GetLength() == 6, "Expected GetLength() to be 6, was: %i\n", test.GetLength());
|
||||
ok(test.GetAllocLength() == ALLOC_EXPECT(7, 6), "Expected GetAllocLength() to be %i, was: %i\n", ALLOC_EXPECT(7, 6), test.GetAllocLength());
|
||||
|
||||
test.Empty();
|
||||
ok(test.IsEmpty() == true, "Expected test to be empty\n");
|
||||
ok(test.GetLength() == 0, "Expected GetLength() to be 0, was: %i\n", test.GetLength());
|
||||
ok(test.GetAllocLength() == 0, "Expected GetAllocLength() to be 0, was: %i\n", test.GetAllocLength());
|
||||
|
||||
test = _X("First ");
|
||||
ok(test.IsEmpty() != true, "Expected test to not be empty\n");
|
||||
ok(test.GetLength() == 6, "Expected GetLength() to be 6, was: %i\n", test.GetLength());
|
||||
ok(test.GetAllocLength() == ALLOC_EXPECT(7, 6), "Expected GetAllocLength() to be %i, was: %i\n", ALLOC_EXPECT(7, 6), test.GetAllocLength());
|
||||
|
||||
test += second;
|
||||
ok(test.IsEmpty() != true, "Expected test to not be empty\n");
|
||||
ok(test.GetLength() == 12, "Expected GetLength() to be 12, was: %i\n", test.GetLength());
|
||||
ok(test.GetAllocLength() == ALLOC_EXPECT(15, 12), "Expected GetAllocLength() to be %i, was: %i\n", ALLOC_EXPECT(15, 12), test.GetAllocLength());
|
||||
|
||||
test = first + second;
|
||||
ok(test.IsEmpty() != true, "Expected test to not be empty\n");
|
||||
ok(test.GetLength() == 12, "Expected GetLength() to be 12, was: %i\n", test.GetLength());
|
||||
ok(test.GetAllocLength() == ALLOC_EXPECT(15, 12), "Expected GetAllocLength() to be %i, was: %i\n", ALLOC_EXPECT(15, 12), test.GetAllocLength());
|
||||
|
||||
test = first + second + _X(".");
|
||||
ok(test.IsEmpty() != true, "Expected test to not be empty\n");
|
||||
ok(test.GetLength() == 13, "Expected GetLength() to be 13, was: %i\n", test.GetLength());
|
||||
ok(test.GetAllocLength() == ALLOC_EXPECT(15, 18), "Expected GetAllocLength() to be %i, was: %i\n", ALLOC_EXPECT(15, 18), test.GetAllocLength());
|
||||
|
||||
CStringX test2(test);
|
||||
ok(test2.IsEmpty() != true, "Expected test2 to not be empty\n");
|
||||
ok(test2.GetLength() == 13, "Expected GetLength() to be 13, was: %i\n", test2.GetLength());
|
||||
ok(test2.GetAllocLength() == ALLOC_EXPECT(15, 18), "Expected GetAllocLength() to be %i, was: %i\n", ALLOC_EXPECT(15, 18), test2.GetAllocLength());
|
||||
|
||||
// Clear it again
|
||||
test.Empty();
|
||||
ok(test.IsEmpty() == true, "Expected test to be empty\n");
|
||||
ok(test.GetLength() == 0, "Expected GetLength() to be 0, was: %i\n", test.GetLength());
|
||||
ok(test.GetAllocLength() == 0, "Expected GetAllocLength() to be 0, was: %i\n", test.GetAllocLength());
|
||||
|
||||
// Assign string
|
||||
test = "First ";
|
||||
ok(test.IsEmpty() != true, "Expected test to not be empty\n");
|
||||
ok(test.GetLength() == 6, "Expected GetLength() to be 6, was: %i\n", test.GetLength());
|
||||
ok(test.GetAllocLength() == ALLOC_EXPECT(7, 6), "Expected GetAllocLength() to be 7, was: %i\n", test.GetAllocLength());
|
||||
|
||||
CStringA testA = test;
|
||||
ok(testA.IsEmpty() != true, "Expected testA to not be empty\n");
|
||||
ok(testA.GetLength() == 6, "Expected GetLength() to be 6, was: %i\n", testA.GetLength());
|
||||
ok(testA.GetAllocLength() == ALLOC_EXPECT(7, 6), "Expected GetAllocLength() to be 7, was: %i\n", testA.GetAllocLength());
|
||||
|
||||
CStringW testW = test;
|
||||
ok(testW.IsEmpty() != true, "Expected testW to not be empty\n");
|
||||
ok(testW.GetLength() == 6, "Expected GetLength() to be 6, was: %i\n", testW.GetLength());
|
||||
ok(testW.GetAllocLength() == ALLOC_EXPECT(7, 6), "Expected GetAllocLength() to be 7, was: %i\n", testW.GetAllocLength());
|
||||
|
||||
// Assign wstring
|
||||
test = L"First ";
|
||||
ok(test.IsEmpty() != true, "Expected test to not be empty\n");
|
||||
ok(test.GetLength() == 6, "Expected GetLength() to be 6, was: %i\n", test.GetLength());
|
||||
ok(test.GetAllocLength() == ALLOC_EXPECT(7, 6), "Expected GetAllocLength() to be 7, was: %i\n", test.GetAllocLength());
|
||||
}
|
||||
|
||||
|
||||
TEST_NAMEX(compare)
|
||||
{
|
||||
CStringX s1, s2;
|
||||
s1 = s2 = _X("some text 1!");
|
||||
|
||||
int c = s1.Compare(s2);
|
||||
ok(c == 0, "Expected c to be 1, was: %i\n", c);
|
||||
|
||||
c = s1.Compare(_X("r"));
|
||||
ok(c == 1, "Expected c to be 1, was: %i\n", c);
|
||||
|
||||
c = s1.Compare(_X("s"));
|
||||
ok(c == 1, "Expected c to be 1, was: %i\n", c);
|
||||
|
||||
c = s1.Compare(_X("t"));
|
||||
ok(c == -1, "Expected c to be -1, was: %i\n", c);
|
||||
|
||||
c = s1.Compare(_X("R"));
|
||||
ok(c == 1, "Expected c to be 1, was: %i\n", c);
|
||||
|
||||
c = s1.Compare(_X("S"));
|
||||
ok(c == 1, "Expected c to be 1, was: %i\n", c);
|
||||
|
||||
c = s1.Compare(_X("T"));
|
||||
ok(c == 1, "Expected c to be 1, was: %i\n", c);
|
||||
|
||||
ok(s1 == s2, "Expected s1 and s2 to be equal: '%s' == '%s'\n", dbgstrx(s1), dbgstrx(s2));
|
||||
|
||||
s1.MakeUpper(); // Does not modify s2
|
||||
ok(s1[0] == _X('S'), "Expected s1[0] to be S, was: %c\n", (char)s1[0]);
|
||||
ok(s2[0] == _X('s'), "Expected s2[0] to be s, was: %c\n", (char)s2[0]);
|
||||
|
||||
ok(s1 == _X("SOME TEXT 1!"), "Expected s1 to be 'SOME TEXT 1!', was: %s\n", dbgstrx(s1));
|
||||
|
||||
CStringX s3 = s1.MakeLower();
|
||||
ok(s1 == _X("some text 1!"), "Expected s1 to be 'some text 1!', was: %s\n", dbgstrx(s1));
|
||||
ok(s1 == s3, "Expected s1 and s3 to be equal: '%s' == '%s'\n", dbgstrx(s1), dbgstrx(s3));
|
||||
}
|
||||
|
||||
|
||||
TEST_NAMEX(find)
|
||||
{
|
||||
CStringX s(_X("adbcdef"));
|
||||
int n = s.Find(_X('c'));
|
||||
ok(n == 3, "Expected n to be 2, was %i\n", n);
|
||||
n = s.Find(_X("de"));
|
||||
ok(n == 4, "Expected n to be 4, was %i\n", n);
|
||||
|
||||
CStringX str(_X("The waves are still"));
|
||||
n = str.Find(_X('e'), 5);
|
||||
ok(n == 7, "Expected n to be 7, was %i\n", n);
|
||||
n = str.Find(_X('e'), 7);
|
||||
ok(n == 7, "Expected n to be 7, was %i\n", n);
|
||||
|
||||
s = _X("abcdefGHIJKLMNop");
|
||||
n = s.FindOneOf(_X("Nd"));
|
||||
ok(n == 3, "Expected n to be 3, was %i\n", n);
|
||||
n = s.FindOneOf(_X("Np"));
|
||||
ok(n == 13, "Expected n to be 13, was %i\n", n);
|
||||
|
||||
n = str.ReverseFind(_X('l'));
|
||||
ok(n == 18, "Expected n to be 18, was %i\n", n);
|
||||
|
||||
n = str.ReverseFind(_X('e'));
|
||||
ok(n == 12, "Expected n to be 12, was %i\n", n);
|
||||
}
|
||||
|
||||
|
||||
void WriteString(const XCHAR* pstrFormat, ...)
|
||||
{
|
||||
CStringX str;
|
||||
|
||||
va_list args;
|
||||
va_start(args, pstrFormat);
|
||||
|
||||
str.FormatV(pstrFormat, args);
|
||||
va_end(args);
|
||||
|
||||
ok(str == _X("10e 1351l"), "Expected str to be '10e 1351l', was: %s\n", dbgstrx(str));
|
||||
}
|
||||
|
||||
TEST_NAMEX(format)
|
||||
{
|
||||
CStringX str;
|
||||
|
||||
str.Format(_X("FP: %.2f"), 12345.12345);
|
||||
ok(str == _X("FP: 12345.12"), "Expected str to be 'FP: 12345.12', was: %s\n", dbgstrx(str));
|
||||
|
||||
str.Format(_X("int: %.6d"), 35);
|
||||
ok(str == _X("int: 000035"), "Expected str to be 'int: 000035', was: %s\n", dbgstrx(str));
|
||||
|
||||
WriteString(_X("%de %dl"), 10, 1351);
|
||||
}
|
||||
|
||||
|
||||
TEST_NAMEX(substr)
|
||||
{
|
||||
CStringX s(_X("abcdef"));
|
||||
|
||||
CStringX m = s.Mid(2, 3);
|
||||
ok(m == _X("cde"), "Expected str to be 'cde', was: %s\n", dbgstrx(m));
|
||||
ok(m.GetLength() == 3, "Expected GetLength() to be 3, was: %i\n", m.GetLength());
|
||||
|
||||
m = s.Mid(-5, 3);
|
||||
ok(m == _X("abc"), "Expected str to be 'abc', was: %s\n", dbgstrx(m));
|
||||
ok(m.GetLength() == 3, "Expected GetLength() to be 3, was: %i\n", m.GetLength());
|
||||
|
||||
m = s.Mid(3, 20);
|
||||
ok(m == _X("def"), "Expected str to be 'def', was: %s\n", dbgstrx(m));
|
||||
ok(m.GetLength() == 3, "Expected GetLength() to be 3, was: %i\n", m.GetLength());
|
||||
|
||||
m = s.Mid(3, -1);
|
||||
ok(m == _X(""), "Expected str to be '', was: %s\n", dbgstrx(m));
|
||||
ok(m.GetLength() == 0, "Expected GetLength() to be 0, was: %i\n", m.GetLength());
|
||||
|
||||
m = s.Mid(2);
|
||||
ok(m == _X("cdef"), "Expected str to be 'cdef', was: %s\n", dbgstrx(m));
|
||||
ok(m.GetLength() == 4, "Expected GetLength() to be 4, was: %i\n", m.GetLength());
|
||||
|
||||
m = s.Mid(-3);
|
||||
ok(m == _X("abcdef"), "Expected str to be 'abcdef', was: %s\n", dbgstrx(m));
|
||||
ok(m.GetLength() == 6, "Expected GetLength() to be 6, was: %i\n", m.GetLength());
|
||||
|
||||
m = s.Mid(20);
|
||||
ok(m == _X(""), "Expected str to be '', was: %s\n", dbgstrx(m));
|
||||
ok(m.GetLength() == 0, "Expected GetLength() to be 0, was: %i\n", m.GetLength());
|
||||
|
||||
m = s.Left(2);
|
||||
ok(m == _X("ab"), "Expected str to be 'ab', was: %s\n", dbgstrx(m));
|
||||
ok(m.GetLength() == 2, "Expected GetLength() to be 2, was: %i\n", m.GetLength());
|
||||
|
||||
m = s.Left(40);
|
||||
ok(m == _X("abcdef"), "Expected str to be 'abcdef', was: %s\n", dbgstrx(m));
|
||||
ok(m.GetLength() == 6, "Expected GetLength() to be 6, was: %i\n", m.GetLength());
|
||||
|
||||
m = s.Left(-10);
|
||||
ok(m == _X(""), "Expected str to be '', was: %s\n", dbgstrx(m));
|
||||
ok(m.GetLength() == 0, "Expected GetLength() to be 0, was: %i\n", m.GetLength());
|
||||
|
||||
m = s.Right(2);
|
||||
ok(m == _X("ef"), "Expected str to be 'ef', was: %s\n", dbgstrx(m));
|
||||
ok(m.GetLength() == 2, "Expected GetLength() to be 2, was: %i\n", m.GetLength());
|
||||
|
||||
m = s.Right(-40);
|
||||
ok(m == _X(""), "Expected str to be '', was: %s\n", dbgstrx(m));
|
||||
ok(m.GetLength() == 0, "Expected GetLength() to be 0, was: %i\n", m.GetLength());
|
||||
|
||||
m = s.Right(99);
|
||||
ok(m == _X("abcdef"), "Expected str to be 'abcdef', was: %s\n", dbgstrx(m));
|
||||
ok(m.GetLength() == 6, "Expected GetLength() to be 6, was: %i\n", m.GetLength());
|
||||
}
|
||||
|
||||
|
||||
TEST_NAMEX(replace)
|
||||
{
|
||||
CStringX str(_X("abcde"));
|
||||
int n = str.Replace(_X("b"), _X("bx"));
|
||||
ok(n == 1, "Expected n to be 1, was %i\n", n);
|
||||
ok(str == _X("abxcde"), "Expected str to be 'abxcde', was: %s\n", dbgstrx(str));
|
||||
ok(str.GetLength() == 6, "Expected GetLength() to be 6, was: %i\n", str.GetLength());
|
||||
|
||||
CStringX strBang(_X("The quick brown fox is lazy today of all days"));
|
||||
|
||||
n = strBang.Replace(_X("is"), _X("was"));
|
||||
ok(n == 1, "Expected n to be 1, was %i\n", n);
|
||||
ok(strBang == _X("The quick brown fox was lazy today of all days"),
|
||||
"Expected str to be 'The quick brown fox was lazy today of all days', was: %s\n", dbgstrx(strBang));
|
||||
ok(strBang.GetLength() == 46, "Expected GetLength() to be 46, was: %i\n", strBang.GetLength());
|
||||
|
||||
n = strBang.Replace(_X("is"), _X("was"));
|
||||
ok(n == 0, "Expected n to be 0, was %i\n", n);
|
||||
ok(strBang == _X("The quick brown fox was lazy today of all days"),
|
||||
"Expected str to be 'The quick brown fox was lazy today of all days', was: %s\n", dbgstrx(strBang));
|
||||
ok(strBang.GetLength() == 46, "Expected GetLength() to be 46, was: %i\n", strBang.GetLength());
|
||||
|
||||
n = strBang.Replace(_X('o'), _X('0'));
|
||||
ok(n == 4, "Expected n to be 4, was %i\n", n);
|
||||
ok(strBang == _X("The quick br0wn f0x was lazy t0day 0f all days"),
|
||||
"Expected str to be 'The quick br0wn f0x was lazy t0day 0f all days', was: %s\n", dbgstrx(strBang));
|
||||
ok(strBang.GetLength() == 46, "Expected GetLength() to be 46, was: %i\n", strBang.GetLength());
|
||||
|
||||
n = strBang.Replace(_X('o'), _X('0'));
|
||||
ok(n == 0, "Expected n to be 0, was %i\n", n);
|
||||
ok(strBang == _X("The quick br0wn f0x was lazy t0day 0f all days"),
|
||||
"Expected str to be 'The quick br0wn f0x was lazy t0day 0f all days', was: %s\n", dbgstrx(strBang));
|
||||
ok(strBang.GetLength() == 46, "Expected GetLength() to be 46, was: %i\n", strBang.GetLength());
|
||||
|
||||
n = strBang.Replace(_X("y "), _X("y, "));
|
||||
ok(n == 2, "Expected n to be 2, was %i\n", n);
|
||||
ok(strBang == _X("The quick br0wn f0x was lazy, t0day, 0f all days"),
|
||||
"Expected str to be 'The quick br0wn f0x was lazy, t0day, 0f all days', was: %s\n", dbgstrx(strBang));
|
||||
ok(strBang.GetLength() == 48, "Expected GetLength() to be 48, was: %i\n", strBang.GetLength());
|
||||
|
||||
n = strBang.Replace(_X(", 0f all days"), _X(""));
|
||||
ok(n == 1, "Expected n to be 1, was %i\n", n);
|
||||
ok(strBang == _X("The quick br0wn f0x was lazy, t0day"),
|
||||
"Expected str to be 'The quick br0wn f0x was lazy, t0day', was: %s\n", dbgstrx(strBang));
|
||||
ok(strBang.GetLength() == 35, "Expected GetLength() to be 35, was: %i\n", strBang.GetLength());
|
||||
|
||||
n = strBang.Replace(_X(" lazy, "), _X(" fast "));
|
||||
ok(n == 1, "Expected n to be 1, was %i\n", n);
|
||||
ok(strBang == _X("The quick br0wn f0x was fast t0day"),
|
||||
"Expected str to be 'The quick br0wn f0x was fast t0day', was: %s\n", dbgstrx(strBang));
|
||||
ok(strBang.GetLength() == 34, "Expected GetLength() to be 34, was: %i\n", strBang.GetLength());
|
||||
|
||||
n = strBang.Replace(_X("The "), _X(""));
|
||||
ok(n == 1, "Expected n to be 1, was %i\n", n);
|
||||
ok(strBang == _X("quick br0wn f0x was fast t0day"),
|
||||
"Expected str to be 'quick br0wn f0x was fast t0day', was: %s\n", dbgstrx(strBang));
|
||||
ok(strBang.GetLength() == 30, "Expected GetLength() to be 30, was: %i\n", strBang.GetLength());
|
||||
|
||||
n = strBang.Replace(_X(" t0day"), _X(""));
|
||||
ok(n == 1, "Expected n to be 1, was %i\n", n);
|
||||
ok(strBang == _X("quick br0wn f0x was fast"),
|
||||
"Expected str to be 'quick br0wn f0x was fast', was: %s\n", dbgstrx(strBang));
|
||||
ok(strBang.GetLength() == 24, "Expected GetLength() to be 24, was: %i\n", strBang.GetLength());
|
||||
|
||||
n = strBang.Replace(_X("quick"), _X("The fast, quick"));
|
||||
ok(n == 1, "Expected n to be 1, was %i\n", n);
|
||||
ok(strBang == _X("The fast, quick br0wn f0x was fast"),
|
||||
"Expected str to be 'The fast, quick br0wn f0x was fast', was: %s\n", dbgstrx(strBang));
|
||||
ok(strBang.GetLength() == 34, "Expected GetLength() to be 34, was: %i\n", strBang.GetLength());
|
||||
}
|
||||
|
||||
|
||||
TEST_NAMEX(trim)
|
||||
{
|
||||
CStringX str;
|
||||
str = _X(" \t\r\n******Trim some text!?!?!?!?!\n\r\t ");
|
||||
|
||||
str.TrimLeft();
|
||||
ok(str == _X("******Trim some text!?!?!?!?!\n\r\t "), "Expected str to be '******Trim some text!?!?!?!?!\n\r\t ', was: %s\n", dbgstrx(str));
|
||||
ok(str.GetLength() == 33, "Expected GetLength() to be 33, was: %i\n", str.GetLength());
|
||||
|
||||
str.TrimRight();
|
||||
ok(str == _X("******Trim some text!?!?!?!?!"), "Expected str to be '******Trim some text!?!?!?!?!', was: %s\n", dbgstrx(str));
|
||||
ok(str.GetLength() == 29, "Expected GetLength() to be 29, was: %i\n", str.GetLength());
|
||||
|
||||
CStringX str2 = str.Trim(_X("?!*"));
|
||||
ok(str2 == _X("Trim some text"), "Expected str to be 'Trim some text', was: %s\n", dbgstrx(str2));
|
||||
ok(str2.GetLength() == 14, "Expected GetLength() to be 14, was: %i\n", str2.GetLength());
|
||||
|
||||
str = _X("\t\t ****Trim some text!");
|
||||
str2 = str.TrimLeft(_X("\t *"));
|
||||
ok(str2 == _X("Trim some text!"), "Expected str to be 'Trim some text!', was: %s\n", dbgstrx(str2));
|
||||
ok(str2.GetLength() == 15, "Expected GetLength() to be 15, was: %i\n", str2.GetLength());
|
||||
|
||||
str = _X("Trim some text!?!?!?!?!");
|
||||
str2 = str.TrimRight(_X("?!"));
|
||||
ok(str2 == _X("Trim some text"), "Expected str to be 'Trim some text', was: %s\n", dbgstrx(str2));
|
||||
ok(str2.GetLength() == 14, "Expected GetLength() to be 14, was: %i\n", str2.GetLength());
|
||||
|
||||
str = _X("\t\t\t\t\t");
|
||||
str2 = str.TrimLeft();
|
||||
ok(str2 == _X(""), "Expected str2 to be '', was: %s\n", dbgstrx(str2));
|
||||
ok(str2.GetLength() == 0, "Expected GetLength() to be 0, was: %i\n", str2.GetLength());
|
||||
|
||||
str = _X("\t\t\t\t\t");
|
||||
str2 = str.TrimRight();
|
||||
ok(str2 == _X(""), "Expected str2 to be '', was: %s\n", dbgstrx(str2));
|
||||
ok(str2.GetLength() == 0, "Expected GetLength() to be 0, was: %i\n", str2.GetLength());
|
||||
|
||||
str = _X("\t\t\t\t\t");
|
||||
str2 = str.Trim();
|
||||
ok(str2 == _X(""), "Expected str2 to be '', was: %s\n", dbgstrx(str2));
|
||||
ok(str2.GetLength() == 0, "Expected GetLength() to be 0, was: %i\n", str2.GetLength());
|
||||
}
|
|
@ -3,10 +3,12 @@
|
|||
|
||||
extern void func_CComBSTR(void);
|
||||
extern void func_CComHeapPtr(void);
|
||||
extern void func_CString(void);
|
||||
|
||||
const struct test winetest_testlist[] =
|
||||
{
|
||||
{ "CComBSTR", func_CComBSTR },
|
||||
{ "CComHeapPtr", func_CComHeapPtr },
|
||||
{ "CString", func_CString },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue