mirror of
https://github.com/reactos/reactos.git
synced 2026-05-31 08:17:09 +08:00
[SHLWAPI][SHLWAPI_APITEST] Rewrite StrToInt* functions (#8591)
JIRA issue: CORE-19278 Reduce Wine test shlwapi:string failures. - Rewrite StrToIntA, StrToIntW, StrToIntExA, StrToInt64ExA, StrToIntExW, and StrToInt64ExW functions. - Add testcase StrToInt.
This commit is contained in:
committed by
GitHub
parent
3319a16288
commit
690fda9f31
@@ -808,6 +808,9 @@ LPWSTR WINAPI StrStrNIW(LPCWSTR lpFirst, LPCWSTR lpSrch, UINT cchMax)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef __REACTOS__
|
||||
#define IS_DIGIT(c) ((UINT)(c) - '0' <= 9)
|
||||
#endif
|
||||
/*************************************************************************
|
||||
* StrToIntA [SHLWAPI.@]
|
||||
*
|
||||
@@ -825,6 +828,28 @@ LPWSTR WINAPI StrStrNIW(LPCWSTR lpFirst, LPCWSTR lpSrch, UINT cchMax)
|
||||
*/
|
||||
int WINAPI StrToIntA(LPCSTR lpszStr)
|
||||
{
|
||||
#ifdef __REACTOS__
|
||||
if (!lpszStr)
|
||||
return 0;
|
||||
|
||||
INT result = 0;
|
||||
BOOL isNegative = FALSE;
|
||||
|
||||
if (*lpszStr == '-')
|
||||
{
|
||||
isNegative = TRUE;
|
||||
++lpszStr;
|
||||
}
|
||||
|
||||
while (IS_DIGIT(*lpszStr))
|
||||
{
|
||||
result *= 10;
|
||||
result += (*lpszStr - '0');
|
||||
++lpszStr;
|
||||
}
|
||||
|
||||
return isNegative ? -result : result;
|
||||
#else
|
||||
int iRet = 0;
|
||||
|
||||
TRACE("(%s)\n", debugstr_a(lpszStr));
|
||||
@@ -838,6 +863,7 @@ int WINAPI StrToIntA(LPCSTR lpszStr)
|
||||
if (*lpszStr == '-' || isdigit(*lpszStr))
|
||||
StrToIntExA(lpszStr, 0, &iRet);
|
||||
return iRet;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
@@ -847,6 +873,28 @@ int WINAPI StrToIntA(LPCSTR lpszStr)
|
||||
*/
|
||||
int WINAPI StrToIntW(LPCWSTR lpszStr)
|
||||
{
|
||||
#ifdef __REACTOS__
|
||||
if (!lpszStr)
|
||||
return 0;
|
||||
|
||||
INT result = 0;
|
||||
BOOL isNegative = FALSE;
|
||||
|
||||
if (*lpszStr == L'-')
|
||||
{
|
||||
isNegative = TRUE;
|
||||
++lpszStr;
|
||||
}
|
||||
|
||||
while (IS_DIGIT(*lpszStr))
|
||||
{
|
||||
result *= 10;
|
||||
result += (*lpszStr - L'0');
|
||||
++lpszStr;
|
||||
}
|
||||
|
||||
return isNegative ? -result : result;
|
||||
#else
|
||||
int iRet = 0;
|
||||
|
||||
TRACE("(%s)\n", debugstr_w(lpszStr));
|
||||
@@ -860,6 +908,7 @@ int WINAPI StrToIntW(LPCWSTR lpszStr)
|
||||
if (*lpszStr == '-' || isdigitW(*lpszStr))
|
||||
StrToIntExW(lpszStr, 0, &iRet);
|
||||
return iRet;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
@@ -891,7 +940,11 @@ BOOL WINAPI StrToIntExA(LPCSTR lpszStr, DWORD dwFlags, int *lpiRet)
|
||||
TRACE("(%s,%08X,%p)\n", debugstr_a(lpszStr), dwFlags, lpiRet);
|
||||
|
||||
bRes = StrToInt64ExA(lpszStr, dwFlags, &li);
|
||||
#ifdef __REACTOS__
|
||||
if (lpiRet) *lpiRet = bRes ? (INT)li : 0;
|
||||
#else
|
||||
if (bRes) *lpiRet = li;
|
||||
#endif
|
||||
return bRes;
|
||||
}
|
||||
|
||||
@@ -902,6 +955,17 @@ BOOL WINAPI StrToIntExA(LPCSTR lpszStr, DWORD dwFlags, int *lpiRet)
|
||||
*/
|
||||
BOOL WINAPI StrToInt64ExA(LPCSTR lpszStr, DWORD dwFlags, LONGLONG *lpiRet)
|
||||
{
|
||||
#ifdef __REACTOS__
|
||||
if (!lpszStr)
|
||||
return FALSE;
|
||||
|
||||
WCHAR wideBuf[MAX_PATH];
|
||||
if (MultiByteToWideChar(CP_ACP, 0, lpszStr, -1, wideBuf, _countof(wideBuf)) <= 0)
|
||||
return FALSE;
|
||||
|
||||
wideBuf[_countof(wideBuf) - 1] = UNICODE_NULL; // SECURITY: Avoid buffer overrun
|
||||
return StrToInt64ExW(wideBuf, dwFlags, lpiRet);
|
||||
#else
|
||||
BOOL bNegative = FALSE;
|
||||
LONGLONG iRet = 0;
|
||||
|
||||
@@ -960,6 +1024,7 @@ BOOL WINAPI StrToInt64ExA(LPCSTR lpszStr, DWORD dwFlags, LONGLONG *lpiRet)
|
||||
}
|
||||
*lpiRet = bNegative ? -iRet : iRet;
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
@@ -975,7 +1040,11 @@ BOOL WINAPI StrToIntExW(LPCWSTR lpszStr, DWORD dwFlags, int *lpiRet)
|
||||
TRACE("(%s,%08X,%p)\n", debugstr_w(lpszStr), dwFlags, lpiRet);
|
||||
|
||||
bRes = StrToInt64ExW(lpszStr, dwFlags, &li);
|
||||
#ifdef __REACTOS__
|
||||
if (lpiRet) *lpiRet = bRes ? (INT)li : 0;
|
||||
#else
|
||||
if (bRes) *lpiRet = li;
|
||||
#endif
|
||||
return bRes;
|
||||
}
|
||||
|
||||
@@ -986,6 +1055,66 @@ BOOL WINAPI StrToIntExW(LPCWSTR lpszStr, DWORD dwFlags, int *lpiRet)
|
||||
*/
|
||||
BOOL WINAPI StrToInt64ExW(LPCWSTR lpszStr, DWORD dwFlags, LONGLONG *lpiRet)
|
||||
{
|
||||
#ifdef __REACTOS__
|
||||
if (!lpszStr)
|
||||
return FALSE;
|
||||
|
||||
// Skip spaces
|
||||
LPCWSTR pch = lpszStr;
|
||||
while (*pch == L' ' || *pch == L'\n' || *pch == L'\t')
|
||||
pch++;
|
||||
|
||||
BOOL isNegative = FALSE;
|
||||
if (*pch == L'+' || *pch == L'-')
|
||||
{
|
||||
isNegative = (*pch == L'-');
|
||||
++pch;
|
||||
}
|
||||
|
||||
ULONGLONG value = 0;
|
||||
LPCWSTR start = pch;
|
||||
|
||||
if ((dwFlags & STIF_SUPPORT_HEX) &&
|
||||
*pch == L'0' && (pch[1] == L'x' || pch[1] == L'X')) // "0x" or "0X"
|
||||
{
|
||||
pch += 2;
|
||||
start = pch;
|
||||
for (;;)
|
||||
{
|
||||
INT digit;
|
||||
if (IS_DIGIT(*pch)) digit = *pch - L'0';
|
||||
else if (L'a' <= *pch && *pch <= L'f') digit = *pch - L'a' + 10;
|
||||
else if (L'A' <= *pch && *pch <= L'F') digit = *pch - L'A' + 10;
|
||||
else break;
|
||||
|
||||
value *= 16;
|
||||
value += digit;
|
||||
++pch;
|
||||
}
|
||||
isNegative = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (IS_DIGIT(*pch))
|
||||
{
|
||||
value *= 10;
|
||||
value += (*pch - L'0');
|
||||
++pch;
|
||||
}
|
||||
}
|
||||
|
||||
if (pch == start)
|
||||
{
|
||||
if (lpiRet)
|
||||
*lpiRet = 0;
|
||||
return FALSE; // No data
|
||||
}
|
||||
|
||||
if (lpiRet)
|
||||
*lpiRet = isNegative ? -(LONGLONG)value : (LONGLONG)value;
|
||||
|
||||
return TRUE;
|
||||
#else
|
||||
BOOL bNegative = FALSE;
|
||||
LONGLONG iRet = 0;
|
||||
|
||||
@@ -1043,6 +1172,7 @@ BOOL WINAPI StrToInt64ExW(LPCWSTR lpszStr, DWORD dwFlags, LONGLONG *lpiRet)
|
||||
}
|
||||
*lpiRet = bNegative ? -iRet : iRet;
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
||||
@@ -22,6 +22,7 @@ list(APPEND SOURCE
|
||||
SHPropertyBag.cpp
|
||||
StrDup.c
|
||||
StrFormatByteSizeW.c
|
||||
StrToInt.c
|
||||
testdata.rc
|
||||
testlist.c)
|
||||
|
||||
|
||||
191
modules/rostests/apitests/shlwapi/StrToInt.c
Normal file
191
modules/rostests/apitests/shlwapi/StrToInt.c
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* PROJECT: ReactOS api tests
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Tests for StrToInt{,Ex,Ex64}{A,W}
|
||||
* COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include <apitest.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
#define ok_longlong(expression, result) do { \
|
||||
long long _value = (expression); \
|
||||
ok(_value == (result), "Wrong value for '%s', expected: " #result " (0x%llx), got: 0x%llx\n", \
|
||||
#expression, (long long)(result), _value); \
|
||||
} while (0)
|
||||
|
||||
static VOID TEST_StrToIntA(VOID)
|
||||
{
|
||||
INT n0, n1;
|
||||
LONGLONG n2;
|
||||
LPCSTR psz;
|
||||
BOOL ret1, ret2;
|
||||
|
||||
n2 = n1 = 0xDEADFACE;
|
||||
psz = NULL;
|
||||
n0 = StrToIntA(psz);
|
||||
ret1 = StrToIntExA(psz, 0, &n1);
|
||||
ret2 = StrToInt64ExA(psz, 0, &n2);
|
||||
ok_int(n0, 0);
|
||||
ok_int(n1, 0);
|
||||
ok_longlong(n2, 0xFFFFFFFFDEADFACE);
|
||||
ok_int(ret1, FALSE);
|
||||
ok_int(ret2, FALSE);
|
||||
|
||||
n2 = n1 = 0xDEADFACE;
|
||||
psz = "";
|
||||
n0 = StrToIntA(psz);
|
||||
ret1 = StrToIntExA(psz, 0, &n1);
|
||||
ret2 = StrToInt64ExA(psz, 0, &n2);
|
||||
ok_int(n0, 0);
|
||||
ok_int(n1, 0);
|
||||
ok_longlong(n2, 0);
|
||||
ok_int(ret1, FALSE);
|
||||
ok_int(ret2, FALSE);
|
||||
|
||||
n2 = n1 = 0xDEADFACE;
|
||||
psz = "123";
|
||||
n0 = StrToIntA(psz);
|
||||
ret1 = StrToIntExA(psz, 0, &n1);
|
||||
ret2 = StrToInt64ExA(psz, 0, &n2);
|
||||
ok_int(n0, 123);
|
||||
ok_int(n1, 123);
|
||||
ok_longlong(n2, 123);
|
||||
ok_int(ret1, TRUE);
|
||||
ok_int(ret2, TRUE);
|
||||
|
||||
n2 = n1 = 0xDEADFACE;
|
||||
psz = "+123";
|
||||
n0 = StrToIntA(psz);
|
||||
ret1 = StrToIntExA(psz, 0, &n1);
|
||||
ret2 = StrToInt64ExA(psz, 0, &n2);
|
||||
ok_int(n0, 0);
|
||||
ok_int(n1, 123);
|
||||
ok_longlong(n2, 123);
|
||||
ok_int(ret1, TRUE);
|
||||
ok_int(ret2, TRUE);
|
||||
|
||||
n2 = n1 = 0xDEADFACE;
|
||||
psz = "-123";
|
||||
n0 = StrToIntA(psz);
|
||||
ret1 = StrToIntExA(psz, 0, &n1);
|
||||
ret2 = StrToInt64ExA(psz, 0, &n2);
|
||||
ok_int(n0, -123);
|
||||
ok_int(n1, -123);
|
||||
ok_longlong(n2, -123);
|
||||
ok_int(ret1, TRUE);
|
||||
ok_int(ret2, TRUE);
|
||||
|
||||
n2 = n1 = 0xDEADFACE;
|
||||
psz = " +123";
|
||||
n0 = StrToIntA(psz);
|
||||
ret1 = StrToIntExA(psz, 0, &n1);
|
||||
ret2 = StrToInt64ExA(psz, 0, &n2);
|
||||
ok_int(n0, 0);
|
||||
ok_int(n1, 123);
|
||||
ok_longlong(n2, 123);
|
||||
ok_int(ret1, TRUE);
|
||||
ok_int(ret2, TRUE);
|
||||
|
||||
n2 = n1 = 0xDEADFACE;
|
||||
psz = " -123";
|
||||
n0 = StrToIntA(psz);
|
||||
ret1 = StrToIntExA(psz, 0, &n1);
|
||||
ret2 = StrToInt64ExA(psz, 0, &n2);
|
||||
ok_int(n0, 0);
|
||||
ok_int(n1, -123);
|
||||
ok_longlong(n2, -123);
|
||||
ok_int(ret1, TRUE);
|
||||
ok_int(ret2, TRUE);
|
||||
}
|
||||
|
||||
static VOID TEST_StrToIntW(VOID)
|
||||
{
|
||||
INT n0, n1;
|
||||
LONGLONG n2;
|
||||
LPCWSTR psz;
|
||||
BOOL ret1, ret2;
|
||||
|
||||
n2 = n1 = 0xDEADFACE;
|
||||
psz = NULL;
|
||||
n0 = StrToIntW(psz);
|
||||
ret1 = StrToIntExW(psz, 0, &n1);
|
||||
ret2 = StrToInt64ExW(psz, 0, &n2);
|
||||
ok_int(n0, 0);
|
||||
ok_int(n1, 0);
|
||||
ok_longlong(n2, 0xFFFFFFFFDEADFACE);
|
||||
ok_int(ret1, FALSE);
|
||||
ok_int(ret2, FALSE);
|
||||
|
||||
n2 = n1 = 0xDEADFACE;
|
||||
psz = L"";
|
||||
n0 = StrToIntW(psz);
|
||||
ret1 = StrToIntExW(psz, 0, &n1);
|
||||
ret2 = StrToInt64ExW(psz, 0, &n2);
|
||||
ok_int(n0, 0);
|
||||
ok_int(n1, 0);
|
||||
ok_longlong(n2, 0);
|
||||
ok_int(ret1, FALSE);
|
||||
ok_int(ret2, FALSE);
|
||||
|
||||
n2 = n1 = 0xDEADFACE;
|
||||
psz = L"123";
|
||||
n0 = StrToIntW(psz);
|
||||
ret1 = StrToIntExW(psz, 0, &n1);
|
||||
ret2 = StrToInt64ExW(psz, 0, &n2);
|
||||
ok_int(n0, 123);
|
||||
ok_int(n1, 123);
|
||||
ok_longlong(n2, 123);
|
||||
ok_int(ret1, TRUE);
|
||||
ok_int(ret2, TRUE);
|
||||
|
||||
n2 = n1 = 0xDEADFACE;
|
||||
psz = L"+123";
|
||||
n0 = StrToIntW(psz);
|
||||
ret1 = StrToIntExW(psz, 0, &n1);
|
||||
ret2 = StrToInt64ExW(psz, 0, &n2);
|
||||
ok_int(n0, 0);
|
||||
ok_int(n1, 123);
|
||||
ok_longlong(n2, 123);
|
||||
ok_int(ret1, TRUE);
|
||||
ok_int(ret2, TRUE);
|
||||
|
||||
n2 = n1 = 0xDEADFACE;
|
||||
psz = L"-123";
|
||||
n0 = StrToIntW(psz);
|
||||
ret1 = StrToIntExW(psz, 0, &n1);
|
||||
ret2 = StrToInt64ExW(psz, 0, &n2);
|
||||
ok_int(n0, -123);
|
||||
ok_int(n1, -123);
|
||||
ok_longlong(n2, -123);
|
||||
ok_int(ret1, TRUE);
|
||||
ok_int(ret2, TRUE);
|
||||
|
||||
n2 = n1 = 0xDEADFACE;
|
||||
psz = L" +123";
|
||||
n0 = StrToIntW(psz);
|
||||
ret1 = StrToIntExW(psz, 0, &n1);
|
||||
ret2 = StrToInt64ExW(psz, 0, &n2);
|
||||
ok_int(n0, 0);
|
||||
ok_int(n1, 123);
|
||||
ok_longlong(n2, 123);
|
||||
ok_int(ret1, TRUE);
|
||||
ok_int(ret2, TRUE);
|
||||
|
||||
n2 = n1 = 0xDEADFACE;
|
||||
psz = L" -123";
|
||||
n0 = StrToIntW(psz);
|
||||
ret1 = StrToIntExW(psz, 0, &n1);
|
||||
ret2 = StrToInt64ExW(psz, 0, &n2);
|
||||
ok_int(n0, 0);
|
||||
ok_int(n1, -123);
|
||||
ok_longlong(n2, -123);
|
||||
ok_int(ret1, TRUE);
|
||||
ok_int(ret2, TRUE);
|
||||
}
|
||||
|
||||
START_TEST(StrToInt)
|
||||
{
|
||||
TEST_StrToIntA();
|
||||
TEST_StrToIntW();
|
||||
}
|
||||
@@ -18,6 +18,7 @@ extern void func_SHLoadRegUIString(void);
|
||||
extern void func_SHPropertyBag(void);
|
||||
extern void func_StrDup(void);
|
||||
extern void func_StrFormatByteSizeW(void);
|
||||
extern void func_StrToInt(void);
|
||||
|
||||
const struct test winetest_testlist[] =
|
||||
{
|
||||
@@ -38,5 +39,6 @@ const struct test winetest_testlist[] =
|
||||
{ "SHPropertyBag", func_SHPropertyBag },
|
||||
{ "StrDup", func_StrDup },
|
||||
{ "StrFormatByteSizeW", func_StrFormatByteSizeW },
|
||||
{ "StrToInt", func_StrToInt },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user